关于 azure-monitor-audit
azure-monitor-audit 是面向团队的 Azure 活动审计技能,用于合规、安全和运维可见性。内容涵盖集中式日志收集、诊断策略强制执行、KQL 调查、告警和合规仪表板。
主要功能
- 01集中收集活动日志
- 02配置资源诊断设置
- 03通过 Azure Policy 强制执行
- 04使用 KQL 调查安全事件
- 05安全告警与合规仪表板
适用场景
- 01集中管理多个订阅的审计日志
- 02调查可疑的 Azure 活动
- 03为新资源强制配置诊断
- 04整理合规证据并构建仪表板
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ bagelhole/ devops-security-agent-skills --skill azure-monitor-audit安装后在 Claude Code 中输入/azure-monitor-audit确认已加载。
详细介绍
Azure Monitor 审计
使用 Monitor、Activity Logs 和 Log Analytics 审计 Azure 活动,满足合规要求,并提升安全性和运营可见性。
适用场景
- 在 Azure 订阅中启用集中式审计日志记录
- 满足 SOC 2、HIPAA、PCI DSS 或 ISO 27001 合规要求
- 调查 Azure 中的安全事件或未授权活动
- 针对管理和安全事件设置警报
- 构建合规仪表板并自动收集证据
创建 Log Analytics 工作区
# Create resource group for audit resources
az group create \
--name rg-audit \
--location eastus
# Create Log Analytics workspace
az monitor log-analytics workspace create \
--resource-group rg-audit \
--workspace-name audit-workspace \
--location eastus \
--retention-time 365 \
--sku PerGB2018
# Get workspace ID for later use
WORKSPACE_ID=$(az monitor log-analytics workspace show \
--resource-group rg-audit \
--workspace-name audit-workspace \
--query id -o tsv)
# Enable audit solutions
az monitor log-analytics solution create \
--resource-group rg-audit \
--solution-type SecurityCenterFree \
--workspace audit-workspace
配置订阅 Activity Log 的诊断设置
# Export subscription activity log to Log Analytics
az monitor diagnostic-settings subscription create \
--name activity-log-to-workspace \
--location global \
--workspace "$WORKSPACE_ID" \
--logs '[
{"category": "Administrative", "enabled": true},
{"category": "Security", "enabled": true},
{"category": "ServiceHealth", "enabled": true},
{"category": "Alert", "enabled": true},
{"category": "Recommendation", "enabled": true},
{"category": "Policy", "enabled": true},
{"category": "Autoscale", "enabled": true},
{"category": "ResourceHealth", "enabled": true}
]'
# Also archive to storage account for long-term retention
az storage account create \
--name auditlogsarchive \
--resource-group rg-audit \
--location eastus \
--sku Standard_GRS \
--kind StorageV2 \
--min-tls-version TLS1_2 \
--allow-blob-public-access false
az monitor diagnostic-settings subscription create \
--name activity-log-to-storage \
--location global \
--storage-account /subscriptions/{sub}/resourceGroups/rg-audit/providers/Microsoft.Storage/storageAccounts/auditlogsarchive \
--logs '[
{"category": "Administrative", "enabled": true, "retentionPolicy": {"enabled": true, "days": 2555}},
{"category": "Security", "enabled": true, "retentionPolicy": {"enabled": true, "days": 2555}}
]'
资源级诊断设置
# Enable diagnostics for Azure Key Vault
az monitor diagnostic-settings create \
--name keyvault-audit \
--resource /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.KeyVault/vaults/{vault} \
--workspace "$WORKSPACE_ID" \
--logs '[
{"category": "AuditEvent", "enabled": true, "retentionPolicy": {"enabled": true, "days": 365}},
{"category": "AzurePolicyEvaluationDetails", "enabled": true}
]' \
--metrics '[
{"category": "AllMetrics", "enabled": true}
]'
# Enable diagnostics for Azure SQL Database
az monitor diagnostic-settings create \
--name sql-audit \
--resource /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Sql/servers/{server}/databases/{db} \
--workspace "$WORKSPACE_ID" \
--logs '[
{"category": "SQLSecurityAuditEvents", "enabled": true},
{"category": "SQLInsights", "enabled": true},
{"category": "AutomaticTuning", "enabled": true}
]'
# Enable diagnostics for Azure App Service
az monitor diagnostic-settings create \
--name appservice-audit \
--resource /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Web/sites/{app} \
--workspace "$WORKSPACE_ID" \
--logs '[
{"category": "AppServiceHTTPLogs", "enabled": true},
{"category": "AppServiceAuditLogs", "enabled": true},
{"category": "AppServiceIPSecAuditLogs", "enabled": true},
{"category": "AppServicePlatformLogs", "enabled": true}
]'
# Enable diagnostics for Network Security Groups
az monitor diagnostic-settings create \
--name nsg-flow-logs \
--resource /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Network/networkSecurityGroups/{nsg} \
--workspace "$WORKSPACE_ID" \
--logs '[
{"category": "NetworkSecurityGroupEvent", "enabled": true},
{"category": "NetworkSecurityGroupRuleCounter", "enabled": true}
]'
使用 Azure Policy 强制实施诊断设置
# Assign built-in policy to require diagnostic settings on Key Vaults
az policy assignment create \
--name require-kv-diagnostics \
--policy "951af2fa-529b-416e-ab6e-066fd85ac459" \
--scope /subscriptions/{sub} \
--params '{
"logAnalytics": {"value": "'$WORKSPACE_ID'"},
"effect": {"value": "DeployIfNotExists"}
}'
# Assign policy to require diagnostic settings on SQL databases
az policy assignment create \
--name require-sql-diagnostics \
--policy "b79fa14e-238a-4c2d-b376-442ce508fc84" \
--scope /subscriptions/{sub} \
--params '{
"logAnalyticsWorkspaceId": {"value": "'$WORKSPACE_ID'"}
}'
用于安全调查的 KQL 查询
// Failed sign-in attempts with location and device details
SigninLogs
| where TimeGenerated > ago(24h)
| where ResultType != "0"
| summarize FailureCount = count(),
DistinctIPs = dcount(IPAddress),
Locations = make_set(LocationDetails.city)
by UserPrincipalName, ResultDescription, AppDisplayName
| where FailureCount > 5
| order by FailureCount desc
// Successful sign-ins from unusual locations
SigninLogs
| where TimeGenerated > ago(7d)
| where ResultType == "0"
| extend City = tostring(LocationDetails.city),
Country = tostring(LocationDetails.countryOrRegion)
| summarize LoginCount = count(),
Cities = make_set(City),
Countries = make_set(Country)
by UserPrincipalName
| where array_length(Countries) > 2
// Risky sign-ins requiring investigation
SigninLogs
| where TimeGenerated > ago(7d)
| where RiskLevelDuringSignIn in ("medium", "high")
| project TimeGenerated, UserPrincipalName, IPAddress,
LocationDetails.city, RiskLevelDuringSignIn,
RiskEventTypes_V2, AppDisplayName
| order by TimeGenerated desc
// Administrative operations across subscriptions
AzureActivity
| where TimeGenerated > ago(24h)
| where CategoryValue == "Administrative"
| where OperationNameValue contains "write" or OperationNameValue contains "delete"
| where ActivityStatusValue == "Success"
| project TimeGenerated, Caller, OperationNameValue,
ResourceGroup, Resource, SubscriptionId
| order by TimeGenerated desc
// Key Vault access patterns
AzureDiagnostics
| where ResourceType == "VAULTS"
| where TimeGenerated > ago(24h)
| where OperationName in ("SecretGet", "SecretSet", "SecretDelete",
"KeySign", "KeyDecrypt", "CertificateGet")
| project TimeGenerated, CallerIPAddress, identity_claim_upn_s,
OperationName, id_s, ResultType
| order by TimeGenerated desc
// Detect changes to Network Security Groups
AzureActivity
| where TimeGenerated > ago(7d)
| where OperationNameValue has_any ("securityRules/write", "securityRules/delete",
"networkSecurityGroups/write")
| where ActivityStatusValue == "Success"
| project TimeGenerated, Caller, OperationNameValue,
ResourceGroup, Properties
| order by TimeGenerated desc
// Azure Policy compliance drift
PolicyInsights
| where TimeGenerated > ago(7d)
| where ComplianceState == "NonCompliant"
| summarize NonCompliantCount = count() by PolicyDefinitionName, ResourceType
| order by NonCompliantCount desc
// Privileged role assignments (PIM)
AuditLogs
| where TimeGenerated > ago(30d)
| where OperationName has_any ("Add member to role", "Add eligible member to role")
| extend RoleName = tostring(TargetResources[0].displayName),
AssignedUser = tostring(TargetResources[2].displayName),
AssignedBy = InitiatedBy.user.userPrincipalName
| project TimeGenerated, AssignedBy, AssignedUser, RoleName, OperationName
| order by TimeGenerated desc
警报规则
# Create action group for security notifications
az monitor action-group create \
--resource-group rg-audit \
--name security-team \
--short-name SecTeam \
--email-receivers name=SecurityLead [email protected] \
--webhook-receivers name=PagerDuty uri=https://events.pagerduty.com/integration/{key}/enqueue
# Alert on multiple failed sign-ins (brute force detection)
az monitor scheduled-query create \
--resource-group rg-audit \
--name brute-force-detection \
--scopes "$WORKSPACE_ID" \
--condition "count > 10" \
--condition-query "SigninLogs | where ResultType != '0' | summarize count() by UserPrincipalName, bin(TimeGenerated, 5m) | where count_ > 10" \
--evaluation-frequency 5m \
--window-size 5m \
--severity 2 \
--action-groups /subscriptions/{sub}/resourceGroups/rg-audit/providers/Microsoft.Insights/actionGroups/security-team
# Alert on Key Vault secret access outside business hours
az monitor scheduled-query create \
--resource-group rg-audit \
--name keyvault-offhours-access \
--scopes "$WORKSPACE_ID" \
--condition "count > 0" \
--condition-query "AzureDiagnostics | where ResourceType == 'VAULTS' | where OperationName in ('SecretGet','SecretList') | where hourofday(TimeGenerated) < 6 or hourofday(TimeGenerated) > 22" \
--evaluation-frequency 15m \
--window-size 15m \
--severity 3 \
--action-groups /subscriptions/{sub}/resourceGroups/rg-audit/providers/Microsoft.Insights/actionGroups/security-team
# Alert on subscription-level administrative changes
az monitor activity-log alert create \
--resource-group rg-audit \
--name critical-admin-changes \
--condition category=Administrative and operationName="Microsoft.Authorization/roleAssignments/write" \
--action-group /subscriptions/{sub}/resourceGroups/rg-audit/providers/Microsoft.Insights/actionGroups/security-team \
--description "Alert on new role assignments"
合规仪表板工作簿(ARM 模板片段)
{
"type": "Microsoft.Insights/workbooks",
"apiVersion": "2022-04-01",
"name": "[guid('compliance-dashboard')]",
"location": "[resourceGroup().location]",
"kind": "shared",
"properties": {
"displayName": "Compliance Audit Dashboard",
"serializedData": "{\"version\":\"Notebook/1.0\",\"items\":[{\"type\":1,\"content\":{\"json\":\"## Compliance Audit Dashboard\"},\"name\":\"title\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SigninLogs | where TimeGenerated > ago(24h) | where ResultType != '0' | summarize count() by bin(TimeGenerated, 1h)\",\"size\":0,\"title\":\"Failed Sign-ins (24h)\",\"timeContext\":{\"durationMs\":86400000},\"queryType\":0},\"name\":\"failed-signins\"}]}"
}
}
设置检查清单
azure_monitor_checklist:
workspace_setup:
- [ ] Log Analytics workspace created in appropriate region
- [ ] Retention period configured (minimum per compliance framework)
- [ ] Daily cap configured to prevent cost overruns
- [ ] RBAC permissions set (Log Analytics Reader for auditors)
diagnostic_settings:
- [ ] Subscription activity log exported to Log Analytics
- [ ] Subscription activity log archived to storage account
- [ ] Key Vault audit events enabled
- [ ] Azure SQL audit logging enabled
- [ ] NSG flow logs enabled
- [ ] App Service audit logs enabled
- [ ] Azure AD sign-in and audit logs connected
policy_enforcement:
- [ ] Azure Policy assigned to enforce diagnostic settings
- [ ] DeployIfNotExists policies for critical resource types
- [ ] Compliance state monitored via Policy Insights
alerting:
- [ ] Action groups configured for security and operations teams
- [ ] Alert on brute force sign-in attempts
- [ ] Alert on privileged role assignments
- [ ] Alert on Key Vault sensitive operations
- [ ] Alert on NSG rule changes
- [ ] Alert on resource deletions in production
reporting:
- [ ] Compliance workbook deployed
- [ ] Weekly automated query reports exported
- [ ] Quarterly access review queries prepared
- [ ] Evidence collection queries documented for auditors
最佳实践
- 将所有审计数据集中到每个租户的单个 Log Analytics 工作区
- 将日志存档到不可变存储中,以满足长期保留和合规要求
- 使用 Azure Policy 和 DeployIfNotExists,在新资源上强制实施诊断设置
- 为常见的调查和合规场景创建已保存的 KQL 查询
- 为安全关键事件设置计划查询警报
- 为审计人员分配 Log Analytics Reader 角色,而不授予更广泛的访问权限
- 监控诊断设置管道本身,及时发现交付失败
- 使用工作簿构建与利益相关者共享的可视化合规仪表板
- 按计划导出查询结果,用于合规证据材料
- 将运营警报与安全警报分开,避免警报疲劳
评论
支持 Markdown