AWS CLIでSwitch Role してさらに Switch Role してみた。(ロールの連鎖:Role chaining)

福岡オフィスの梶原です。 先日、福岡オフィスでこんな会話がありました。

「スイッチロールしたいけどできないんですよね。」
「できるでしょ。」
「いや、正確にはユーザからはスイッチロールできるんですけど、スイッチロールしてからスイッチロールできなくて。」
「できないでしょ。スイッチロール元のユーザーで制限かかってるから」
「えー、そうなんですかー」
(わいがや)
「スイッチロール元を制限したいんですけど、それをロールにできないんですか?」
(わいがや)
「え、できた・・・CLIだけど」

ということで、調べたところこの動きは用語としては、ロールの連鎖(Role chaining)という動きみたいです。 https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_roles_terms-and-concepts.html#iam-term-role-chaining

User1 に、RoleA および RoleB を引き受けるアクセス許可があるとします。さらに、RoleA には RoleB を引き受けるアクセス許可があるとします。AssumeRole API オペレーションで User1 の長期的なユーザー認証情報を使用して RoleA を引き受けることができます。このオペレーションは RoleA の短期的な認証情報を返します。ロールの連鎖を行うには、RoleA の短期認証情報を使用して RoleB を引き受けます。

図にするとこういう感じです。

ということで、

  1. User1で認証

  2. User1からRoleAにスイッチロール

  3. RoleAからRoleBにスイッチロール

をAWS CLIでやってみました。

いるもの

  • User1 : AWS アカウント(要アクセスキー)  ※(AWS 多要素認証 (MFA) で認証)非ルートユーザ
  • RoleA : IAMロール(引き受け元User1)
  • RoleB : IAMロール(引き受け元RoleA)

ポリシー設定

RoleAのポリシードキュメント

RoleAのポリシーでPrincipal(信頼されたエンティティ)にUser1を指定します。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::YYYYYYYYYYYY:user/User1"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "Bool": {
          "aws:MultiFactorAuthPresent": "true"
        }
      }
    }
  ]
}

※ログイン時MFAを有効に

RoleBのポリシードキュメント

RoleBのポリシーでPrincipal(信頼されたエンティティ)にRoleAを指定します。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::XXXXXXXXXXXX:role/RoleA"
      },
      "Action": "sts:AssumeRole",
      "Condition": {}
    }
  ]
}

ポイントはPrincipalのrole/RoleAの部分になります。
AWSのドキュメントによると保存時にプリンシパル ID に変換されます

ロールの Principal 要素に、特定の IAM ロールを指し示す ARN が含まれている場合、その ARN はポリシーを保存するときにロールの一意のプリンシパル ID に変換されます

https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_elements_principal.html

1. User1で認証

User1の認証情報設定

User1のアクセスキーID、シークレットアクセスキーをAWS CLIに設定します。

$ aws configure
AWS Access Key ID [None]: HOGEHOGEHOGEHOGE
AWS Secret Access Key [None]: FUGAFUGAFUGAFUGA
Default region name [None]: ap-northeast-1
Default output format [None]: 

~/.aws/credentials ファイルが作成されているかと思います

$ cat ~/.aws/credentials
[default]
aws_access_key_id = HOGEHOGEHOGEHOGE
aws_secret_access_key = FUGAFUGAFUGAFUGA

認証確認

$ aws sts get-caller-identity
Enter MFA code for arn:aws:iam::YYYYYYYYYYYY:mfa/User1:
{
    "UserId": "XXXXXXXXXXXXXXXXXXXXX",
    "Account": "YYYYYYYYYYYY",
    "Arn": "arn:aws:iam::YYYYYYYYYYYY:user/User1"
}
※各値は環境によります
$ aws s3 ls
Enter MFA code for arn:aws:iam::YYYYYYYYYYYY:mfa/User1:
(S3へのアクセス権限があればバケットが表示されます)

2. スイッチロール1回目(User1 から RoleAへ)

.aws/configの設定

ロールの新しいプロファイル"role-a"を .aws/config ファイルに設定します

[profile role-a]
role_arn = arn:aws:iam::XXXXXXXXXXXX:role/RoleA
mfa_serial = arn:aws:iam::YYYYYYYYYYYY:mfa/User1
source_profile = default

※ポリシーでAWS 多要素認証 (MFA) を必須にしていますのでmfa_serialを指定します

動作確認

AWS CLIのコマンド時profileオプションに"role-a"を指定します

$ aws sts get-caller-identity --profile role-a
Enter MFA code for arn:aws:iam::YYYYYYYYYYYY:mfa/User1:
{
    "UserId": "XXXXXXXXXXXXXXXXXXXXX:botocore-session-0123456789",
    "Account": "XXXXXXXXXXXX",
    "Arn": "arn:aws:sts::XXXXXXXXXXXX:assumed-role/RoleA/botocore-session-0123456789"
}
※各値は環境によります
$ aws s3 ls --profile role-a
Enter MFA code for arn:aws:iam::YYYYYYYYYYYY:mfa/User1:
(S3へのアクセス権限があればバケットが表示されます)

または

export AWS_PROFILE=role-a

を実施し、環境変数のAWS_PROFILEで、切り替えるプロファイルを指定してください。

3. スイッチロール2回目(User1 から RoleAから RoleBへ)

.aws/configの設定

ロールの新しいプロファイル"role-b"を .aws/config ファイルに設定します

[profile role-a]
role_arn = arn:aws:iam::XXXXXXXXXXXX:role/RoleA
mfa_serial = arn:aws:iam::YYYYYYYYYYYY:mfa/User1
source_profile = default

[profile role-b]
role_arn = arn:aws:iam::XXXXXXXXXXXX:role/RoleB
source_profile = role-a

ポイントはsource_profile = role-a で、引き受け元のRoleAのプロファイルを指定します。

動作確認

AWS CLIのコマンド時profileオプションに"role-b"を指定します

$ aws sts get-caller-identity --profile role-b
Enter MFA code for arn:aws:iam::YYYYYYYYYYYY:mfa/User1:
{
    "UserId": "XXXXXXXXXXXXXXXXXXXXX:botocore-session-0123456789",
    "Account": "XXXXXXXXXXXX",
    "Arn": "arn:aws:sts::XXXXXXXXXXXX:assumed-role/RoleB/botocore-session-0123456789"
}

※各値は環境によります

$ aws s3 ls --profile role-b
Enter MFA code for arn:aws:iam::YYYYYYYYYYYY:mfa/User1:
(S3へのアクセス権限があればバケットが表示されます)

または

export AWS_PROFILE=role-b

を実施し、環境変数のAWS_PROFILEを指定してください。

補足 キャッシュされている認証情報の削除

どの認証情報を使っているかわからない。なんかキャッシュが効いているとわかりづらいとかあれば 以下コマンドでキャッシュを削除できます。

$ rm -r ~/.aws/cli/cache

まとめ

ユーザーからRoleにスイッチロールすることはよくあるのですが、RoleからRoleにスイッチロールする方法と指定の仕方はわかりにくかったので、まとめてみました。 使い方によっては、踏み台Roleみたいにできるかもしれません(通常は別の方法で制限することをおすすめします) また、CLIからは使えますので、CloudFormationの実行などで使える場面もあるかと思います。 尚、AWSコンソールからのロールからロールへの切り替えは現在のところ元の認証情報を使用するためできないようです。

おまけ

「ロールからスイッチロールできたけど、どこまでいけるんでしょうか?」
「え?なにが?」
「chaining」(なんか発音いいな。)
「・・・」

[profile role-a]
role_arn = arn:aws:iam::XXXXXXXXXXXX:role/RoleA
mfa_serial = arn:aws:iam::XXXXXXXXXXXX:mfa/User1
source_profile = default

[profile role-b]
role_arn = arn:aws:iam::XXXXXXXXXXXX:role/RoleB
source_profile = role-a

[profile role-c]
role_arn = arn:aws:iam::XXXXXXXXXXXX:role/RoleC
source_profile = role-b

[profile role-d]
role_arn = arn:aws:iam::XXXXXXXXXXXX:role/RoleD
source_profile = role-c

[profile role-e]
role_arn = arn:aws:iam::XXXXXXXXXXXX:role/RoleE
source_profile = role-d
$ aws sts get-caller-identity --profile role-e
{
    "UserId": "XXXXXXXXXXXX:botocore-session-1234567890",
    "Account": "XXXXXXXXXXXX",
    "Arn": "arn:aws:sts::XXXXXXXXXXXX:assumed-role/RoleE/botocore-session-1234567890"
}

「スイッチロール5回まではいけました。これ以上は怒られそうなのでやめときます。」

「Let's Loop!」 (ちょ発音w)
「(ざわざわ)」

やり方は記載しませんが、中でちゃんと連鎖をスタックにつんで管理しているようで、ループするように設定したらエラーとなりました。 --debugなどを指定してAWS CLIを実行してみると動きがわかって面白いです!すばらっ

参考URL

IAM JSON ポリシーの要素:Principal https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_elements_principal.html

AWS CLI の設定 » IAM ロールを引き受ける https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-role.html