-
Notifications
You must be signed in to change notification settings - Fork 567
[Examples] Create Custom Policies Policy Sets and Assignments
This page describes how to deploy your Azure landing zone with custom policy definitions and policy set (Initiative) definitions.
In this example you will use three custom policies and a custom policy set definition. The custom policies will be named Enforce-RG-Tags
, Enforce-Resource-Tags
and Deny-NIC-NSG
. You will then create a custom policy set definition (Initiative) named Enforce-Mandatory-Tags
that will include the Enforce-RG-Tags
and Enforce-Resource-Tags
custom policies.
You will update the built-in configuration by following these steps:
- Create the custom policy definition file for
Enforce-RG-Tags
- Create the custom policy definition file for
Enforce-Resource-Tags
- Create the custom policy definition file for
Deny-NIC-NSG
- Create the custom policy set definition file for
Enforce-Mandatory-Tags
- Make the custom policy definitions available for use in Azure by extending the built-in archetype for
es_root
- Create the policy assignment files for
Enforce-RG-Tags
,Enforce-Resource-Tags
,Deny-NIC-NSG
andEnforce-Mandatory-Tags
- Assign the custom policy set definition for
Enforce-Mandatory-Tags
at thees_root
Management Group by extending the built-in archetype fores_root
- Assign the custom policy definition for
Deny-NIC-NSG
at theLanding Zones
Management Group by extending the built-in archetype fores_landing_zones
IMPORTANT: To allow the declaration of custom or expanded templates, you must create a custom library folder within the root module and include the path to this folder using the
library_path
variable within the module configuration. In our example, the directory is/lib
.
In order to create and assign custom policies, we need to create both a definition file and an assignment file for each custom policy or custom policy set definition. In this example we will do this by using the below files:
- lib/policy_definitions/policy_definition_es_enforce_rg_tags.json
- lib/policy_definitions/policy_definition_es_enforce_resource_tags.json
- lib/policy_definitions/policy_definition_es_deny_nic_nsg.json
- lib/policy_set_definitions/policy_set_definition_enforce_mandatory_tagging.json
- lib/policy_assignments/policy_assignment_es_enforce_rg_tags.json
- lib/policy_assignments/policy_assignment_es_enforce_resource_tags.json
- lib/policy_assignments/policy_assignment_es_deny_nic_nsg.json
- lib/policy_assignments/policy_assignment_es_enforce_mandatory_tagging.json
NOTE: This module provides the ability to define custom template variables used when reading in template files from the built-in and custom library_path. For more info click here.
In your /lib
directory create a policy_definitions
subdirectory if you don't already have one. You can learn more about archetypes and custom libraries in this article.
NOTE: Creating a
policy_definitions
subdirectory is a recommendation only. If you prefer not to create one or to call it something else, the custom policies will still work.
In the policy_definitions
subdirectory, create a policy_definition_es_policy_enforce_rg_tags.json
file. This file will contain the policy definition for Enforce-RG-Tags
. Copy the below code in to the file and save it.
{
"name": "Enforce-RG-Tags",
"type": "Microsoft.Authorization/policyDefinitions",
"apiVersion": "2021-06-01",
"scope": null,
"properties": {
"displayName": "Resource groups must have mandatory tagging applied",
"policyType": "Custom",
"mode": "All",
"description": "Enforce mandatory 'Owner' and 'Department' tags on Resource Groups",
"metadata": {
"version": "1.0.0",
"category": "Tags"
},
"policyRule": {
"if": {
"allOf":[
{
"field": "type",
"equals": "Microsoft.Resources/subscriptions/resourceGroups"
},
{
"anyof": [
{
"field": "[concat('tags[', parameters('Owner'), ']')]",
"exists": "false"
},
{
"field": "[concat('tags[', parameters('Department'), ']')]",
"exists": "false"
}
]
}
]
},
"then": {
"effect": "deny"
}
},
"parameters": {
"Owner": {
"type": "String",
"metadata": {
"displayName": "Owner",
"description": "Specifies the Owner of the Resource Group'"
}
},
"Department": {
"type": "String",
"metadata": {
"displayName": "Department",
"description": "Specifies the Department that the Resource Group belongs to"
}
}
}
}
}
Now create a policy_definition_es_policy_enforce_resource_tags.json
file. This file will contain the policy definition for Enforce-Resource-Tags
. Copy the below code in to the file and save it.
{
"name": "Enforce-Resource-Tags",
"type": "Microsoft.Authorization/policyDefinitions",
"apiVersion": "2021-06-01",
"scope": null,
"properties": {
"displayName": "Resources must have mandatory tagging applied",
"policyType": "Custom",
"mode": "Indexed",
"description": "Enforce mandatory 'Owner' and 'Department' tags on Resources",
"metadata": {
"version": "1.0.0",
"category": "Tags"
},
"policyRule": {
"if": {
"anyof": [
{
"field": "[concat('tags[', parameters('Owner'), ']')]",
"exists": "false"
},
{
"field": "[concat('tags[', parameters('Department'), ']')]",
"exists": "false"
}
]
},
"then": {
"effect": "deny"
}
},
"parameters": {
"Owner": {
"type": "String",
"metadata": {
"displayName": "Owner",
"description": "Specifies the Owner of the resource"
}
},
"Department": {
"type": "String",
"metadata": {
"displayName": "Department",
"description": "Specifies the Department that the resource belongs to"
}
}
}
}
}
Next create a policy_definition_es_policy_deny_nsg_nic.json
file. This file will contain the policy definition for our last custom policy - Deny-NSG-NIC
. Copy the below code in to the file and save it.
{
"type": "Microsoft.Authorization/policyDefinitions",
"name": "Deny-NIC-NSG",
"properties": {
"displayName": "Prevent Network Security Groups from being applied to Network Interface Cards",
"description": "This policy will prevent NSGs from being applied to network interface cards.",
"policyType": "Custom",
"mode": "All",
"metadata": {
"version": "1.0.0",
"category": "Network"
},
"parameters": {
"effect": {
"type": "String",
"defaultValue": "deny",
"allowedValues": [
"audit",
"deny",
"disabled"
],
"metadata": {
"displayName": "Effect",
"description": "Enable or disable the execution of the policy"
}
}
},
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Network/networkInterfaces"
},
{
"field": "Microsoft.Network/networkInterfaces/networkSecurityGroup.id",
"like": "*"
}
]
},
"then": {
"effect": "[parameters('effect')]"
}
}
}
}
In your /lib
directory create a policy_set_definitions
subdirectory.
NOTE: Creating a
policy_set_definitions
subdirectory is a recommendation only. If you prefer not to create one or to call it something else, the custom policies will still work.
In the policy_set_definitions
subdirectory, create a policy_set_definition_enforce_mandatory_tags.json
file. This file will contain the Policy Set Definition for Enforce-Mandatory-Tags
. The policy set will contain the Enforce-RG-Tags
and Enforce-Resource-Tags
custom policies that you previously created. Copy the below code in to the file and save it.
{
"name": "Enforce-Mandatory-Tags",
"type": "Microsoft.Authorization/policySetDefinitions",
"apiVersion": "2021-06-01",
"scope": null,
"properties": {
"policyType": "Custom",
"displayName": "Ensure mandatory tagging is applied to both Resources and Resource Groups",
"description": "Contains the core tagging policies applicable to the org",
"metadata": {
"version": "1.0.0",
"category": "General"
},
"parameters": {
"EnforceRGTags-Owner": {
"type": "String",
"metadata": {
"displayName": "Owner",
"description": "Specifies the Owner of the Resource Group"
}
},
"EnforceRGTags-Department": {
"type": "String",
"metadata": {
"displayName": "Department",
"description": "Specifies the Department that the Resource Group belongs to"
}
},
"EnforceResourceTags-Owner": {
"type": "String",
"metadata": {
"displayName": "Owner",
"description": "Specifies the Owner of the resource"
}
},
"EnforceResourceTags-Department": {
"type": "String",
"metadata": {
"displayName": "Department",
"description": "Specifies the Department that the resource belongs to"
}
}
},
"policyDefinitions": [
{
"policyDefinitionReferenceId": "Resource groups must have mandatory tagging applied",
"policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policyDefinitions/Enforce-RG-Tags",
"parameters": {
"Owner": {
"value": "[parameters('EnforceRGTags-Owner')]"
},
"Department": {
"value": "[parameters('EnforceRGTags-Department')]"
}
},
"groupNames": []
},
{
"policyDefinitionReferenceId": "Resources must have mandatory tagging applied",
"policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policyDefinitions/Enforce-Resource-Tags",
"parameters": {
"Owner": {
"value": "[parameters('EnforceResourceTags-Owner')]"
},
"Department": {
"value": "[parameters('EnforceResourceTags-Department')]"
}
},
"groupNames": []
}
],
"policyDefinitionGroups": null
}
}
In order to assign your custom policies or policy sets, you need to create policy assignment files. The first step is to create a policy_assignments
subdirectory within /lib
.
NOTE: Creating a
policy_assignments
subdirectory within\lib
is a recommendation only. If you prefer not to create one or to call it something else, the custom policies will still work.
- lib/policy_assignments/policy_assignment_es_enforce_rg_tags.json
- lib/policy_assignments/policy_assignment_es_enforce_resource_tags.json
- lib/policy_assignments/policy_assignment_es_deny_nic_nsg.json
- lib/policy_assignments/policy_assignment_es_enforce_mandatory_tagging.json
You will then need to create a file named policy_assignment_es_enforce_rg_tags.json
within the policy_assignments
directory. Copy the below code in to the file and save it.
{
"name": "Enforce-RG-Tags",
"type": "Microsoft.Authorization/policyAssignments",
"apiVersion": "2019-09-01",
"properties": {
"description": "Enforce Mandatory Tags on Resource Groups",
"displayName": "Resource groups must have mandatory tagging applied",
"notScopes": [],
"parameters": {
} ,
"policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policyDefinitions/Enforce-RG-Tags",
"nonComplianceMessages": [
{
"message": "Mandatory tags {enforcementMode} be applied to Resource Groups."
}
],
"scope": "${current_scope_resource_id}",
"enforcementMode": null,
"nonComplianceMessages": [
{
"message": "Mandatory tags must be provided."
}
]
},
"location": "${default_location}",
"identity": {
"type": "SystemAssigned"
}
}
Now create a file named policy_assignment_es_enforce_resource_tags.json
within the policy_assignments
directory. Copy the below code in to the file and save it.
{
"name": "Enforce-Resource-Tags",
"type": "Microsoft.Authorization/policyAssignments",
"apiVersion": "2019-09-01",
"properties": {
"description": "Enforce Mandatory Tags on Resources",
"displayName": "Resources must have mandatory tagging applied",
"notScopes": [],
"parameters": {
} ,
"policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policyDefinitions/Enforce-Resource-Tags",
"nonComplianceMessages": [
{
"message": "Mandatory tags {enforcementMode} be applied to resources."
}
],
"scope": "${current_scope_resource_id}",
"enforcementMode": null,
"nonComplianceMessages": [
{
"message": "Mandatory tags must be provided."
}
]
},
"location": "${default_location}",
"identity": {
"type": "SystemAssigned"
}
}
Next create a file named policy_assignment_es_deny_nic_nsg.json
within the policy_assignments
directory. Copy the below code in to the file and save it.
{
"name": "Deny-NIC-NSG",
"type": "Microsoft.Authorization/policyAssignments",
"apiVersion": "2019-09-01",
"properties": {
"description": "This policy will prevent NSGs from being applied to network interface cards.",
"displayName": "Prevent Network Security Groups from being applied to Network Interface Cards",
"notScopes": [],
"parameters": {} ,
"policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policyDefinitions/Deny-NIC-NSG",
"nonComplianceMessages": [
{
"message": "NSGs {enforcementMode} not be applied to network interface cards."
}
],
"scope": "${current_scope_resource_id}",
"enforcementMode": null,
"nonComplianceMessages": [
{
"message": "NSGs must not be applied to Network Interface cards."
}
]
},
"location": "${default_location}",
"identity": {
"type": "SystemAssigned"
}
}
Finally, create a file named policy_assignment_es_enforce_mandatory_tagging.json
. Copy the below code in to the file and save it.
{
"name": "Enforce-Mandatory-Tags",
"type": "Microsoft.Authorization/policyAssignments",
"apiVersion": "2019-09-01",
"properties": {
"description": "Contains the core policies applicable to the org",
"displayName": "Ensure mandatory tagging is applied to both Resources and Resource Groups",
"notScopes": [],
"parameters": {
"EnforceRGTags-Owner": {
"Value": "Jane Doe"
},
"EnforceRGTags-Department": {
"Value": "IT"
},
"EnforceResourceTags-Owner": {
"Value": "Jane Doe"
},
"EnforceResourceTags-Department": {
"Value": "IT"
}
},
"policyDefinitionId": "${root_scope_resource_id}/providers/Microsoft.Authorization/policySetDefinitions/Enforce-Mandatory-Tags",
"nonComplianceMessages": [
{
"message": "Mandatory tags {enforcementMode} be applied to Resources and Resource Groups."
}
],
"scope": "${current_scope_resource_id}",
"enforcementMode": null
},
"location": "${default_location}",
"identity": {
"type": "SystemAssigned"
}
}
You now need to save your custom policy and policy set definitions at the es_root
Management Group to ensure they can be used at that scope or any scope beneath. To do that, we need to extend the built-in archetype for es_root
.
NOTE: Extending built-in archetypes is explained further in this article.
If you don't already have an archetype_extension_es_root.tmpl.json
file within your custom /lib
directory, create one and copy the below code in to the file. This code saves the custom policy definition and policy set definitions but we still haven't assigned them anywhere yet.
{
"extend_es_root": {
"policy_assignments": [],
"policy_definitions": ["Enforce-RG-Tags", "Enforce-Resource-Tags", "Deny-NIC-NSG"],
"policy_set_definitions": ["Enforce-Mandatory-Tags"],
"role_definitions": [],
"archetype_config": {
"access_control": {
}
}
}
}
You now need to assign the Enforce-Mandatory-Tags
policy set and in this example, we will assign it at es_root
. To do this, update your existing archetype_extension_es_root.tmpl.json
file with the below code and save it.
{
"extend_es_root": {
"policy_assignments": ["Enforce-Mandatory-Tags"],
"policy_definitions": ["Enforce-RG-Tags", "Enforce-Resource-Tags", "Deny-NIC-NSG"],
"policy_set_definitions": ["Enforce-Mandatory-Tags"],
"role_definitions": [],
"archetype_config": {
"access_control": {
}
}
}
}
You should now kick-off your Terraform workflow (init, plan, apply) to apply the new configuration. This can be done either locally or through a pipeline. When your workflow has finished, the Enforce-Mandatory-Tags
policy set will be assigned at es_root
.
As you have already saved the Deny-NIC-NSG
Custom Policy Set at es_root
, this gives us the ability to assign it at the es_root
scope or at any scope beneath it. In this example, we will assign it at the Landing Zones
Management Group. To do this, either update your existing archetype_extension_es_landing_zones.tmpl.json
file or create one and copy the below code in to it and save.
{
"extend_es_landing_zones": {
"policy_assignments": ["Deny-NIC-NSG"],
"policy_definitions": [],
"policy_set_definitions": [],
"role_definitions": [],
"archetype_config": {
"access_control": {
}
}
}
}
You should now kick-off your Terraform workflow (init, plan, apply) again to apply the updated configuration. This can be done either locally or through a pipeline. When your workflow has finished, the Deny-NIC-NSG
Policy Definition will be assigned at the Landing Zones
Management Group.
You have now successfully created and assigned both a Custom Policy Definition and a Custom Policy Set Definition within your Azure environment. You can re-use the steps in this article for any Custom Policies of your own that you may wish to use.
This wiki is being actively developed
If you discover any documentation bugs or would like to request new content, please raise them as an issue or feel free to contribute to the wiki via a pull request. The wiki docs are located in the repository in the docs/wiki/
folder.
- Home
- User guide
- Video guides
-
Examples
- Level 100
- Level 200
-
Level 300
- Deploy multi region networking with custom settings (Hub and Spoke)
- Deploy multi region networking with custom settings (Virtual WAN)
- Deploy with Zero Trust network principles (Hub and Spoke)
- Deploy identity resources with custom settings
- Deploy management resources with custom settings
- Expand built-in archetype definitions
- Create custom policies, initiatives and assignments
- Override module role assignments
- Control policy enforcement mode
- Policy assignments with user assigned managed identities
- Level 400
- Frequently Asked Questions
- Troubleshooting
- Contributing