AWSマルチアカウント環境で、2段階認証(MFA)制限をかけたロールに対してAWS CLIでスイッチします。
ついでにセッション名の固定というTipsもご紹介します。
(AWS Vaultというツールで安全にアクセスキーを保存しつつ同様のことができます。こちらの記事をご参照ください)
前提
いくつか事前準備や前提知識が必要になります。
2段階認証(MFA)制限付きのロール設定
2段階認証(MFA)制限付きのロール設定自体は、AWSマネジメントコンソールで行います。
設定手順や実行環境などの説明は、以下の記事をご参照ください。
今回は、この手順が完了しているものとして進めます。AWSアカウントIDは引き続き以下を使用します。
環境 | AWSアカウントID |
---|---|
踏み台(JUMP) | 111111111111 |
開発(DEV) | 222222222222 |
本番(PROD) | 333333333333 |
またスイッチ先のロール名は、管理者用として作成した AdminRoleFromJump を使用します。
AWS CLI 名前付きプロファイル
AWS CLIで –profile というオプションを使用します。
設定手順や説明は、以下の記事をご参照ください。
スイッチロールで環境切替え
それでは設定していきます。 といっても1コマンド打って1ファイル編集するだけです。
AWS CLIの設定
IAMユーザーのアクセスキー保存
まず踏み台環境(JUMP)に作成した、IAMユーザーの認証情報(アクセスキー)の設定をします。
$ aws configure --profile tester-01-jump
AWS Access Key ID [None]: xxxxxxxxxxx
AWS Secret Access Key [None]: yyyyyyyyyyyyy
Default region name [None]: ap-northeast-1
Default output format [None]:
$
AWS CLI設定ファイル スイッチロールの設定
次に、~/.aws/configへスイッチ先環境(開発、本番)のロールの設定を追加します。
aws configure set というサブコマンドでの設定も可能ですが、編集内容が多く、configファイルの場所を把握している場合は、viなどで直接編集したほうが楽です。
$ vi ~/.aws/config
...
## 踏み台環境(JUMP) のIAMユーザーは、aws configure で既に設定されています
[profile tester-01-jump]
region = ap-northeast-1
## 開発(DEV)の設定を追加します
[profile tester-01-dev]
region = ap-northeast-1
role_arn=arn:aws:iam::222222222222:role/AdminRoleFromJump
source_profile=tester-01-jump
mfa_serial=arn:aws:iam::111111111111:mfa/tester-01
## 本番(PROD)の設定を追加します
[profile tester-01-prod]
region = ap-northeast-1
role_arn=arn:aws:iam::333333333333:role/AdminRoleFromJump
source_profile=tester-01-jump
mfa_serial=arn:aws:iam::111111111111:mfa/tester-01
...
以下、設定項目の説明です。
role_arn
スイッチ先のロールARNを指定します。
arn:aws:iam::AWSアカウントID:role/ロール名
source_profile
スイッチ元のプロファイル名を指定します。
上記例では tester-01-jump で設定したプロファイルのIAMユーザーからスイッチします。
mfa_serial
QRコードを読み取ったMFAデバイスのARNを指定します。
arn:aws:iam::AWSアカウントID:mfa/IAMユーザー名
なおMFAデバイスのARNは、AWSマネジメントコンソールのIAMユーザーの認証情報画面から確認できます。
スイッチロール確認
以上で設定完了したので確認します。
コマンド実行時、MFAコードの入力を求められます。
$ aws s3 ls --profile tester-01-dev
Enter MFA code for arn:aws:iam::111111111111:mfa/tester-01:[6桁のコードを入力]
...
DEV環境のバケット一覧が出力されます
...
$
$ aws s3 ls --profile tester-01-prod
Enter MFA code for arn:aws:iam::111111111111:mfa/tester-01:[6桁のコードを入力]
...
PROD環境のバケット一覧が出力されます
...
$
なお踏み台アカウントのプロファイルを指定しても、踏み台のIAMユーザーには、実質MFA作成以外の操作を拒否するpolicyを設定しているのでエラーとなります。
$ aws s3 ls --profile tester-01-jump
An error occurred (AccessDenied) when calling the ListBuckets operation: Access Denied
$
Tips
スイッチロール時(AssumeRole)の認証情報
コマンド実行時、MFAの入力は毎回求められるわけではありません。
~/.aws/cli/cache に認証情報が保存され、情報の有効期限(デフォルト1時間)内であれば6桁のコードを入力せずにコマンド実行できます。
## スイッチロール単位で作成され、同じファイルが更新されます
$ find ~/.aws/cli/cache -type f
/Users/xxx/.aws/cli/cache/xxxxx.json
/Users/xxx/.aws/cli/cache/yyyyy.json
/Users/xxx/.aws/cli/cache/12345.json
/Users/xxx/.aws/cli/cache/56789.json
$
## 中身を確認してみます
$ cat /Users/xxx/.aws/cli/cache/56789.json | jq
{
"Credentials": {
"AccessKeyId": "aaa",
"SecretAccessKey": "bbb",
"SessionToken": "ccc==",
"Expiration": "2021-07-12T22:47:36+00:00"
},
"AssumedRoleUser": {
"AssumedRoleId": "xxx:botocore-session-1626126444",
"Arn": "arn:aws:sts::222222222222:assumed-role/AdminRoleFromJump/botocore-session-1626126444"
},
"ResponseMetadata": {
"RequestId": "xxx-yyy-zzz-111-222",
"HTTPStatusCode": 200,
"HTTPHeaders": {
"x-amzn-requestid": "xxx-yyy-zzz-111-222",
"content-type": "text/xml",
"content-length": "1522",
"date": "Mon, 12 Jul 2021 21:47:35 GMT"
},
"RetryAttempts": 0
}
}
$
上記例では、 “Expiration”: “2021-07-12T22:47:36+00:00″、日本時間(JST)はその時刻から+9時間なので13日のAM 07:47が期限となります。
(が僕の環境では、それより早めに(15分ほど前)に期限切れとなってる気がしました。。
セッション名を固定して操作履歴を追跡する
~/.aws/config で role_session_name を指定できます。
[profile tester-01-prod]
region = ap-northeast-1
role_arn=arn:aws:iam::333333333333:role/AdminRoleFromJump
source_profile=tester-01-jump
mfa_serial=arn:aws:iam::111111111111:mfa/tester-01
## セッション名を追加します
role_session_name=tester-01
セッション名を特に指定しない場合は、自動的に生成されます。(AWS CLIでは botocore-session-ランダム数値 になる模様)
この role_session_name は任意ですが、IAMユーザー名と同じにすると誰かと重複することなく AWS CloudTrailでAWS CLIからのアクセス履歴を簡単に追えるようになります。
以下のように、CloudTrailのイベント履歴画面でユーザー名を条件に、素早く正確に検索できるようになります。
これがbotocore-session-ランダム数値 のままだと問題がおきたときに、誰が何をしたかがサクッと追えなくなってしまいます。
またAWSマネジメントコンソールでのスイッチロールのセッション名は自動でIAMユーザー名が設定されているようで、その点からもセッション名を統一したほうが追跡が楽になります。
セッション名にIAMユーザー名を適用することを強制する
role_session_name を IAMユーザー名でお願いね! とチームでルールづくりしても設定ミスや詐称の不安は拭えないので、システムでチェックします。
こちらの記事の開発環境(DEV)・本番環境(PROD)用 YAMLファイル作成 のロール に StringLike: sts:RoleSessionName: ${aws:username} の設定を追加します。
# 管理者ロール
Resources:
AdminRoleFromJump:
Type: AWS::IAM::Role
Properties:
RoleName: "AdminRoleFromJump"
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
AWS:
- !Sub "arn:aws:iam::${JumpAccountID}:user/tester-01"
Action:
- 'sts:AssumeRole'
Condition:
Bool:
aws:MultiFactorAuthPresent: true
## この StringLike の条件を追加します
StringLike:
sts:RoleSessionName: ${aws:username}
...
この条件を設定した上で、IAMユーザー名と一致しないセッション名でスイッチロールすると以下のようにエラーで弾いてくれます。
$ aws s3 ls --profile tester-01-prod
Enter MFA code for arn:aws:iam::111111111111:mfa/tester-01:[6桁のコードを入力]
An error occurred (AccessDenied) when calling the AssumeRole operation: User: arn:aws:iam::111111111111:user/tester-01 is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::333333333333:role/AdminRoleFromJump
$
今回は以上です〜ノシ
参考
アリガト━━━ヾ(´∀`)ノ━━━━♪
AWS CLI での IAM ロールの使用 多要素認証を使用する
サポートされる config ファイル設定
[アップデート] IAMロールセッション名にユーザー名を強制できる条件 sts:RoleSessionName が使えるようになりました