Closed glsutter closed 1 year ago
Did EPAC deploy the custom Policy?
Yes, did you use "policyDefinitionName " in the Policy set
{
"policyDefinitionReferenceId": "require-nsg-on-subnet",
"policyDefinitionName": "require-nsg-on-subnet",
"parameters": {
"effect": {
"value": "[parameters('effect- require-nsg-on-subnet')]"
}
}
},
If no, same problem
I was using policyDefinitionId, but I changed it to policyDefinitionName. But the problem is still there. Doing some debugging to see if it's actually being found and an entry created in the PowerShell.
YOU MUST USE "policyDefinitionName" for custom Policies when assigning them or including them in a Policy SET (Initiative). The below is correct:
The second line captures legacy use of "policyDefinitionName" for built-in Policy Definitions. The correct approach is to use "policyDefinitionId" for built-ins
Heinrich Gantenbein (he/him) Senior Principal Consultant Cybersecurity Microsoft Security Enterprise Services
From: glsutter @.> Sent: Thursday, September 7, 2023 2:44 PM To: Azure/enterprise-azure-policy-as-code @.> Cc: Comment @.>; Subscribed @.> Subject: Re: [Azure/enterprise-azure-policy-as-code] Invalid Policy entry referenced in Policy Set (Issue #350)
I may have found the problem, but I'm not sure why it's occurring. In Build-PolicySetPlan.ps1, policyDefinitionScopes looks a little strange:
Thanks, Heinrich. That was the problem. For the two custom policies, I was using a full policy definition resource id instead of the simple name.
I am creating a policy set (legacy-network-guardrails) that includes two policies:
But Build-DeploymentPlan keeps throwing thw error below.
I can see earlier in the output that the new policies are recognized: New 'Require a specific NSG on every subnet' New 'Restrict Source IPs in NSG Inbound Rules'
After some debugging, it appears that the the policy isn't present in the AllDefinitions hashtable passed to Confirm-PolicyDefinitionUsedExists. But I could be wrong about that, just my initial observation.
I'm inserting my policy set definition file and the two policy definition files below. Wondering if I have a typo somewhere?
Policy Set Definition { "name": "legacy-network-guardrails", "properties": { "displayName": "Legacy subscription network guardrails", "description": "This initiative contains policies that require a specific NSG on subnets and allow only certain inbound source IPs", "metadata": { "version": "1.0.0", "category": "Network" }, "parameters": { "rgName": { "type": "String", "defaultValue": "nsg-rg" }, "nsgName": { "type": "String", "defaultValue": "Baseline-NSG" }, "allowedIPRanges": { "type": "Array", "defaultValue": [ "129.83.0.0/16", "128.29.0.0/16" ] } }, "PolicyDefinitions": [ { "policyDefinitionReferenceId": "require-nsg-on-subnet", "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/require-nsg-on-subnet", "parameters": { "nsgName": { "value": "[parameters('nsgName')]" }, "rgName": { "value": "[parameters('rgName')]" } } }, { "policyDefinitionReferenceId": "restrict-nsg-inbound-ips", "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/restrict-nsg-inbound-ips", "parameters": { "allowedIPRanges": { "value": "[parameters('allowedIPRanges')]" } } } ] } }
Policy 1 { "name": "require-nsg-on-subnet", "properties": { "policyType": "Custom", "displayName": "Require a specific NSG on every subnet", "description": "This policy enforces a specific NSG on every subnet", "mode": "All", "metadata": { "version": "1.0.0", "category": "Network", "pedigree": "See Community-Policy c8178b2d-ab54-4c43-9620-7a2aa854049e" }, "parameters": { "rgName": { "type": "String", "metadata": { "description": "Name of the resource group containing the NSG", "displayName": "Resource group name" }, "defaultValue": "nsg-rg" }, "nsgName": { "type": "String", "metadata": { "description": "Name of the Network Security Group", "displayName": "NSG Name" } } }, "policyRule": { "if": { "anyOf": [ { "allOf": [ { "field": "type", "equals": "Microsoft.Network/virtualNetworks" }, { "not": { "field": "Microsoft.Network/virtualNetworks/subnets[*].networkSecurityGroup.id", "equals": "[concat(subscription().id, '/resourceGroups/', parameters('rgName'), '/providers/Microsoft.Network/networkSecurityGroups/',parameters('nsgName'))]" } } ] }, { "allOf": [ { "field": "type", "equals": "Microsoft.Network/virtualNetworks/subnets" }, { "not": { "field": "Microsoft.Network/virtualNetworks/subnets/networkSecurityGroup.id", "equals": "[concat(subscription().id, '/resourceGroups/', parameters('rgName'), '/providers/Microsoft.Network/networkSecurityGroups/',parameters('nsgName'))]" } } ] } ] }, "then": { "effect": "deny" } } } }
Policy 2 { "name": "restrict-nsg-inbound-ips", "properties": { "policyType": "Custom", "displayName": "Restrict Source IPs in NSG Inbound Rules", "description": "This policy restricts source IPs in NSG inbound rules to a specific set of allowed IPs or CIDRs", "mode": "All", "metadata": { "version": "1.0.0", "category": "Network", "pedigree": "See Community-Policy 995ee9de-5f92-40bd-a795-696323068dff" }, "parameters": { "destinationPort": { "type": "Array", "metadata": { "displayName": "destinationPort", "description": null }, "default": "" }, "allowedIPRanges": { "type": "Array", "metadata": { "displayName": "allowedIPRanges", "description": null } }, "effect": { "type": "String", "metadata": { "displayName": "Effect", "description": "Deny, Audit or Disabled the execution of the Policy" }, "allowedValues": [ "Deny", "Audit", "Disabled" ], "defaultValue": "Deny" } }, "policyRule": { "if": { "allOf": [ { "field": "type", "equals": "Microsoft.Network/networkSecurityGroups/securityRules" }, { "field": "Microsoft.Network/networkSecurityGroups/securityRules/access", "equals": "Allow" }, { "field": "Microsoft.Network/networkSecurityGroups/securityRules/direction", "equals": "Inbound" }, { "anyOf": [ { "count": { "value": "[parameters('allowedIPRanges')]", "name": "allowedIPRanges", "where": { "value": "[if(empty(field('Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefix')), bool('true'), ipRangeContains(current('allowedIPRanges'), if(or(greaterOrEquals(first(field('Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefix')), 'a'), equals(field('Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefix'), '')), current('allowedIPRanges'), field('Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefix'))))]", "equals": false } }, "equals": "[length(parameters('allowedIPRanges'))]" }, { "count": { "field": "Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefixes[]", "where": { "count": { "value": "[parameters('allowedIPRanges')]", "name": "allowedIPRanges", "where": { "value": "[ipRangeContains(current('allowedIPRanges'), first(field('Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefixes[]')))]", "equals": true } }, "greater": 0 } }, "notEquals": "[length(field('Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefixes[]'))]" }, { "field": "Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefix", "equals": "" }, { "field": "Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefix", "equals": "Internet" } ] }, { "count": { "value": "[parameters('destinationPort')]", "name": "destinationPort", "where": { "anyOf": [ { "value": "[if(empty(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRange')), bool('false'), if(contains(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRange'), ''), bool('true'), and(greaterOrEquals(int(current('destinationPort')), int(first(split(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRange'), '-')))), lessOrEquals(int(current('destinationPort')), int(last(split(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRange'), '-')))))))]", "equals": true }, { "count": { "field": "Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRanges[]", "where": { "value": "[if(empty(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRanges[]')), bool('false'), if(contains(string(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRanges[]')), ''), bool('true'), and(greaterOrEquals(int(current('destinationPort')), int(first(split(substring(string(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRanges[]')), 2, sub(length(string(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRanges[]'))), 4)), '-')))), lessOrEquals(int(current('destinationPort')), int(last(split(substring(string(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRanges[]')), 2, sub(length(string(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRanges[*]'))), 4)), '-')))))))]", "equals": true } }, "greater": 0 } ] } }, "greater": 0 } ] }, "then": { "effect": "[parameters('effect')]" } } } }