Policies, Assignments and Roles
Documentation for Azure Policy definitions, initiatives, assignments, and custom role definitions within the Sovereign Landing Zones Library.
Table of Contents
Introduction
The core assets in a library are the definitions and assignments for Azure Policy, and the custom role definitions for RBAC. These will be grouped together into archetypes on the next page, but let’s explore these first.
Policy Definitions
Full JSON definitions of custom policies.
policy_definitions/<name>.alz_policy_definition.json
Policy: Enforce-KV-Premium
{
"name": "Enforce-KV-Premium",
"type": "Microsoft.Authorization/policyDefinitions",
"properties": {
"displayName": "Enforce Azure Key Vault Premium SKU",
"description": "This policy enforces Premium sku for Azure Key Vaults.",
"policyType": "Custom",
"metadata": {
"category": "Key Vault",
"alzCloudEnvironments": [
"AzureCloud"
],
"source": "https://github.com/richeney-org/Sovereign-Landing-Zone-Packs/",
"version": "1.0.0"
},
"mode": "Indexed",
"parameters": {
"effect": {
"type": "String",
"metadata": {
"displayName": "Effect",
"description": "Deny, Audit or Disabled the execution of the Policy"
},
"allowedValues": [
"Deny",
"Audit",
"Disabled"
],
"defaultValue": "Audit"
}
},
"policyRule": {
"if": {
"allOf": [
{
"equals": "Microsoft.KeyVault/Vaults",
"field": "type"
},
{
"field": "Microsoft.KeyVault/Vaults/sku.name",
"notEquals": "premium"
}
]
},
"then": {
"effect": "[parameters('effect')]"
}
}
}
}
- The name in the file - Enforce-KV-Premium - will be used in the archetype definition.
- The metadata is recommended for tracing the source of definitions and for visibility in the portal.
- This custom policy definition is based on one of the Azure/Community-Policy repo’s Key Vault samples, enforce-key-vault-premium-sku.
Policy Set Definitions
Collections of related policy definitions that are grouped together for simplified management and assignment. Also called Policy Initiatives. The policy definitions referenced by the policy set definition may either be built-in definitions or custom.
policy_set_definitions/<name>.alz_policy_set_definition.json
Policy Set #1: Deny-NL-Global
{
"name": "Deny-NL-Global",
"type": "Microsoft.Authorization/policySetDefinitions",
"apiVersion": "2021-06-01",
"properties": {
"displayName": "Deny - Additional Non-BIO Sovereignty Controls for the Netherlands - Global",
"description": "This policy set enforces optional global security controls for Dutch organizations including geographic restrictions to EU regions.",
"policyType": "Custom",
"metadata": {
"category": "Regulatory Compliance",
"alzCloudEnvironments": [
"AzureCloud"
],
"source": "https://github.com/richeney-org/Sovereign-Landing-Zone-Packs/",
"version": "1.0.0"
},
"parameters": {
"allowedLocations": {
"type": "Array",
"metadata": {
"displayName": "Allowed locations",
"description": "The list of locations that can be specified when deploying resources",
"strongType": "location"
},
"defaultValue": []
}
},
"policyDefinitions": [
{
"policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/e56962a6-4747-49cd-b67b-bf8b01975c4c",
"policyDefinitionReferenceId": "AllowedLocations",
"parameters": {
"listOfAllowedLocations": {
"value": "[parameters('allowedLocations')]"
}
}
}
]
}
}
- The name in the file - Deny-NL-Global - will be used in the archetype definition.
- This is an example of a policy set with only a single built-in policy, AllowedLocations.
- A benefit of assigning policy sets is that they can be easily expanded without creating additional clutter.
- It is common to have restrictive defaults, e.g. the empty list for allowed location.
Policy Set #2: Deny-NL-Confidential
{
"name": "Deny-NL-Confidential",
"type": "Microsoft.Authorization/policySetDefinitions",
"apiVersion": "2021-06-01",
"properties": {
"displayName": "Deny - Additional Non-BIO Sovereignty Controls for the Netherlands - Confidential Workloads",
"description": "This policy set enforces optional security controls for Dutch confidential workloads.",
"policyType": "Custom",
"metadata": {
"category": "Regulatory Compliance",
"alzCloudEnvironments": [
"AzureCloud"
],
"source": "https://github.com/richeney-org/Sovereign-Landing-Zone-Packs/",
"version": "1.0.0"
},
"parameters": {
"AllowedVirtualMachineSKUs": {
"type": "Array",
"metadata": {
"displayName": "Allowed virtual machine SKUs",
"description": "The list of virtual machine SKUs that can be deployed"
},
"defaultValue": []
},
"effectForKeyVaultPremiumSKU": {
"type": "String",
"metadata": {
"displayName": "Effect for Key Vault Premium SKU policy",
"description": "The effect determines what happens when the policy rule is evaluated to match"
},
"allowedValues": [
"Audit",
"Deny",
"Disabled"
],
"defaultValue": "Deny"
}
},
"policyDefinitions": [
{
"policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/cccc23c7-8427-4f53-ad12-b6a63eb452b3",
"policyDefinitionReferenceId": "AllowedVirtualMachineSKUs",
"parameters": {
"listOfAllowedSKUs": {
"value": "[parameters('AllowedVirtualMachineSKUs')]"
}
}
},
{
"policyDefinitionId": "/providers/Microsoft.Management/managementGroups/placeholder/providers/Microsoft.Authorization/policyDefinitions/Enforce-KV-Premium",
"policyDefinitionReferenceId": "KeyVaultShouldUsePremiumSKU",
"parameters": {
"effect": {
"value": "[parameters('effectForKeyVaultPremiumSKU')]"
}
}
}
]
}
}
- The name in the file - Deny-NL-Confidential - will be used in the archetype definition.
- This file includes built-in and custom so that you can compare the policyDefinitionIds.
- The first policy, AllowedVirtualMachineSKUs, is built in.
- The second policy, KeyVaultShouldUsePremiumSKU, is the custom policy above.
- The policyDefinitionId for the custom policy includes “placeholder”.
- This will automatically be replaced with the correct management group name by the alz provider.
Policy Assignments
Policy Assignments for both policy definitions and policy set definitions. It is more common to assign policy sets as this is a more manageable and scalable approach. The policy and policy set definitions can either be built-in definitions, or the custom definitions shown above.
policy_assignments/<name>.alz_policy_assignment.json
Assignment #1: Audit-NL-BIO
{
"type": "Microsoft.Authorization/policyAssignments",
"apiVersion": "2024-04-01",
"name": "Audit-NL-BIO",
"location": "${default_location}",
"dependsOn": [],
"identity": {
"type": "SystemAssigned"
},
"properties": {
"description": "This policy assignment audits compliance with the Dutch Baseline Informatiebeveiliging (BIO) controls specifically for the 'thema-uitwerking Clouddiensten' theme. It includes policies covered under SOC2 and ISO 27001:2013 controls to ensure compliance with Dutch cybersecurity standards.",
"displayName": "Audit - Dutch BIO Cloud Theme V2 Compliance (Global)",
"policyDefinitionId": "/providers/Microsoft.Authorization/policySetDefinitions/d8b2ffbe-c6a8-4622-965d-4ade11d1d2ee",
"definitionVersion": "2.*.*",
"enforcementMode": "Default",
"nonComplianceMessages": [
{
"message": "Resources must comply with Dutch BIO Cloud Theme V2 requirements for information security and data protection."
}
],
"parameters": {},
"scope": "/providers/Microsoft.Management/managementGroups/placeholder",
"notScopes": []
}
}
- The name in the file - Audit-NL-BIO - will be used in the archetype definition.
- It is common to use the effect as the first part of the naming.
- This assigns a built-in policy initiative. You can browse definitions using the Azure Portal or AzAdvertizer.
Assignment #2: Deny-NL-Global
{
"type": "Microsoft.Authorization/policyAssignments",
"apiVersion": "2024-04-01",
"name": "Audit-NL-BIO",
"location": "${default_location}",
"dependsOn": [],
"identity": {
"type": "SystemAssigned"
},
"properties": {
"description": "This policy assignment audits compliance with the Dutch Baseline Informatiebeveiliging (BIO) controls specifically for the 'thema-uitwerking Clouddiensten' theme. It includes policies covered under SOC2 and ISO 27001:2013 controls to ensure compliance with Dutch cybersecurity standards.",
"displayName": "Audit - Dutch BIO Cloud Theme V2 Compliance (Global)",
"policyDefinitionId": "/providers/Microsoft.Authorization/policySetDefinitions/d8b2ffbe-c6a8-4622-965d-4ade11d1d2ee",
"definitionVersion": "2.*.*",
"enforcementMode": "Default",
"nonComplianceMessages": [
{
"message": "Resources must comply with Dutch BIO Cloud Theme V2 requirements for information security and data protection."
}
],
"parameters": {},
"scope": "/providers/Microsoft.Management/managementGroups/placeholder",
"notScopes": []
}
}
- The name in the file - Deny-NL-Global - will be used in the archetype definition.
- This uses the first custom policy set definition above and illustrates the differences.
- The policyDefinitionID and scope fields both use “placeholder”.
- The placeholder text may be different. You will see examples with “contoso” instead. The alz provider replaces the text based on field position.
- Note the parameter value is set to West Europe and West Europe. This may be overridden as we will see later.
Custom Role Definitions
It is also possible to include custom role definitions. Here is one included in the main Azure Landing Zone Library.
Role: Network-Subnet-Contributor
{
"name": "3485cc09-cc28-5b69-9679-1732b147a79a",
"type": "Microsoft.Authorization/roleDefinitions",
"apiVersion": "2018-01-01-preview",
"properties": {
"roleName": "Network-Subnet-Contributor",
"description": "Enterprise-scale custom Role Definition. Grants full access to manage Virtual Network subnets, but no other network resources.",
"type": "CustomRole",
"permissions": [
{
"actions": [
"Microsoft.Authorization/*/read",
"Microsoft.Insights/alertRules/*",
"Microsoft.ResourceHealth/availabilityStatuses/read",
"Microsoft.Resources/deployments/*",
"Microsoft.Resources/subscriptions/resourceGroups/read",
"Microsoft.Support/*",
"Microsoft.Network/*/read",
"Microsoft.Network/virtualNetworks/subnets/*"
],
"notActions": [],
"dataActions": [],
"notDataActions": []
}
],
"assignableScopes": [
"${current_scope_resource_id}"
]
}
}
- The roleName in the file - Network-Subnet-Contributor - is used in the root archetype definition.
- The name must be a GUID, e.g. from
uuidgenor[System.Guid]::NewGuid().ToString(). - The assignableScopes should be a single array element,
"${current_scope_resource_id}".