Search code examples
amazon-web-servicesterraformamazon-sqsterraform-provider-aws

How to append multiple AWS SQS policies using Terraform


I do have the default policy for the SQS like below. Referred the documentation - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue_policy

And if there is sns-subscription required, I would like to append the policy on top of the default policy.

Default policy is like below

  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "sqs:SendMessage*"
      ],
      "Resource": [
        "${aws_sqs_queue.queue.arn}"
      ]
    }
  ]
}

Additional policy like below

{
      "Sid": "topic-subscription-arn-test",
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "SQS:SendMessage",
      "Resource": ["${aws_sqs_queue.queue.arn}"],
      "Condition": {
        "ArnLike": {
          "aws:SourceArn": "arn-test"
        }
      }
    }

I just tried, but the policy getting override. Any thoughts how policy can be appended using Terraform? Thanks in advance. Looking for somekind of thought for this approach? It may be more than 2 policies, so I am trying to append these policies.


Solution

  • I would strongly suggest using the aws_iam_policy_document data source [1] for building policies in Terraform instead of JSON. Since the SQS queue has an argument policy [2], the resource aws_sqs_queue_policy does not have to be used, but it can also be combined with the data source mentioned above. So there are two options:

    1. Create a policy using data source and attach it by using the policy argument
    2. Create a policy using data source and attach it to the aws_sqs_queue_policy

    If you decide for the first option, here is how the code should look like:

    data "aws_iam_policy_document" "sqs_policy" {
    
      statement {
        sid = "FirstSQSPolicy"
        effect  = "Allow"
        actions = [
          "sqs:SendMessage*"
        ]
        resources = [
          aws_sqs_queue.queue.arn
        ]
      }
    
      statement {
        sid     = "topic-subscription-arn-test"
        effect  = "Allow"
        actions = [
          "sqs:SendMessage"
        ]
        resources = [
          aws_sqs_queue.queue.arn
        ]
        condition {
          test     = "ArnLike"
          variable = "aws:SourceArn"
          values = [
            "arn-test"
          ]
        }
      }
    }
    
    resource "aws_sqs_queue" "terraform_queue" {
      ...
      policy = data.aws_iam_policy_document.sqs_policy.json
    }
    

    For the second option, you can use the same data source and attach the JSON to the aws_sqs_queue_policy resource:

    data "aws_iam_policy_document" "sqs_policy" {
    
      statement {
        sid = "FirstSQSPolicy"
        effect  = "Allow"
        actions = [
          "sqs:SendMessage*"
        ]
        resources = [
          aws_sqs_queue.queue.arn
        ]
      }
    
      statement {
        sid     = "topic-subscription-arn-test"
        effect  = "Allow"
        actions = [
          "sqs:SendMessage"
        ]
        resources = [
          aws_sqs_queue.queue.arn
        ]
        condition {
          test     = "ArnLike"
          variable = "aws:SourceArn"
          values = [
            "arn-test"
          ]
        }
      }
    }
    
    resource "aws_sqs_queue_policy" "sqs_queue_policy" {
      queue_url = aws_sqs_queue.queue.id
    
      policy = data.aws_iam_policy_document.sqs_policy.json
    }
    

    Using the data source for IAM policies you can add statements as you need them.


    [1] https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document

    [2] https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue#policy