Terraform创建SQS及访问策略时出现循环错误的解决方法
修复Terraform中SQS队列与IAM策略文档的循环依赖问题
问题背景
尝试创建SQS队列并通过data "aws_iam_policy_document"生成访问策略附加到队列,但触发循环依赖错误。
报错信息
╷ │ Error: Cycle: data.aws_iam_policy_document.sqs_vote_policy, aws_sqs_queue.sqs_vote │
原Terraform代码
resource "aws_sqs_queue" "sqs_vote" { name = "sqs-erjan" delay_seconds = 0 message_retention_seconds = 86400 receive_wait_time_seconds = 0 policy = data.aws_iam_policy_document.sqs_vote_policy.json } data "aws_iam_policy_document" "sqs_vote_policy" { policy_id = "__default_policy_ID" statement { sid = "__console_sub_0" actions = ["SQS:SendMessage"] resources = [aws_sqs_queue.sqs_vote.arn] principals { type = "AWS" identifiers = ["*"] } effect = "Allow" condition { test = "ArnLike" variable = "AWS:SourceArn" values = [ aws_sns_topic.vote_sns.arn ] } } statement { sid = "__owner_statement" actions = ["SQS:*"] resources = [aws_sqs_queue.sqs_vote.arn] principals { type = "arn:aws:iam::025416187662:root" identifiers = ["*"] } effect = "Allow" } # 添加了depends_on但仍出现循环错误 depends_on = [ aws_sqs_queue.sqs_vote,aws_sns_topic.vote_sns ] }
问题原因
循环依赖的核心是双向引用:
- SQS队列资源需要策略文档生成的JSON内容才能创建
- 策略文档又依赖SQS队列的ARN来生成内容
- 额外添加的
depends_on = [aws_sqs_queue.sqs_vote]进一步强化了这种双向依赖,导致Terraform无法确定执行顺序。
修复方案
方案一:内联生成策略文档
直接在SQS队列资源中用jsonencode内联编写策略,通过self.arn引用当前队列的ARN,避免外部依赖。
resource "aws_sqs_queue" "sqs_vote" { name = "sqs-erjan" delay_seconds = 0 message_retention_seconds = 86400 receive_wait_time_seconds = 0 policy = jsonencode({ "Version" : "2012-10-17", "Id" : "__default_policy_ID", "Statement" : [ { "Sid" : "__console_sub_0", "Effect" : "Allow", "Principal" : { "AWS" : "*" }, "Action" : "SQS:SendMessage", "Resource" : self.arn, "Condition" : { "ArnLike" : { "AWS:SourceArn" : aws_sns_topic.vote_sns.arn } } }, { "Sid" : "__owner_statement", "Effect" : "Allow", "Principal" : { "AWS" : "arn:aws:iam::025416187662:root" }, "Action" : "SQS:*", "Resource" : self.arn } ] }) }
方案二:使用单独的aws_sqs_queue_policy资源
拆分资源创建顺序:先创建SQS队列,再生成策略文档,最后通过单独的队列策略资源将策略附加到队列。
# 先创建SQS队列,不指定policy参数 resource "aws_sqs_queue" "sqs_vote" { name = "sqs-erjan" delay_seconds = 0 message_retention_seconds = 86400 receive_wait_time_seconds = 0 } # 生成IAM策略文档,仅依赖SNS主题 data "aws_iam_policy_document" "sqs_vote_policy" { policy_id = "__default_policy_ID" statement { sid = "__console_sub_0" actions = ["SQS:SendMessage"] resources = [aws_sqs_queue.sqs_vote.arn] principals { type = "AWS" identifiers = ["*"] } effect = "Allow" condition { test = "ArnLike" variable = "AWS:SourceArn" values = [aws_sns_topic.vote_sns.arn] } } statement { sid = "__owner_statement" actions = ["SQS:*"] resources = [aws_sqs_queue.sqs_vote.arn] principals { type = "AWS" identifiers = ["arn:aws:iam::025416187662:root"] } effect = "Allow" } depends_on = [aws_sns_topic.vote_sns] } # 单独创建队列策略,附加到已创建的SQS队列 resource "aws_sqs_queue_policy" "sqs_vote_policy" { queue_url = aws_sqs_queue.sqs_vote.id policy = data.aws_iam_policy_document.sqs_vote_policy.json }
方案对比
- 方案一:代码更简洁,适合策略逻辑简单的场景,无需额外资源。
- 方案二:逻辑更清晰,策略文档可复用,适合复杂策略或需要单独管理策略的场景。
内容的提问来源于stack exchange,提问作者ERJAN
相关产品推荐
相关产品推荐

