Activity Log & immutable trails
Diagnostic settings to a locked, central store.
You cannot respond to what you cannot see, and you cannot trust evidence an attacker could edit. The foundation of Azure detection and incident response is a complete, centralized, tamper-resistant record of what happened — the Activity Log and resource diagnostics, routed to a store nobody can quietly delete from.
Activity Log, diagnostics, and where they go
The Azure Activity Log records control-plane operations — who created, changed, or deleted a resource, and when — at the subscription level. Resource diagnostic settings capture the data plane: Key Vault access, storage operations, NSG flow logs, firewall logs, and more. Neither is retained usefully by default; you route both, plus Entra sign-in and audit logs, to a Log Analytics workspace for querying and correlation (this is what Sentinel reads), and optionally to immutable storage or an Event Hub. Diagnostic settings are the switch that turns an un-auditable resource into an investigable one.
# Send a Key Vault's diagnostics to the central Log Analytics workspace.az monitor diagnostic-settings create --name to-la \--resource $(az keyvault show -g rg -n app-kv --query id -o tsv) \--workspace $(az monitor log-analytics workspace show -g sec -n central-la --query id -o tsv) \--logs '[{"category":"AuditEvent","enabled":true}]'# Archive the Activity Log to immutable storage (time-based retention + legal# hold) so the trail is write-once — even an owner cannot erase it.az storage container immutability-policy create --account-name auditsa \--container-name activity --period 400 --allow-protected-append-writes true
Segregate and alert on blinding
Send logs to a dedicated logging/security subscription with minimal human access, so a workload compromise cannot reach its own audit record, and make the archive immutable so the trail is write-once. Then alert on the meta-events — a diagnostic setting being removed, a log profile deleted, immutability being weakened — because an attacker who understands the trail tries to blind it first. Enforce the whole pattern with Azure Policy (deployIfNotExists on diagnostic settings) so every new resource is logged automatically rather than depending on someone remembering.