aswrap - ~/.aws/(config|credentials) で定義した AssumeRole 定義から一時キーを取得してコマンドを起動してくれる wrapper を書いた

業務では多数の AWS アカウントを運用しています (現時点でアクティブなのは100行かないぐらい)。

AWS アカウントごとに利用者それぞれに IAM User や IAM key を発行するのは権限管理が煩雑になるため、以下のようなアカウント運用をしています。

  1. ログインを集約する専用の AWS アカウントを用意 (account A とします)
    • このアカウントに IAM User を作成し、IAM key を発行する
  2. 各案件用の AWS アカウント(account B) に IAM Role を定義し、Assume Role によって権限を付与

(最近 AWS Organization が Single Sign On に対応したので、今後は不要になるのかもしれませんが…)

こうしておくことで、AWS console には account A でログインした上で、各アカウントにロールの切り替えで遷移することができます。

また、aws-cli では以下のような定義を ~/.aws/credentials 等に記述しておくことで、aws --profile service1 ... として実行すれば自動的に一時キーを取得して account B に対してアクセスすることができます。

# account A
[kayac-iam]
aws_access_key_id=XXXXXXX
aws_secret_access_key=YYYYYYY

# account B
[service1]
role_arn=arn:aws:iam::9999999999:role/InfraTeam
source_profile=kayac-iam

dev.classmethod.jp

aws-cli 以外での問題

Terraform 等、aws-cli ではない AWS SDK を利用したアプリケーションを実行する際には、上記の記述での一時キー解決が動作しません。

そのため、Insntance Profile が付与された EC2 上で実行するか、IAM User を account B に作成してそのキーを使う必要がありました。 しかし、各アカウントで個別に IAM User を作成してしまうと管理が面倒ですし、キーを複数人で共有したりする問題が起きやすくなります。

ということで、思い立って aswrap という wrapper コマンドを書きました。

github.com

このコマンドは、~/.aws/(config|credentials) に定義されてる profile を元に aws sts assume-role で一時キーを取得し、それを環境変数 AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN に設定した上で引数に渡したコマンドを exec する、というものです。

$ AWS_PROFILE=service1 aswrap terraform plan

(terraform plan を一時キー環境変数設定済みの状態で実行する)

また、引数なしで起動すると環境変数を export する shell command を出力するので、eval することで現在の shell に環境変数を設定できます。

$ eval "$(AWS_PROFILE=service1 aswrap)"
$ aws sts get-caller-identity   # service1 の credential で実行される

ということで、aswrap を利用すると、aws-cli と同様の profile 管理で多数のコマンドが実行できるようになります。便利!

Perl 製ですが、fatpack してあるので 5.14.0 以降(または JSON::PP がインストールされていればそれ以下でも) なら、特に依存はなくファイル単体で利用できるはずです。