0
votes

I am trying to set role for azure container registry for multiple service principals

variable "custom_role_list" {

  type        = list(object ({ service_principal_id = string, role = string }) )

} 

When i try to set it from resource module, which I am not sure is the correct way?

resource "azurerm_role_assignment" "ad_sp_role_assignment" {

  scope                = azurerm_container_registry.acr.id
  for_each = var.custom_role_list
  role_definition_name           = each.value.role
  principal_id = each.value.service_principal_id

}

Essentially I am trying to set the azure container registry to work with multiple service principal with specific access roles.

Following is the var definition.

custom_role_list = [
    {
        service_principal_id = aserviceprincipal.id
        role = "Contributor"
    },

    {
        service_principal_id = bserviceprincipal.id
        role = "Contributor"
    }


]

When I execute it I get the following error.

Error: Invalid for_each argument

  on ../modules/az-acr/main.tf line 46, in resource "azurerm_role_assignment" "ad_sp_role_assignment":
  46:   for_each = var.custom_role_list

The given "for_each" argument value is unsuitable: the "for_each" argument
must be a map, or set of strings, and you have provided a value of type list
of object.

Please if someone can guide will be very much helpful. thanks!

2

2 Answers

2
votes

As the error suggests, for_each only supports maps and sets when used with a resource. You're trying to use a list of objects.

Instead, perhaps your variable can be simply of type map, where each service principle is a key and its corresponding role is the value. For example:

variable "custom_role_list" {
  type        = map
}

The variable definition:

custom_role_map = {
  aserviceprincipal.id = "Contributor"
  bserviceprincipal.id = "Contributor"
}

And finally use for_each:

resource "azurerm_role_assignment" "ad_sp_role_assignment" {
  for_each = var.custom_role_map

  scope                    = azurerm_container_registry.acr.id
  role_definition_name     = each.value
  principal_id             = each.key
}

You might find this blog post to help you with using loops and conditionals with Terraform.

0
votes

You can use a for_each loop with your list of objects by adapting your code to the following:

variable "custom_role_list" {
  type = list(object({
    service_principal_id = string
    role  = string 
  }))
  default = [
    {
        service_principal_id= "27d653c-aB53-4ce1-920",
        role  = "Contributor"
    },
     {
        service_principal_id= "57d634c-aB53-4ce1-397",
        role  = "Contributor"
    }
  ]
}
    
resource "azurerm_role_assignment" "ad_sp_role_assignment" {

for_each = {for sp in var.custom_role_list: sp.service_principal_id => sp}
    
scope                    = azurerm_container_registry.acr.id
role_definition_name     = each.value.service_principal_id 
principal_id             = each.value.role 
}