例えば、以下のようなシチュエーションです。
- あるAWS アカウントPにバケット削除をMFA 保護したS3バケットが存在する
- AWS アカウントPにアクセスするには認証用のAWS アカウントA からIAM ロールを利用する
- この状況でAWS CLI を利用してS3 バケットを削除したい
結論:
STS::GetSessionToken API を実行 -> STS::AssumeRole を実行 -> S3バケットを削除
解説
MFA 保護したAWS API とは以下のドキュメントに記載のあるような内容です。
参考) MFA 保護 API アクセスの設定 – AWS Identity and Access Management
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_credentials_mfa_configure-api-require.html
今回のシチュエーションでは、アカウントP に以下のようなバケットポリシーが設定されたS3 バケットがあるとします。この場合、MFA 認証されていないとこのバケットを削除ことはできません。
{
"Id": "Policy1623673100192",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1623672743376",
"Action": [
"s3:DeleteBucket"
],
"Effect": "Deny",
"Resource": "arn:aws:s3:::<your_bucket_name>",
"Condition": {
"BoolIfExists": {
"aws:MultiFactorAuthPresent": "false"
}
},
"Principal": "*"
}
]
}
認証用AWS アカウントAからアカウントP にアクセスするには、アカウントPのIAMロールをAssumeRole します。AWS CLI では例えば以下のようにSTS AssumeRole を実行します。
aws sts assume-role --role-arn arn:aws:iam::<account_P_id>:role/<role_name> \
--role-session-name <session_name>
これを実行すると一時的認証情報を取得できますので、その認証情報を利用してアカウントP のDeleteBucket API を実行できます。
aws s3 rb s3://<your_bucket_name>
しかし、このときの一時的認証情報はMFA 認証されていないため失敗します。
ではどうするのかというと、まずAWS CLI にてMFA 認証されたリクエストを実行する場合は、STS GetSessionToken API を実行します。
aws sts get-session-token \
--serial-number arn:aws:iam::<aaccount_A_id>:mfa/<your_user_name> \
--token-code <your_mfa_token>
これを実行するとMFA認証済みの一時的認証情報を取得できます。そのMFA認証済みの一時的認証情報を利用して、先程のassume-role を実行します。そうするとassume-role から返却された一時的認証情報はMFA認証情報を含みます。さらに、assume-role により返却された認証情報を利用することで今回のS3バケットの削除のようなMFA保護されたAPI 呼び出しをCLI から実行できます。
ただ、毎回手動でget-session-token -> assume-role を実行するのは面倒なので、一つのシェルなどにまとめることができます。
間違いその1: AssumeRole を実行する際にMFAトークンコードを指定する
sts::AssumeRole はMFA トークンコードを指定して実行することもできます。例えば以下のような呼び出しです。
aws sts assume-role --role-arn arn:aws:iam::<account_P_id>:role/<role_name> \
--serial-number arn:aws:iam::<account_A_id>:mfa/<iam_username> \
--token-code <your_mfa_token_code> \
--role-session-name <session_name>
この場合、MFA はAssumeRole の実行に利用されるのみでSTS により生成される一時的認証情報にはMFA 情報は含まれません。
AssumeRole によって返される一時的な認証情報のコンテキストには MFA 情報が含まれていないので、MFA に対する個別の API オペレーションを確認できません。このため、リソースベースのポリシーで保護されたリソースへのアクセスを制限するために、
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_credentials_mfa_configure-api-require.htmlGetSessionToken
を使用する必要があります。
間違いその2: AWS CLI のconfig にIAM ロールの指定をして実行する
以下のようにAWS CLI のconfig ファイルにIAM ロールとそのロールをAssume する際に利用するMFAの設定が可能です。
[profile roleP]
role_arn = arn:aws:iam::<account_P_id>:role/<your_role_name>
mfa_serial = arn:aws:iam::<account_A_id>:mfa/<user_name>
source_profile = <source_profile>
このように構成するとコマンド実行時に以下のようにMFAトークンコードの入力プロンプトが表示されます。
aws s3 rb s3://<your_bucket_name> --profile roleP
Enter MFA code for arn:aws:iam::<account_A_id>:mfa/<user_name>: トークンコードをここに入力
ただ、この場合も内部的にはMFA 認証されていない一時的認証情報が生成されているだけですので、MFA保護したAPI を呼び出すことはできません。
まとめ
MFA 保護したAPI をIAM ロール経由でCLI から実行したい場合は、
STS::GetSessionToken API を実行 -> STS::AssumeRole を実行 -> MFA保護されたAPI実行
以上です。