AWS EmulatorでIAMの権限がAWSどおりに判定されない例
AWS Emulator では、IAM の権限がない操作でも通ることがあります。ローカルのテストや CI で「権限が足りないと AccessDenied になる」ことを確かめようとしても、エミュレーターの結果は当てになりません。権限のないユーザーとすべてを拒否するポリシーを作って操作を呼び、どの操作が通り、どの操作が拒否されたかを出力のまま載せます。
検証環境は Ubuntu 24.04.5(x86_64)、AWS Emulator 1.0.353(2026年11月14日リリース、Debian パッケージ)、AWS CLI 2.40.3 です。AWS のアカウントは使わず、リクエストはすべて手元の AWS Emulator に送りました。本物の AWS での結果は試しておらず、IAM の公式ドキュメントをもとに書いています。試したのは AWS CLI から呼べる一部の操作だけで、IAM ロールと STS の AssumeRole、権限の境界(permissions boundary)、KMS のキーポリシーは試していません。
公式ドキュメントに書かれている制限
AWS Emulator の紹介ページには、制限の1つ目として「IAM のポリシーとリソースベースのポリシーを、AWS と同じようには評価しない」と書かれています。セキュリティのテストには使わないように、とも書かれています。
セキュリティのページはもう少し詳しく、次のように説明しています。
- エミュレーターの中で作った IAM ユーザーやロールについて、ポリシーを評価するサービスもあるが、AWS と同じ評価ではない
- エミュレーター自身のキーで署名したリクエストは、拒否しない
- AWS なら拒否するリクエストが通ることも、AWS なら通るリクエストが失敗することもある
ここからは、この説明を実際の操作で確かめます。
準備:エミュレーターを起動して、AWS CLI の接続先にする
入れ方は公式ガイドの Linux 向けの手順のとおりで、Debian パッケージの署名を gpg で確かめてから入れました。テレメトリーを切って起動します。
aws-emulator -t off
別の端末で、公式ガイドにある環境変数を設定します。最後の AWS_PAGER は、出力をページャーで開かないために私が足したものです。
export AWS_ENDPOINT_URL=https://127.0.0.1:9297
export AWS_SHARED_CREDENTIALS_FILE=~/.aws/emulator/9297/emulator_credentials
export AWS_CONFIG_FILE=~/.aws/emulator/9297/config
export AWS_CA_BUNDLE=~/.aws/emulator/9297/ca.pem
export AWS_EC2_METADATA_DISABLED=true
export AWS_DISABLE_HOST_PREFIX_INJECTION=true
export AWS_REGION=us-east-1
export AWS_DEFAULT_REGION=us-east-1
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN AWS_PROFILE
export AWS_PAGER=""
以下の出力では、エミュレーターのアカウントID(12桁の0)を <12桁の0> に置き換えています。
エミュレーターのキーには、ポリシーが1つも付いていない
起動したときに書き出されるキーは、emulator という IAM ユーザーのものです。このユーザーには、付けたポリシーもインラインポリシーも、所属するグループもありません。
$ aws sts get-caller-identity --query Arn --output text
arn:aws:iam::<12桁の0>:user/emulator
$ aws iam list-attached-user-policies --user-name emulator
{
"AttachedPolicies": []
}
$ aws iam list-user-policies --user-name emulator
{
"PolicyNames": []
}
$ aws iam list-groups-for-user --user-name emulator
{
"Groups": []
}
それでも、S3 のバケット、DynamoDB のテーブル、IAM ユーザーを作れました。セキュリティのページにある「エミュレーター自身のキーで署名したリクエストは拒否しない」という説明のとおりです。
$ aws s3api create-bucket --bucket demo-emulator-bucket
{
"Location": "/demo-emulator-bucket",
"BucketArn": "arn:aws:s3:::demo-emulator-bucket"
}
$ aws dynamodb create-table --table-name DemoTable \
--attribute-definitions AttributeName=id,AttributeType=S \
--key-schema AttributeName=id,KeyType=HASH \
--billing-mode PAY_PER_REQUEST --query TableDescription.TableStatus
"CREATING"
$ aws iam create-user --user-name no-policy-user --query User.Arn
"arn:aws:iam::<12桁の0>:user/no-policy-user"
本物の AWS では、IAM ユーザーのページにあるとおり、新しい IAM ユーザーは初めは何の権限も持っていません。明示的な拒否と暗黙的な拒否の説明によると、当てはまる Allow も Deny もないリクエストは暗黙的に拒否されます。
ポリシーのないユーザーで呼ぶと、通る操作と拒否される操作に分かれる
次に、上で作った no-policy-user のアクセスキーを作り、そのキーで操作を呼びました。このユーザーにもポリシーは付いていません。
アクセスキーIDとシークレットアクセスキーをシェルの変数に読み込み、環境変数 AWS_ACCESS_KEY_ID と AWS_SECRET_ACCESS_KEY に入れます。エミュレーターのキーのファイルを読まないように、AWS_SHARED_CREDENTIALS_FILE は外します。
read -r AK SK < <(aws iam create-access-key --user-name no-policy-user --query 'AccessKey.[AccessKeyId,SecretAccessKey]' --output text)
unset AWS_SHARED_CREDENTIALS_FILE
export AWS_ACCESS_KEY_ID=$AK AWS_SECRET_ACCESS_KEY=$SK
コマンドのリファレンスによると、エミュレーターの IAM で作ったキーも、署名に使えます。
$ aws sts get-caller-identity --query Arn --output text
arn:aws:iam::<12桁の0>:user/no-policy-user
SQS のキューの作成、SNS のトピックの作成、Systems Manager の Parameter Store への書き込みは、どれも通りました。
$ aws sqs create-queue --queue-name demo-queue
{
"QueueUrl": "https://sqs.us-east-1.amazonaws.com/<12桁の0>/demo-queue"
}
$ aws sns create-topic --name demo-topic
{
"TopicArn": "arn:aws:sns:us-east-1:<12桁の0>:demo-topic"
}
$ aws ssm put-parameter --name /demo/param --value hello --type String
{
"Version": 1,
"Tier": "Standard"
}
一方、DynamoDB の項目の書き込みは拒否されました。メッセージの形は、IAM のアクセス拒否のトラブルシューティングに載っている、暗黙的な拒否のときの文言(because no identity-based policy allows ...)と同じです。
$ aws dynamodb put-item --table-name DemoTable --item '{"id":{"S":"cat-1"}}'
aws: [ERROR]: An error occurred (AccessDeniedException) when calling the PutItem operation: User: arn:aws:iam::<12桁の0>:user/no-policy-user is not authorized to perform: dynamodb:PutItem on resource: arn:aws:dynamodb:us-east-1:<12桁の0>:table/DemoTable because no identity-based policy allows the dynamodb:PutItem action
同じ S3 でも、バケットの一覧は取れて、バケットの作成は拒否されました。
$ aws s3api list-buckets --query 'Buckets[].Name'
[
"demo-emulator-bucket"
]
$ aws s3api create-bucket --bucket demo-no-policy-bucket
aws: [ERROR]: An error occurred (AccessDenied) when calling the CreateBucket operation: User: arn:aws:iam::<12桁の0>:user/no-policy-user is not authorized to perform: s3:CreateBucket on resource: "arn:aws:s3:::demo-no-policy-bucket" because no identity-based policy allows the s3:CreateBucket action
このユーザーで呼んだ結果をまとめると、次のとおりです。本物の AWS では、上で引いた IAM の公式ドキュメントによれば、どれも暗黙的に拒否されます。
| 操作 | AWS Emulator 1.0.353 での結果 |
|---|---|
SQS CreateQueue |
通った |
SNS CreateTopic |
通った |
Systems Manager PutParameter |
通った |
S3 ListBuckets |
通った |
S3 CreateBucket |
拒否(AccessDenied) |
DynamoDB PutItem、GetItem |
拒否(AccessDeniedException) |
IAM CreateUser |
拒否(AccessDenied) |
KMS CreateKey |
拒否(AccessDeniedException) |
Secrets Manager CreateSecret |
拒否(AccessDeniedException) |
すべてを拒否するポリシーを付けても、通る操作がある
次に、no-policy-user に AWS 管理ポリシーの AdministratorAccess を付け、さらに、すべての操作を拒否するインラインポリシーを付けました。
$ cat deny-all.json
{"Version":"2012-10-17","Statement":[{"Effect":"Deny","Action":"*","Resource":"*"}]}
$ aws iam attach-user-policy --user-name no-policy-user --policy-arn arn:aws:iam::aws:policy/AdministratorAccess
$ aws iam put-user-policy --user-name no-policy-user --policy-name DenyAll --policy-document file://deny-all.json
ポリシーの評価の流れの説明によれば、明示的な拒否は許可より優先されます。本物の AWS では、このユーザーの操作はすべて拒否されることになります。エミュレーターでは、SQS のキューの作成と、Parameter Store の読み出しが通りました。
$ aws sqs create-queue --queue-name demo-queue-2
{
"QueueUrl": "https://sqs.us-east-1.amazonaws.com/<12桁の0>/demo-queue-2"
}
$ aws ssm get-parameter --name /demo/param --query Parameter.Value --output text
hello
同じ SQS でも、キューの削除は拒否されました。メッセージには、明示的な拒否を表す with an explicit deny in an identity-based policy が入っています。同じサービスの中でも、操作によって結果が違いました。
$ aws sqs delete-queue --queue-url https://sqs.us-east-1.amazonaws.com/<12桁の0>/demo-queue
aws: [ERROR]: An error occurred (AccessDenied) when calling the DeleteQueue operation: User: arn:aws:iam::<12桁の0>:user/no-policy-user is not authorized to perform: sqs:deletequeue on resource: arn:aws:sqs:us-east-1:<12桁の0>:demo-queue with an explicit deny in an identity-based policy
DynamoDB の DeleteItem、S3 の CreateBucket、IAM の CreateUser も、同じく明示的な拒否のメッセージで拒否されました。
エミュレーターのキーに拒否のポリシーを付けた場合
同じ拒否のポリシーを、エミュレーターのキーの emulator ユーザーに付けて試しました。SQS のキューの作成と IAM ユーザーの作成は通り、S3 のバケットの作成は拒否されました。
$ aws iam put-user-policy --user-name emulator --policy-name DenyAll --policy-document file://deny-all.json
$ aws sqs create-queue --queue-name demo-queue-3
{
"QueueUrl": "https://sqs.us-east-1.amazonaws.com/<12桁の0>/demo-queue-3"
}
$ aws iam create-user --user-name made-by-emulator-after-deny --query User.Arn
"arn:aws:iam::<12桁の0>:user/made-by-emulator-after-deny"
$ aws s3api create-bucket --bucket demo-emulator-deny-bucket
aws: [ERROR]: An error occurred (AccessDenied) when calling the CreateBucket operation: User: arn:aws:iam::<12桁の0>:user/emulator is not authorized to perform: s3:CreateBucket on resource: "arn:aws:s3:::demo-emulator-deny-bucket" with an explicit deny in an identity-based policy
セキュリティのページには「エミュレーター自身のキーで署名したリクエストは拒否しない」とありますが、1.0.353 の S3 では、明示的な拒否のポリシーを付けると拒否されました。
S3 のバケットポリシーも試しました。emulator ユーザーから DenyAll を外し、すべてを拒否するバケットポリシーを付ける前と後で、オブジェクトを書き込みます。セキュリティのページには「S3 のバケットポリシーは確かめない」とありますが、ポリシーを付けた後の PutObject は拒否されました。
$ aws iam delete-user-policy --user-name emulator --policy-name DenyAll
$ aws s3api put-object --bucket demo-emulator-bucket --key before.txt --body hello.txt --query ETag
"\"b1946ac92492d2347c6235b4d2611184\""
$ aws s3api put-bucket-policy --bucket demo-emulator-bucket --policy file://bucket-deny.json
$ aws s3api put-object --bucket demo-emulator-bucket --key after.txt --body hello.txt
aws: [ERROR]: An error occurred (AccessDenied) when calling the PutObject operation: User: arn:aws:iam::<12桁の0>:user/emulator is not authorized to perform: s3:PutObject on resource: "arn:aws:s3:::demo-emulator-bucket/after.txt" with an explicit deny in a resource-based policy
bucket-deny.json は、Principal を *、Action を s3:* にした Deny の文1つだけのバケットポリシーです。公式ドキュメントによると、AWS Emulator は1日に何度も更新されます。ここに載せた結果は、1.0.353 で試したときのものです。
AccessDenied が出るかどうかを、テストで当てにしない
ここまでの結果から、エミュレーターで AccessDenied が出ても、出なくても、本物の AWS で同じになるとは言えません。拒否されるべき操作が通る例(SQS、SNS、Parameter Store)も、AWS と同じ形式のメッセージで拒否される例(S3、DynamoDB、IAM、KMS、Secrets Manager)も、同じ1つのエミュレーターの中にあります。
エミュレーターでテストが通っても、IAM の権限が正しいことにはなりません。公式のセキュリティのページも、IAM のポリシー、権限の境界、バケットポリシー、KMS のキーポリシーなどのテストには使わず、本番の前に本物の AWS で確かめるように求めています。





