[アップデート] IAMポリシーシミュレーターがIAMコンソールに移行して機能が追加されました
はじめに
皆様こんにちは、あかいけです。
IAMポリシーの権限をチェックする時などに使用するIAM Policy Simulatorについて、アップデートがありました。
ただ、公式の発表を読んだだけだと、どこが新しくて、どこが従来からある機能なのかが少しわかりにくく感じました。
というわけで今回は、IAM Policy SimulatorがIAMコンソールに移行し、機能が追加された件について、従来からできたことと今回新しくなったことを切り分けながらまとめます。
アップデートの概要
今回のアップデートで、IAM Policy Simulatorは以下の3点が変わりました。
- スタンドアロンのサイトからIAMコンソール内へ移行した
- SCPの条件を含む評価や、APIでのカスタムSCP階層の指定に対応した
- 「特定のポリシーを除外」といった、より実践的なシナリオを再現できるようになった
従来の挙動
これまでのIAM Policy Simulatorは、IAMコンソールとは別の以下スタンドアロンのサイトで提供されていました。
そのため、検証のためにわざわざ別サイトを開く手間があり、地味なことではありますが少し面倒だと感じる場面もありました。
またSCPについては、評価自体は以前から可能でした。
ただし条件(Condition)付きのSCPは正しく評価されず、リージョン制限やタグ要件といった条件をシミュレーターで再現することはできませんでした。
新しい機能
マネジメントコンソール
IAMコンソールへの統合
まず一番わかりやすい変更点として、IAM Policy SimulatorがIAMコンソールに統合されました。
IAMコンソールのナビゲーションペインから「 ポリシーシミュレータ」を選択することでアクセスできます。

IAMポリシーを管理しているのと同じ場所でテストができるので、編集と検証の往復がしやすくなりました。
なお公式ドキュメントを見たところ、従来のスタンドアロンサイトは今後メンテナンスされないようなので、今後はIAMコンソールへ一本化されるのでしょう。
The standalone policy simulator console at https://policysim.aws.amazon.com/ is no longer maintained. Use the policy simulator in the IAM console.
API
以下の機能のうち、条件付きSCPの評価とクロスアカウントの評価は、現状マネジメントコンソールからは行えず、AWS CLI/APIが必要です。(ポリシーの除外はコンソールでも可能)
詳細は以下APIの変更履歴にあります。
SCPを含めたシミュレーション
SCPのシミュレーション自体は以前から可能でしたが、今回、条件(Condition)やリソーススコープを含めたSCPの評価(リージョン制限やタグ要件など)と、API経由での任意のSCP階層の指定に対応しました。
具体的には、SimulateCustomPolicyにOrderedOrganizationPolicyInputListパラメータが追加されています。
ポリシーの除外シミュレーション
特定のポリシーを除外して「このポリシーを外したらどうなるか」を確認できる機能です。
コンソールでは以前からできましたが、今回SimulatePrincipalPolicyにPolicyExclusionListパラメータが追加され、APIでも除外できるようになりました。
クロスアカウントシミュレーションの強化
クロスアカウントのシミュレーションで、アイデンティティポリシーとリソースポリシーそれぞれの判定が返るようになり、拒否時に返る一致ステートメントも、判定を左右したポリシーだけに絞られるよう改善されました。
試してみた
というわけで以下の4つを試します。
- マネジメントコンソールに統合されたシミュレーターを使う
- APIでSCPの新機能(
OrderedOrganizationPolicyInputList)を使う - APIで特定のポリシーを除外する新機能(
PolicyExclusionList)を使う - APIでクロスアカウントシミュレーションを使う
検証1〜3では、S3バケットへのS3読み取りを許可するIAMポリシーをアタッチしたIAMロールを対象にします。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowReadMyBucket",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::akaike-sample-bucket",
"arn:aws:s3:::akaike-sample-bucket/*"
]
}
]
}
なお検証2〜4で使うAPIパラメータは2026年7月30日に追加されたものです。
AWS CLIのバージョンが古いとUnknown optionsエラーになるので、最新版に更新しておいてください。
検証で使うCLIコマンドの詳細は以下を参照してください。
検証1:マネジメントコンソールに統合されたシミュレーターを使う
s3:GetObjectとs3:DeleteObjectをアクションに追加し、リソースにarn:aws:s3:::akaike-sample-bucket/test.txtを指定して「シミュレート」を実行します。

結果は、s3:GetObjectが「許可」(1件のステートメントの明示的な許可)、s3:DeleteObjectが「拒否済み」(一致するステートメントがないことによる暗黙的な拒否)となります。
test-s3-policyで許可したアクションだけが通ることを確認できます。

続いて、左側の「組織ポリシー」にある「サービスコントロールポリシー (SCP)」のトグルをオンにして、SCPを評価に含めてみます。

また前提として、以下のようなS3バケットへの操作を拒否するSCPを適用しています。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyS3OnSampleBucket",
"Effect": "Deny",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::akaike-sample-bucket",
"arn:aws:s3:::akaike-sample-bucket/*"
]
}
]
}
この状態でシミュレートすると、先ほど「許可」だったs3:GetObjectも「拒否済み」に変わり、詳細に「AWS Organizationsによって拒否されました」と表示されます。
拒否される理由も明記されるので、わかりやすくていいですね。

検証2:APIでSCPの新機能(OrderedOrganizationPolicyInputList)を使う
検証1のとおり、コンソールでSCPを含めること自体は以前からできました。
今回新しくなったのは、条件(Condition)付きSCPの評価と、APIでの任意のSCP階層の指定です。
コンソールではSCPだけが参照する条件キー(aws:RequestedRegionなど)に値を設定できないため、条件付きSCPの検証にはAPIを使います。
例として、ap-northeast-1(東京リージョン)以外でのアクションを拒否するSCPを用意します。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyOutsideTokyo",
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
"StringNotEquals": {
"aws:RequestedRegion": "ap-northeast-1"
}
}
}
]
}
これを--ordered-organization-policy-input-listに渡します。
このパラメータは、組織ルートからアカウントまでの階層を順に並べたリストで、各階層のServiceControlPolicyInputListにSCPを指定します。
ここで注意点が2つあります。
- 1つ目は、
ServiceControlPolicyInputListが「文字列の配列」である点- SCPをJSONオブジェクトのまま入れ子にはできず、SCPのJSON全体を1つの文字列として渡す必要があります(そのため
\"でエスケープします)
- SCPをJSONオブジェクトのまま入れ子にはできず、SCPのJSON全体を1つの文字列として渡す必要があります(そのため
- 2つ目は、SCPは階層の各レベルで明示的な
Allowが必要な点- 上記のSCPは
Denyだけなので、これをアカウント階層に単独で置くと、東京リージョンでDenyが不発になったときにそのレベルにAllowが無く、暗黙的に拒否されてしまいます。
- 上記のSCPは
実際の組織では各アカウントにFullAWSAccessも適用されているため、ここでもアカウント階層にFullAWSAccessを含めます。
組織ルートにFullAWSAccess、アカウント階層にFullAWSAccessと上記のリージョン制限SCPを置くと、以下のようになります。
[
{
"ServiceControlPolicyInputList": [
"{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Action\":\"*\",\"Resource\":\"*\"}]}"
]
},
{
"ServiceControlPolicyInputList": [
"{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Action\":\"*\",\"Resource\":\"*\"}]}",
"{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"DenyOutsideTokyo\",\"Effect\":\"Deny\",\"Action\":\"*\",\"Resource\":\"*\",\"Condition\":{\"StringNotEquals\":{\"aws:RequestedRegion\":\"ap-northeast-1\"}}}]}"
]
}
]
条件キーaws:RequestedRegionの値を--context-entriesで指定して実行します。
検証対象のアイデンティティポリシー(冒頭のIAMポリシー)は--policy-input-listで渡します。
なお--policy-input-listは「文字列の配列」を取るパラメータのため、file://でJSONオブジェクトのファイルを渡すと配列として解釈されずエラーになります(Policy input list item 1 has invalid content)。
ここでは$(cat ...)でファイルの中身を文字列として渡しています。
aws iam simulate-custom-policy \
--policy-input-list "$(cat test-s3-policy.json)" \
--ordered-organization-policy-input-list file://scp-input.json \
--action-names "s3:GetObject" \
--resource-arns "arn:aws:s3:::akaike-sample-bucket/test.txt" \
--context-entries "ContextKeyName=aws:RequestedRegion,ContextKeyType=string,ContextKeyValues=us-east-1"
aws:RequestedRegionをus-east-1にするとSCPのDeny条件に一致するため、結果はexplicitDenyになります。
"EvalActionName": "s3:GetObject",
"EvalDecision": "explicitDeny"
逆にap-northeast-1にすれば条件に一致しなくなり、アクションは許可されます。
aws iam simulate-custom-policy \
--policy-input-list "$(cat test-s3-policy.json)" \
--ordered-organization-policy-input-list file://scp-input.json \
--action-names "s3:GetObject" \
--resource-arns "arn:aws:s3:::akaike-sample-bucket/test.txt" \
--context-entries "ContextKeyName=aws:RequestedRegion,ContextKeyType=string,ContextKeyValues=ap-northeast-1"
"EvalActionName": "s3:GetObject",
"EvalDecision": "allowed"
検証3:APIで特定のポリシーを除外する新機能(PolicyExclusionList)を使う
特定のポリシーを除外して「このポリシーを外したらどうなるか」を確認する機能です。
コンソールでポリシーをチェックボックスで除外する操作は以前からありましたが、今回SimulatePrincipalPolicyにPolicyExclusionListパラメータが追加され、APIでも除外できるようになりました。
ここでは、test-s3-roleに検証用としてもう1つAmazonS3FullAccessポリシーもアタッチした状態を考えます。
「過剰に見えるAmazonS3FullAccessを外しても、業務で必要なakaike-sample-bucketへの読み取りは維持されるか」を確認します。
--policy-exclusion-listに、除外したいAmazonS3FullAccessのARNを指定します。
aws iam simulate-principal-policy \
--policy-source-arn "arn:aws:iam::111111111111:role/test-s3-role" \
--policy-exclusion-list '[{"PolicyArn":"arn:aws:iam::aws:policy/AmazonS3FullAccess"}]' \
--action-names "s3:GetObject" \
--resource-arns "arn:aws:s3:::akaike-sample-bucket/test.txt"
AmazonS3FullAccessを除外しても、test-s3-policyが読み取りを許可しているため結果はallowedのままです。
"EvalActionName": "s3:GetObject"
"EvalDecision": "allowed"
また当然ですが全部のポリシーを除外すれば、denyになります。
aws iam simulate-principal-policy \
--policy-source-arn "arn:aws:iam::111111111111:role/test-s3-role" \
--policy-exclusion-list '[{"PolicyArn":"arn:aws:iam::aws:policy/AmazonS3FullAccess"},{"PolicyArn":"arn:aws:iam::111111111111:policy/test-s3-policy"}]' \
--action-names "s3:GetObject" \
--resource-arns "arn:aws:s3:::akaike-sample-bucket/test.txt"
"EvalActionName": "s3:GetObject"
"EvalDecision": "implicitDeny"
このように、過剰な権限を安全に削れるかを、実際にポリシーを変更することなく事前に判断できます。
検証4:APIでクロスアカウントシミュレーションを使う
最後に、クロスアカウントのシミュレーションです。
これは今回の新機能ではなく、リソースベースポリシー対応として以前から提供されているものですが、あわせて確認しておきます。
まず制約としてクロスアカウントの評価はマネジメントコンソールではできず、AWS CLI/APIを使う必要があります。
コンソールにはリソースの所有アカウント(APIでいうResourceOwner)を指定する欄がなく、別アカウントのバケットを指定しても同一アカウント扱いとなり成功してしまうためです。
クロスアカウントでは、アクセスする側のアイデンティティポリシーとリソース側のバケットポリシーの両方が許可して初めて許可されるので、これがコンソールでは再現できません。
ここでは、アカウントAにs3:GetObjectを許可する同じポリシーをアタッチしたロールを2つ(test-s3-allow-role-1、test-s3-allow-role-2)用意します。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowReadAccountBBucket",
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::akaike-sample-bucket/*"
}
]
}
一方、アカウントB側のバケットには、test-s3-allow-role-1にのみ読み取りを許可するバケットポリシーを付けると仮定します。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowRole1Read",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:role/test-s3-allow-role-1"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::akaike-sample-bucket/*"
}
]
}
SimulatePrincipalPolicyを使い、--resource-ownerにリソース側のアカウント(B)を指定することで、クロスアカウントの評価を再現できます。
--policy-source-arnには、検証したいアカウントAのロールを指定します。(このロールのアタッチ済みポリシーは自動で読み取られます)
一方、アカウントBのバケットポリシーはAPIが自動取得しないため、--resource-policyで明示的に渡します。
aws iam simulate-principal-policy \
--policy-source-arn "arn:aws:iam::111111111111:role/test-s3-allow-role-1" \
--resource-policy file://bucket-policy.json \
--resource-owner "arn:aws:iam::222222222222:root" \
--action-names "s3:GetObject" \
--resource-arns "arn:aws:s3:::akaike-sample-bucket/test.txt"
まずtest-s3-allow-role-1は、アイデンティティ側もリソース側(バケットポリシー)も許可しているためallowedになります。
EvalDecisionDetailsを見ると、両方の種別が許可しているのがわかります。
"EvalDecision": "allowed",
"EvalDecisionDetails": {
"IAM Policy": "allowed",
"Resource Policy": "allowed"
}
--policy-source-arnをtest-s3-allow-role-2に変えると、アイデンティティ側は許可でもバケットポリシーに含まれないため、リソース側で許可されず拒否になります。
"EvalDecision": "implicitDeny",
"EvalDecisionDetails": {
"IAM Policy": "allowed",
"Resource Policy": "implicitDeny"
}
このようにEvalDecisionDetailsでアイデンティティポリシーとリソースポリシーそれぞれの判定が返るので、どちら側が原因かを切り分けられます。
今回のアップデートでは、拒否時に返る一致ステートメントも、判定を左右したポリシーだけに絞られるよう改善されています。
さいごに
以上、IAM Policy SimulatorがIAMコンソールに移行して機能が追加されたアップデートでした。
IAMのポリシー検証は、地味ながらもセキュリティを支える重要な作業です。
特にSCPを含めたシミュレーションや、ポリシー除外のシナリオ再現ができるようになったことで、より実際の運用に近い形で権限をテストできるようになりました。
皆様のIAMポリシー検証が、より安心して行えるようになれば幸いです。








