はじめに
AWS CLI を使う時に、MFA が設定されている IAM ユーザーのクレデンシャル情報を利用して、他のAWSアカウントにある IAM Role を AssumeRole して使う(Switch Roleを実行する)設定について調べてやったことのメモ書きです。
MFA 用のプロファイルを定義して、コマンド実行に MFA のコードを入力するパターンと、MFA の認証処理をした一時認証情報を取得し、それを使って CLI を実行するパターンがあるようでした。 それぞれのやり方について試したことを書いてます。
各 IAM Role/Policy の設定
踏み台側の IAM Policy の設定
踏み台となる AWS アカウントでは以下のようなポリシーを作成し、該当 IAM ユーザーにアタッチされているものとします。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": "sts:AssumeRole", "Resource": "arn:aws:iam::123456789123:role/AdminRole", "Condition": { "BoolIfExists": { "aws:MultiFactorAuthPresent": "true" } } } ] }
Terraform だと以下のような感じになると思います。
// IAM ポリシー resource "aws_iam_policy" "switch_role_policy" { name = "${aws_iam_group.switch_role_policy.name}" policy = "${data.aws_iam_policy_document.switch_role_policy.json}" } // IAM ポリシードキュメント data "aws_iam_policy_document" "switch_role_policy" { statement { // 123456789123 の AWS アカウントの AdminRole という IAM ロールを利用可能にする effect = "Allow" actions = ["sts:AssumeRole"] resources = [ "arn:aws:iam::123456789123:role/AdminRole", ] // MFA 認証されている場合に AssumeRole を許可する condition { test = "Bool" variable = "aws:MultiFactorAuthPresent" values = ["true"] } } }
アクセス先AWSアカウントの IAM Role の設定
AdminRole という IAM ポリシーに、以下のような信頼ポリシードキュメントを設定します。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::987654321987:root" }, "Action": [ "sts:AssumeRole", "sts:TagSession" ] } ] }
Terraform だと以下のような感じになると思います。
// IAM ロール resource "aws_iam_role" "admin" { name = "AdminRole" assume_role_policy = "${data.aws_iam_policy_document.assume_role_policy.json}" } // IAM ポリシードキュメント data "aws_iam_policy_document" "assume_role_policy" { statement { effect = "Allow" actions = ["sts:AssumeRole"] principals { type = "AWS" identifiers = ["arn:aws:iam::987654321987:root"] } condition { test = "Bool" variable = "aws:MultiFactorAuthPresent" values = ["true"] } } }
1つ目のやり方: aws profile に mfa_serial を定義する
~/.aws/credentials
を以下のように設定します。
[default] aws_access_key_id = ******************** aws_secret_access_key = ***************************************
~/.aws/config
を以下のように設定します。
[default] region = ap-northeast-1 output = json [profile dev] region = ap-northeast-1 output = json role_arn = arn:aws:iam::123456789123:role/AdminRole # アクセス先の AWS アカウントに作成しているロール mfa_serial = arn:aws:iam::987654321987:mfa/dshimizu # 踏み台 AWS アカウントに作成している IAM ユーザーの MFA の ARN source_profile = default # default プロファイルの認証情報を利用する設定
この状態で、dev のプロファイルをつかって 123456789123
のアカウントのリソースにアクセスするために AWS CLI を実行すると、MFA のコードを要求するプロンプトが表示されます。
これを入力すると、S3 の一覧の結果が得られます。
% aws --profile dev s3 ls Enter MFA code for arn:aws:iam::987654321987:mfa/dshimizu:
このとき、AWS CLI のキャッシュ情報を見ると、以下のようなものが記録されていました。
% cat ~/.aws/cli/cache/************.json | jq { "Credentials": { "AccessKeyId": "********************", "SecretAccessKey": "****************************************", "SessionToken": "************************************************************************************************************************", "Expiration": "2023-02-03T11:26:11+00:00" }, "AssumedRoleUser": { "AssumedRoleId": "****************:botocore-session-123456789123", "Arn": "arn:aws:sts::123456789123:assumed-role/AdminRole/botocore-session-123456789123" }, "ResponseMetadata": { "RequestId": "********-****-****-****-************", "HTTPStatusCode": 200, "HTTPHeaders": { "x-amzn-requestid": "********-****-****-****-************", "content-type": "text/xml", "content-length": "1520", "date": "Fri, 03 Feb 2023 10:26:10 GMT" }, "RetryAttempts": 0 } }
ドキュメントを見ると、下記のようにあり、指定されたロールの一時認証情報が取得されるとのことなので、キャッシュに記録されているのはその情報のようです。
When you specify that an AWS CLI command is to use the profile marketingadmin, the AWS CLI automatically looks up the credentials for the linked user1 profile and uses them to request temporary credentials for the specified IAM role. The CLI uses the sts:AssumeRole operation in the background to accomplish this. Those temporary credentials are then used to run the requested AWS CLI command. The specified role must have attached IAM permission policies that allow the requested AWS CLI command to run.
2つ目のやり方: aws profile に一時認証情報を定義する
一時認証情報を利用するやり方をやってみます。
~/.aws/credentials
を以下のように設定します。
[default] aws_access_key_id = ******************** aws_secret_access_key = ****************************************
~/.aws/config
を以下のように設定します。
[default] region = ap-northeast-1 output = json
以下のコマンドで、IAM ユーザーの一時認証情報を取得します。get-session-token
の API を実行するためのアクセス権限設定は不要なようなので、何もしなくても実行できると思います。
% aws --profile default sts get-session-token --serial-number arn:aws:iam::987654321987:mfa/dshimizu --token-code <MFA の 6桁の番号を指定>
以下のような一時認証情報用のアクセスキー、シークレットキー、セッショントークンが返されます。 これで MFA 認証が通った状態の一時認証情報を取得できました。
{ "Credentials": { "AccessKeyId": "********************", "SecretAccessKey": "****************************************", "SessionToken": "************************************************************************************************************************", "Expiration": "2023-02-02T22:13:39+00:00" } }
取得した一時認証情報を ~/.aws/credentials
へ追記します。
[default] aws_access_key_id = ******************** aws_secret_access_key = **************************************** [mfa] aws_access_key_id = ******************** aws_secret_access_key = **************************************** aws_session_token = ************************************************************************************************************************
~/.aws/config
では、以下のように Assume する Role に対して一時認証情報を利用するように source_profile
を定義します。
[default] region = ap-northeast-1 output = json [profile mfa] region = ap-northeast-1 output = json source_profile = mfa role_arn = arn:aws:iam::123456789123:role/AdminRole
これで AWS CLI が実行できるようになりました。 MFAの認証は通っているので、6桁のコードを入力することなく実行できます。
% aws --profile dev s3 ls : :
まとめ
MFA が設定されている IAM ユーザーのクレデンシャル情報を利用して、他のAWSアカウントにある IAM Role を AssumeRole して使う(Switch Roleを実行する)設定について書きました。
ドキュメントを見る限りですと、 get-session-token
の API が、 MFA 認証する場合のために用意されているためのもののようですので、これを利用するのが良さそうです。