AWS Valut と direnv を使い簡単安全にスイッチロールしてみた

AWS Vault と direnv を利用し、簡単にスイッチロールを行う環境を作ってみました。
2022.12.20

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

ブログ内容

こんにちは、望月です。
AWS Vault 使ってますか?私は最近 PC の入れ替えをしたタイミングで導入してみました。

AWS Vault を利用することでアクセスキー/シークレットキーをキーチェーン等で保存することができるため、安全に AWS CLI などを利用することが出来ます。インストール方法については以下ブログを読んでもらえばサクッと対応できると思います。

AWS Vaultで端末内のAWSアクセスキー平文保存をやめてみた

AWS Valut と合わせて、今までの環境で利用していた direnv を組み合わせて使ってみたのでここではその方法をまとめたいと思います。direnv はスイッチロールをする際にディレクトリ移動することで一時クレデンシャルを取得・設定することが出来るため、気軽にスイッチロールを行うことが出来ます。direnv については以下ブログをご確認ください。

[小ネタ]ディレクトリ移動した際に自動で一時クレデンシャルを取得・設定する

やってみた

前提

  • AWS Vault をインストール済み
    • バージョン 6.6.0-Homebrew を利用
  • direnv をインストール済み
    • バージョン 2.32.2 を利用
  • zsh 5.9 を利用

どれも Homebrew を利用することで簡単にインストールすることが出来ます。

Profile の設定内容

スイッチロール先の情報を ~/.aws/config に記載します。direnv ではカレントディレクトリ名を利用し、スイッチロールするので Profile 名とカレントディレクトリ名を合わせる必要があります。ここでは [profile test] という形で Profile 名を設定します。

[profile test]
include_profile=...
role_arn=...
...

設定後に aws-vault ls コマンドを実施し、Profile test が表示されるようになります。

% aws-vault ls
Profile                  Credentials              Sessions
=======                  ===========              ========
...
test                     -                        -
...

.envrc の作成

test ディレクトリを作成し test ディレクトリ配下に以下のように .envrc を作成します。

PROFILE_NAME=$(basename $(pwd))

export AWS_ACCESS_KEY_ID=$(aws-vault exec ${PROFILE_NAME} -j | jq -r '.AccessKeyId')
export AWS_SECRET_ACCESS_KEY=$(aws-vault exec ${PROFILE_NAME} -j | jq -r '.SecretAccessKey')
export AWS_SESSION_TOKEN=$(aws-vault exec ${PROFILE_NAME} -j | jq -r '.SessionToken')

# PROMPT
export PROMPT="%F{red}[$(aws sts get-caller-identity | jq -r '.Account')]%f ${PROMPT}"

実行している内容については以下説明していきます。

  • PROFILE_NAME=$(basename $(pwd))
    • 変数 PROFILE_NAME にカレントディレクトリ名を設定します
  • export AWS_ACCESS_KEY_ID=$(aws-vault exec ${PROFILE_NAME} -j | jq -r '.AccessKeyId')
    • アクセスキーを取得し、変数 AWS_ACCESS_KEY_ID に設定します
  • export AWS_SECRET_ACCESS_KEY=$(aws-vault exec ${PROFILE_NAME} -j | jq -r '.SecretAccessKey')
    • シークレットキーを取得し、変数 AWS_SECRET_ACCESS_KEY に設定します
  • export AWS_SESSION_TOKEN=$(aws-vault exec ${PROFILE_NAME} -j | jq -r '.SessionToken')
    • セッショントークンを取得し、変数 AWS_SESSION_TOKEN に設定します

aws-vault exec のヘルプを確認すると -j オプションを使うことで、クレデンシャル情報が JSON で受け取ることが出来ることが分かります。そのため aws-vault exec test -j コマンドを実行し、一時クレデンシャルを取得し各変数に設定していきます。

% aws-vault exec --help
usage: aws-vault exec [<flags>] <profile> [<cmd>] [<args>...]

Executes a command with AWS credentials in the environment

Flags:
      --help                     Show context-sensitive help (also try --help-long and --help-man).
      --version                  Show application version.
      --debug                    Show debugging output
      --backend=keychain         Secret backend to use [keychain pass file] ($AWS_VAULT_BACKEND)
      --prompt=terminal          Prompt driver to use [kdialog osascript pass terminal ykman zenity] ($AWS_VAULT_PROMPT)
      --keychain="aws-vault"     Name of macOS keychain to use, if it doesn't exist it will be created ($AWS_VAULT_KEYCHAIN_NAME)
      --secret-service-collection="awsvault"
                                 Name of secret-service collection to use, if it doesn't exist it will be created ($AWS_VAULT_SECRET_SERVICE_COLLECTION_NAME)
      --pass-dir=PASS-DIR        Pass password store directory ($AWS_VAULT_PASS_PASSWORD_STORE_DIR)
      --pass-cmd=PASS-CMD        Name of the pass executable ($AWS_VAULT_PASS_CMD)
      --pass-prefix=PASS-PREFIX  Prefix to prepend to the item path stored in pass ($AWS_VAULT_PASS_PREFIX)
      --file-dir="~/.awsvault/keys/"
                                 Directory for the "file" password store ($AWS_VAULT_FILE_DIR)
  -d, --duration=DURATION        Duration of the temporary or assume-role session. Defaults to 1h
  -n, --no-session               Skip creating STS session with GetSessionToken
      --region=REGION            The AWS region
  -t, --mfa-token=MFA-TOKEN      The MFA token to use
  -j, --json                     Output credentials in JSON that can be used by credential_process
  -s, --server                   Alias for --ec2-server. Run a EC2 metadata server in the background for credentials
      --ec2-server               Run a EC2 metadata server in the background for credentials
      --ecs-server               Run a ECS credential server in the background for credentials (the SDK or app must support AWS_CONTAINER_CREDENTIALS_FULL_URI)
      --lazy                     When using --ecs-server, lazily fetch credentials
      --stdout                   Print the SSO link to the terminal without automatically opening the browser

Args:
  <profile>  Name of the profile
  [<cmd>]    Command to execute, defaults to $SHELL
  [<args>]   Command arguments

おまけ

最後に export PROMPT="%F{red}[$(aws sts get-caller-identity | jq -r '.Account')]%f ${PROMPT}" を実行していますが、こちらはプロンプトに AWS アカウント ID を表示するコマンドになります。カレントディレクトリ名で接続しているアカウントは分かりますが、念のため AWS アカウント ID を表示することでなんとなくいつも見てる ID と違う…みたいな予防を想定しています。

[123456789012] 10:00 @mochizuki.yuta test %

まとめ

AWS Vault と direnv を利用し、簡単にスイッチロールを行う環境を作ることができました。複数の AWS アカウントを利用しつつ、セキュアに AWS を使いたいといった場合に AWS Vault と direnv を利用するのはいかがでしょうか。