I am trying to create multiple SNS topic subscription in the SQS. I do have the config file like below in json format
"snsSubscriptionArns": [
"arn:aws:sns:<region>:<accountno>:test1",
"arn:aws:sns:<region>:<accountno>:test2",
"arn:aws:sns:<region>:<accountno>:test3"
]
Above mentioned Arns will be based on the requirement. It's dynamic. It can be 0, can be 5.. I am trying to create policy using the below
locals {
# Load all of the data from json
config = jsondecode(file("testsqs.json"))
}
data "aws_iam_policy_document" "sns_policy" {
for_each = lookup(local.config, "snsSubscriptionArns", null) == null ? toset([]) : [ for i in local.config.snsSubscriptionArns : i ]
statement {
sid = "topic-subscription-${each.key}"
effect = "Allow"
actions = [
"sqs:SendMessage"
]
resources = [
"test-arn"
]
condition {
test = "ArnLike"
variable = "aws:SourceArn"
values = [
"${each.key}"
]
}
}
policy = data.aws_iam_policy_document.sns_policy[each.key].json
}
I need to collect all the policies and then I will use resource block to create SQS with above policy like below
resource "aws_sqs_queue_policy" "sqs_queue_policy" {
queue_url = aws_sqs_queue.queue.id
policy = data.aws_iam_policy_document.sns_policy.json
}
But I am getting the below error msg.
Error: Unsupported argument
on main.tf line 36, in data "aws_iam_policy_document" "sns_policy":
36: policy = data.aws_iam_policy_document.sns_policy[each.key].json
An argument named "policy" is not expected here.
It looks my approach is wrong in terraform. Could someone please guide me to achieve? Thanks in advance.
As you can see from the docs for data source aws_iam_policy_document, there is no policy
attribute. I believe either of these two options should work. You are very close.
Given the source json file testsqs.json:
{
"snsSubscriptionArns": [
"arn:aws:sns:<region>:<accountno>:test1",
"arn:aws:sns:<region>:<accountno>:test2",
"arn:aws:sns:<region>:<accountno>:test3"
]
}
and main.tf:
locals {
config = jsondecode(file("testsqs.json"))
arns = lookup(local.config, "snsSubscriptionArns", [])
}
data "aws_iam_policy_document" "sns_policy_one_statement" {
statement {
actions = ["sqs:SendMessage"]
resources = ["test-arn"]
condition {
test = "ArnLike"
variable = "aws:SourceArn"
values = local.arns
}
}
}
data "aws_iam_policy_document" "sns_policy_many_statements" {
dynamic "statement" {
for_each = local.arns
content {
sid = "topic-subscription-${statement.key}"
actions = ["sqs:SendMessage"]
resources = ["test-arn"]
condition {
test = "ArnLike"
variable = "aws:SourceArn"
values = [statement.value]
}
}
}
}
output "sns_policy_one_statement" {
value = data.aws_iam_policy_document.sns_policy_one_statement.json
}
output "sns_policy_many_statements" {
value = data.aws_iam_policy_document.sns_policy_many_statements.json
}
You get outputs like:
Changes to Outputs:
+ sns_policy_many_statements = jsonencode(
{
+ Statement = [
+ {
+ Action = "sqs:SendMessage"
+ Condition = {
+ ArnLike = {
+ "aws:SourceArn" = "arn:aws:sns:<region>:<accountno>:test1"
}
}
+ Effect = "Allow"
+ Resource = "test-arn"
+ Sid = "topic-subscription-0"
},
+ {
+ Action = "sqs:SendMessage"
+ Condition = {
+ ArnLike = {
+ "aws:SourceArn" = "arn:aws:sns:<region>:<accountno>:test2"
}
}
+ Effect = "Allow"
+ Resource = "test-arn"
+ Sid = "topic-subscription-1"
},
+ {
+ Action = "sqs:SendMessage"
+ Condition = {
+ ArnLike = {
+ "aws:SourceArn" = "arn:aws:sns:<region>:<accountno>:test3"
}
}
+ Effect = "Allow"
+ Resource = "test-arn"
+ Sid = "topic-subscription-2"
},
]
+ Version = "2012-10-17"
}
)
+ sns_policy_one_statement = jsonencode(
{
+ Statement = [
+ {
+ Action = "sqs:SendMessage"
+ Condition = {
+ ArnLike = {
+ "aws:SourceArn" = [
+ "arn:aws:sns:<region>:<accountno>:test1",
+ "arn:aws:sns:<region>:<accountno>:test2",
+ "arn:aws:sns:<region>:<accountno>:test3",
]
}
}
+ Effect = "Allow"
+ Resource = "test-arn"
+ Sid = ""
},
]
+ Version = "2012-10-17"
}
)
You only need for_each at the resource level if you want to create multiple of that resource. In your case, I think you only need one policy. You can decide which works for aws_sqs_queue_policy
. This uses the dynamic block.