一部のリソースベースポリシーではSidが必須になります
【9サービス徹底検証】

はじめに

CloudFormationでSNSトピックポリシーをデプロイしようとしたところ、以下のように怒られました。

Every policy statement must have a unique ID

怒られたトピックポリシーは以下の通りです。どうやら複数のステートメントがあるのにSidを設定していないことで怒られていた模様。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      PolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              AWS: "*"
            Action:
              - SNS:GetTopicAttributes
              - SNS:SetTopicAttributes
              - SNS:AddPermission
              - SNS:RemovePermission
              - SNS:DeleteTopic
              - SNS:Subscribe
              - SNS:ListSubscriptionsByTopic
              - SNS:Publish
            Resource: !Ref HealthSnsTopic
            Condition:
              StringEquals:
                AWS:SourceOwner: !Sub ${AWS::AccountId}
          - Effect: Allow
            Principal:
              Service: events.amazonaws.com
            Action: SNS:Publish
            Resource: !Ref HealthSnsTopic
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Sidを設定するとエラーは解消されました。


めでたしめでたし......あれ、Sidってオプションじゃなかったっけ?

目次

  1. 公式ドキュメントを確認してみる
  2. 検証1:ステートメント数を調整して再確認
  3. 検証2:SQSでも確認
  4. 検証3:他のリソースベースポリシーも調べてみた
  5. 検証結果
  6. まとめ
  7. 参考リンク

公式ドキュメントを確認してみる

まず、SNSの公式ドキュメントを確認しましたがSidが必須である旨の記載は見つかりませんでした。

IAMドキュメントを確認してみると、

IAM JSON policy elements: Sid

You can provide a Sid (statement ID) as an optional identifier for the policy statement.

と、やっぱり「optional」とあります。

しかし、よくよく読み進めてみると下の方に、

Some AWS services (for example, Amazon SQS or Amazon SNS) might require this element and have uniqueness requirements for it. For service-specific information about writing policies, refer to the documentation for the service you work with.

「SNSやSQSでは必須の場合がある」と記載がありました。具体的にどういう条件で必須になるのかは明記されていません。

検証1:ステートメント数を調整して再確認

元々「単一ステートメント・Sidなし」でデプロイして成功していたものにステートメントを追加しようとしたところでエラーが発生していたため、ステートメント数を調整してSNSトピックポリシーが作成できるか確認しました。


★検証を効率化するためにKiro CLIを活用させてもらっています。


単一ステートメントの場合

# トピック作成
aws sns create-topic --name test-multi-statement-topic --region ap-northeast-1

# 単一ステートメント(Sidなし)
aws sns set-topic-attributes \
  --topic-arn arn:aws:sns:ap-northeast-1:123456789012:test-multi-statement-topic \
  --attribute-name Policy \
  --attribute-value '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"s3.amazonaws.com"},"Action":"SNS:Publish","Resource":"arn:aws:sns:ap-northeast-1:123456789012:test-multi-statement-topic"}]}' \
  --region ap-northeast-1

結果:成功


複数ステートメントの場合

# 複数ステートメント(Sidなし)
aws sns set-topic-attributes \
  --topic-arn arn:aws:sns:ap-northeast-1:123456789012:test-multi-statement-topic \
  --attribute-name Policy \
  --attribute-value '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"s3.amazonaws.com"},"Action":"SNS:Publish","Resource":"arn:aws:sns:ap-northeast-1:123456789012:test-multi-statement-topic"},{"Effect":"Allow","Principal":{"Service":"lambda.amazonaws.com"},"Action":"SNS:Subscribe","Resource":"arn:aws:sns:ap-northeast-1:123456789012:test-multi-statement-topic"}]}' \
  --region ap-northeast-1

結果:失敗

An error occurred (InvalidParameter) when calling the SetTopicAttributes operation: Invalid parameter: Every policy statement must have a unique ID

どうやらポリシードキュメント内に複数ステートメントを含む場合のみSidが必須になるようです。

検証2:SQSでも確認

ドキュメントには「SQSやSNS」と並べて書かれていたため、SNSと同様のエラーがSQS作成時にも発生するのか検証しました。


AWS CLIで検証

まず、SQSキューを作成し、複数のステートメントを持つポリシーをSidなしで設定してみます。

# キュー作成
aws sqs create-queue --queue-name test-multi-statement-queue --region ap-northeast-1

# 複数ステートメント(Sidなし)のポリシーを設定
aws sqs set-queue-attributes \
  --queue-url https://sqs.ap-northeast-1.amazonaws.com/123456789012/test-multi-statement-queue \
  --attributes Policy='{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"sns.amazonaws.com"},"Action":"SQS:SendMessage","Resource":"arn:aws:sqs:ap-northeast-1:123456789012:test-multi-statement-queue"},{"Effect":"Allow","Principal":{"Service":"s3.amazonaws.com"},"Action":"SQS:SendMessage","Resource":"arn:aws:sqs:ap-northeast-1:123456789012:test-multi-statement-queue"}]}' \
  --region ap-northeast-1

結果:成功

SQSは複数ステートメントでもSidなしで正常に動作しました。


CloudFormationでも確認

念のためCloudFormationでも試してみました。

AWSTemplateFormatVersion: '2010-09-09'
Resources:
  TestQueue:
    Type: AWS::SQS::Queue
    Properties:
      QueueName: test-cfn-multi-statement-queue

  TestQueuePolicy:
    Type: AWS::SQS::QueuePolicy
    Properties:
      Queues:
        - !Ref TestQueue
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: sns.amazonaws.com
            Action: SQS:SendMessage
            Resource: !GetAtt TestQueue.Arn
          - Effect: Allow
            Principal:
              Service: s3.amazonaws.com
            Action: SQS:SendMessage
            Resource: !GetAtt TestQueue.Arn

結果:CREATE_COMPLETE

CloudFormationでもSidなしで正常にデプロイすることができました。てっきりSQSもSNSと同条件でSidが必須になるものと思っていたため意外です。

検証3:他のリソースベースポリシーも調べてみた

興味が湧いたのでその他のAWSサービスのリソースベースポリシーでも調べてみることにしました。


検証対象サービス

以下のサービスで、複数ステートメント + Sidなしのポリシーが設定できるか検証しました:

  1. S3(バケットポリシー)
  2. SQS(キューポリシー)
  3. SNS(トピックポリシー)
  4. Secrets Manager(シークレットポリシー)
  5. KMS(キーポリシー)
  6. ECR(リポジトリポリシー)
  7. EventBridge(イベントバスポリシー)
  8. API Gateway(リソースポリシー)
  9. Lambda(関数ポリシー)

検証コマンド例

S3バケットポリシー

aws s3api create-bucket \
  --bucket test-sid-validation \
  --create-bucket-configuration LocationConstraint=ap-northeast-1 \
  --region ap-northeast-1

aws s3api put-bucket-policy \
  --bucket test-sid-validation \
  --policy '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":"arn:aws:iam::123456789012:root"},"Action":"s3:GetObject","Resource":"arn:aws:s3:::test-sid-validation/*"},{"Effect":"Allow","Principal":{"AWS":"arn:aws:iam::123456789012:root"},"Action":"s3:ListBucket","Resource":"arn:aws:s3:::test-sid-validation"}]}' \
  --region ap-northeast-1

結果:成功


Secrets Managerシークレットポリシー

aws secretsmanager create-secret \
  --name test-sid-validation-secret \
  --secret-string "test-value" \
  --region ap-northeast-1

aws secretsmanager put-resource-policy \
  --secret-id test-sid-validation-secret \
  --resource-policy '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":"arn:aws:iam::123456789012:root"},"Action":"secretsmanager:GetSecretValue","Resource":"*"},{"Effect":"Allow","Principal":{"AWS":"arn:aws:iam::123456789012:root"},"Action":"secretsmanager:DescribeSecret","Resource":"*"}]}' \
  --region ap-northeast-1

結果:成功


KMSキーポリシー

aws kms create-key \
  --description "Test key for Sid validation" \
  --region ap-northeast-1

aws kms put-key-policy \
  --key-id <key-id> \
  --policy-name default \
  --policy '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":"arn:aws:iam::123456789012:root"},"Action":"kms:*","Resource":"*"},{"Effect":"Allow","Principal":{"AWS":"arn:aws:iam::123456789012:root"},"Action":"kms:Decrypt","Resource":"*"}]}' \
  --region ap-northeast-1

結果:成功


ECRリポジトリポリシー

aws ecr create-repository \
  --repository-name test-sid-validation-repo \
  --region ap-northeast-1

aws ecr set-repository-policy \
  --repository-name test-sid-validation-repo \
  --policy-text '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":"arn:aws:iam::123456789012:root"},"Action":"ecr:GetDownloadUrlForLayer"},{"Effect":"Allow","Principal":{"AWS":"arn:aws:iam::123456789012:root"},"Action":"ecr:BatchGetImage"}]}' \
  --region ap-northeast-1

結果:成功


EventBridgeイベントバスポリシー

aws events create-event-bus \
  --name test-sid-validation-bus \
  --region ap-northeast-1

aws events put-permission \
  --event-bus-name test-sid-validation-bus \
  --policy '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":"arn:aws:iam::123456789012:root"},"Action":"events:PutEvents","Resource":"arn:aws:events:ap-northeast-1:123456789012:event-bus/test-sid-validation-bus"},{"Effect":"Allow","Principal":{"AWS":"arn:aws:iam::123456789012:root"},"Action":"events:PutRule","Resource":"arn:aws:events:ap-northeast-1:123456789012:event-bus/test-sid-validation-bus"}]}' \
  --region ap-northeast-1

結果:エラー

An error occurred (ValidationException) when calling the PutPermission operation: Missing required field Sid

EventBridgeのput-permissionコマンドは、StatementIdパラメータが必須のようです。


API Gatewayリソースポリシー

aws apigateway create-rest-api \
  --name test-sid-validation-api \
  --region ap-northeast-1

aws apigateway update-rest-api \
  --rest-api-id <api-id> \
  --patch-operations op=replace,path=/policy,value='{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":"*","Action":"execute-api:Invoke","Resource":"*"},{"Effect":"Deny","Principal":"*","Action":"execute-api:Invoke","Resource":"*","Condition":{"NotIpAddress":{"aws:SourceIp":"203.0.113.0/24"}}}]}' \
  --region ap-northeast-1

結果:成功


Lambda関数ポリシー

aws lambda add-permission \
  --function-name test-sid-validation-func \
  --statement-id Statement1 \
  --action lambda:InvokeFunction \
  --principal s3.amazonaws.com \
  --region ap-northeast-1

aws lambda add-permission \
  --function-name test-sid-validation-func \
  --statement-id Statement2 \
  --action lambda:InvokeFunction \
  --principal sns.amazonaws.com \
  --region ap-northeast-1

Lambdaのadd-permissionコマンドもEvent Bridgeと同様に--statement-idパラメータが必須のようです。

検証結果

サービス 複数ステートメント + Sidなし Sid必須の理由
S3 ✅ 成功 -
SQS ✅ 成功 -
SNS ❌ 失敗 ポリシードキュメント検証で複数ステートメント時に必須
Secrets Manager ✅ 成功 -
KMS ✅ 成功 -
ECR ✅ 成功 -
EventBridge ❌ 失敗 APIコマンド仕様put-permissionStatementIdパラメータが必須)
API Gateway ✅ 成功 -
Lambda ❌ 失敗 APIコマンド仕様add-permissionStatementIdパラメータが必須)

Sid必須のパターン分類

検証の結果、3つのサービスのリソースベースポリシーでSidが必須となる(場合がある)ことが分かりました。また、一口にSid必須といっても種類があります。

1. ポリシードキュメントレベルの検証:SNSのみ

2. APIの仕様:EventBridge、Lambda

SNSは単一ステートメントのポリシーであればポリシードキュメントレベルの検証をクリアできますが、EventBridgeとLambdaはAPIの仕様としてStatementIdパラメータが必須であるため、ステートメント数に関わらずSidが必須になります。

APIの仕様なのでコンソールから設定しようとした場合でも同様です。


①EventBridgeバスポリシー

EventBridgeパスポリシー設定失敗.png

②Lambdaアクセス許可

Lambdaアクセス許可設定失敗.png

まとめ

①ポリシーステートメントのSidは常に設定しましょう!!

リソースベースポリシーにおいてSidの設定が必須になるパターンを確認しましたが、そもそも毎回設定しているならこんなこと気にする必要はありません。Sidがあるとポリシードキュメントの可読性が上がり、保守もしやすくなります。めんどくさがらず毎回設定するのがよいでしょう。


②Kiro CLIはAWSの実際の仕様を検証するのに便利

今回の検証ではKiro CLIが非常に役立ちました。気になる仕様について「ちょっと確かめてみて」と自然言語で依頼しただけで、実際にリソースを作って検証~情報の整理~クリーンアップまで爆速でやってくれました。「これって本当にそうなのかな?」「ほかのパターンではどうなんだろう?」を簡単に解決できるのはKiro CLIの強みだと思いました。

参考リンク

IAM JSON policy elements: Sid - AWS Documentation

Example cases for Amazon SNS access control - AWS Documentation

Basic examples of Amazon SQS policies - AWS Documentation

AWS policy application failure for a topic with strange error - Stack Overflow

CLI - Kiro


この記事は2025年11月27日時点の情報に基づいています。

クラウド基盤ソリューション