Architecting Secure Azure Infrastructure with Terraform and Managed Identities

In the modern landscape of cloud infrastructure automation, the management of credentials represents one of the most significant security vulnerabilities. Traditional methods of authentication—such as service accounts with static passwords, API keys stored in environment variables, or certificates that inevitably expire—create a perpetual operational burden and an expanded attack surface. For DevOps engineers and cloud architects, the goal is to move toward a "secretless" architecture.

Azure Managed Identities provide the definitive solution to this problem by granting Azure resources an identity in Microsoft Entra ID (formerly Azure Active Directory) without requiring the developer or operator to manage any credentials. When paired with Terraform, the industry-standard Infrastructure as Code (IaC) tool, organizations can define, deploy, and govern these identities with surgical precision. This integration allows for the automated provisioning of resources that can authenticate to other Azure services—such as Key Vault or Storage Accounts—using native Azure Role-Based Access Control (RBAC), entirely eliminating the risk of credential leakage in source code.

Understanding Azure Managed Identities

Managed identities are essentially a wrapper around a service principal in Microsoft Entra ID. The primary distinction is that the management of the service principal's credentials (the rotation of keys and secrets) is handled entirely by Azure. There are two distinct types of managed identities, each serving different architectural requirements.

System-Assigned Managed Identity

A system-assigned managed identity is tied directly to the lifecycle of a specific Azure resource. It is created automatically when the identity is enabled on that resource. Because the identity is bound to the resource, if the resource is deleted, the associated identity is automatically purged from Entra ID. This creates a strict 1:1 relationship, making it ideal for workloads that require a unique identity that should not persist beyond the life of the resource itself.

User-Assigned Managed Identity

A user-assigned managed identity is created as a standalone Azure resource. Unlike system-assigned identities, a user-assigned identity is not tied to any single resource's lifecycle and can be assigned to multiple Azure resources simultaneously. This makes it a powerful tool for scaling applications where multiple Virtual Machines or App Services need to share the same set of permissions to access a common backend resource.

Feature System-Assigned User-Assigned
Lifecycle Tied to the resource Independent standalone resource
Relationship 1:1 (One identity per resource) 1:Many (One identity, multiple resources)
Deletion Deleted when resource is deleted Persists until manually deleted
Use Case Resource-specific unique permissions Shared permissions across a cluster/app tier
Configuration Enabled on the resource Created first, then attached to resource

Terraform Provider Authentication via Managed Identity

Terraform allows for the definition and deployment of cloud infrastructure using HashiCorp Configuration Language (HCL). When running Terraform in a non-interactive manner—such as within a CI/CD pipeline—HashiCorp recommends using either a Service Principal or a managed identity for authentication.

The Challenge with Remote Execution in HCP Terraform

A common point of failure occurs when attempting to use managed identity authentication within HCP Terraform. By default, HCP Terraform workspaces execute operations on HashiCorp-managed infrastructure. Because this infrastructure resides outside of your specific Azure environment, it cannot natively assume a managed identity that exists within your Azure subscription.

To resolve this, HCP Terraform Agents must be utilized. The architectural requirements for this configuration are as follows:

  • The agent must be deployed on a supported Azure resource (such as a VM or a Kubernetes cluster) that supports managed identities.
  • The resource hosting the agent must meet the specific system requirements for running HCP Terraform agents.
  • The workspace must be configured to use the agent pool where the agent is registered.
  • The managed identity on the agent-hosting resource must be granted the appropriate RBAC roles (e.g., Contributor) for the subscription it is intended to manage.

Implementing Managed Identity in Terraform Code

The power of Terraform lies in its ability to not only create the identity but also to assign roles and attach that identity to resources in a single execution plan.

Creating and Attaching User-Assigned Identities

When using a user-assigned identity, the identity must be defined as its own resource before it can be referenced by other components. For instance, when deploying a Linux Virtual Machine, the identity block within the azurerm_linux_virtual_machine resource is used to link the identity.

The following implementation demonstrates the creation of a production-grade Linux VM with a user-assigned identity:

```hcl
resource "azurermuserassignedidentity" "app" {
name = "ui-app-prod-identity"
resource
groupname = azurermresourcegroup.app.name
location = azurerm
resource_group.app.location
}

resource "azurermlinuxvirtualmachine" "app" {
name = "vm-app-prod-01"
location = azurerm
resourcegroup.app.location
resource
groupname = azurermresourcegroup.app.name
size = "Standard
D2sv5"
admin
username = "azureuser"

adminsshkey {
username = "azureuser"
publickey = file("~/.ssh/idrsa.pub")
}

networkinterfaceids = [
azurermnetworkinterface.app.id,
]

osdisk {
caching = "ReadWrite"
storage
accounttype = "PremiumLRS"
}

sourceimagereference {
publisher = "Canonical"
offer = "0001-com-ubuntu-server-jammy"
sku = "22_04-lts"
version = "latest"
}

# Assign the user-assigned managed identity
identity {
type = "UserAssigned"
identityids = [azurermuserassignedidentity.app.id]
}
}
```

Combining Identity Types

Azure allows a single resource to possess both a system-assigned and a user-assigned identity. This is useful in hybrid scenarios where a resource needs a unique identity for its own logs and a shared identity for accessing a corporate database. In Terraform, this is achieved by updating the type attribute:

hcl identity { type = "SystemAssigned, UserAssigned" identity_ids = [azurerm_user_assigned_identity.app.id] }

Managed Identities for App Services

Managed identities are not limited to VMs. Cloud-native services like Azure App Service (Web Apps) and Function Apps support them as well. In the azurerm_linux_web_app resource, the identity block is applied similarly to the VM configuration, allowing the web application to authenticate to other Azure services without storing passwords in the application settings.

Role-Based Access Control (RBAC) and Permissions

Creating an identity is only the first step; the identity must be granted permission to perform specific actions. This is handled via the azurerm_role_assignment resource.

System-Assigned Role Assignment

For a system-assigned identity, the principal_id is an attribute of the resource itself. This creates a dependency: the VM must be created before the role can be assigned.

```hcl
data "azurerm_subscription" "current" {}

resource "azurermroleassignment" "example" {
scope = data.azurermsubscription.current.id
role
definitionname = "Contributor"
principal
id = azurermvirtualmachine.main.identity[0].principal_id
}
```

Best Practices for Identity Governance

To maintain a secure and auditable environment, the following principles should be applied to all Terraform-managed identities:

  • Principle of Least Privilege: Avoid using broad roles like "Contributor" at the subscription level if a more granular role, such as "Reader" on a specific resource group, is sufficient.
  • Separation of Concerns: Assign separate identities to different applications. If two applications require different permission sets, creating one "super-identity" for both increases the blast radius in the event of a compromise.
  • Naming Conventions: Implement a strict naming schema. Identity names should include the application name, the environment (e.g., dev, stage, prod), and the purpose of the identity.
  • Centralized Management: Organize all managed identities within a dedicated resource group. This simplifies the auditing process and provides a single point of visibility for identity access.
  • Key Vault Integration: Instead of injecting secrets into application settings, use Key Vault references. The application uses its managed identity to authenticate to Key Vault and retrieve the secret at runtime, ensuring the secret never exists in plaintext within the configuration.

Advanced Implementation Strategies

When deploying at scale, the interaction between the identity, the resource, and the permission set becomes more complex. Utilizing Terraform's data sources and variables allows for more dynamic configurations.

For user-assigned identities, the id is available as a resource attribute. This eliminates the need for manual lookups and ensures that the azurerm_role_assignment is perfectly synced with the azurerm_user_assigned_identity.

Summary of Implementation Workflow

The standard workflow for deploying a secure, identity-driven resource in Azure via Terraform follows this logical sequence:

  1. Define the Resource Group to act as the container.
  2. Provision the azurerm_user_assigned_identity (if not using system-assigned).
  3. Provision the target resource (VM, Web App, etc.) and include the identity block referencing the ID from step 2.
  4. Use azurerm_role_assignment to link the identity's principal_id to a specific Azure Role and Scope.
  5. Verify the connection by attempting to access a protected resource (e.g., a Storage Account blob) from within the provisioned resource.

Conclusion

The integration of Azure Managed Identities within Terraform represents a fundamental shift toward zero-trust architecture in cloud computing. By eliminating the need for static credentials, organizations can virtually remove the risk of password leakage, reduce the overhead of secret rotation, and simplify the auditing of their cloud environment.

Whether utilizing system-assigned identities for resource-specific tasks or user-assigned identities for scalable application tiers, the result is a more robust security posture. When executing these configurations through HCP Terraform, the use of Terraform Agents ensures that the identity-based authentication chain remains intact, even when operating from a remote management plane. Ultimately, adopting managed identities is not merely a technical convenience but a security imperative for any organization operating at scale within the Azure ecosystem.

Sources

  1. Provisioning Azure Virtual Machines with Managed Identity Using Terraform
  2. Using Managed Identity with the Azure or AzureAD Provider in HCP Terraform
  3. How to Create Azure User Assigned Managed Identities in Terraform
  4. Authenticate to Azure with Managed Identity for Azure Services

Related Posts