Microsoft Sentinel Analytic Rules
cloudbrothers.infoAzure Sentinel RepoToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Azure Security Benchmark Posture Changed

Back
Id0610e72f-ceaf-42d1-879e-952a1bd8d07a
RulenameAzure Security Benchmark Posture Changed
DescriptionThis rule monitors Azure policies aligned with the Azure Security Benchmark regulatory compliance initiative and triggers when policy compliance falls below 70% within a 7-day time window.
SeverityMedium
TacticsDiscovery
TechniquesT1082
Required data connectorsAzureSecurityCenter
KindScheduled
Query frequency7d
Query period7d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/AzureSecurityBenchmark/Analytic Rules/AzureSecurityBenchmarkPostureChanged.yaml
Version1.0.2
Arm template0610e72f-ceaf-42d1-879e-952a1bd8d07a.json
Deploy To Azure
let ComplianceDomainLookup = SecurityRecommendation
| join kind=fullouter (SecurityRegulatoryCompliance | where ComplianceStandard == "Azure-Security-Benchmark") on RecommendationName
| summarize arg_max(TimeGenerated, *) by AssessedResourceId, RecommendationName
| extend ComplianceDomain = iff(ComplianceControl contains "NS.", "Network Security", iff(ComplianceControl contains "IM.", "Identity Management", iff(ComplianceControl contains "PA.", "Privileged Access", iff(ComplianceControl contains "DP.", "Data Protection", iff(ComplianceControl contains "AM.", "Asset Management", iff(ComplianceControl contains "LT.", "Logging & Threat Detection", iff(ComplianceControl contains "IR.", "Incident Response", iff(ComplianceControl contains "PV.", "Posture & Vulnerability Management", iff(ComplianceControl contains "ES.", "Endpoint Security", iff(ComplianceControl contains "BR.", "Backup & Recovery", iff(ComplianceControl startswith "DS.", "DevOps Security", iff(ComplianceControl contains "GS.", "Governance & Strategy", "Other"))))))))))));
SecurityRecommendation
| join kind=fullouter (SecurityRegulatoryCompliance | where ComplianceStandard == "Azure-Security-Benchmark") on RecommendationName
| summarize arg_max(TimeGenerated, *) by AssessedResourceId, RecommendationName
| extend ComplianceDomain = iff(ComplianceControl contains "NS.", "Network Security", iff(ComplianceControl contains "IM.", "Identity Management", iff(ComplianceControl contains "PA.", "Privileged Access", iff(ComplianceControl contains "DP.", "Data Protection", iff(ComplianceControl contains "AM.", "Asset Management", iff(ComplianceControl contains "LT.", "Logging & Threat Detection", iff(ComplianceControl contains "IR.", "Incident Response", iff(ComplianceControl contains "PV.", "Posture & Vulnerability Management", iff(ComplianceControl contains "ES.", "Endpoint Security", iff(ComplianceControl contains "BR.", "Backup & Recovery", iff(ComplianceControl startswith "DS.", "DevOps Security", iff(ComplianceControl contains "GS.", "Governance & Strategy", "Other"))))))))))))
| summarize Failed = countif(RecommendationState == "Unhealthy"), Passed = countif(RecommendationState == "Healthy"), Total = countif(RecommendationState == "Healthy" or RecommendationState == "Unhealthy") by ComplianceDomain
| extend PassedControlsPercentage = iff(Total > 0, (Passed / todouble(Total)) * 100.0, real(null))
| join kind=leftouter (ComplianceDomainLookup) on ComplianceDomain
| project ComplianceDomain, Total, PassedControlsPercentage, Passed, Failed, LastEvaluated = TimeGenerated
| summarize arg_max(LastEvaluated, *) by ComplianceDomain, Total, PassedControlsPercentage, Passed, Failed
| where PassedControlsPercentage < 70
| sort by PassedControlsPercentage asc, Passed desc
| extend RemediationLink = strcat("https://portal.azure.com/#blade/Microsoft_Azure_Security/SecurityMenuBlade/22")
entityMappings:
- entityType: URL
  fieldMappings:
  - identifier: Url
    columnName: RemediationLink
tactics:
- Discovery
requiredDataConnectors:
- dataTypes:
  - SecurityRecommendation
  - SecurityRegulatoryCompliance
  connectorId: AzureSecurityCenter
alertDetailsOverride:
  alertDisplayNameFormat: Azure Security Benchmark posture below threshold for {{ComplianceDomain}}
id: 0610e72f-ceaf-42d1-879e-952a1bd8d07a
severity: Medium
customDetails:
  TotalControls: Total
  PassedControls: Passed
  FailedControls: Failed
  ComplianceDomain: ComplianceDomain
query: |
  let ComplianceDomainLookup = SecurityRecommendation
  | join kind=fullouter (SecurityRegulatoryCompliance | where ComplianceStandard == "Azure-Security-Benchmark") on RecommendationName
  | summarize arg_max(TimeGenerated, *) by AssessedResourceId, RecommendationName
  | extend ComplianceDomain = iff(ComplianceControl contains "NS.", "Network Security", iff(ComplianceControl contains "IM.", "Identity Management", iff(ComplianceControl contains "PA.", "Privileged Access", iff(ComplianceControl contains "DP.", "Data Protection", iff(ComplianceControl contains "AM.", "Asset Management", iff(ComplianceControl contains "LT.", "Logging & Threat Detection", iff(ComplianceControl contains "IR.", "Incident Response", iff(ComplianceControl contains "PV.", "Posture & Vulnerability Management", iff(ComplianceControl contains "ES.", "Endpoint Security", iff(ComplianceControl contains "BR.", "Backup & Recovery", iff(ComplianceControl startswith "DS.", "DevOps Security", iff(ComplianceControl contains "GS.", "Governance & Strategy", "Other"))))))))))));
  SecurityRecommendation
  | join kind=fullouter (SecurityRegulatoryCompliance | where ComplianceStandard == "Azure-Security-Benchmark") on RecommendationName
  | summarize arg_max(TimeGenerated, *) by AssessedResourceId, RecommendationName
  | extend ComplianceDomain = iff(ComplianceControl contains "NS.", "Network Security", iff(ComplianceControl contains "IM.", "Identity Management", iff(ComplianceControl contains "PA.", "Privileged Access", iff(ComplianceControl contains "DP.", "Data Protection", iff(ComplianceControl contains "AM.", "Asset Management", iff(ComplianceControl contains "LT.", "Logging & Threat Detection", iff(ComplianceControl contains "IR.", "Incident Response", iff(ComplianceControl contains "PV.", "Posture & Vulnerability Management", iff(ComplianceControl contains "ES.", "Endpoint Security", iff(ComplianceControl contains "BR.", "Backup & Recovery", iff(ComplianceControl startswith "DS.", "DevOps Security", iff(ComplianceControl contains "GS.", "Governance & Strategy", "Other"))))))))))))
  | summarize Failed = countif(RecommendationState == "Unhealthy"), Passed = countif(RecommendationState == "Healthy"), Total = countif(RecommendationState == "Healthy" or RecommendationState == "Unhealthy") by ComplianceDomain
  | extend PassedControlsPercentage = iff(Total > 0, (Passed / todouble(Total)) * 100.0, real(null))
  | join kind=leftouter (ComplianceDomainLookup) on ComplianceDomain
  | project ComplianceDomain, Total, PassedControlsPercentage, Passed, Failed, LastEvaluated = TimeGenerated
  | summarize arg_max(LastEvaluated, *) by ComplianceDomain, Total, PassedControlsPercentage, Passed, Failed
  | where PassedControlsPercentage < 70
  | sort by PassedControlsPercentage asc, Passed desc
  | extend RemediationLink = strcat("https://portal.azure.com/#blade/Microsoft_Azure_Security/SecurityMenuBlade/22")  
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/AzureSecurityBenchmark/Analytic Rules/AzureSecurityBenchmarkPostureChanged.yaml
kind: Scheduled
queryPeriod: 7d
version: 1.0.2
name: Azure Security Benchmark Posture Changed
queryFrequency: 7d
triggerThreshold: 0
relevantTechniques:
- T1082
description: This rule monitors Azure policies aligned with the Azure Security Benchmark regulatory compliance initiative and triggers when policy compliance falls below 70% within a 7-day time window.
triggerOperator: gt