diff --git a/docs/wiki/ALZ-Policies.md b/docs/wiki/ALZ-Policies.md index cef05074be..5be1df643a 100644 --- a/docs/wiki/ALZ-Policies.md +++ b/docs/wiki/ALZ-Policies.md @@ -68,7 +68,7 @@ This management group is a parent to all the other management groups created wit | **Policy Type** | **Count** | | :--- | :---: | | `Policy Definition Sets` | **11** | -| `Policy Definitions` | **2** | +| `Policy Definitions` | **3** | The table below provides the specific **Custom** and **Built-in** **policy definitions** and **policy definitions sets** assigned at the **Intermediate Root Management Group**. @@ -89,6 +89,7 @@ The table below provides the specific **Custom** and **Built-in** **policy defin | **Deny Virtual Machines and Virtual Machine Scale Sets from not using OS Managed Disks** | **Deny Virtual Machines and Virtual Machine Scale Sets from not using OS Managed Disks** | `Policy Definition`, **Built-In** | Deny virtual machines not using managed disk. It checks the managedDisk property on virtual machine OS Disk fields. | Deny | | **Deploy Azure Monitor Baseline Alerts for Service Health** | **Deploy Azure Monitor Baseline Alerts for Service Health** | `Policy Definition Set`, **Custom** | Deploys service health alerts, action group and alert processing rule. For more detail on policies included please refer to https://aka.ms/amba/alz/wiki under Policy Initiatives/Service Health initiative. | DeployIfNotExists | | **Resources should be Zone Resilient** | **Resources should be Zone Resilient** | `Policy Definition Set`, **Built-in** | Some resource types can be deployed Zone Redundant (e.g. SQL Databases); some can be deploy Zone Aligned (e.g. Virtual Machines); and some can be deployed either Zone Aligned or Zone Redundant (e.g. Virtual Machine Scale Sets). Being zone aligned does not guarantee resilience, but it is the foundation on which a resilient solution can be built (e.g. three Virtual Machine Scale Sets zone aligned to three different zones in the same region with a load balancer). See https://aka.ms/AZResilience for more info. | Audit | +| **Resource Group and Resource locations should match** | **Resource Group and Resource locations should match** | `Policy Definition`, **Built-in** | In order to improve resilience and reliability, you need to be aware of where resources are deployed. To aid this awareness, ensure that the location of the resource group matches the location of the resources it contains. | Audit | ### Platform diff --git a/docs/wiki/Whats-new.md b/docs/wiki/Whats-new.md index 3af120131e..f908117221 100644 --- a/docs/wiki/Whats-new.md +++ b/docs/wiki/Whats-new.md @@ -45,6 +45,7 @@ Here's what's changed in Enterprise Scale/Azure Landing Zones: #### Policy - Added new initiative default assignment at the Intermediate Root Management Group for [Resources should be Zone Resilient](https://www.azadvertizer.net/azpolicyinitiativesadvertizer/130fb88f-0fc9-4678-bfe1-31022d71c7d5.html) in Audit mode. +- Added new custom policy and default assignment at the Intermediate Root Management Group for "Resource Group and Resource locations should match", which will help customers better manage and identify regionally deployed resources and ultimately support improved resilience. ### November 2023 diff --git a/docs/wiki/media/ALZ Policy Assignments v2.xlsx b/docs/wiki/media/ALZ Policy Assignments v2.xlsx index 5e8dc4529f..86aad013cd 100644 Binary files a/docs/wiki/media/ALZ Policy Assignments v2.xlsx and b/docs/wiki/media/ALZ Policy Assignments v2.xlsx differ diff --git a/eslzArm/managementGroupTemplates/policyAssignments/AUDIT-ResourceRGLocationPolicyAssignment.json b/eslzArm/managementGroupTemplates/policyAssignments/AUDIT-ResourceRGLocationPolicyAssignment.json new file mode 100644 index 0000000000..9177d7e15a --- /dev/null +++ b/eslzArm/managementGroupTemplates/policyAssignments/AUDIT-ResourceRGLocationPolicyAssignment.json @@ -0,0 +1,72 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-08-01/managementGroupDeploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "topLevelManagementGroupPrefix": { + "type": "string", + "metadata": { + "description": "Provide the ESLZ company prefix to the intermediate root management group containing the policy definitions." + } + }, + "effect": { + "type": "string", + "allowedValues": [ + "Deny", + "Audit", + "Disabled" + ], + "defaultValue": "Audit" + }, + "enforcementMode": { + "type": "string", + "allowedValues": [ + "Default", + "DoNotEnforce" + ], + "defaultValue": "Default" + }, + "nonComplianceMessagePlaceholder": { + "type": "string", + "defaultValue": "{enforcementMode}" + } + }, + "variables": { + "policyDefinitions": { + "auditRGL": "[concat('/providers/Microsoft.Management/managementGroups/', parameters('topLevelManagementGroupPrefix'), '/providers/Microsoft.Authorization/policySetDefinitions/Audit-ResourceRGLocation')]" + }, + "policyAssignmentNames": { + "auditRGL": "Audit-ResourceRGLocation", + "description": "Resource Group and Resource locations should match.", + "displayName": "Resource Group and Resource locations should match" + }, + "nonComplianceMessage": { + "message": "Resources {enforcementMode} be Zone Resilient.", + "Default": "must", + "DoNotEnforce": "should" + } + }, + "resources": [ + { + "type": "Microsoft.Authorization/policyAssignments", + "apiVersion": "2022-06-01", + "name": "[variables('policyAssignmentNames').auditRGL]", + "properties": { + "description": "[variables('policyAssignmentNames').description]", + "displayName": "[variables('policyAssignmentNames').displayName]", + "policyDefinitionId": "[variables('policyDefinitions').auditRGL]", + "enforcementMode": "[parameters('enforcementMode')]", + "nonComplianceMessages": [ + { + "message": "[replace(variables('nonComplianceMessage').message, parameters('nonComplianceMessagePlaceholder'), variables('nonComplianceMessage')[parameters('enforcementMode')])]" + } + ], + "parameters": { + "effect": { + "value": "[parameters('effect')]" + } + } + } + } + ], + "outputs": {} +} \ No newline at end of file diff --git a/src/resources/Microsoft.Authorization/policyDefinitions/Audit-ResourceRGLocation.json b/src/resources/Microsoft.Authorization/policyDefinitions/Audit-ResourceRGLocation.json new file mode 100644 index 0000000000..01aa3e1411 --- /dev/null +++ b/src/resources/Microsoft.Authorization/policyDefinitions/Audit-ResourceRGLocation.json @@ -0,0 +1,58 @@ +{ + "name": "Audit-ResourceRGLocation", + "type": "Microsoft.Authorization/policyDefinitions", + "apiVersion": "2021-06-01", + "scope": null, + "properties": { + "displayName": "Resource Group and Resource locations should match", + "description": "In order to improve resilience and reliability, you need to be aware of where resources are deployed. To aid this awareness, ensure that the location of the resource group matches the location of the resources it contains.", + "version": "1.0.0", + "metadata": { + "version": "1.0.0", + "category": "General", + "source": "https://github.com/Azure/Enterprise-Scale/", + "alzCloudEnvironments": [ + "AzureCloud", + "AzureChinaCloud", + "AzureUSGovernment" + ] + }, + "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": [ + { + "field": "location", + "notEquals": "[resourceGroup().location]" + }, + { + "field": "location", + "notEquals": "global" + }, + { + "field": "type", + "notEquals": "Microsoft.AzureActiveDirectory/b2cDirectories" + } + ] + }, + "then": { + "effect": "[parameters('effect')]" + } + } + } + } \ No newline at end of file diff --git a/src/templates/policies.bicep b/src/templates/policies.bicep index 29b9776eda..11a477c1ec 100644 --- a/src/templates/policies.bicep +++ b/src/templates/policies.bicep @@ -179,6 +179,7 @@ var loadPolicyDefinitions = { loadTextContent('../resources/Microsoft.Authorization/policyDefinitions/Audit-PrivateLinkDnsZones.json') loadTextContent('../resources/Microsoft.Authorization/policyDefinitions/DenyAction-DiagnosticLogs.json') loadTextContent('../resources/Microsoft.Authorization/policyDefinitions/DenyAction-ActivityLogs.json') + loadTextContent('../resources/Microsoft.Authorization/policyDefinitions/Audit-ResourceRGLocation.json') ] AzureCloud: [ loadTextContent('../resources/Microsoft.Authorization/policyDefinitions/Audit-MachineLearning-PrivateEndpointId.json') // Needs validating in AzureChinaCloud and AzureUSGovernment