如何修复 CloudFormation 中的“Unable to validate the following destination configurations”(无法验证以下目标配置)错误?

7 分钟阅读
0

我订阅了 AWS 服务,但在 AWS CloudFormation 中收到“Unable to validate the following destination configurations”错误。

解决方法

要解决 Unable to validate(无法验证)错误,请对您的配置采取故障排除操作。

**注意:**如果您在运行 AWS 命令行界面 (AWS CLI) 命令时收到错误,请参阅 AWS CLI 错误故障排除。此外,请确保您使用的是最新版本的 AWS CLI

Lambda 通知配置问题

Lambda 函数 ARN 不存在或无效

如果您的 Amazon Simple Storage Service (Amazon S3) 存储桶使用 AWS Lambda 属性 LambdaConfigurations,则您可能会收到 lambda function does not exist(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 的权限

如果您收到 resource you requested does not exist(您请求的资源不存在)错误,则表示您的 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 属性,则您可能会收到 Unable to validate the following destination configurations(无法验证以下目标配置)错误。当 Amazon Simple Notification Service (Amazon SNS) 主题不存在或无效时,将会出现此错误。ARN 格式和值必须与 Amazon 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 密钥策略问题

AWS Key Management Service (AWS KMS) 策略必须允许 Amazon S3 访问 AWS KMS 密钥。要查看加密配置和所需的最低策略,请完成以下步骤:

要检查 SNS 主题是否使用 AWS KMS 密钥加密,请运行 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 密钥 ARN。

要检查 AWS KMS 密钥策略,请运行 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 密钥的 ARN,将 YOUR-REGION 替换为您的区域。为了提高可读性,最佳做法是使用 jq 命令以 JSON 格式显示策略内容。有关详细信息,请参阅 jq 网站上的 ./jq

以下示例策略显示了所需的最低要求的 AWS KMS 密钥策略:

{
    "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 密钥的 ARN。

如果您的策略没有所需的权限,请更新 AWS KMS 密钥策略

Amazon SQS 通知配置问题

Amazon SQS ARN 不存在或无效

如果您的 S3 存储桶使用 QueueConfigurations 属性,则您可能会收到 SQS queue does not exist(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 替换为您的队列 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 替换为您的队列 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 替换为您的队列 URL,将 YOUR-SQS-QUEUE-ARN 替换为您的队列 ARN。

创建或更新策略后,确认您现在可以创建新堆栈更新现有堆栈

有关详细信息,请参阅访问 Amazon SQS 队列需要什么权限?如果您仍然遇到问题,请参阅 How do I troubleshoot the Amazon SQS error "Invalid value for the parameter policy"?

与 SQS 队列相关的 AWS KMS 密钥策略问题

要解决 AWS KMS 密钥策略问题,请完成以下步骤:

  1. 要获取 SQS 队列 URL,请运行 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 密钥 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 替换为您的队列 URL,将 YOUR-REGION 替换为您的区域。
  3. 要获取 AWS KMS 密钥的 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 密钥的 ARN,将 YOUR-REGION 替换为您的区域。
  5. 在输出中,验证该策略是否允许 Amazon S3 使用 AWS KMS 密钥。权限示例:
    {
        "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 密钥的 ARN。

如果您的策略没有所需的权限,请更新密钥策略

资源之间的循环依赖项

**重要事项:**在订阅 SNS 主题接收 S3 事件通知之前,必须创建具有所需权限的 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 资源有一个明确的 DependsOn 属性,该属性设置为 SNSTopicPolicy。该属性指定模板在 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 资源有一个显式的 DependsOn 属性,该属性设置为 SNSTopicPolicy

创建堆栈,然后更新堆栈

**注意:**在此方法中,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 事件通知时出现的“Unable to validate the following destination configurations”错误?

使用 AWS CloudFormation 堆栈将 AWS 资源作为单个单元进行管理

设置 Amazon SNS 通知

AWS 官方
AWS 官方已更新 5 个月前
没有评论

相关内容