You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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:*"]
  }
}

问题原因与解决方案

核心问题

  1. 初始策略缺少主体(Principal)与安全条件
    第一个版本的IAM策略未指定允许执行SNS:Publish操作的主体,AWS会拒绝这种不完整的权限配置;同时也没有限制仅目标S3 Bucket能触发通知,不符合安全规范。

  2. 内联策略的循环依赖
    第二个写法中,在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 16:07:56