Azure security best practices come down to four things most teams get wrong in the same order: identity permissions are too broad, network isolation stops at “it’s in a VNet,” Key Vault gets configured with the legacy access-policy model instead of the current default, and Microsoft Defender for Cloud gets left on its free tier without anyone checking what that tier actually excludes. This covers all four with the real Azure CLI commands and built-in role names, not generic advice to “enable monitoring.”
Identity: Microsoft Entra ID and Azure RBAC Come First
Every Azure security best practice below assumes identity is already tight, because a permissive role assignment defeats network isolation, Key Vault permissions, and Defender alerts all at once — an over-privileged identity can just reach past them. Azure role-based access control (Azure RBAC) grants access to users, groups, service principals, or managed identities at one of four scope levels: a single resource, a resource group, a subscription, or a management group. The rule that matters: assign the role at the narrowest scope that still does the job, not “Contributor on the subscription” because it’s faster to set up once.
Assigning a role takes three inputs — who, what role, and what scope. Here’s a service principal getting a role scoped to one resource group, not the whole subscription:
az role assignment create --assignee-object-id "<service-principal-object-id>" \
--assignee-principal-type "ServicePrincipal" \
--role "Virtual Machine Contributor" \
--scope "/subscriptions/<subscription-id>/resourceGroups/<resource-group>"
Note: for a brand-new service principal or managed identity, skip plain --assignee and use --assignee-object-id with --assignee-principal-type ServicePrincipal instead. A new identity can hit a replication delay across Azure regions, and the role assignment can fail if you don’t specify the principal type explicitly.
To find what a role actually grants before you assign it: az role definition list --name "<roleName>". Scripts and automation should reference the role’s GUID, not its display name — Microsoft occasionally renames preview roles once they go GA, and the ID never changes even when the name does.
Network Isolation: What NSGs and Private Link Actually Block
A Network Security Group (NSG) filters inbound and outbound traffic by IP, port, and protocol at the subnet or NIC level — it’s a firewall rule set, and it’s the layer most Azure security checklists stop at. The gap: an NSG alone doesn’t mean a resource is unreachable from the public internet, only that specific ports are closed. A storage account or SQL server can still have a public endpoint enabled behind a perfectly-configured NSG.
Azure Private Link closes that specific gap. A private endpoint gives a PaaS resource — Storage, Key Vault, SQL Database, and dozens of others — a private IP address inside your VNet, so traffic to it never touches the public internet at all. But there’s a genuinely confusing point in Microsoft’s own documentation here: a private endpoint provides a private IP address, but it doesn’t automatically block the existing public endpoint. You still have to disable public network access on the resource itself; the private endpoint is an additional path in, not a replacement for turning the public one off.
The other thing worth knowing: NSGs do apply to private endpoint traffic (via network policies, which you enable per-subnet), but a few services — Cosmos DB is the documented example — need all destination ports open on that NSG for the private endpoint to work at all. If you lock every port down out of habit, you’ll break the exact connection you were trying to secure.
Azure Key Vault: RBAC Is Now the Default, Not Access Policies
This is the one place the old advice is now actually wrong, not just incomplete: Key Vault has run on two separate permission models — the legacy vault access policy and Azure RBAC — and as of API version 2026-02-01, Azure RBAC is the default access control model for newly created key vaults. If your vault predates that, it may still be on the legacy model and needs an explicit opt-in to switch.
Under RBAC, Key Vault splits cleanly into control-plane access (managing the vault itself — who can create or delete it) and data-plane access (reading the actual keys, secrets, and certificates inside it). These are different roles, and mixing them up is the most common Key Vault misconfiguration:
| Role | What it grants |
|---|---|
Key Vault Reader | Metadata only — can’t read secret contents or key material |
Key Vault Secrets Officer | Full control over secrets, not certificates or keys |
Key Vault Secrets User | Read secret values — the role an application’s managed identity should hold |
Key Vault Crypto User | Use keys for crypto operations, can’t manage or export them |
Key Vault Administrator | Full data-plane control over everything in the vault, but can’t manage role assignments |
Grant a service its actual working permission — usually Key Vault Secrets User for an app reading a connection string — at the vault scope, not Key Vault Administrator because it’s the one role that obviously works:
az role assignment create --role "Key Vault Secrets User" \
--assignee "<managed-identity-object-id>" \
--scope "/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.KeyVault/vaults/<vault-name>"
Important: if a user or service principal has Contributor on the vault’s control plane, they can grant themselves data-plane access on the legacy access-policy model. Tightly control who holds Contributor on any resource group containing a key vault — it’s a privilege-escalation path that doesn’t show up if you’re only reviewing the data-plane role assignments.
Encryption at Rest and in Transit: What’s Automatic, What Isn’t
Storage Service Encryption (SSE) is on by default for every Azure Storage account — enabled at creation, can’t be disabled. That’s the part most checklists get right. What they skip: the default uses Microsoft-managed keys, which satisfies most compliance baselines but not all. Customer-managed keys (CMK) are a separate opt-in tying the account to a Key Vault key, and they add real operational weight — you now own key rotation and availability, and losing the key means losing the data.
Encryption in transit is not automatic in the same way. Secure transfer required on a storage account rejects any HTTP connection, forcing HTTPS/TLS — but it’s a setting you have to turn on, and older storage accounts predating the current defaults may still have it off. Check it explicitly rather than assuming a storage account created years ago matches what a new one gets today.
Microsoft Defender for Cloud: What’s Free vs What Needs a Paid Plan
Azure Security Center was renamed Microsoft Defender for Cloud, and the older name still shows up in a lot of security checklists that haven’t been touched since. The product now splits into two genuinely separate pillars, and the free-vs-paid line falls exactly on that split:
- Cloud Security Posture Management (CSPM) — the Secure Score, recommendations, and regulatory compliance mapping. This is free for every Azure subscription.
- Cloud Workload Protection Platform (CWPP) — active threat detection and alerts per resource type (Defender for Servers, Defender for Storage, Defender for SQL, and so on). Each plan is billed separately, and none of them are on by default.
This means a subscription can show a healthy Secure Score while having zero active threat detection running — the free tier only tells you what’s misconfigured, not what’s actively being attacked. If your Azure security posture depends on Defender catching an intrusion, confirm the relevant Defender plan is actually enabled per resource type, not just that Defender for Cloud is “on.”
Microsoft is also mid-migration of Defender for Cloud into a unified Defender portal (security.microsoft.com) that brings cloud and endpoint security into one interface. Some features are only reachable there now — if a setting you expect isn’t in the classic Azure portal view, check the Defender portal before assuming it’s gone.
Monitoring: Azure Monitor and Diagnostic Settings
Azure Monitor collects metrics and logs, but most resources don’t send anything useful until you explicitly turn on diagnostic settings. Route them to a Log Analytics workspace, not just the built-in Activity Log — Activity Log only captures control-plane operations (who created or deleted a resource), not data-plane activity inside it.
For Key Vault specifically, enable diagnostic logging on the vault itself — AuditEvent logs every single secret and key access, which is the only way to answer “who read this secret and when” after the fact. Without it, that question has no answer, RBAC role assignment or not.
Azure Policy: Enforcing These Azure Security Best Practices Automatically
Role assignments and Key Vault configuration are things a person has to remember to do correctly every time. Azure Policy turns the ones that matter most into something the platform enforces on every new resource, so a misconfigured deployment gets denied or flagged instead of quietly shipping. A handful of built-in policies cover most of what’s above without writing custom policy JSON: Non-internet-facing virtual machines should be protected with network security groups, Disk encryption should be applied on virtual machines, and Allowed locations for data-residency requirements.
Assigning one is a single command once you have the built-in definition’s ID:
az policy assignment create \
--name "enforce-allowed-locations" \
--policy "e56962a6-4747-49cd-b67b-bf8b01975c4c" \
--scope "/subscriptions/<subscription-id>" \
--params "{ 'listOfAllowedLocations': { 'value': ['eastus', 'westeurope'] } }"
Group several related policies into an initiative (Microsoft’s term for a named bundle of policy definitions) when you want one compliance score across all of them instead of tracking each policy’s status separately — that’s the difference between “12 unrelated dashboards” and “one security baseline.”
Frequently Asked Questions
Q: Should I use Key Vault access policies or Azure RBAC?
A: Azure RBAC — it’s the current default for new vaults as of API version 2026-02-01, and it’s the only model that lets you scope permissions down to individual keys, secrets, or certificates when you genuinely need that. Access policies are the legacy model and only support vault-wide grants.
Q: Does a private endpoint mean a resource is no longer reachable from the public internet?
A: Not by itself. A private endpoint adds a private path in; it doesn’t disable the resource’s existing public endpoint. You have to turn off public network access separately for the resource to actually become unreachable from outside your network.
Q: Is Microsoft Defender for Cloud free?
A: The posture-management half (Secure Score, recommendations, compliance mapping) is free on every subscription. Active threat detection (Defender for Servers, Defender for Storage, etc.) is billed per plan and isn’t enabled by default — check per resource type, not just at the subscription level.
Q: What’s the minimum role to give an app that just needs to read one secret?
A: Key Vault Secrets User, scoped to that specific vault — not Key Vault Administrator or Contributor, both of which grant far more than reading a secret value requires.
Q: Do I need customer-managed keys for encryption at rest?
A: Only if a specific compliance framework requires it. Microsoft-managed keys (the default, already on for every storage account) satisfy most baselines. Customer-managed keys add real operational responsibility — you own rotation and availability, and losing the key means losing the data — so don’t add that burden without a concrete requirement driving it.
Quick Summary:
- Scope every role assignment to the narrowest level that works — resource or resource group, not subscription-wide Contributor
- A private endpoint doesn’t disable a resource’s public endpoint by itself; turn public access off separately
- Key Vault now defaults to Azure RBAC (API version 2026-02-01+) — check whether older vaults still need to be migrated off access policies
- Defender for Cloud’s free tier is posture management only; active threat detection is a separate, billed, per-resource-type plan
- Enable diagnostic logging on Key Vault specifically —
AuditEventlogs are the only record of who accessed which secret
For the identity layer specifically, see the full Azure service principal guide. For the network-isolation options in more depth, service endpoints vs. private endpoints vs. Private Link covers the trade-offs between each layer.