Safeguard
Cloud Security

Azure Security Best Practices for 2026

A practical Azure hardening guide covering Entra ID identity, Azure Policy guardrails, network isolation, Key Vault secrets, and Defender for Cloud — with Terraform and az CLI examples.

Marcus Chen
Cloud Security Engineer
6 min read

Most Azure incidents don't start with a zero-day. They start with a storage account someone flipped to public "just to test something," a network security group opened to 0.0.0.0/0 on RDP, or a service principal handed the Owner role on an entire subscription because scoping felt like too much friction on a Friday afternoon. Azure's default posture is permissive by design — Microsoft optimizes for developers getting started quickly, and the burden of tightening that posture falls on you. This guide walks through the controls that actually move the needle, organized the way a platform team should roll them out: identity first, then guardrails, then network, secrets, and detection.

Treat Identity as the Real Perimeter

In Azure, the network is no longer the boundary — Microsoft Entra ID (formerly Azure Active Directory) is. Every meaningful attack path eventually runs through a token, so identity hygiene is the highest-leverage work you can do.

  • Enforce phishing-resistant MFA through Conditional Access, not per-user MFA toggles. Require multifactor for all administrative roles and block legacy authentication protocols that can't honor MFA.
  • Use managed identities instead of secrets. A system-assigned managed identity lets a VM, Function, or App Service authenticate to Key Vault or Storage with no credential to leak, rotate, or commit to Git.
  • Apply Privileged Identity Management (PIM) so roles like Global Administrator and Subscription Owner are eligible rather than permanently assigned, activated just-in-time with approval and an audit trail.

Scope role assignments to the narrowest resource that works. A workload that reads one Key Vault should get Key Vault Secrets User on that vault, not Contributor on the resource group.

Enforce Guardrails with Azure Policy and Management Groups

Manual review doesn't scale. Azure Policy lets you codify rules that deny non-compliant resources at deployment time, and management groups let you inherit those rules across every subscription in the tenant.

{
  "if": {
    "allOf": [
      { "field": "type", "equals": "Microsoft.Storage/storageAccounts" },
      { "field": "Microsoft.Storage/storageAccounts/allowBlobPublicAccess", "equals": true }
    ]
  },
  "then": { "effect": "deny" }
}

Assign policy initiatives like the Microsoft cloud security benchmark at the top-level management group so new subscriptions are governed from the moment they're created. deny effects prevent drift; audit and deployIfNotExists effects catch and remediate what already exists.

Isolate the Network by Default

Public exposure is the misconfiguration that turns a minor bug into a breach. Build private-by-default and open exceptions deliberately.

resource "azurerm_storage_account" "data" {
  name                            = "sgdatastore2026"
  resource_group_name             = azurerm_resource_group.app.name
  location                        = azurerm_resource_group.app.location
  account_tier                    = "Standard"
  account_replication_type        = "GRS"
  allow_nested_items_to_be_public = false
  public_network_access_enabled   = false
  min_tls_version                 = "TLS1_2"
}

resource "azurerm_network_security_rule" "no_public_rdp" {
  name                        = "deny-inbound-rdp"
  priority                    = 100
  direction                   = "Inbound"
  access                      = "Deny"
  protocol                    = "Tcp"
  source_port_range           = "*"
  destination_port_range      = "3389"
  source_address_prefix       = "Internet"
  destination_address_prefix  = "*"
  network_security_group_name = azurerm_network_security_group.app.name
  resource_group_name         = azurerm_resource_group.app.name
}

Use Private Endpoints to keep PaaS traffic (Storage, SQL, Key Vault) on the Microsoft backbone rather than the public internet, and reach management planes through Azure Bastion instead of exposing RDP or SSH. Building these controls into your Terraform means they're reviewed in the pull request, which is exactly what infrastructure-as-code scanning validates before merge.

Centralize Secrets and Encryption in Key Vault

Never ship a connection string in an app setting or a .env file baked into a container. Store secrets, keys, and certificates in Azure Key Vault, grant access through Azure RBAC and managed identities, and enable soft-delete and purge protection so a deleted vault can't be permanently destroyed by an attacker or a bad script.

# Audit storage accounts that still allow public blob access
az storage account list \
  --query "[?allowBlobPublicAccess].{name:name, rg:resourceGroup}" -o table

# Read a secret using the workload's managed identity (no secret in code)
az keyvault secret show --vault-name sg-app-kv --name db-password --query value -o tsv

Enable encryption at rest with customer-managed keys where compliance requires control over the key lifecycle, and enforce TLS 1.2 or higher on every public endpoint.

Turn On Detection and Keep the Logs

Prevention fails eventually, so you need to see it when it does. Enable Microsoft Defender for Cloud for CSPM and workload protection, and route Activity Logs plus resource diagnostic settings to a Log Analytics workspace feeding Microsoft Sentinel. Without diagnostic settings configured, many resources emit no logs at all — the default is silence.

Azure Hardening Checklist

ControlWhat to verify
Conditional Access MFAEnforced for all admin roles; legacy auth blocked
Managed identitiesUsed in place of stored service-principal secrets
PIMOwner/Global Admin roles eligible, not permanent
Azure Policydeny initiatives assigned at management-group root
StorageallowBlobPublicAccess false; public network access disabled
NetworkNo 0.0.0.0/0 inbound on 22/3389; Private Endpoints for PaaS
Key VaultSoft-delete + purge protection on; RBAC access model
Defender for CloudEnabled; Activity + diagnostic logs to Log Analytics/Sentinel

How Safeguard Helps

Azure misconfigurations almost always exist in Bicep or Terraform before they exist in the portal, which is the cheapest place to catch them. Safeguard's infrastructure-as-code scanning inspects your Azure templates for public storage accounts, wildcard NSG rules, disabled TLS enforcement, and over-scoped role assignments in the pull request that introduces them — tied to the exact line so a developer fixes it before merge. The application code deploying onto that infrastructure is covered by software composition analysis, which builds an SBOM and flags vulnerable dependencies your functions and containers actually call. Griffin, Safeguard's AI triage engine, then ranks findings by real blast radius so a public endpoint on a production data store outranks a cosmetic warning. Because it all runs through the pipeline-native Safeguard CLI, you can gate merges so a non-compliant resource never ships. If you're weighing this build-time model against an agentless posture platform that evaluates Azure after deployment, the Safeguard vs Wiz comparison breaks down where each vantage point fits.

Start hardening your Azure estate at the pull request — create a free account or read the documentation.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.