在为 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),并且此主题策略必须在订阅前已存在。

尝试下列策略之一:

在 CloudFormation 模板中为 BucketName 指定值

通过在 CloudFormation 模板中为 S3 存储桶资源内的 BucketName 参数指定一个值,对 S3 存储桶使用静态名称。这使得不再需要在 SNS 主题策略中包括 { "Ref": "S3bucket" },并删除了 SNS 主题策略和 Amazon S3 之间的固有依赖关系。要促进模板重复使用,S3 存储桶名称可设置为参数并在堆栈创建期间传递。

在模板中为 BucketName 参数指定一个值,如以下示例中所示:

{
  "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 的 DependsOn 显式设置为 SNSTopicPolicy。这确认已在开始存储桶创建之前启用必需权限。

创建堆栈,然后执行堆栈更新

将堆栈创建分为两个阶段。首先,创建堆栈,但不在 S3 存储桶资源中指定 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"
                    }
                ]
            }
        }
    }
  }
}

有关更多信息,请参阅使用堆栈(位于 AWS CloudFormation 用户指南中)。

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


此页面对您有帮助吗? |

返回 AWS Support 知识中心

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

发布时间:2016 年 9 月 15 日

更新时间:2018 年 7 月 23 日