Policy and Governance Guardrails
For new Azure projects, prevent credential-bearing patterns from being created rather than relying only on code review.
Recommended policy intents
Apply these at management group or subscription scope as appropriate for the landing zone:
| Resource | Policy intent |
|---|---|
| Storage accounts | Deny or audit allowSharedKeyAccess not set to false for workloads that support Microsoft Entra auth |
| Cosmos DB accounts | Deny or audit disableLocalAuth not set to true |
| Service Bus namespaces | Deny or audit disableLocalAuth not set to true |
| Event Hubs namespaces | Deny or audit disableLocalAuth not set to true |
| Key Vault | Require RBAC authorization model, purge protection, and soft delete for production vaults |
| App Service / Functions / Container Apps | Audit workloads without managed identity enabled |
| Role assignments | Audit broad data-plane roles at subscription scope |
| Pipeline service connections | Require workload identity federation for new Azure deployment connections where the platform supports it |
Use built-in Azure Policy definitions where available. Use custom policies only to cover gaps or organization-specific standards.
Azure Resource Graph checks
Storage shared key
resources
| where type =~ 'microsoft.storage/storageaccounts'
| project id, name, resourceGroup, allowSharedKeyAccess = tostring(properties.allowSharedKeyAccess)
| where allowSharedKeyAccess != 'false'Cosmos DB local auth
resources
| where type =~ 'microsoft.documentdb/databaseaccounts'
| project id, name, resourceGroup, disableLocalAuth = tostring(properties.disableLocalAuth)
| where disableLocalAuth != 'true'Service Bus and Event Hubs local auth
resources
| where type in~ ('microsoft.servicebus/namespaces', 'microsoft.eventhub/namespaces')
| project id, name, type, resourceGroup, disableLocalAuth = tostring(properties.disableLocalAuth)
| where disableLocalAuth != 'true'Workloads without managed identity
resources
| where type in~ ('microsoft.web/sites', 'microsoft.app/containerapps', 'microsoft.compute/virtualmachines')
| project id, name, type, resourceGroup, identityType = tostring(identity.type)
| where isempty(identityType) or identityType =~ 'None'Exception handling
Every exception must include:
- Business justification.
- Owner.
- Expiry date.
- Compensating controls.
- Migration issue or backlog item.
- Evidence that the service currently lacks a supported identity-based alternative or that migration cannot happen safely yet.