Help us understand the problem. What is going on with this article?

aws-vault についてのあれこれ

More than 1 year has passed since last update.

クラウドワークス 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アカウントを使用する構成を推奨しています。
image.png
Enterprise Network Architectures on AWS

その際、各AWSアカウントのユーザ管理やログインはどのように行うべきなのでしょうか?
AWSアカウントごとに必要となる人数分のIAMユーザを作成し、アクセスキーを払い出し…のような管理をするのは現実的ではありません。

このような場合の解決策として、AWSへのログインを1つのAWSアカウントに集約し、そこから別のアカウントにAssumeRoleを使用してログインするという方法が考えられます。これにより、管理者は1つのアカウントのみユーザを管理すれば良くなります。ユーザも複数のAWSアカウントのパスワードを覚える必要はありません。
クラウドワークスではcustodian(守衛・番人)と呼ばれるアカウント経由で他のアカウントにログインする方式を取っています。
image.png
参考: CustodianアカウントによるIAMユーザの集約管理

最小権限の原則

また、1つのアカウントの中でもAssumeRoleを使用するケースがあります。最小権限の原則による権限の切り替えがそれにあたります。

最小権限の原則をWikipediaで調べてみると…

最小権限の原則は、ユーザーアカウントに対して、そのユーザーにとって必要な権限だけを与えることを意味する。例えば、バックアップ用ユーザーアカウントでは、ソフトウェアをインストールする必要はなく、バックアップ関連のアプリケーションだけを実行できればよいので、新規ソフトウェアをインストールする権限などは付与されない。この原則は、普通のユーザーアカウントで作業しているパーソナルコンピュータのユーザーにも当てはまる。つまり、事態が完全に特権を要求する場合に限って管理者権限を与えられ、パスワードで保護されたアカウント(すなわちスーパーユーザー)にログインする。
最小権限の原則 - Wikipedia

AWSの運用時に、更新可能な権限が必要なシチュエーションは多くありません。ログの確認やEC2インスタンスの状態確認はReadOnlyの権限でアクセスし、設定の変更時のみ必要な権限を使用したいですね。
このような時にもAssumeRoleが使えます。必要な権限に応じてRoleを切り替えることで余分な権限を持つことなくアカウントを運用することができます。
image.png

課題

暗号化されていない認証情報

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_profilerole_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とを組み合わせて使います。

$HOME/.config/direnv/direnvrc
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を使用するディレクトリに以下のファイルを追加します。

.envrc
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での実行イメージはこんな感じです。

b5515fe2-6cc2-9329-52fb-93b6df0d7f7a.gif

備考

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ライフに役立ててください!

crowdworks
21世紀の新しいワークスタイルを提供する日本最大級のクラウドソーシング「クラウドワークス」のエンジニアチームです!
https://crowdworks.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away