はじめに
この度、特定のIAMロールが特定のS3バケットに対して、想定したアクションを実施できるか、事前検証することになりました。
例:IAMロール「TestRole」がバケット「TestBacket」のオブジェクトを削除可能だが、バケットポリシーの変更は不可・・・など
そこで、表題のIAM Policy Simulatorという機能を初めて使ってみました。
本ブログにて、本機能について紹介していきます。
IAM Policy Simulator とは
IAM ポリシーを 実際のリクエストを送らずに 評価し、「このユーザがこの操作をしたら許可されるか、拒否されるか」を返してくれる機能です。
特徴は以下です。
- 実 API は呼ばれないので、本番リソースに対して試しても何も起きない
- アクションごとに
allowed/explicitDeny/implicitDenyの 3 値で返る - allow または explicitDeny のときは、どのポリシーのどの Statement が効いたかも教えてくれる
評価に含められるポリシーは次の 4 種類です。
| 種類 | 例 |
|---|---|
| アイデンティティベースポリシー | ユーザ・ロールに付いている IAM ポリシー |
| アクセス許可の境界 | Permissions boundary |
| SCP | Organizations のサービスコントロールポリシー |
| リソースベースポリシー | S3 バケットポリシー、SQS キューポリシーなど |
公式: IAM policy testing with the IAM policy simulator
今回はS3のバケットポリシーとIAMユーザーの評価に使いました。
評価バケットポリシー
バケットポリシーの要件は以下です。
- 特定のIAMロールのみ、オブジェクトの追加や削除が可能
- バケットの管理ユーザーのみ、バケットポリシーの編集が可能
そのため以下のような Deny のみで構成したバケットポリシーを作成しました。
- オブジェクトの書き込み・削除は
user/backup-writer以外を拒否 - バケットの管理操作(削除・ポリシー変更など)は管理者ロール 2 つ(BackupAdmin/InfraOps)と root 以外を拒否
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyObjectWriteExceptBackupWriter",
"Effect": "Deny",
"Principal": "*",
"Action": ["s3:PutObject", "s3:DeleteObject"],
"Resource": "arn:aws:s3:::example-backup-bucket/*",
"Condition": {
"ArnNotEquals": {
"aws:PrincipalArn": "arn:aws:iam::123456789012:user/backup-writer"
}
}
},
{
"Sid": "DenyBucketManagementExceptAdmins",
"Effect": "Deny",
"Principal": "*",
"Action": ["s3:DeleteBucket", "s3:PutBucketPolicy", "s3:DeleteBucketPolicy"],
"Resource": "arn:aws:s3:::example-backup-bucket",
"Condition": {
"ArnNotEquals": {
"aws:PrincipalArn": [
"arn:aws:iam::123456789012:role/BackupAdmin",
"arn:aws:iam::123456789012:role/InfraOps",
"arn:aws:iam::123456789012:root"
]
}
}
}
]
}
では以下の二点について、IAM Policy Simulatorを使用して検証していきます。
backup-writerの DeleteObject が allowed になることbackup-writerの DeleteBucket が explicitDeny になること
CLIでの実行例
以下コマンドにてbackup-writer の DeleteObject が allowed になることを確認します。
aws iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::123456789012:user/backup-writer \
--action-names s3:DeleteObject \
--resource-arns arn:aws:s3:::example-backup-bucket/test/x \
--resource-policy file://bucketpolicy.json \
--context-entries "ContextKeyName=aws:PrincipalArn,ContextKeyValues=arn:aws:iam::123456789012:user/backup-writer,ContextKeyType=string" \
--query 'EvaluationResults[].[EvalActionName,EvalDecision]'
各オプションの意味は次のとおりです。
| オプション | 意味 |
|---|---|
--policy-source-arn |
誰の権限で試すか |
--action-names |
試す操作。複数指定可 |
--resource-arns |
対象バケット |
--resource-policy |
渡すバケットポリシー |
--context-entries |
条件キーの値 |
--query |
出力を「操作名と判定」だけに絞る |
出力:
["s3:DeleteObject", "allowed"]
公式: simulate-principal-policy (AWS CLI reference)
注意点: --context-entries を付けないと全部拒否になる
上のコマンドから --context-entries を外して実行すると、以下のような結果になりバケットポリシーでDenyしていないアクションまでDenyされています。
[["s3:PutObject", "explicitDeny"], ["s3:DeleteObject", "explicitDeny"], ["s3:GetObject", "allowed"]]
原因
理由は 2 つの仕様の組み合わせです。
(1) Simulator には –policy-source-arnで渡すarnと条件キーで使うaws:PrincipalArnは別物
Simulator実行時、以下のように複数の情報をくっつけたものが、実行するようなイメージです。
例
| 情報 | 名前 | 例 | CLI での渡し方 |
|---|---|---|---|
| 誰が | Principal(プリンシパル) | backup-writer |
--policy-source-arn |
| 何を | Action(アクション) | s3:PutObject |
--action-names |
| どこに | Resource(リソース) | example-backup-bucket/test/x |
--resource-arns |
| どこから | aws:SourceIp(グローバル条件キー) |
203.0.113.5 |
--context-entries、型 ip |
| いつ | aws:CurrentTime(グローバル条件キー) |
2026-09-05T01:00:00Z |
--context-entries、型 date |
| ARN は | aws:PrincipalArn(グローバル条件キー) |
arn:aws:iam::123456789012:user/backup-writer |
--context-entries、型 string |
しかし、aws:PrincipalArn については自動で渡されず、明示的に情報を付与してあげる必要があります。
※上記のIPや時間も、aws:PrincipalArnと同様に明示的に付与する必要がある
(2)バケットポリシーでaws:PrincipalArnを指定している
以下でaws:PrincipalArnを指定しています。--context-entries で明示的にarnを指定しないと、バケットポリシーは問答無用で拒否します。
→backup-writer で試しているのに aws:PrincipalArn が空 → 「backup-writer ではない」と判定 → Deny
"Condition": {
"ArnNotEquals": {
"aws:PrincipalArn": "arn:aws:iam::123456789012:user/backup-writer"
}
まとめ
IAM Policy Simulatorについて深掘りしてみました。
--context-entriesでarnの指定が必要だった件は、「それくらい融通利かせてくれ」と思いましたが、
あくまで実際にAPIをたたかないという仕組み上、仕方ないことなのかもしれません。
今回はS3のバケットポリシーが主な検証対象でしたが、MFAや送信元制限の検証など、色々と便利そうなので、今後機会があれば試してみたいと思います。

