Terraform配置S3触发SNS通知报错排查求助
问题:Terraform配置S3对象创建触发SNS通知时策略报错
我正在用Terraform编写代码,实现当S3 Bucket中有对象创建时,向SNS Topic发送通知。以下是我的初始代码片段:
// 创建SNS Topic resource "aws_sns_topic" "topic" { name = "topic-name" } // 创建允许S3 Bucket发布消息的策略 data "aws_iam_policy_document" "iam_policy" { statement { effect = "Allow" actions = [ "SNS:Publish" ] resources = [ aws_sns_topic.topic.arn ] } } resource "aws_sns_topic_policy" "topic_policy" { arn = aws_sns_topic.topic.arn policy = data.aws_iam_policy_document.iam_policy.json } // S3 Bucket有对象创建时向SNS Topic发送告警 resource "aws_s3_bucket_notification" "bucket_notification" { bucket = aws_s3_bucket.s3-bucket.id topic { topic_arn = aws_sns_topic.topic.arn events = ["s3:ObjectCreated:*"] } }
执行代码时,所有基础设施均可创建,但创建策略时出现如下错误:
aws_sns_topic_policy.topic_policy: Creating... aws_sns_topic_policy.topic_policy: Still creating... [10s elapsed] aws_sns_topic_policy.topic_policy: Still creating... [20s elapsed] aws_sns_topic_policy.topic_policy: Still creating... [30s elapsed] aws_sns_topic_policy.topic_policy: Still creating... [40s elapsed] aws_sns_topic_policy.topic_policy: Still creating... [50s elapsed] aws_sns_topic_policy.topic_policy: Still creating... [1m0s elapsed] aws_sns_topic_policy.topic_policy: Still creating... [1m10s elapsed] aws_sns_topic_policy.topic_policy: Still creating... [1m20s elapsed] aws_sns_topic_policy.topic_policy: Still creating... [1m30s elapsed] aws_sns_topic_policy.topic_policy: Still creating... [1m40s elapsed] aws_sns_topic_policy.topic_policy: Still creating... [1m50s elapsed] │ Error: setting SNS Topic (arn:aws:sns:<REGION>:<ACCOUNTID>:topic-name) attribute (Policy): InvalidParameter: Invalid parameter: Policy Error: null │ status code: 400, request id: │ │ on sns.tf line 19, in resource "aws_sns_topic_policy" "topic_policy": │ 19: resource "aws_sns_topic_policy" "topic_policy" { │ ╵ ╷ │ Error: putting S3 Bucket Notification Configuration: InvalidArgument: Unable to validate the following destination configurations │ status code: 400, request id: , host id: │ │ on sns.tf line 26, in resource "aws_s3_bucket_notification" "bucket_notification": │ 26: resource "aws_s3_bucket_notification" "bucket_notification" {
我尝试了另一种SNS Topic Policy写法,但仍出现相同错误,请求协助排查:
// 创建SNS Topic resource "aws_sns_topic" "topic" { name = "topic-name" policy = <<POLICY { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "s3.amazonaws.com" }, "Action": "sns:Publish", "Resource": "${aws_sns_topic.topic.arn}", "Condition": { "ArnLike": { "aws:SourceArn": "arn:aws:s3:::${aws_s3_bucket.s3-bucket.id}" } } } ] } POLICY } // S3 Bucket有对象创建时向SNS Topic发送告警 resource "aws_s3_bucket_notification" "bucket_notification" { bucket = aws_s3_bucket.s3-bucket.id topic { topic_arn = aws_sns_topic.topic.arn events = ["s3:ObjectCreated:*"] } }
问题原因与解决方案
核心问题
初始策略缺少主体(Principal)与安全条件
第一个版本的IAM策略未指定允许执行SNS:Publish操作的主体,AWS会拒绝这种不完整的权限配置;同时也没有限制仅目标S3 Bucket能触发通知,不符合安全规范。内联策略的循环依赖
第二个写法中,在aws_sns_topic的policy属性里直接引用aws_sns_topic.topic.arn,导致Terraform出现循环依赖——Topic的ARN需要Topic创建完成,但Topic的创建又依赖ARN值生成策略。
修正方案1:使用独立的aws_sns_topic_policy资源(推荐)
这种方式逻辑清晰,避免循环依赖,同时保证权限配置完整:
// 先定义S3 Bucket(确保名称全局唯一) resource "aws_s3_bucket" "s3-bucket" { bucket = "your-unique-bucket-name" } // 创建SNS Topic resource "aws_sns_topic" "topic" { name = "topic-name" } // 生成合规的SNS Topic策略文档 data "aws_iam_policy_document" "sns_topic_policy" { statement { effect = "Allow" // 指定允许S3服务作为主体 principals { type = "Service" identifiers = ["s3.amazonaws.com"] } actions = ["sns:Publish"] resources = [aws_sns_topic.topic.arn] // 限制仅目标S3 Bucket能触发通知 condition { test = "ArnLike" variable = "aws:SourceArn" values = ["arn:aws:s3:::${aws_s3_bucket.s3-bucket.id}"] } } } // 将策略绑定到SNS Topic resource "aws_sns_topic_policy" "topic_policy" { arn = aws_sns_topic.topic.arn policy = data.aws_iam_policy_document.sns_topic_policy.json } // 配置S3 Bucket通知,依赖策略配置完成 resource "aws_s3_bucket_notification" "bucket_notification" { bucket = aws_s3_bucket.s3-bucket.id topic { topic_arn = aws_sns_topic.topic.arn events = ["s3:ObjectCreated:*"] // 可选:添加前缀/后缀过滤特定对象的通知 // filter_prefix = "uploads/" // filter_suffix = ".txt" } depends_on = [aws_sns_topic_policy.topic_policy] }
修正方案2:修复内联策略的循环依赖
如果偏好使用内联策略,可通过self.arn引用当前Topic的ARN,避免循环依赖:
resource "aws_s3_bucket" "s3-bucket" { bucket = "your-unique-bucket-name" } resource "aws_sns_topic" "topic" { name = "topic-name" policy = <<POLICY { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "s3.amazonaws.com" }, "Action": "sns:Publish", // 使用self:arn引用当前Topic的ARN,避免循环依赖 "Resource": "${self.arn}", "Condition": { "ArnLike": { "aws:SourceArn": "arn:aws:s3:::${aws_s3_bucket.s3-bucket.id}" } } } ] } POLICY } resource "aws_s3_bucket_notification" "bucket_notification" { bucket = aws_s3_bucket.s3-bucket.id topic { topic_arn = aws_sns_topic.topic.arn events = ["s3:ObjectCreated:*"] } }
关键注意事项
- 必须指定Principal:AWS权限策略要求明确授权主体,不能省略。
- 避免循环依赖:内联策略用
self.arn替代资源引用,或使用独立策略资源配合depends_on确保配置顺序。 - 添加条件限制:通过
aws:SourceArn限制仅目标Bucket能触发通知,提升安全性。 - Bucket名称唯一性:S3 Bucket名称需全局唯一,确保配置的名称未被占用。
内容的提问来源于stack exchange,提问作者TayOnTech
相关产品推荐
相关产品推荐

