Error while deploying Azure Json policy using powershell - json

I am trying to create a policy for Azure CIS, and getting the following error when I attempt to deploy it via powershell on the management group level - im trying to figure out what is missing as it says invalid template.
It looks like the error is related to something to do with the scope, but not sure what exactly is going on:
New-AzManagementGroupDeployment : 1:19:17 AM - The deployment 'cis1.23-azurepolicy' failed with error(s). Showing 1 out of 1 error(s).
Status Message: Unable to process template language expressions for resource
'/providers/Microsoft.Management/managementGroups/MGName/providers/Microsoft.Authorization/policyDefinitions/CIS1.23-EnsureNoCustomerOwnerRoles' at line '23' and
column '9'. 'The deployment metadata 'SUBSCRIPTION' is not valid.' (Code:InvalidTemplate)
Here is the template:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"effect": {
"type": "string",
"metadata": {
"displayName": "Effect",
"description": "Enable or disable the execution of the policy"
},
"allowedValues": [
"Audit",
"Disabled"
],
"defaultValue": "Audit"
}
},
"variables": {},
"resources": [
{
"name": "CIS1.23-EnsureNoCustomerOwnerRoles",
"type": "Microsoft.Authorization/policyDefinitions",
"apiVersion": "2018-03-01",
"properties": {
"policyType": "Custom",
"displayName": "CIS 1.23 Custom Owner Roles should not exist (Not Scored)",
"description": "This policy checks that Custom Roles with Owner privileges are removed",
"mode": "all",
"metadata": {
"category": "Identity"
},
"parameters": {
"effect": {
"type": "String",
"metadata": {
"displayName": "Effect",
"description": "Enable or disable the execution of the policy"
},
"allowedValues": [
"Audit",
"Disabled"
],
"defaultValue": "Audit"
}
},
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Authorization/roleDefinitions"
},
{
"field": "Microsoft.Authorization/roleDefinitions/type",
"equals": "CustomRole"
},
{
"anyOf": [
{
"not": {
"field": "Microsoft.Authorization/roleDefinitions/permissions[*].actions[*]",
"notEquals": "*"
}
},
{
"not": {
"field": "Microsoft.Authorization/roleDefinitions/permissions.actions[*]",
"notEquals": "*"
}
}
]
},
{
"anyOf": [
{
"not": {
"field": "Microsoft.Authorization/roleDefinitions/assignableScopes[*]",
"notIn": [
"[concat(subscription().id,'/')]",
"[subscription().id]",
"/"
]
}
},
{
"not": {
"field": "Microsoft.Authorization/roleDefinitions/assignableScopes[*]",
"notLike": "/providers/Microsoft.Management/*"
}
}
]
}
]
},
"then": {
"effect": "[parameters('effect')]"
}
}
}
}

You are deploying the ARM template to a management group, but you are referencing the ARM template subscription() function. The subscription() function is only valid when deploying to a subscription or resource group. When deploying to a management group then there is no subscription that could be referenced.
To resolve this you need to deploy this policy to a subscription, not to a management group.

Related

Azure Policy to deny creation of Network Interfaces without NSG attached

Hey I am looking to assign Azure Policy which will deny creation of Network Interfaces without NSG attached.
I looked with build-in role and couldn't find anything related. Maybe someone have script that does the job.
Thanks for your help in advance.
I tried to create the azure policy to deny creation of network interface without NSG
I have created the policy definition named network
In the policy rule write the below json script to create the policy rules to deny the virtual network without NSG rules
I took the example reference from git URL #withstu
{
"name": "Deny-Subnet-Without-Nsg",
"type": "Microsoft.Authorization/policyDefinitions",
"apiVersion": "2022-11-22",
"scope": null,
"properties": {
"policyType": "Custom",
"mode": "All",
"displayName": "Subnets should have a Network Security Group",
"description": " policy will deny the creation of a network/subnet with out an NSG.",
"metadata": {
"version": "1.1.0",
"category": "Network"
},
"parameters": {
"effect": {
"type": "String",
"allowedValues": [
"Audit",
"Deny",
"Disabled"
],
"defaultValue": "Deny",
"metadata": {
"displayName": "Effect",
"description": " disable the execution of the policy"
}
},
"excludedSubnets": {
"type": "Array",
"metadata": {
"displayName": "Excluded Subnets",
"description": "subnets excluded from this policy"
},
"defaultValue": [
"GatewaySubnet",
"AzureFirewallSubnet",
"AzureFirewallManagementSubnet"
]
}
},
"policyRule": {
"if": {
"anyOf": [
{
"allOf": [
{
"equals": "Microsoft.Network/virtualNetworks",
"field": "type"
},
{
"exists": "false",
"field": "Microsoft.Network/virtualNetworks/subnets[*].networkSecurityGroup.id"
}
]
},
{
"allOf": [
{
"equals": "Microsoft.Network/virtualNetworks/subnets",
"field": "type"
},
{
"field": "name",
"notIn": "[parameters('excludedSubnets')]"
},
{
"exists": "false",
"field": "Microsoft.Network/virtualNetworks/subnets/networkSecurityGroup.id"
}
]
}
]
},
"then": {
"effect": "[parameters('effect')]"
}
}
}
}
I have assigned the policy to the policy definition
In left side of the menu click on Assignment => click on assign policy and added the appropriate fields to create
After assigning the polices it will take 30 minutes to reflect
I am trying to creating the virtual network , I got the error because of deny subnet without NSG

Audit for specific Azure DNS in a specific region (Azure Policy)

I'd like to have an Azure Policy that audits for specific Azure DNS's in the targeted Region. Both should be available in an array so the policy can be scoped multiple times.
So far I've got this, which does not work since it puts the state in compliance by having the right DNS set, but completely ignores the region specified in the array. My goal is to have the policy compliance check for both.
{
"mode": "All",
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Network/virtualNetworks"
},
{
"anyOf": [
{
"value": "[if(empty(field('Microsoft.Network/virtualNetworks/dhcpOptions.dnsServers')), bool('false'), equals(length(intersection(parameters('dnsSettings'), field('Microsoft.Network/virtualNetworks/dhcpOptions.dnsServers'))), length(parameters('dnsSettings'))))]",
"equals": false
},
{
"value": "[if(empty(field('Microsoft.Network/virtualNetworks/dhcpOptions.dnsServers')), bool('false'), equals(length(field('Microsoft.Network/virtualNetworks/dhcpOptions.dnsServers')),length(parameters('dnsSettings'))))]",
"equals": false
}
]
},
{
"not": {
"allOf": [
{
"field": "location",
"in": "[parameters('location')]"
}
]
}
}
]
},
"then": {
"effect": "[parameters('effect')]"
}
},
"parameters": {
"dnsSettings": {
"type": "Array",
"metadata": {
"displayName": "dnsSettings",
"description": "Audit for specific DNS settings."
}
},
"location": {
"type": "Array",
"metadata": {
"displayName": "Location",
"description": "Choose specific location",
"strongType": "location"
}
},
"effect": {
"type": "String",
"metadata": {
"displayName": "Effects",
"description": "Enable or disable the execution of the Policy."
},
"allowedValues": [
"Audit",
"Disabled"
],
"defaultValue": "Audit"
}
}
}
We can use auditIfNotExists with few logic operations so that this will allow only after the success code, below sample is to understand about .
{
"if": {
"field": "type",
"equals": "Microsoft.Compute/virtualMachines"
},
"then": {
"effect": "auditIfNotExists",
"details": {
"type": "Microsoft.Compute/virtualMachines/extensions",
"existenceCondition": {
"allOf": [{
"field": "Microsoft.Compute/virtualMachines/extensions/publisher",
"equals": "Microsoft.Azure.Security"
},
{
"field": "Microsoft.Compute/virtualMachines/extensions/type",
"equals": "IaaSAntimalware"
}
]
}
}
}
}
Below is the way we can specify the dns, Sample for adding dns:
{
"mode": "All",
"name": "Deny changing VNet DNS settings from pre-defined value",
"description": "This Policy will prevent users from changing DNS settings on a VNet",
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Network/virtualNetworks"
},
{
"anyOf": [
{
"value": "[if(empty(field('Microsoft.Network/virtualNetworks/dhcpOptions.dnsServers')), bool('false'), equals(length(intersection(parameters('dnsSettings'), field('Microsoft.Network/virtualNetworks/dhcpOptions.dnsServers'))), length(parameters('dnsSettings'))))]",
"equals": false
},
{
"value": "[if(empty(field('Microsoft.Network/virtualNetworks/dhcpOptions.dnsServers')), bool('false'), equals(length(field('Microsoft.Network/virtualNetworks/dhcpOptions.dnsServers')),length(parameters('dnsSettings'))))]",
"equals": false
}
]
}
]
},
"then": {
"effect": "auditIfNotExists"
}
},
"parameters": {
"dnsSettings": {
"type": "array",
"metadata": {
"displayname": "Enforced DNS Settings",
"description": "Users will be unable to change the DNS settings on a VNet from the values defined in this array."
}
}
}
}
Check AzurePolicy.json and AzurePolicy.rules.json to understand about allowing standard dns within application rules. Include location settings in it.

Does Azure Policy need to be in a separate JSON template or can it exist in a main JSON template?

Usually in an ARM Infrastructure as Code, there is a main JSON and a parameters JSON. Trying to figure out if the Azure Policy needs to be in a separate JSON template or can it exist in a main JSON template?
Azure Policy definition is just another resource in the ARM engine:
{
"type": "Microsoft.Authorization/policyDefinitions",
"name": "allowed-role-definitions-def",
"apiVersion": "2018-03-01",
"properties": {
"policyType": "Custom",
"displayName": "Allowed Role Definitions",
"description": "This policy defines a white list of role deifnitions that can be used in IAM",
"mode": "all",
"parameters": {
"roleDefinitionIds": {
"type": "array",
"metadata": {
"description": "The list of role definition Ids",
"displayName": "Approved Role Definitions"
}
}
},
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Authorization/roleAssignments"
},
{
"not": {
"field": "Microsoft.Authorization/roleAssignments/roleDefinitionId",
"in": "[parameters('roleDefinitionIds')]"
}
}
]
},
"then": {
"effect": "deny"
}
}
}
}
this has to a be a subscription level deployment (not resource group).
https://blog.tyang.org/2018/06/06/using-arm-templates-to-deploying-azure-policy-definitions-that-requires-input-parameters/

How to add a Runbook action to a Metric rule (classic) using Json Template Azure?

Im having an issue about how to add a Runbook action to my metric alert, there is a lot of dosumentation about sending email to owner, but none of them tells about an action Runbook.
This is my template to create a Metric alert:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"AlertName": {
"type": "string"
},
"Description": {
"type": "string"
},
"VirtualMachineId": {
"type": "string"
},
"MetricName": {
"type": "string"
},
"Operator": {
"type": "string"
},
"Threshold": {
"type": "string"
},
"Aggregation": {
"type": "string"
},
"WindowSize": {
"type": "string"
}
},
"variables": {
},
"resources": [
{
"type": "microsoft.insights/alertRules",
"name": "[parameters('AlertName')]",
"location": "[resourceGroup().location]",
"apiVersion": "2016-03-01",
"properties": {
"name": "[parameters('AlertName')]",
"description": "[parameters('Description')]",
"isEnabled": "true",
"windowSize": "[parameters('WindowSize')]",
"condition": {
"odata.type": "Microsoft.Azure.Management.Insights.Models.ThresholdRuleCondition",
"dataSource": {
"odata.type": "Microsoft.Azure.Management.Insights.Models.RuleMetricDataSource",
"resourceUri": "[resourceId('Microsoft.Compute/virtualMachines',parameters('VirtualMachineId'))]",
"metricName": "[parameters('MetricName')]"
},
"operator": "[parameters('Operator')]",
"threshold": "[parameters('Threshold')]",
"windowSize": "[parameters('WindowSize')]",
"timeAggregation": "[parameters('Aggregation')]"
},
"actions": [
{
"odata.type": "RuleAction"
//Runbook....
}
]
}
}
]
}
There is no documentation about adding a RuleAction and im stuck at this point after creating a virtual machine with a Json Template.
Thank you.
You could follow the steps below.
1.Navigate to your Runbook in the portal, go to Webhooks -> Add Webhook, create a new webhook and copy the URL. For more details, refer to this link.
2.In your template, add the sample below to the actions, and specify the webhookUrl with your webhook URL , refer to this link.
"actions": [
{
"odata.type": "Microsoft.Azure.Management.Insights.Models.RuleEmailAction",
"sendToServiceOwners": "[variables('sendToServiceOwners')]",
"customEmails": "[variables('customEmails')]"
},
{
"odata.type": "Microsoft.Azure.Management.Insights.Models.RuleWebhookAction",
"serviceUri": "[variables('webhookUrl')]",
"properties": {}
}
]
Create the alert and check it in the portal, it works fine on my side.

Multiple values for a property on resource in Azure ARM Template

According to https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-multiple#property-iteration it should be possible to create multiple values on a resource using copy but I can't make it work. Here is my code...
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"appServiceName": {
"type": "string",
"metadata": {
"description": "Name of app service to apply SSL to."
}
},
"certificateName": {
"type": "string",
"metadata": {
"description": "User friendly certificate resource name"
}
},
"appServicePlan": {
"type": "string",
"metadata": {
"description": "App Service Plan Name"
}
},
"keyVaultId": {
"type": "string",
"metadata": {
"description": "Existing Key Vault resource Id with an access policy to allow Microsoft.Web RP to read Key Vault secrets (Checkout README.md for more information)"
}
},
"hostname": {
"type": "array",
"metadata": {
"description": "Custom hostname for creating SSL binding. This hostname should already be assigned to the Web App"
}
}
},
"resources": [
{
"apiVersion": "2017-03-30",
"type": "Microsoft.Web/sites",
"name": "[parameters('appServiceName')]",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.Web/certificates', parameters('certificateName'))]"
],
"properties": {
"copy": [
{
"name": "hostnames",
"count": "[length(parameters('hostname'))]",
"input": {
"name": "[copyIndex('hostnames')]",
"properties": {
"hostNameSslStates": [
{
"name": "[[copyIndex(hostname)]]",
"sslState": "SniEnabled",
"thumbprint": "[reference(resourceId('Microsoft.Web/certificates', parameters('certificateName'))).Thumbprint]",
"toUpdate": true
}
]
}
}
}
]
}
},
{
"type": "Microsoft.Web/certificates",
"name": "[parameters('certificateName')]",
"apiVersion": "2016-03-01",
"location": "[resourceGroup().location]",
"properties": {
"keyVaultId": "[parameters('keyVaultId')]",
"keyVaultSecretName": "[parameters('certificateName')]",
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms',parameters('appServicePlan'))]"
}
}
]
}
And it returns Error: Code=InvalidTemplate; Message=Deployment template l
anguage expression evaluation failed: 'Unable to parse language expression 'copyIndex(hostname)]': expecte
d token 'LeftParenthesis' and actual 'RightParenthesis'.'. Please see https://aka.ms/arm-template-expressi
ons for usage details.
Any ideas what am I doing wrong?
Thanks in advance!
the error gives is away:
change "[[copyIndex(hostname)]]", to "[copyIndex('hostname')]"
you even have it right in other places, why not here?
and you probably want to do this:
"[parameters('hostname')[copyIndex('hostname')]]"