クラウドワークス SREチームの @kangaechu です。アンタッチャブルのコンビ復活に目が離せないこの頃です。
クラウドワークス Advent Calendar 2019の4日目として、最近SREチーム内で使われるようになったツール、 aws-vault を紹介します。
背景
aws-vaultの話をする前に、少しだけAssumeRoleの話をします。
AssumeRole
assumeは引き受けるなどの意味を持つ単語で、AWSを使用するユーザやリソースが本来持っている権限とは別の権限を引き受けることができるしくみです。ものすごいざっくりいうと、sudoコマンドのような感じです。AssumeRoleはどのようなときに便利なのでしょうか。
マルチアカウントでのIAMユーザ集約管理
リソースの分離や課金管理などを目的として、最近はAWS Organizationsを使用したマルチアカウントでの運用をすることが多くなりました。AWSの2019年のReference Network Architectureでも、環境ごとに複数のAWSアカウントを使用する構成を推奨しています。
Enterprise Network Architectures on AWS
その際、各AWSアカウントのユーザ管理やログインはどのように行うべきなのでしょうか?
AWSアカウントごとに必要となる人数分のIAMユーザを作成し、アクセスキーを払い出し…のような管理をするのは現実的ではありません。
このような場合の解決策として、AWSへのログインを1つのAWSアカウントに集約し、そこから別のアカウントにAssumeRoleを使用してログインするという方法が考えられます。これにより、管理者は1つのアカウントのみユーザを管理すれば良くなります。ユーザも複数のAWSアカウントのパスワードを覚える必要はありません。
クラウドワークスではcustodian(守衛・番人)と呼ばれるアカウント経由で他のアカウントにログインする方式を取っています。
参考: CustodianアカウントによるIAMユーザの集約管理
最小権限の原則
また、1つのアカウントの中でもAssumeRoleを使用するケースがあります。最小権限の原則による権限の切り替えがそれにあたります。
最小権限の原則をWikipediaで調べてみると…
最小権限の原則は、ユーザーアカウントに対して、そのユーザーにとって必要な権限だけを与えることを意味する。例えば、バックアップ用ユーザーアカウントでは、ソフトウェアをインストールする必要はなく、バックアップ関連のアプリケーションだけを実行できればよいので、新規ソフトウェアをインストールする権限などは付与されない。この原則は、普通のユーザーアカウントで作業しているパーソナルコンピュータのユーザーにも当てはまる。つまり、事態が完全に特権を要求する場合に限って管理者権限を与えられ、パスワードで保護されたアカウント(すなわちスーパーユーザー)にログインする。
最小権限の原則 - Wikipedia
AWSの運用時に、更新可能な権限が必要なシチュエーションは多くありません。ログの確認やEC2インスタンスの状態確認はReadOnlyの権限でアクセスし、設定の変更時のみ必要な権限を使用したいですね。
このような時にもAssumeRoleが使えます。必要な権限に応じてRoleを切り替えることで余分な権限を持つことなくアカウントを運用することができます。
課題
暗号化されていない認証情報
AssumeRoleにより、複数アカウントのログインができるアカウントや、強い権限に切り替え可能なアカウントなどを準備すると、1アカウントが持つ権限が強くなっていきます。それに伴い、アクセスキーの管理はますます重要になります。
通常、AWSのアクセスキーは $HOME/.aws/credentials
に記述します。その場合、認証情報は暗号化しない状態で格納されています。macOSであれば、FileVaultによるファイルシステムレベルでの暗号化がされていますが、マルウェアにより不正に $HOME/.aws/credentials
の内容を取得され、利用されてしまうことも考えられます。
aws-vaultのしくみ
aws-vaultはAWSのアクセスキーをOSのキーストアに保存します。これによりアクセスキーを暗号化して保持することができます。macOSであればKeyChain、Windowsであれば資格情報マネージャに保存されます。これにより、マルウェア経由でのアクセスは拒否されます。
aws-vaultはSTSを使用することにより、一時的セキュリティ認証情報(AWSの公式な用語ですが硬いですね)を払い出します。一時的セキュリティ認証情報は短命であり、万が一漏れたとしてもリスクを減らすことができます。
また、一時的セキュリティ認証情報はMFAの情報を含むため、期限内でのMFAの再入力は必要ありません。
インストール方法
macOSであれば、Homebrew経由でインストールできます。
brew cask install aws-vault
Windows/Linuxは Installing を参照してください。
認証情報の追加
IAMで払い出したアクセスキーをaws-vaultに登録します。
$ aws-vault add private
Enter Access Key Id: AKIAIOSFODNN7EXAMPLE
Enter Secret Key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
また、$HOME/.aws/config
に設定を追加します。
[profile private]
[profile private_admin]
source_profile=private
role_arn=arn:aws:iam::123456789012:role/admins-assume
role_session_name=user01
mfa_serial=arn:aws:iam::123456789012:mfa/user01
region=ap-northeast-1
まずはAssumeRole元のprofileであるprivate
です。
通常 AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
を指定する必要がありますが、アクセスキーはaws-vaultで管理していますので、指定する必要はありません。
次にAssumeRole先のprofileである、private_admin
です。
AssumeRoleに必要となるパラメータは source_profile
と role_arn
です。
source_profile
はAssumeRole元のプロファイルを指定します。今回は private
からAssumeRoleするので、 profile
を指定します。
role_arn
は引き受けるRoleのARNを指定します。
role_session_name
はユーザがRoleを引き受ける時に指定するロールセッション名になります。ロールセッションのARNにはarn:aws:iam::123456789012:assumed-role/admins-assume/user01
のようにロールセッション名が含まれるので、正しく指定しましょう。
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-role.html
mfa_serial
にはMFAトークンのARNを指定します。
引き受け先のロールにアタッチされた信頼ポリシーが MFA を必要とする場合、この指定は必須となります。MFAの使用によりセキュリティを高めることができるのでおすすめです。
キーの使用
aws-vault exec
は認証情報を含んだ環境変数を追加し、--
以下のコマンドを実行します。
$ aws-vault exec private -- aws s3 ls
bucket_1
bucket_2
direnvとの組み合わせ
direnvはカレントディレクトリに応じて環境変数をロードおよびアンロードすることができるツールです。
今まではディレクトリごとの .envrc
や、 $HOME/.config/direnv/direnvrc
を作成し、AWSの認証情報を記述することでAWSコマンドを使用していました。
しかし、設定の方法により、暗号化されてないアクセスキーが設定ファイルに残る可能性があります。
そこで、aws-vaultとdirenvとを組み合わせて使います。
use_aws_profile(){
profile_name=$1
export AWS_ASSUME_ROLE_TTL=1h
export $(aws-vault exec $profile_name --prompt=osascript -- env | grep AWS_ | grep -v AWS_VAULT)
}
次に、direnvを使用するディレクトリに以下のファイルを追加します。
use aws_profile private
これにより、aws-vault exec
で払い出した一時的セキュリティ認証情報をdirenvで使用することができます。
セッションの有効期限切れになった場合は direnv reload
を実行すると一時的セキュリティ認証情報を更新できます。
参考 : aws-vaultをdirenvと組み合わせて使う
ブラウザでのログイン
aws-vault login
で認証情報を含んだURLを元に、AWSのコンソールを開きます。
aws-vault login private
複数のAWSアカウントをaws-vaultから開く
AWSのマネージメントコンソールは複数のAWSアカウントを切り替えて使用することができないため、AWSアカウントの切り替え時にはログアウトが必要となります。
その対策として、Chromeのプロファイルを複数作成し、AWSアカウントごとに切り替えて使用することで複数のAWSマネージメントコンソールを同時に立ち上げることができます。
以下のaliasを.zshrcに追加します。
alias avl='(){ open -na "Google Chrome" --args --incognito --user-data-dir=$HOME/Library/Application\ Support/Google/Chrome/aws-vault/$@ $(aws-vault login $@ --stdout) }'
avl <プロファイル名>
で任意のAWSアカウントのマネージメントコンソールをChromeから起動することができます。
参考: aws-vault loginでChromeのウィンドウをAWSアカウント毎に分離する
Alfredとの組み合わせ
こうなればAlfredからも起動したいですね。というわけで自作のAlfred workflowを公開しています。Open AWS via aws-vault という名前です(packal / GitHub)。
aws <プロファイル名>
で任意のAWSアカウントのマネージメントコンソールをChromeから起動することができます。
Alfredでの実行イメージはこんな感じです。
備考
AssumeRoleのセッションは最長1時間
AssumeRoleのセッションのタイムアウトはデフォルトで15分ですが、コマンド実行時の引数 --assume-role-ttl
、または環境変数 AWS_ASSUME_ROLE_TTL
で指定できます。最大 12h
まで指定可能です。
しかし、複数のRoleを引き受ける(ロールの連鎖)場合、指定可能な値は最長 1h
になります。
長時間実行するような処理の場合、処理途中でセッションがタイムアウトする場合がありますのでご注意ください。
macOSのKeyChainのタイムアウトを伸ばす
デフォルトではmacOSを5分操作しない場合にパスワードの入力が必要となりますが、以下の設定を行うことにより、タイムアウトを変更することが可能です。
aws-vaultのmacOSのキーチェーンのタイムアウトを伸ばす
まとめ
aws-vaultの導入により、コマンドラインやAlfredから複数のAWS環境を安全に使い分けることができるようになりました。皆様の安全なAWSライフに役立ててください!