AssumeRoleで取得した一時クレデンシャルの情報を環境変数にセットしてもAWS認証が通らずハマった話

原因は、「AWS_SECURITY_TOKEN」に古い一時クレデンシャルが残っていたためでした。
2020.09.06

こんにちは、CX事業本部の若槻です。

前回投稿した次の記事の執筆のための検証の際に、

記事で紹介しているワンライナーにより取得した一時クレデンシャルの情報を環境変数にセットしてもAWS認証が通らずハマったので、その際の話を共有します。

事象

前述の記事で紹介している次のコマンドを実行して、AssumeRoleで取得した一時クレデンシャルの情報をを環境変数AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYおよびAWS_SESSION_TOKENにセットしました。

% target_profile=<Assume先プロファイル名>
% mfa_code=<6桁のMFAコード>
% AWS_STS_CREDENTIALS=`aws sts assume-role --profile default --role-arn $(aws configure get ${target_profile}.role_arn) --role-session-name ${target_profile}-session --serial-number $(aws configure get ${target_profile}.mfa_serial) --token-code $mfa_code`;export AWS_ACCESS_KEY_ID=`echo "${AWS_STS_CREDENTIALS}" | jq -r '.Credentials.AccessKeyId'`;export AWS_SECRET_ACCESS_KEY=`echo "${AWS_STS_CREDENTIALS}" | jq -r '.Credentials.SecretAccessKey'`;export AWS_SESSION_TOKEN=`echo "${AWS_STS_CREDENTIALS}" | jq -r '.Credentials.SessionToken'`

しかしAWS CLIコマンドを実行すると次のようにThe provided token has expired.とトークン期限切れのエラーとなりAWS認証が通りません。

% aws sts get-caller-identity
An error occurred (ExpiredToken) when calling the GetCallerIdentity operation: The provided token has expired.

原因・解決

原因は、環境変数AWS_SECURITY_TOKENに古い一時クレデンシャルの情報が残っていたことでした。

環境変数を確認すると、ワンライナーによりセットされたAWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYおよびAWS_SESSION_TOKENに加えて、AWS_SECURITY_TOKENが定義され値にAWS_SESSION_TOKENと異なるトークン値がセットされていました。

% printenv | grep AWS
AWS_VAULT=xxxxxxxxxx
AWS_DEFAULT_REGION=ap-northeast-1
AWS_REGION=ap-northeast-1
AWS_SECURITY_TOKEN=XXXXXXX//////////XXXXXXXXXXXXXXX
AWS_SESSION_EXPIRATION=2020-09-05T09:06:10Z
AWS_ACCESS_KEY_ID=XXXXXXXXXXXXXX
AWS_SECRET_ACCESS_KEY=YYYYYYYYYYYYYYY
AWS_SESSION_TOKEN=YYYYYYYYYYYYY//////////YYYYYYYYYYYYYY==

このAWS_SECURITY_TOKENは、記事執筆前に別件でaws-vault(サードパーティのAWS向け認証管理ツール)による一時クレデンシャルの取得を行った際にセットされていたものでした。ドキュメントにある通り、aws-vaultの動作仕様として一時クレデンシャルのトークン値を環境変数AWS_SESSION_TOKENAWS_SECURITY_TOKENの双方にセットされていたようです。

その状態でAWS_SESSION_TOKENの方にのみワンライナーで新しいトークン値をセットしても、AWS CLIコマンドがAWS_SECURITY_TOKENの方のトークン値を優先して参照してしまったため実行がトークン期限切れエラーとなったようです。

AWS_SECURITY_TOKENをクリアするとAWS CLIコマンドはエラー無く実行できるようになりました。

% unset AWS_SECURITY_TOKEN

AWS_SESSION_TOKENAWS_SECURITY_TOKENの違いは?

事象の原因と解決方法は分かりましたが、そもそもなんでトークン値の取得先がAWS_SESSION_TOKENAWS_SECURITY_TOKENの2つもあるの?それぞれの使い分けは?というのが気になり調べてみると次のような記事を見つけました。

もともとAWSアクセス時の認証トークンの取得先にはAWS_SESSION_TOKENAWS_SECURITY_TOKENのいずれかもしくは両方が使われていましたが、その仕様はSDKごとにバラバラだったようです。

それが2014年にほぼ全てのSDKは認証トークンをAWS_SESSION_TOKENから取得するように統一されましたが、それまで使用されていたAWS_SECURITY_TOKENからも取得できる仕様は残されていたようです。

aws-vaultが両方の環境変数にセットするようになっているのは、そのような歴史的経緯により生まれたAWS側の仕様に対応するためだったんですね。

おわりに

AssumeRoleで取得した一時クレデンシャルの情報を環境変数にセットしてもAWS認証が通らずハマった話のご紹介でした。

教訓としては、きちんと環境変数をクリアする癖をつけたり、認証ツールを統一したりするようにしましょう。

参考

以上