Azure Service Principals vs Managed Identities: Secure App Auth
In Azure, apps and automation tools often need to authenticate to call APIs or access resources. You have two main options: Service Principals and Managed Identities. Both offer secure, credential-based access but they work differently and are suited for different scenarios.
What is a Service Principal?
A service principal is an identity created for use with apps, scripts, or automation. It's backed by a client ID and secret or certificate. You register it via Microsoft Entra ID.
Common use cases:
- Terraform deployments
- CI/CD pipelines (e.g., GitHub Actions, Azure DevOps, Atlantis)
- Third-party integrations that need Azure access
What is a Managed Identity?
Managed Identities are system-managed service principals that don’t require credential management. Azure handles rotation and lifecycle. They work only with Azure-hosted resources like VMs, Functions, Web Apps, etc.
Types:
- System-assigned: Tied to the resource’s lifecycle.
- User-assigned: Standalone identity reusable across resources.
Comparison table
Feature | Service Principal | Managed Identity |
---|---|---|
Credential rotation | Manual | Automatic |
Supports on-premises | ✅ | ❌ |
Works outside Azure | ✅ | ❌ |
Ideal for automation | ✅ | ✅ (in-Azure) |
Best practices
- Use managed identities when running code in Azure. It’s safer and easier to manage.
- Use service principals for cross-cloud, on-prem, or external automation.
- Always use least-privilege role assignments.
- Set up expiration alerts or rotate secrets regularly for SPs.
Terraform Example: Service Principal RBAC
This example grants a service principal the Contributor
role on a resource group:
resource "azurerm_role_assignment" "sp" {
name = "sp-contributor-assignment"
scope = azurerm_resource_group.example.id
role_definition_name = "Contributor"
principal_id = azuread_service_principal.my_app.id
}
Terraform Example: Managed Identity RBAC
This setup creates a reusable user-assigned managed identity and grants it the Reader
role:
resource "azurerm_user_assigned_identity" "example" {
name = "uami-example"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
}
resource "azurerm_role_assignment" "mi" {
name = "mi-reader-assignment"
scope = azurerm_resource_group.example.id
role_definition_name = "Reader"
principal_id = azurerm_user_assigned_identity.example.principal_id
}
Final thoughts
Service Principals and Managed Identities each play a vital role in Azure security. The key is choosing the right tool for the right job and making sure access is tightly scoped and auditable.