AWSアカウント間のIAMロールを使用したアクセスの委任をしているときのクレデンシャル設定

AWS CLI上のお話

本番環境と開発環境でAWSアカウントを分けることがある。

で、以下のような感じでsts:AssumeRoleを使って開発環境のIAMユーザのまま本番環境のIAMロールで振る舞えるようにすることがある(あまりサクサク切り替えられるとAWSアカウントを分けた意味がないので実際には色々と調整)。

チュートリアル: AWS アカウント間の IAM ロールを使用したアクセスの委任
http://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/tutorial_cross-account-with-roles.html

このときに手元のPCからAWS CLIのコマンドを開発環境用と本番環境用で呼び分けたいと思ったのでそのときのメモ(defaultはまた別のアカウント用なので気にしない)。
まあ実際にはAWS CLIコマンドではなくterraformの適用先の切り替えをしたくてやっているのですが(resourceのproviderが変数を受け付けてくれないのでmoduleと併用だといろいろ厳しい)。

~/.aws/credentials

[default]
aws_access_key_id=xxx
aws_secret_access_key=xxx

[development]
aws_access_key_id=yyy
aws_secret_access_key=yyy

~/.aws/config

[default]
region=ap-northeast-1

[profile development]
region=ap-northeast-1

[profile production]
source_profile=development
role_arn=arn:aws:iam::xxx:role/role-xxx
region=ap-northeast-1

これで以下のように切り替えて使うことができる。めでたし。

aws ec2 describe-instances --profile development
aws ec2 describe-instances --profile production

terraform上のお話

なお、現時点のterraform(0.6.16)ではproviderを複数指定できるものの、resourceのproviderには変数が使えないため、provider汎用のmoduleを作って呼び元で指定しわけるということができない。
同じようなresourceでproviderをハードコードしたのを複数作らないとダメかなぁ。tjたんも「しかたないのでコピペしてる」って言ってるし。
https://github.com/hashicorp/terraform/issues/1819

追記01:

結局、ハードコードしてもproviderのaliasがmoduleに伝わらないことが分かったのでダミーのproviderをトップに置きつつ(「No valid credential sources found for AWS Provider.」って怒られるので)、実際にはaws_workaround.tfなるものを各moduleの中に入れた。うーん。

aws_workaround.tf

# TODO:
# 本当はprovider汎用のmoduleにproviderのaliasを渡してハンドリングしたいが
# terraform 0.6.16ではresourceのproviderに変数が使えず動的に変えられない。
# https://github.com/hashicorp/terraform/issues/1819
# かつ、そもそもmoduleにaliasしたproviderが伝達されない。
# https://github.com/hashicorp/terraform/issues/4789
# 仕方ないのでproviderを個々のmoduleで定義しているがいつ使えなくなるのか分からないので注意。

variable "profile" { }
variable "region" { }

provider "aws" {
  profile = "${var.profile}"
  region = "${var.region}"
}
追記02:

トップのが効いてダメそうだ。うーん。
とりあえず横断的にやるのは諦めて、
env/development/main.tf
env/production/main.tf
module/xxx/main.tf
module/yyy/main.tf
的にやって各envの中(provider定義こみ)でコマンド発行する方向にした。

ただ、今度はterraform remote configでS3にアクセスする際にassume roleが効かないというのが……。
https://github.com/hashicorp/terraform/issues/7014

以下の感じだとそもそもaws-sdk-go自体が対応していないのかな。
https://github.com/aws/aws-sdk-go/issues/472

gitをGitLabに移行したよ

GUIなんかいらんわ」って思って私的リポジトリをずっとさくらVPSに入れたgitoliteで運用してたけど、業務ではGitLabずっと使ってるしいろいろ進化してインストールも楽になってるようだから最新版入れてみようかなということで入れてみた。


進化が激しくて巷のブログに「こうやってここを変更する」とか書いてあるのはほとんど陳腐化していて、結局公式ドキュメントに書いてあることを愚直に実行していくのが吉らしい。
ここにも流れを記すけれど、同様にすぐに陳腐化すると思われるので実際にインストールする際にはその時点での公式ドキュメントみるよろし。インストールコマンド実行後にどこを参照しなさいとかどこを変更しなさいとか教えてくれるのでちゃんとコマンド実行後の出力をみてれば大体わかるはず。

今回の条件

  • CentOS6。
  • 既存のgitリポジトリあり(gitoliteベースだが実質的には素のgitと同じ)。
  • 既に別件でnginxを載せているホストに相乗りさせる。ただしGitLabの独立したnginxを使う。
  • 定期バックアップもする。

注記

  • nginxやpostgresqlなどのミドルウェアは「/opt/gitlab」や「/var/opt/gitlab」に入るのでファイル的には既に入っているものと競合しない。
  • 既存のものと競合するのは基本的にはポートのみ。
  • gitユーザはホームディレクトリが「/var/opt/gitlab」に変更される(GitLabで登録したデプロイキーなどはこの中の.ssh配下で扱われる)。既にgitユーザが存在する場合は「/home/git」の中身自体はそのまま残る。

資料

今回はCentOS6上にいれるので以下がベース。
https://about.gitlab.com/downloads/#centos6

HTTPSで使うので以下も参照。
https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/nginx.md

既存のgitを移行する際には以下を参照。
https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/raketasks/import.md

バックアップのやり方は以下。
https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/raketasks/backup_restore.md

流れ

「/etc/sysconfig/iptables」を更新してポート「12345」をGitLabのWeb UI用に開けて「sudo service iptables restart」する。


公式ドキュメントに沿って以下を実行。ただしドキュメントには「sudo lokkit -s http -s ssh」とあるがiptablesは自分でいじりたかったので実行せず(ほとんどデフォルトで既に入っていたり設定されてたりするが、再度適用しても困るものではないので気にせず実行)。

sudo yum install curl openssh-server postfix cronie
sudo service postfix start
sudo chkconfig postfix on


公式ドキュメントに沿って以下を実行。

curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash
sudo yum install gitlab-ce


「sudo view /etc/gitlab/gitlab.rb」設定ファイルを開く。巷のサイトではymlを更新してたりするが現バージョンではreconfigureするときに使われるのはこちらのファイル。別のファイルをいじっても上書きされる可能性があるので注意。
自分の場合は以下を変えた。たぶんコメントアウトされてるのはデフォルト値なので同じ値ならわざわざコメントアウトを外さなくてよさそう。

SSL使う場合でもSSL用の設定は不要(後述の通りキーペアを所定のルールで置けば勝手に適用してくれる)。Web UIのポート設定も上記のようにexternal_urlに混ぜておくだけでOK。「○○port」などの設定はいじらなくてよい。


以下のようにオレオレSSL証明書を生成。公開鍵は自分の作業PCの「信頼されたルート証明書」に登録。

sudo mkdir -p /etc/gitlab/ssl
sudo chmod 700 /etc/gitlab/ssl

openssl req -nodes -newkey rsa:4098 -keyout foo.bar.com.key -out foo.bar.com.csr -subj "/C=JP/ST=Tokyo/L=Shinjuku-ku/O=FooBar/OU=IT Department/CN=foo.bar.com"
openssl x509 -req -days 3650 -sha256 -in foo.bar.com.csr -signkey foo.bar.com.key -out foo.bar.com.crt

sudo cp foo.bar.com.key foo.bar.com.crt /etc/gitlab/ssl

※ポイントは「/etc/gitlab/ssl」に「【external_urlで設定したホスト名】.key」「【external_urlで設定したホスト名】.crt」というファイル名で格納すること。こうすると設定ファイルに明示しなくても自動的に読み込んでくれるようになる。


これまでの設定後に「sudo gitlab-ctl reconfigure」とするとchefで諸々導入された末にGitLabが起動する。
作業PCから「https://foo.bar.com:12345」にアクセスして初期パスワードでログインするとパスワードの変更を求められるので適宜変更しておく。


バックアップはroot権限で動くcronに以下を記すと2時に発動して「/var/opt/gitlab/backups」にはき出される。
ここではき出されたバックアップファイルは「/etc/gitlab/gitlab.rb」の「gitlab_rails['backup_keep_time']」に記した期間(秒)が過ぎると次のバックアップ処理時に削除される。

0 2 * * * /opt/gitlab/bin/gitlab-rake gitlab:backup:create CRON=1

AWSで新規にシステムを構築する際のアドレス体系案


AWSのネットワーク設計をサボらないでちゃんとやる
という記事があって、自分もちょうどこのあたりを検討しているので自分の検討している体系も書いてみる。


この体系は「現時点でオンプレミスの環境があってそことVPN接続する」「今回たまたまAWSを使っているものの今後ほかのクラウド環境も使うかもしれない」「少し共通の機構を持つ小さいシステムが10〜20個ぐらい格納されるかもしれない」という前提で作ってある。


おそらく方向性としては「システム別に独立した体系にする」などの方針でシステム別に小分けになって相互に疎結合の通信のみにするというのもありえるが、今回はオンプレミスからの緩やかな移行なども鑑みて「大きな体系内に小さなシステムを内包する」方向性にしている。


ビット体系:AAAAAAAA BBBBBCCD DDEEFFGG GGGGGGGG

CIDR bit 個数 概要 説明
A /8 8 - クラスA クラスAのプライベートアドレス体系(=10)。
B /13 5 32 事業 Aとセットで当該事業に割り当てられた値。
C /15 2 4 拠点 AWSの各リージョンや別クラウド。DRも独立拠点。
D /18 3 8 環境 共通、本番、ステージング、開発、DRなどの環境。VPCはこの単位。
E /20 2 4 カテゴリ Private、Publicなどのカテゴリ。当面はこの2で残り2つは予備。
F /22 2 4 AZ アベイラビリティゾーン。ここまででサブネットを形成。4AZまで対応しているが事業によっては2AZにして他のセグメントを拡張してもよい。
G /32 10 1024 ホスト ホストやELB等の資源。
  • AWSVPCの制限としてCIDRは/16〜/24なのでA〜Dで1VPCの基底CIDRとする。
  • 環境は「共通」とそれ以外は性質が異なり、「共通」以外の各環境は「共通」とVPC peeringで接続する。
  • 「共通」以外の各環境は相互に直接通信できない。
  • VPNとの接続はPrivateカテゴリのみ許可する(各環境のPrivateカテゴリにVPNが張られる)。
  • 外部ELB/踏み台/NATはPublicカテゴリに入れる。
  • DBサブネットグループやElasticCacheサブネットグループはA〜Fまでで決まるサブネットを設定する。あまりサブネットを小分けにしすぎない。
  • 何らかの事情で自動で勝手に消費されない固定IPアドレス帯が欲しい場合はEのカテゴリを1つ固定IP用として利用する。
  • AWSの場合、D以降は異なる体系になる可能性が高い。


事業によってはホスト部分(G)は1桁減らして512にしてそれ以外のところを拡張してもよいかもしれない。


この体系を検討するうえで参考にしたのは以下。
図が2あってとても参考になるのだけれど微妙に間違いがあるので注意。
https://www.itcloudarchitect.com/index.php?view=posts&id=169