From f356baa91624f78f7dfd01805ecf1727b09dc985 Mon Sep 17 00:00:00 2001 From: Hugo Ribeiro Date: Fri, 17 Jan 2025 14:35:15 +0000 Subject: [PATCH] Add policy Enforce tag Name and Value casing on resource groups and subscriptions --- .../azurepolicy.json | 100 ++++++++++++++++++ .../azurepolicy.parameters.json | 42 ++++++++ .../azurepolicy.rules.json | 45 ++++++++ 3 files changed, 187 insertions(+) create mode 100644 policyDefinitions/Tags/enforce-tag-name-and-value-casing-on-rg-and-sub/azurepolicy.json create mode 100644 policyDefinitions/Tags/enforce-tag-name-and-value-casing-on-rg-and-sub/azurepolicy.parameters.json create mode 100644 policyDefinitions/Tags/enforce-tag-name-and-value-casing-on-rg-and-sub/azurepolicy.rules.json diff --git a/policyDefinitions/Tags/enforce-tag-name-and-value-casing-on-rg-and-sub/azurepolicy.json b/policyDefinitions/Tags/enforce-tag-name-and-value-casing-on-rg-and-sub/azurepolicy.json new file mode 100644 index 00000000..105b0ffe --- /dev/null +++ b/policyDefinitions/Tags/enforce-tag-name-and-value-casing-on-rg-and-sub/azurepolicy.json @@ -0,0 +1,100 @@ +{ + "name": "dd478b1b-83a0-48d3-92fe-bba17c3a72a4", + "type": "Microsoft.Authorization/policyDefinitions", + "properties": { + "displayName": "Enforce tag Name and Value casing on resource groups and subscriptions", + "description": "This policy can be used to convert a specific tag name and value on a resource to either being all lowercase or all uppercase. IMPORTANT: Tag Names are NOT case sensitive in azure therefore this is just a workaround that might stop working at any time.", + "mode": "All", + "metadata": { + "category": "Tags", + "version": "1.0.0" + }, + "parameters": { + "toLowerOrToUpper": { + "type": "String", + "metadata": { + "displayName": "Enforce lowercase or uppercase", + "description": "If set to lowercase/uppercase then the Policy will convert the tag name and value on existing and new resources groups to lowercase/Uppercase " + }, + "allowedValues": [ + "Lowercase", + "Uppercase" + ] + }, + "tagName": { + "type": "String", + "metadata": { + "displayName": "TagName", + "description": "Tag name that will be used for enforcement of lowercase/uppercase case." + } + }, + "applyCaseToValue": { + "type": "Boolean", + "metadata": { + "displayName": "Apply Case to Value", + "description": "Control if the same case applied to the tag name should be applied to the value." + }, + "defaultValue": true + }, + "effect": { + "type": "String", + "metadata": { + "displayName": "Effect", + "description": "Modify, Deny, Audit or Disabled the execution of the Policy" + }, + "allowedValues": [ + "Modify", + "Deny", + "Audit", + "Disabled" + ], + "defaultValue": "Modify" + } + }, + "policyRule": { + "if": { + "allOf": [ + { + "anyOf": [ + { + "field": "type", + "equals": "Microsoft.Resources/subscriptions" + }, + { + "field": "type", + "equals": "Microsoft.Resources/subscriptions/resourceGroups" + } + ] + }, + { + "field": "[concat('tags[', parameters('tagName'), ']')]", + "exists": true + }, + { + "value": "[if(empty(field('tags')), bool('false'), if(contains(field('tags'), parameters('tagName')), bool('true'), bool('false')))]", + "equals": true + }, + { + "value": "[if(empty(field('tags')), bool('false'), if(contains(field('tags'), parameters('tagName')), if(equals(parameters('applyCaseToValue'), bool('true')),if(equals(parameters('toLowerOrToUpper'), 'Lowercase'), not(equals(base64(toLower(string(field(concat('tags[', parameters('tagName'), ']'))))), base64(string(field(concat('tags[', parameters('tagName'), ']')))))), not(equals(base64(toUpper(string(field(concat('tags[', parameters('tagName'), ']'))))), base64(string(field(concat('tags[', parameters('tagName'), ']'))))))), bool('false')), bool('false')))]", + "equals": true + } + ] + }, + "then": { + "effect": "[parameters('effect')]", + "details": { + "roleDefinitionIds": [ + "/providers/microsoft.authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c" + ], + "operations": [ + { + "operation": "addOrReplace", + "field": "tags", + "value": "[json(if(empty(field('tags')), '{}', if(equals(parameters('toLowerOrToUpper'), 'Lowercase'), string(union(field('tags'), createObject(tolower(parameters('tagName')), if(parameters('applyCaseToValue'),toLower(string(field(concat('tags[', parameters('tagName'), ']')))) , string(field(concat('tags[', parameters('tagName'), ']'))))))), string(union(field('tags'), createObject(toUpper(parameters('tagName')), if(parameters('applyCaseToValue'),toUpper(string(field(concat('tags[', parameters('tagName'), ']')))) , string(field(concat('tags[', parameters('tagName'), ']'))))))))))]" + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/policyDefinitions/Tags/enforce-tag-name-and-value-casing-on-rg-and-sub/azurepolicy.parameters.json b/policyDefinitions/Tags/enforce-tag-name-and-value-casing-on-rg-and-sub/azurepolicy.parameters.json new file mode 100644 index 00000000..b871c3bf --- /dev/null +++ b/policyDefinitions/Tags/enforce-tag-name-and-value-casing-on-rg-and-sub/azurepolicy.parameters.json @@ -0,0 +1,42 @@ +{ + "toLowerOrToUpper": { + "type": "String", + "metadata": { + "displayName": "Enforce lowercase or uppercase", + "description": "If set to lowercase/uppercase then the Policy will convert the tag name and value on existing and new resources groups to lowercase/Uppercase " + }, + "allowedValues": [ + "Lowercase", + "Uppercase" + ] + }, + "tagName": { + "type": "String", + "metadata": { + "displayName": "TagName", + "description": "Tag name that will be used for enforcement of lowercase/uppercase case." + } + }, + "applyCaseToValue": { + "type": "Boolean", + "metadata": { + "displayName": "Apply Case to Value", + "description": "Control if the same case applied to the tag name should be applied to the value." + }, + "defaultValue": true + }, + "effect": { + "type": "String", + "metadata": { + "displayName": "Effect", + "description": "Modify, Deny, Audit or Disabled the execution of the Policy" + }, + "allowedValues": [ + "Modify", + "Deny", + "Audit", + "Disabled" + ], + "defaultValue": "Modify" + } +} \ No newline at end of file diff --git a/policyDefinitions/Tags/enforce-tag-name-and-value-casing-on-rg-and-sub/azurepolicy.rules.json b/policyDefinitions/Tags/enforce-tag-name-and-value-casing-on-rg-and-sub/azurepolicy.rules.json new file mode 100644 index 00000000..3e27a0d2 --- /dev/null +++ b/policyDefinitions/Tags/enforce-tag-name-and-value-casing-on-rg-and-sub/azurepolicy.rules.json @@ -0,0 +1,45 @@ +{ + "if": { + "allOf": [ + { + "anyOf": [ + { + "field": "type", + "equals": "Microsoft.Resources/subscriptions" + }, + { + "field": "type", + "equals": "Microsoft.Resources/subscriptions/resourceGroups" + } + ] + }, + { + "field": "[concat('tags[', parameters('tagName'), ']')]", + "exists": true + }, + { + "value": "[if(empty(field('tags')), bool('false'), if(contains(field('tags'), parameters('tagName')), bool('true'), bool('false')))]", + "equals": true + }, + { + "value": "[if(empty(field('tags')), bool('false'), if(contains(field('tags'), parameters('tagName')), if(equals(parameters('applyCaseToValue'), bool('true')),if(equals(parameters('toLowerOrToUpper'), 'Lowercase'), not(equals(base64(toLower(string(field(concat('tags[', parameters('tagName'), ']'))))), base64(string(field(concat('tags[', parameters('tagName'), ']')))))), not(equals(base64(toUpper(string(field(concat('tags[', parameters('tagName'), ']'))))), base64(string(field(concat('tags[', parameters('tagName'), ']'))))))), bool('false')), bool('false')))]", + "equals": true + } + ] + }, + "then": { + "effect": "[parameters('effect')]", + "details": { + "roleDefinitionIds": [ + "/providers/microsoft.authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c" + ], + "operations": [ + { + "operation": "addOrReplace", + "field": "tags", + "value": "[json(if(empty(field('tags')), '{}', if(equals(parameters('toLowerOrToUpper'), 'Lowercase'), string(union(field('tags'), createObject(tolower(parameters('tagName')), if(parameters('applyCaseToValue'),toLower(string(field(concat('tags[', parameters('tagName'), ']')))) , string(field(concat('tags[', parameters('tagName'), ']'))))))), string(union(field('tags'), createObject(toUpper(parameters('tagName')), if(parameters('applyCaseToValue'),toUpper(string(field(concat('tags[', parameters('tagName'), ']')))) , string(field(concat('tags[', parameters('tagName'), ']'))))))))))]" + } + ] + } + } +} \ No newline at end of file