aws-vault のメモ。概ね USAGE.md を見れば十分ですが WSL で使用する場合の特有の問題などもあります。
pass バックエンド
ずっと昔は aws-vault で認証情報を保存するバックエンドとして Linux の CLI のみの環境だと aws-vault 独自の暗号化ファイルしか無く、その場合は環境変数 AWS_VAULT_FILE_PASSPHRASE
にパスワードを持たせないことには使い勝手が悪く、実質のところ暗号化にあまり意味がありませんでした。
いつからかバックエンドとして pass というパスワードマネージャーが指定できるようになりました。
pass なら gpg 鍵で暗号化されるため gpg 鍵のパスフレーズがマスターパスワードとなり、より安全です(gpg-agent が一定時間記憶するので都度入力の必要はありません)。
.bash_profile で次のように環境変数を設定すれば pass をバックエンドにできます。AWS_VAULT_PASS_PREFIX
は無くても良いですが pass のパスワードストア内でグループ化するために適当に指定した方が良いでしょう。
export AWS_VAULT_BACKEND=pass export AWS_VAULT_PASS_PREFIX=aws-vault/
gpg や pass の初期設定も必要なら次のようにすればできると思います。
gpg --full-generate-key # いろいろプロンプトが出てくるのでそれっぽく入力して進める # 最後の方でパスフレーズの設定があります # 鍵のIDを表示します。xxx のところにあるのが鍵のIDです gpg -k #=> /home/oreore/.gnupg/pubring.kbx #=> ------------------------------- #=> pub ed25519 2023-08-28 [SC] #=> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx #=> uid [ultimate] oreore #=> sub cv25519 2023-08-28 [E] # gpg 鍵のIDを指定して pass のパスワードストアを初期化します pass init xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # aws-vault でアクセスキー・シークレットキーが追加できます aws-vault add my-profile # 使用時は gpg 鍵のパスフレーズの入力が求められます aws-vault exec my-profile
なお Linux なら keyctl なるバックエンドも利用可能なはずなのですが機能してないようです。
keyctl はデバイスが対応していれば TPM とかも使えるようです。
WSL では対応していませんが。
aws-vault login と wsl-open
aws-vault login
を使えば一時クレデンシャルを使ってマネジメントコンソールにログインできます。ので IAM User のパスワードは必要ありません。
ただ、WSL 環境だと xdg-open
でブラウザを開こうとするため普通には使えませんが wsl-open を入れておけば OK です。
既にブラウザでログイン済みだと次のようなページが表示されてしまうのが若干煩雑ですが、 (「ここ」を Ctrl+クリック とかで開いた後 F5 リロードで OK です)
Amazon Web Services サインインページ 別の AWS アカウントにログインするには、まずログアウトする必要があります。 ログアウトするには、 ここをクリックしてください。
これが表示されたページの URL をコピーして、シークレットモードやゲストモードで URL を張り付ければ複数プロファイルを同時に操作もできます。aws-vault login my-proile -s
で URL が標準出力にでるの clip.exe などを使って直接クリップボードに張り付けとかでも良いと思います。
pass-otp と mfa_process
pass-otp は pass の拡張機能のようなもので、pass のパスワードストアに TOTP のシークレットを保存しておけば pass otp
コマンドでワンタイムコードが得られるようになります。
もちろんシークレットは gpg 鍵で暗号化されます。
pass otp insert aws/otp/my-profile # プロンプトが出るので otpauth:// の形式で入力する pass otp aws/otp/my-profile # ワンタイムコードが表示される
さらに ~/.aws/config
で次のように記述しておくと aws-vault でワンタイムコードが必要なときに pass otp
で生成されたワンタイムコードが使用されるため、都度ワンタイムコードを転記する必要がなくなります。
[profile my-profile] mfa_serial=arn:aws:iam::999999999999:mfa/my-profile mfa_process=pass otp aws/otp/my-profile
aws-vault exec --server
aws-vault で実行時間が超長いコマンドを実行するとき(例えば terraform で作成にものすごい時間のかかるリソースを作るときなど)、一時クレデンシャルの有効期限が途中が切れてしまうことがあります。そのような場合は aws-vault exec --server <profile>
を使えば OK です。
--server
オプションを付けて実行すると aws-vault がバックグラウンドで一時クレデンシャルを返すためのサーバを実行し、その URL や認証用トークンを環境変数 AWS_CONTAINER_CREDENTIALS_FULL_URI
と AWS_CONTAINER_AUTHORIZATION_TOKEN
に設定します。
この環境変数は ECS でコンテナが一時クレデンシャルを得るためのもので、次のように認証情報が得られます。
aws-vault exec --server my-profile curl -H "Authorization:$AWS_CONTAINER_AUTHORIZATION_TOKEN" "$AWS_CONTAINER_CREDENTIALS_FULL_URI" #=> 一時クレデンシャル
AWS SDK がクレデンシャルを要求したとき、既に発行済の一時クレデンシャルの有効期限が切れていれば aws-vault によって一時クレデンシャルが再発行されるため、長時間のコマンドでも大丈夫です。
ただし、このオプションを使用するためには aws-vault の prompt で terminal 以外が使用可能な必要があります。
prompt とは aws-vault で何かしらのユーザー入力が必要になったときにどのような方法で入力を得るかの設定です。例えば MFA のワンタイムトークの入力などです。prompt には次のものが指定可能です。
- kdialog
- osascript
- terminal
- wincredui_windows
- ykman
- zenity
デフォルトは terminal で、これは標準入出力が用いられますが --server
オプションを付けて何かのコマンドを実行中は標準入出力はそのコマンドに取られているので、仮に一時クレデンシャルの有効期限が切れて再発行が必要になったとしてもワンタイムコードが入力できません。そのため --server
オプションの利用時は terminal 以外に何かの prompt が利用可能になっている必要があります。
ただ、前述の mfa_process を使っていればワンタイムコードを手入力することは無いし、gpg 鍵のパスフレーズの入力は環境変数 GPG_TTY
を設定していれば標準入出力は使いません。ので、どうせ呼ばれないことが分かっているので適当にダミーのスクリプトを用意しておけば OK です。
touch ~/bin/kdialog chmod +x ~/bin/kdialog
わたしは次のように tty から直接入出力するコマンドに置き換えています。
#!/bin/bash title= inputbox= while [ $# -ne 0 ]; do case "$1" in --inputbox) shift inputbox=$1 ;; --title) shift title=$1 ;; *) echo "unknown kdialog options [$1]" 1>&2 exit 1 esac shift done exec </dev/tty 2>/dev/tty read -p "[$title] $inputbox" -r input echo -n "$input"
GPG_TTY
前後しましたが gpg 鍵のパスフレーズの入力が必要になったとき、デフォルトでは標準入出力が使用されますが、環境変数 GPG_TTY
に tty デバイスファイルを指定しておけば標準入出力は使われずに tty から直接入出力されます。
export GPG_TTY="$(tty)"
前述の --server
オプションもそうですが、ProxyCommand に aws ssm start-session を記述して ssm session manager で ssh している場合などでも標準入出力が使われると困るので GPG_TTY
は指定しておくと良いでしょう。
さいごに
アクセスキー・シークレットキーと、MFA の TOTP シークレットが同じパスワードストアで同じ gpg 鍵で暗号化されていると MFA が台無しになりそうですが、アクセスキー・シークレットキーを暗記しているような人は存在しないわけで、アクセスキー・シークレットキーと TOTP は結局どちらもそれらが保存されているデバイスの所有物認証でしかなく、暗号化されたパスワードストア(所有物)と gpg 鍵のパスフレーズ(知識)の方がむしろ多要素ではないでしょうか。
もしくは MFA には YubiKey とかも使えるようなので(prompt の ykman が YubiKey です)使えるならそれでも良いかもしれませんが WSL だと簡単ではなさそうです。