IAMポリシーの権限評価は「明示的なDeny > 明示的なAllow > 暗黙的なDeny」が基本です。
別のポリシーでAllowされていても明示的なDenyがあれば操作は拒否されます。
私が扱っていた環境では、IAMユーザのMFA認証を必須にしており、
MFA未認証では、ほぼすべての操作を明示的にDenyしていました。
その環境で、IAMユーザのアクセスキーを使ってAWS CLIを利用することになりました。
MFAが必要な操作をCLIから実行するには、
AWS STSのGetSessionTokenというAPIアクションを呼び、MFA認証済みの一時認証情報を取得します。
CLIでは、次のように実行します。
aws sts get-session-token --serial-number [MFA識別子] --token-code [OTPコード]
ただ、このコマンドを呼ぶ時点では、まだMFA認証済みの一時認証情報を持っていません。
元のIAMユーザのアクセスキーを使うので、GetSessionTokenもDenyされるはずだと考えていました。
ところが、実際には一時認証情報を取得できました。
公式ドキュメントを確認する
IAMの公式ドキュメントにはGetSessionTokenについて次の説明があります。
You cannot use policies to control authentication operations.
認証操作は、ポリシーでは制御できないという説明です。
さらに、GetSessionTokenをポリシーに含めても、ユーザがこの操作を実行できるかどうかには影響しないと明記されています。
IAM公式ドキュメント:Permissions for GetSessionToken
つまり、GetSessionTokenの呼び出し自体は、IAMポリシーによる権限制御の対象外です。
呼び出しを許可するsts:GetSessionTokenのAllowも不要です。
STSは指定されたMFA情報を検証し、正しければMFA認証済みの一時認証情報を返します。
その認証情報を使った後続の操作は、MFA認証済みとして扱われます。
GetSessionTokenはIAMポリシーで呼び出しを制御できないため、冒頭の環境でも一時認証情報を取得できました。
この説明どおりなら、明示的なDenyを設定しても、GetSessionTokenの呼び出しを禁止できないはずです。
条件や例外を設けず、すべての操作をDenyするポリシーを付けて、実際に確かめます。
明示的なDenyを付けて検証する
GetSessionTokenは、IAMユーザの長期認証情報で呼ぶ必要があります。
検証用IAMユーザとアクセスキーを用意し、MFAデバイスを登録します。
そのアクセスキーをmfa-testという名前のCLIプロファイルに設定しました。
検証に使うポリシー
検証用IAMユーザに、次のインラインポリシーを設定します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": "*",
"Resource": "*"
}
]
}
条件や除外するアクションを設けず、すべての操作を明示的にDenyする内容です。
通常の操作がDenyされることを確認する
まず検証用IAMユーザでS3のバケット一覧を取得します。
aws s3 ls --profile mfa-test
An error occurred (AccessDenied) when calling the ListBuckets operation: User: arn:aws:iam::471036546540:user/mfa-test is not authorized to perform: s3:ListAllMyBuckets with an explicit deny in an identity-based policy
s3:ListAllMyBucketsは明示的なDenyで拒否されました。
GetSessionTokenを呼び出す
このポリシーを付けた状態で、検証用IAMユーザのアクセスキーを使って実行します。
aws sts get-session-token --profile mfa-test --serial-number [MFA識別子] --token-code [OTPコード]
結果
一時認証情報が返ってきました。
認証情報の値はマスクしています。
{
"Credentials": {
"AccessKeyId": "********",
"SecretAccessKey": "********",
"SessionToken": "********",
"Expiration": "2026-10-11T23:06:06+00:00"
}
}
S3の一覧取得が明示的なDenyで拒否される状態でも、GetSessionTokenでは一時認証情報を取得できました。
呼び出しをポリシーで制御できないという公式ドキュメントの説明と一致する結果です。
一時認証情報を取得できても、S3の一覧取得などは引き続き拒否されます。
取得した認証情報を使う場合も元のIAMユーザに設定したDenyが適用されるためです。
公式資料にある、ほかの例
GetSessionToken以外にも、IAMポリシーで呼び出しを制御できない操作や、特定のDenyに対する例外があります。
呼び出し元を確認するGetCallerIdentity
GetCallerIdentityは、呼び出し元のアカウントID、ARN、ユーザIDを返すSTSのAPIです。
公式ドキュメントには、sts:GetCallerIdentityを明示的にDenyするポリシーを付けても実行できると書かれています。
アクセス拒否時にも同じ呼び出し元情報が得られるため、この操作には権限を必要としないという説明です。
S3やDynamoDBのポリシーを復旧する操作
リソースのポリシーで操作を拒否してしまっても、所有アカウントのrootユーザがポリシーを修正・削除できる例もあります。
S3の汎用バケットでは、所有アカウントのrootユーザは、バケットポリシーで自身を明示的にDenyされていても、次の操作を実行できます。
GetBucketPolicyPutBucketPolicyDeleteBucketPolicy
この例外が対象とするのは、バケットポリシーによるDenyです。
VPCエンドポイントのポリシーやAWS Organizationsのポリシーでは、これらの操作を制限できます。
DynamoDBでも、リソースを所有するアカウントのrootユーザは、リソースポリシーで自身を拒否されていても、DeleteResourcePolicyでそのポリシーを削除できます。
これらは、rootユーザによる復旧に備えた、リソースポリシーのDenyに対する例外です。
まとめ
GetSessionTokenは明示的なDenyを設定していても呼び出せました。
呼び出し自体はIAMポリシーによる権限制御の対象外だったため、MFA認証前の操作を拒否する環境でも一時認証情報を取得できました。
ほかにも呼び出し元情報を返すAPIやrootユーザによるポリシーの復旧操作に、それぞれ異なる理由でDenyが適用されない例がありました。
以上、明示的なDenyを貫通するIAMアクションのおはなしでした。