Assumed-role セッションプリンシパルのサービス名前空間を iam にしたが そっと sts に書き換えられた

iam な表情もいいけれど やっぱり assumed-role には sts でいて欲しい

arn:${Partition}:iam::${Account}:assumed-role/${RoleName}/${RoleSessionName} なんてあるのか?

コンバンハ、千葉(幸)です。

突然ですがわたしは AssumeRole (IAM ロールを引き受ける)が好きです。AssumeRole するさまを「お面を被る」と表現するのが好きです。


▲ お面を被って力を得ている図


IAM ユーザーが別の AWS アカウントにある IAM ロールを引き受けるケースを考えると、それぞれの ARN は以下の通りです。

  • arn:aws:iam::999999999999:user/ユーザー名
  • arn:aws:iam::000000000000:role/ロール名
  • arn:aws:sts::000000000000:assumed-role/ロール名/セッション名

3つ目の 「IAM ロールを引き受けたセッション(Assumed-role セッション)」のみ、サービスの名前空間がstsです。サービスの名前空間とは、今回の例で言えばarn:aws:の後にくる部分を指します。 *1

「正しくはstsだけどうっかりiam間違いがちなところだよね〜」などと思っていたのですが、公式のリファレンスでiamが入っているパターンを見つけてしまいました。

Identity_and_Access_Management_service_authorization_reference

AssumeRole 大好きおじさんとしては、「sts以外は認められない。これは誤りでは?ということは遂にわたし自身がリファレンスになる時が来たのでは?」などと思っていたのですが、もしかしたらiamにしても正常に動作するのかもしれない、と思い、試してみることにしたのであった。

まとめ

  • 構文としてはサービス名前空間がiamでも間違ってはいない
  • ただし設定値として保存される際にはstsに自動で置き換えられる
  • 捕まえたと思ったら手のひらから零れ落ち逃げていくような儚さを感じる

sts で合ってるよな?という土台を固める

iamでも正しく動くのか?を確かめる前に、急に不安になってきたのでstsが正しいかどうかを調べます。

とは言っても実際に AssumeRole した後にプリンシパルを確認すればstsになっているので、一目瞭然ではあります。

# AssumeRole を実行し環境変数を設定
% OUTPUT=$(aws sts assume-role --role-arn arn:aws:iam::000000000000:role/IAMRoleA --role-session-name hoge)

export AWS_ACCESS_KEY_ID=$(echo $OUTPUT | jq -r .Credentials.AccessKeyId)
export AWS_SECRET_ACCESS_KEY=$(echo $OUTPUT | jq -r .Credentials.SecretAccessKey)
export AWS_SESSION_TOKEN=$(echo $OUTPUT | jq -r .Credentials.SessionToken)

# プリンシパルの確認
% aws sts get-caller-identity
{
    "UserId": "AROAQ3BIIH736BYCRY6IV:hoge",
    "Account": "000000000000",
    "Arn": "arn:aws:sts::000000000000:assumed-role/IAMRoleA/hoge"
}

そのほかの例で言うと IAM ARN の構文を見るとstsになっていますし、

JSON ポリシーの Principal 要素で Assumed-role セッションプリンシパルを指定する際の書き方もstsになっています。

むしろこれで「iamでも書けます」と言われても少し困ってしまうな、と言うレベルでstsが正しそうです。

でも iam で書いてある例があるなぁ

とは言っても冒頭で引用した例ではiamで表されています。そしてそもそもこれを調べようと思ったきっかけは以下の記述を見かけたことです。

Access_Analyzer_policy_check_reference_-_AWS_Identity_and_Access_Management2

これは IAM AcceccAnalyzer によるポリシーチェック項目のリファレンスです。IAM ロール信頼ポリシーで冗長な書き方をした時にその除去を提案してくれる項目の例として書かれています。

初見で「誤記では?」と思ったのですが、実際に信頼ポリシーの編集画面で再現してみるときちんと提案が行われました。

IAM_Management_Console

(↓ちなみにstsに置き換えても同じ提案がされます。)

IAM_Management_Console_turstpolicy_suggest

ここで1番目の画像の状態、つまりiamにした状態でポリシーを保存しても、なぜかstsに置き換わっていました。 *2

IAM_Management_Console_trustpolicy_sts

不思議動作だ。

AWS マネジメントコンソールで試してみる

もうちょっと挙動を確認するために以下のポリシーの Principal 要素にiamの Assumed-role セッションプリンシパルを指定してみます。

  • S3 バケットポリシー
  • IAM ロール信頼ポリシー

S3 バケットポリシー

この状態で保存を試みます。

S3_bucket-policy_assumed-role_session

stsに変わっていました。

S3_bucketpolicy_assumed_role_session_principal

なるほど。

IAM ロール信頼ポリシー

この状態で保存を試みます。

IAM_Management_Console_trustpolicy_assumed_role_session_principal

お、更新後もiamのまま表示されました!

IAM_Management_Console_trustpolicy_iam_servicenamespace

勢い余ってページをリロードしたらstsに変わっていました。

IAM_Management_Console_trustpolicy_sts_assumed_role

そうですか。

AWS CLI で試してみる

AWS マネジメントコンソールは気を利かせていろいろやってくれることがあるので、AWS CLI での挙動も確認してみます。

S3 バケットポリシー

以下コマンドでバケットポリシーを設定します。

# 変数にバケットポリシーの中身を格納
% policy=$(cat <<EOM
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::012345678910:assumed-role/IAMRoleA/hoge"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::chibayuki-hoge-hoge/*"
        }
    ]
}
EOM
)

# 上記の変数を指定してコマンド実行
% aws s3api put-bucket-policy --bucket chibayuki-hoge-hoge --policy "$policy"

設定後にポリシーを確認したところ、stsに置き換わっていました。

% aws s3api get-bucket-policy --bucket chibayuki-hoge-hoge | jq -r .Policy | jq .
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:sts::012345678910:assumed-role/IAMRoleA/hoge"
      },
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::chibayuki-hoge-hoge/*"
    }
  ]
}

ふーむ。

IAM ロール信頼ポリシー

以下コマンドで IAM ロールを作成します。(信頼ポリシーだけ設定するコマンドはなさそうでした。)

# 変数に信頼ポリシーの中身を格納
% policy=$(cat <<EOM
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::012345678910:assumed-role/IAMRoleA/hoge"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
EOM
)

# 上記の変数を指定してコマンド実行
% aws iam create-role --role-name hoge --assume-role-policy-document "$policy"
{
    "Role": {
        "Path": "/",
        "RoleName": "hoge",
        "RoleId": "AROAQ3BIIH73SQIEWG7ZS",
        "Arn": "arn:aws:iam::012345678910:role/hoge",
        "CreateDate": "2022-10-04T17:53:04+00:00",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "AWS": "arn:aws:iam::012345678910:assumed-role/IAMRoleA/hoge"
                    },
                    "Action": "sts:AssumeRole"
                }
            ]
        }
    }
}

↑コマンドの戻り値ではiamのままになっています!

その後に信頼ポリシーを確認すると、stsに置き換わっていました。

% aws iam get-role --role-name hoge
{
    "Role": {
        "Path": "/",
        "RoleName": "hoge",
        "RoleId": "AROAQ3BIIH73SQIEWG7ZS",
        "Arn": "arn:aws:iam::012345678910:role/hoge",
        "CreateDate": "2022-10-04T17:53:04+00:00",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "AWS": "arn:aws:sts::012345678910:assumed-role/IAMRoleA/hoge"
                    },
                    "Action": "sts:AssumeRole"
                }
            ]
        },
        "MaxSessionDuration": 3600,
        "RoleLastUsed": {}
    }
}

そうですか。

まとめ(再掲)

  • 構文としてはサービス名前空間がiamでも間違ってはいない
  • ただし設定値として保存される際にはstsに自動で置き換えられる
  • 捕まえたと思ったら手のひらから零れ落ち逃げていくような儚さを感じる

終わりに

Assumed-role セッションプリンシパルのサービス名前空間をiamにしてみたけどそっとstsに置き換えられた、という話でした。

プリンシパルの構文としては誤っていないため設定リクエストは正常に通りますが、iamのまま設定値が落ち着くということはなさそうでした。いっそのことstsじゃないとリクエストが成功しないようにしてくれれば分かりやすいのに、とも思いますが、どこか儚さを感じて風流な気もしてきたのでこれはこれでいいと思えてきました。

iamで合ってるんだっけ?」と疑問に思う方が世界に80人くらいはいると思うので、そんな方の参考になれば幸いです。

以上、 チバユキ (@batchicchi) がお送りしました。

参考

脚注

  1. Amazon リソースネーム (ARN) - AWS 全般のリファレンス
  2. さらに言うとプリンシパルの順番も入れ替わっていますが、そこはあまり重要じゃないのでサラッと流しておきます。