Sample rules
Azure Resource Group Deleted by Unusual Principal
- source: elastic
- technicques:
- T1485
- T1489
- T1490
- T1529
- T1562
Description
Identifies Azure resource group deletions by a principal that has not performed this operation in the prior 7 days. Deletion of a resource group is permanent and removes all resources in the group. This rule uses an ES|QL first-seen (new terms) approach keyed on the acting principal so routine infrastructure-as-code teardown is suppressed after the first occurrence, while still surfacing first-time or unusual identities performing the delete.
Detection logic
FROM logs-azure.activitylogs-*, filebeat-*
| WHERE data_stream.dataset == "azure.activitylogs"
AND event.action == "MICROSOFT.RESOURCES/SUBSCRIPTIONS/RESOURCEGROUPS/DELETE"
AND event.outcome IN ("success", "Success")
AND azure.activitylogs.identity.authorization.evidence.principal_id IS NOT NULL
| STATS Esql.first_time_seen = MIN(@timestamp),
Esql.last_time_seen = MAX(@timestamp),
Esql.event_count = COUNT(*),
Esql.resource_group_values = VALUES(azure.resource.group),
Esql.resource_name_values = VALUES(azure.resource.name),
Esql.resource_id_values = VALUES(azure.resource.id),
Esql.principal_type_values = VALUES(azure.activitylogs.identity.authorization.evidence.principal_type),
Esql.initiated_by_user_values = VALUES(azure.activitylogs.identity.claims_initiated_by_user.name),
Esql.appid_values = VALUES(azure.activitylogs.identity.claims.appid),
Esql.session_id_values = VALUES(azure.activitylogs.identity.claims.sid),
Esql.unique_token_id_values = VALUES(azure.activitylogs.identity.claims.uti),
Esql.correlation_id_values = VALUES(azure.correlation_id),
Esql.role_values = VALUES(azure.activitylogs.identity.authorization.evidence.role),
Esql.role_assignment_id_values = VALUES(azure.activitylogs.identity.authorization.evidence.role_assignment_id),
Esql.source_ip_values = VALUES(source.ip),
Esql.source_country_values = VALUES(source.geo.country_name),
Esql.source_as_number_values = VALUES(source.`as`.number),
Esql.subscription_id_values = VALUES(azure.subscription_id)
BY azure.activitylogs.identity.authorization.evidence.principal_id
// new terms emulation: fire when this principal's first_seen falls in the current interval
// (schedule + ingest-lag buffer), i.e. it was absent from the rest of the 7-day window
| EVAL Esql.recent_minutes = DATE_DIFF("minute", Esql.first_time_seen, NOW())
| WHERE Esql.recent_minutes <= 10
| KEEP azure.*, Esql.*
Azure Diagnostic Settings Deleted
- source: elastic
- technicques:
- T1562
Description
Identifies deletion of Azure diagnostic settings for a resource group that has not had this operation in the prior 7 days. Diagnostic settings send platform logs and metrics to Log Analytics, Event Hubs, or storage; removing them blinds monitoring and detection. This rule uses an ES|QL first-seen (new terms) approach keyed on the resource group so groups that constantly churn logging configuration are suppressed after the first occurrence, while a newly seen group still alerts.
Detection logic
FROM logs-azure.activitylogs-*
| WHERE data_stream.dataset == "azure.activitylogs"
AND event.action == "MICROSOFT.INSIGHTS/DIAGNOSTICSETTINGS/DELETE"
AND event.outcome IN ("success", "Success")
AND azure.resource.group IS NOT NULL
| STATS Esql.first_time_seen = MIN(@timestamp),
Esql.last_time_seen = MAX(@timestamp),
Esql.event_count = COUNT(*),
Esql.event_action_values = VALUES(event.action),
Esql.resource_name_values = VALUES(azure.resource.name),
Esql.resource_id_values = VALUES(azure.resource.id),
Esql.resource_provider_values = VALUES(azure.resource.provider),
Esql.principal_id_values = VALUES(azure.activitylogs.identity.authorization.evidence.principal_id),
Esql.principal_type_values = VALUES(azure.activitylogs.identity.authorization.evidence.principal_type),
Esql.initiated_by_user_values = VALUES(azure.activitylogs.identity.claims_initiated_by_user.name),
Esql.appid_values = VALUES(azure.activitylogs.identity.claims.appid),
Esql.session_id_values = VALUES(azure.activitylogs.identity.claims.sid),
Esql.unique_token_id_values = VALUES(azure.activitylogs.identity.claims.uti),
Esql.correlation_id_values = VALUES(azure.correlation_id),
Esql.role_values = VALUES(azure.activitylogs.identity.authorization.evidence.role),
Esql.role_assignment_id_values = VALUES(azure.activitylogs.identity.authorization.evidence.role_assignment_id),
Esql.role_assignment_scope_values = VALUES(azure.activitylogs.identity.authorization.evidence.role_assignment_scope),
Esql.source_ip_values = VALUES(source.ip),
Esql.source_country_values = VALUES(source.geo.country_name),
Esql.source_as_number_values = VALUES(source.`as`.number),
Esql.subscription_id_values = VALUES(azure.subscription_id)
BY azure.resource.group
// new terms emulation: fire when this resource group's first_seen falls in the current interval
// (schedule + ingest-lag buffer), i.e. it was absent from the rest of the 7-day window
| EVAL Esql.recent_minutes = DATE_DIFF("minute", Esql.first_time_seen, NOW())
| WHERE Esql.recent_minutes <= 10
| KEEP azure.*, Esql.*