Terraform配置S3 Bucket到SNS通知失败,请求排查
错误概述
执行terraform apply时出现以下错误:
Error: creating S3 Bucket (aws-solution-associate) Notification: operation error S3: PutBucketNotificationConfiguration, https response error StatusCode: 400, RequestID: VPV6DW8AMS2NS31S, HostID: QavFpP5mW+8RR8nexKcwwsytg+2gXe3cwAuyQqv9GzpD8OMIXZT8Y9EDHMtN+WZwC8lhAqFwkcA=, api error InvalidArgument: Unable to validate the following destination configurations
with aws_s3_bucket_notification.s3_sns_notification,
on main.tf line 249, in resource "aws_s3_bucket_notification" "s3_sns_notification":
249: resource "aws_s3_bucket_notification" "s3_sns_notification" {
该错误源于S3无法验证目标SNS主题的权限配置,以下是具体问题和修复方案:
问题1:S3桶策略完全配置错误
你定义的aws_iam_policy_document.s3_bucket_to_sns_topic_policy是允许指定SNS主题对S3桶执行s3:PutObject操作,这和S3触发通知到SNS的需求完全无关,属于配置方向错误。S3向SNS发送通知不需要配置S3桶策略,而是需要SNS主题策略允许S3服务向其发布消息。
修复
删除以下代码块:
data "aws_iam_policy_document" "s3_bucket_to_sns_topic_policy" { statement { sid = "AllowSNSPublish" effect = "Allow" actions = ["s3:PutObject"] resources = ["arn:aws:s3:::aws-solution-associate/*"] condition { test = "StringEquals" variable = "aws:SourceArn" values = ["arn:aws:sns:${var.region}:${data.aws_caller_identity.current.account_id}:resize-image-topic-1451"] } } } resource "aws_s3_bucket_policy" "bucket_policy" { bucket = data.aws_s3_bucket.s3_sns.id policy = data.aws_iam_policy_document.s3_bucket_to_sns_topic_policy.json }
问题2:SNS主题策略中AWS:SourceAccount条件值错误
在data.aws_iam_policy_document.sns-topic-policy的第二个statement里,AWS:SourceAccount的values设置成了SNS主题的ARN,而AWS:SourceAccount要求的值是AWS账号ID,不是ARN。同时建议添加AWS:SourceArn条件,限制只有指定S3桶能向该主题发布消息,增强安全性。
修复
修改后的SNS主题策略第二个statement:
statement { sid = "lab4-sns-topic-policy-s3" effect = "Allow" principals { type = "Service" identifiers = ["s3.amazonaws.com"] } actions = [ "SNS:Publish", ] condition { test = "StringEquals" variable = "AWS:SourceAccount" values = [data.aws_caller_identity.current.account_id] } condition { test = "ArnEquals" variable = "AWS:SourceArn" values = ["arn:aws:s3:::aws-solution-associate"] } resources = [ "arn:aws:sns:${var.region}:${data.aws_caller_identity.current.account_id}:resize-image-topic-1451" ] }
问题3:S3通知资源的依赖关系与ARN引用错误
你的aws_s3_bucket_notification.s3_sns_notification依赖的是data.aws_s3_bucket.s3_sns,但实际需要确保SNS主题已创建完成;同时硬编码ARN存在维护风险,建议直接引用资源属性。
修复
修改后的S3通知资源:
resource "aws_s3_bucket_notification" "s3_sns_notification" { bucket = data.aws_s3_bucket.s3_sns.id topic { topic_arn = aws_sns_topic.resize-image-topic.arn # 直接引用资源ARN,避免硬编码 events = ["s3:ObjectCreated:*"] filter_suffix = ".jpg" filter_prefix = "ingest/" } depends_on = [ aws_sns_topic.resize-image-topic ] }
问题4:SNS主题策略权限过度开放(可选优化)
原策略中给了*主体大量不必要的权限(如SNS:DeleteTopic、SNS:SetTopicAttributes),存在安全风险,建议只保留SQS订阅和发布的必要权限:
statement { sid = "lab4-sns-topic-policy-sqs" effect = "Allow" principals { type = "AWS" identifiers = ["*"] } actions = [ "SNS:Subscribe", "SNS:Publish" ] condition { test = "StringLike" variable = "SNS:Endpoint" values = [ "arn:aws:sqs:${var.region}:${data.aws_caller_identity.current.account_id}:mobile-queue", "arn:aws:sqs:${var.region}:${data.aws_caller_identity.current.account_id}:thumbnail-queue", "arn:aws:sqs:${var.region}:${data.aws_caller_identity.current.account_id}:web-queue", ] } resources = [ aws_sns_topic.resize-image-topic.arn # 直接引用资源ARN ] }
完成以上修改后,重新执行terraform apply即可解决该错误。
内容的提问来源于stack exchange,提问作者Norman

