principal に IAM ロールを指定したことはありますか?
あまりないような気もしますが、ドキュメントに気になる内容を発見したので書いてみます。
principal に IAM ロールを指定するとは
IAM ポリシーは以下のように、
Principal が Resource に対して Action することを Condition の条件のもと Effect する
という構成になっています。
例1)
Lambda (Principal)が S3(Resource)に対して s3:GetObject(Action)することを Allow(Effect)する
という IAM ポリシーを書くことができます。
例2)
IAM ユーザー(Principal)が IAM ロール(Resource)に対して sts:AssumeRole(Action)することを Allow(Effect)する
という IAM ポリシーを書くことができます。
IAM ロールに設定する信頼ポリシーでよくあるパターンです。
つまり、principal に IAM ロールを指定するとは、
IAM ロール(Principal)が Resource に対して Action することを Effect する
という内容のポリシーを設定することと言えます。
で今回発見したこと
以下ドキュメントの「重要」という赤の網掛け部分です。
ロール信頼ポリシーの Principal 要素に、特定の IAM ロールを指し示す ARN が含まれている場合、その ARN はポリシーを保存するときにロールの一意のプリンシパル ID に変換されます。これにより、ロールを削除して再作成することにより、誰かがそのユーザーの特権をエスカレートするリスクを緩和できます。
通常、この ID はコンソールには表示されません。これは、信頼ポリシーが表示されるときに、IAM が ロール ARN への逆変換を行うためです。
ただし、ロールを削除すると、関係が壊れます。
ロールを再作成した場合でも、ポリシーは適用されません。これは、新しいロールは信頼ポリシーに保存されている ID と一致しない新しいプリンシパル ID を持っているためです。
この場合、プリンシパル ID はリソースベースポリシーに表示されます。これは AWS が有効な ARN に戻って ID をマッピングできなくなるためです。その結果、信頼ポリシーの Principal 要素で参照されているロールを削除して再作成する場合は、ロールを編集して正しくなくなったプリンシパル ID を正しい ARN に置き換える必要があります。ポリシーを保存するときに、ARN は再びロールの新しいプリンシパル ID に変換されます。
なんだか難しい感じがしますが、
「principal に IAM ロールを指定して、その IAM ロールを削除してから同じロール名で別の IAM ロールを作成しても、同じようにアクセスすることはできません」
ということのようです。
動作確認してみたい
検証
ロールの連鎖(Role chaining) で検証してみます。
IAM ユーザー「principal-test-user」から、IAM ロール「principal-test-role」にスイッチロールし、さらに IAM ロール「s3-access-role」にスイッチロールして S3 バケット「20221220-emiki-s3bucket」にアクセスできるか確認します。
ここでキモになるのが、IAM ロール「s3-access-role」の信頼ポリシーの Principal に IAM ロール「principal-test-role」を指定するところです。
IAM ロール「principal-test-role」を削除し、全く同じポリシーで全く同じロール名のロールを再作成した場合、S3 バケット「20221220-emiki-s3bucket」にアクセスできるのか試します。
1. IAM ユーザー「principal-test-user」を作成する
IAM ユーザー「principal-test-user」を作成します。
IAM コンソールからサクッと作成します。
- パスワード - AWS マネジメントコンソールへのアクセス
アクセス許可の設定はしません。
AWS マネジメントコンソールへのアクセスをするために、パスワードだけ設定します。
2. IAM ロール「principal-test-role」を作成する
IAM ロール「principal-test-role」を作成します。
IAM コンソールからサクッと作成します。
-
ステップ 1 信頼されたエンティティを選択
- 信頼されたエンティティタイプ:AWS アカウント
- AWS アカウント:このアカウント
-
ステップ 2 許可を追加
- AWSCloudShellFullAccess
-
ステップ 3 名前、確認、および作成
- ロール名:principal-test-role
- 説明:principal-test-role before
- タグを追加
- key:Environment
- Value:before
作成した IAM ロール「principal-test-role」の信頼ポリシーを少し編集します。
AWS アカウントに所属する IAM ユーザーすべてが principal になっているので、先ほど作成した IAM ユーザー「principal-test-user」を principal に設定します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:root"
},
"Action": "sts:AssumeRole",
"Condition": {}
}
]
}
↓
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:user/principal-test-user"
},
"Action": "sts:AssumeRole",
"Condition": {}
}
]
}
3. IAM ロール「s3-access-role」を作成する
S3 へのアクセス権限を持つ IAM ロール「s3-access-role」を作成します。
IAM コンソールからサクッと作成します。
-
ステップ 1 信頼されたエンティティを選択
- 信頼されたエンティティタイプ:AWS アカウント
- AWS アカウント:このアカウント
-
ステップ 2 許可を追加
- AmazonS3FullAccess
-
ステップ 3 名前、確認、および作成
- ロール名:s3-access-role
- 説明:s3-access-role
作成した IAM ロール「s3-access-role」の信頼ポリシーを少し編集します。
AWS アカウントに所属する IAM ユーザーすべてが principal になっているので、先ほど作成した IAM ロール「principal-test-role」を principal に設定します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:root"
},
"Action": "sts:AssumeRole",
"Condition": {}
}
]
}
↓
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:role/principal-test-role"
},
"Action": "sts:AssumeRole",
"Condition": {}
}
]
}
4. S3 バケットにアクセスする
「principal-test-user」で「principal-test-role」にスイッチロールし、CloudShell で「s3-access-role」にスイッチします。
二重にスイッチ後、S3 バケットにアクセスできるか確認します。
4-1. スイッチロール 1 回目
「principal-test-user」で AWS マネジメントコンソールにログインします。
続いて「principal-test-role」にスイッチロールします。
スイッチロール後の「principal-test-role」で CloudShell を開きます。
この段階で aws sts get-caller-identity
すると、現在の権限が「principal-test-role」であることが分かります。
[cloudshell-user@ip-10-6-47-215 ~]$ aws sts get-caller-identity
{
"UserId": "AROA4LMX2UGT7Q4RLBOOI:principal-test-user",
"Account": "123456789012",
"Arn": "arn:aws:sts::123456789012:assumed-role/principal-test-role/principal-test-user"
}
[cloudshell-user@ip-10-6-47-215 ~]$
4-2. スイッチロール 2 回目
この後スイッチロールする「s3-access-role」のプロファイルを設定します。
まず CloudShell で「~/.aws」ディレクトリを作成します。
(デフォルトでは存在しないようです)
[cloudshell-user@ip-10-6-47-215 ~]$ mkdir ~/.aws
[cloudshell-user@ip-10-6-47-215 ~]$ ls -la
total 37
drwxr-xr-x 5 cloudshell-user cloudshell-user 4096 Jan 9 06:53 .
drwxr-xr-x 3 root root 1024 Jan 9 06:24 ..
drwxrwxr-x 2 cloudshell-user cloudshell-user 4096 Jan 9 06:53 .aws
-rw------- 1 cloudshell-user cloudshell-user 118 Dec 22 13:56 .bash_history
-rw-r--r-- 1 cloudshell-user cloudshell-user 18 Dec 22 13:28 .bash_logout
-rw-r--r-- 1 cloudshell-user cloudshell-user 193 Dec 22 13:28 .bash_profile
-rw-r--r-- 1 cloudshell-user cloudshell-user 314 Dec 22 13:28 .bashrc
drwxr-xr-x 3 cloudshell-user cloudshell-user 4096 Dec 22 13:28 .config
drwxr-xr-x 3 cloudshell-user cloudshell-user 4096 Jan 9 06:25 .local
-rw-r--r-- 1 cloudshell-user cloudshell-user 777 Dec 22 13:28 .zshrc
[cloudshell-user@ip-10-6-47-215 ~]$
「credentials」ファイルを作成します。
vim で「credentials」ファイルを開きます。
[cloudshell-user@ip-10-6-47-215 ~]$ vim ~/.aws/credentials
「i」を押下して編集モードに移行し、以下のように設定します。
[s3-access-role]
role_arn = arn:aws:iam::123456789012:role/s3-access-role
credential_source = EcsContainer
「esc」を押下して編集モードから抜け、「:wq」で保存します。
この段階で aws sts get-caller-identity --profile s3-access-role
すると、現在の権限が「s3-access-role」であることが分かります。
[cloudshell-user@ip-10-6-47-215 ~]$ aws sts get-caller-identity --profile s3-access-role
{
"UserId": "AROA4LMX2UGTS5YWJ3QKR:botocore-session-1673247507",
"Account": "123456789012",
"Arn": "arn:aws:sts::123456789012:assumed-role/s3-access-role/botocore-session-1673247507"
}
[cloudshell-user@ip-10-6-47-215 ~]$
4-3. S3 バケット内のオブジェクト表示
バケットとオブジェクトの一覧表示 を参考に、S3 バケット内のオブジェクトを表示します。
[cloudshell-user@ip-10-6-47-215 ~]$ aws s3 ls s3://20221220-emiki-s3bucket --profile s3-access-role
2022-12-20 14:02:16 0 test - コピー (2).txt
2022-12-20 14:02:16 0 test - コピー (3).txt
2022-12-20 14:02:16 0 test - コピー (4).txt
2022-12-20 14:02:16 0 test - コピー.txt
2022-12-20 14:02:16 0 test.txt
[cloudshell-user@ip-10-6-47-215 ~]$
表示できました。
ここで、CloudShell を閉じ、「principal-test-user」にスイッチバックします。
5. 「principal-test-role」を削除する
6. 再度同じ名前と権限で「principal-test-role」を作成する
再度同じ名前と権限で「principal-test-role」を作成します。
IAM コンソールからサクッと作成します。
-
ステップ 1 信頼されたエンティティを選択
- 信頼されたエンティティタイプ:AWS アカウント
- AWS アカウント:このアカウント
-
ステップ 2 許可を追加
- AWSCloudShellFullAccess
-
ステップ 3 名前、確認、および作成
- ロール名:principal-test-role
- 説明:principal-test-role after
- タグを追加
- key:Environment
- Value:after
作成した IAM ロール「principal-test-role」の信頼ポリシーを編集します。
AWS アカウントに所属する IAM ユーザーすべてが principal になっているので、既存の IAM ユーザー「principal-test-user」を principal に設定します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:root"
},
"Action": "sts:AssumeRole",
"Condition": {}
}
]
}
↓
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:user/principal-test-user"
},
"Action": "sts:AssumeRole",
"Condition": {}
}
]
}
7. S3 バケットにアクセスする
「principal-test-user」で「principal-test-role」にスイッチロールし、CloudShell で「s3-access-role」にスイッチします。
二重にスイッチ後、S3 バケットにアクセスできるか確認します。
7-1. スイッチロール 1 回目
「principal-test-user」で AWS マネジメントコンソールにログインします。
続いて「principal-test-role」にスイッチロールします。
スイッチロール後の「principal-test-role」で CloudShell を開きます。
この段階で aws sts get-caller-identity すると、現在の権限が「principal-test-role」であることが分かります。
[cloudshell-user@ip-10-6-20-151 ~]$ aws sts get-caller-identity
{
"UserId": "AROA4LMX2UGTZFOGO2J5M:principal-test-user",
"Account": "123456789012",
"Arn": "arn:aws:sts::123456789012:assumed-role/principal-test-role/principal-test-user"
}
[cloudshell-user@ip-10-6-20-151 ~]$
7-2. スイッチロール 2 回目
この後スイッチロールする「s3-access-role」のプロファイルを設定します。
まず CloudShell で「~/.aws」ディレクトリを作成します。
[cloudshell-user@ip-10-6-20-151 ~]$ mkdir ~/.aws
[cloudshell-user@ip-10-6-20-151 ~]$ ls -la
total 32
drwxr-xr-x 4 cloudshell-user cloudshell-user 4096 Jan 9 07:16 .
drwxr-xr-x 4 root root 4096 Jan 9 07:06 ..
drwxrwxr-x 2 cloudshell-user cloudshell-user 4096 Jan 9 07:16 .aws
-rw-r--r-- 1 cloudshell-user cloudshell-user 18 Jan 9 07:06 .bash_logout
-rw-r--r-- 1 cloudshell-user cloudshell-user 193 Jan 9 07:06 .bash_profile
-rw-r--r-- 1 cloudshell-user cloudshell-user 314 Jan 9 07:06 .bashrc
drwxr-xr-x 3 cloudshell-user cloudshell-user 4096 Jan 9 07:06 .config
-rw-r--r-- 1 cloudshell-user cloudshell-user 777 Jan 9 07:06 .zshrc
[cloudshell-user@ip-10-6-20-151 ~]$
「credentials」ファイルを作成します。
vim で「credentials」ファイルを開きます。
[cloudshell-user@ip-10-6-20-151 ~]$ vim ~/.aws/credentials
「i」を押下して編集モードに移行し、以下のように設定します。
[s3-access-role]
role_arn = arn:aws:iam::123456789012:role/s3-access-role
credential_source = EcsContainer
「esc」を押下して編集モードから抜け、「:wq」で保存します。
この段階で aws sts get-caller-identity --profile s3-access-role
すると、アクセスが拒否されます。
[cloudshell-user@ip-10-6-20-151 ~]$ aws sts get-caller-identity --profile s3-access-role
An error occurred (AccessDenied) when calling the AssumeRole operation: User: arn:aws:sts::123456789012:assumed-role/principal-test-role/principal-test-user is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::123456789012:role/s3-access-role
[cloudshell-user@ip-10-6-20-151 ~]$
7-3. S3 バケット内のオブジェクト表示
S3 バケット内のオブジェクト一覧も表示できません。
[cloudshell-user@ip-10-6-20-151 ~]$ aws s3 ls s3://20221220-emiki-s3bucket --profile s3-access-role
An error occurred (AccessDenied) when calling the AssumeRole operation: User: arn:aws:sts::123456789012:assumed-role/principal-test-role/principal-test-user is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::12345689012:role/s3-access-role
[cloudshell-user@ip-10-6-20-151 ~]$
参考