Home > Enterprise >  Create Role assignment dynamically in Terraform from input
Create Role assignment dynamically in Terraform from input

Time:02-22

I am trying to create multiple role assignments using a typical variable given below where "permission {}" is a new variable I would like to introduce in the form of a type map, so I can perform multiple role assignments.

My TFVARS file

azure_vnets= {
  prod= [
    {
      cidr = ["10.0.0.0/24"]
      vnet_name = "vnet1"
      dns  = ["10.0.0.1"]
      rg   = "myrg1"
      permission = {
      Contributor =  ["xxxxxxxxxxxx", "xxxxxxxxxxxxx"],
      Reader = ["xxxxxxxxxxx", "xxxxxxxxxx"]
      } 
      location = "eastus"
    },
    {
      cidr = ["10.0.1.0/24"]
      vnet_name = "vnet2"
      dns  = ["10.0.1.2"]
      rg   = "myrg2"
      permission = {
      Contributor =  ["xxxxxxxxxxxx", "xxxxxxxxxxxxx"],
      Reader = ["xxxxxxxxxxx", "xxxxxxxxxx"]
      } 
      location = "westeurope"
    }
  ],
  nonprod = [
     {
      cidr = ["10.0.3.0/24"]
      vnet_name = "vnet1"
      dns  = ["10.0.3.1"]
      rg   = "nonprodrg"
      location = "eastus"
      permission = {
      Contributor =  ["xxxxxxxxxxxx", "xxxxxxxxxxxxx"],
      Reader = ["xxxxxxxxxxx", "xxxxxxxxxx"]
      } 
    },
    {
      cidr = ["10.0.4.0/24"]
      vnet_name = "nonprod-vnet2"
      dns  = ["10.0.4.2"]
      sub  = "nonProd"
      rg   = "mynonprodrg"
      permission = {
      Contributor =  ["xxxxxxxxxxxx", "xxxxxxxxxxxxx"],
      Reader = ["xxxxxxxxxxx", "xxxxxxxxxx"]
      } 
      location = "westeurope"
    }
  ]
}

My resource creation file I have a local defined here which helps me use the above variable in a for_each loop given below in the role assignment creation. I would like to know how to get the Rolename as Key and ObjectID as value in the below for_each role_assignment creation from the above TFvar variable


locals {
  flat_azure_vnets = merge([
      for env_name, env_vn_list in var.azure_vnets:
         {
           for idx, env_vn in env_vn_list:
             "${env_name}-${idx}" => env_vn
         }
    ]...)
}


resource "azurerm_role_assignment" "role_assignment" {
    for_each = { for k, v in local.flat_azure_vnets  : k => v }
    scope                = azurerm_resource_group.this.id
    role_definition_name = each.xxx
    principal_id         = each.key
}

CodePudding user response:

To iterate over your new permission attribute, you have to further flatten your flat_azure_vnets. So you can introduce flat_azure_vnets2:

locals {
  flat_azure_vnets = merge([
      for env_name, env_vn_list in var.azure_vnets:
         {
           for idx, env_vn in env_vn_list:
             "${env_name}-${idx}" => env_vn
         }
    ]...)
    

  flat_azure_vnets2 = merge([
      for key, env in local.flat_azure_vnets:
         {
           for cidx, contrinutor in env["permission"]["Contributor"]:
             "${key}-${cidx}" => merge(
                   env, {
                       "contrinutor" = contrinutor,
                       "reader" = env["permission"]["Reader"][cidx]
                       }
               )
         }
    ]...)
}

which produces flat_azure_vnets2 in the form of (notice new contrinutor and reader attributes):

test = {
  "nonprod-0-0" = {
    "cidr" = [
      "10.0.3.0/24",
    ]
    "contrinutor" = "xxxxxxxxxxxx"
    "dns" = [
      "10.0.3.1",
    ]
    "location" = "eastus"
    "permission" = {
      "Contributor" = [
        "xxxxxxxxxxxx",
        "xxxxxxxxxxxxx",
      ]
      "Reader" = [
        "xxxxxxxxxxx",
        "xxxxxxxxxx",
      ]
    }
    "reader" = "xxxxxxxxxxx"
    "rg" = "nonprodrg"
    "vnet_name" = "vnet1"
  }
  "nonprod-0-1" = {
    "cidr" = [
      "10.0.3.0/24",
    ]
    "contrinutor" = "xxxxxxxxxxxxx"
    "dns" = [
      "10.0.3.1",
    ]
    "location" = "eastus"
    "permission" = {
      "Contributor" = [
        "xxxxxxxxxxxx",
        "xxxxxxxxxxxxx",
      ]
      "Reader" = [
        "xxxxxxxxxxx",
        "xxxxxxxxxx",
      ]
    }
    "reader" = "xxxxxxxxxx"
    "rg" = "nonprodrg"
    "vnet_name" = "vnet1"
  }
  "nonprod-1-0" = {
    "cidr" = [
      "10.0.4.0/24",
    ]
    "contrinutor" = "xxxxxxxxxxxx"
    "dns" = [
      "10.0.4.2",
    ]
    "location" = "westeurope"
    "permission" = {
      "Contributor" = [
        "xxxxxxxxxxxx",
        "xxxxxxxxxxxxx",
      ]
      "Reader" = [
        "xxxxxxxxxxx",
        "xxxxxxxxxx",
      ]
    }
    "reader" = "xxxxxxxxxxx"
    "rg" = "mynonprodrg"
    "sub" = "nonProd"
    "vnet_name" = "nonprod-vnet2"
  }
  "nonprod-1-1" = {
    "cidr" = [
      "10.0.4.0/24",
    ]
    "contrinutor" = "xxxxxxxxxxxxx"
    "dns" = [
      "10.0.4.2",
    ]
    "location" = "westeurope"
    "permission" = {
      "Contributor" = [
        "xxxxxxxxxxxx",
        "xxxxxxxxxxxxx",
      ]
      "Reader" = [
        "xxxxxxxxxxx",
        "xxxxxxxxxx",
      ]
    }
    "reader" = "xxxxxxxxxx"
    "rg" = "mynonprodrg"
    "sub" = "nonProd"
    "vnet_name" = "nonprod-vnet2"
  }
  "prod-0-0" = {
    "cidr" = [
      "10.0.0.0/24",
    ]
    "contrinutor" = "xxxxxxxxxxxx"
    "dns" = [
      "10.0.0.1",
    ]
    "location" = "eastus"
    "permission" = {
      "Contributor" = [
        "xxxxxxxxxxxx",
        "xxxxxxxxxxxxx",
      ]
      "Reader" = [
        "xxxxxxxxxxx",
        "xxxxxxxxxx",
      ]
    }
    "reader" = "xxxxxxxxxxx"
    "rg" = "myrg1"
    "vnet_name" = "vnet1"
  }
  "prod-0-1" = {
    "cidr" = [
      "10.0.0.0/24",
    ]
    "contrinutor" = "xxxxxxxxxxxxx"
    "dns" = [
      "10.0.0.1",
    ]
    "location" = "eastus"
    "permission" = {
      "Contributor" = [
        "xxxxxxxxxxxx",
        "xxxxxxxxxxxxx",
      ]
      "Reader" = [
        "xxxxxxxxxxx",
        "xxxxxxxxxx",
      ]
    }
    "reader" = "xxxxxxxxxx"
    "rg" = "myrg1"
    "vnet_name" = "vnet1"
  }
  "prod-1-0" = {
    "cidr" = [
      "10.0.1.0/24",
    ]
    "contrinutor" = "xxxxxxxxxxxx"
    "dns" = [
      "10.0.1.2",
    ]
    "location" = "westeurope"
    "permission" = {
      "Contributor" = [
        "xxxxxxxxxxxx",
        "xxxxxxxxxxxxx",
      ]
      "Reader" = [
        "xxxxxxxxxxx",
        "xxxxxxxxxx",
      ]
    }
    "reader" = "xxxxxxxxxxx"
    "rg" = "myrg2"
    "vnet_name" = "vnet2"
  }
  "prod-1-1" = {
    "cidr" = [
      "10.0.1.0/24",
    ]
    "contrinutor" = "xxxxxxxxxxxxx"
    "dns" = [
      "10.0.1.2",
    ]
    "location" = "westeurope"
    "permission" = {
      "Contributor" = [
        "xxxxxxxxxxxx",
        "xxxxxxxxxxxxx",
      ]
      "Reader" = [
        "xxxxxxxxxxx",
        "xxxxxxxxxx",
      ]
    }
    "reader" = "xxxxxxxxxx"
    "rg" = "myrg2"
    "vnet_name" = "vnet2"
  }
}

CodePudding user response:

You can use the below example which I have tested in my environment:

provider "azurerm"{
    features{}
}
locals {
  flat_azure_vnets = merge([
      for env_name, env_vn_list in var.azure_vnets:
         {
           for idx, env_vn in env_vn_list:
             "${env_name}-${idx}" => env_vn
         }
    ]...)
    flat_rbac = {for i,r in local.flat_azure_vnets : "role-${i}"=>"${r.permission}"}

    
}

variable "azure_vnets" {}

output "rbac" {
  value = local.flat_rbac
}
module "Contributor_roleAssignment" {
  for_each = zipmap(keys(local.flat_rbac), values(local.flat_rbac)[*].Contributor)
  source   = "./modules/roleAssignment"

  role_definition_name = "Contributor"
  scope_id             = "/subscriptions/948d4068-cee2-492b-8f82-e00a844e059b/resourceGroups/ansumantest"
  principal_ids        = each.value
}

module "Reader_roleAssignment" {
  for_each = zipmap(keys(local.flat_rbac), values(local.flat_rbac)[*].Reader)
  source   = "./modules/roleAssignment"

  role_definition_name = "Reader"
  scope_id             = "/subscriptions/948d4068-cee2-492b-8f82-e00a844e059b/resourceGroups/ansumantest"
  principal_ids        = each.value
}

Role assignment module i.e. "./modules/roleAssignment"

main.tf

locals {
    principals = toset(var.principal_ids)
}

resource "azurerm_role_assignment" "role_assignment" {
    for_each = local.principals
    
    scope                = var.scope_id
    role_definition_name = var.role_definition_name
    principal_id         = each.key
}

variables.tf :

variable "role_definition_name" {
    type        = any
    description = "The name of the Role to assign to the chosen Scope."
}

variable "scope_id" {
  type        = string
  description = "The Id of the scope where the role should be assigned."
}

variable "principal_ids" {
  type        = list(string)
  description = "The ID of the principal that is to be assigned the role at the given scope. Can be User, Group or SPN."
}

Output:

enter image description here

enter image description here

enter image description here enter image description here

  • Related