Securing Production Systems in Azure
Security in production Azure environments is not a single control but a layered system — each layer assumes the one above it may be breached. This defence-in-depth model means that no single misconfiguration or compromised credential results in a complete breach. Building secure production systems in Azure requires deliberate work across identity, network, data, application, and monitoring layers, applied consistently from day one rather than retrofitted after an incident.
Identity: the new perimeter
In cloud architecture, identity has replaced the network as the primary security boundary. Every service-to-service call, every developer action, and every automated deployment is authenticated through Microsoft Entra ID (formerly Azure Active Directory). Getting identity right is the foundation on which everything else rests.
Use managed identities for all Azure-hosted compute. VMs, App Service, Container Apps, AKS pods (via Workload Identity), and Azure Functions can all authenticate to other Azure services without any stored credentials. Assign the minimum RBAC role needed. A Function that reads from a storage account needs only Storage Blob Data Reader, not Storage Account Contributor.
Enforce Multi-Factor Authentication (MFA) for all human access. Require MFA via Conditional Access policies for all users accessing the Azure portal, CLI, and Azure-connected applications. Use number matching to prevent MFA fatigue attacks. Require phishing-resistant MFA (FIDO2 keys or certificate-based authentication) for privileged roles (Contributor, Owner, Global Administrator).
Implement Privileged Identity Management (PIM) for all privileged Azure RBAC roles. PIM requires just-in-time activation with business justification, enforces approval workflows for sensitive roles, and provides a time-limited elevation that expires automatically. No one should hold permanent Owner or Global Administrator assignments.
# Assign managed identity to an App Service and grant it Key Vault Secrets User role
az webapp identity assign \
--resource-group myRG \
--name myWebApp
# Get the principal ID of the managed identity
PRINCIPAL_ID=$(az webapp identity show \
--resource-group myRG \
--name myWebApp \
--query principalId --output tsv)
# Grant Key Vault Secrets User role
az role assignment create \
--assignee $PRINCIPAL_ID \
--role "Key Vault Secrets User" \
--scope /subscriptions/SUB_ID/resourceGroups/myRG/providers/Microsoft.KeyVault/vaults/myKeyVaultNetwork segmentation
The principle of least network access says that every resource should only be reachable from the network paths it legitimately needs. Public internet access should be the exception, not the default.
Deploy all PaaS services with Private Endpoints. Private Endpoints assign a private IP address from your VNet to a PaaS service (Azure SQL, Key Vault, Storage, Service Bus, etc.), making it reachable only from within the VNet. Disable public access on every PaaS service that has a Private Endpoint. This prevents any traffic from reaching the service without going through your network controls.
Use Network Security Groups (NSGs) to restrict traffic between subnets. Define a deny-all default rule and whitelist only required communication paths. Document every NSG rule with its business justification. Audit NSG rules quarterly and remove any that are no longer needed.
Route all outbound internet traffic through Azure Firewall. Azure Firewall provides FQDN-based allow lists, TLS inspection, intrusion detection, and centralised logging. Without it, a compromised workload can reach any internet address freely. With it, outbound traffic is restricted to the FQDNs your applications legitimately need.
# Disable public network access on an Azure SQL Server
az sql server update \
--resource-group myRG \
--name mySQLServer \
--enable-public-network false
# Disable public network access on a Key Vault
az keyvault update \
--resource-group myRG \
--name myKeyVault \
--public-network-access Disabled
# Create a Private Endpoint for Key Vault
az network private-endpoint create \
--resource-group myRG \
--name kvPrivateEndpoint \
--vnet-name myVNet \
--subnet privateEndpointSubnet \
--private-connection-resource-id /subscriptions/SUB_ID/resourceGroups/myRG/providers/Microsoft.KeyVault/vaults/myKeyVault \
--connection-name kvConnection \
--group-id vaultSecrets and key management
Azure Key Vault is the central secrets store for production systems. All database connection strings, API keys, TLS certificates, and encryption keys must be stored in Key Vault. No secrets in code, no secrets in environment variables, no secrets in deployment pipelines.
Enable Key Vault soft delete and purge protection. Soft delete retains deleted secrets for 7–90 days (configurable), preventing accidental permanent deletion. Purge protection prevents anyone from permanently deleting a soft-deleted secret during the retention period — even if they have Key Vault Administrator role. This is critical for compliance and protects against insider threats.
Enable Key Vault logging to a Log Analytics workspace. Every secret access, creation, and deletion is logged. Set up an alert for high-volume secret reads, reads from unexpected IP addresses, and any failed authentication attempts to Key Vault.
# Enable soft delete and purge protection on Key Vault
az keyvault update \
--resource-group myRG \
--name myKeyVault \
--enable-soft-delete true \
--enable-purge-protection true \
--retention-days 90
# Enable Key Vault diagnostic logging
az monitor diagnostic-settings create \
--resource /subscriptions/SUB_ID/resourceGroups/myRG/providers/Microsoft.KeyVault/vaults/myKeyVault \
--name kv-diagnostics \
--workspace /subscriptions/SUB_ID/resourceGroups/myRG/providers/microsoft.operationalinsights/workspaces/myLogAnalytics \
--logs '[{"category":"AuditEvent","enabled":true}]' \
--metrics '[{"category":"AllMetrics","enabled":true}]'Threat detection with Microsoft Defender for Cloud
Microsoft Defender for Cloud provides two functions: security posture management (what is misconfigured) and threat protection (what is being attacked). Enable the relevant Defender plans for your production workload types.
Defender for Servers monitors VMs and container hosts for suspicious process execution, file integrity violations, network anomalies, and known attack patterns. It integrates with Microsoft Defender for Endpoint for EDR capabilities. Defender for Containers monitors AKS clusters for privileged container launches, unusual API server access, and crypto-mining indicators. Defender for SQL monitors Azure SQL for SQL injection attempts, unusual data access patterns, and brute-force attacks.
Review the Secure Score in Defender for Cloud weekly. The Secure Score reflects the percentage of security recommendations that are implemented. Each recommendation has an associated resource and a remediation step. Prioritise recommendations with high impact and high severity first.
Security posture governance
Azure Policy enforces security requirements as guardrails at the platform level. Assign policies to Management Groups so they apply to all subscriptions and cannot be bypassed by individual teams. Key policies for production environments:
- Require HTTPS-only on App Service and Storage Accounts.
- Require Private Endpoints and deny public access on SQL, Storage, and Key Vault.
- Require TLS 1.2 as the minimum TLS version on all applicable services.
- Deny VM creation without the Guest Attestation extension (for Trusted Launch VMs).
- Require Azure Monitor diagnostic settings to be enabled on specific service types.
- Deny storage accounts with public blob access enabled.
# Assign built-in policy to require HTTPS on storage accounts
az policy assignment create \
--name require-https-storage \
--policy /providers/Microsoft.Authorization/policyDefinitions/404c3081-a854-4457-ae30-26a93ef643f9 \
--scope /subscriptions/SUB_ID \
--enforcement-mode DefaultIncident response preparation
Security incidents are not if but when. Having a tested incident response process dramatically reduces the impact and duration of incidents. Define your RACI (Responsible, Accountable, Consulted, Informed) for security incidents before one occurs. Every engineer should know who to call, not just the security team lead.
Connect Defender for Cloud alerts to Microsoft Sentinel (Azure’s SIEM) for correlation across multiple alert sources. Sentinel’s automation rules can trigger Logic Apps or Playbooks that automatically isolate a compromised VM (by applying an NSG deny-all rule), revoke suspicious AAD tokens, or notify the incident response team via PagerDuty or Teams.
Common mistakes
- Using connection strings in App Service application settings. Application settings appear in the Azure portal, in deployment logs, and can be accessed by anyone with Reader role. Store connection strings in Key Vault and reference them via Key Vault references in App Service settings. The reference syntax fetches the secret at runtime using managed identity — the actual value is never exposed in the portal.
- Granting Owner or Contributor roles to service principals for CI/CD. A deployment pipeline needs to create and update specific resources, not to have full control of the subscription. Use the minimum RBAC role required and scope it to the specific resource groups the pipeline manages. Use Workload Identity Federation for GitHub Actions and Azure DevOps rather than client secrets, which expire and leak.
- Neglecting to rotate credentials that cannot use managed identity. Some third-party services require API keys stored as secrets. Set up a rotation alert in Key Vault for every manually managed secret. Use Azure Key Vault automatic rotation (available for SQL and Storage account keys) where possible. When a secret is not rotated, it ages until it becomes a liability.
Summary
- Use managed identities for all Azure-hosted compute; eliminate service principal client secrets where possible.
- Deploy PaaS services with Private Endpoints and disable public access; route all outbound traffic through Azure Firewall.
- Store every secret, certificate, and key in Azure Key Vault with soft delete and purge protection enabled.
- Enable Microsoft Defender plans for your active compute types and review Secure Score weekly.
- Enforce security requirements with Azure Policy at the Management Group level so teams cannot bypass guardrails.
- Prepare and test an incident response process before an incident occurs.
Frequently asked questions
What is managed identity and why should I use it instead of service principals with client secrets?
A managed identity is an identity assigned to an Azure resource (a VM, App Service, Function App, Container App, etc.) that Azure manages automatically — there is no credential to create, rotate, or store. The resource authenticates to other Azure services using its identity, and Azure handles the token exchange invisibly. Service principal client secrets, by contrast, must be stored somewhere (Key Vault, environment variable, config file), rotated on a schedule, and are a common source of credential leaks. Use managed identity wherever the compute resource is Azure-hosted.
How do I prevent secrets from appearing in deployment logs and environment variables?
Store all secrets in Azure Key Vault. Reference them in App Service configuration using Key Vault references (format: @Microsoft.KeyVault(SecretUri=...)). The App Service runtime fetches the secret at startup using its managed identity — the secret value never appears in the portal, deployment logs, or environment variable listings. For Kubernetes, use the Azure Key Vault provider for Secrets Store CSI Driver to mount secrets as volumes rather than environment variables.
What is Microsoft Defender for Cloud and should I enable it for production?
Microsoft Defender for Cloud is a cloud security posture management (CSPM) and cloud workload protection platform (CWPP). The free tier provides security recommendations and a secure score. The paid Defender plans (Defender for Servers, Defender for Containers, Defender for Databases, etc.) add threat detection, behavioural analysis, and automated response capabilities. For any production workload, enable at minimum the plans covering your active compute types. The cost is typically small relative to the risk reduction.