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.