如何修改PowerShell脚本跨多订阅获取指定策略的不合规资源列表
问题
希望通过邮件获取跨多个订阅的某一指定Azure策略对应的不合规资源列表,但现有PowerShell脚本仅能获取单个订阅的不合规资源。已完成以下操作:
- 配置Automation Account(自动化账户)
- 创建PowerShell (PS) Runbook(运行手册)并执行PS脚本
- 配置Logic App(逻辑应用)以触发邮件发送不合规资源列表
原脚本如下:
Connect-AzAccount -Identity $policyDefinitionName = "policy-XXXXX" $complianceState = Get-AzPolicyState -PolicyDefinitionName $policyDefinitionName $nonCompliantResources = $complianceState | Where-Object { $_.ComplianceState -eq "NonCompliant" } $csvString = $nonCompliantResources | Select-Object @{Name="SubscriptionName";Expression={(Get-AzSubscription -SubscriptionId $_.SubscriptionId).Name}}, @{Name="ResourceGroup";Expression={($_.ResourceId -split '/')[4]}}, @{Name="ResourceName";Expression={($_.ResourceId -split '/')[8]}}, PolicyDefinitionName | ConvertTo-Csv -NoTypeInformation | Out-String return $csvString
解决方案
要实现跨多个订阅获取不合规资源,需要遍历目标订阅集合,逐个切换订阅上下文后查询合规状态,最后汇总结果。修改后的脚本如下:
# 以托管身份连接Azure Connect-AzAccount -Identity # 指定目标策略名称 $policyDefinitionName = "policy-XXXXX" # 定义需要查询的订阅ID列表(可根据需求调整,也可通过Get-AzSubscription批量获取有权限的订阅) $targetSubscriptions = @( "订阅ID1", "订阅ID2", "订阅ID3" ) # 初始化空数组存储所有订阅的不合规资源 $allNonCompliantResources = @() foreach ($subId in $targetSubscriptions) { try { # 切换到当前订阅上下文 Set-AzContext -SubscriptionId $subId -ErrorAction Stop Write-Output "正在查询订阅: $subId" # 获取当前订阅下指定策略的合规状态 $complianceState = Get-AzPolicyState -PolicyDefinitionName $policyDefinitionName -ErrorAction Stop # 筛选不合规资源并添加到汇总数组 $nonCompliant = $complianceState | Where-Object { $_.ComplianceState -eq "NonCompliant" } if ($nonCompliant) { $allNonCompliantResources += $nonCompliant } } catch { Write-Error "查询订阅 $subId 时出错: $_" continue } } # 转换为CSV格式,优化订阅名称获取逻辑(提前获取所有订阅信息避免重复调用API) $subscriptionsLookup = Get-AzSubscription -SubscriptionId $targetSubscriptions | Select-Object SubscriptionId, Name $csvString = $allNonCompliantResources | Select-Object ` @{Name="SubscriptionName";Expression={($subscriptionsLookup | Where-Object {$_.SubscriptionId -eq $_.SubscriptionId}).Name}}, @{Name="ResourceGroup";Expression={($_.ResourceId -split '/')[4]}}, @{Name="ResourceName";Expression={($_.ResourceId -split '/')[8]}}, PolicyDefinitionName | ConvertTo-Csv -NoTypeInformation | Out-String return $csvString
关键修改点
- 遍历目标订阅:添加
$targetSubscriptions数组定义需要查询的订阅,通过foreach循环逐个处理 - 上下文切换:使用
Set-AzContext切换到每个订阅,确保Get-AzPolicyState查询对应订阅的资源 - 结果汇总:初始化空数组
$allNonCompliantResources,将每个订阅的不合规资源统一存入 - 性能优化:提前批量获取订阅名称并构建查找表,避免在
Select-Object中重复调用Get-AzSubscription,减少API请求次数 - 错误容错:添加
try/catch块处理单个订阅查询失败的情况,保证脚本不会因某一个订阅出错而中断
内容的提问来源于stack exchange,提问作者Manju S
相关产品推荐
相关产品推荐

