
Assumed-role セッションプリンシパルのサービス名前空間を iam にしたが そっと sts に書き換えられた
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
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が入っているパターンを見つけてしまいました。

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で表されています。そしてそもそもこれを調べようと思ったきっかけは以下の記述を見かけたことです。

これは IAM AcceccAnalyzer によるポリシーチェック項目のリファレンスです。IAM ロール信頼ポリシーで冗長な書き方をした時にその除去を提案してくれる項目の例として書かれています。
初見で「誤記では?」と思ったのですが、実際に信頼ポリシーの編集画面で再現してみるときちんと提案が行われました。

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

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

不思議動作だ。
AWS マネジメントコンソールで試してみる
もうちょっと挙動を確認するために以下のポリシーの Principal 要素にiamの Assumed-role セッションプリンシパルを指定してみます。
- S3 バケットポリシー
- IAM ロール信頼ポリシー
S3 バケットポリシー
この状態で保存を試みます。

stsに変わっていました。

なるほど。
IAM ロール信頼ポリシー
この状態で保存を試みます。

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

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

そうですか。
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) がお送りしました。
参考
- AWS JSON policy elements: Principal - AWS Identity and Access Management
- IAM ID - AWS Identity and Access Management
- Identity and Access Management のアクション、リソース、および条件キー - サービス認証リファレンス
- Access Analyzer policy check reference - AWS Identity and Access Management
脚注
- Amazon リソースネーム (ARN) - AWS 全般のリファレンス ↩
- さらに言うとプリンシパルの順番も入れ替わっていますが、そこはあまり重要じゃないのでサラッと流しておきます。 ↩











