AWS

AWS Vaultでアクセスキーをセキュアに管理して平文テキストファイル保存をやめる

ローカルPCからAWS CLIやTerraformを実行するときは、スイッチロールするにしろ最初のIAMユーザーの認証でアクセスキーが必要になります。

僕はしばらくこちらの記事のときのように、~/.aws/credencialsにそのまま平文保存していました。

しかし、せっかくAWSがセキュリティ周りを強固にしてくれているのにローカルPCへアクセスキーをテキストで平文保存していることが不安でした。


そこでアクセスキーを安全なキーストア用のアプリケーションに保存するためのツール AWS Vault を使ってみます。(vault = 金庫室、貴重品保管室)

99design という企業の方が、PCの盗難やマルウェアの脅威から守るため開発してくれたもので、記事執筆時点で、Star 5.2kと評価が高く、開発も継続されているため安心して使えそうです。

スポンサーリンク

手順

Macで進めます。Linux(EC2)での手順はこちらの記事にまとめました。

インストール

様々な環境に対応しています。各環境へのインストール方法は、公式ドキュメントのこちらに記載されています。

Mac では brew でインストールできます。

$ brew install --cask aws-vault
==> Downloading https://github.com/99designs/aws-vault/releases/download/v6.3.1/aws-vault-darwin-amd64.dmg
....

🍺  aws-vault was successfully installed!
$

基本構文・実行例

add – クレデンシャル追加

アクセスキーを保存します。

Macではキーの保存先として、デフォルトでキーチェーン(Keychain)が使用されるようです。

## aws-vault add プロファイル名
$ aws-vault add testuser
Enter Access Key ID: ABCD1234
Enter Secret Access Key:
Added credentials to profile "testuser" in vault
$

コマンド実行時、キーチェーンのパスワード入力画面が出るので、Macのパスワードを入れてください。

最初はパスワードを2回聞かれると思います。パスワード入力の設定変更については、こちらに後述しました

exec – AWSコマンド実行

aws-vaultコマンドに続いて、AWS CLIやTerraformコマンドなどを入力します。

途中にある “–” が aws-valutオプションの終了を意味しています。

## aws-vault exec プロファイル名 -- AWS CLIコマンド
$ aws-vault exec testuser -- aws s3 ls
2021-06-04 14:42:19 bucket-a
2021-05-29 16:10:30 bucket-b
...
$


env コマンドを実行すると認証周りの環境変数が表示されます。

$ aws-vault exec dev -- env | grep AWS
AWS_VAULT=dev
AWS_DEFAULT_REGION=ap-northeast-1
AWS_REGION=ap-northeast-1
AWS_ACCESS_KEY_ID=ASIAXXX
AWS_SECRET_ACCESS_KEY=yyy
AWS_SESSION_TOKEN=zzz
AWS_SECURITY_TOKEN=zzz
AWS_SESSION_EXPIRATION=2021-08-12T14:00:01Z
$


また “–“をつけずに、そのまま起動したシェルの中でAWS CLIを操作できます。

$ aws-vault exec testuser
$
$ aws s3 ls
2021-06-04 14:42:19 bucket-a
2021-05-29 16:10:30 bucket-b
...
$

ちなみにこの状態で ps をみると、子シェル(/bin/zsh とか)が立ち上がっていることがわかります。

list – プロファイル一覧

プロファイルを一覧表示します。

明示的に aws-vault で add したものだけではなく AWS CLI の config で定義されている内容が全部出力されます。

なお add したタイミングで、自動的に config へプロファイルが追加されます。

$ aws-vault list
Profile                  Credentials              Sessions
=======                  ===========              ========
hoge                     hoge                     -
testuser                 testuser                 sts.GetSessionToken:20m11s
...
$

remove – クレデンシャル削除

クレデンシャルをキーチェーンから削除します。

なおconfig からプロファイルは削除されないので、不要であれば手動で削除しましょう。

## aws-vault remove プロファイル名
$ aws-vault remove hoge
Delete credentials for profile "hoge"? (y|N) y
Deleted credentials.
$

login – マネジメントコンソールログイン

自動的にブラウザが立ち上がり、AWSマネジメントコンソールが開きます。

$ aws-vault login testuser
$


便利そうですが個人的にはあまり使ってません。ブラウザでのスイッチロールができず開発や本番などの各環境をいったりきたりできないので。。


loginはフェデレーションログインという機構を利用しているようです。その辺りの権限が足りない(以下はReadOnlyAccess ポリシーのみ付与していた場合)とエラーになります。

$ aws-vault login testuser
aws-vault: error: login: Failed to get credentials for testuser: AccessDenied: User: arn:aws:iam::111111111111:user/testuser is not authorized to perform: sts:GetFederationToken on resource: arn:aws:sts::111111111111:federated-user/testuser
	status code: 403, request id: xxx
$ 

rotate – クレデンシャルのローテーション

アクセスキーのローテーションを行います。今まで使用していたアクセスキーは削除されるので、その点ご注意ください。

## aws-vault rotate プロファイル名 -no-session
$ aws-vault rotate testuser --no-session
Rotating credentials stored for profile 'testuser' using master credentials (takes 10-20 seconds)
Creating a new access key
Created new access key ****************RGA3
Deleting old access key ****************24E6
Deleted old access key ****************24E6
Finished rotating access key
$


既にアクセスキーが最大数の2つあると作成できません。(新たに作成してから削除の流れなので)

$ aws-vault rotate testuser --no-session
Rotating credentials stored for profile 'testuser' using master credentials (takes 10-20 seconds)
Creating a new access key
aws-vault: error: rotate: LimitExceeded: Cannot exceed quota for AccessKeysPerUser: 2
	status code: 409, request id: xxx
$


特にドキュメントに記載が見当たらなかったのですが、–no-sessionでない、一時的なセッショントークンでは以下のエラーとなります。

$ aws-vault rotate testuser
Rotating credentials stored for profile 'testuser' using a session from profile 'testuser' (takes 10-20 seconds)
Creating a new access key
aws-vault: error: rotate: InvalidClientTokenId: The security token included in the request is invalid
	status code: 403, request id: xxx
$


2段階認証(MFA)制限のスイッチロールで環境切替え

AWS CLI 2段階認証(MFA)制限のスイッチロールで環境切替え で、AWS CLIでスイッチロールをしていましたが、同じようにAWS Vaultでもスイッチロールが可能です。

AWS CLIの設定

~/.aws/config は こちらの内容と同じ設定でいけます。コマンド実行時、MFAコードの入力を求められます。

$ aws-vault exec dev -- aws s3 ls
Enter token for arn:aws:iam::111111111111:mfa/testuser: 123456
2021-06-04 14:42:19 bucket-a
2021-05-29 16:10:30 bucket-b
...

mfa_serialをソースプロファイルにも記述してMFAコードの入力を省略

mfa_serial を踏み台のプロファイルにも記述します。

これにより、一度MFAコードを入力したら各環境でのコマンド実行時に、再度のMFAコードの入力が不要となります。
(踏み台に mfa_serial が設定されない場合は、各環境ごとにMFAコードを入力することになります)

MFAコードは、それほど頻繁に入力するものではないですが(セッションが切れない限り入力不要)、複数環境でコマンド打つときは地味に便利です。

$ vi ~/.aws/config
...

[profile step]
region = ap-northeast-1
###########################
## STEPにもmfa_serial を記述 
###########################
mfa_serial=arn:aws:iam::111111111111:mfa/testuser 

[profile dev]
region = ap-northeast-1
role_arn=arn:aws:iam::222222222222:role/AdminStepUserRole
source_profile=step
mfa_serial=arn:aws:iam::111111111111:mfa/testuser
role_session_name=testuser

[profile prod]
region = ap-northeast-1
role_arn=arn:aws:iam::333333333333:role/AdminStepUserRole
source_profile=step
mfa_serial=arn:aws:iam::111111111111:mfa/testuser
role_session_name=testuser

...

include_profile でスマートに記述する

include_profile を使用して、冗長な記述を省略できます。直感的にも設定内容がわかりやすくなると思います。

例えば前述の設定では、include_profile を使用して以下のように置き換えられます。

$ vi ~/.aws/config
...

[profile step]
region=ap-northeast-1
source_profile=step
mfa_serial=arn:aws:iam::111111111111:mfa/testuser
role_session_name=testuser

[profile dev]
role_arn=arn:aws:iam::222222222222:role/AdminStepUserRole
include_profile=step

[profile prod]
role_arn=arn:aws:iam::333333333333:role/AdminStepUserRole
include_profile=step

...


ただ、この include_profileはaws-vault独自の実装であるため、素の AWS CLI でのスイッチロールが動かなくなるのでご注意ください。

$ aws s3 ls --profile dev

Partial credentials found in assume-role, missing: source_profile or credential_source
$

メタデータサーバ

exec での環境変数から資格情報を取得するのとは別の、もう一つのやり方がメタデータサーバを使用した方法になります。

が、個人的に使用しておらず、かつ exec のサブシェルの中で実行するの比較して何がメリットなのかイマイチ把握できてないので、どなたか教えて下さいmm
(クレデンシャル知らない人もURIから取得できるから便利とか?)

ECSサーバ – ecs-server

ecs-serverオプションで起動すると環境変数が以下のように設定されます。

## aws-vault exec プロファイル名 --ecs-server
$ aws-vault exec dev --ecs-server
$
$ env | grep AWS
AWS_VAULT=dev
AWS_DEFAULT_REGION=ap-northeast-1
AWS_REGION=ap-northeast-1
AWS_CONTAINER_CREDENTIALS_FULL_URI=http://127.0.0.1:57914
AWS_CONTAINER_AUTHORIZATION_TOKEN=3aovxxx
$


exec のときと同様、そのままサブシェルの中でコマンドが打てます。Terraformもできます。

$ aws s3 ls
2021-06-04 14:42:19 bucket-a
2021-05-29 16:10:30 bucket-b
...
$


また AWS_CONTAINER_AUTHORIZATION_TOKEN を Authorization ヘッダにセットし、AWS_CONTAINER_CREDENTIALS_FULL_URI へアクセスすれば、サブシェルではない別なプロセスからもクレデンシャルを取得できます。

それらを環境変数へセットすればAWS CLIを実行できます。

$ curl -s http://127.0.0.1:57914  -H "Authorization: 3aovxxx" | jq .
{
  "AccessKeyId": "ASIAXXX",
  "Expiration": "2021-08-12T13:37:29Z",
  "SecretAccessKey": "yyy",
  "Token": "zzz"
}
$
$
## 取得したクレデンシャルを環境変数へセット
$ export AWS_ACCESS_KEY_ID=ASIAXXX
$ export AWS_SECRET_ACCESS_KEY=yyy
$ export AWS_SESSION_TOKEN=zzz
$
$ aws sts get-caller-identity
{
    "UserId": "AROAXXX:testuser",
    "Account": "111111111111",
    "Arn": "arn:aws:sts::111111111111:assumed-role/AdminStepUserRole/testuser"
}
$

EC2サーバ – server

serverオプションで起動すると、環境変数が以下のように設定されます。コマンド実行時、特権ポートにバインドするためにrootのパスワードを求められます。

## aws-vault exec プロファイル名 --server
$ aws-vault exec dev --server
Password:
$
$ env | grep AWS
AWS_VAULT=dev
AWS_DEFAULT_REGION=ap-northeast-1
AWS_REGION=ap-northeast-1
$


ECSのときと同様、メタデータ取得URLにアクセスしクレデンシャルを取得できます。

ただ、EC2の場合はURLが固定されており、Authorizationなどが不要です。
URLを知っていれば、誰でもアクセスできるためセキュリティ面ではECSより劣ります。

$ curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/local-credentials | jq .
{
  "AccessKeyId": "ASIAXXX",
  "Code": "Success",
  "Expiration": "2021-08-12T14:03:38Z",
  "LastUpdated": "2021-08-12T13:10:43Z",
  "SecretAccessKey": "yyy",
  "Token": "zzz",
  "Type": "AWS-HMAC"
}
$

ちなみにURLパスは、ソースコードのここら辺に書いてあります。



Tips

Mac キーチェーンの設定

AWS Vault実行時、ロック解除やKeychainの使用許可のため連続で最大2回パスワード入力を求められると思います。

これらはキーチェーンの設定画面から変更、確認できます。

Launchpad で keychain と入力、起動してください。もしくは、Launchpad の [ その他 ] → [ キーチェーン アクセス ] をクリックでもいけます。

1回目のパスワード入力

は、キーチェーン設定画面の左ペイン [ カスタムキーチェーン ] → [ aws-vault ] を右クリック → [ キーチェーン”aws-vault”の設定を変更 ] → [ 操作しない状態がx分間続いたらロック ] のチェックを外すと聞かれなくなります。

時間を延長することで入力頻度を減らすことも可能です。

2回目のパスワード入力

は、 [ 常に許可 ] をクリックすれば聞かれなくなります。

当該行のアプリケーションパスワードをダブルクリックして [ アクセス制御 ] タブを選択すると以下のようにaws-vaultへの許可設定が自動的に追加されていることが確認できます。

また、この画面から左下の [ + − ] ボタンを押して、手動で追加、削除もできます。

Mac キーチェーンの中身

アプリケーションパスワード と aws-vault session の2種類が作成されています。


当該行をダブルクリックして、[ パスワードの表示 ] をするとアプリケーションパスワードには、add した際に入力したアクセスキーが保存されています。

{"AccessKeyID":"AKIAXXX","SecretAccessKey":"yyy","SessionToken":"","ProviderName":""}


aws-vault session には、exec コマンド実行時に発行された一時的なセッション用のクレデンシャルが保存されています。

{"AccessKeyId":"ASIAXXX","Expiration":"2021-08-12T16:36:23Z","SecretAccessKey":"yyy","SessionToken":"zzz"}

アクセスキーの AKIA とか ASIA の意味

今までなんとなく違うなーくらいで、特に調べてなかったのですが、公式ドキュメント 一意の識別子 に記載がありました。

とりあえず僕がちょこちょこ見るのを記載しておきます。

プレフィックス意味
AKIAアクセスキー
ASIA一時 (AWS STS) アクセスキー ID
AROAロール



今回は以上です〜ノシ

参考

アリガト━━━ヾ(´∀`)ノ━━━━♪

GitHub aws-vault
99designsのエンジニアブログ Securing AWS Credentials on Engineer’s Machines
aws-vaultのmacOSのキーチェーンのタイムアウトを伸ばす

関連書籍

更新履歴

  • 2021.09.05 小見出しを改善