Azure Policy Tag with predefined values - azure

I struggling currently at some point with Azure Policy. I want to enforce
a specific Tag and its value. (Sounds standard)
But I want to allow one value from a predefined set which
during creation is needed. For e.g.
Environment: (Any of these predefined values are allowed)
Dev
Test
Prod
PreProd
I created an Initiative with some other policies and when I assign this Initiative.
It will enforce only the chosen value but all other values are not allowed.
"properties": {
"displayName": "Tag3",
"policyType": "Custom",
"mode": "All",
"metadata": {
},
"parameters": {
"tags": {
"type": "Array",
"metadata": {
"displayName": "Environment",
"description": "The list of Environments"
},
"allowedValues": [
"Test",
"Dev",
"PreProd",
"Prod"
],
"defaultValue": [
"Prod"
]
}
},
"policyRule": {
"if": {
"not": {
"field": "tags",
"in": "[parameters('tags')]"
}
},
"then": {
"effect": "deny"
}
}
}

Can you pls try this?...
"properties": {
"displayName": "Tag3",
"policyType": "Custom",
"mode": "All",
"metadata": {
},
"parameters": {
"tags": {
"type": "Array",
"metadata": {
"displayName": "Environment",
"description": "The list of Environments"
},
"allowedValues": [
"Test",
"Dev",
"PreProd",
"Prod"
],
"defaultValue": [
"Prod"
]
}
},
"policyRule": {
"if": {
"not": {"or": {
{"field": "tags",
"equals": "Test"},
{"field": "tags",
"equals": "Dev"},
{"field": "tags",
"equals": "PreProd"},
{"field": "tags",
"equals": "Prod"},
}
}
},
"then": {
"effect": "deny"
}
}
}

Set defaultValue without []. Like this one :"defaultValue": "Prod".
For more details, you could refer to this article.

Option1: Remove the "defaultvalue" property and provide the list of the desired values when you assign the policy, as a ';' separated list:
Test;Dev;PreProd
Option2: Leave the "defaultvalue" as array, filled with all allowed values:
"defaultvalue": [
"Test",
"Dev",
"PreProd",
"Prod"
]

Related

Azure Policy to allow only lowercase string

I am planning to achieve the below naming pattern in Azure using a policy.
tstpaas-appName-Env-Serial
tstpaas is a string constant
appname can be string with length of 3-5 characters
env - dev/ust/prd
serial - three numbers
Example:
tstpaas-app-dev-001
All of the characters should be lower case. I am able to match the pattern, however, allowing 3-5 characters for app name and allowing only lower case values is not working. Please let me know how can I achieve this.
Here is my policy:
{
"mode": "All",
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"in": "[parameters('allowedResourceTypes')]"
},
{
"anyOf": [
{
"not": {
"field": "name",
"match": "[parameters('nameMatchPattern1')]"
}
},
{
"not": {
"value": "[if(greaterOrEquals(length(field('name')), 18), substring(field('name'), 14, 3), 'not in allowed values')]",
"in": "[parameters('allowedEnvironments')]"
}
}
]
}
]
},
"then": {
"effect": "deny"
}
},
"parameters": {
"nameMatchPattern1": {
"type": "String",
"metadata": {
"displayName": "nameMatchPattern1",
"description": "Pattern to match for names. Cna include ? and # for digits and letters"
}
},
"allowedResourceTypes": {
"type": "Array",
"metadata": {
"displayName": "allowedResourceTypes",
"description": "List of resource types, for which policy applies"
}
},
"allowedEnvironments": {
"type": "Array",
"metadata": {
"displayName": "Allowed Environments",
"description": "The list of Environments"
},
"allowedValues": [
"dev",
"int",
"uat",
"prd"
]
}
}
}
Parameter for namematchpatter is:
tstpaas-?????-???-###

azure policy : only allow certain tag values in azure resources group tag

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.

Error in policy definition deployment "parameter not found"

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

How to add multible accepted variables to Tag

I can't figure out a way to assign multible accepted Variables on a single tag.
Say we have "Environment Tag"
I want the only accepted variables to be "Production, Testing, Pending"
However i've only been able to assign one Variable per Tag.
I've tried using pre-built policys and build around them. As i'm fairly new to policies.
I have a tag "Environment"
I've created the tag Environment on the sub, so it appears in the dropdown menu.
I've tried to create multible variables in the variable section, however i can only create one.
I can get it working with one variable, such as production, but if i assign more than one variable in the text box it just adds it as one value, i've tried seperation with ("',;:) Nothing seems to work.
{
"properties": {
"displayName": "Require tag and its value",
"policyType": "BuiltIn",
"mode": "Indexed",
"description": "Enforces a required tag and its value. Does not apply to 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": {
"not": {
"field": "[concat('tags[', parameters('tagName'), ']')]",
"equals": "[parameters('tagValue')]"
}
},
"then": {
"effect": "deny"
}
}
},
"id": "/providers/Microsoft.Authorization/policyDefinitions/1e30110a-5ceb-460c-a204-c1c3969c6d62",
"type": "Microsoft.Authorization/policyDefinitions",
"name": "1e30110a-5ceb-460c-a204-c1c3969c6d62"
}
When inputting the TAG, and Variable
"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'"
}
I'd like to know if it's possible to add a secondary tagvalue "Tagvalue1,2,3 ect"
"tagValue": {
"type": "String",
"metadata": {
"displayName": "Tag Value",
"description": "Value of the tag, such as 'production'"
}
"tagValue1": {
"type": "String",
"metadata": {
"displayName": "Tag Value",
"description": "Value of the tag, such as 'Testing'"
}
"tagValue2": {
"type": "String",
"metadata": {
"displayName": "Tag Value",
"description": "Value of the tag, such as 'Pending'"
}
All other Variables for this tag should be rejected.
However i'm unable to get it working.
i think you need to use the in property. from examples:
"parameters": {
"allowedLocations": {
"type": "array",
"metadata": {
"description": "The list of allowed locations for resources.",
"displayName": "Allowed locations",
"strongType": "location"
},
"defaultValue": [ "westus2" ],
"allowedValues": [
"eastus2",
"westus2",
"westus"
]
}
}
and then you can reference it:
{
"field": "location",
"in": "[parameters('allowedLocations')]"
}
You can take an example from Azure documentation site: https://learn.microsoft.com/en-us/azure/governance/policy/samples/enforce-tag-on-resource-groups
If you do not need any parameters for the policy:
{
"properties": {
"displayName": "Enforce tag Environment and its value on resource groups",
"description": "Enforces a required tag and its value on resource groups.",
"mode": "All",
"parameters": {
},
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Resources/subscriptions/resourceGroups"
},
{
"anyOf": [
{
"field": "tags[Environment]",
"notEquals": "Production"
},
{
"field": "tags[Environment]",
"notEquals": "Testing"
},
{
"field": "tags[Environment]",
"notEquals": "Pending"
}
]
}
]
},
"then": {
"effect": "deny"
}
}
}
}
with parameters :
{
"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"
}
},
"tagValue1": {
"type": "String",
"metadata": {
"description": "Value of the tag, such as production"
}
},
"tagValue2": {
"type": "String",
"metadata": {
"description": "Value of the tag, such as testing"
}
},
"tagValue3": {
"type": "String",
"metadata": {
"description": "Value of the tag, such as pending"
}
}
},
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Resources/subscriptions/resourceGroups"
},
{
"anyOf" : [
{
"field": "[concat('tags[',parameters('tagName'), ']')]",
"notEquals": "[parameters('tagValue1')]"
},
{
"field": "[concat('tags[',parameters('tagName'), ']')]",
"notEquals": "[parameters('tagValue2')]"
},
{
"field": "[concat('tags[',parameters('tagName'), ']')]",
"notEquals": "[parameters('tagValue3')]"
}
]
}
]
},
"then": {
"effect": "deny"
}
}
}
}
If you are creating a policy from the Azure Portal, you do not need to copy displayName and description inside properties:
{
"mode": "All",
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Compute/virtualMachines"
},
{
"anyOf": [
{
"field": "tags[Environment]",
"notEquals": "Production"
},
{
"field": "tags[Environment]",
"notEquals": "Testing"
},
{
"field": "tags[Environment]",
"notEquals": "Pending"
}
]
}
]
},
"then": {
"effect": "deny"
}
},
"parameters": {}
}
I've gotten this far thanks to your amazing help, however upon validating new VM's i get the following error, despite which value i type: Pending, Testing or Production
{
"code": "InvalidTemplateDeployment",
"message": "The template deployment failed because of policy violation. Please see details for more information.",
"details": [
{
"code": "RequestDisallowedByPolicy",
"target": "tester123",
"message": "Resource 'tester123' was disallowed by policy. Policy identifiers: '[{\"policyAssignment\":{\"name\":\"Enforce tag Environment\",\"id\":\"/subscriptions/f3434458-6c34-41bf-b159-04eff84fb1b8/providers/Microsoft.Authorization/policyAssignments/363b1c045401446eafdd29bf\"},\"policyDefinition\":{\"name\":\"Enforce tag Environment\",\"id\":\"/subscriptions/f3434458-6c34-41bf-b159-04eff84fb1b8/providers/Microsoft.Authorization/policyDefinitions/7be665bc-57a5-451d-b159-6cabcfd1042a\"}}]'.",
"additionalInfo": [
{
"type": "PolicyViolation",
"info": {
"policyDefinitionDisplayName": "Enforce tag Environment",
"evaluationDetails": {
"evaluatedExpressions": [
{
"result": "True",
"expressionKind": "Field",
"expression": "type",
"path": "type",
"expressionValue": "Microsoft.Compute/virtualMachines",
"targetValue": "Microsoft.Compute/virtualMachines",
"operator": "Equals"
},
{
"result": "True",
"expressionKind": "Field",
"expression": "tags[Environment]",
"path": "tags[Environment]",
"expressionValue": "Testing",
"targetValue": "Production",
"operator": "NotEquals"
}
]
},
"policyDefinitionId": "/subscriptions/f3434458-6c34-41bf-b159-04eff84fb1b8/providers/Microsoft.Authorization/policyDefinitions/7be665bc-57a5-451d-b159-6cabcfd1042a",
"policyDefinitionName": "7be665bc-57a5-451d-b159-6cabcfd1042a",
"policyDefinitionEffect": "deny",
"policyAssignmentId": "/subscriptions/f3434458-6c34-41bf-b159-04eff84fb1b8/providers/Microsoft.Authorization/policyAssignments/363b1c045401446eafdd29bf",
"policyAssignmentName": "363b1c045401446eafdd29bf",
"policyAssignmentDisplayName": "Enforce tag Environment",
"policyAssignmentScope": "/subscriptions/f3434458-6c34-41bf-b159-04eff84fb1b8",
"policyAssignmentParameters": {}
}
}
]
}
]
}
it would appear to me at least, that i fail because of wrong targetvalue. However I'd suppose that anyof the 3 options defined in policy definition would do?
Atleast i figured out how to only target this to our VM's, or at least i think i did.
There is a solution for restricting the values in basics called "allowedValues":
https://learn.microsoft.com/pl-pl/azure/governance/policy/concepts/definition-structure
https://learn.microsoft.com/pl-pl/azure/governance/policy/concepts/definition-structure#parameter-properties
"parameters": {
"allowedLocations": {
"type": "array",
"metadata": {
"description": "The list of allowed locations for resources.",
"displayName": "Allowed locations",
"strongType": "location"
},
"defaultValue": [ "westus2" ],
"allowedValues": [
"eastus2",
"westus2",
"westus"
]
}
}

Appending tag policy isn't working for some resources

I'm creating one azure policy to appending tags to newly created resources, it works well for most components, but I found this policy is not working for some components, for example: logic apps.
{
"mode": "All",
"parameters": {
"Environment": {
"type": "String",
"metadata": {
"displayName": "Environment"
},
"defaultValue": "dev"
},
"Owner": {
"type": "String",
"metadata": {
"displayName": "Owner"
},
"defaultValue": "Admin"
},
"CostCenter": {
"type": "String",
"metadata": {
"displayName": "CostCenter"
},
"defaultValue": "NA"
}
},
"policyRule": {
"if": {
"field": "tags",
"exists": "false"
},
"then": {
"effect": "append",
"details": [
{
"field": "tags",
"value": {
"Environment": "[parameters('Environment')]",
"Owner": "[parameters('Owner')]",
"CostCenter": "[parameters('CostCenter')]"
}
}
]
}
}
}
I added a similar policy to apply tags to resource groups, doesn't working at all, I have no idea what's going on.
{
"mode": "All",
"parameters": {
"Environment": {
"type": "String",
"metadata": {
"displayName": "Environment"
},
"defaultValue": "dev"
},
"Owner": {
"type": "String",
"metadata": {
"displayName": "Owner"
},
"defaultValue": "admin"
},
"CostCenter": {
"type": "String",
"metadata": {
"displayName": "CostCenter"
},
"defaultValue": "NA"
}
}
"policyRule": {
"if": {
"allOf": [
{
"field": "tags",
"exists": "false"
},
{
"field": "type",
"equals": "Microsoft.Resources/subscriptions/resourceGroups"
}
]
},
"then": {
"effect": "append",
"details": [
{
"field": "tags",
"value": {
"Environment": "[parameters('Environment')]",
"Owner": "[parameters('Owner')]",
"CostCenter": "[parameters('CostCenter')]"
}
}
]
}
}
}
Figure it out myself, The "exists": "false" condition in my policy will only trigger if the "tags" property is either missing or null, so a resource group or resource with "tags": {} will bypass my policy even though it doesn't have any tags.
Besides, the simple checking on tags is not reasonable, should check by tag name from one to another, if not meet, take action to append.
And I also found below statement isn't working for resource groups, maybe because it's irregular practices.
{
"then": {
"effect": "append",
"details": [
{
"field": "tags",
"value": {
"Environment": "[parameters('Environment')]",
"Owner": "[parameters('Owner')]",
"CostCenter": "[parameters('CostCenter')]"
}
}
]
}
}
suggest using below statement instead
{
"then": {
"effect": "append",
"details": [
{
"field": "tags['Environment']",
"value": "[parameters('Environment')]"
},
{
"field": "tags['Owner']",
"value": "[parameters('Owner')]"
},
{
"field": "tags['CostCenter']",
"value": "[parameters('CostCenter')]"
}
]
}
}

Resources