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
azurermLong 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
➕ 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
azurermRole assignments for Azure RBAC and Azure AD show human-readable role names, scopes, and principal information in a clear table format.
❌ Without tfplan2md
# 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
➕ module.security.azurerm_role_assignment.rg_reader
| 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.
➕ 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 |➕ 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 |➕ azuread_user jane — 👤 Jane Doe (🆔 jane.doe@example.com) 📧 jane.doe@example.com
| Attribute | Value |
|---|---|
| display_name | 👤 Jane Doe |
| 📧 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
azurermMap 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 + azapiAzure 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.