earlO
earlO

Reputation: 43

Terraform import azurerm_role_assignment id

I want to import an azurerm_role_assignment (Azure) in Terraform dependent on my environment (dev, test, prod) by using an import block such as

import {
  to = azurerm_role_assignment.test_role_assignment
  id = "<scope>/.../<GUID>"
}

At the moment I use

az role assignment list --assignee ... --all

which returns a list of role assignments and now based on matching roleDefinitionName I copy the related id manually into the import block and it works. But it is different for the other environments. I want to avoid copying a lot of IDs manually.

So I was thinking within the scope I can use a variable "env" in order to import from the correct environment. But the changing GUID is required - for example:

import {
  to = azurerm_role_assignment.test_role_assignment
  id = "/subscriptions/.../resourcegroups/$(var.env)-rg/$(data.<something>.id)"
}

Is there a way to get the GUID in a data block or similar so that I can put the GUID in the id of the import block? I don't want to manually import all role assignments for all environments manually. Thank you!

Upvotes: 0

Views: 820

Answers (2)

Cloudkollektiv
Cloudkollektiv

Reputation: 14729

You can accomplish this by using the AzAPI provider. This provider offers all the capabilities of the azure rest api. And may be useful if resources or data sources are not yet readily available in the AzureRM provider. However, since this provider is less abstract it might require more in depth knowledge about the underlying rest objects and responses.

The azapi_resource_list data source can be used to list all role assignments for a particular assignee. In this case I assume that the assignee is a user, but it can also be another entity. Make sure that you correctly specify the filter in the resource type field. More filters for role assignments can be found in the official documentation. And don't forget to set enable_hcl_output_for_data_source on the AzAPI provider, so that you can easily use data source outputs in hcl format.

provider "azurerm" {
  features {}
}

provider "azapi" {
  enable_hcl_output_for_data_source = true
}

data "azuread_user" "assignee" {
  user_principal_name = "[email protected]"
}

data "azurerm_subscription" "current" {}

data "azapi_resource_list" "role_assignments" {
  parent_id              = "/subscriptions/${data.azurerm_subscription.id}"
  type                   = join("", [
    "Microsoft.Authorization/roleAssignments@2022-04-01",
    "$filter=atScope()+and+assignedTo('${data.azuread_user.assignee.object_id}')"
  ])
  response_export_values = ["*"]
}

locals {
  role_assignments = {
    for item in data.azapi_resource_list.role_assignment.output.value : item.id => item
  }
}

resource "azurerm_role_assignment" "example" {
  for_each = local.role_assignments
  
  scope              = each.value.properties.scope
  role_definition_id = each.value.properties.roleDefinitionId
  principal_id       = each.value.properties.principalId
}

import {
  for_each = local.role_assignments
  
  to = azurerm_role_assignment.role_assignment.example[each.key]
  id = each.value.id
}

Finally, if you want to deploy this to multiple environments (i.e. subscriptions), you can set a different value for the environment variable ARM_SUBSCRIPTION_ID before running your terraform commands.

Note: I did not fully test this, because I don’t have an active Azure account. Feel free to correct me or provide additional information.

Upvotes: 0

Marco
Marco

Reputation: 605

For this answer I'll go with: You have a role definition name you can match with, and you require the GUID for the role assignment to be returned to you as a value so you can use it for your imports. Probably in this case, if it must be az cli, I would try the az rest command.

az rest --method get --url "https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.Authorization/roleAssignments?api-version=2022-04-01&$filter=atScope()+and+assignedTo('{objectId}')"

With this you can go over the subscriptions, and get the GUID for the role assignment. Read docs here.

Perhaps, if your logic is something like:

  • Store all subscriptions for the loop

for each subscription:

  • Find the role definition ID for 'roledefinitionname'
  • Extract all role assignment IDs for the role Perhaps something like will help you out:
az account list --query '[].id' -o tsv

role_definition_name="roledefinitionname"

for subscription in $(az account list --query '[].id' -o tsv); do

    az account set --subscription $subscription
    
    role_definition_id=$(az role definition list --name $role_definition_name --query '[0].id' -o tsv)
    
    if [ -n "$role_definition_id" ]; then
        echo "Role definition ID for $role_definition_name: $role_definition_id"
        
        az role assignment list --query "[?roleDefinitionId=='$role_definition_id'].{assignmentId:id}" -o tsv
    else
        echo "Role definition $role_definition_name not found in subscription $subscription"
    fi

done

Granted this is written for Windows. But the az commands are there for your personal fine-tuning. Hope it helps.

Upvotes: 1

Related Questions