如何修正 CloudFormation 中的「無法驗證下列目的地組態」錯誤?

6 分的閱讀內容
0

我訂閱 AWS 服務,並在 AWS CloudFormation 中收到「無法驗證下列目的地組態」錯誤。

解決方法

若要解決「無法驗證」錯誤,請針對您的組態執行疑難排解動作。

**注意:**如果您在執行 AWS Command Line Interface (AWS CLI) 命令時收到錯誤,則請參閱對 AWS CLI 進行錯誤疑難排解。此外,請確定您使用的是最新的 AWS CLI 版本

Lambda 通知組態的問題

Lambda 函數 ARN 不存在或無效

如果您的 Amazon Simple Storage Service (Amazon S3) 儲存貯體使用 AWS Lambda 屬性 LambdaConfigurations,您可能會收到「Lambda 函數不存在」錯誤。如果 CloudFormation 範本中為 Lambda 函數設定的 ARN 不存在或無效,則會發生此錯誤。

若要檢查 Lambda 函數是否存在,請執行 get-function 命令:

aws lambda get-function
--function-name YOUR-FUNCTION-ARN-VALUE

**注意:**將 YOUR-FUNCTION-ARN-VALUE 取代為函數的 ARN。

如果您在命令輸出中收到錯誤,則函數的 ARN 無效或不存在。請更新範本以包含正確的 ARN。然後,使用更新的範本建立新堆疊,或更新現有堆疊

Lambda 函數沒有調用 Amazon S3 的權限

如果您收到「請求的資源不存在」錯誤,則表示您的 Lambda 函數缺少必要的權限。若要解決此問題,請完成下列步驟:

  1. 若要檢查 Lambda 函數權限,請執行 get-policy 命令:
    aws lambda get-policy
    --function-name YOUR-FUNCTION-ARN-VALUE
    --region YOUR-REGION
    **注意:**將 FUNCTION-ARN-VALUE 取代為函數的 ARN,並且將 YOUR-REGION 取代為您的 AWS 區域。
  2. 若要允許 Lambda 函數調用 Amazon S3,請更新 CloudFormation 範本以附加下列權限:
    S3Permission:    
      Type: AWS::Lambda::Permission
      Properties:
        FunctionName: YOUR-FUNCTION-ARN-VALUE
        Action: lambda:InvokeFunction
        Principal: s3.amazonaws.com
        SourceAccount: !Ref 'AWS::AccountId'
    **注意:**將 FUNCTION-ARN-VALUE 取代為函數的 ARN,並且將 AccountID 取代為擁有該函數的 AWS 帳戶。您可以使用 AWS::AccountId 虛擬參數來自動取代 CloudFormation 在其中建立堆疊的帳戶 ID。
  3. 若要確保 CloudFormation 僅在 Lambda 函數擁有所需權限之後才建立 S3 儲存貯體,請新增 DependSon 屬性:
    S3Bucket:    
      Type: AWS::S3::Bucket
      DependsOn: "S3Permission"
      Properties:
        NotificationConfiguration:
          LambdaConfigurations:
            - Function: YOUR-FUNCTION-ARN-VALUE
                Event: "s3:ObjectCreated:Put"
    
    **注意:**將 FUNCTION-ARN-VALUE 取代為函數的 ARN。

Amazon SNS 通知組態的問題

**Amazon SNS ARN 不存在或無效 **

如果您的 S3 儲存貯體使用 TopicConfigurations 屬性,則可能會收到「無法驗證下列目的地組態」錯誤。當 Amazon Simple Notification Service (Amazon SNS) 主題不存在或無效時,就會發生此錯誤。ARN 格式和值必須與 SNS 主題的 ARN 相符。

若要檢查您的帳戶中是否存在 SNS 主題的 ARN,請執行 list-topics 命令:

aws sns list-topics \
--region YOUR-REGION \
--query "Topics[?TopicArn=='YOUR-TOPIC-ARN-VALUE']"

**注意:**將 YOUR-REGION 取代為您的區域,並且將 YOUR-TOPIC-ARN-VALUE 取代為主題的 ARN。

如果您在命令輸出中沒有收到任何記錄,則 SNS 主題不存在或無效。若要解決此問題,請建立 SNS 主題。請確定您在 TopicConfigurations 屬性中提供有效的主題 ARN。

SNS 主題沒有必要的存取政策

若要驗證 SNS 主題具有必要的存取政策,請完成下列步驟:

  1. 若要檢查附加至 SNS 主題的存取政策,請執行get-topic-attributes 命令:
    aws sns get-topic-attributes \
    --topic-arn YOUR-TOPIC-ARN-VALUE \
    --region YOUR-REGION \
    --query 'Attributes.Policy'
    **注意:**將 YOUR-TOPIC-ARN-VALUE 取代為您的主題 ARN,並且將 YOUR-REGION 取代為您的區域。
  2. 存取政策必須允許 Amazon S3 服務發佈至主題。如果政策沒有這些權限,請編輯主題的存取政策,以包含下列權限:
    {     
          "Sid": "S3AccessForNotification",      
          "Effect": "Allow",
          "Principal": {
            "Service": "s3.amazonaws.com"
          },
          "Action": "SNS:Publish",
          "Resource": "YOUR-TOPIC-ARN-VALUE"
    }
    **注意:**將 YOUR-TOPIC-ARN-VALUE 取代為您的主題 ARN。
  3. 確認您現在可以建立新堆疊,或更新現有堆疊

與 SNS 主題相關聯AWS KMS key 政策問題

AWS Key Management Service (KMS) 政策必須允許 Amazon S3 存取 AWS KMS key。若要檢視加密組態和最低的必要政策,請完成下列步驟:

若要檢查 SNS 主題是否使用 AWS KMS key 加密,請執行 get-topic-attributes 命令:

aws sns get-topic-attributes \
--topic-arn YOUR-TOPIC-ARN-VALUE \
--region YOUR-REGION \
--query "Attributes.KmsMasterKeyId"

**注意:**將 YOUR-TOPIC-ARN-VALUE 取代為您的主題 ARN,並且將 YOUR-REGION 取代為您的區域。如果 SNS 主題已加密,則命令的輸出會顯示 AWS KMS key ARN。

若要檢查 AWS KMS key 政策,請執行 get-key-policy 命令:

aws kms get-key-policy \
--key-id YOUR-KMS-KEY-ARN \
--policy-name default \
--region YOUR-REGION | jq -r '.Policy' | jq .

**注意:**將 YOUR-KMS-KEY-ARN 取代為您的 AWS KMS key ARN,並且將 YOUR-REGION 取代為您的區域。為獲得更佳的可讀性,最佳做法是使用 jq 命令,以 JSON 格式顯示政策內容。如需詳細資訊,請參閱 jq 網站上的 ./jq

下列範例政策顯示最低的必要 AWS KMS key 政策:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "s3.amazonaws.com"
            },
            "Action": ["kms:GenerateDataKey*", "kms:Decrypt"],
            "Resource": "YOUR-KMS-KEY-ARN"
        }
    ]
}

**注意:**將 YOUR-KMS-KEY-ARN 取代為 AWS KMS key 的 ARN。

如果您的政策沒有必要的權限,請更新 AWS KMS key 政策

Amazon SQS 通知組態的問題

Amazon SQS ARN 不存在或無效

如果您的 S3 儲存貯體使用 QueueConfigurations 屬性,則您可能會收到「SQS 佇列不存在」錯誤。當 Amazon Simple Queue Service (Amazon SQS) ARN 不存在或無效時,就會發生此錯誤。

若要檢查帳戶中是否存在 Amazon SQS 佇列,請執行 list-queues 命令:

aws sqs list-queues
--queue-name-prefix YOUR-SQS-QUEUE-NAME
--region YOUR-REGION

**注意:**將 YOUR-SQS-QUEUE-NAME 取代為您的 SQS 佇列名稱,並且將 YOUR-REGION 取代為您的區域。

如果 SQS 佇列不存在,則請建立新佇列,或使用現有佇列更新範本:

Resources:
  SNSTopic:
    Type: AWS::SNS::Topic
  SNSTopicPolicy:
    Type: AWS::SNS::TopicPolicy
    Properties:
      PolicyDocument:
        Id: MyTopicPolicy
        Version: '2012-10-17'
        Statement:
          - Sid: Statement-id
            Effect: Allow
            Principal:
              Service: s3.amazonaws.com
            Action: "SNS:Publish"
            Resource: !Ref SNSTopic
            Condition:
              ArnLike:
                aws:SourceArn: !Join
                  - ''
                  - - 'arn:aws:s3:::'
                    - !Ref S3Bucket
      Topics:
        - !Ref SNSTopic
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      AccessControl: BucketOwnerFullControl

SQS 佇列沒有必要的存取政策

若要驗證 SQS 佇列是否具有必要的存取政策,您可以使用 AWS CLI 或 CloudFormation 主控台。

若要使用 AWS CLI 驗證佇列的存取政策,請完成下列步驟:

  1. 若要檢查 SQS 佇列政策,請執行 get-queue-attributes 命令:
    aws sqs get-queue-attributes \
    --queue-url YOUR-SQS-QUEUE-URL \
    --region YOUR-REGION \
    --attribute-names Policy | jq .
    **注意:**將 YOUR-SQS-QUEUE-NAME 取代為您的 SQS 佇列名稱,並且將 YOUR-REGION 取代為您的區域,然後將 YOUR-SQS-QUEUE-URL 取代為您的佇列網址。為獲得更佳的可讀性,最佳做法是使用 jq 命令,以 JSON 格式顯示政策內容。如需詳細資訊,請參閱 jq 網站上的 ./jq
  2. 如果您的政策無法存取 Amazon S3,請在 JSON 檔案中建立新的存取政策:
    {"Policy": "{\"Version\":\"2012-10-17\",\"Statement\":
    [{\"Sid\":\"S3AccessForNotification\",\"Effect\":\"Allow\",\"Principal\":
    {\"Service\":\"s3.amazonaws.com\"},\"Action\":\"SQS:SendMessage\",\"Resource\":\"YOUR-SQS-QUEUE-ARN\"}]}"}
    **注意:**將 YOUR-SQS-QUEUE-ARN 取代為佇列 ARN。
  3. 若要更新策略,請執行 set-queue-attributes 命令:
    aws sqs set-queue-attributes
    --queue-url YOUR-SQS-QUEUE-URL
    --attributes file://sqs-policy.json
    **注意:**將 YOUR-SQS-QUEUE-URL 取代為您的佇列網址,並且將 sqs-policy.json 取代為您的政策 JSON 檔案。

若要使用 CloudFormation 主控台來驗證佇列的存取政策,請更新 CloudFormation 範本,以包含下列資源:

SampleSQSPolicy:
  Type: AWS::SQS::QueuePolicy
  Properties:
    Queues:
      - YOUR-SQS-QUEUE-URL
    PolicyDocument:
      Statement:
        -
          Action:
            - "SQS:SendMessage"
          Effect: "Allow"
          Resource: YOUR-SQS-QUEUE-ARN
          Principal:  
            Service:
              - "s3.amazonaws.com"

**注意:**將 YOUR-SQS-QUEUE-URL 取代為您的佇列網址,並且將 YOUR-SQS-QUEUE-ARN 取代為您的佇列 ARN。

建立或更新政策之後,請確認您現在可以建立新堆疊,或更新現有堆疊

如需詳細資訊,請參閱我需要哪些權限才能存取 Amazon SQS 佇列?如果仍然遇到問題,請參閱如何疑難排解「參數政策無效值」Amazon SQS 錯誤?

與 SQS 佇列相關聯的 AWS KMS key 政策的問題

若要解決 AWS KMS key 政策的問題,請完成下列步驟:

  1. 若要取得 SQS 佇列網址,請執行 list-queues 命令:
    aws sqs list-queues
    --queue-name-prefix YOUR-SQS-QUEUE-NAME
    --region YOUR-REGION
    **注意:**將 YOUR-SQS-QUEUE-NAME 取代為您的 SQS 佇列名稱,並且將 YOUR-REGION 取代為您的區域。
  2. 若要取得 AWS KMS key ID,請執行 get-queue-attributes 命令:
    aws sqs get-queue-attributes \
    --queue-url YOUR-SQS-QUEUE-URL \
    --region YOUR-REGION \
    --attribute-names KmsMasterKeyId
    **注意:**將 YOUR-SQS-QUEUE-URL 取代為您的佇列網址,並且將 YOUR-REGION 取代為您區域。
  3. 若要取得 AWS KMS key ARN,請執行 describe-key 命令:
    aws kms describe-key --key-id YOUR-KMS-KEY-ID
    **注意:**將 YOUR-KMS-KEY-ID 取代為金鑰 ID。
  4. 若要檢視完整金鑰政策,請執行 get-key-policy 命令:
    aws kms get-key-policy \
    --key-id YOUR-KMS-KEY-ARN \
    --policy-name default \
    --region YOUR-REGION
    **注意:**將 YOUR-KMS-KEY-ARN 取代為您的 AWS KMS key ARN,並且將 YOUR-REGION 取代為您的區域。
  5. 在輸出中,確認政策是否允許 Amazon S3 使用 AWS KMS key。範例權限:
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Principal": {
                    "Service": "s3.amazonaws.com"
                },
                "Action": ["kms:GenerateDataKey*", "kms:Decrypt"],
                "Resource": "YOUR-KMS-KEY-ARN"
            }
        ]
    }
    **注意:**將 YOUR-KMS-KEY-ARN 取代為 AWS KMS key 的 ARN。

如果您的策略沒有必要的權限,請更新金鑰政策

資源之間的循環相依性

**重要:**在訂閱 S3 事件通知的 SNS 主題之前,您必須使用必要的權限來建立 AWS::SNS::TopicPolicy。在建立訂閱之前,必須存在該主題政策。

若要先建立主題政策,您必須在 AWS::S3::Bucket 資源上使用 DependsOn 屬性。此屬性會在儲存貯體之前建立主題政策。或者,您可以使用兩個堆疊作業來先行建立所有資源,然後更新 S3Bucket 資源,以包括 NotificationConfiguration 屬性。請採取下列其中一個動作。

在 CloudFormation 範本中指定 BucketName 的值

在 CloudFormation 範本的 S3Bucket 資源中,為 BucketName 屬性內的 S3 儲存貯體使用靜態名稱。靜態 S3 儲存貯體會移除 SNS 主題政策與 Amazon S3 之間的內在相依性。

**重要:**S3 儲存貯體名稱必須是全域唯一名稱。

下列範例 CloudFormation 範本會指定 BucketName 屬性的硬式編碼 -Bucket-Name- 值:

Resources:
  SNSTopic:
    Type: AWS::SNS::Topic
  SNSTopicPolicy:
    Type: AWS::SNS::TopicPolicy
    Properties:
      PolicyDocument:
        Id: MyTopicPolicy
        Version: '2012-10-17'
        Statement:
          - Sid: Statement-id
            Effect: Allow
            Principal:
              Service: s3.amazonaws.com
            Action: "SNS:Publish"
            Resource: !Ref SNSTopic
            Condition:
              ArnLike:
                aws:SourceArn: !Join
                  - ''
                  - - 'arn:aws:s3:::'
                    - '-Bucket-Name-'
      Topics:
        - !Ref SNSTopic
  S3Bucket:
    Type: AWS::S3::Bucket
    DependsOn:
      - SNSTopicPolicy
    Properties:
      AccessControl: BucketOwnerFullControl
      BucketName: "-Bucket-Name-"
      NotificationConfiguration:
        TopicConfigurations:
          - Topic: !Ref SNSTopic
            Event: s3:ObjectCreated:Put

**注意:**將 -Bucket-Name- 取代為您的儲存貯體名稱。S3Bucket 資源具有設定為 SNSTopicPolicy 的明確 DependsOn 值。此屬性會指定範本在 S3Bucket 資源之前建立 SNSTopicPolicy 資源。

使用 BucketName 的參數

參數可讓您針對具有不同名稱的 S3 儲存貯體使用相同的 CloudFormation 範本。在建立堆疊期間,您可以設定 paramBucketName 參數的值。範例政策:

Parameters:
  paramBucketName:
    Type: String
    Description: Bucket Name
Resources:
  SNSTopic:
    Type: AWS::SNS::Topic
  SNSTopicPolicy:
    Type: AWS::SNS::TopicPolicy
    Properties:
      PolicyDocument:
        Id: MyTopicPolicy
        Version: '2012-10-17'
        Statement:
          - Sid: Statement-id
            Effect: Allow
            Principal:
              Service: s3.amazonaws.com
            Action: "SNS:Publish"
            Resource: !Ref SNSTopic
            Condition:
              ArnLike:
                aws:SourceArn: !Join
                  - ''
                  - - 'arn:aws:s3:::'
                    - !Ref paramBucketName
      Topics:
        - !Ref SNSTopic
  S3Bucket:
    Type: AWS::S3::Bucket
    DependsOn:
      - SNSTopicPolicy
    Properties:
      AccessControl: BucketOwnerFullControl
      BucketName: !Ref paramBucketName
      NotificationConfiguration:
        TopicConfigurations:
          - Topic: !Ref SNSTopic
            Event: s3:ObjectCreated:Put

**注意:**在先前的範例中,S3Bucket 資源具有設定為 SNSTopicPolicy 的明確 DependsOn 屬性。

建立堆疊,然後更新堆疊

**注意:**在此方法中,S3Bucket 資源不包括 BucketName 屬性。因此,CloudFormation 會為您建立一個唯一的儲存貯體名稱。為了避免出現循環相依性,請不要使用 DependsOn 屬性。

首先,請建立堆疊,但不包含 S3Bucket 資源中的 NotificationConfiguration 屬性。範例:

Resources:
  SNSTopic:
    Type: AWS::SNS::Topic
  SNSTopicPolicy:
    Type: AWS::SNS::TopicPolicy
    Properties:
      PolicyDocument:
        Id: MyTopicPolicy
        Version: '2012-10-17'
        Statement:
          - Sid: Statement-id
            Effect: Allow
            Principal:
              Service: s3.amazonaws.com
            Action: "SNS:Publish"
            Resource: !Ref SNSTopic
            Condition:
              ArnLike:
                aws:SourceArn: !Join
                  - ''
                  - - 'arn:aws:s3:::'
                    - !Ref S3Bucket
      Topics:
        - !Ref SNSTopic
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      AccessControl: BucketOwnerFullControl

S3Bucket 資源中新增 NotificationConfiguration 屬性,然後更新堆疊。範例:

Resources:
  SNSTopic:
    Type: AWS::SNS::Topic
  SNSTopicPolicy:
    Type: AWS::SNS::TopicPolicy
    Properties:
      PolicyDocument:
        Id: MyTopicPolicy
        Version: '2012-10-17'
        Statement:
          - Sid: Statement-id
            Effect: Allow
            Principal:
              Service: s3.amazonaws.com
            Action: "SNS:Publish"
            Resource: !Ref SNSTopic
            Condition:
              ArnLike:
                aws:SourceArn: !Join
                  - ''
                  - - 'arn:aws:s3:::'
                    - !Ref S3Bucket
      Topics:
        - !Ref SNSTopic
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      AccessControl: BucketOwnerFullControl
      NotificationConfiguration:
        TopicConfigurations:
          - Topic: !Ref SNSTopic
            Event: s3:ObjectCreated:Put

相關資訊

授予發佈事件通知訊息至目的地的許可

如何避免 CloudFormation 中的 Lambda 事件通知發生「無法驗證下列目的地組態」錯誤?

使用 AWS CloudFormation 堆疊將 AWS 資源作為單一單元進行管理

設定 Amazon SNS 通知

AWS 官方
AWS 官方已更新 3 個月前