感谢 iRon 本周早些时候通过此 question 提供的帮助,他为我目前正在进行的一项工作提供了巨大帮助。
总之,我们有一个 Azure CICD 管道来部署策略。我们有一个包含 200 多个 JSON 策略文件的文件夹,CICD 流程将它们全部放在 1 个 JSON 文件中并将它们部署出来。我们发现的最初问题是参数需要一个额外的前导“[”,否则该过程将失败。这在 article 中得到了强调。 (如果您搜索 [[)。
无论如何,解决问题。 iRons 支持帮了很大的忙,但在 200 个文件中,我们得到了一些文件,其中我们收到以下消息:
Cannot bind argument to parameter 'FilterScript' because it is null.
代码:
iRon 提供的功能:
function Get-Node {
[CmdletBinding()][OutputType([Object[]])] param(
[ScriptBlock]$Where,
[Parameter(ValueFromPipeLine = $True, Mandatory = $True)]$InputObject,
[Int]$Depth = 10
)
process {
if ($_ -isnot [String] -and $Depth -gt 0) {
if ($_ -is [Collections.IDictionary]) {
if (& $Where) {$_}
$_.get_Values() | Get-Node -Where $Where -Depth ($Depth -1)
}
elseif ($_ -is [Collections.IEnumerable]) {
for ($i = 0; $i -lt $_.get_Count(); $i++) { $_[$i] | Get-Node -Where $Where -Depth ($Depth -1) }
}
elseif ($Nodes = $_.PSObject.Properties.Where{$_.MemberType -eq 'NoteProperty'}) {
$Nodes.ForEach{
if (& $Where) { $_ }
$_.Value | Get-Node -Where $Where -Depth ($Depth -1)
}
}
}
}
}
我调用上述函数的位置(此代码位于每个文件的循环中):
$policyRule = @("notIn", "in", "value", "equals", "field", "effect", "like", "greaterOrEquals", "name", "resourceGroupName", "resourceGroup", "location", "storageName", "uniqueStorage", "storageContainerPath", "storageAccountAccessKey", "dependsOn", "targetResourceId", "storageId", "enabled")
if ($content.properties -ne $null){
# Loop all the Policy Rule names for fix the values within them
foreach ($rule in $policyRule){
$Node = $content.properties.policyRule | Get-Node -Where {$_.name -eq $rule -and $_.value -Match "^\[\w+" -and $_.value -ne ""}
$Node | ForEach-Object {$_.Value = '[' + $_.Value}
}
}
有效的 JSON 文件:
{
"name": "POLICY-001",
"properties": {
"displayName": "Allowed Locations for Resources",
"policyType": "Custom",
"mode": "Indexed",
"description": "This policy enables you to restrict the locations your organization can specify when deploying resources. Use to enforce your geo-compliance requirements. Excludes resource groups, Microsoft.AzureActiveDirectory/b2cDirectories, and resources that use the 'global' region.",
"metadata": {
"version": "1.0.0",
"category": "General"
},
"parameters": {
"listOfAllowedLocations": {
"type": "Array",
"metadata": {
"description": "The list of locations that can be specified when deploying resources.",
"strongType": "location",
"displayName": "Allowed locations"
},
"allowedValues": [
"uksouth",
"ukwest"
],
"defaultValue": [
"uksouth",
"ukwest"
]
}
},
"policyRule": {
"if": {
"allOf": [
{
"field": "location",
"notIn": "[parameters('listOfAllowedLocations')]"
},
{
"field": "location",
"notEquals": "global"
},
{
"field": "type",
"notEquals": "Microsoft.Resources/subscriptions/resourceGroups"
},
{
"field": "type",
"notEquals": "Microsoft.Resources/b2cDirectories"
}
]
},
"then": {
"effect": "deny"
}
}
},
"excludedScopes": [
],
"nonComplianceMessage": "only allow resources to be deployed from UK South and UK West"
}
失败的一个:
{
"Name": "Policy-106",
"Properties": {
"Description": "This policy automatically deploys and enable diagnostic settings to Log Analytics",
"DisplayName": "Apply diagnostic settings for Log Analytics Workspaces",
"Mode": "Indexed",
"policyType": "Custom",
"Metadata": {
"version": "1.0",
"category": "Monitoring"
},
"Parameters": {
"diagnosticsSettingNameToUse": {
"type": "string",
"metadata": {
"displayName": "Apply diagnostic settings for Log Analytics Workspaces - Setting name",
"description": "Name of the policy for the diagnostics settings."
},
"defaultValue": "setViaPolicy"
},
"logAnalytics": {
"type": "string",
"metadata": {
"displayName": "Apply diagnostic settings for Log Analytics Workspaces - Log Analytics workspace",
"description": "Select the Log Analytics workspace from dropdown list",
"strongType": "omsWorkspace",
"assignPermissions": true
},
"defaultValue": "/subscriptions/......"
}
},
"PolicyRule": {
"if": {
"field": "type",
"equals": "Microsoft.OperationalInsights/Workspaces"
},
"then": {
"effect": "deployIfNotExists",
"details": {
"type": "Microsoft.Insights/diagnosticSettings",
"roleDefinitionIds": [
"/providers/Microsoft.Authorization/roleDefinitions/123"
],
"existenceCondition": {
"allOf": [
{
"field": "Microsoft.Insights/diagnosticSettings/logs.enabled",
"equals": "True"
},
{
"field": "Microsoft.Insights/diagnosticSettings/metrics.enabled",
"equals": "True"
},
{
"field": "Microsoft.Insights/diagnosticSettings/workspaceId",
"matchInsensitively": "[parameters('logAnalytics')]"
}
]
},
"deployment": {
"properties": {
"mode": "incremental",
"template": {
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"diagnosticsSettingNameToUse": {
"type": "string"
},
"resourceName": {
"type": "string"
},
"logAnalytics": {
"type": "string"
},
"location": {
"type": "string"
}
},
"variables": {},
"resources": [
{
"type": "Microsoft.OperationalInsights/Workspaces/providers/diagnosticSettings",
"apiVersion": "2017-05-01-preview",
"name": "[concat(parameters('resourceName'), '/', 'Microsoft.Insights/', parameters('diagnosticsSettingNameToUse'))]",
"location": "[parameters('location')]",
"dependsOn": [],
"properties": {
"workspaceId": "[parameters('logAnalytics')]",
"metrics": [
{
"category": "AllMetrics",
"timeGrain": null,
"enabled": true,
"retentionPolicy": {
"enabled": false,
"days": 0
}
}
],
"logs": [
{
"category": "Audit",
"enabled": true
}
]
}
}
],
"outputs": {}
},
"parameters": {
"diagnosticsSettingNameToUse": {
"value": "[parameters('diagnosticsSettingNameToUse')]"
},
"logAnalytics": {
"value": "[parameters('logAnalytics')]"
},
"location": {
"value": "[field('location')]"
},
"resourceName": {
"value": "[field('name')]"
}
}
}
}
}
}
}
},
"excludedScopes": [
],
"nonComplianceMessage": ""
}
正如我在原来的帖子中提到的,我的 PowerShell 充其量只是基本的,如果有任何支持,我们将不胜感激。
最佳答案
处理失败的 JSON 文件包含 null
值,当通过 ConvertFrom-Json
将 JSON 文件转换为对象图时,这些值会在 PowerShell 中变成 $null
值.
问题中所示的 Get-Node
函数不支持将 $null
绑定(bind)到其管道绑定(bind) -InputObject
参数,每当以下语句中 $_.Value
恰好为 $null
时,就会导致错误:
$_.Value | Get-Node -Where $Where -Depth ($Depth - 1)
解决方案很简单:通过添加 [AllowNull()]
允许 -InputObject
参数接受 $null
属性为 original function :
function Get-Node {
[CmdletBinding()][OutputType([Object[]])] param(
[ScriptBlock]$Where,
[AllowNull()] # <- now $null may be passed too
[Parameter(ValueFromPipeLine = $True, Mandatory = $True)]$InputObject,
[Int]$Depth = 10
)
process {
if ($_ -isnot [String] -and $Depth -gt 0) {
if ($_ -is [Collections.IDictionary]) {
if (& $Where) { $_ }
$_.get_Values() | Get-Node -Where $Where -Depth ($Depth - 1)
}
elseif ($_ -is [Collections.IEnumerable]) {
for ($i = 0; $i -lt $_.get_Count(); $i++) { $_[$i] | Get-Node -Where $Where -Depth ($Depth - 1) }
}
elseif ($Nodes = $_.PSObject.Properties.Where{ $_.MemberType -eq 'NoteProperty' }) {
$Nodes.ForEach{
if (& $Where) { $_ }
$_.Value | Get-Node -Where $Where -Depth ($Depth - 1)
}
}
}
}
}
关于某些 JSON 文件出现 PowerShell FilterScript 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74510152/