aws-vaultの使い方と仕組み

## はじめに

awsで認証情報を`~/.aws/credentials`に平文で記入していませんか？
ローテーションする際はコンソール上で変更した後にコピペして貼り付けていませんか？
ローカルマシンだけなら問題にならないことが多いとは思いますが、流出のリスクは否めないですよね。
aws-vaultを使うとリスクを減らして快適に管理できるようになります。

## aws-vaultの概要

- 認証情報の管理の他、ローテーションやコンソールログインのコマンドも提供
- 公式：https://github.com/99designs/aws-vault
- vaultは[vôlt]と発音。単語のイメージは銀行の地下にある厳重な金庫室

### コマンド例

機能概要として実行できるコマンド例を示します。

|コマンド例|効果|
|--|--|
|`$ aws-vault exec admin -- terraform apply`|管理者ユーザーでterraformで構築|
|`$ aws-vault exec dev-user -- aws s3 ls`|開発ユーザーでawsコマンド実行|
|`$ aws s3 ls --profile dev-user`|上記のコマンドを設定により従来通りの実行方法にする|
|`$ aws-vault rotate dev-user --no-session`|アクセスキーのローテション|
|`$ aws-vault login dev-user`|AWSコンソールへのログイン|

### 動作確認環境

- Apple M1
- macOS 14.1.2
- aws-vault --version v7.2.0
- aws-cli/2.15.0 Python/3.11.6 Darwin/22.5.0 source/arm64 prompt/off

## 設定手順

※以降でprofile名を`takuzo`にしている箇所はご自身のものに置き換えてください

```sh
# 本体のインストール
$ brew install --cask aws-vault
$ aws-vault --version
v7.2.0

# アクセスキーを追加
$ aws-vault add takuzo # 名前は管理用なのでiam userと同じでなくて良い
Enter Access Key ID: xxx
Enter Secret Access Key: ****************************************
## ここでウィンドウが起動しaws-vault takuzo用のpasswordを入力
Added credentials to profile "takuzo" in vault
# 追加を確認
$ aws-vault ls
Profile                  Credentials              Sessions
=======                  ===========              ========
takuzo                   takuzo                   -

# 補足：作成されるのはconfigのみでcredentialsが作成されていない
$ ls ~/.aws/
config

# 補足：configの中身を確認
$ cat ~/.aws/config
[profile takuzo]

# default region追加
$ echo "region = ap-northeast-1" >> ~/.aws/config

# mfa必須化（必要に応じて実施）
$ echo "mfa_serial = arn:aws:iam::XXXXXXXXXXXX:mfa/takuzo"
```

### 動作確認

```sh
# 動作確認：結果が表示される
$ aws-vault exec takuzo -- aws s3 ls
"aws-vault"のキーチェーンのパスワードを入力:
202X-XX-XX XX:XX:XX XXXXXXXXXXXXX-ap-northeast-1-XXXXXXXXXXXX
202X-XX-XX XX:XX:XX XXXXXXXXXXXXX-ap-northeast-1-XXXXXXXXXXXX

# 動作確認：エラーになる（aws-vaultなしでは認証情報が不足するので期待通り）
$ aws s3 ls --profile takuzo
Unable to locate credentials. You can configure credentials by running "aws configure".
```

### 仕組み

`aws-vault exec takuzo`を実行すると環境変数へ認証情報が出力されます。この状態で`--`の右側のコマンドが実行されるので認証情報が使用できるようになります。また、コマンドが終了すると認証情報は環境変数からなくなります。
上記のことは下記のコマンドで確認できます。
```sh
$ aws-vault exec takuzo -- env | grep AWS
AWS_VAULT=takuzo
AWS_ACCESS_KEY_ID=ASIAxxxxxx
AWS_SECRET_ACCESS_KEY=xxx
AWS_SESSION_TOKEN=xxx
AWS_SECURITY_TOKEN=xxx
AWS_SESSION_EXPIRATION=2023-12-12T20:52:12Z
# aws-vaultなしでは何も表示されない
$ env | grep AWS
$ 
```
なお、ASIAで始まるものは一時(AWS STS)アクセスキーと呼ばれるものでAKIAから始まるアクセスキーとは異なります。
参考： [一意の ID プレフィックスを理解する - AWS Identity and Access Management](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_identifiers.html#identifiers-unique-ids)

### 従来通りのコマンド形式を可能にする方法

さて、上記の設定を行ったのでこれからは`aws-vault exec <profile>`をつければ良いのですが、入力が面倒であったり従来のスクリプトを変えたくない場合があります。
その場合は下記の設定で従来通りのコマンドで実行できます。
```sh
# configに下記の設定を追加
$ echo "credential_process=aws-vault exec takuzo --json --prompt=osascript" >> ~/.aws/config
# 実行確認（先ほど失敗したコマンドが通るようになる）
$ aws s3 ls --profile takuzo
202X-XX-XX XX:XX:XX XXXXXXXXXXXXX-ap-northeast-1-XXXXXXXXXXXX
202X-XX-XX XX:XX:XX XXXXXXXXXXXXX-ap-northeast-1-XXXXXXXXXXXX
```

仕組みについてです。
aws cliは認証情報を調達する際に環境変数やcredentialsファイルを探しに行くのですが、configファイル内にcredential_processを追加することで指定した認証方法で調達することが可能になります。
`aws-vault exec takuzo --json`を実行すると下記が標準出力され、aws-cliがそれを読み込みます。

```json
{
  "Version": 1,
  "AccessKeyId": "ASIAxxxxxx",
  "SecretAccessKey": "your AWS secret access key",
  "SessionToken": "the AWS session token for temporary credentials",
  "Expiration": "ISO8601 timestamp when the credentials expire"
}
```
参考： [外部プロセスを使用して認証情報を作成する](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-sourcing-external.html)

### セッションの持続時間を伸ばす

使っているとパスワードの入力頻度が高いと感じるかもしれません。その場合は下記を参考に伸ばすことができます。

[aws-vaultのmacOSのキーチェーンのタイムアウトを伸ばす](https://qiita.com/minamijoyo/items/5ed3113434e51308ded1)

## おわりに

初めは少々手間に感じるかもしれませんが慣れると快適でリスクも低減できた安心感も得られました。
未導入の方は是非試してみてください。

また、記事作成にあたり下記を参考にさせていただきました！

- https://github.com/99designs/aws-vault
- https://blog.microcms.io/aws-vault-introduction/
- https://dev.classmethod.jp/articles/aws-vault/
- https://dev.classmethod.jp/articles/awsvault_config/