Home > database >  Create multiple IAM roles with different policies in Terraform
Create multiple IAM roles with different policies in Terraform

Time:09-01

Good day everyone, I am new to terraform, trying to solve a problem and stuck in it. I want to create multiple AWS IAM roles using input variables and then assign different policies to those roles. I am trying to do this in for_each loop. However, I am unable to solve the riddle that how to provide different policies. I am trying to solve this using a map variable. Here is my test code

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
    }
  }
}


provider "aws" {
  region = "region"
  shared_credentials_file = "path_to_creds"
  profile                 = "profile_name"
}

variable "roles" {
  type = map
  default = {

*   # These bucket names should be different in each policy

    "TestRole1"  = "module.s3_bucket_raw.s3_bucket_arn, module.s3_bucket_bronze.s3_bucket_arn"
    "TestRole2" = "module.s3_bucket_bronze.s3_bucket_arn, module.s3_bucket_silver.s3_bucket_arn"
  }
}

resource "aws_iam_role" "example" {
  for_each = var.roles
  name    = "${each.key}"
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = [
          "s3:PutObject",
          "s3:GetObject",
          "s3:ListBucket",
          "s3:GetBucketAcl",
          "s3:DeleteObject",
          "s3:GetBucketLocation"
        ]
        Effect   = "Allow"
        Resource = [
           each.value,
           "${each.value}/*"
        ]
      }
    ]
  })
  
}

As you can see in the Resource block of the policy the bucket name will be each.value which will be

module.s3_bucket_raw.s3_bucket_arn, module.s3_bucket_bronze.s3_bucket_arn

this is fine however I also want to do the

module.s3_bucket_raw.s3_bucket_arn/*, module.s3_bucket_bronze.s3_bucket_arn/*

which is not possible with my approach because when i do "${each.value}/*" this will translate into

module.s3_bucket_raw.s3_bucket_arn, module.s3_bucket_bronze.s3_bucket_arn/*

I hope some expert can spend few minutes for me, for which I am thanking you all in anticipation.

CodePudding user response:

I would first either update the variable definition to store the buckets as a list or add a local to convert your variable to a nice object before creating the resource if you can't update the variable definition. This variable would be nicer to work with:

variable "roles" {
    type = map
    default = {
        "TestRole1" = ["module.s3_bucket_raw.s3_bucket_arn", "module.s3_bucket_bronze.s3_bucket_arn"]
        "TestRole2" = ["module.s3_bucket_bronze.s3_bucket_arn", "module.s3_bucket_silver.s3_bucket_arn"]
    }
}

Then you can use a for loop in the resource like this:

resource "aws_iam_role" "example" {
    for_each = var.roles
    name    = "${each.key}"
    assume_role_policy = jsonencode({
        Version = "2012-10-17"
        Statement = [
        {
            Action = [
            "s3:PutObject",
            "s3:GetObject",
            "s3:ListBucket",
            "s3:GetBucketAcl",
            "s3:DeleteObject",
            "s3:GetBucketLocation"
            ]
            Effect   = "Allow"
            Resource = flatten([for bucket in each.value: [bucket, "${bucket}/*"]]),
        }]
    }) 
}

I prefer the aws_iam_policy_document data source for complex policies but I'll leave that to you.

  • Related