Reputation: 1
I am trying to create multiple IAM Groups and then attach multiple AWS policies to each group using terraform (v0.12).
Currently I have:
resource "aws_iam_group" "group1" {
name = "group1"
path = "/"
}
resource "aws_iam_group" "group2" {
name = "group2"
path = "/"
}
resource "aws_iam_group_policy_attachment" "group1" {
for_each = toset([
"arn:aws:iam::aws:policy/AmazonS3FullAccess",
"arn:aws:iam::aws:policy/AmazonCodeGuruProfilerFullAccess",
"arn:aws:iam::aws:policy/job-function/Billing"
])
group = aws_iam_group.group1.name
policy_arn = each.value
}
Is there a cleaner way for this to be done so that I won't end up using so much duplicated code.
Upvotes: 0
Views: 1596
Reputation: 846
You can use the built-in setproduct
function to achieve this functionality.
For example, given the following Terraform configuration:
variable "group_names" {
default = []
type = set(string)
}
variable "policy_arns" {
default = []
type = set(string)
}
locals {
group_policies = [
for group_policy in setproduct(var.group_names, var.policy_arns) : {
group_name = group_policy[0]
policy_arn = group_policy[1]
}
]
}
resource "aws_iam_group" "iam_group" {
for_each = var.group_names
name = each.value
}
resource "aws_iam_group_policy_attachment" "iam_group_policy_attachment" {
for_each = {
for group_policy in local.group_policies : "${group_policy.group_name}.${group_policy.policy_arn}" => group_policy
}
group = each.value.group_name
policy_arn = each.value.policy_arn
}
Results in the following plan:
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.
------------------------------------------------------------------------
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# aws_iam_group.iam_group["group1"] will be created
+ resource "aws_iam_group" "iam_group" {
+ arn = (known after apply)
+ id = (known after apply)
+ name = "group1"
+ path = "/"
+ unique_id = (known after apply)
}
# aws_iam_group.iam_group["group2"] will be created
+ resource "aws_iam_group" "iam_group" {
+ arn = (known after apply)
+ id = (known after apply)
+ name = "group2"
+ path = "/"
+ unique_id = (known after apply)
}
# aws_iam_group_policy_attachment.iam_group_policy_attachment["group1.arn:aws:iam::aws:policy/AmazonCodeGuruProfilerFullAccess"] will be created
+ resource "aws_iam_group_policy_attachment" "iam_group_policy_attachment" {
+ group = "group1"
+ id = (known after apply)
+ policy_arn = "arn:aws:iam::aws:policy/AmazonCodeGuruProfilerFullAccess"
}
# aws_iam_group_policy_attachment.iam_group_policy_attachment["group1.arn:aws:iam::aws:policy/AmazonEC2FullAccess"] will be created
+ resource "aws_iam_group_policy_attachment" "iam_group_policy_attachment" {
+ group = "group1"
+ id = (known after apply)
+ policy_arn = "arn:aws:iam::aws:policy/AmazonEC2FullAccess"
}
# aws_iam_group_policy_attachment.iam_group_policy_attachment["group1.arn:aws:iam::aws:policy/AmazonS3FullAccess"] will be created
+ resource "aws_iam_group_policy_attachment" "iam_group_policy_attachment" {
+ group = "group1"
+ id = (known after apply)
+ policy_arn = "arn:aws:iam::aws:policy/AmazonS3FullAccess"
}
# aws_iam_group_policy_attachment.iam_group_policy_attachment["group2.arn:aws:iam::aws:policy/AmazonCodeGuruProfilerFullAccess"] will be created
+ resource "aws_iam_group_policy_attachment" "iam_group_policy_attachment" {
+ group = "group2"
+ id = (known after apply)
+ policy_arn = "arn:aws:iam::aws:policy/AmazonCodeGuruProfilerFullAccess"
}
# aws_iam_group_policy_attachment.iam_group_policy_attachment["group2.arn:aws:iam::aws:policy/AmazonEC2FullAccess"] will be created
+ resource "aws_iam_group_policy_attachment" "iam_group_policy_attachment" {
+ group = "group2"
+ id = (known after apply)
+ policy_arn = "arn:aws:iam::aws:policy/AmazonEC2FullAccess"
}
# aws_iam_group_policy_attachment.iam_group_policy_attachment["group2.arn:aws:iam::aws:policy/AmazonS3FullAccess"] will be created
+ resource "aws_iam_group_policy_attachment" "iam_group_policy_attachment" {
+ group = "group2"
+ id = (known after apply)
+ policy_arn = "arn:aws:iam::aws:policy/AmazonS3FullAccess"
}
Plan: 8 to add, 0 to change, 0 to destroy.
------------------------------------------------------------------------
Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.
The setproduct
function returns all the possible combinations of elements given 2 or more arguments.
The for_each
expression in the aws_iam_group_policy_attachment
creates a map of key-value pairs where each key is formatted like so group_name.policy_arn
(e.g., "group2.arn:aws:iam::aws:policy/AmazonS3FullAccess"
) and each value is a map containing two keys, group_name
and policy_arn
, respectively.
It is important to create a unique key in the for_each
expression to prevent the possibility of overwriting existing keys in the map.
Upvotes: 2