Azure Optimizations

Purpose-built features for Azure that format resource IDs, map principals and scopes, suppress Azure ID noise, and show role assignments clearly.

Readable Azure Resource IDs

azurerm

Long Azure resource IDs are automatically parsed and formatted as human-readable scopes instead of displaying raw GUID paths.

❌ Without tfplan2md

# module.security.azurerm_key_vault_secret.db_password will be created
+ resource "azurerm_key_vault_secret" "db_password" {
    + key_vault_id = "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/rg-tfplan2md-demo/providers/Microsoft.KeyVault/vaults/kv-tfplan2md"
    + name         = "db-password"
  }

Long Azure IDs make it hard to identify the resource and scope at a glance.

✅ With tfplan2md

Key Vault Secret Output

➕ module.security.azurerm_key_vault_secret.db_password

Attribute Value
content_type password
key_vault_id Key Vault kv-tfplan2md in resource group rg-tfplan2md-demo
name 🆔 db-password
### ➕ module.security.azurerm_key_vault_secret.db_password

| Attribute | Value |
| ----------- | ------- |
| content_type | `password` |
| key_vault_id | Key Vault `kv-tfplan2md` in resource group `rg-tfplan2md-demo` |
| name | `🆔 db-password` |

The rendered scope emphasizes the resource group and resource name instead of an unreadable ID path.

Features

  • Automatic detection for subscription, tenant, management group, resource group, and resource IDs
  • Only the values are formatted as code while labels stay readable
  • Scope summaries add semantic icons for subscription and resource-group context
  • Azure IDs remain in the primary attribute tables instead of being pushed into a large-values section
  • Works across Azure resources without extra configuration

Azure Role Assignment Display

azurerm

Role assignments for Azure RBAC and Azure AD show human-readable role names, scopes, and principal information in a clear table format.

azuread

❌ Without tfplan2md

Raw Terraform Output
# module.iam.azurerm_role_assignment.rg_reader will be created
+ resource "azurerm_role_assignment" "rg_reader" {
    + principal_id         = "00000000-0000-0000-0000-000000000001"
    + principal_type       = "User"
    + role_definition_name = "Reader"
    + scope                = "/subscriptions/.../resourceGroups/rg-tfplan2md-demo"
  }

GUIDs and long scopes obscure who is getting what access.

✅ With tfplan2md

Role Assignment Output

➕ module.security.azurerm_role_assignment.rg_reader

👤 User → 🛡️ Reader on rg-tfplan2md-demo
Attribute Value
scope 📁 rg-tfplan2md-demo
role_definition_name 🛡️ Reader
principal_type 👤 User
principal_id 00000000-0000-0000-0000-000000000001
### ➕ module.security.azurerm_role_assignment.rg_reader

<summary>👤 User → 🛡️ Reader on rg-tfplan2md-demo</summary>

| Attribute | Value |
| ----------- | ------- |
| scope | `📁 rg-tfplan2md-demo` |
| role_definition_name | `🛡️ Reader` |
| principal_type | `👤 User` |
| principal_id | `00000000-0000-0000-0000-000000000001` |

The summary, principal, and scope are readable immediately, which reduces access-review friction.

Azure AD Examples

The same readable rendering works for groups, service principals, app roles, and other Azure AD-backed assignments.

Azure AD Group with Members

➕ azuread_group platform_team — 👥 Platform Team (🆔 Platform Engineering) Core platform engineering team | 2 👤 1 👥 1 💻 1 ❓

Attribute Value
description Core platform engineering team
display_name Platform Team
mail_nickname Platform Engineering
members[0] user-100
members[1] user-101
members[2] group-100
members[3] spn-200
members[4] unknown-999
### ➕ azuread_group platform_team — 👥 Platform Team (🆔 Platform Engineering) Core platform engineering team | 2 👤 1 👥 1 💻 1 ❓

| Attribute | Value |
| ----------- | ------- |
| description | Core platform engineering team |
| display_name | Platform Team |
| mail_nickname | Platform Engineering |
| members[0] | user-100 |
| members[1] | user-101 |
| members[2] | group-100 |
| members[3] | spn-200 |
| members[4] | unknown-999 |
Azure AD Service Principal

➕ azuread_service_principal terraform_spn — 💻 terraform-spn (🆔 app-123-456) Terraform automation service principal

Attribute Value
application_id app-123-456
description Terraform automation service principal
display_name terraform-spn
### ➕ azuread_service_principal terraform_spn — 💻 terraform-spn (🆔 app-123-456) Terraform automation service principal

| Attribute | Value |
| ----------- | ------- |
| application_id | app-123-456 |
| description | Terraform automation service principal |
| display_name | terraform-spn |
Azure AD User

➕ azuread_user jane — 👤 Jane Doe (🆔 jane.doe@example.com) 📧 jane.doe@example.com

Attribute Value
display_name 👤 Jane Doe
mail 📧 jane.doe@example.com
user_principal_name 🆔 jane.doe@example.com
### ➕ azuread_user jane — 👤 Jane Doe (🆔 jane.doe@example.com) 📧 jane.doe@example.com

| Attribute | Value |
| ----------- | ------- |
| display_name | 👤 Jane Doe |
| mail | 📧 jane.doe@example.com |
| user_principal_name | 🆔 jane.doe@example.com |

Principal and Scope Mapping

azurerm

Map cryptic principal IDs and Azure scope identifiers to human-readable names, such as user emails, tenant names, management groups, subscriptions, and service principals, using a JSON mapping file.

tfplan2md plan.json --principal-mapping principals.json

Benefits

  • No more cryptic GUIDs in role assignments
  • Reviewers can immediately see who has access to what
  • Works with role assignments, tenant scopes, management groups, subscriptions, and Azure DevOps entities in the same file
  • Falls back to the raw GUID when no mapping entry exists

Unified Mapping File

{ "subscriptions": [{ "id": "sub-guid", "displayName": "Production" }], "managementGroups": [{ "id": "mg-prod", "displayName": "Production Workloads" }], "tenants": [{ "id": "tenant-guid", "displayName": "Contoso Corp" }], "azdoUsers": { "4a2c...": "John Smith" }, "azdoRepositories": { "a1b2...": "Infrastructure Repo" } }

Case-Insensitive Azure ID Filter

azurerm + azapi

Azure resource IDs that differ only in casing are filtered by default, reducing ARM API noise in both AzureRM attributes and AzAPI body properties.

tfplan2md plan.json --ignore-azure-id-case-changes

Behavior

  • Enabled by default, with `--ignore-azure-id-case-changes` available to make the behavior explicit
  • Suppresses casing-only Azure resource ID rows while keeping the resource itself visible in the report
  • Applies to AzureRM resources and AzAPI body-level Azure resource IDs
  • Plays well with `--show-unchanged-values` by keeping the noise filtered out

Learn More

Azure optimizations include automatic formatting of resource IDs, readable role assignment views, and principal name mapping.