在为 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 存储桶资源时建立。

因此,必须按以下顺序创建资源:
注意:此解决方法使用 Amazon SNS 主题作为示例 - 如果在使用 AWS Lambda 函数时收到错误,可使用类似解决方法。

  1. 创建 SNS 主题,因为 S3 存储桶引用 SNS 主题。
  2. 创建 S3 存储桶,因为 SNS 主题策略引用 S3 存储桶和 SNS 主题。

在为 S3 事件通知订阅 SNS 主题之前,必须指定具有相应权限的主题策略 (AWS::SNS::TopicPolicy),并且此主题策略必须在您创建订阅前已存在。

请尝试以下策略之一以避免错误“Unable to validate the following destination configurations (无法验证以下目标配置)”:

在 CloudFormation 模板中为 BucketName 指定值

通过在 CloudFormation 模板中为 S3Bucket 资源内的 BucketName 属性指定一个值,对 S3 存储桶使用静态名称。这使得不再需要在 SNS 主题策略中包括 { "Ref": "paramBucketName" },并删除了 SNS 主题策略和 Amazon S3 之间的固有依赖关系。

以下示例 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": { "AWS": "*" },
                        "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 资源的 DependsOn 值明确设置为 SNSTopicPolicy。此属性指定模板将在 S3Bucket 资源之前创建 SNSTopicPolicy 资源。

要对具有不同名称的 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": { "AWS": "*" },
                        "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 事件通知。

在第一个阶段中,创建所有资源(包括 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": { "AWS": "*" },
                            "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"
            }
        }
    }
}

然后,更新堆栈以添加 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": { "AWS": "*" },
                        "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"
                    }
                ]
            }
        }
    }
  }
}

有关更多信息,请参阅使用堆栈

注意:要使用 YAML CloudFormation 模板,请参阅在 JSON 和 YAML 格式之间转换 AWS CloudFormation 模板的工具


此页内容对您是否有帮助? |

返回 AWS Support 知识中心

需要帮助? 请访问 AWS 支持中心

发布时间:2016 年 9 月 15 日

更新时间:2018 年 11 月 2 日