I have the following policy definition to run a script for all the Linux Virtual machines in my subscription - resource group. I have 4 Linux virtual machines, OpenSuse, Ubuntu18.04, Ubuntu-server22.04, OracleLinux8.6.
I partially copied what Microsoft did to deploy a script on Linux VMs, and I modified to install a script called bac.sh. For a test, I installed the script on a Linux VM and it works. I made sure that it doesn't prompt the user for any input values, except that the script will need to be run as "sudo bash bac.sh" on the Linux VM. Microsoft uses the following : "commandToExecute": "bash rac.sh"; to run the script on Linux VMs
{
"mode": "All",
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Compute/virtualMachines"
},
{
"anyOf": [
{
"allOf": [
{
"field": "Microsoft.Compute/imagePublisher",
"equals": "RedHat"
},
{
"field": "Microsoft.Compute/imageOffer",
"in": [
"RHEL",
"RHEL-SAP-HANA",
"RHEL-ARM64",
"RHEL-BYOS",
"RHEL-HA",
"RHEL-SAP",
"RHEL-SAP-APPS",
"RHEL-SAP-HA"
]
},
{
"anyOf": [
{
"field": "Microsoft.Compute/imageSku",
"like": "7*"
},
{
"field": "Microsoft.Compute/imageSku",
"like": "8*"
},
{
"field": "Microsoft.Compute/imageSku",
"like": "rhel-lvm7*"
},
{
"field": "Microsoft.Compute/imageSku",
"like": "rhel-lvm8*"
}
]
}
]
},
{
"allOf": [
{
"field": "Microsoft.Compute/imagePublisher",
"equals": "SUSE"
},
{
"field": "Microsoft.Compute/imageOffer",
"in": [
"SLES",
"SLES-HPC",
"SLES-HPC-Priority",
"SLES-SAP",
"SLES-SAP-BYOS",
"SLES-Priority",
"SLES-BYOS",
"SLES-SAPCAL",
"SLES-Standard",
"SLES-12-SP5",
"SLES-15-SP2"
]
},
{
"anyOf": [
{
"field": "Microsoft.Compute/imageSku",
"like": "12*"
},
{
"field": "Microsoft.Compute/imageSku",
"like": "15*"
},
{
"field": "Microsoft.Compute/imageSku",
"like": "gen*"
}
]
}
]
},
{
"allOf": [
{
"field": "Microsoft.Compute/imagePublisher",
"equals": "Canonical"
},
{
"anyOf": [
{
"field": "Microsoft.Compute/imageOffer",
"equals": "UbuntuServer"
},
{
"field": "Microsoft.Compute/imageOffer",
"like": "0001-com-ubuntu-server-*"
},
{
"field": "Microsoft.Compute/imageOffer",
"like": "0001-com-ubuntu-pro-*"
}
]
},
{
"anyOf": [
{
"field": "Microsoft.Compute/imageSku",
"like": "18_04-lts*"
},
{
"field": "Microsoft.Compute/imageSku",
"like": "18.04-lts*"
},
{
"field": "Microsoft.Compute/imageSku",
"like": "20_04-lts*"
},
{
"field": "Microsoft.Compute/imageSku",
"like": "22_04-lts*"
},
{
"field": "Microsoft.Compute/imageSku",
"like": "pro-18_04-lts*"
},
{
"field": "Microsoft.Compute/imageSku",
"like": "pro-20_04-lts*"
},
{
"field": "Microsoft.Compute/imageSku",
"like": "pro-22_04-lts*"
}
]
}
]
},
{
"allOf": [
{
"field": "Microsoft.Compute/imagePublisher",
"equals": "Oracle"
},
{
"field": "Microsoft.Compute/imageOffer",
"equals": "Oracle-Linux"
},
{
"anyOf": [
{
"field": "Microsoft.Compute/imageSku",
"like": "7*"
},
{
"field": "Microsoft.Compute/imageSku",
"like": "8*"
}
]
}
]
},
{
"allOf": [
{
"field": "Microsoft.Compute/imagePublisher",
"equals": "OpenLogic"
},
{
"field": "Microsoft.Compute/imageOffer",
"in": [
"CentOS",
"Centos-LVM",
"CentOS-SRIOV"
]
},
{
"anyOf": [
{
"field": "Microsoft.Compute/imageSku",
"like": "6.*"
},
{
"field": "Microsoft.Compute/imageSku",
"like": "7*"
},
{
"field": "Microsoft.Compute/imageSku",
"like": "8*"
}
]
}
]
},
{
"allOf": [
{
"field": "Microsoft.Compute/imagePublisher",
"equals": "cloudera"
},
{
"field": "Microsoft.Compute/imageOffer",
"equals": "cloudera-centos-os"
},
{
"field": "Microsoft.Compute/imageSku",
"like": "7*"
}
]
},
{
"allOf": [
{
"field": "Microsoft.Compute/imagePublisher",
"equals": "almalinux"
},
{
"field": "Microsoft.Compute/imageOffer",
"like": "almalinux*"
},
{
"field": "Microsoft.Compute/imageSku",
"like": "8*"
}
]
},
{
"allOf": [
{
"field": "Microsoft.Compute/imagePublisher",
"equals": "ctrliqinc1648673227698"
},
{
"field": "Microsoft.Compute/imageOffer",
"like": "rocky-8*"
},
{
"field": "Microsoft.Compute/imageSku",
"like": "rocky-8*"
}
]
},
{
"allOf": [
{
"field": "Microsoft.Compute/imagePublisher",
"equals": "credativ"
},
{
"field": "Microsoft.Compute/imageOffer",
"in": [
"debian"
]
},
{
"field": "Microsoft.Compute/imageSku",
"equals": "9"
}
]
},
{
"allOf": [
{
"field": "Microsoft.Compute/imagePublisher",
"equals": "Debian"
},
{
"field": "Microsoft.Compute/imageOffer",
"in": [
"debian-10",
"debian-11"
]
},
{
"anyOf": [
{
"field": "Microsoft.Compute/imageSku",
"like": "10*"
},
{
"field": "Microsoft.Compute/imageSku",
"like": "11*"
}
]
}
]
},
{
"allOf": [
{
"field": "Microsoft.Compute/imagePublisher",
"equals": "microsoftcblmariner"
},
{
"field": "Microsoft.Compute/imageOffer",
"equals": "cbl-mariner"
}
]
}
]
}
]
},
"then": {
"effect": "deployIfNotExists",
"details": {
"type": "Microsoft.Compute/virtualMachines/extensions",
"name": "CBCSE",
"deployment": {
"properties": {
"mode": "incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"location": {
"type": "string"
},
"vmname": {
"type": "string"
},
> "vmName": {
> "type": "string"
> }
},
"resources": [
{
"apiVersion": "2020-06-01",
"name": "[concat(parameters('vmName'), '/CBCSE')]",
"type": "Microsoft.Compute/virtualMachines/extensions",
"location": "[parameters('location')]",
"properties": {
"publisher": "Microsoft.Compute",
"type": "CustomScriptExtension",
"autoUpgradeMinorVersion": true,
"typeHandlerVersion": "1.0",
"settings": {
"timestamp": 123456789,
"commandToExecute": "bash bac.sh",
"fileUris": [
"https://mystorage.blob.core.windows.net/hbs/bac.sh"
]
},
"protectedSettings": {}
}
}
]
},
"parameters": {
"location": {
"value": "[field('location')]"
},
"vmname": {
"value": "[field('name')]"
},
> "vmName": {
> "value": "[field('name')]"
> }
}
}
},
"roleDefinitionIds": [
"/providers/microsoft.authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c"
],
"existenceCondition": {
"allOf": [
{
"field": "Microsoft.Compute/virtualMachines/extensions/type",
"equals": "CBCSE"
},
{
"field": "Microsoft.Compute/virtualMachines/extensions/provisioningState",
"equals": "Succeeded"
}
]
}
}
}
},
"parameters": {}
}
After checking the "deployment error" in the Remediation task, I found the following error message
Code CaseSensitiveDeploymentParameterNamesFound
Message The deployment parameters are using case sensitive names. The error parameter name(s): vmName. Please see https://aka.ms/arm-keyvault for usage details.
Note: The "vname" appears twice, I removed it several times, but not why Azure keeps adding it.
Any comment/help will be appreciated!
I was expecting the script to run on all the Linux VMs, but I am seeing the deployment error as
Details
Code CaseSensitiveDeploymentParameterNamesFound
Message The deployment parameters are using case sensitive names. The error parameter name(s): vmName. Please see https://aka.ms/arm-keyvault for usage details.
I think Azure Resource Manager is actually running in to an issue removing the duplicate vmName/vmname property because of the case sensitivity issue in the original error. Thirst thing I would try is making sure you have a backup of the policy JSON as a file on your computer. Remove the duplicate vmname entry and save the file. Then delete the original Policy in Azure and recreate it from the edited local file.
Related
As part of the suggestion: https://github.com/microsoft/azure-container-apps/issues/338
I need some help in modifying the Azure Policy definition to include the below lines:
{
"allOf": [
{
"field": "type",
"equals": "Microsoft.Resources/subscriptions/resourceGroups"
},
{
"field": "[concat('tags[', parameters('tagName'), ']')]",
"exists": "false"
},
{
"anyOf": [
{
"value": "[startsWith(field('name'), 'MC_')]",
"notEquals": "true"
}
]
}
]
}
This is my existing Azure policy definition with allOf:
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Network/virtualNetworks"
},
{
"field": "Microsoft.Network/virtualNetworks/addressSpace.addressPrefixes[*]",
"notContains": "11.22.33"
}
]
},
"then": {
"effect": "deny"
}
}
and another one with anyOf
"policyRule": {
"if": {
"anyOf": [
{
"not": {
"field": "[concat('tags[', parameters('tagnameteam'), ']')]",
"in": "[parameters('listofallowedtagvalues')]"
}
}
]
},
"then": {
"effect": "Deny"
}
}
}
How can I achieve it by modifying the existing Azure policy definition?
It really depends on when you want the policy to trigger the effect...
For example in the "allOf" policy:
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Network/virtualNetworks"
},
{
"field": "Microsoft.Network/virtualNetworks/addressSpace.addressPrefixes[*]",
"notContains": "11.22.33"
},
{
"field": "type",
"equals": "Microsoft.Resources/subscriptions/resourceGroups"
},
{
"field": "[concat('tags[', parameters('tagName'), ']')]",
"exists": "false"
},
{
"anyOf": [
{
"value": "[startsWith(field('name'), 'MC_')]",
"notEquals": "true"
}
]
}
]
},
"then": {
"effect": "deny"
}
}
would mean that your old conditions AND the new ones have to apply (which is what I think you want?).
On the other hand, if you want that your old conditions OR the new ones should apply, you would need to add the two "allOf" parts in an "anyOf" part:
"policyRule": {
"if": {
"anyOf":[
{
"allOf": [
{
"field": "type",
"equals": "Microsoft.Network/virtualNetworks"
},
{
"field": "Microsoft.Network/virtualNetworks/addressSpace.addressPrefixes[*]",
"notContains": "11.22.33"
}
]
},
{
"allOf": [
{
"field": "type",
"equals": "Microsoft.Resources/subscriptions/resourceGroups"
},
{
"field": "[concat('tags[', parameters('tagName'), ']')]",
"exists": "false"
},
{
"anyOf": [
{
"value": "[startsWith(field('name'), 'MC_')]",
"notEquals": "true"
}
]
}
]
}
]
},
"then": {
"effect": "deny"
}
}
The same goes for the "anyOf" policy. If you want the old "anyOf" condition OR the new "allOf":
"policyRule": {
"if": {
"anyOf": [
{
"not": {
"field": "[concat('tags[', parameters('tagnameteam'), ']')]",
"in": "[parameters('listofallowedtagvalues')]"
}
},
{
"allOf": [
{
"field": "type",
"equals": "Microsoft.Resources/subscriptions/resourceGroups"
},
{
"field": "[concat('tags[', parameters('tagName'), ']')]",
"exists": "false"
},
{
"anyOf": [
{
"value": "[startsWith(field('name'), 'MC_')]",
"notEquals": "true"
}
]
}
]
}
]
},
"then": {
"effect": "Deny"
}
}
}
And if yo need to have both the "anyOf" and the new "allOf" parts to be true (which is the one, I think you want?):
"policyRule": {
"if": {
"allOf": [
{
"not": {
"field": "[concat('tags[', parameters('tagnameteam'), ']')]",
"in": "[parameters('listofallowedtagvalues')]"
}
},
{
"field": "type",
"equals": "Microsoft.Resources/subscriptions/resourceGroups"
},
{
"field": "[concat('tags[', parameters('tagName'), ']')]",
"exists": "false"
},
{
"anyOf": [
{
"value": "[startsWith(field('name'), 'MC_')]",
"notEquals": "true"
}
]
}
]
},
"then": {
"effect": "Deny"
}
}
I am trying to modify an existing custom policy which I obtained from github. The goal is to not allow users to RDP from public IP addresses. The ARM template needs to support only private ranges. Here is the code:
{
"mode": "All",
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Network/networkSecurityGroups/securityRules"
},
{
"allOf": [
{
"field": "Microsoft.Network/networkSecurityGroups/securityRules/access",
"equals": "Allow"
},
{
"field": "Microsoft.Network/networkSecurityGroups/securityRules/direction",
"equals": "Inbound"
},
{
"anyOf": [
{
"field": "Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRange",
"equals": "*"
},
{
"field": "Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRange",
"equals": "3389"
},
{
"value": "[if(and(not(empty(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRange'))), contains(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRange'),'-')), and(lessOrEquals(int(first(split(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRange'), '-'))),3389),greaterOrEquals(int(last(split(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRange'), '-'))),3389)), 'false')]",
"equals": "true"
},
{
"count": {
"field": "Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRanges[*]",
"where": {
"value": "[if(and(not(empty(first(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRanges[*]')))), contains(first(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRanges[*]')),'-')), and(lessOrEquals(int(first(split(first(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRanges[*]')), '-'))),3389),greaterOrEquals(int(last(split(first(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRanges[*]')), '-'))),3389)) , 'false')]",
"equals": "true"
}
},
"greater": 0
},
{
"not": {
"field": "Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRanges[*]",
"notEquals": "*"
}
},
{
"not": {
"field": "Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRanges[*]",
"notEquals": "3389"
}
}
]
},
{
"anyOf": [
{
"field": "Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefix",
"equals": "*"
},
{
"field": "Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefix",
"equals": "Internet"
},
{
"value": "[or(ipRangeContains('10.0.0.0/8', field('Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefix')),ipRangeContains('172.16.0.0/12', field('Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefix')),ipRangeContains('192.168.0.0/16', field('Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefix')))]",
"equals": false
},
{
"count": {
"field": "Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefixes[*]",
"where": {
"value": "[or(ipRangeContains('10.0.0.0/8', first(field('Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefixes[*]'))),ipRangeContains('172.16.0.0/12', first(field('Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefixes[*]'))),ipRangeContains('192.168.0.0/16', first(field('Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefixes[*]'))))]",
"equals": false
}
},
"greater": 0
},
{
"not": {
"field": "Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefixes[*]",
"notEquals": "*"
}
},
{
"not": {
"field": "Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefixes[*]",
"notEquals": "Internet"
}
}
]
}
]
}
]
},
"then": {
"effect": "deny"
}
},
"parameters": {}
}
The following section works well. It does not allow me to add IP addresses other than private IP ranges. So policy denies creation of NSG rule with MY PUBLIC IP address.
{
"value": "[or(ipRangeContains('10.0.0.0/8', field('Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefix')),ipRangeContains('172.16.0.0/12', field('Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefix')),ipRangeContains('192.168.0.0/16', field('Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefix')))]",
"equals": false
}
The next section throws an error
{
"count": {
"field": "Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefixes[*]",
"where": {
"value": "[or(ipRangeContains('10.0.0.0/8', first(field('Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefixes[*]'))),ipRangeContains('172.16.0.0/12', first(field('Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefixes[*]'))),ipRangeContains('192.168.0.0/16', first(field('Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefixes[*]'))))]",
"equals": false
}
},
"greater": 0
}
So, if I enter multiple Private IP's separated by comma, when creating NSG for SourceAddress, I get the following error:
The inner error is 'The policy language function 'ipRangeContains' has encountered one or more invalid IP Ranges: '"10.0.0.0/8",null'. IP Ranges can be specified in CIDR notation, single IP address or a range with start and end addresses separated with a '-'. Ranges that mix between IPv4 and IPv6 and ranges that don't include any addresses are not allowed.'.
Any ideas/suggestions on fixing this error will be great help..
I had to include logic for not empty source IP fields and check them to not match * and Internet.
{
"mode": "All",
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Network/networkSecurityGroups/securityRules"
},
{
"allOf": [
{
"field": "Microsoft.Network/networkSecurityGroups/securityRules/access",
"equals": "Allow"
},
{
"field": "Microsoft.Network/networkSecurityGroups/securityRules/direction",
"equals": "Inbound"
},
{
"anyOf": [
{
"field": "Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRange",
"equals": "*"
},
{
"field": "Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRange",
"equals": "3389"
},
{
"value": "[if(and(not(empty(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRange'))), contains(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRange'),'-')), and(lessOrEquals(int(first(split(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRange'), '-'))),3389),greaterOrEquals(int(last(split(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRange'), '-'))),3389)), 'false')]",
"equals": "true"
},
{
"count": {
"field": "Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRanges[*]",
"where": {
"value": "[if(and(not(empty(first(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRanges[*]')))), contains(first(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRanges[*]')),'-')), and(lessOrEquals(int(first(split(first(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRanges[*]')), '-'))),3389),greaterOrEquals(int(last(split(first(field('Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRanges[*]')), '-'))),3389)) , 'false')]",
"equals": "true"
}
},
"greater": 0
},
{
"not": {
"field": "Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRanges[*]",
"notEquals": "*"
}
},
{
"not": {
"field": "Microsoft.Network/networkSecurityGroups/securityRules/destinationPortRanges[*]",
"notEquals": "3389"
}
}
]
},
{
"anyOf": [
{
"field": "Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefix",
"equals": "*"
},
{
"field": "Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefix",
"equals": "Internet"
},
{
"value": "[if(and(not(empty(field('Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefix'))),not(contains(field('Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefix'),'*')),not(contains(field('Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefix'),'Internet'))),not(or(ipRangeContains('10.0.0.0/8', field('Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefix')),ipRangeContains('172.16.0.0/12', field('Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefix')),ipRangeContains('192.168.0.0/16', field('Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefix')))),'false')]",
"equals": true
},
{
"count": {
"field": "Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefixes[*]",
"where": {
"value": "[or(ipRangeContains('10.0.0.0/8', first(field('Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefixes[*]'))),ipRangeContains('172.16.0.0/12', first(field('Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefixes[*]'))),ipRangeContains('192.168.0.0/16', first(field('Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefixes[*]'))))]",
"equals": false
}
},
"greater": 0
},
{
"not": {
"field": "Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefixes[*]",
"notEquals": "*"
}
},
{
"not": {
"field": "Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefixes[*]",
"notEquals": "Internet"
}
}
]
}
]
}
]
},
"then": {
"effect": "deny"
}
},
"parameters": {}
}
I'm trying to create Azure custom policy to install extension "AADLoginForWindows" to be enabled on all existing and newly created VMs. When im creating the custom policy definition getting below error message.
Custom policy:
{
"properties": {
"policyType": "custom",
"displayName": "Install aadloginforwindows extension on Windows 2019 server and Windows 10 VMs",
"mode": "all",
"description": "Install aadloginforwindows extension on Windows 2019 server and Windows 10 VMs for Azure active directory login",
"parameters": {
"listOfImageIdToInclude": {
"type": "Array",
"metadata": {
"displayName": "Optional: List of virtual machine images that have supported Windows OS to add to scope",
"description": "Windows Server 2019 and Windows10 is supported"
},
"defaultValue": []
},
"effect": {
"type": "String",
"metadata": {
"displayName": "Effect",
"description": "Enable or disable the execution of the policy"
},
"allowedValues": [
"DeployIfNotExists",
"Disabled"
],
"defaultValue": "DeployIfNotExists"
},
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Compute/virtualMachines"
},
{
"anyOf": [
{
"field": "Microsoft.Compute/imageId",
"in": "[parameters('listOfImageIdToInclude')]"
},
{
"allOf": [
{
"field": "Microsoft.Compute/imagePublisher",
"equals": "MicrosoftWindowsServer"
},
{
"field": "Microsoft.Compute/imageOffer",
"equals": "WindowsServer"
},
{
"field": "Microsoft.Compute/imageSKU",
"in": [
"2019-Datacenter",
"2019-Datacenter-smalldisk",
"2019-Datacenter-with-Containers",
"2019-Datacenter-with-Containers-smalldisk",
"2019-Datacenter-zhcn",
"2019-datacenter-gensecond"
]
}
]
},{
"allOf": [
{
"field": "Microsoft.Compute/imagePublisher",
"equals": "MicrosoftWindowsDesktop"
},
{
"field": "Microsoft.Compute/imageOffer",
"equals": "Windows-10"
}
]
}
]
}
]
},
"then": {
"effect": "[parameters('effect')]",
"details": {
"type": "Microsoft.Compute/virtualMachines/extensions",
"roleDefinitionIds": [
"/providers/microsoft.authorization/roleDefinitions/92aaf0da-9dab-42b6-94a3-d43ce8d16293"
],
"existenceCondition": {
"allOf": [
{
"field": "Microsoft.Compute/virtualMachines/extensions/type",
"equals": "AADLoginForWindows"
},
{
"field": "Microsoft.Compute/virtualMachines/extensions/provisioningState",
"equals": "Succeeded"
}
]
},
"deployment": {
"properties": {
"mode": "incremental",
"template": {
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"vmName": {
"type": "string"
},
"location": {
"type": "string"
}
},
"variables": {
"vmExtensionName": "AADLoginForWindows",
"vmExtensionPublisher": "Microsoft.Azure.ActiveDirectory",
"vmExtensionType": "AADLoginForWindows",
"vmExtensionTypeHandlerVersion": "1.0"
},
"resources": [
{
"type": "Microsoft.Compute/virtualMachines/extensions",
"name": "[concat(parameters('vmName'), '/', variables('vmExtensionName'))]",
"apiVersion": "2021-04-01",
"location": "[parameters('location')]",
"properties": {
"publisher": "[variables('vmExtensionPublisher')]",
"type": "[variables('vmExtensionType')]",
"typeHandlerVersion": "[variables('vmExtensionTypeHandlerVersion')]",
"autoUpgradeMinorVersion": true
}
}
],
"outputs": {
"policy": {
"type": "string",
"value": "[concat('Enabled extension for VM', ': ', parameters('vmName'))]"
}
}
},
"parameters": {
"vmName": {
"value": "[field('name')]"
},
"location": {
"value": "[field('location')]"
}
}
}
}
}
}
}
}
}}
Error message:
The request content was invalid and could not be deserialized: 'Required property 'type' not found in JSON. Path 'properties.parameters.policyRule', line 1, position 571.'.
Any inputs/feedback will be helpful. Couldnt find any policy sample or built in policy for this extension.
• According to the error that you are encountering, the Azure custom policy created by you regarding the ‘AADLoginForWindows’ extension to be used and mandated by the Azure policy for the Azure AD login to be done on the VMs, the policy properties regarding the conditions of the policy rule are incorrect. Therefore, in the following section as stated by you in the question, the policy rules should be as follows: -
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Compute/virtualMachines"
},
{
"anyOf": [
{
"field": "Microsoft.Compute/imageId",
"in": "[parameters('listOfImageIdToInclude')]"
},
{
"allOf": [
{
"field": "Microsoft.Compute/imagePublisher",
"equals": "MicrosoftWindowsServer"
},
{
"field": "Microsoft.Compute/imageOffer",
"equals": "WindowsServer"
},
{
"field": "Microsoft.Compute/imageSKU",
"in": [
"2019-Datacenter",
"2019-Datacenter-smalldisk",
"2019-Datacenter-with-Containers",
"2019-Datacenter-with-Containers-smalldisk",
"2019-Datacenter-zhcn",
"2019-datacenter-gensecond"
]
}
]
},
{
"allOf": [
{
"field": "Microsoft.Compute/imagePublisher",
"equals": "MicrosoftWindowsDesktop"
},
{
"field": "Microsoft.Compute/imageOffer",
"equals": "Windows-10"
}
In the above section, the section for ‘imageID’ should be omitted completely because the ‘imageID’ is not a correct parameter with regards to ‘VM Compute Image’ to be included in the custom policy for ‘AADLoginForWindows’ extension.
Thus, if it is not included as per the sample policy as shown below, the error that you are encountering might not encountered.
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Compute/virtualMachines"
},
{
"anyOf": [
{
"allOf": [
{
"field": "Microsoft.Compute/imagePublisher",
"equals": "MicrosoftWindowsServer"
},
{
"field": "Microsoft.Compute/imageOffer",
"equals": "WindowsServer"
},
{
"field": "Microsoft.Compute/imageSKU",
"in": [
"2008-R2-SP1",
"2008-R2-SP1-smalldisk",
"2012-Datacenter",
"2012-Datacenter-smalldisk",
"2012-R2-Datacenter",
"2012-R2-Datacenter-smalldisk",
"2016-Datacenter",
"2016-Datacenter-Server-Core",
"2016-Datacenter-Server-Core-smalldisk",
"2016-Datacenter-smalldisk",
"2016-Datacenter-with-Containers",
"2016-Datacenter-with-RDSH",
"2019-Datacenter",
"2019-Datacenter-Core",
"2019-Datacenter-Core-smalldisk",
"2019-Datacenter-Core-with-Containers",
"2019-Datacenter-Core-with-Containers-smalldisk",
"2019-Datacenter-smalldisk",
"2019-Datacenter-with-Containers",
"2019-Datacenter-with-Containers-smalldisk",
"2019-Datacenter-zhcn"
]
}
]
},
{
"allOf": [
{
"field": "Microsoft.Compute/imagePublisher",
"equals": "MicrosoftWindowsServer"
},
{
"field": "Microsoft.Compute/imageOffer",
"equals": "WindowsServerSemiAnnual"
},
{
"field": "Microsoft.Compute/imageSKU",
"in": [
"Datacenter-Core-1709-smalldisk",
"Datacenter-Core-1709-with-Containers-smalldisk",
"Datacenter-Core-1803-with-Containers-smalldisk"
]
}
]
},
{
"allOf": [
{
"field": "Microsoft.Compute/imagePublisher",
"equals": "MicrosoftWindowsServerHPCPack"
},
{
"field": "Microsoft.Compute/imageOffer",
"equals": "WindowsServerHPCPack"
}
]
},
{
"allOf": [
{
"field": "Microsoft.Compute/imagePublisher",
"equals": "MicrosoftSQLServer"
},
{
"anyOf": [
{
"field": "Microsoft.Compute/imageOffer",
"like": "*-WS2019"
},
{
"field": "Microsoft.Compute/imageOffer",
"like": "*-WS2019-BYOL"
},
{
"field": "Microsoft.Compute/imageOffer",
"like": "*-WS2016"
},
{
"field": "Microsoft.Compute/imageOffer",
"like": "*-WS2016-BYOL"
},
{
"field": "Microsoft.Compute/imageOffer",
"like": "*-WS2012R2"
},
{
"field": "Microsoft.Compute/imageOffer",
"like": "*-WS2012R2-BYOL"
}
]
}
]
},
For more detailed information regarding this, kindly visit the below link: -
https://learn.microsoft.com/en-us/azure/governance/policy/tutorials/create-custom-policy-definition#completed-definition
i am trying to create a resource health alert on azure using powershell because arm templates are not allowed.
Here is what i have so far:
$condition1 = New-AzActivityLogAlertCondition -Field 'category' -Equal 'ResourceHealth'
$json = #"
{
[
{
"field": "status",
"equals": "Active"
},
{
"field": "status",
"equals": "In Progress"
},
{
"field": "status",
"equals": "Resolved"
},
{
"field": "status",
"equals": "Updated"
}
]
}
"#
# fails if we inlcude this condition
$condition2 = New-AzActivityLogAlertCondition -Field 'anyOf' -Equal $json
$setAzActivityLogAlertSplat = #{
Location = $ResourceHealthAlertLocation
Name = $ResourceHealthAlertName
Description = $ResourceHealthAlertDescription
ResourceGroupName = $ResourceHealthAlertResourceGroupName
Scope = $ResourceHealthAlertScope
Action = $agAlertObject
Condition = $condition1,$condition2
Verbose = $true
}
Set-AzActivityLogAlert #setAzActivityLogAlertSplat
if i run with just condition1 the code succeeds but i want to fine tune with a second condition which is failing with an error :
Message: Microsoft.Azure.Management.Monitor.Models.ErrorResponseException: Operation returned an invalid status code 'BadRequest'
Basically i am trying to re-create the arm template here in powerrshell:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"activityLogAlertName": {
"type": "string",
"metadata": {
"description": "Unique name (within the Resource Group) for the Activity log alert."
}
},
"actionGroupResourceId": {
"type": "string",
"metadata": {
"description": "Resource Id for the Action group."
}
}
},
"resources": [
{
"type": "Microsoft.Insights/activityLogAlerts",
"apiVersion": "2017-04-01",
"name": "[parameters('activityLogAlertName')]",
"location": "Global",
"properties": {
"enabled": true,
"scopes": [
"[subscription().id]"
],
"condition": {
"allOf": [
{
"field": "category",
"equals": "ResourceHealth",
"containsAny": null
},
{
"anyOf": [
{
"field": "properties.currentHealthStatus",
"equals": "Available",
"containsAny": null
},
{
"field": "properties.currentHealthStatus",
"equals": "Unavailable",
"containsAny": null
},
{
"field": "properties.currentHealthStatus",
"equals": "Degraded",
"containsAny": null
}
]
},
{
"anyOf": [
{
"field": "properties.previousHealthStatus",
"equals": "Available",
"containsAny": null
},
{
"field": "properties.previousHealthStatus",
"equals": "Unavailable",
"containsAny": null
},
{
"field": "properties.previousHealthStatus",
"equals": "Degraded",
"containsAny": null
}
]
},
{
"anyOf": [
{
"field": "properties.cause",
"equals": "PlatformInitiated",
"containsAny": null
}
]
},
{
"anyOf": [
{
"field": "status",
"equals": "Active",
"containsAny": null
},
{
"field": "status",
"equals": "Resolved",
"containsAny": null
},
{
"field": "status",
"equals": "In Progress",
"containsAny": null
},
{
"field": "status",
"equals": "Updated",
"containsAny": null
}
]
}
]
},
"actions": {
"actionGroups": [
{
"actionGroupId": "[parameters('actionGroupResourceId')]"
}
]
}
}
}
]
}
help me to make the mandatory tag using azure policy and users are not allowed to give their own tag name. the below code mandatory the mentioned tags and not to control the disallowed other tags
{
"mode": "All",
"policyRule": {
"if": {
"anyOf": [
{
"field": "tags['environment']",
"exists": "false"
},
{
"field": "tags['Location']",
"exists": "false"
}
]
},
"then": {
"effect": "deny"
}
},
"parameters": {}
}
Here is the example to make changes with Tag in Azure Policy
"policyRule": {
"if": {
"allOf": [{
"field": "type",
"equals": "Microsoft.Resources/subscriptions/resourceGroups"
},
{
"field": "name",
"like": "prd-*"
},
{
"field": "tags['Env']",
"notEquals": "Production"
}
]
},
"then": {
"effect": "modify",
"details": {
"roleDefinitionIds": [
"/providers/microsoft.authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c"
],
"operations": [{
"operation": "addOrReplace",
"field": "tags['Env']",
"value": "Production"
}]
}
}
}
for further information could you please check the Azure Policy documentation