Azure PowerShell获取自定义Policy Exemption时匹配异常及范围问题
问题修复方案
1. 解决筛选逻辑异常问题
你的脚本存在两个导致筛选失效的核心问题:
- 不必要地将豁免项转为JSON再转回对象,这不仅冗余,还可能引入格式解析误差;
- 通过字符串拼接生成JSON,会导致输出的JSON格式无效(无法形成合法数组),甚至意外保留不符合条件的条目。
正确做法是直接对PowerShell对象进行筛选,再将筛选后的对象数组一次性转为JSON:
- 使用
Where-Object在获取豁免项后直接过滤符合条件的条目; - 最后将整个匹配结果数组转为JSON,确保输出格式合法且仅包含匹配项。
2. 获取资源组和资源级别的豁免项
默认的Get-AzPolicyExemption仅返回当前订阅级别及继承的豁免项。若要获取资源组或资源级别的豁免项,需指定订阅范围并添加-IncludeDescendantScopes参数,这样可以一次性获取当前订阅及其所有子范围(资源组、资源)的豁免项,无需逐个遍历资源组和资源。
修正后的脚本
$allSubscriptions = Get-AzSubscription $baseFolder = "C:\source\PowerShell Exemptions Dump\" # 目标文件夹不存在则创建 if (-not (Test-Path -Path $baseFolder)) { New-Item -ItemType Directory -Path $baseFolder | Out-Null } foreach ($sub in $allSubscriptions) { Write-Host "正在处理订阅: $($sub.Name) ($($sub.Id))" # 切换到目标订阅 Set-AzContext -Subscription $sub.Id | Out-Null # 获取当前订阅及所有子范围的豁免项(资源组、资源级别) $allExemptions = Get-AzPolicyExemption -Scope "/subscriptions/$($sub.Id)" -IncludeDescendantScopes # 筛选PolicyAssignmentId包含"abc"的豁免项 $matchingExemptions = $allExemptions | Where-Object { $_.Properties.PolicyAssignmentId -match "abc" } if ($matchingExemptions) { $fileName = Join-Path -Path $baseFolder -ChildPath "$($sub.Name).json" # 将匹配结果转为JSON数组(-Depth避免嵌套属性被截断) $matchingExemptions | ConvertTo-Json -Depth 10 | Out-File -FilePath $fileName Write-Host "已将$($matchingExemptions.Count)条匹配豁免项保存到$fileName" } else { Write-Host "订阅$($sub.Name)中未找到匹配的豁免项" } }
关键改动说明
- 增加文件夹自动创建逻辑,避免因文件夹不存在导致的报错;
- 使用订阅ID切换上下文,比订阅名称更可靠(名称可能重复);
- 通过
-Scope和-IncludeDescendantScopes一次性获取所有层级的豁免项; - 直接对PowerShell对象筛选,确保仅保留符合条件的条目;
- 使用
Join-Path构建文件路径,避免手动拼接路径的潜在错误; - 添加
-Depth 10参数防止嵌套属性被截断(可根据实际情况调整深度); - 增加处理进度提示,方便跟踪脚本运行状态。
注意:如果需要精确匹配而非正则匹配(比如"abc"包含正则特殊字符),可将
-match "abc"替换为-like "*abc*"。
内容的提问来源于stack exchange,提问作者Raymondo
相关产品推荐
相关产品推荐

