Attach multiple policy to single SSO permission set

Hello,
I am trying attach multiple managed policy to single AWS SSO permission set.
But not able to iterate through list inside the map.

modules/sso_aws_managed_policy_attachment/main.tf

variable "policy_attachments" {
  type = map(list(any))
  description = "Map of policy attachments with permission set name as key and list of policy ARNs as value."
}

data "aws_ssoadmin_instances" "abc-company" {}

resource "aws_ssoadmin_permission_set" "ssoadmin_permission_set" {
  for_each    = var.policy_attachments

  instance_arn     = tolist(data.aws_ssoadmin_instances.moonfrog.arns)[0]
  name        = each.key
}

resource "aws_ssoadmin_managed_policy_attachment" "policy_attachment" {
  for_each           = var.policy_attachments
  permission_set_arn = aws_ssoadmin_permission_set.ssoadmin_permission_set[each.key].arn
  instance_arn     = tolist(data.aws_ssoadmin_instances.abc-company.arns)[0]
  dynamic "managed_policy_arn" {
    for_each = each.key
    content {
      managed_policy_arn = managed_policy_arn.value
    }
  }
}
}

main.tf

module "aws_managed_policy_attachment" {
  source = "./modules/sso_aws_managed_policy_attachment"

  policy_attachments = {
    "admin" = ["arn:aws:iam::aws:policy/AdministratorAccess"],
    "finance" =  ["arn:aws:iam::aws:policy/job-function/Billing"],
    "sse" =  ["arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess", "arn:aws:iam::aws:policy/CloudWatchReadOnlyAccess"]
  }
}

Getting following error:

β”‚ Error: Missing required argument
β”‚
β”‚   on modules/sso_aws_managed_policy_attachment/main.tf line 46, in resource "aws_ssoadmin_managed_policy_attachment" "policy_attachment":
β”‚   46: resource "aws_ssoadmin_managed_policy_attachment" "policy_attachment" {
β”‚
β”‚ The argument "managed_policy_arn" is required, but no definition was found.
β•΅
β•·
β”‚ Error: Unsupported block type
β”‚
β”‚   on modules/sso_aws_managed_policy_attachment/main.tf line 51, in resource "aws_ssoadmin_managed_policy_attachment" "policy_attachment":
β”‚   51:   dynamic "managed_policy_arn" {
β”‚
β”‚ Blocks of type "managed_policy_arn" are not expected here.

It will be really great if anyone can help.

Avoid any unless supporting multiple types is genuinely required. Here, it’s clear that the values inside the lists will always be of type string.

There are a couple of problems here: managed_policy_arn is not a block, and dynamic is only for creating blocks. managed_policy_arn also only accepts a single value.

You need a separate instance of aws_ssoadmin_managed_policy_attachment for every combination of ARNs.

That means your top level for_each within the resource block needs to iterate over both permissions sets and policies.

This is possible, it just gets a bit messy:

resource "aws_ssoadmin_managed_policy_attachment" "policy_attachment" {
  for_each = {
    for combination in flatten([
      for permission_set, policy_arns in var.policy_attachments : [
        for policy_arn in policy_arns : {
          key            = "${permission_set} ${policy_arn}"
          permission_set = permission_set
          policy_arn     = policy_arn
        }
      ]
    ]) :
    combination.key => combination
  }

  permission_set_arn = aws_ssoadmin_permission_set.ssoadmin_permission_set[each.value.permission_set].arn
  managed_policy_arn = each.value.policy_arn
  instance_arn       = ...
}
1 Like

Works like charm!
Thank you, saved my day.