如何修复 AWS CloudFormation 中出现的“Unable to validate the following destination configurations(无法验证以下目标配置)”错误?
我订阅 Amazon Simple Storage Service(Amazon S3)事件通知的 Amazon Simple Notification Service(Amazon SNS)主题或 AWS Lambda 函数。我收到以下错误:“Unable to validate the following destination configurations(无法验证以下目标配置)”。 尝试从模板中的 S3 存储桶设置与 SNS 主题策略的依赖项时,我收到循环依赖项验证错误。
简短描述
因为 AWS CloudFormation 处理依赖关系排序的方式,Amazon S3 事件通知定义为 S3 存储桶的属性。在创建 S3 存储桶资源时会建立这些通知。
要避免错误,您必须按以下顺序创建资源:
- 创建 SNS 主题,因为 S3 存储桶引用 SNS 主题。
- 创建 S3 存储桶,因为 SNS 主题策略引用 S3 存储桶和 SNS 主题。
在订阅 S3 事件通知的 SNS 主题之前,您必须使用适当的权限指定主题策略(AWS::SNS::TopicPolicy)。创建订阅之前,该主题策略必须已存在。
请尝试以下其中一个策略,以避免出现“Unable to validate the following destination configurations”错误:
- 在 AWS CloudFormation 模板中指定 BucketName 的值
- 创建堆栈,然后执行堆栈更新
解决方法
在 AWS CloudFormation 模板中指定 BucketName 的值
通过为 AWS CloudFormation 模板的 S3Bucket 资源中的 BucketName 属性指定值,来使用 S3 存储桶的静态名称。这样就不需要在 SNS 主题策略中包含 {"Ref": "paramBucketName"}。同样可避免 SNS 主题策略与 Amazon S3 之间的内在依赖项。
以下示例 AWS CloudFormation 模板指定了 BucketName 属性的硬编码值(-Bucket-Name-)。在您的模板中,将 -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": { "Fn::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" } ] } } } } }
**注意:**S3Bucket 资源具有已设置为 SNSTopicPolicy 的显式 DependsOn 值。此属性会指定模板将在 S3Bucket 资源之前创建 SNSTopicPolicy 资源。
要将相同的 AWS CloudFormation 模板用于名称不同的 S3 存储桶,请为存储桶名称定义参数。通过参数可以将相同模板用于不同的存储桶名称,方法是在堆栈创建期间以参数形式传递存储桶名称。
要使用以下示例模板,您必须在堆栈创建期间以 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": { "Fn::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 资源中指定 NotificationConfiguration 属性。然后,执行堆栈更新以添加 S3 事件通知。这样可避免在创建 SNS 主题策略之前设置 S3 事件通知。
1. 创建所有资源,包括 SNS 主题策略。例如:
{ "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": { "Fn::Join": [ "", [ "arn:aws:s3:::", { "Ref": "S3Bucket" } ] ] } } } } ] }, "Topics": [ { "Ref": "SNSTopic" } ] } }, "S3Bucket": { "Type": "AWS::S3::Bucket", "Properties": { "AccessControl": "BucketOwnerFullControl" } } } }
2. 更新堆栈以添加 S3 事件通知。例如:
{ "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": { "Fn::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" } ] } } } } }
**注意:**您可以使用 AWS CloudFormation Template Flip,在 JSON 和 YAML 格式之间转换 AWS CloudFormation 模板。
相关信息
相关内容
- AWS 官方已更新 2 年前