Alert on critical operationsMediumazure-activity-log-alerts
Activity Log alerts notify on high-risk operations (role assignment changes, NSG edits, security-solution deletions) in near-realtime. Catching these as they happen beats finding them in a quarterly review.
Forward the Activity LogHighazure-activity-log-to-la
Without an Activity Log → Log Analytics diagnostic setting, control-plane events (role changes, NSG edits, resource deletes) only retain 90 days natively. Most security investigations need year-plus retention.
Enable WAF on Application GatewayHighazure-app-gateway-waf
WAF disabled, or in Detection mode, doesn't block attacks. Production App Gateways should run WAF in Prevention mode (blocks + logs).
Enable App Service authenticationMediumazure-app-service-auth-disabled
App Services serving the public internet without 'Easy Auth' rely on in-app authentication, which is harder to audit and bypassable through forgotten endpoints. Easy Auth integrates Entra SSO without code changes.
Require HTTPS on App ServicesHighazure-app-service-https-only
App Services should have httpsOnly=true so HTTP traffic is auto-redirected. Avoids credentials and cookies traveling in cleartext during the initial request.
Require TLS 1.2 on App ServicesHighazure-app-service-tls-min
App Service siteConfig.minTlsVersion below 1.2 lets clients negotiate TLS 1.0 / 1.1 and breaks PCI-DSS / FedRAMP / most enterprise baselines.
Back up virtual machinesHighazure-backup-coverage
Every virtual machine should be protected by Azure Backup with a healthy, recent recovery point. Unbacked-up VMs are unrecoverable after ransomware, accidental deletion, or a failed change — the restore simply does not exist.
Protect backup vaults from deletionHighazure-backup-vault-hardening
Recovery Services and Backup vaults should have soft delete enabled so that backup data deleted by a compromised or mistaken administrator is retained and recoverable rather than destroyed immediately.
Enable DDoS ProtectionMediumazure-ddos-protection-standard
DDoS Protection Standard mitigates volumetric attacks against public IPs. Only VNets containing public-IP attached workloads are evaluated — pure internal VNets don't need it.
Enable Defender auto-provisioningMediumazure-defender-auto-provisioning
Auto-provisioning deploys the Log Analytics agent / MDE extension to new VMs automatically. Without it, new VMs silently fall out of MDE coverage as they're created.
Enable Defender for Cloud plansInfoazure-defender-plan-enablement
Defender for Cloud's per-workload plans (Servers, Storage, SQL, etc.) provide threat-detection signal on each workload type. Subscriptions on the Free tier only get configuration recommendations — no runtime threat protection.
Top Defender recommendationsInfoazure-defender-recommendations-summary
Per-subscription roll-up of the top 5 unhealthy high-severity Defender for Cloud recommendations. Informational — drives the 'what Defender thinks' dashboard panel. Never fails on its own.
Configure diagnostic settingsMediumazure-diagnostic-settings-coverage
Per-resource diagnostic settings forward data-plane logs (storage requests, KV accesses, SQL audits, NSG flow logs) to Log Analytics. Coverage <80% across critical resource types indicates substantial blind spots for forensic investigation.
Attach a WAF to Front DoorHighazure-front-door-waf
Front Door WAF is opt-in per frontend. Frontends without an attached WAF policy are unprotected against OWASP attacks and bot traffic.
Narrow overbroad custom rolesHighazure-iam-custom-roles-overbroad
Custom roles whose actions include `*`, `*/*`, or `Microsoft.Authorization/*` grant near-Owner privileges and bypass least-privilege. Microsoft.Authorization/* in particular is a privilege-escalation primitive (holder can grant themselves Owner).
Remove guest role assignmentsMediumazure-iam-guest-rbac-assignments
External B2B guest accounts with RBAC role assignments expand the trust boundary. Their authentication posture is controlled by their home tenant. Prefer Entra access reviews or per-resource sharing.
Use managed identitiesMediumazure-iam-managed-identity-coverage
Managed identities eliminate stored credentials for service-to-service auth. Coverage <50% suggests significant credential-rotation debt; <80% is a hygiene target worth working toward.
Remove orphaned role assignmentsLowazure-iam-orphaned-role-assignments
Role assignments referencing deleted Entra principals can't be exploited but clutter audits and signal missed access-review hygiene. Microsoft surfaces these without a resolvable principalDisplayName / principalUpn.
Use PIM for privileged rolesMediumneeds EntraID_P2azure-iam-pim-enabled
PIM lets users hold privileged Azure roles as eligible rather than active, requesting just-in-time activation. Substantially reduces standing-access blast radius. Requires Entra ID P2.
Limit service principal scopeHighazure-iam-sp-broad-scope
Service principals holding Owner or Contributor at subscription level have authority across every resource in the subscription. Scope them down to the specific resource groups they need.
Rotate service principal credentialsMediumazure-iam-sp-stale-credentials
Service principal secrets and certificates should be rotated yearly or sooner. Long-lived credentials accumulate exposure surface (logs, configs, source control).
Limit subscription OwnersHighazure-iam-subscription-owners
Microsoft recommends ≤2 Owners per subscription. Each Owner is a tenant-wide compromise risk; reducing the count reduces the blast radius of a phished credential.
Restrict Key Vault network accessHighazure-kv-public-network
Key Vaults with publicNetworkAccess=Enabled expose the management endpoint to the internet. Disable and configure private endpoints for the applications that need vault access.
Use RBAC for Key VaultsMediumazure-kv-rbac-mode
RBAC authorization integrates Key Vault with PIM, conditional access, and central RBAC auditing. Legacy Access Policies are vault-local and can't be governed centrally.
Enable Key Vault purge protectionHighazure-kv-soft-delete
Soft delete retains deleted vaults/keys for 90 days; purge protection blocks force-delete during that window. Together they protect against scenarios where attackers delete keys to lock out the owner.
Retain logs for 90+ daysMediumazure-log-retention
Workspace retention <90 days truncates data before most breach investigation windows. CIS recommends ≥90 days; PCI-DSS and HIPAA require at least 1 year of accessible logs.
Assign the security benchmarkMediumazure-mcsb-assigned
MCSB is Microsoft's canonical Azure security baseline. Assigning it at the subscription or management-group root gives continuous compliance scoring in Defender for Cloud.
Enforce SSL on MySQLHighazure-mysql-ssl-enforce
MySQL Single Server: sslEnforcement should be Enabled. Flexible Server: require_secure_transport server parameter should be ON. Without these, clients can connect in plaintext.
Block database ports from the internetHighazure-nsg-db-ports-internet
Database ports (1433, 3306, 5432, 27017, 6379) open to *, Internet, or 0.0.0.0/0 expose databases to credential-stuffing, unauthenticated access (Redis default), and data exfiltration.
Remove allow-any firewall rulesMediumazure-nsg-overly-permissive
Any-protocol, any-source, any-port Allow rules defeat the principle of least connectivity and provide lateral-movement paths even when not directly internet-exposed.
Block RDP from the internetCriticalazure-nsg-rdp-internet
TCP/3389 open to *, Internet, or 0.0.0.0/0 exposes Windows RDP to the internet. Public RDP is a primary initial-access vector for ransomware.
Block SSH from the internetCriticalazure-nsg-ssh-internet
TCP/22 open to *, Internet, or 0.0.0.0/0 lets the world brute-force SSH. Use Bastion / VPN / IP allowlists instead.
Delete unattached managed disksLowazure-orphaned-disks
Managed disks in the Unattached state are billed at full provisioned capacity while serving no workload, and still contain a complete readable copy of whatever the deleted VM held.
Clean up orphaned network resourcesLowazure-orphaned-network-resources
Network interfaces attached to no VM, public IPs attached to no resource, and network security groups attached to no subnet or NIC. Billed or reserved for nothing, and — in the NSG case — usually a rule set someone believes is in force.
Enforce SSL on PostgreSQLHighazure-postgres-ssl-enforce
Postgres Single Server: sslEnforcement should be Enabled. Flexible Server: require_secure_transport server parameter should be ON. Without these, clients can connect in plaintext.
Public IP inventoryInfoazure-public-ip-inventory
Catalogs every public IP in scope and what resource it's attached to. Never fails — purely informational. These IPs are also fed into the external attack surface (Shodan/crt.sh) as seed inputs.
Set an Entra admin for SQLHighazure-sql-aad-admin
SQL Servers without an AAD admin force clients onto local SQL auth, which doesn't support MFA / conditional access / centralized governance.
Narrow SQL firewall rulesCriticalazure-sql-firewall-broad
Firewall rules permitting 0.0.0.0 → 255.255.255.255 (all IPv4) or 0.0.0.0 → 0.0.0.0 (all Azure services) expose the SQL Server to anything on the internet or the entire Azure fleet.
Encrypt SQL databasesMediumazure-sql-tde
TDE encrypts data at rest with negligible perf impact. On by default for new databases; older ones may still have it off.
Enable SQL threat protectionMediumneeds DefenderForCloud_SQLazure-sql-threat-protection
Defender for SQL detects SQL injection attempts, brute force, and anomalous access patterns. Requires Defender for Cloud's SQL plan.
Block anonymous container accessCriticalazure-storage-anonymous-containers
A container with publicAccess set to Blob or Container is anonymously readable from the internet. Worse than the account-level toggle: this represents an explicit per-container intent to make data public.
Enable blob soft deleteMediumazure-storage-blob-soft-delete
Blob soft delete protects against accidental and malicious deletion. Microsoft recommends ≥7-day retention; longer is better for ransomware recovery.
Restrict storage network accessHighazure-storage-firewall-public
networkAcls.defaultAction = Allow means the storage firewall is open to any network. Set Deny with explicit allowlists or private endpoints.
Require TLS 1.2 on storageHighazure-storage-min-tls-version
minimumTlsVersion below TLS 1.2 lets clients negotiate weaker cipher suites and breaks PCI-DSS / FedRAMP / most enterprise compliance baselines.
Use private endpoints for storageInfoazure-storage-private-endpoint-coverage
Private endpoints let storage accounts be reached only over the VNet, eliminating public network exposure. Coverage <50% indicates substantial public-surface storage; ≥80% is a hygiene target worth pursuing.
Disable public blob accessCriticalazure-storage-public-blob-account
When allowBlobPublicAccess is true, individual containers can opt into anonymous internet access. Disabling at the account level enforces the secure default across every container.
Require HTTPS on storageHighazure-storage-secure-transfer
Storage accounts with supportsHttpsTrafficOnly=false accept plaintext HTTP requests. Forces all REST API calls to use TLS when enabled.
Encrypt VM disksHighazure-vm-disk-encryption
VM disks should be encrypted via encryptionAtHost (preferred) or Azure Disk Encryption (legacy). Default platform encryption protects only the underlying storage; per-VM controls protect against escape scenarios.
Onboard VMs to DefenderMediumneeds DefenderForCloud_Serversazure-vm-mde-coverage
Defender for Endpoint provides EDR on the guest OS. Coverage below 80% indicates onboarding debt; below 50% means significant attack surface is unmonitored. Defender for Cloud auto-provisioning handles most.
Remove public IPs from VMsMediumazure-vm-public-ip
VMs with a directly attached public IP expose the host to the internet. Prefer Azure Bastion (for admin access) or App Gateway / LB with WAF (for app traffic) rather than direct public IP exposure.
Retire unsupported OS versionsHighazure-vm-stale-os
VMs on EOL operating systems receive no vendor security patches. Migrate to a supported image or apply Microsoft Extended Security Updates (paid).