I'm struggling with a policy which should allow only certain values for tags.
Here is the code
{
"mode": "Indexed",
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Compute/virtualMachines"
},
{
"field": "[concat('tags[', parameters('tagName'), ']')]",
"notIn": "[parameters('listOfAllowedValues')]"
}
]
},
"then": {
"effect": "deny"
}
},
"parameters": {
"tagName": {
"type": "String",
"metadata": {
"displayName": "Tag Name",
"description": "Name of the tag, such as 'environment'"
}
},
"listOfAllowedValues": {
"type": "Array",
"metadata": {
"displayName": "Allowed values",
"description": "The list of values which tag can have."
}
}
}
}
I put this array for assigments: ["Not Appliable","1","2","3","4"]
Policy evaluation works perfectly fine for numbers, but when I put tag value to be Not applicable policy always denies creation of VM.
Not sure what's wrong with it..Any help is appreciated!
In your policy definition, for the parameter listOfAllowedValues you are passing the allowed values as Notappliable and while creating the virtual machine you are passing the tag value as NotApplicable since there is spelling mistake that is the reason your policy valuation is getting failed.
I have test the above policy in my local and it working as expected from my end.
Related
My resource groups has an environment tag where only specific values are allowed: "dev,test,prod". I want to enforce that with an Azure Policy which will deny all the resource group creation which doesn't have one of this "dev,test,prod" values in their environment tag. My policy code is as below:
{
"properties": {
"displayName": "Allowed tag values for Resource Groups",
"description": "This policy enables you to restrict the tag values for Resource Groups.",
"policyType": "Custom",
"mode": "Indexed",
"metadata": {
"version": "1.0.0",
"category": "Tags"
},
"parameters": {
"allowedTagValues": {
"type": "array",
"metadata": {
"description": "The list of tag values that can be specified when deploying resource groups",
"displayName": "Allowed tag values"
},
"defaultValue": [
"dev","test","prod"
]
}
},
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Resources/subscriptions/resourceGroups"
},
{
"field": "tags[environment]",
"notIn": "[parameters('allowedTagValues')]"
}
]
},
"then": {
"effect": "deny"
}
}
},
"id": "/providers/Microsoft.Authorization/policyDefinitions/xxxxxxx-xxxxxxx-xxxxxxxxxx-xxxxxxx",
"name": "xxxxxxx-xxxxxxx-xxxxxxxxxx-xxxxxxx"
}
This doesn't have any effect at all. I have tried this as well:
{
"not": {
"field": "tags[environment]",
"in": "[parameters('allowedTagValues')]"
}
}
Neither this does work.
Any suggestion?
You need to pass the tag values "dev","test","prod" as allowed values for the parameter listofallowedTags as shown below.
Based on your requirement we have created the below policy definition. we have tested this in our local environment which is working fine.
{
"mode": "All",
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Resources/subscriptions/resourceGroups"
},
{
"not": {
"field": "[concat('tags[', parameters('tagName'), ']')]",
"in": "[parameters('listofallowedtagValues')]"
}
}
]
},
"then": {
"effect": "[parameters('effect')]"
}
},
"parameters": {
"effect": {
"type": "String",
"metadata": {
"displayName": "Effect",
"description": "Enable or disable the execution of the audit policy"
},
"allowedValues": [
"Audit",
"Deny",
"Disabled"
],
"defaultValue": "Deny"
},
"tagName": {
"type": "String",
"metadata": {
"displayName": "Tag Name",
"description": "Name of the tag, such as 'environment'"
},
"defaultValue": "environment"
},
"listofallowedtagValues": {
"type": "Array",
"metadata": {
"displayName": "Tag Values",
"description": "Value of the tag, such as 'production'"
},
"allowedValues": [
"dev",
"test",
"prod"
]
}
}
}
Note: As you can see from the below image, the custom policy has been assigned to subscription.
Here are the some sample outputs for reference:
In the below example, we have passed environment tag a different value apart from those 3 values defined in listofallowedtagValues parameter & while deploying the resource group it got failed since it doesn't met policy requirement.
In the below example, we have passed environment tag value as test resource group deployment got succeeded as it met the policy requirements.
I am trying to deploy an azure policy via ARM template. This is my definition file . The error I get is Status Message: Unable to process template language expressions for resource '/subscriptions/xxx/providers/Microsoft.Authorization/policyDefinitions/deploy-rg-lock' at line '13' and column '9'. 'The template parameter 'tagName' is not found. Please see https://aka.ms/arm-template/#parameters for usage details.' (Code:InvalidTemplate)
{
"$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"policyDefinitionName": {
"type": "string"
}
},
"resources": [{
"type": "Microsoft.Authorization/policyDefinitions",
"name": "[parameters('policyDefinitionName')]",
"apiVersion": "2019-09-01",
"properties": {
"displayName": "Lock Resource Group based on tags",
"policyType": "Custom",
"mode": "All",
"description": "This policy locks a resource group if the tag mentioned in the parameter is not present",
"metadata": {
"category": "Tags"
},
"parameters": {
"tagName": {
"type": "String",
"metadata": {
"displayName": "Tag Name",
"description": "Tag name to prevent resource lock"
}
},
"tagValue": {
"type": "String",
"metadata": {
"displayName": "Tag Value",
"description": "Tag value to prevent resource lock"
}
}
},
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Resources/subscriptions/resourceGroups"
},
{
"field": "[concat('tags[', parameters('tagName'), ']')]",
"notEquals": "[parameters('tagValue')]"
}
]
},
"then": {
"effect": "deployIfNotExists",
"details": {
"type": "Microsoft.Authorization/locks",
"roleDefinitionIds": [
"/providers/microsoft.authorization/roleDefinitions/92aaf0da-9dab-42b6-94a3-d43ce8d16293"
],
"existenceCondition": {
"field": "Microsoft.Authorization/locks/level",
"equals": "CanNotDelete"
},
"deployment": {
"properties": {
"mode": "incremental",
"template": {
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"name": "PolicyDeleteLock",
"type": "Microsoft.Authorization/locks",
"apiVersion": "2016-09-01",
"properties": {
"level": "CanNotDelete",
"notes": "Set by policy RG_ResourceLockCheck"
}
}
],
"outputs": {
"policy": {
"type": "string",
"value": "locked RG"
}
}
}
}
}
}
}
}
}
}]
}
Inside your policyRule, you need to escape ARM expressions with an extra opening bracket to prevent them from being evaluated at top-level. For example at line 45:
"field": "[concat('tags[', parameters('tagName'), ']')]"
Should become:
"field": "[[concat('tags[', parameters('tagName'), ']')]"
(Note that there is no extra closing bracket. It's a bit weird but this is how you should do it)
Do this for all ARM expressions inside the policy rule and it should work.
You can define the parameters tagName and tagValue as well.
So adding the parameters as I have applied below will solve the issue.
{
"$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"policyDefinitionName": {
"type": "string"
},
# define tag name and tag value
"tagName":{
"type": "string"
},
"tagValue": {
"type": "string"
},
"policyDefinitionID": {
"type": "string"
}
},
"resources": [{
"type": "Microsoft.Authorization/policyDefinitions",
"name": "[parameters('policyDefinitionName')]",
"apiVersion": "2019-09-01",
"properties": {
"displayName": "Lock Resource Group based on tags",
"policyType": "Custom",
"mode": "All",
"description": "This policy locks a resource group if the tag mentioned in the parameter is not present",
"metadata": {
"category": "tags"
},
"parameters": {
"": {
"type": "String",
"metadata": {
"displayName": "Cannot Delete",
"description": "Tag name to prevent resource lock"
}
},
"tagValue": {
"type": "String",
"metadata": {
"displayName": "Tag Value",
"description": "Tag value to prevent resource lock"
}
}
},
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Resources/subscriptions/resourceGroups"
},
{
"field": "[concat('Tags[', parameters('tagName'), ']')]",
"notEquals": "[parameters('tagValue')]"
}
]
},
"then": {
"effect": "deployIfNotExists",
"details": {
"type": "Microsoft.Authorization/locks",
"roleDefinitionIds": [
"[parameters('policyDefinitionID')]"
],
"existenceCondition": {
"field": "Microsoft.Authorization/locks/level",
"equals": "CanNotDelete"
},
"deployment": {
"properties": {
"mode": "incremental",
"template": {
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"name": "PolicyDeleteLock",
"type": "Microsoft.Authorization/locks",
"apiVersion": "2016-09-01",
"properties": {
"level": "CanNotDelete",
"notes": "Set by policy RG_ResourceLockCheck"
}
}
],
"outputs": {
"policy": {
"type": "string",
"value": "locked RG"
}
}
}
}
}
}
}
}
}
}]
}
It will execute the after giving the command
Trying to create a policy tied to a subscription in Azure that will deny the create of a resource group without a specific "costCenter" tag. I have the following policy assigned to the subscription with the "coreTagName1" completed as "costCenter":
"properties": {
"displayName": "manual_test_1",
"policyType": "Custom",
"mode": "Indexed",
"description": "manual test for tag enforcement",
"metadata": {
"category": "test",
"createdBy": "#########",
"createdOn": "2020-04-02T12:27:39.2686671Z",
"updatedBy": "#########",
"updatedOn": "2020-04-02T12:35:32.5608728Z"
},
"parameters": {
"coreTagName1": {
"type": "String",
"metadata": {
"displayName": "tagName to enforce",
"description": "Name of the tag, such as costCenter"
}
}
},
"policyRule": {
"if": {
"anyOf": [
{
"field": "type",
"equals": "Microsoft.Resources/subscriptions/resourceGroups"
},
{
"exists": "false",
"field": "[concat('tags[', parameters('coreTagName1'), ']')]"
}
]
},
"then": {
"effect": "deny"
}
}
},
"id": "/subscriptions/#########/providers/Microsoft.Authorization/policyDefinitions/########",
"type": "Microsoft.Authorization/policyDefinitions",
"name": "#######"
}
But i can still create a Resource Group and not specify any tags at all. I feel like I am missing something fundamental in my approach but cant get my head round it yet.
as Jagrati mentioned. Please allow for sometime for the policy to run a compliance scan before checking for compliance results. (Typically wait time is 30 mins, but it depends heavily on scope and # of resources).
How do I write an Azure policy that only allows resources to be created if both of these conditions are met:
The resource has an "Owner" tag assigned to it
The value of the "Owner" tag is a valid email address format
EDIT: I'd only do simple email address validation as it is supposed to just remind people in my company to use their email address and not their full name. I'm not trying to validate all possible email addresses.
The regex would probably look something like this:
[A-Z0-9a-z._-]+#[A-Za-z0-9.-]+\.[A-Za-z]+
There is built in policies to enforce a tag and its value that you can leverage to customize your own. If you want to add the tag even if it doesnt exisit, you can use the new Modify effect. Here is an example
{"properties": {
"displayName": "Add a tag to resources",
"policyType": "BuiltIn",
"mode": "Indexed",
"description": "Adds the specified tag and value when any resource missing this tag is created or updated. Existing resources can be remediated by triggering a remediation task. If the tag exists with a different value it will not be changed. Does not modify tags on resource groups.",
"metadata": {
"category": "Tags"
},
"parameters": {
"tagName": {
"type": "String",
"metadata": {
"displayName": "Tag Name",
"description": "Name of the tag, such as 'environment'"
}
},
"tagValue": {
"type": "String",
"metadata": {
"displayName": "Tag Value",
"description": "Value of the tag, such as 'production'"
}
}
},
"policyRule": {
"if": {
"field": "[concat('tags[', parameters('tagName'), ']')]",
"exists": "false"
},
"then": {
"effect": "modify",
"details": {
"roleDefinitionIds": [
"/providers/microsoft.authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c"
],
"operations": [
{
"operation": "add",
"field": "[concat('tags[', parameters('tagName'), ']')]",
"value": "[parameters('tagValue')]"
}
]
}
}
}
},"id": "/providers/Microsoft.Authorization/policyDefinitions/4f9dc7db-30c1-420c-b61a-e1d640128d26",
"type": "Microsoft.Authorization/policyDefinitions",
"name": "4f9dc7db-30c1-420c-b61a-e1d640128d26"
}
Now for the email address, you can try using contains or not contains. Information here
Is there a way to create an Azure policy that requires a Tag exist on a resource when it's created, but not check for a specific value? All the examples I've seen are for "check if tag X is there, and has value Y".
I want to simply let the user know "you need to put tag X on this resource" because the value is user-defined so I can't enforce a specific value.
For example - I need "BillingCode" on every resource, but only the person creating the resource knows their correct billing code since it's different for each person or project.
You can use subscription policies to accomplish this. They will prevent deployment of Azure resources unless certain rules are met.
Below example taken from here.
You could modify this example by using the notMatch operator instead of the direct match below. More operators here.
{
"properties": {
"displayName": "Enforce tag and its value on resource groups",
"description": "Enforces a required tag and its value on resource groups.",
"mode": "All",
"parameters": {
"tagName": {
"type": "String",
"metadata": {
"description": "Name of the tag, such as costCenter"
}
},
"tagValue": {
"type": "String",
"metadata": {
"description": "Value of the tag, such as headquarter"
}
}
},
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Resources/subscriptions/resourceGroups"
},
{
"not": {
"field": "[concat('tags[',parameters('tagName'), ']')]",
"equals": "[parameters('tagValue')]"
}
}
]
},
"then": {
"effect": "deny"
}
}
}
}
You need the exists operator.
For example:
{
"policyRule": {
"if": {
"field": "[concat('tags[',parameters('tagName'), ']')]",
"exists": "false"
},
"then": {
"effect": "deny"
}
},
"parameters": {
"tagName": {
"type": "String",
"metadata": {
"description": "Name of the tag, such as costCenter"
}
}
}
}