Magnus
Magnus

Reputation: 3712

Terraform: how to concatenate lists of AWS arns?

I want to create a iam_policy_arn_list in terraform where the list consists of the "FullAccess" arns of existing AWS policies, and the arn of a policy that I create on the fly. (I'm trying to create a Lambda function that can read/write to only a specified bucket.) If I only use existing AWS policies, then the following ingredients in my setup work:

variable "iam_policy_arn_list" {
  type        = list(string)
  description = "IAM Policies to be attached to role"
  default = [
    "arn:aws:iam::aws:policy/CloudWatchFullAccess",
    "arn:aws:iam::aws:policy/AmazonSESFullAccess",
    "arn:aws:iam::aws:policy/AmazonS3FullAccess"
  ]
}

resource "aws_iam_role_policy_attachment" "role-policy-attachment" {
  role       = "${var.prefix}${var.role_name}"
  count      = length(var.iam_policy_arn_list)
  policy_arn = var.iam_policy_arn_list[count.index]
  depends_on = [aws_iam_role.iam_for_lambda]
}

But now I want to remove "arn:aws:iam::aws:policy/AmazonS3FullAccess" and replace it with the arn of a policy that I create on the fly that lets the Lambda function only access a specified S3 bucket. Where I am stuck is how to end up with a list variable of the rough form:

variable "iam_policy_arn_list" {
  type        = list(string)
  description = "IAM Policies to be attached to role"
  default = [
    "arn:aws:iam::aws:policy/CloudWatchFullAccess",
    "arn:aws:iam::aws:policy/AmazonSESFullAccess",
    arn_of_the_policy_I_create_on_the_fly
  ]
}

... because the concat function will not work when defining variables. I have tried using the concat function elsewhere, but nothing seems to work. E.g. I tried:

resource "aws_iam_policy" "specific_s3_bucket_policy" {
  name        = "my_name"
  description = "Grant access to one specific S3 bucket"
  policy = jsonencode({
    "Version" : "2012-10-17",
    "Statement" : [
      {
        "Effect" : "Allow",
        "Action" : [
          "s3:ListAllMyBuckets",
          "s3:ListBucket"
        ],
        "Resource" : "*"
      },
      {
        "Effect" : "Allow",
        "Action" : [
          "s3:PutObject",
          "s3:PutObjectAcl",
          "s3:GetObject",
          "s3:GetObjectAcl",
          "s3:DeleteObject"
        ],
        "Resource" : "arn:aws:s3:::${var.S3_BUCKET_NAME}/*"
      }
    ]
  })
}



resource "aws_iam_role_policy_attachment" "role-policy-attachment" {
  role       = "${var.prefix}${var.role_name}"
  count      = length(var.iam_policy_arn_list)
  policy_arn = concat(var.iam_policy_arn_list, [aws_iam_policy.specific_s3_bucket_policy.arn])[count.index]
  depends_on = [aws_iam_role.iam_for_lambda]
}

... but this does not work. Suggestions?

Upvotes: 1

Views: 1081

Answers (1)

yvesonline
yvesonline

Reputation: 4837

Given the following iam_policy_arn_list:

variable "iam_policy_arn_list" {
  type        = list(string)
  description = "IAM Policies to be attached to role"
  default = [
    "arn:aws:iam::aws:policy/CloudWatchFullAccess",
    "arn:aws:iam::aws:policy/AmazonSESFullAccess",
  ]
}

Then create a local value like this:

locals {
  combined_iam_policy_arn_list = concat(var.iam_policy_arn_list, [aws_iam_policy.specific_s3_bucket_policy.arn])
}

And then apply it like this:

resource "aws_iam_role_policy_attachment" "role-policy-attachment" {
  role       = "${var.prefix}${var.role_name}"
  count      = length(local.combined_iam_policy_arn_list)
  policy_arn = local.combined_iam_policy_arn_list[count.index]
  depends_on = [aws_iam_role.iam_for_lambda]
}

Upvotes: 2

Related Questions