` or `az deployment mg delete -management-group-id --name` commands.
+
+*Please be aware and careful when using the delete command. Any resources and workloads that were migrated will also be deleted.*
+
+### Why am I getting a "Subscription Alias Already Exist" error?
+
+This commonly because a previous SLZ preview deployment shared the same prefix and suffix. See the `Why am I getting a "deployment already exists" error?` FAQ for resolution steps.
+
+### I am getting a 'ReferencedResourceNotProvisioned' error. How do I resolve this?
+
+If you encounter this error, it is likely due to a transient issue with resource availability. The SLZ Preview deployment script has retry logic to resolve these types of issues, but it may be necessary to rerun the SLZ Preview deployment script if the script terminates.
+
+If it is a viable option, you can attempt deployment to a different region.
+
+### Why am I getting a deployment failure when attempting to deploy the platform?
+
+This error is likely to occur if the subscriptions being created in the Bootstrap step are not yet active. Wait 30 minutes and try again. If the problem persists, please log an [Issue](https://github.com/Azure/sovereign-landing-zone/issues).
+
+ {
+ "status": "Failed",
+ "error": {
+ "code": "DeploymentFailed",
+ "message": "At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/DeployOperations for usage details.",
+ }
+
+### What are the allowed Azure resource types for confidential management groups (Confidential Corp and Confidential Online)?
+
+For an overview of confidential computing resources in Azure please refer to this [documentation.](https://learn.microsoft.com/azure/confidential-computing/overview-azure-products) The list used by the SLZ Preview can be found [here](../modules/compliance/policyAssignments/policy_assignment_deploy_slz_confidential_defaults.tmpl.json), and the list can be customized to meet an organization's needs.
+
+### What information should I consider removing from my failed deployment details logs?
+
+Under `/modules/util/Get-FailedDeploymentDetails.ps1` is a PowerShell script that aids in generating the logs for the failed deployments. Execute this script to share the deployment error logs with Microsoft for troubleshooting.
+
+This script may capture some information that you should consider removing before sending to Microsoft based on the parameters provided. Below we explain where this information can be surfaced so that you know what text from the JSON file you can consider removing before sending to Microsoft.
+
+ **tenantlogs.json considerations**
+
+In the generated `tenantlogs.json` consider the following. If you enter your name, like `ABC`, as a deployment prefix, your name may appear in a few areas of the log file:
+
+* In any `targetResource.id` you may see the following `"id": "/providers/Microsoft.Subscription/aliases/ABC-identity"`.
+* In `targetResource.resourceName` you may see the following `"resourceName": "ABC-identity"`, for example.
+
+ **managementgrouplogs.json considerations**
+
+In the generated `managementgrouplogs.json` consider the following. If you enter your company name, like `xbox`, as a deployment prefix, the company name may appear in a few areas of the log file:
+
+* In any `targetResource.id` you may see the following `"id": "/subscriptions/aec8ebac-dc86-4012-b19a-b4fdea23e635/resourceGroups/rg-xbox-hub-network-eastus/providers/Microsoft.Resources/deployments/xbox-deploy-Hub-Network-20221104T205002Z"`
+* In any `targetResource.resourceName` you may see the following `"resourceName": "xbox-deploy-Hub-Network-20221104T205002Z"`
+* In any `targetResource.resourceGroup` you may see the following `"resourceGroup": "rg-xbox-hub-network-eastus"`.
+
+Also consider the information stored in the `properties.statusMessage.message` as this may contain information on the prefix used.
+
+### I am getting an error that says "Unable to edit or replace deployment..." What should I do?
+
+This error indicates that there is an active deployment in progress while an attempt is being made to start the same deployment again. Wait for the deployment to complete and then run the deployment again, if required.
+
+### I am getting a different deployment error. Where can I find more information?
+
+Please reference the Microsoft Learn document that addresses [common Azure deployment errors](https://learn.microsoft.com/azure/azure-resource-manager/troubleshooting/common-deployment-errors).
+
+### Why am I getting an error message stating `Account already exists in another resourcegroup in a subscription`
+
+This commonly happens with Private Preview customers attempting to upgrade to the Public Preview version. For more details look at our [upgrade documentation](./06-Upgrade-Existing-SLZ-Preview.md).
+
+### Why do I keep getting an error message stating creating the deployment will exceed the quota of '800'?
+
+In most cases this will be automatically resolved in 1-2 hours. Azure will keep a deployment history up to the most recent 800 deployments and by default it will automatically prune this history down to the most recent 600 deployments. However, if multiple deployments are being made in rapid succession, it's possible to hit the max history of 800 before automatic systems can remove older deployments.
+
+More details can be found at [https://aka.ms/800LimitFix](https://aka.ms/800LimitFix)
+
+While it's recommended to wait for Azure to automatically clean up the deployment history, some users may need an immediate fix. Below is a reference script that can be used to resolve the issue. It is necessary for users to review this script to ensure it's only deleting the relevant deployment history as this action is not reversible.
+
+```
+ #EXAMPLE SCRIPT ONLY, USER-SPECIFIC MODIFICATIONS REQUIRED
+
+ #provide deployment prefix and suffix for which deployment history needs to be deleted
+ $parDeploymentPrefix = ""
+ $parTopLevelManagementGroupSuffix = ""
+
+ #fetch all management groups
+ $varManagementGroupId = "$parDeploymentPrefix$parTopLevelManagementGroupSuffix"
+ $response = Get-AzManagementGroup -GroupName $varManagementGroupId -Expand -Recurse
+ $managementGroups = @($varManagementGroupId)
+
+ foreach ($children in $response.Children) {
+ $managementGroups += $children.Name;
+ if($children.Count -gt 0) {
+ for ($i=0; $i -le $children.Count; $i++) {
+ $managementGroups += $children[$i].Children.Name
+ }
+ }
+ }
+
+ #fetch all subscriptions under the managementGroups
+ $subscriptions = @()
+ foreach($mg in $managementGroups ) {
+ if($mg) {
+ $subscriptions += Get-AzManagementGroupSubscription -GroupName $mg
+ }
+ }
+
+ #fetch resourcegroups under the subscriptions and for each resource groups get the deployments name and delete the corresponding deployment from deployment history
+ $subscriptions | ForEach-Object {
+ Set-AzContext -SubscriptionName $_.DisplayName
+ Get-AzResourceGroup | ForEach-Object {
+ $deployments = Get-AzResourceGroupDeployment -ResourceGroupName $_.ResourceGroupName
+ foreach ($deployment in $deployments) {
+ Remove-AzResourceGroupDeployment -ResourceGroupName $_.ResourceGroupName -Name $deployment.DeploymentName
+ }
+ }
+ }
+```
+
+### Can I Use a Managed Identity / Service Principal to Deploy the SLZ Preview?
+
+Yes, provided this identity has been successfully authenticated prior to initiating the deployment such as through an `az login` command. The `New-SovereignLandingZone.ps1` script has two relevant CLI parameters that should be used:
+
+* *parDeployment*: Default `null`. This parameter specifies the deployment type so it doesn't need to be typed in manually.
+* *parAttendedLogin*: Default `$true`. This parameter tells the script to perform various login and validation steps that are not necessary when using a managed identity.
+
+A managed identity with appropriate permissions and running in a context with all necessary modules installed can deploy the SLZ Preview through a command such as this:
+
+```
+.\New-SovereignLandingZone.ps1 -parDeployment all -parAttendedLogin $false
+```
+
+Reference our [pipeline deployments](./scenarios/Pipeline-Deployments.md) document for additional details.
+
+### Can I Choose which Parameter File to Use?
+
+Yes, for many organizations with multiple SLZ Preview deployments it is advisable to minimize operational activities by creating a new parameter file for each SLZ Preview deployment. The `New-SovereignLandingZone.ps1` script has one relevant CLI parameter that should be used:
+
+* *parParametersFilePath*: Default `.\parameters\sovereignLandingZone.parameters.json`. This is the relative path from the `New-SovereignLandingZone.ps1` script to the parameter file.
+
+An organization with multiple SLZ Preview deployments each with a unique parameter file in the local parameters directory can manage a new deployment through a command such as this:
+
+```
+.\New-SovereignLandingZone.ps1 -parParametersFilePath .\parameters\testSLZ.parameters.json
+```
+
+Reference our [pipeline deployments](./scenarios/Pipeline-Deployments.md) document for additional details.
+
+## Compliance Dashboard
+
+### How can I give 'read only' access to a user in my organization to the dashboard?
+
+You will need to assign an Azure `Reader` role the user at the top-level management group scope. Please follow instructions here on how to add an Azure role: [Azure Role Based Access Control](https://learn.microsoft.com/azure/role-based-access-control/role-assignments-portal)
+
+## [Preview Notice](./PREVIEW.md)
diff --git a/docs/13-Troubleshooting.md b/docs/13-Troubleshooting.md
new file mode 100644
index 00000000..31d97cdd
--- /dev/null
+++ b/docs/13-Troubleshooting.md
@@ -0,0 +1,61 @@
+# Troubleshooting
+
+If you are running into issues with your SLZ Preview deployment, review the common troubleshooting topic here or common questions in the [FAQ](./12-FAQ.md). If neither of these resolve your issue, please reach out for assistance through your standard support process or file a [GitHub issue](https://github.com/Azure/sovereign-landing-zone/issues) with us.
+
+## Determining Deployment Steps
+
+When a user creates or updates the SLZ Preview, they will execute the `/orchestration/scripts/New-SovereignLandingZone.ps1` script. This script has a required `parDeployment` parameter, but it will also prompt the user to select if not provided. Review the [deployment overview](./03-Deployment-Overview.md) doc for more information about deployment steps.
+
+Any time the user should be informed of a specific log, that log will start with `>>>` including when a deployment step is beginning or ending. When an error occurs, the current deployment step will be the last deployment step printed in the logs. The screenshot below shows an example for the bootstrap deployment step.
+
+![SLZ Preview Deployment Step in Logs](images/ViewDeploymentStep.png)
+
+## Determining Error from the Error Message
+
+When an error occurs, the error message will most often be presented in a human readable format in red text, with the relevant details being contained within the `Status Message` field as seen below or in a generic `Message` field.
+
+![SLZ Preview Erro in Logs](images/ViewErrorFromLog.png)
+
+## Bootstrap Errors
+
+### User is not authorized to create subscriptions on this enrollment account.
+
+This error means that the SLZ Preview parameter `parSubscriptionBillingScope` value is not valid. Refer to the [permissions setup](./05-Permissions-Tooling.md) doc for more details about the permissions required for your Azure Agreement type.
+
+Once a valid value is provided, rerun the SLZ Preview deployment.
+
+### The provided location [LOCATION] is not available for deployment.
+
+This error means that the SLZ Preview parameter `parDeploymentLocation` value is referring to a region that the user does not have permissions to use. This is commonly the case when there is a typo in this value.
+
+Once a valid value is provided, rerun the SLZ Preview deployment.
+
+### Invalid deployment location [LOCATION]. The deployment [DEPLOYMENT NAME] already exists in location [OTHER LOCATION].
+
+This error commonly means that the `parDeploymentLocation` value has been changed when trying to update an existing SLZ Preview deployment, or that the `parDeploymentPrefix` and `parDeploymentSuffix` value pair is already being used by an existing SLZ Preview deployment.
+
+If you are attempting to move the SLZ Preview deployment, you will need to instead create a new SLZ Preview deployment with a unique `parDeploymentPrefix` and `parDeploymentSuffix` value pair as Azure resources in general cannot be moved.
+
+If an existing SLZ Preview deployment is already using the `parDeploymentPrefix` and `parDeploymentSuffix` value pair, you will need to select a new value for one or both of those parameters. Once a valid set of values are provided, rerun the SLZ Preview deployment.
+
+## Platform Errors
+
+### [Subnet] has an invalid CIDR notation.
+
+This error commonly occurs when the subnet CIDR range for one of the subnets is outside the hub VNET CIDR range. You will need to review the `parHubNetworkAddressPrefix`, `parAzureBastionSubnet`, `parGatewaySubnet`, `parAzureFirewallSubnet`, and `parCustomSubnets` parameters to ensure there are no overlaps and all subnet ranges are within the hub VNET CIDR range.
+
+Once valid values are provided for the hub VNET and subnets, rerun the SLZ Preview deployment.
+
+### Resource [LOG ANALYTICS WORKSPACE RESOURCE OR SOLUTION ID] was disallowed by policy.
+
+This error means that the SLZ Global Defaults policy assignment has been configured to block the `parDeploymentLocation`. This commonly occurs when trying to update an existing SLZ Preview deployment. You will need to review the `parAllowedLocations` array to ensure it contains the `parDeploymentLocation` value.
+
+Once a valid value is provided, run the SLZ Preview compliance deployment step to update the policy assignment, then rerun the SLZ Preview deployment. This error is related to the other ones where policy is blocking the resource.
+
+## Dashboard Errors
+
+### Resource [DASHBOARD RESOURCE GROUP NAME] was disallowed by policy.
+
+This error means that the SLZ Global Defaults policy assignment has been configured to block the `parDeploymentLocation`. This commonly occurs when trying to create a new SLZ Preview deployment. You will need to review the `parAllowedLocations` array to ensure it contains the `parDeploymentLocation` value.
+
+Once a valid value is provided, run the SLZ Preview compliance deployment step to update the policy assignment, then rerun the SLZ Preview deployment. This error is related to the other ones where policy is blocking the resource.
diff --git a/docs/PREVIEW.md b/docs/PREVIEW.md
new file mode 100644
index 00000000..a0faa1f5
--- /dev/null
+++ b/docs/PREVIEW.md
@@ -0,0 +1,3 @@
+# Preview Notice
+
+**Preview Terms**. The Sovereign Landing Zone Preview (the "PREVIEW") is licensed to you as part of your [Azure subscription](https://azure.microsoft.com/en-us/support/legal/) and subject to terms applicable to "Previews" as detailed in the Universal License Terms for Online Services section of the Microsoft Product Terms and the [Microsoft Products and Services Data Protection Addendum ("DPA")](https://www.microsoft.com/licensing/terms/welcome/welcomepage). AS STATED IN THOSE TERMS, PREVIEWS ARE PROVIDED "AS-IS," "WITH ALL FAULTS," AND "AS AVAILABLE," AND ARE EXCLUDED FROM THE SERVICE LEVEL AGREEMENTS AND LIMITED WARRANTY. Previews may employ lesser or different privacy and security measures than those typically present in Azure Services. Unless otherwise noted, you should not use Previews to process Personal Data or other data that is subject to legal or regulatory compliance requirements. The following terms in the [DPA](https://www.microsoft.com/licensing/docs/view/Microsoft-Products-and-Services-Data-Protection-Addendum-DPA) do not apply to Previews: Processing of Personal Data; GDPR, Data Security, and HIPAA Business Associate. We may change or discontinue Previews at any time without notice. We also may choose not to release a Preview into General Availability.
diff --git a/docs/images/LightHouseTenantID.png b/docs/images/LightHouseTenantID.png
new file mode 100644
index 00000000..09d85775
Binary files /dev/null and b/docs/images/LightHouseTenantID.png differ
diff --git a/docs/images/LighthouseSubscriptionID.png b/docs/images/LighthouseSubscriptionID.png
new file mode 100644
index 00000000..4a0b3d98
Binary files /dev/null and b/docs/images/LighthouseSubscriptionID.png differ
diff --git a/docs/images/Upgrade-ComplianceDetails.png b/docs/images/Upgrade-ComplianceDetails.png
new file mode 100644
index 00000000..b3bfb050
Binary files /dev/null and b/docs/images/Upgrade-ComplianceDetails.png differ
diff --git a/docs/images/Upgrade-ManagementGroup.png b/docs/images/Upgrade-ManagementGroup.png
new file mode 100644
index 00000000..b6c14757
Binary files /dev/null and b/docs/images/Upgrade-ManagementGroup.png differ
diff --git a/docs/images/Upgrade-ManagementGroupDetail.png b/docs/images/Upgrade-ManagementGroupDetail.png
new file mode 100644
index 00000000..c2d64247
Binary files /dev/null and b/docs/images/Upgrade-ManagementGroupDetail.png differ
diff --git a/docs/images/Upgrade-PolicyAssignmentDelete.png b/docs/images/Upgrade-PolicyAssignmentDelete.png
new file mode 100644
index 00000000..d5f5d61a
Binary files /dev/null and b/docs/images/Upgrade-PolicyAssignmentDelete.png differ
diff --git a/docs/images/Upgrade-PolicyAssignmentFilter.png b/docs/images/Upgrade-PolicyAssignmentFilter.png
new file mode 100644
index 00000000..713cd0d6
Binary files /dev/null and b/docs/images/Upgrade-PolicyAssignmentFilter.png differ
diff --git a/docs/images/Upgrade-PolicyAssignmentScope.png b/docs/images/Upgrade-PolicyAssignmentScope.png
new file mode 100644
index 00000000..e0ec41b9
Binary files /dev/null and b/docs/images/Upgrade-PolicyAssignmentScope.png differ
diff --git a/docs/images/Upgrade-PolicyAssignmentsBlade.png b/docs/images/Upgrade-PolicyAssignmentsBlade.png
new file mode 100644
index 00000000..86bd94c6
Binary files /dev/null and b/docs/images/Upgrade-PolicyAssignmentsBlade.png differ
diff --git a/docs/images/Upgrade-PolicyDefinitionFilter.png b/docs/images/Upgrade-PolicyDefinitionFilter.png
new file mode 100644
index 00000000..465b556b
Binary files /dev/null and b/docs/images/Upgrade-PolicyDefinitionFilter.png differ
diff --git a/docs/images/Upgrade-PolicyDefinitionFilterDelete.png b/docs/images/Upgrade-PolicyDefinitionFilterDelete.png
new file mode 100644
index 00000000..3e8ece73
Binary files /dev/null and b/docs/images/Upgrade-PolicyDefinitionFilterDelete.png differ
diff --git a/docs/images/Upgrade-PolicyDefinitionList.png b/docs/images/Upgrade-PolicyDefinitionList.png
new file mode 100644
index 00000000..625f682c
Binary files /dev/null and b/docs/images/Upgrade-PolicyDefinitionList.png differ
diff --git a/docs/images/ViewDeploymentStep.png b/docs/images/ViewDeploymentStep.png
new file mode 100644
index 00000000..10d4af38
Binary files /dev/null and b/docs/images/ViewDeploymentStep.png differ
diff --git a/docs/images/ViewErrorFromLog.png b/docs/images/ViewErrorFromLog.png
new file mode 100644
index 00000000..58acc569
Binary files /dev/null and b/docs/images/ViewErrorFromLog.png differ
diff --git a/docs/images/access-permissions.png b/docs/images/access-permissions.png
new file mode 100644
index 00000000..28c4c99d
Binary files /dev/null and b/docs/images/access-permissions.png differ
diff --git a/docs/images/accessmanagementpermissions.png b/docs/images/accessmanagementpermissions.png
new file mode 100644
index 00000000..964cbe3e
Binary files /dev/null and b/docs/images/accessmanagementpermissions.png differ
diff --git a/docs/images/alz-update-initiative-with-builtin-01.png b/docs/images/alz-update-initiative-with-builtin-01.png
new file mode 100644
index 00000000..63ba11a7
Binary files /dev/null and b/docs/images/alz-update-initiative-with-builtin-01.png differ
diff --git a/docs/images/alz-update-initiative-with-builtin-04.png b/docs/images/alz-update-initiative-with-builtin-04.png
new file mode 100644
index 00000000..bb3a3196
Binary files /dev/null and b/docs/images/alz-update-initiative-with-builtin-04.png differ
diff --git a/docs/images/custom-policies-folder.png b/docs/images/custom-policies-folder.png
new file mode 100644
index 00000000..c49de9fc
Binary files /dev/null and b/docs/images/custom-policies-folder.png differ
diff --git a/docs/images/deployerror-vscode.png b/docs/images/deployerror-vscode.png
new file mode 100644
index 00000000..c218b786
Binary files /dev/null and b/docs/images/deployerror-vscode.png differ
diff --git a/docs/images/downloadzipofrepo.png b/docs/images/downloadzipofrepo.png
new file mode 100644
index 00000000..87abbff1
Binary files /dev/null and b/docs/images/downloadzipofrepo.png differ
diff --git a/docs/images/empty-custom-policies.png b/docs/images/empty-custom-policies.png
new file mode 100644
index 00000000..d9d2310e
Binary files /dev/null and b/docs/images/empty-custom-policies.png differ
diff --git a/docs/images/forkgithubrepo.png b/docs/images/forkgithubrepo.png
new file mode 100644
index 00000000..19b31fdb
Binary files /dev/null and b/docs/images/forkgithubrepo.png differ
diff --git a/docs/images/github_compliance-dashboard.png b/docs/images/github_compliance-dashboard.png
new file mode 100644
index 00000000..bbf38b83
Binary files /dev/null and b/docs/images/github_compliance-dashboard.png differ
diff --git a/docs/images/parBillingAccountID.png b/docs/images/parBillingAccountID.png
new file mode 100644
index 00000000..4754819c
Binary files /dev/null and b/docs/images/parBillingAccountID.png differ
diff --git a/docs/images/parEnrollmentID.png b/docs/images/parEnrollmentID.png
new file mode 100644
index 00000000..f9aa51e8
Binary files /dev/null and b/docs/images/parEnrollmentID.png differ
diff --git a/docs/images/sovereign-scale-architecture.png b/docs/images/sovereign-scale-architecture.png
new file mode 100644
index 00000000..e8902f74
Binary files /dev/null and b/docs/images/sovereign-scale-architecture.png differ
diff --git a/docs/scenarios/Custom-Policies.md b/docs/scenarios/Custom-Policies.md
new file mode 100644
index 00000000..3f9fd431
--- /dev/null
+++ b/docs/scenarios/Custom-Policies.md
@@ -0,0 +1,43 @@
+# Customize baseline policies
+
+Once the SLZ Preview is deployed, the management group structure, subscriptions, and the [sovereignty policy baseline](Sovereignty-Policy-Baseline.md) will be in place. While the baseline can be configured, it may be necessary to apply additional policies to address local laws and regulations. Review the [Microsoft Cloud for Sovereignty Policy Portfolio](https://github.com/Azure/cloud-for-sovereignty-policy-portfolio) for policies that support specific regulations, or follow the below steps to deploy your own policies alongside the SLZ Preview.
+
+## Customization step by step
+
+The SLZ Preview allows for custom policy initiatives to be deployed within the standard management group scopes for each deployment through the following:
+
+1. Navigate to the custom policy definitions located in `/custom/policies/definitions` in your version of the GitHub repository.
+2. Each definition corresponds to one of the default management group scopes deployed as part of the SLZ Preview management group hierarchy ![Custom Policy Folder](../images/custom-policies-folder.png)
+ * `slzConfidentialCustom.json` -> Confidential Corp and Confidential Online Management Groups
+ * `slzConnectivityCustom.json` -> Connectivity Management Group
+ * `slzCorpCustom.json` -> Corp and Confidential Corp Management Groups
+ * `slzDecommissionedCustom.json` -> Decommissioned Management Group
+ * `slzGlobalCustom.json` -> The Top-Level Management Group
+ * `slzIdentityCustom.json` -> Identity Management Group
+ * `slzLandingZoneCustom.json` -> Landing Zones Management Group
+ * `slzManagementCustom.json` -> Management Management Group
+ * `slzOnlineCustom.json` -> Online and Confidential Online Management Groups
+ * `slzPlatformCustom.json` -> Platform Management Group
+ * `slzSandboxCustom.json` -> Sandbox Management Group
+3. Select the file for management group scope that you want custom policies to apply to and if you want to apply custom policies to all application workloads then select `slzLandingZoneCustom.json`
+4. If custom policies have not been added yet, then the custom policy file will look like the screenshot below. Do NOT edit the `policyType`, `id`, `type`, or `name` fields. You will update the `parameters`, `policyDefinitions`, and `policyDefinitionGroups` as described by the [initiative definition structure](https://learn.microsoft.com/azure/governance/policy/concepts/initiative-definition-structure)
+![Empty Policy File](../images/empty-custom-policies.png)
+5. Grouping policies together on the [SLZ Preview dashboard](./Extending-Compliance-Dashboard.md) is accomplished by adding `dashboard-` to the beginning of the policy definition group name, but any name can be used. The documentation for the [policy set definition group structure](https://learn.microsoft.com/azure/governance/policy/concepts/initiative-definition-structure#policy-definition-groups) describes the group structure further. A valid policy definition group can be found below:
+```
+ {
+ "name": "dashboard-NIST_SP_800-171_R2",
+ "category": "Regulatory Compliance",
+ "description": "NIST 800-171 rev2"
+ }
+```
+6. Passing values to the custom policy definitions is not currently supported. You can set default values in the definition file or in the assignment file (located in the `/custom/policies/assignments` folder) but you cannot pass in values from the orchestration script at this time. Documentation on the assignment structure and how to set parameters is located [here](https://learn.microsoft.com/azure/governance/policy/concepts/assignment-structure)
+7. Once you have added the custom policies to the policy set file, you only need to save the file and run `.\New-SovereignLandingZone.ps1` with either the `all`, or `compliance` deployment step and your custom policies will be added and assigned to the appropriate management group scopes.
+8. If you need to change a policy effect, you will need to make that change to the above definitions and redeploy the SLZ Preview as above. For documentation on how to set a policy effect please review the documentation [here](https://learn.microsoft.com/azure/governance/policy/concepts/effects)
+
+**Note** Custom policies will need to fit with the [Azure policy and policy rule limits](https://learn.microsoft.com/azure/azure-resource-manager/management/azure-subscription-service-limits#azure-policy-limits) otherwise Azure will not create the definitions.
+
+## Next step
+
+[View your compliance dashboard.](../10-Compliance-Dashboard.md)
+
+### [Preview Notice](./PREVIEW.md)
diff --git a/docs/scenarios/Expanding-SLZ-ManagementGroups.md b/docs/scenarios/Expanding-SLZ-ManagementGroups.md
new file mode 100644
index 00000000..8defc5ae
--- /dev/null
+++ b/docs/scenarios/Expanding-SLZ-ManagementGroups.md
@@ -0,0 +1,21 @@
+# Adding New Management Group Scopes to the SLZ Preview
+
+The SLZ Preview deploys a standard set of management groups that are used to organize resources and manage policy assignments. This set also has the following recommended usage patterns:
+
+1. [Connectivity](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/connectivity-to-azure) - Used to host platform workloads that provide core networking capabilities
+2. [Identity](https://learn.microsoft.com/azure/cloud-adoption-framework/decision-guides/identity/) - Used to host platform workloads that provide identity management, access, and syncing capabilities
+3. [Management](https://learn.microsoft.com/azure/cloud-adoption-framework/manage/monitor/) - Used to host platform workloads that provide core monitoring and alerting capabilities
+4. Corp - Used to host application workloads that do not need to be accessed from the public internet
+ * Public internet access restriction is provided by enabling the ALZ Policies
+5. Confidential Corp - Used to host application workloads that do not need to be accessed from the public internet but require use of confidential computing
+ * Public internet access restriction is provided by enabling the ALZ Policies
+6. Online - Used to host application workloads that do need to be accessed from the public internet
+7. Confidential Online - Used to host application workloads that do need to be accessed from the public internet but require use of confidential computing
+8. [Sandbox](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/sandbox-environments) - Used to host isolated environments for testing workloads and capabilities
+9. [Decommissioned](https://learn.microsoft.com/azure/cloud-adoption-framework/migrate/migration-considerations/optimize/decommission) - Used to host workloads or capabilities that are retired, but still need to be retained
+
+The policy assignments will provide guardrails designed to support these usage patterns with the [Sovereignty Policy Baseline](./Sovereignty-Policy-Baseline.md) enforcing confidential computing SKUs and if enabled the [ALZ policies](https://github.com/Azure/Enterprise-Scale/wiki/ALZ-Policies) focus on security best practices.
+
+As organizations use the SLZ Preview they may find it useful refine their management group structure to group workloads further or under different contexts. This can be achieved by using the `parLandingZoneMgChildren` parameter value to create more sibling management groups to the Corp, Online, and Confidential variants.
+
+Note that custom management groups will need to manage policy assignments to them as post-deployment steps. Further developments will improve upon this customization experience.
diff --git a/docs/scenarios/Extending-Compliance-Dashboard.md b/docs/scenarios/Extending-Compliance-Dashboard.md
new file mode 100644
index 00000000..58582bc8
--- /dev/null
+++ b/docs/scenarios/Extending-Compliance-Dashboard.md
@@ -0,0 +1,21 @@
+# Extending the Compliance Dashboard
+
+The SLZ Preview [Compliance Dashboard](../10-Compliance-Dashboard.md) provides a singular Azure policy compliance view for every resource within the SLZ Preview deployment. While this is a great starting point for viewing the default and built-in policies assigned with the SLZ Preview, many governance teams want to also see their own policies in the same view. This can be achieved through a few ways.
+
+## Overall and Subscription Compliance Views
+
+For the most part, no customization needs to be done for the overall or subscription views as these queries will search for assignment and compliance results for every resource and subscription under the top-level management group so any additional policies will be picked up natively.
+
+## Data Residency Views
+
+The data residency views are created by filtering by compliance results for policies under initiatives in the `dashboard-data residency` group. Custom policy assignments can populate these views by creating the group name `dashboard-data residency` in the custom initiative and grouping relevant policies into it.
+
+## Confidential Computing Views
+
+The confidential computing views are created by filtering by compliance results for policies under initiatives in one of the following groups: `dashboard-storage security`, `dashboard-transport security`, `dashboard-confidential computing`, or `dashboard-key management`. Custom policy assignments can populate these views by creating one or more of the above group names in the custom initiative and grouping relevant policies into it.
+
+## Custom Tiles
+
+When one of the above methods is not sufficient, additional tiles can be added to the SLZ Preview Compliance Dashboard by adding these to the [tiles JSON](../../custom/dashboard/compliance/tiles.json) file. This JSON file takes [Azure Portal Dashboard](https://learn.microsoft.com/azure/azure-portal/azure-portal-dashboards) tiles and will append them to the compliance dashboard.
+
+Worth noting that the `position.y` value for tile elements will need to be lower than the y-values already used by the compliance dashboard otherwise tile elements could be missing or moved. Checkout the [tiles sample](../../custom/dashboard/compliance/tiles-sample.json) for an example of this extension.
diff --git a/docs/scenarios/Landing-Zone-Vending.md b/docs/scenarios/Landing-Zone-Vending.md
new file mode 100644
index 00000000..19c88c83
--- /dev/null
+++ b/docs/scenarios/Landing-Zone-Vending.md
@@ -0,0 +1,55 @@
+# Workload Landing Zones
+
+After the SLZ Preview has been deployed, organizations can begin using it to host workloads. Workloads will need their own landing zones, and for more details about the types of landing zones review the [what is a landing zone](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/#platform-landing-zones-vs-application-landing-zones) documentation.
+
+In short, the landing zone as deployed by the SLZ Preview provides the governance framework and controls that can simplify the onboarding of workload landing zones within it's management group structure. This means workload landing zones don't need to recreate common infrastructure such as a hub network as they may use the one that already exists, nor do they need to manage policy assignments as they'll inherent the ones already assigned.
+
+Workload landing zones require the creation of a subscription and placing it within the management group structure. While you may [customize the management groups](Expanding-SLZ-ManagementGroups.md) available, the following exist by default:
+
+1. [Connectivity](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/connectivity-to-azure) - Used to host platform workloads that provide core networking capabilities
+2. [Identity](https://learn.microsoft.com/azure/cloud-adoption-framework/decision-guides/identity/) - Used to host platform workloads that provide identity management, access, and syncing capabilities
+3. [Management](https://learn.microsoft.com/azure/cloud-adoption-framework/manage/monitor/) - Used to host platform workloads that provide core monitoring and alerting capabilities
+4. Corp - Used to host application workloads that do not need to be accessed from the public internet
+5. Confidential Corp - Used to host application workloads that do not need to be accessed from the public internet but require use of confidential computing
+6. Online - Used to host application workloads that do need to be accessed from the public internet
+7. Confidential Online - Used to host application workloads that do need to be accessed from the public internet but require use of confidential computing
+8. [Sandbox](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/sandbox-environments) - Used to host isolated environments for testing workloads and capabilities
+9. [Decommissioned](https://learn.microsoft.com/azure/cloud-adoption-framework/migrate/migration-considerations/optimize/decommission) - Used to host workloads or capabilities that are retired, but still need to be retained
+
+# Landing Zone Vending
+
+[Subscription vending](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/landing-zone/design-area/subscription-vending) provides a platform mechanism for programmatically issuing subscriptions to application teams that need to deploy workloads. This notion allows for an organization's governance and security teams to build controls and a process around subscription creation, then application teams can request a new subscription for their workload on demand after making a few choices.
+
+[Landing zone vending](https://github.com/Azure/bicep-lz-vending) is a GitHub repository provides the automation to deploy landing zones for workloads within the SLZ Preview. It is recommended for an organization's governance and security teams to review the parameters available in this module and enforce certain values for some, while leaving the others up to the requesting team to fill out. Once all values are added, then a pipeline running with a highly privileged account would create the landing zone and grant reduced permissions to the development team to deploy their workload within.
+
+It is recommended to not allow a development team set the following values:
+
+* subscriptionBillingScope
+* subscriptionTenantId
+* virtualNetworkDdosPlanId
+* virtualNetworkLocation
+* hubNetworkResourceId
+
+It is recommended to allow a development to set the following values:
+
+* subscriptionDisplayName
+* subscriptionAliasName
+* subscriptionWorkload
+* subscriptionManagementGroupId
+
+However, organizations may customize these lists further and provide certain allowed values that a development team can request.
+
+# SLZ Preview Logging
+
+To support usage of the landing zone vending module and [running individual deployment steps](Pipeline-Deployments.md), during every execution of the SLZ Preview key resources will be logged to a CSV file. These log files will be stored in `/orchestration/scripts/outputs` and will be timestamped with the deployment name in the title.
+
+The CSV file has the following columns:
+* Resource Name - The human readable resource name
+* Resource Type - The resource type useful for filtering the CSV
+* Resource Id - The unique identifier for the resource that's commonly needed as a parameter
+* Deployment Module - The deployment module where this resource is created
+* Comments - A human readable comment about where this value is commonly used
+
+# Workload Templates
+
+Microsoft Cloud for Sovereignty has published a variety of [workload templates](https://github.com/Azure/cloud-for-sovereignty-quickstarts) including a sample application that are designed to be deployed within the SLZ Preview. These are useful resources to reference during the workload migration process.
diff --git a/docs/scenarios/Piloting-SLZ.md b/docs/scenarios/Piloting-SLZ.md
new file mode 100644
index 00000000..c0c56f4a
--- /dev/null
+++ b/docs/scenarios/Piloting-SLZ.md
@@ -0,0 +1,27 @@
+# Sovereign Landing Zone Pilots
+
+The numbered getting started docs are intended to overview the steps that would be required for a production deployment of the SLZ Preview. However, this often requires greater permissions and has a higher cost than what an organization may be willing to spend while they are conducting a pilot.
+
+## Reduced Permissions
+
+**Note** the reduced permission set listed below is pending completion this feature. Documentation is being left as-is to show the current direction. When the feature is finished, this note will be removed and it will be listed in the release notes. For the time being, Global Administrator with elevated Azure permissions are required. The `Confirm-SovereignLandingZonePrerequisites.ps1` script will not attempt to automatically elevate Azure permissions when using a child management group as the top-level.
+
+Reference the production deployment [permission setup](../05-Permissions-Tooling.md) for the recommended steps. For pilot deployments, there are a few additional recommendations.
+
+1. **Use existing subscriptions**
+ * This means the identity being used to deploy the SLZ Preview does not need broad permissions to create subscriptions, but can be given a set of existing subscriptions to use.
+ * See the [using existing subscriptions](./Using-Existing-Subscriptions.md) doc for more details.
+2. **Use a child management group as the top-level**
+ * By default the SLZ Preview will attempt to create a top-level management group to store all resources at the [tenant root group](https://learn.microsoft.com/azure/governance/management-groups/overview#root-management-group-for-each-directory) level. This is a very board permission that may allow the identity to alter any resource within the tenant.
+ * Instead, it is recommended to create a new management group at some other level and assign the broad permissions there so the identity deploying the SLZ Preview will have no ability to other existing Azure resources.
+ * The SLZ Preview can be configured to deploy within this new management group via the `parTopLevelManagementGroupParentId` parameter. View our [parameter guidance](../07-Deployment-Parameters.md) doc for further details on configuring the SLZ Preview.
+ * **Note** Using the `parTopLevelManagementGroupParentId` parameter to separate multiple SLZ Preview deployments is also the recommended approach for managing multiple side-by-side deployments as is needed to meet development, testing, and isolation requirements.
+
+## Reduced Resources
+
+It is crucial to be conscientious of the cost implications when conducting a pilot. It is worth considering if the following resources are required for the pilot and making the following changes in the parameter file to disable them if they are not:
+
+1. [Azure DDos Protection](https://learn.microsoft.com/azure/ddos-protection/ddos-protection-overview) - This can be disabled by setting the `parDeployDdosProtection` value to `false`
+2. [Azure Firewall](https://learn.microsoft.com/azure/firewall/overview) - This can be disabled by setting the `parEnableFirewall` value to `false`.
+ * If Azure Firewall is needed, consider using the basic SKU by setting `parUsePremiumFirewall` to `false`
+3. [Azure Bastion](https://learn.microsoft.com/azure/bastion/bastion-overview) - This can be disabled by setting the `parDeployBastion` value to `false`.
diff --git a/docs/scenarios/Pipeline-Deployments.md b/docs/scenarios/Pipeline-Deployments.md
new file mode 100644
index 00000000..1ed0065d
--- /dev/null
+++ b/docs/scenarios/Pipeline-Deployments.md
@@ -0,0 +1,59 @@
+# Deploying the SLZ Preview in a Pipeline
+
+While the SLZ Preview deployment process works well to be executed manually, it can also easily be executed in a pipeline. This will require that a [service principal (SPN)](https://learn.microsoft.com/azure/active-directory/develop/howto-create-service-principal-portal) has been granted the same [required permissions](../05-Permissions-Tooling.md) that a user must have, and that the SPN is bound to a [service connection](https://learn.microsoft.com/azure/devops/pipelines/library/service-endpoints?view=azure-devops&tabs=yaml#azure-resource-manager-service-connection) and used during the [pipeline execution](https://learn.microsoft.com/azure/devops/pipelines/library/service-endpoints?view=azure-devops&tabs=yaml#use-a-service-connection). There are a few considerations when doing this:
+
+## Running in Unattended Mode
+
+When the SLZ Preview deployment script is executed, it will check for dependencies and prompt the user for information. This is not suitable for pipeline deployments where it is not possible to interact with the script. Pipelines can execute the same flow without being prompted by running the script in unattended mode:
+
+```
+.\New-SovereignLandingZone.ps1 -parDeployment all -parAttendedLogin $false
+```
+
+Unattended mode will expect that an identity has already been logged in and that their AZ context is setup to the appropriate tenant.
+
+## Multiple Parameter Files
+
+When the SLZ Preview deployment script is executed, it will reference the [parameter file](../../orchestration/scripts/parameters/sovereignLandingZone.parameters.json) for all values required for the deployment. This is not suitable for pipeline deployments where you may not want to have the parameter file checked into the same repository as the code, or when you want to use manage multiple deployments. The deployment script can be directed to find the parameter file at a different path:
+
+```
+.\New-SovereignLandingZone.ps1 -parDeployment all -parParametersFilePath path/to/parameter/file.json
+```
+
+## Individual Deployment Steps
+
+The SLZ Preview deployment script has [multiple steps](../03-Deployment-Overview.md) that can be deployed individually. It is useful to run a singular deployment step to speed up the deployment process when the change that needs to be deployed is limited to one deployment step. For instance, adding new custom policies does not require redeploying the entire platform, but instead can be executed by setting the appropriate `parDeployment` CLI parameter:
+
+```
+.\New-SovereignLandingZone.ps1 -parDeployment compliance
+```
+
+Or by running:
+
+```
+.\New-Compliance.ps1
+```
+
+These are the deployment steps:
+
+|Step Name|parDeployment value|Individual Script|Description|
+|---------|-------------------|-----------------|-----------|
+|Bootstrap|bootstrap|New-Bootstrap.ps1|Deploys the management groups and subscriptions|
+|Platform|platform|New-Platform.ps1|Deploys all Azure resources|
+|Compliance|compliance|New-Compliance.ps1|Deploys and assigns all Azure policies|
+|Dashboard|dashboard|New-Dashboard.ps1|Deploys the compliance dashboard|
+|Policy Exemptions|policyexemption|New-PolicyExemption.ps1|Deploys all custom policy exemptions|
+|Policy Remediations|policyremediation|New-PolicyRemediation.ps1|Executes all policy remediations and scans|
+
+## Required Parameters
+
+These deployment steps also have additional required parameters as the SLZ Preview deployment script will not attempt to query an environment to determine these values. An individual deployment step will also have the required parameters of the deployment steps that are before it. For instance the `Compliance` step will also need the `Platform` step's required parameters. Every execution of the SLZ Preview will log key resources including these required parameters to a CSV file. These log files will be stored in `/orchestration/scripts/outputs` and will be timestamped with the deployment name in the title.
+
+|Step Name|Required Parameters|
+|---------|-------------------|
+|Bootstrap|N/A|
+|Platform|`parManagementSubscriptionId`
`parIdentitySubscriptionId`
`parConnectivitySubscriptionId`|
+|Compliance|`parLogAnalyticsWorkspaceId`
`parAutomationAccountName`
`parPrivateDnsResourceGroupId`
`parDdosProtectionResourceId` (if `parDeployDdosProtection` is `true`)|
+|Dashboard|N/A|
+|Policy Exemptions|N/A|
+|Policy Remediations|N/A|
diff --git a/docs/scenarios/README.md b/docs/scenarios/README.md
new file mode 100644
index 00000000..788d40b1
--- /dev/null
+++ b/docs/scenarios/README.md
@@ -0,0 +1,13 @@
+# Sovereign Landing Zone Preview Scenarios
+
+The following are common scenarios found during initial deployment or through operational tasks within an SLZ Preview deployment.
+
+1. [Conducting a pilot of the SLZ Preview](./Piloting-SLZ.md)
+2. [Deploying the SLZ Preview in a pipeline](./Pipeline-Deployments.md)
+3. [Using existing subscriptions for the SLZ Preview](./Using-Existing-Subscriptions.md)
+4. [What is the Sovereignty Policy Baseline](./Sovereignty-Policy-Baseline.md)
+5. [Using built-in policies or the Policy Portfolio](./Using-Policy-Portfolio.md)
+6. [Custom Azure Policies within the SLZ Preview](./Custom-Policies.md)
+7. [Customizing the compliance dashboard](./Extending-Compliance-Dashboard.md)
+8. [Deploying application or platform landing zones](./Landing-Zone-Vending.md)
+9. [Adding additional landing zone management groups](./Expanding-SLZ-ManagementGroups.md)
diff --git a/docs/scenarios/Removing-Policy-Assignments.md b/docs/scenarios/Removing-Policy-Assignments.md
new file mode 100644
index 00000000..63258e55
--- /dev/null
+++ b/docs/scenarios/Removing-Policy-Assignments.md
@@ -0,0 +1,66 @@
+# Removing Policy Assignments
+
+There are several options for the SLZ Preview to deploy policies. However, the SLZ Preview does not remove policy assignments by design. Policy assignments are the technical guardrails used by governance and security teams, and we want removing of policy assignments to be an intentional effort instead of an accidental one caused by a misconfiguration. To remove a policy assignment, the SLZ Preview parameter file needs to be updated to ensure it does not attempt to recreate the assignment then a secondary or manual process must go through and remove the assignment.
+
+Upgrades to the Sovereignty Policy Baseline or any of the built-in Policy Portfolio initiatives will be automatically addressed without secondary steps or manual intervention.
+
+## Removing Old Custom Policies
+
+Update the [custom policy definitions](../../custom/policies/definitions/) by removing the old policies out of the definitions and incrementing the version number before redeploying the SLZ Preview. The SLZ Preview will automatically remove the old definition assignment during the upgrade process.
+
+## Removing Old Policy Portfolio Assignments
+
+Update the SLZ Preview parameter file and remove the old assignment out of the `parCustomerPolicySets` parameter. This will prevent the SLZ Preview from deploying the assignment in the future.
+
+Navigate to the [Management Group](https://portal.azure.com/#view/Microsoft_Azure_ManagementGroups/ManagementGroupBrowseBlade/~/MGBrowse_overview) view and select the top-level management group for the SLZ Preview deployment. In the policies blade, find the assignment with the same name and manually delete it.
+
+## Removing the ALZ Policies
+
+Update the SLZ Preview parameter file and set `parDeployAlzDefaultPolicies` to `false`. This will prevent the SLZ Preview from deploying the ALZ Policies in the future.
+
+Navigate to the [Management Group](https://portal.azure.com/#view/Microsoft_Azure_ManagementGroups/ManagementGroupBrowseBlade/~/MGBrowse_overview) view and select the top-level management group for the SLZ Preview deployment.
+
+ ![alz-delete-initiative-assignments](../images/alz-update-initiative-with-builtin-04.png)
+
+- For each assignment, click the ellipsis and select Delete Assignment.
+- Once all initiative assignments are deleted, go to the Definitions pane, search for the initiative definition. Once found click the ellipsis and choose Delete Policy Definition.
+
+ ![alz-custom-initiative-def-search](../images/alz-update-initiative-with-builtin-01.png)
+- For implementation details refer to the [ALZ Assignment Deletion](https://github.com/Azure/ALZ-Bicep/blob/da0af7a5a1f21825b497017f52264df2d29aa0a6/docs/wiki/PolicyDeepDive.md) docs, and for design consideration refer to the [ALZ Policies](https://github.com/Azure/Enterprise-Scale/wiki/ALZ-Policies) doc.
+
+## ALZ Policy Assignments
+
+| **Assignment Name** | **Definition Name** |
+|--------------------------|---------------------------|
+|Deploy Microsoft Defender for Cloud configuration|Deploy Microsoft Defender for Cloud configuration|
+|Deploy-Resource-Diag |Deploy Diagnostic Settings to Azure Services |
+|Deploy Diagnostic Settings for Activity Log to Log Analytics workspace |Configure Azure Activity logs to stream to specified Log Analytics workspace |
+|[Preview]: Deploy Microsoft Defender for Endpoint agent |[Preview]: Deploy Microsoft Defender for Endpoint agent |
+|Enable Azure Monitor for Virtual Machine Scale Sets |Enable Azure Monitor for Virtual Machine Scale Sets |
+|Configure Azure Defender to be enabled on SQL Servers and SQL Managed Instances |Configure Azure Defender to be enabled on SQL Servers and SQL Managed Instances |
+|Configure Advanced Threat Protection to be enabled on open-source relational databases |Configure Advanced Threat Protection to be enabled on open-source relational databases |
+|Enable Azure Monitor for VMs |Enable Azure Monitor for VMs |
+|Deny the deployment of classic resources |Not allowed resource types |
+|Enforce ALZ Decommissioned Guardrails |Enforce ALZ Decommissioned Guardrails |
+|Subnets should have a Network Security Group |Subnets should have a Network Security Group |
+|Management port access from the Internet should be blocked |Management port access from the Internet should be blocked |
+|Web Application Firewall (WAF) should be enabled for Application Gateway |Web Application Firewall (WAF) should be enabled for Application Gateway |
+|Kubernetes clusters should not allow container privilege escalation |Kubernetes clusters should not allow container privilege escalation |
+|Kubernetes clusters should be accessible only over HTTPS |Kubernetes clusters should be accessible only over HTTPS |
+|Kubernetes cluster should not allow privileged containers |Kubernetes cluster should not allow privileged containers |
+|Network interfaces should disable IP forwarding |Network interfaces should disable IP forwarding |
+|Enforce recommended guardrails for Azure Key Vault |Enforce recommended guardrails for Azure Key Vault |
+|Secure transfer to storage accounts should be enabled |Secure transfer to storage accounts should be enabled |
+|Deploy Threat Detection on SQL servers |Configure Azure Defender to be enabled on SQL servers |
+|Configure backup on virtual machines without a given tag to a new recovery services vault with a default policy |Configure backup on virtual machines without a given tag to a new recovery services vault with a default policy |
+|Deploy TDE on SQL servers |Deploy TDE on SQL servers |
+|Deploy Azure Policy Add-on to Azure Kubernetes Service clusters |Deploy Azure Policy Add-on to Azure Kubernetes Service clusters |
+|Deny or Deploy and append TLS requirements and SSL enforcement on resources without Encryption in transit |Deny or Deploy and append TLS requirements and SSL enforcement on resources without Encryption in transit |
+|Configure SQL servers to have auditing enabled to Log Analytics workspace |Configure SQL servers to have auditing enabled to Log Analytics workspace |
+|Deny the deployment of vWAN/ER/VPN gateway resources |Not allowed resource types |
+|Audit Private Link Private DNS Zone resources |Audit the creation of Private Link Private DNS Zones |
+|Public network access should be disabled for PaaS services |Public network access should be disabled for PaaS services |
+|Deny network interfaces having a public IP associated |Network interfaces should not have public IPs |
+|Configure Azure PaaS services to use private DNS zones |Configure Azure PaaS services to use private DNS zones |
+|Deny the creation of public IP |Not allowed resource types |
+|Deploy-Log-Analytics |Configure Log Analytics workspace and automation account to centralize logs and monitoring |
diff --git a/docs/scenarios/Sovereignty-Policy-Baseline.md b/docs/scenarios/Sovereignty-Policy-Baseline.md
new file mode 100644
index 00000000..9b7313f9
--- /dev/null
+++ b/docs/scenarios/Sovereignty-Policy-Baseline.md
@@ -0,0 +1,54 @@
+# Sovereignty Policy Baseline
+
+The Sovereignty Policy Baseline (baseline) is one of the sets of policies in the [Microsoft Cloud for Sovereignty Portfolio](https://learn.microsoft.com/industry/sovereignty/policy-portfolio-baseline). It comes deployed within every SLZ Preview environment and can be [used outside an SLZ Preview](https://github.com/Azure/cloud-for-sovereignty-policy-portfolio/) environment.
+
+The baseline is intended to supplement existing security control frameworks used by customers today with Azure policies that are grouped into the sovereignty control objectives listed below. It is not intended to replace a security control framework or fully meet the sovereignty control objectives by themselves. It should be viewed as providing a guardrail starting point for best practices past what traditional control frameworks may require and supports an organization's effort in addressing the listed control objectives.
+
+The baseline does this by introducing the notion of **customer-defined sensitive** data, which is not meant to map to any data classification framework. Instead it is there to differentiate data that an organization denotes as having additional sovereignty requirements. The below sovereignty control objectives are examples of the types of controls that an organization may have for protecting **customer-defined sensitive** data. The related policies to these objectives are only assigned to the confidential scopes while other controls are applied to all resources.
+
+## Configuring the Baseline
+
+The following parameters are useful for configuring the policy baseline:
+
+1. `parAllowedLocations` - This is applied to all resources to restrict the regions where they can be deployed.
+2. `parAllowedLocationsForConfidentialComputing` - This is applied to all resources within the confidential scopes to restrict the regions where they can be deployed. Resources under this scope are exempt from the `parAllowedLocations` rule to support cases where confidential computing is not currently available in the desired region.
+3. `parPolicyEffect` - This is the policy effect used by all policies within the baseline that supports the effect.
+
+## Sovereignty Control Objectives
+
+### SO-1
+
+**Customer data must be stored and processed entirely in data centers that reside in approved geopolitical regions based upon customer-defined requirements.**
+
+The related policies are in the `dashboard-Data Residency` group within these files:
+
+* [SLZ Global Defaults](../../modules/compliance/policySetDefinitions/slzGlobalDefaults.json)
+* [SLZ Confidential Defaults](../../modules/compliance/policySetDefinitions/slzConfidentialDefaults.json)
+
+### SO-2
+
+**Customers must approve the access of customer data by cloud and managed service operators.**
+
+There is no policy in the baseline that supports this and it is intended to be addressed by enabling [Customer Lockbox](https://learn.microsoft.com/azure/security/fundamentals/customer-lockbox-overview).
+
+### SO-3
+
+**Customer-defined sensitive customer data must only be accessible in an encrypted manner to cloud and managed service operators.**
+
+The related policies are in the `dashboard-Confidential Computing` group within these files:
+
+* [SLZ Confidential Defaults](../../modules/compliance/policySetDefinitions/slzConfidentialDefaults.json)
+
+**Note** The resources are intended to be restricted to only those that have SKUs backed by confidential computing or do not process customer data. If this list is too restrictive, users are recommended to add other approved resources to the [allowed resources list](../../modules/compliance/policyAssignments/policy_assignment_deploy_slz_confidential_defaults.tmpl.json) in the assignment definition.
+
+### SO-4
+
+**The customer must have exclusive control over deciding which identities can access keys used to decrypt customer-defined sensitive data.**
+
+The related policies are in the `dashboard-Key Management` group within these files:
+
+* [SLZ Confidential Defaults](../../modules/compliance/policySetDefinitions/slzConfidentialDefaults.json)
+
+## Improvement Ideas
+
+The Sovereignty Policy Baseline is exploring a new space and we are eager to hear any suggestions about how they should be structured, other control objectives that should be included, how they should support specific workload architectures, or any other areas. Please submit any [feedback or improvement ideas](https://github.com/Azure/sovereign-landing-zone/issues/new/choose) you may have.
diff --git a/docs/scenarios/Using-Existing-Subscriptions.md b/docs/scenarios/Using-Existing-Subscriptions.md
new file mode 100644
index 00000000..dddf3737
--- /dev/null
+++ b/docs/scenarios/Using-Existing-Subscriptions.md
@@ -0,0 +1,22 @@
+# Using Existing Subscriptions
+
+In some cases the user will not be able to use the SLZ Preview to create subscriptions. This often happens for organizations that procure subscriptions through a partner or when an organization's policy requires the user to procure subscriptions through another internal team or process.
+
+In either case, the lifecycle for subscriptions does not need to be managed by the SLZ Preview and the SLZ Preview can be configured to use existing subscriptions. In this case the user will still require the permissions described [during the setup steps](../05-Permissions-Tooling.md) as well as the [Owner](https://learn.microsoft.com/azure/role-based-access-control/built-in-roles#owner) permission within all subscriptions being used.
+
+It is recommended for these subscriptions to follow the same naming convention as the SLZ Preview deployed ones:
+1. `{parDeploymentPrefix}-connectivity{parDeploymentSuffix}`
+2. `{parDeploymentPrefix}-identity{parDeploymentSuffix}`
+3. `{parDeploymentPrefix}-management{parDeploymentSuffix}`
+
+Although any naming convention can be used. To configure the SLZ Preview to use these subscriptions when deploying resources, update the parameters file with the following values:
+1. `parConnectivitySubscriptionId`.value
+ * The ID of the `{parDeploymentPrefix}-connectivity{parDeploymentSuffix}` subscription.
+2. `parIdentitySubscriptionId`.value
+ * The ID of the `{parDeploymentPrefix}-identity{parDeploymentSuffix}` subscription.
+3. `parManagementSubscriptionId`.value
+ * The ID of the `{parDeploymentPrefix}-management{parDeploymentSuffix}` subscription.
+
+## Deployments in a Singular Subscription
+
+While it is technically possible to use the same subscription ID for all 3 default subscriptions to effectively deploy the SLZ Preview into one subscription, this is not a supported scenario and there may be unexpected conflicts.
diff --git a/docs/scenarios/Using-Policy-Portfolio.md b/docs/scenarios/Using-Policy-Portfolio.md
new file mode 100644
index 00000000..f0779193
--- /dev/null
+++ b/docs/scenarios/Using-Policy-Portfolio.md
@@ -0,0 +1,7 @@
+# Using the Policy Portfolio
+
+The Microsoft Cloud for Sovereignty has as [Policy Portfolio](https://github.com/Azure/cloud-for-sovereignty-policy-portfolio) with each set of initiatives within the portfolio designed to help an organization demonstrate compliance against a country or industry specific regulation. Our [public documentation](https://learn.microsoft.com/industry/sovereignty/policy-portfolio-baseline) contains more information.
+
+All sets of initiatives within the policy portfolio can be used in any landing zone, but have also been tested against workloads running within the SLZ Preview. For the [sets of policies](https://github.com/Azure/cloud-for-sovereignty-policy-portfolio) that are not yet built-in, their definitions will need to be deployed in the top-level or parent management group for the SLZ Preview prior to being deployed. Follow the documentation within the portfolio repository for more details. All others will be built-in and no additional setup steps are required.
+
+To use one or more policy sets from the policy portfolio update the `parCustomerPolicySets` parameter with the assignment information. These assignments will be created at the top-level management group for the SLZ Preview and will apply to all resources contained within. All policy sets within the portfolio have safe defaults, so no additional configuration is required to get started with them. The `parCustomerPolicySets` parameter does not allow for Azure policy assignment parameters to be passed.
diff --git a/modules/Microsoft.ManagedIdentity/userAssignedIdentities/.bicep/nested_roleAssignments.bicep b/modules/Microsoft.ManagedIdentity/userAssignedIdentities/.bicep/nested_roleAssignments.bicep
new file mode 100644
index 00000000..02417d1d
--- /dev/null
+++ b/modules/Microsoft.ManagedIdentity/userAssignedIdentities/.bicep/nested_roleAssignments.bicep
@@ -0,0 +1,72 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+@sys.description('Required. The IDs of the principals to assign the role to.')
+param parPrincipalIds array
+
+@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead.')
+param parRoleDefinitionIdOrName string
+
+@sys.description('Required. The resource ID of the resource to apply the role assignment to.')
+param parResourceId string
+
+@sys.description('Optional. The principal type of the assigned principal ID.')
+@allowed([
+ 'ServicePrincipal'
+ 'Group'
+ 'User'
+ 'ForeignGroup'
+ 'Device'
+ ''
+])
+param parPrincipalType string = ''
+
+@sys.description('Optional. The description of the role assignment.')
+param parDescription string = ''
+
+@sys.description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container"')
+param parCondition string = ''
+
+@sys.description('Optional. Version of the condition.')
+@allowed([
+ '2.0'
+])
+param parConditionVersion string = '2.0'
+
+@sys.description('Optional. Id of the delegated managed identity resource.')
+param parDelegatedManagedIdentityResourceId string = ''
+
+var varBuiltInRoleNames = {
+ Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')
+ Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')
+ Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')
+ 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')
+ 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')
+ 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')
+ 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')
+ 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')
+ 'Managed Identity Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59')
+ 'Managed Identity Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830')
+ 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')
+ 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb')
+ 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')
+ 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')
+ 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')
+}
+
+resource resUserMsi 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = {
+ name: any(last(split(parResourceId, '/')))
+}
+
+resource resRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for principalId in parPrincipalIds: {
+ name: guid(resUserMsi.id, principalId, parRoleDefinitionIdOrName)
+ properties: {
+ description: parDescription
+ roleDefinitionId: contains(varBuiltInRoleNames, parRoleDefinitionIdOrName) ? varBuiltInRoleNames[parRoleDefinitionIdOrName] : parRoleDefinitionIdOrName
+ principalId: principalId
+ principalType: !empty(parPrincipalType) ? any(parPrincipalType) : null
+ condition: !empty(parCondition) ? parCondition : null
+ conditionVersion: !empty(parConditionVersion) && !empty(parCondition) ? parConditionVersion : null
+ delegatedManagedIdentityResourceId: !empty(parDelegatedManagedIdentityResourceId) ? parDelegatedManagedIdentityResourceId : null
+ }
+ scope: resUserMsi
+}]
diff --git a/modules/Microsoft.ManagedIdentity/userAssignedIdentities/deploy.bicep b/modules/Microsoft.ManagedIdentity/userAssignedIdentities/deploy.bicep
new file mode 100644
index 00000000..b7ec97e9
--- /dev/null
+++ b/modules/Microsoft.ManagedIdentity/userAssignedIdentities/deploy.bicep
@@ -0,0 +1,87 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+/*
+ SUMMARY : Creates a user assigned identity and optionally assigns RBAC roles to it.
+*/
+
+@description('Optional. Name of the User Assigned Identity.')
+param parName string = guid(resourceGroup().id)
+
+@description('Optional. Location for all resources.')
+param parLocation string = resourceGroup().location
+
+@allowed([
+ ''
+ 'CanNotDelete'
+ 'ReadOnly'
+])
+@description('Optional. Specify the type of lock.')
+param parLock string = ''
+
+@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.')
+param parRoleAssignments array = []
+
+@description('Optional. Tags of the resource.')
+param parTags object = {}
+
+@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).')
+param parEnableDefaultTelemetry bool = true
+
+// Create default telemetry deployment
+resource resDefaultTelemetry 'Microsoft.Resources/deployments@2022-09-01' = if (parEnableDefaultTelemetry) {
+ name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, parLocation)}'
+ properties: {
+ mode: 'Incremental'
+ template: {
+ '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#'
+ contentVersion: '1.0.0.0'
+ resources: []
+ }
+ }
+}
+
+// Create user assigned identity
+resource resUserMsi 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
+ name: parName
+ location: parLocation
+ tags: parTags
+}
+
+// Create locks on user assigned identity
+resource resUserMsiLock 'Microsoft.Authorization/locks@2020-05-01' = if (!empty(parLock)) {
+ name: '${resUserMsi.name}-${parLock}-lock'
+ properties: {
+ level: any(parLock)
+ notes: parLock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.'
+ }
+ scope: resUserMsi
+}
+
+// Create role assignments
+module modUserMsiRoleAssignments '.bicep/nested_roleAssignments.bicep' = [for (roleAssignment, index) in parRoleAssignments: {
+ name: '${uniqueString(deployment().name, parLocation)}-UserMSI-Rbac-${index}'
+ params: {
+ parDescription: contains(roleAssignment, 'description') ? roleAssignment.description : ''
+ parPrincipalIds: roleAssignment.principalIds
+ parPrincipalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : ''
+ parRoleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName
+ parCondition: contains(roleAssignment, 'condition') ? roleAssignment.condition : ''
+ parDelegatedManagedIdentityResourceId: contains(roleAssignment, 'delegatedManagedIdentityResourceId') ? roleAssignment.delegatedManagedIdentityResourceId : ''
+ parResourceId: resUserMsi.id
+ }
+}]
+
+@description('The name of the user assigned identity.')
+output outName string = resUserMsi.name
+
+@description('The resource ID of the user assigned identity.')
+output outResourceId string = resUserMsi.id
+
+@description('The principal ID of the user assigned identity.')
+output outPrincipalId string = resUserMsi.properties.principalId
+
+@description('The resource group the user assigned identity was deployed into.')
+output outResourceGroupName string = resourceGroup().name
+
+@description('The location the resource was deployed into.')
+output outLocation string = resUserMsi.location
diff --git a/modules/Microsoft.ManagedIdentity/userAssignedIdentities/readme.md b/modules/Microsoft.ManagedIdentity/userAssignedIdentities/readme.md
new file mode 100644
index 00000000..cd2c7692
--- /dev/null
+++ b/modules/Microsoft.ManagedIdentity/userAssignedIdentities/readme.md
@@ -0,0 +1,212 @@
+# User Assigned Identities `[Microsoft.ManagedIdentity/userAssignedIdentities]`
+
+This module deploys a user assigned identity.
+
+## Navigation
+
+- [Resource types](#Resource-types)
+- [Parameters](#Parameters)
+- [Outputs](#Outputs)
+- [Cross-referenced modules](#Cross-referenced-modules)
+- [Deployment examples](#Deployment-examples)
+
+## Resource types
+
+| Resource Type | API Version |
+| :-- | :-- |
+| `Microsoft.Authorization/locks` | [2017-04-01](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) |
+| `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) |
+| `Microsoft.ManagedIdentity/userAssignedIdentities` | [2018-11-30](https://docs.microsoft.com/en-us/azure/templates/Microsoft.ManagedIdentity/2018-11-30/userAssignedIdentities) |
+
+## Parameters
+
+**Optional parameters**
+| Parameter Name | Type | Default Value | Allowed Values | Description |
+| :-- | :-- | :-- | :-- | :-- |
+| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). |
+| `location` | string | `[resourceGroup().location]` | | Location for all resources. |
+| `lock` | string | `''` | `['', CanNotDelete, ReadOnly]` | Specify the type of lock. |
+| `name` | string | `[guid(resourceGroup().id)]` | | Name of the User Assigned Identity. |
+| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. |
+| `tags` | object | `{object}` | | Tags of the resource. |
+
+
+### Parameter Usage: `roleAssignments`
+
+Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure.
+
+
+
+Parameter JSON format
+
+```json
+"roleAssignments": {
+ "value": [
+ {
+ "roleDefinitionIdOrName": "Reader",
+ "description": "Reader Role Assignment",
+ "principalIds": [
+ "12345678-1234-1234-1234-123456789012", // object 1
+ "78945612-1234-1234-1234-123456789012" // object 2
+ ]
+ },
+ {
+ "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11",
+ "principalIds": [
+ "12345678-1234-1234-1234-123456789012" // object 1
+ ],
+ "principalType": "ServicePrincipal"
+ }
+ ]
+}
+```
+
+
+
+
+
+Bicep format
+
+```bicep
+roleAssignments: [
+ {
+ roleDefinitionIdOrName: 'Reader'
+ description: 'Reader Role Assignment'
+ principalIds: [
+ '12345678-1234-1234-1234-123456789012' // object 1
+ '78945612-1234-1234-1234-123456789012' // object 2
+ ]
+ }
+ {
+ roleDefinitionIdOrName: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'
+ principalIds: [
+ '12345678-1234-1234-1234-123456789012' // object 1
+ ]
+ principalType: 'ServicePrincipal'
+ }
+]
+```
+
+
+
+
+### Parameter Usage: `tags`
+
+Tag names and tag values can be provided as needed. A tag can be left without a value.
+
+
+
+Parameter JSON format
+
+```json
+"tags": {
+ "value": {
+ "Environment": "Non-Prod",
+ "Contact": "test.user@testcompany.com",
+ "PurchaseOrder": "1234",
+ "CostCenter": "7890",
+ "ServiceName": "DeploymentValidation",
+ "Role": "DeploymentValidation"
+ }
+}
+```
+
+
+
+
+
+Bicep format
+
+```bicep
+tags: {
+ Environment: 'Non-Prod'
+ Contact: 'test.user@testcompany.com'
+ PurchaseOrder: '1234'
+ CostCenter: '7890'
+ ServiceName: 'DeploymentValidation'
+ Role: 'DeploymentValidation'
+}
+```
+
+
+
+
+## Outputs
+
+| Output Name | Type | Description |
+| :-- | :-- | :-- |
+| `location` | string | The location the resource was deployed into. |
+| `name` | string | The name of the user assigned identity. |
+| `principalId` | string | The principal ID of the user assigned identity. |
+| `resourceGroupName` | string | The resource group the user assigned identity was deployed into. |
+| `resourceId` | string | The resource ID of the user assigned identity. |
+
+## Cross-referenced modules
+
+_None_
+
+## Deployment examples
+
+The following module usage examples are retrieved from the content of the files hosted in the module's `.test` folder.
+ >**Note**: The name of each example is based on the name of the file from which it is taken.
+
+ >**Note**: Each example lists all the required parameters first, followed by the rest - each in alphabetical order.
+
+
Example 1: Parameters
+
+
+
+via Bicep module
+
+```bicep
+module userAssignedIdentities './Microsoft.ManagedIdentity/userAssignedIdentities/deploy.bicep' = {
+ name: '${uniqueString(deployment().name)}-UserAssignedIdentities'
+ params: {
+ lock: 'CanNotDelete'
+ name: '<>-az-msi-x-001'
+ roleAssignments: [
+ {
+ principalIds: [
+ '<>'
+ ]
+ roleDefinitionIdOrName: 'Reader'
+ }
+ ]
+ }
+}
+```
+
+
+
+
+
+
+via JSON Parameter file
+
+```json
+{
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
+ "contentVersion": "1.0.0.0",
+ "parameters": {
+ "lock": {
+ "value": "CanNotDelete"
+ },
+ "name": {
+ "value": "<>-az-msi-x-001"
+ },
+ "roleAssignments": {
+ "value": [
+ {
+ "principalIds": [
+ "<>"
+ ],
+ "roleDefinitionIdOrName": "Reader"
+ }
+ ]
+ }
+ }
+}
+```
+
+
+
diff --git a/modules/compliance/customCompliance.bicep b/modules/compliance/customCompliance.bicep
new file mode 100644
index 00000000..e72ee787
--- /dev/null
+++ b/modules/compliance/customCompliance.bicep
@@ -0,0 +1,425 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+/*
+ SUMMARY : Deploys the Management Groups and Subscriptions for the Sovereign Landing Zone
+ AUTHOR/S: Cloud for Sovereignty
+*/
+targetScope = 'managementGroup'
+@description('The prefix that will be added to all resources created by this deployment.')
+@minLength(2)
+@maxLength(5)
+param parDeploymentPrefix string
+
+@description('The suffix that will be added to management group suffix name the same way to be added to management group prefix names.')
+@maxLength(5)
+param parDeploymentSuffix string
+
+@description('An array containing a list of Subscription IDs that the System-assigned Managed Identity associated to the policy assignment will be assigned to in addition to the Management Group the policy is deployed/assigned to.')
+param parIdentityRoleAssignmentsSubs array
+
+@description('The role definition ids for permissions.')
+param parRoleDefinitionIds array
+
+// Managment Groups Varaibles - Used For Policy Assignments
+var varManagementGroupIDs = {
+ intRoot: '${parDeploymentPrefix}${parDeploymentSuffix}'
+ platform: '${parDeploymentPrefix}-platform${parDeploymentSuffix}'
+ platformManagement: '${parDeploymentPrefix}-platform-management${parDeploymentSuffix}'
+ platformConnectivity: '${parDeploymentPrefix}-platform-connectivity${parDeploymentSuffix}'
+ platformIdentity: '${parDeploymentPrefix}-platform-identity${parDeploymentSuffix}'
+ landingZones: '${parDeploymentPrefix}-landingzones${parDeploymentSuffix}'
+ landingZonesCorp: '${parDeploymentPrefix}-landingzones-corp${parDeploymentSuffix}'
+ landingZonesOnline: '${parDeploymentPrefix}-landingzones-online${parDeploymentSuffix}'
+ landingZonesConfidentialCorp: '${parDeploymentPrefix}-landingzones-confidential-corp${parDeploymentSuffix}'
+ landingZonesConfidentialOnline: '${parDeploymentPrefix}-landingzones-confidential-online${parDeploymentSuffix}'
+ decommissioned: '${parDeploymentPrefix}-decommissioned${parDeploymentSuffix}'
+ sandbox: '${parDeploymentPrefix}-sandbox${parDeploymentSuffix}'
+}
+
+var varTopLevelManagementGroupResourceID = '/providers/Microsoft.Management/managementGroups/${varManagementGroupIDs.intRoot}'
+
+// Policy Assignments Modules Variables
+
+var varGlobalCustomPoliciesLibDef = loadJsonContent('../../custom/policies/definitions/slzGlobalCustom.json')
+var varGlobalCustomPolicies = {
+ definitionID: replace('${varGlobalCustomPoliciesLibDef.id}.v${varGlobalCustomPoliciesLibDef.properties.metadata.version}', '\${varTargetManagementGroupResourceId}', varTopLevelManagementGroupResourceID)
+ libAssignment: loadJsonContent('../../custom/policies/assignments/policy_assignment_deploy_slz_global_custom.tmpl.json')
+ libDefinition: varGlobalCustomPoliciesLibDef
+ version: replace('v${varGlobalCustomPoliciesLibDef.properties.metadata.version}', '.', '')
+}
+
+var varLandingZonesPoliciesLibDef = loadJsonContent('../../custom/policies/definitions/slzLandingZoneCustom.json')
+var varLandingZonesPolicies = {
+ definitionID: replace('${varLandingZonesPoliciesLibDef.id}.v${varLandingZonesPoliciesLibDef.properties.metadata.version}', '\${varTargetManagementGroupResourceId}', varTopLevelManagementGroupResourceID)
+ libAssignment: loadJsonContent('../../custom/policies/assignments/policy_assignment_deploy_slz_landing_zones_custom.tmpl.json')
+ libDefinition: varLandingZonesPoliciesLibDef
+ version: replace('v${varLandingZonesPoliciesLibDef.properties.metadata.version}', '.', '')
+}
+
+var varConfidentialCustomPoliciesLibDef = loadJsonContent('../../custom/policies/definitions/slzConfidentialCustom.json')
+var varConfidentialCustomPolicies = {
+ definitionID: replace('${varConfidentialCustomPoliciesLibDef.id}.v${varConfidentialCustomPoliciesLibDef.properties.metadata.version}', '\${varTargetManagementGroupResourceId}', varTopLevelManagementGroupResourceID)
+ libAssignment: loadJsonContent('../../custom/policies/assignments/policy_assignment_deploy_slz_confidential_custom.tmpl.json')
+ libDefinition: varConfidentialCustomPoliciesLibDef
+ version: replace('v${varConfidentialCustomPoliciesLibDef.properties.metadata.version}', '.', '')
+}
+
+var varCorpCustomPoliciesLibDef = loadJsonContent('../../custom/policies/definitions/slzCorpCustom.json')
+var varCorpCustomPolicies = {
+ definitionID: replace('${varCorpCustomPoliciesLibDef.id}.v${varCorpCustomPoliciesLibDef.properties.metadata.version}', '\${varTargetManagementGroupResourceId}', varTopLevelManagementGroupResourceID)
+ libAssignment: loadJsonContent('../../custom/policies/assignments/policy_assignment_deploy_slz_corp_custom.tmpl.json')
+ libDefinition: varCorpCustomPoliciesLibDef
+ version: replace('v${varCorpCustomPoliciesLibDef.properties.metadata.version}', '.', '')
+}
+
+var varOnlineCustomPoliciesLibDef = loadJsonContent('../../custom/policies/definitions/slzOnlineCustom.json')
+var varOnlineCustomPolicies = {
+ definitionID: replace('${varOnlineCustomPoliciesLibDef.id}.v${varOnlineCustomPoliciesLibDef.properties.metadata.version}', '\${varTargetManagementGroupResourceId}', varTopLevelManagementGroupResourceID)
+ libAssignment: loadJsonContent('../../custom/policies/assignments/policy_assignment_deploy_slz_online_custom.tmpl.json')
+ libDefinition: varOnlineCustomPoliciesLibDef
+ version: replace('v${varOnlineCustomPoliciesLibDef.properties.metadata.version}', '.', '')
+}
+
+var varPlatformCustomPoliciesLibDef = loadJsonContent('../../custom/policies/definitions/slzPlatformCustom.json')
+var varPlatformCustomPolicies = {
+ definitionID: replace('${varPlatformCustomPoliciesLibDef.id}.v${varPlatformCustomPoliciesLibDef.properties.metadata.version}', '\${varTargetManagementGroupResourceId}', varTopLevelManagementGroupResourceID)
+ libAssignment: loadJsonContent('../../custom/policies/assignments/policy_assignment_deploy_slz_platform_custom.tmpl.json')
+ libDefinition: varPlatformCustomPoliciesLibDef
+ version: replace('v${varPlatformCustomPoliciesLibDef.properties.metadata.version}', '.', '')
+}
+
+var varConnectivityCustomPoliciesLibDef = loadJsonContent('../../custom/policies/definitions/slzConnectivityCustom.json')
+var varConnectivityCustomPolicies = {
+ definitionID: replace('${varConnectivityCustomPoliciesLibDef.id}.v${varConnectivityCustomPoliciesLibDef.properties.metadata.version}', '\${varTargetManagementGroupResourceId}', varTopLevelManagementGroupResourceID)
+ libAssignment: loadJsonContent('../../custom/policies/assignments/policy_assignment_deploy_slz_connectivity_custom.tmpl.json')
+ libDefinition: varConnectivityCustomPoliciesLibDef
+ version: replace('v${varConnectivityCustomPoliciesLibDef.properties.metadata.version}', '.', '')
+}
+
+var varIdentityCustomPoliciesLibDef = loadJsonContent('../../custom/policies/definitions/slzIdentityCustom.json')
+var varIdentityCustomPolicies = {
+ definitionID: replace('${varIdentityCustomPoliciesLibDef.id}.v${varIdentityCustomPoliciesLibDef.properties.metadata.version}', '\${varTargetManagementGroupResourceId}', varTopLevelManagementGroupResourceID)
+ libAssignment: loadJsonContent('../../custom/policies/assignments/policy_assignment_deploy_slz_identity_custom.tmpl.json')
+ libDefinition: varIdentityCustomPoliciesLibDef
+ version: replace('v${varIdentityCustomPoliciesLibDef.properties.metadata.version}', '.', '')
+}
+
+var varManagementCustomPoliciesLibDef = loadJsonContent('../../custom/policies/definitions/slzManagementCustom.json')
+var varManagementCustomPolicies = {
+ definitionID: replace('${varManagementCustomPoliciesLibDef.id}.v${varManagementCustomPoliciesLibDef.properties.metadata.version}', '\${varTargetManagementGroupResourceId}', varTopLevelManagementGroupResourceID)
+ libAssignment: loadJsonContent('../../custom/policies/assignments/policy_assignment_deploy_slz_management_custom.tmpl.json')
+ libDefinition: varManagementCustomPoliciesLibDef
+ version: replace('v${varManagementCustomPoliciesLibDef.properties.metadata.version}', '.', '')
+}
+
+var varSandboxCustomPoliciesLibDef = loadJsonContent('../../custom/policies/definitions/slzSandboxCustom.json')
+var varSandboxCustomPolicies = {
+ definitionID: replace('${varSandboxCustomPoliciesLibDef.id}.v${varSandboxCustomPoliciesLibDef.properties.metadata.version}', '\${varTargetManagementGroupResourceId}', varTopLevelManagementGroupResourceID)
+ libAssignment: loadJsonContent('../../custom/policies/assignments/policy_assignment_deploy_slz_sandbox_custom.tmpl.json')
+ libDefinition: varSandboxCustomPoliciesLibDef
+ version: replace('v${varSandboxCustomPoliciesLibDef.properties.metadata.version}', '.', '')
+}
+
+var varDecommissionedCustomPoliciesLibDef = loadJsonContent('../../custom/policies/definitions/slzDecommissionedCustom.json')
+var varDecommissionedCustomPolicies = {
+ definitionID: replace('${varDecommissionedCustomPoliciesLibDef.id}.v${varDecommissionedCustomPoliciesLibDef.properties.metadata.version}', '\${varTargetManagementGroupResourceId}', varTopLevelManagementGroupResourceID)
+ libAssignment: loadJsonContent('../../custom/policies/assignments/policy_assignment_deploy_slz_decommissioned_custom.tmpl.json')
+ libDefinition: varDecommissionedCustomPoliciesLibDef
+ version: replace('v${varDecommissionedCustomPoliciesLibDef.properties.metadata.version}', '.', '')
+}
+
+var varDeploymentNameWrappers = {
+ basePrefix: parDeploymentPrefix
+ #disable-next-line no-loc-expr-outside-params //Policies resources are not deployed to a region, like other resources, but the metadata is stored in a region hence requiring this to keep input parameters reduced. See https://github.com/Azure/ALZ-Bicep/wiki/FAQ#why-are-some-linter-rules-disabled-via-the-disable-next-line-bicep-function for more information
+ baseSuffixTenantAndManagementGroup: deployment().location
+}
+
+@description('Timestamp with format yyyyMMddTHHmmssZ. Default value set to Execution Timestamp to avoid deployment contention.')
+param parTimestamp string = utcNow()
+
+var varModuleDeploymentNames = {
+ modPolicyAssignmentIntRootSlzCustom: take('${varDeploymentNameWrappers.basePrefix}-polAssi-slzCustom-intRoot-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}-${parTimestamp}', 64)
+ modPolicyAssignmentPlatformCustom: take('${varDeploymentNameWrappers.basePrefix}-polAssi-platformCustom-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}-${parTimestamp}', 64)
+ modPolicyAssignmentSandboxCustom: take('${varDeploymentNameWrappers.basePrefix}-polAssi-sandboxCustom-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}-${parTimestamp}', 64)
+ modPolicyAssignmentDecommissionedCustom: take('${varDeploymentNameWrappers.basePrefix}-polAssi-decomCustom-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}-${parTimestamp}', 64)
+ modPolicyAssignmentLandingZoneCustom: take('${varDeploymentNameWrappers.basePrefix}-polAssi-landingZoneCustom-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}-${parTimestamp}', 64)
+ modPolicyAssignmentCorpCustom: take('${varDeploymentNameWrappers.basePrefix}-polAssi-corpCustom-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}-${parTimestamp}', 64)
+ modPolicyAssignmentOnlineCustom: take('${varDeploymentNameWrappers.basePrefix}-polAssi-onlineCustom-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}-${parTimestamp}', 64)
+ modPolicyAssignmentConfidentialCorpCustom_Confidential: take('${varDeploymentNameWrappers.basePrefix}-polAssi-confidentialCorpCustom_Confidential-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}-${parTimestamp}', 64)
+ modPolicyAssignmentConfidentialCorpCustom_Corp: take('${varDeploymentNameWrappers.basePrefix}-polAssi-confidentialCorpCustom_Corp-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}-${parTimestamp}', 64)
+ modPolicyAssignmentConfidentialOnlineCustom_Confidential: take('${varDeploymentNameWrappers.basePrefix}-polAssi-confidentialOnlineCustom_Confidential-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}-${parTimestamp}', 64)
+ modPolicyAssignmentConfidentialOnlineCustom_Online: take('${varDeploymentNameWrappers.basePrefix}-polAssi-confidentialOnlineCustom_Online-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}-${parTimestamp}', 64)
+ modPolicyAssignmentConnectivityCustom: take('${varDeploymentNameWrappers.basePrefix}-polAssi-connectivityCustom-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}-${parTimestamp}', 64)
+ modPolicyAssignmentIdentityCustom: take('${varDeploymentNameWrappers.basePrefix}-polAssi-identityCustom-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}-${parTimestamp}', 64)
+ modPolicyAssignmentManagementCustom: take('${varDeploymentNameWrappers.basePrefix}-polAssi-managementCustom-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}-${parTimestamp}', 64)
+}
+
+// Module - Policy Assignments - Root Management Group
+module modPolicyAssignmentGlobalCustom '../../dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep' = if (!empty(varGlobalCustomPolicies.libDefinition.properties.policyDefinitions)) {
+ name: varModuleDeploymentNames.modPolicyAssignmentIntRootSlzCustom
+ scope: managementGroup(varManagementGroupIDs.intRoot)
+ params: {
+ parPolicyAssignmentDefinitionId: varGlobalCustomPolicies.definitionID
+ parPolicyAssignmentDescription: '${varGlobalCustomPolicies.libAssignment.properties.description} ${varGlobalCustomPolicies.version}'
+ parPolicyAssignmentDisplayName: '${varGlobalCustomPolicies.libAssignment.properties.displayName} ${varGlobalCustomPolicies.version}'
+ parPolicyAssignmentName: take('${varGlobalCustomPolicies.libAssignment.name}${varGlobalCustomPolicies.version}', 24)
+ parPolicyAssignmentEnforcementMode: 'Default'
+ parPolicyAssignmentIdentityRoleAssignmentsSubs: parIdentityRoleAssignmentsSubs
+ parPolicyAssignmentIdentityRoleDefinitionIds: parRoleDefinitionIds
+ parPolicyAssignmentIdentityType: 'SystemAssigned'
+ parTelemetryOptOut: true
+ }
+}
+
+// Module - Policy Assignments - Decommisioned Management Group
+module modPolicyAssignmentDecommissionedCustom '../../dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep' = if (!empty(varDecommissionedCustomPolicies.libDefinition.properties.policyDefinitions)) {
+ name: varModuleDeploymentNames.modPolicyAssignmentDecommissionedCustom
+ scope: managementGroup(varManagementGroupIDs.decommissioned)
+ params: {
+ parPolicyAssignmentDefinitionId: varDecommissionedCustomPolicies.definitionID
+ parPolicyAssignmentDescription: '${varDecommissionedCustomPolicies.libAssignment.properties.description} ${varDecommissionedCustomPolicies.version}'
+ parPolicyAssignmentDisplayName: '${varDecommissionedCustomPolicies.libAssignment.properties.displayName} ${varDecommissionedCustomPolicies.version}'
+ parPolicyAssignmentName: take('${varDecommissionedCustomPolicies.libAssignment.name}${varDecommissionedCustomPolicies.version}', 24)
+ parPolicyAssignmentEnforcementMode: 'Default'
+ parPolicyAssignmentIdentityRoleAssignmentsSubs: parIdentityRoleAssignmentsSubs
+ parPolicyAssignmentIdentityRoleDefinitionIds: parRoleDefinitionIds
+ parPolicyAssignmentIdentityType: 'SystemAssigned'
+ parTelemetryOptOut: true
+ }
+}
+
+// Module - Policy Assignments - Landing Zone Management Group
+module modPolicyAssignmentLandingZoneCustom '../../dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep' = if (!empty(varLandingZonesPolicies.libDefinition.properties.policyDefinitions)) {
+ name: varModuleDeploymentNames.modPolicyAssignmentLandingZoneCustom
+ scope: managementGroup(varManagementGroupIDs.landingZones)
+ params: {
+ parPolicyAssignmentDefinitionId: varLandingZonesPolicies.definitionID
+ parPolicyAssignmentDescription: '${varLandingZonesPolicies.libAssignment.properties.description} ${varLandingZonesPolicies.version}'
+ parPolicyAssignmentDisplayName: '${varLandingZonesPolicies.libAssignment.properties.displayName} ${varLandingZonesPolicies.version}'
+ parPolicyAssignmentName: take('${varLandingZonesPolicies.libAssignment.name}${varLandingZonesPolicies.version}', 24)
+ parPolicyAssignmentEnforcementMode: 'Default'
+ parPolicyAssignmentIdentityRoleAssignmentsSubs: parIdentityRoleAssignmentsSubs
+ parPolicyAssignmentIdentityRoleDefinitionIds: parRoleDefinitionIds
+ parPolicyAssignmentIdentityType: 'SystemAssigned'
+ parTelemetryOptOut: true
+ }
+}
+
+// Module - Policy Assignments - Landing Zone Confidential Corp Management Group
+module modPolicyAssignmentConfidentialCorpCustom_Confidential '../../dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep' = if (!empty(varConfidentialCustomPolicies.libDefinition.properties.policyDefinitions)) {
+ name: varModuleDeploymentNames.modPolicyAssignmentConfidentialCorpCustom_Confidential
+ scope: managementGroup(varManagementGroupIDs.landingZonesConfidentialCorp)
+ params: {
+ parPolicyAssignmentDefinitionId: varConfidentialCustomPolicies.definitionID
+ parPolicyAssignmentDescription: '${varConfidentialCustomPolicies.libAssignment.properties.description} ${varConfidentialCustomPolicies.version}'
+ parPolicyAssignmentDisplayName: '${varConfidentialCustomPolicies.libAssignment.properties.displayName} ${varConfidentialCustomPolicies.version}'
+ parPolicyAssignmentName: take('${varConfidentialCustomPolicies.libAssignment.name}${varConfidentialCustomPolicies.version}', 24)
+ parPolicyAssignmentEnforcementMode: 'Default'
+ parPolicyAssignmentIdentityRoleAssignmentsAdditionalMgs: []
+ parPolicyAssignmentIdentityRoleAssignmentsSubs: parIdentityRoleAssignmentsSubs
+ parPolicyAssignmentIdentityRoleDefinitionIds: parRoleDefinitionIds
+ parPolicyAssignmentIdentityType: 'SystemAssigned'
+ parPolicyAssignmentNonComplianceMessages: []
+ parPolicyAssignmentNotScopes: []
+ parTelemetryOptOut: true
+ }
+}
+
+module modPolicyAssignmentConfidentialCorpCustom_Corp '../../dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep' = if (!empty(varCorpCustomPolicies.libDefinition.properties.policyDefinitions)) {
+ name: varModuleDeploymentNames.modPolicyAssignmentConfidentialCorpCustom_Corp
+ scope: managementGroup(varManagementGroupIDs.landingZonesConfidentialCorp)
+ params: {
+ parPolicyAssignmentDefinitionId: varCorpCustomPolicies.definitionID
+ parPolicyAssignmentDescription: '${varCorpCustomPolicies.libAssignment.properties.description} ${varCorpCustomPolicies.version}'
+ parPolicyAssignmentDisplayName: '${varCorpCustomPolicies.libAssignment.properties.displayName} ${varCorpCustomPolicies.version}'
+ parPolicyAssignmentName: take('${varCorpCustomPolicies.libAssignment.name}${varCorpCustomPolicies.version}', 24)
+ parPolicyAssignmentEnforcementMode: 'Default'
+ parPolicyAssignmentIdentityRoleAssignmentsAdditionalMgs: []
+ parPolicyAssignmentIdentityRoleAssignmentsSubs: parIdentityRoleAssignmentsSubs
+ parPolicyAssignmentIdentityRoleDefinitionIds: parRoleDefinitionIds
+ parPolicyAssignmentIdentityType: 'SystemAssigned'
+ parPolicyAssignmentNonComplianceMessages: []
+ parPolicyAssignmentNotScopes: []
+ parTelemetryOptOut: true
+ }
+}
+
+// Module - Policy Assignments - Landing Zone Confidential Online Management Group
+module modPolicyAssignmentConfidentialOnlineCustom_Confidential '../../dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep' = if (!empty(varConfidentialCustomPolicies.libDefinition.properties.policyDefinitions)) {
+ name: varModuleDeploymentNames.modPolicyAssignmentConfidentialOnlineCustom_Confidential
+ scope: managementGroup(varManagementGroupIDs.landingZonesConfidentialOnline)
+ params: {
+ parPolicyAssignmentDefinitionId: varConfidentialCustomPolicies.definitionID
+ parPolicyAssignmentDescription: '${varConfidentialCustomPolicies.libAssignment.properties.description} ${varConfidentialCustomPolicies.version}'
+ parPolicyAssignmentDisplayName: '${varConfidentialCustomPolicies.libAssignment.properties.displayName} ${varConfidentialCustomPolicies.version}'
+ parPolicyAssignmentName: take('${varConfidentialCustomPolicies.libAssignment.name}${varConfidentialCustomPolicies.version}', 24)
+ parPolicyAssignmentEnforcementMode: 'Default'
+ parPolicyAssignmentIdentityRoleAssignmentsAdditionalMgs: []
+ parPolicyAssignmentIdentityRoleAssignmentsSubs: parIdentityRoleAssignmentsSubs
+ parPolicyAssignmentIdentityRoleDefinitionIds: parRoleDefinitionIds
+ parPolicyAssignmentIdentityType: 'SystemAssigned'
+ parPolicyAssignmentNonComplianceMessages: []
+ parPolicyAssignmentNotScopes: []
+ parTelemetryOptOut: true
+ }
+}
+
+// Module - Policy Assignments - Landing Zone Confidential Online Management Group
+module modPolicyAssignmentConfidentialOnlineCustom_Online '../../dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep' = if (!empty(varOnlineCustomPolicies.libDefinition.properties.policyDefinitions)) {
+ name: varModuleDeploymentNames.modPolicyAssignmentConfidentialOnlineCustom_Online
+ scope: managementGroup(varManagementGroupIDs.landingZonesConfidentialOnline)
+ params: {
+ parPolicyAssignmentDefinitionId: varOnlineCustomPolicies.definitionID
+ parPolicyAssignmentDescription: '${varOnlineCustomPolicies.libAssignment.properties.description} ${varOnlineCustomPolicies.version}'
+ parPolicyAssignmentDisplayName: '${varOnlineCustomPolicies.libAssignment.properties.displayName} ${varOnlineCustomPolicies.version}'
+ parPolicyAssignmentName: take('${varOnlineCustomPolicies.libAssignment.name}${varOnlineCustomPolicies.version}', 24)
+ parPolicyAssignmentEnforcementMode: 'Default'
+ parPolicyAssignmentIdentityRoleAssignmentsAdditionalMgs: []
+ parPolicyAssignmentIdentityRoleAssignmentsSubs: parIdentityRoleAssignmentsSubs
+ parPolicyAssignmentIdentityRoleDefinitionIds: parRoleDefinitionIds
+ parPolicyAssignmentIdentityType: 'SystemAssigned'
+ parPolicyAssignmentNonComplianceMessages: []
+ parPolicyAssignmentNotScopes: []
+ parTelemetryOptOut: true
+ }
+}
+
+// Module - Policy Assignments - Landing Zone Corp Management Group
+module modPolicyAssignmentCorpCustom '../../dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep' = if (!empty(varCorpCustomPolicies.libDefinition.properties.policyDefinitions)) {
+ name: varModuleDeploymentNames.modPolicyAssignmentCorpCustom
+ scope: managementGroup(varManagementGroupIDs.landingZonesCorp)
+ params: {
+ parPolicyAssignmentDefinitionId: varOnlineCustomPolicies.definitionID
+ parPolicyAssignmentDescription: '${varCorpCustomPolicies.libAssignment.properties.description} ${varOnlineCustomPolicies.version}'
+ parPolicyAssignmentDisplayName: '${varCorpCustomPolicies.libAssignment.properties.displayName} ${varOnlineCustomPolicies.version}'
+ parPolicyAssignmentName: take('${varCorpCustomPolicies.libAssignment.name}${varOnlineCustomPolicies.version}', 24)
+ parPolicyAssignmentEnforcementMode: 'Default'
+ parPolicyAssignmentIdentityRoleAssignmentsAdditionalMgs: []
+ parPolicyAssignmentIdentityRoleAssignmentsSubs: parIdentityRoleAssignmentsSubs
+ parPolicyAssignmentIdentityRoleDefinitionIds: parRoleDefinitionIds
+ parPolicyAssignmentIdentityType: 'SystemAssigned'
+ parPolicyAssignmentNonComplianceMessages: []
+ parPolicyAssignmentNotScopes: []
+ parTelemetryOptOut: true
+ }
+}
+
+// Module - Policy Assignments - Landing Zone Online Management Group
+module modPolicyAssignmentOnlineCustom '../../dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep' = if (!empty(varOnlineCustomPolicies.libDefinition.properties.policyDefinitions)) {
+ name: varModuleDeploymentNames.modPolicyAssignmentOnlineCustom
+ scope: managementGroup(varManagementGroupIDs.landingZonesOnline)
+ params: {
+ parPolicyAssignmentDefinitionId: varOnlineCustomPolicies.definitionID
+ parPolicyAssignmentDescription: '${varOnlineCustomPolicies.libAssignment.properties.description} ${varOnlineCustomPolicies.version}'
+ parPolicyAssignmentDisplayName: '${varOnlineCustomPolicies.libAssignment.properties.displayName} ${varOnlineCustomPolicies.version}'
+ parPolicyAssignmentName: take('${varOnlineCustomPolicies.libAssignment.name}${varOnlineCustomPolicies.version}', 24)
+ parPolicyAssignmentEnforcementMode: 'Default'
+ parPolicyAssignmentIdentityRoleAssignmentsAdditionalMgs: []
+ parPolicyAssignmentIdentityRoleAssignmentsSubs: parIdentityRoleAssignmentsSubs
+ parPolicyAssignmentIdentityRoleDefinitionIds: parRoleDefinitionIds
+ parPolicyAssignmentIdentityType: 'SystemAssigned'
+ parPolicyAssignmentNonComplianceMessages: []
+ parPolicyAssignmentNotScopes: []
+ parTelemetryOptOut: true
+ }
+}
+
+// Module - Policy Assignments - Platform Management Group
+module modPolicyAssignmentPlatformCustom '../../dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep' = if (!empty(varPlatformCustomPolicies.libDefinition.properties.policyDefinitions)) {
+ name: varModuleDeploymentNames.modPolicyAssignmentPlatformCustom
+ scope: managementGroup(varManagementGroupIDs.platform)
+ params: {
+ parPolicyAssignmentDefinitionId: varPlatformCustomPolicies.definitionID
+ parPolicyAssignmentDescription: '${varPlatformCustomPolicies.libAssignment.properties.description} ${varPlatformCustomPolicies.version}'
+ parPolicyAssignmentDisplayName: '${varPlatformCustomPolicies.libAssignment.properties.displayName} ${varPlatformCustomPolicies.version}'
+ parPolicyAssignmentName: take('${varPlatformCustomPolicies.libAssignment.name}${varPlatformCustomPolicies.version}', 24)
+ parPolicyAssignmentEnforcementMode: 'Default'
+ parPolicyAssignmentIdentityRoleAssignmentsAdditionalMgs: []
+ parPolicyAssignmentIdentityRoleAssignmentsSubs: parIdentityRoleAssignmentsSubs
+ parPolicyAssignmentIdentityRoleDefinitionIds: parRoleDefinitionIds
+ parPolicyAssignmentIdentityType: 'SystemAssigned'
+ parPolicyAssignmentNonComplianceMessages: []
+ parPolicyAssignmentNotScopes: []
+ parTelemetryOptOut: true
+ }
+}
+
+// Module - Policy Assignments - Platform Connectivity Management Group
+module modPolicyAssignmentConnectivityCustom '../../dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep' = if (!empty(varConnectivityCustomPolicies.libDefinition.properties.policyDefinitions)) {
+ name: varModuleDeploymentNames.modPolicyAssignmentConnectivityCustom
+ scope: managementGroup(varManagementGroupIDs.platformConnectivity)
+ params: {
+ parPolicyAssignmentDefinitionId: varConnectivityCustomPolicies.definitionID
+ parPolicyAssignmentDescription: '${varConnectivityCustomPolicies.libAssignment.properties.description} ${varConnectivityCustomPolicies.version}'
+ parPolicyAssignmentDisplayName: '${varConnectivityCustomPolicies.libAssignment.properties.displayName} ${varConnectivityCustomPolicies.version}'
+ parPolicyAssignmentName: take('${varConnectivityCustomPolicies.libAssignment.name}${varConnectivityCustomPolicies.version}', 24)
+ parPolicyAssignmentEnforcementMode: 'Default'
+ parPolicyAssignmentIdentityRoleAssignmentsAdditionalMgs: []
+ parPolicyAssignmentIdentityRoleAssignmentsSubs: parIdentityRoleAssignmentsSubs
+ parPolicyAssignmentIdentityRoleDefinitionIds: parRoleDefinitionIds
+ parPolicyAssignmentIdentityType: 'SystemAssigned'
+ parPolicyAssignmentNonComplianceMessages: []
+ parPolicyAssignmentNotScopes: []
+ parTelemetryOptOut: true
+ }
+}
+
+// Module - Policy Assignments - Platform Identity Management Group
+module modPolicyAssignmentIdentityCustom '../../dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep' = if (!empty(varIdentityCustomPolicies.libDefinition.properties.policyDefinitions)) {
+ name: varModuleDeploymentNames.modPolicyAssignmentIdentityCustom
+ scope: managementGroup(varManagementGroupIDs.platformIdentity)
+ params: {
+ parPolicyAssignmentDefinitionId: varIdentityCustomPolicies.definitionID
+ parPolicyAssignmentDescription: '${varIdentityCustomPolicies.libAssignment.properties.description} ${varIdentityCustomPolicies.version}'
+ parPolicyAssignmentDisplayName: '${varIdentityCustomPolicies.libAssignment.properties.displayName} ${varIdentityCustomPolicies.version}'
+ parPolicyAssignmentName: take('${varIdentityCustomPolicies.libAssignment.name}${varIdentityCustomPolicies.version}', 24)
+ parPolicyAssignmentEnforcementMode: 'Default'
+ parPolicyAssignmentIdentityRoleAssignmentsAdditionalMgs: []
+ parPolicyAssignmentIdentityRoleAssignmentsSubs: parIdentityRoleAssignmentsSubs
+ parPolicyAssignmentIdentityRoleDefinitionIds: parRoleDefinitionIds
+ parPolicyAssignmentIdentityType: 'SystemAssigned'
+ parPolicyAssignmentNonComplianceMessages: []
+ parPolicyAssignmentNotScopes: []
+ parTelemetryOptOut: true
+ }
+}
+
+// Module - Policy Assignments - Platform Management Management Group
+module modPolicyAssignmentManagementCustom '../../dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep' = if (!empty(varManagementCustomPolicies.libDefinition.properties.policyDefinitions)) {
+ name: varModuleDeploymentNames.modPolicyAssignmentManagementCustom
+ scope: managementGroup(varManagementGroupIDs.platformManagement)
+ params: {
+ parPolicyAssignmentDefinitionId: varManagementCustomPolicies.definitionID
+ parPolicyAssignmentDescription: '${varManagementCustomPolicies.libAssignment.properties.description} ${varManagementCustomPolicies.version}'
+ parPolicyAssignmentDisplayName: '${varManagementCustomPolicies.libAssignment.properties.displayName} ${varManagementCustomPolicies.version}'
+ parPolicyAssignmentName: take('${varManagementCustomPolicies.libAssignment.name}${varManagementCustomPolicies.version}', 24)
+ parPolicyAssignmentEnforcementMode: 'Default'
+ parPolicyAssignmentIdentityRoleAssignmentsAdditionalMgs: []
+ parPolicyAssignmentIdentityRoleAssignmentsSubs: parIdentityRoleAssignmentsSubs
+ parPolicyAssignmentIdentityRoleDefinitionIds: parRoleDefinitionIds
+ parPolicyAssignmentIdentityType: 'SystemAssigned'
+ parPolicyAssignmentNonComplianceMessages: []
+ parPolicyAssignmentNotScopes: []
+ parTelemetryOptOut: true
+ }
+}
+
+// Module - Policy Assignments - Sandbox Management Group
+module modPolicyAssignmentSandboxCustom '../../dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep' = if (!empty(varSandboxCustomPolicies.libDefinition.properties.policyDefinitions)) {
+ name: varModuleDeploymentNames.modPolicyAssignmentSandboxCustom
+ scope: managementGroup(varManagementGroupIDs.sandbox)
+ params: {
+ parPolicyAssignmentDefinitionId: varSandboxCustomPolicies.definitionID
+ parPolicyAssignmentDescription: '${varSandboxCustomPolicies.libAssignment.properties.description} ${varSandboxCustomPolicies.version}'
+ parPolicyAssignmentDisplayName: '${varSandboxCustomPolicies.libAssignment.properties.displayName} ${varSandboxCustomPolicies.version}'
+ parPolicyAssignmentName: take('${varSandboxCustomPolicies.libAssignment.name}${varSandboxCustomPolicies.version}', 24)
+ parPolicyAssignmentEnforcementMode: 'Default'
+ parPolicyAssignmentIdentityRoleAssignmentsAdditionalMgs: []
+ parPolicyAssignmentIdentityRoleAssignmentsSubs: parIdentityRoleAssignmentsSubs
+ parPolicyAssignmentIdentityRoleDefinitionIds: parRoleDefinitionIds
+ parPolicyAssignmentIdentityType: 'SystemAssigned'
+ parPolicyAssignmentNonComplianceMessages: []
+ parPolicyAssignmentNotScopes: []
+ parTelemetryOptOut: true
+ }
+}
diff --git a/modules/compliance/customerPolicySetAssignments.bicep b/modules/compliance/customerPolicySetAssignments.bicep
new file mode 100644
index 00000000..c0602ce0
--- /dev/null
+++ b/modules/compliance/customerPolicySetAssignments.bicep
@@ -0,0 +1,57 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+/*
+ SUMMARY :
+ -This module deploys customer configured policy set assignments to the root management group.
+ - Only policy set definition with no parameters or parameters with default values are supported for customer assignment.
+ AUTHOR/S: Cloud for Sovereignty
+*/
+targetScope = 'managementGroup'
+
+@description('The prefix that will be added to all resources created by this deployment.')
+@minLength(2)
+@maxLength(5)
+param parDeploymentPrefix string
+
+@description('The suffix that will be added to management group suffix name the same way to be added to management group prefix names.')
+@maxLength(5)
+param parDeploymentSuffix string
+
+@description('Deployed policy set definition id ')
+param parPolicySetDefinitionId string
+
+@description('Name for the policy set assignment')
+@minLength(1)
+param parPolicySetAssignmentName string
+
+@description('Display name for the policy set assignment')
+param parPolicySetAssignmentDisplayName string
+
+@description('descritpion for the policy set assignment')
+param parPolicySetAssignmentDescription string
+
+var varRootManagementGroupId = '${parDeploymentPrefix}${parDeploymentSuffix}'
+var varRbacRoleDefinitionIds = {
+ owner: '8e3af657-a8ff-443c-a75c-2fe8c4bcb635'
+ contributor: 'b24988ac-6180-42a0-ab88-20f7382dd24c'
+ networkContributor: '4d97b98b-1d4f-4787-a291-c67834d212e7'
+ aksContributor: 'ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8'
+}
+
+// Module - Policy Assignments - Root Management Group
+module modUserPolicyAssignment '../../dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep' = {
+ scope: managementGroup(varRootManagementGroupId)
+ name: take('${parDeploymentPrefix}-polAssi-CustomerPolicySet-intRoot-${parPolicySetAssignmentName}${parDeploymentSuffix}', 64)
+ params: {
+ parPolicyAssignmentDefinitionId: parPolicySetDefinitionId
+ parPolicyAssignmentName: take('${parPolicySetAssignmentName}', 24)
+ parPolicyAssignmentDisplayName: parPolicySetAssignmentDisplayName
+ parPolicyAssignmentDescription: parPolicySetAssignmentDescription
+ parPolicyAssignmentIdentityType: 'SystemAssigned'
+ parPolicyAssignmentIdentityRoleDefinitionIds: [
+ varRbacRoleDefinitionIds.owner
+ ]
+ parPolicyAssignmentEnforcementMode: 'Default'
+ parTelemetryOptOut: true
+ }
+}
diff --git a/modules/compliance/defaultCompliance.bicep b/modules/compliance/defaultCompliance.bicep
new file mode 100644
index 00000000..4995d508
--- /dev/null
+++ b/modules/compliance/defaultCompliance.bicep
@@ -0,0 +1,500 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+/*
+ SUMMARY : This module deploys the policy assignments for the top level management group and the management groups that are children of the top level management group.
+ AUTHOR/S: Cloud for Sovereignty
+*/
+targetScope = 'managementGroup'
+
+@description('The top level management group name which is also the prefix used for resources')
+param parDeploymentPrefix string
+
+@description('The suffix that will be added to management group suffix name the same way to be added to management group prefix names.')
+@maxLength(5)
+param parDeploymentSuffix string
+
+@description('The Azure regions where resources are allowed to be deployed by policy.')
+param parAllowedLocations array
+
+@description('Locations where confidential resources are available and allowed to be used by workloads.')
+param parAllowedLocationsForConfidentialComputing array
+
+@description('Timestamp with format yyyyMMddTHHmmssZ. Default value set to Execution Timestamp to avoid deployment contention.')
+param parTimestamp string = utcNow()
+
+@description('Effect type for all policy definitions')
+param parPolicyEffect string = 'Deny'
+
+// **Variables**
+// Orchestration Module Variables
+var varDeploymentNameWrappers = {
+ basePrefix: parDeploymentPrefix
+ #disable-next-line no-loc-expr-outside-params //Policies resources are not deployed to a region, like other resources, but the metadata is stored in a region hence requiring this to keep input parameters reduced. See https://github.com/Azure/ALZ-Bicep/wiki/FAQ#why-are-some-linter-rules-disabled-via-the-disable-next-line-bicep-function for more information
+ baseSuffixTenantAndManagementGroup: deployment().location
+}
+
+// RBAC Role Definitions Variables - Used For Policy Assignments
+var varRbacRoleDefinitionIds = {
+ owner: '8e3af657-a8ff-443c-a75c-2fe8c4bcb635'
+ contributor: 'b24988ac-6180-42a0-ab88-20f7382dd24c'
+ networkContributor: '4d97b98b-1d4f-4787-a291-c67834d212e7'
+ aksContributor: 'ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8'
+}
+
+var varModuleDeploymentNames = {
+ modPolicyAssignmentIntRootSlzDefaults: take('${varDeploymentNameWrappers.basePrefix}-polAssi-slzDefaults-intRoot-${parTimestamp}', 64)
+ modPolicyAssignmentPlatformDefaults: take('${varDeploymentNameWrappers.basePrefix}-polAssi-platformDefaults-${parTimestamp}', 64)
+ modPolicyAssignmentSandboxDefaults: take('${varDeploymentNameWrappers.basePrefix}-polAssi-sandboxDefaults-${parTimestamp}', 64)
+ modPolicyAssignmentDecommissionedDefaults: take('${varDeploymentNameWrappers.basePrefix}-polAssi-decomDefaults-${parTimestamp}', 64)
+ modPolicyAssignmentLandingZoneDefaults: take('${varDeploymentNameWrappers.basePrefix}-polAssi-landingZoneDefaults-${parTimestamp}', 64)
+ modPolicyAssignmentCorpDefaults: take('${varDeploymentNameWrappers.basePrefix}-polAssi-corpDefaults-${parTimestamp}', 64)
+ modPolicyAssignmentOnlineDefaults: take('${varDeploymentNameWrappers.basePrefix}-polAssi-onlineDefaults-${parTimestamp}', 64)
+ modPolicyAssignmentConfidentialCorpDefaults_Confidential: take('${varDeploymentNameWrappers.basePrefix}-polAssi-confCorpDefaults_Confidential-${parTimestamp}', 64)
+ modPolicyAssignmentConfidentialCorpDefaults_Corp: take('${varDeploymentNameWrappers.basePrefix}-polAssi-confCorpDefaults_Corp-${parTimestamp}', 64)
+ modPolicyAssignmentConfidentialOnlineDefaults_Confidential: take('${varDeploymentNameWrappers.basePrefix}-polAssi-confOnlineDefaults_Confidential-${parTimestamp}', 64)
+ modPolicyAssignmentConfidentialOnlineDefaults_Online: take('${varDeploymentNameWrappers.basePrefix}-polAssi-confOnlineDefaults_Online-${parTimestamp}', 64)
+ modPolicyAssignmentConnectivityDefaults: take('${varDeploymentNameWrappers.basePrefix}-polAssi-connectivityDefaults-${parTimestamp}', 64)
+ modPolicyAssignmentIdentityDefaults: take('${varDeploymentNameWrappers.basePrefix}-polAssi-identityDefaults-${parTimestamp}', 64)
+ modPolicyAssignmentManagementDefaults: take('${varDeploymentNameWrappers.basePrefix}-polAssi-managementDefaults-${parTimestamp}', 64)
+}
+
+// Policy Assignments Modules Variables
+var varSlzGlobalLibDef = loadJsonContent('policySetDefinitions/slzGlobalDefaults.json')
+var varSlzGlobalDefaults = {
+ definitionID: replace('${varSlzGlobalLibDef.id}.v${varSlzGlobalLibDef.properties.metadata.version}', '\${varTargetManagementGroupResourceId}', varTopLevelManagementGroupResourceID)
+ libAssignment: loadJsonContent('policyAssignments/policy_assignmnet_deploy_slz_global_defaults.tmpl.json')
+ libDefinition: varSlzGlobalLibDef
+ version: replace('v${varSlzGlobalLibDef.properties.metadata.version}', '.', '')
+}
+
+var varSlzPlatformLibDef = loadJsonContent('policySetDefinitions/slzPlatformDefaults.json')
+var varSlzPlatformDefaults = {
+ definitionID: replace('${varSlzPlatformLibDef.id}.v${varSlzPlatformLibDef.properties.metadata.version}', '\${varTargetManagementGroupResourceId}', varTopLevelManagementGroupResourceID)
+ libAssignment: loadJsonContent('policyAssignments/policy_assignment_deploy_slz_platform_defaults.tmpl.json')
+ libDefinition: varSlzPlatformLibDef
+ version: replace('v${varSlzPlatformLibDef.properties.metadata.version}', '.', '')
+}
+
+var varSlzSandboxLibDef = loadJsonContent('policySetDefinitions/slzSandboxDefaults.json')
+var varSlzSandboxDefaults = {
+ definitionID: replace('${varSlzSandboxLibDef.id}.v${varSlzSandboxLibDef.properties.metadata.version}', '\${varTargetManagementGroupResourceId}', varTopLevelManagementGroupResourceID)
+ libAssignment: loadJsonContent('policyAssignments/policy_assignment_deploy_slz_sandbox_defaults.tmpl.json')
+ libDefinition: varSlzSandboxLibDef
+ version: replace('v${varSlzSandboxLibDef.properties.metadata.version}', '.', '')
+}
+
+var varSlzDecommissionedLibDef = loadJsonContent('policySetDefinitions/slzDecommissionedDefaults.json')
+var varSlzDecommissionedDefaults = {
+ definitionID: replace('${varSlzDecommissionedLibDef.id}.v${varSlzDecommissionedLibDef.properties.metadata.version}', '\${varTargetManagementGroupResourceId}', varTopLevelManagementGroupResourceID)
+ libAssignment: loadJsonContent('policyAssignments/policy_assignment_deploy_slz_decommissioned_defaults.tmpl.json')
+ libDefinition: varSlzDecommissionedLibDef
+ version: replace('v${varSlzDecommissionedLibDef.properties.metadata.version}', '.', '')
+}
+
+var varSlzLandingZoneLibDef = loadJsonContent('policySetDefinitions/slzLandingZoneDefaults.json')
+var varSlzLandingZoneDefaults = {
+ definitionID: replace('${varSlzLandingZoneLibDef.id}.v${varSlzLandingZoneLibDef.properties.metadata.version}', '\${varTargetManagementGroupResourceId}', varTopLevelManagementGroupResourceID)
+ libAssignment: loadJsonContent('policyAssignments/policy_assignment_deploy_slz_landing_zones_defaults.tmpl.json')
+ libDefinition: varSlzLandingZoneLibDef
+ version: replace('v${varSlzLandingZoneLibDef.properties.metadata.version}', '.', '')
+}
+
+var varSlzCorpLibDef = loadJsonContent('policySetDefinitions/slzCorpDefaults.json')
+var varSlzCorpDefaults = {
+ definitionID: replace('${varSlzCorpLibDef.id}.v${varSlzCorpLibDef.properties.metadata.version}', '\${varTargetManagementGroupResourceId}', varTopLevelManagementGroupResourceID)
+ libAssignment: loadJsonContent('policyAssignments/policy_assignment_deploy_slz_corp_defaults.tmpl.json')
+ libDefinition: varSlzCorpLibDef
+ version: replace('v${varSlzCorpLibDef.properties.metadata.version}', '.', '')
+}
+
+var varSlzOnlineLibDef = loadJsonContent('policySetDefinitions/slzOnlineDefaults.json')
+var varSlzOnlineDefaults = {
+ definitionID: replace('${varSlzOnlineLibDef.id}.v${varSlzOnlineLibDef.properties.metadata.version}', '\${varTargetManagementGroupResourceId}', varTopLevelManagementGroupResourceID)
+ libAssignment: loadJsonContent('policyAssignments/policy_assignment_deploy_slz_online_defaults.tmpl.json')
+ libDefinition: varSlzOnlineLibDef
+ version: replace('v${varSlzOnlineLibDef.properties.metadata.version}', '.', '')
+}
+
+var varSlzConfidentialLibDef = loadJsonContent('policySetDefinitions/slzConfidentialDefaults.json')
+var varSlzConfidentialDefaults = {
+ definitionID: replace('${varSlzConfidentialLibDef.id}.v${varSlzConfidentialLibDef.properties.metadata.version}', '\${varTargetManagementGroupResourceId}', varTopLevelManagementGroupResourceID)
+ libAssignment: loadJsonContent('policyAssignments/policy_assignment_deploy_slz_confidential_defaults.tmpl.json')
+ libDefinition: varSlzConfidentialLibDef
+ version: replace('v${varSlzConfidentialLibDef.properties.metadata.version}', '.', '')
+}
+
+var varSlzConnectivityLibDef = loadJsonContent('policySetDefinitions/slzConnectivityDefaults.json')
+var varSlzConnectivityDefaults = {
+ definitionID: replace('${varSlzConnectivityLibDef.id}.v${varSlzConnectivityLibDef.properties.metadata.version}', '\${varTargetManagementGroupResourceId}', varTopLevelManagementGroupResourceID)
+ libAssignment: loadJsonContent('policyAssignments/policy_assignment_deploy_slz_connectivity_defaults.tmpl.json')
+ libDefinition: varSlzConnectivityLibDef
+ version: replace('v${varSlzConnectivityLibDef.properties.metadata.version}', '.', '')
+}
+
+var varSlzIdentityLibDef = loadJsonContent('policySetDefinitions/slzIdentityDefaults.json')
+var varSlzIdentityDefaults = {
+ definitionID: replace('${varSlzIdentityLibDef.id}.v${varSlzIdentityLibDef.properties.metadata.version}', '\${varTargetManagementGroupResourceId}', varTopLevelManagementGroupResourceID)
+ libAssignment: loadJsonContent('policyAssignments/policy_assignment_deploy_slz_identity_defaults.tmpl.json')
+ libDefinition: varSlzIdentityLibDef
+ version: replace('v${varSlzIdentityLibDef.properties.metadata.version}', '.', '')
+}
+
+var varSlzManagementLibDef = loadJsonContent('policySetDefinitions/slzManagementDefaults.json')
+var varSlzManagementDefaults = {
+ definitionID: replace('${varSlzManagementLibDef.id}.v${varSlzManagementLibDef.properties.metadata.version}', '\${varTargetManagementGroupResourceId}', varTopLevelManagementGroupResourceID)
+ libAssignment: loadJsonContent('policyAssignments/policy_assignment_deploy_slz_management_defaults.tmpl.json')
+ libDefinition: varSlzManagementLibDef
+ version: replace('v${varSlzManagementLibDef.properties.metadata.version}', '.', '')
+}
+
+// Managment Groups Varaibles - Used For Policy Assignments
+var varManagementGroupIDs = {
+ intRoot: '${parDeploymentPrefix}${parDeploymentSuffix}'
+ platform: '${parDeploymentPrefix}-platform${parDeploymentSuffix}'
+ platformManagement: '${parDeploymentPrefix}-platform-management${parDeploymentSuffix}'
+ platformConnectivity: '${parDeploymentPrefix}-platform-connectivity${parDeploymentSuffix}'
+ platformIdentity: '${parDeploymentPrefix}-platform-identity${parDeploymentSuffix}'
+ landingZones: '${parDeploymentPrefix}-landingzones${parDeploymentSuffix}'
+ landingZonesCorp: '${parDeploymentPrefix}-landingzones-corp${parDeploymentSuffix}'
+ landingZonesOnline: '${parDeploymentPrefix}-landingzones-online${parDeploymentSuffix}'
+ landingZonesConfidentialCorp: '${parDeploymentPrefix}-landingzones-confidential-corp${parDeploymentSuffix}'
+ landingZonesConfidentialOnline: '${parDeploymentPrefix}-landingzones-confidential-online${parDeploymentSuffix}'
+ decommissioned: '${parDeploymentPrefix}-decommissioned${parDeploymentSuffix}'
+ sandbox: '${parDeploymentPrefix}-sandbox${parDeploymentSuffix}'
+}
+
+var varTopLevelManagementGroupResourceID = '/providers/Microsoft.Management/managementGroups/${varManagementGroupIDs.intRoot}'
+
+// Module - Policy Assignments - Root Management Group
+module modPolicyAssignmentSlzGlobalDefaults '../../dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep' = if (!empty(varSlzGlobalDefaults.libDefinition.properties.policyDefinitions)) {
+ scope: managementGroup(varManagementGroupIDs.intRoot)
+ name: varModuleDeploymentNames.modPolicyAssignmentIntRootSlzDefaults
+ params: {
+ parPolicyAssignmentDefinitionId: varSlzGlobalDefaults.definitionID
+ parPolicyAssignmentName: take('${varSlzGlobalDefaults.libAssignment.name}${varSlzGlobalDefaults.version}', 24)
+ parPolicyAssignmentDisplayName: '${varSlzGlobalDefaults.libAssignment.properties.displayName} ${varSlzGlobalDefaults.version}'
+ parPolicyAssignmentDescription: '${varSlzGlobalDefaults.libAssignment.properties.description} ${varSlzGlobalDefaults.version}'
+ parPolicyAssignmentParameters: varSlzGlobalDefaults.libAssignment.properties.parameters
+ parPolicyAssignmentParameterOverrides: {
+ listOfAllowedLocations: {
+ value: parAllowedLocations
+ }
+ }
+ parPolicyAssignmentIdentityType: 'SystemAssigned'
+ parPolicyAssignmentIdentityRoleDefinitionIds: [
+ varRbacRoleDefinitionIds.owner
+ ]
+ parPolicyAssignmentEnforcementMode: 'Default'
+ parTelemetryOptOut: true
+ }
+}
+
+// Module - Policy Assignments - Decommisioned Management Group
+module modPolicyAssignmentSlzDecommissionedDefaults '../../dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep' = if (!empty(varSlzDecommissionedDefaults.libDefinition.properties.policyDefinitions)) {
+ scope: managementGroup(varManagementGroupIDs.decommissioned)
+ name: varModuleDeploymentNames.modPolicyAssignmentDecommissionedDefaults
+ params: {
+ parPolicyAssignmentDefinitionId: varSlzDecommissionedDefaults.definitionID
+ parPolicyAssignmentName: take('${varSlzDecommissionedDefaults.libAssignment.name}${varSlzDecommissionedDefaults.version}', 24)
+ parPolicyAssignmentDisplayName: '${varSlzDecommissionedDefaults.libAssignment.properties.displayName} ${varSlzDecommissionedDefaults.version}'
+ parPolicyAssignmentDescription: '${varSlzDecommissionedDefaults.libAssignment.properties.description} ${varSlzDecommissionedDefaults.version}'
+ parPolicyAssignmentParameters: varSlzDecommissionedDefaults.libAssignment.properties.parameters
+ parPolicyAssignmentParameterOverrides: {
+ effect: {
+ value: parPolicyEffect
+ }
+ }
+ parPolicyAssignmentIdentityType: 'SystemAssigned'
+ parPolicyAssignmentIdentityRoleDefinitionIds: [
+ varRbacRoleDefinitionIds.owner
+ ]
+ parPolicyAssignmentEnforcementMode: 'Default'
+ parTelemetryOptOut: true
+ }
+}
+
+// Module - Policy Assignments - Landing Zone Management Group
+module modPolicyAssignmentSlzLandingZoneDefaults '../../dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep' = if (!empty(varSlzLandingZoneDefaults.libDefinition.properties.policyDefinitions)) {
+ scope: managementGroup(varManagementGroupIDs.landingZones)
+ name: varModuleDeploymentNames.modPolicyAssignmentLandingZoneDefaults
+ params: {
+ parPolicyAssignmentDefinitionId: varSlzLandingZoneDefaults.definitionID
+ parPolicyAssignmentName: take('${varSlzLandingZoneDefaults.libAssignment.name}${varSlzLandingZoneDefaults.version}', 24)
+ parPolicyAssignmentDisplayName: '${varSlzLandingZoneDefaults.libAssignment.properties.displayName} ${varSlzLandingZoneDefaults.version}'
+ parPolicyAssignmentDescription: '${varSlzLandingZoneDefaults.libAssignment.properties.description} ${varSlzLandingZoneDefaults.version}'
+ parPolicyAssignmentParameters: varSlzLandingZoneDefaults.libAssignment.properties.parameters
+ parPolicyAssignmentIdentityType: 'SystemAssigned'
+ parPolicyAssignmentIdentityRoleDefinitionIds: [
+ varRbacRoleDefinitionIds.owner
+ ]
+ parPolicyAssignmentEnforcementMode: 'Default'
+ parTelemetryOptOut: true
+ }
+}
+
+// Module - Policy Assignments - Landing Zone Confidential Corp Management Group
+module modPolicyAssignmentSlzConfidentialCorpDefaults_Confidential '../../dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep' = if (!empty(varSlzConfidentialDefaults.libDefinition.properties.policyDefinitions)) {
+ scope: managementGroup(varManagementGroupIDs.landingZonesConfidentialCorp)
+ name: varModuleDeploymentNames.modPolicyAssignmentConfidentialCorpDefaults_Confidential
+ params: {
+ parPolicyAssignmentDefinitionId: varSlzConfidentialDefaults.definitionID
+ parPolicyAssignmentName: take('${varSlzConfidentialDefaults.libAssignment.name}${varSlzConfidentialDefaults.version}', 24)
+ parPolicyAssignmentDisplayName: '${varSlzConfidentialDefaults.libAssignment.properties.displayName} ${varSlzConfidentialDefaults.version}'
+ parPolicyAssignmentDescription: '${varSlzConfidentialDefaults.libAssignment.properties.description} ${varSlzConfidentialDefaults.version}'
+ parPolicyAssignmentParameters: varSlzConfidentialDefaults.libAssignment.properties.parameters
+ parPolicyAssignmentParameterOverrides: {
+ listOfAllowedLocations: {
+ value: parAllowedLocationsForConfidentialComputing
+ }
+ effect: {
+ value: parPolicyEffect
+ }
+ }
+ parPolicyAssignmentIdentityType: 'SystemAssigned'
+ parPolicyAssignmentIdentityRoleDefinitionIds: [
+ varRbacRoleDefinitionIds.owner
+ ]
+ parPolicyAssignmentEnforcementMode: 'Default'
+ parTelemetryOptOut: true
+ }
+}
+// Module - Policy Assignments - Landing Zone Confidential Corp Management Group
+module modPolicyAssignmentSlzConfidentialCorpDefaults_Corp '../../dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep' = if (!empty(varSlzCorpDefaults.libDefinition.properties.policyDefinitions)) {
+ scope: managementGroup(varManagementGroupIDs.landingZonesConfidentialCorp)
+ name: varModuleDeploymentNames.modPolicyAssignmentConfidentialCorpDefaults_Corp
+ params: {
+ parPolicyAssignmentDefinitionId: varSlzCorpDefaults.definitionID
+ parPolicyAssignmentName: take('${varSlzCorpDefaults.libAssignment.name}${varSlzCorpDefaults.version}', 24)
+ parPolicyAssignmentDisplayName: '${varSlzCorpDefaults.libAssignment.properties.displayName} ${varSlzCorpDefaults.version}'
+ parPolicyAssignmentDescription: '${varSlzCorpDefaults.libAssignment.properties.description} ${varSlzCorpDefaults.version}'
+ parPolicyAssignmentParameters: varSlzCorpDefaults.libAssignment.properties.parameters
+ parPolicyAssignmentIdentityType: 'SystemAssigned'
+ parPolicyAssignmentParameterOverrides: {
+ effect: {
+ value: parPolicyEffect
+ }
+ }
+ parPolicyAssignmentIdentityRoleDefinitionIds: [
+ varRbacRoleDefinitionIds.owner
+ ]
+ parPolicyAssignmentEnforcementMode: 'Default'
+ parTelemetryOptOut: true
+ }
+}
+
+// Module - Policy Assignments - Landing Zone Confidential Online Management Group
+module modPolicyAssignmentSlzConfidentialOnlineDefaults_Confidential '../../dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep' = if (!empty(varSlzConfidentialDefaults.libDefinition.properties.policyDefinitions)) {
+ scope: managementGroup(varManagementGroupIDs.landingZonesConfidentialOnline)
+ name: varModuleDeploymentNames.modPolicyAssignmentConfidentialOnlineDefaults_Confidential
+ params: {
+ parPolicyAssignmentDefinitionId: varSlzConfidentialDefaults.definitionID
+ parPolicyAssignmentName: take('${varSlzConfidentialDefaults.libAssignment.name}${varSlzConfidentialDefaults.version}', 24)
+ parPolicyAssignmentDisplayName: '${varSlzConfidentialDefaults.libAssignment.properties.displayName} ${varSlzConfidentialDefaults.version}'
+ parPolicyAssignmentDescription: '${varSlzConfidentialDefaults.libAssignment.properties.description} ${varSlzConfidentialDefaults.version}'
+ parPolicyAssignmentParameters: varSlzConfidentialDefaults.libAssignment.properties.parameters
+ parPolicyAssignmentParameterOverrides: {
+ listOfAllowedLocations: {
+ value: parAllowedLocationsForConfidentialComputing
+ }
+ effect: {
+ value: parPolicyEffect
+ }
+ }
+ parPolicyAssignmentIdentityType: 'SystemAssigned'
+ parPolicyAssignmentIdentityRoleDefinitionIds: [
+ varRbacRoleDefinitionIds.owner
+ ]
+ parPolicyAssignmentEnforcementMode: 'Default'
+ parTelemetryOptOut: true
+ }
+}
+
+// Module - Policy Assignments - Landing Zone Confidential Online Management Group
+module modPolicyAssignmentSlzConfidentialOnlineDefaults_Online '../../dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep' = if (!empty(varSlzOnlineDefaults.libDefinition.properties.policyDefinitions)) {
+ scope: managementGroup(varManagementGroupIDs.landingZonesConfidentialOnline)
+ name: varModuleDeploymentNames.modPolicyAssignmentConfidentialOnlineDefaults_Online
+ params: {
+ parPolicyAssignmentDefinitionId: varSlzOnlineDefaults.definitionID
+ parPolicyAssignmentName: take('${varSlzOnlineDefaults.libAssignment.name}${varSlzOnlineDefaults.version}', 24)
+ parPolicyAssignmentDisplayName: '${varSlzOnlineDefaults.libAssignment.properties.displayName} ${varSlzOnlineDefaults.version}'
+ parPolicyAssignmentDescription: '${varSlzOnlineDefaults.libAssignment.properties.description} ${varSlzOnlineDefaults.version}'
+ parPolicyAssignmentParameters: varSlzOnlineDefaults.libAssignment.properties.parameters
+ parPolicyAssignmentIdentityType: 'SystemAssigned'
+ parPolicyAssignmentParameterOverrides: {
+ effect: {
+ value: parPolicyEffect
+ }
+ }
+ parPolicyAssignmentIdentityRoleDefinitionIds: [
+ varRbacRoleDefinitionIds.owner
+ ]
+ parPolicyAssignmentEnforcementMode: 'Default'
+ parTelemetryOptOut: true
+ }
+}
+
+// Module - Policy Assignments - Landing Zone Corp Management Group
+module modPolicyAssignmentSlzCorpDefaults '../../dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep' = if (!empty(varSlzCorpDefaults.libDefinition.properties.policyDefinitions)) {
+ scope: managementGroup(varManagementGroupIDs.landingZonesCorp)
+ name: varModuleDeploymentNames.modPolicyAssignmentCorpDefaults
+ params: {
+ parPolicyAssignmentDefinitionId: varSlzCorpDefaults.definitionID
+ parPolicyAssignmentName: take('${varSlzCorpDefaults.libAssignment.name}${varSlzCorpDefaults.version}', 24)
+ parPolicyAssignmentDisplayName: '${varSlzCorpDefaults.libAssignment.properties.displayName} ${varSlzCorpDefaults.version}'
+ parPolicyAssignmentDescription: '${varSlzCorpDefaults.libAssignment.properties.description} ${varSlzCorpDefaults.version}'
+ parPolicyAssignmentParameters: varSlzCorpDefaults.libAssignment.properties.parameters
+ parPolicyAssignmentIdentityType: 'SystemAssigned'
+ parPolicyAssignmentIdentityRoleDefinitionIds: [
+ varRbacRoleDefinitionIds.owner
+ ]
+ parPolicyAssignmentParameterOverrides: {
+ effect: {
+ value: parPolicyEffect
+ }
+ }
+ parPolicyAssignmentEnforcementMode: 'Default'
+ parTelemetryOptOut: true
+ }
+}
+
+// Module - Policy Assignments - Landing Zone Online Management Group
+module modPolicyAssignmentSlzOnlineDefaults '../../dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep' = if (!empty(varSlzOnlineDefaults.libDefinition.properties.policyDefinitions)) {
+ scope: managementGroup(varManagementGroupIDs.landingZonesOnline)
+ name: varModuleDeploymentNames.modPolicyAssignmentOnlineDefaults
+ params: {
+ parPolicyAssignmentDefinitionId: varSlzOnlineDefaults.definitionID
+ parPolicyAssignmentName: take('${varSlzOnlineDefaults.libAssignment.name}${varSlzOnlineDefaults.version}', 24)
+ parPolicyAssignmentDisplayName: '${varSlzOnlineDefaults.libAssignment.properties.displayName} ${varSlzOnlineDefaults.version}'
+ parPolicyAssignmentDescription: '${varSlzOnlineDefaults.libAssignment.properties.description} ${varSlzOnlineDefaults.version}'
+ parPolicyAssignmentParameters: varSlzOnlineDefaults.libAssignment.properties.parameters
+ parPolicyAssignmentIdentityType: 'SystemAssigned'
+ parPolicyAssignmentIdentityRoleDefinitionIds: [
+ varRbacRoleDefinitionIds.owner
+ ]
+ parPolicyAssignmentParameterOverrides: {
+ effect: {
+ value: parPolicyEffect
+ }
+ }
+ parPolicyAssignmentEnforcementMode: 'Default'
+ parTelemetryOptOut: true
+ }
+}
+
+// Module - Policy Assignments - Platform Management Group
+module modPolicyAssignmentSlzPlatformDefaults '../../dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep' = if (!empty(varSlzPlatformDefaults.libDefinition.properties.policyDefinitions)) {
+ scope: managementGroup(varManagementGroupIDs.platform)
+ name: varModuleDeploymentNames.modPolicyAssignmentPlatformDefaults
+ params: {
+ parPolicyAssignmentDefinitionId: varSlzPlatformDefaults.definitionID
+ parPolicyAssignmentName: take('${varSlzPlatformDefaults.libAssignment.name}${varSlzPlatformDefaults.version}', 24)
+ parPolicyAssignmentDisplayName: '${varSlzPlatformDefaults.libAssignment.properties.displayName} ${varSlzPlatformDefaults.version}'
+ parPolicyAssignmentDescription: '${varSlzPlatformDefaults.libAssignment.properties.description} ${varSlzPlatformDefaults.version}'
+ parPolicyAssignmentParameters: varSlzPlatformDefaults.libAssignment.properties.parameters
+ parPolicyAssignmentIdentityType: 'SystemAssigned'
+ parPolicyAssignmentIdentityRoleDefinitionIds: [
+ varRbacRoleDefinitionIds.owner
+ ]
+ parPolicyAssignmentEnforcementMode: 'Default'
+ parTelemetryOptOut: true
+ }
+}
+
+// Module - Policy Assignments - Platform Connectivity Management Group
+module modPolicyAssignmentSlzConnectivityDefaults '../../dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep' = if (!empty(varSlzConnectivityDefaults.libDefinition.properties.policyDefinitions)) {
+ scope: managementGroup(varManagementGroupIDs.platformConnectivity)
+ name: varModuleDeploymentNames.modPolicyAssignmentConnectivityDefaults
+ params: {
+ parPolicyAssignmentDefinitionId: varSlzConnectivityDefaults.definitionID
+ parPolicyAssignmentName: take('${varSlzConnectivityDefaults.libAssignment.name}${varSlzConnectivityDefaults.version}', 24)
+ parPolicyAssignmentDisplayName: '${varSlzConnectivityDefaults.libAssignment.properties.displayName} ${varSlzConnectivityDefaults.version}'
+ parPolicyAssignmentDescription: '${varSlzConnectivityDefaults.libAssignment.properties.description} ${varSlzConnectivityDefaults.version}'
+ parPolicyAssignmentParameters: varSlzConnectivityDefaults.libAssignment.properties.parameters
+ parPolicyAssignmentIdentityType: 'SystemAssigned'
+ parPolicyAssignmentEnforcementMode: 'Default'
+ parPolicyAssignmentIdentityRoleDefinitionIds: [
+ varRbacRoleDefinitionIds.networkContributor
+ ]
+ parPolicyAssignmentParameterOverrides: {
+ effect: {
+ value: parPolicyEffect
+ }
+ }
+ parTelemetryOptOut: true
+ }
+}
+
+// Module - Policy Assignments - Platform Identity Management Group
+module modPolicyAssignmentIdentityDefaults '../../dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep' = if (!empty(varSlzIdentityDefaults.libDefinition.properties.policyDefinitions)) {
+ scope: managementGroup(varManagementGroupIDs.platformIdentity)
+ name: varModuleDeploymentNames.modPolicyAssignmentIdentityDefaults
+ params: {
+ parPolicyAssignmentDefinitionId: varSlzIdentityDefaults.definitionID
+ parPolicyAssignmentName: take('${varSlzIdentityDefaults.libAssignment.name}${varSlzIdentityDefaults.version}', 24)
+ parPolicyAssignmentDisplayName: '${varSlzIdentityDefaults.libAssignment.properties.displayName} ${varSlzIdentityDefaults.version}'
+ parPolicyAssignmentDescription: '${varSlzIdentityDefaults.libAssignment.properties.description} ${varSlzIdentityDefaults.version}'
+ parPolicyAssignmentParameters: varSlzIdentityDefaults.libAssignment.properties.parameters
+ parPolicyAssignmentIdentityType: 'SystemAssigned'
+ parPolicyAssignmentIdentityRoleDefinitionIds: [
+ varRbacRoleDefinitionIds.owner
+ ]
+ parPolicyAssignmentParameterOverrides: {
+ effect: {
+ value: parPolicyEffect
+ }
+ }
+ parPolicyAssignmentEnforcementMode: 'Default'
+ parTelemetryOptOut: true
+ }
+}
+
+// Module - Policy Assignments - Platform Management Management Group
+module modPolicyAssignmentSlzManagementDefaults '../../dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep' = if (!empty(varSlzManagementDefaults.libDefinition.properties.policyDefinitions)) {
+ scope: managementGroup(varManagementGroupIDs.platformManagement)
+ name: varModuleDeploymentNames.modPolicyAssignmentManagementDefaults
+ params: {
+ parPolicyAssignmentDefinitionId: varSlzManagementDefaults.definitionID
+ parPolicyAssignmentName: take('${varSlzManagementDefaults.libAssignment.name}${varSlzManagementDefaults.version}', 24)
+ parPolicyAssignmentDisplayName: '${varSlzManagementDefaults.libAssignment.properties.displayName} ${varSlzManagementDefaults.version}'
+ parPolicyAssignmentDescription: '${varSlzManagementDefaults.libAssignment.properties.description} ${varSlzManagementDefaults.version}'
+ parPolicyAssignmentParameters: varSlzManagementDefaults.libAssignment.properties.parameters
+ parPolicyAssignmentIdentityType: 'SystemAssigned'
+ parPolicyAssignmentIdentityRoleDefinitionIds: [
+ varRbacRoleDefinitionIds.owner
+ ]
+ parPolicyAssignmentParameterOverrides: {
+ effect: {
+ value: parPolicyEffect
+ }
+ }
+ parPolicyAssignmentEnforcementMode: 'Default'
+ parTelemetryOptOut: true
+ }
+}
+
+// Module - Policy Assignments - Sandbox Management Group
+module modPolicyAssignmentSlzSandboxDefaults '../../dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep' = if (!empty(varSlzSandboxDefaults.libDefinition.properties.policyDefinitions)) {
+ scope: managementGroup(varManagementGroupIDs.sandbox)
+ name: varModuleDeploymentNames.modPolicyAssignmentSandboxDefaults
+ params: {
+ parPolicyAssignmentDefinitionId: varSlzSandboxDefaults.definitionID
+ parPolicyAssignmentName: take('${varSlzSandboxDefaults.libAssignment.name}${varSlzSandboxDefaults.version}', 24)
+ parPolicyAssignmentDisplayName: '${varSlzSandboxDefaults.libAssignment.properties.displayName} ${varSlzSandboxDefaults.version}'
+ parPolicyAssignmentDescription: '${varSlzSandboxDefaults.libAssignment.properties.description} ${varSlzSandboxDefaults.version}'
+ parPolicyAssignmentParameters: varSlzSandboxDefaults.libAssignment.properties.parameters
+ parPolicyAssignmentIdentityType: 'SystemAssigned'
+ parPolicyAssignmentIdentityRoleDefinitionIds: [
+ varRbacRoleDefinitionIds.owner
+ ]
+ parPolicyAssignmentParameterOverrides: {
+ effect: {
+ value: parPolicyEffect
+ }
+ }
+ parPolicyAssignmentEnforcementMode: 'Default'
+ parTelemetryOptOut: true
+ }
+}
+
+output outSlzGlobalVersion string = varSlzGlobalDefaults.version
+output outSlzGlobalAssignmentName string = take('${varSlzGlobalDefaults.libAssignment.name}${varSlzGlobalDefaults.version}', 24)
diff --git a/modules/compliance/policyAssignments/policy_assignment_deploy_slz_confidential_defaults.tmpl.json b/modules/compliance/policyAssignments/policy_assignment_deploy_slz_confidential_defaults.tmpl.json
new file mode 100644
index 00000000..f7461d8c
--- /dev/null
+++ b/modules/compliance/policyAssignments/policy_assignment_deploy_slz_confidential_defaults.tmpl.json
@@ -0,0 +1,274 @@
+{
+ "name": "Deploy-SLZ-Conf",
+ "type": "Microsoft.Authorization/policyAssignments",
+ "apiVersion": "2019-09-01",
+ "properties": {
+ "description": "SLZ Confidential Policies",
+ "displayName": "SLZ Confidential Policies",
+ "notScopes": [],
+ "parameters": {
+ "listOfAllowedLocations": {
+ "value": []
+ },
+ "Resource Types": {
+ "value": [
+ "Microsoft.Attestation/attestationProviders",
+ "Microsoft.Compute/availabilitySets",
+ "Microsoft.Compute/capacityReservationGroups",
+ "Microsoft.Compute/capacityReservationGroups/capacityReservations",
+ "Microsoft.Compute/cloudServices",
+ "Microsoft.Compute/cloudServices/roles",
+ "Microsoft.Compute/cloudServices/roleInstances",
+ "Microsoft.Compute/cloudServices/networkInterfaces",
+ "Microsoft.Compute/cloudServices/roleInstances/networkInterfaces",
+ "Microsoft.Compute/cloudServices/publicIPAddresses",
+ "Microsoft.Compute/disks",
+ "Microsoft.Compute/diskEncryptionSets",
+ "Microsoft.Compute/diskAccesses",
+ "Microsoft.Compute/galleries",
+ "Microsoft.Compute/galleries/images",
+ "Microsoft.Compute/galleries/images/versions",
+ "Microsoft.Compute/galleries/applications",
+ "Microsoft.Compute/galleries/applications/versions",
+ "Microsoft.Compute/hostGroups",
+ "Microsoft.Compute/hostGroups/hosts",
+ "Microsoft.Compute/images",
+ "Microsoft.Compute/locations",
+ "Microsoft.Compute/locations/artifactPublishers",
+ "Microsoft.Compute/locations/csoperations",
+ "Microsoft.Compute/locations/cloudServiceOsVersions",
+ "Microsoft.Compute/locations/cloudServiceOsFamilies",
+ "Microsoft.Compute/locations/capsoperations",
+ "Microsoft.Compute/locations/communityGalleries",
+ "Microsoft.Compute/locations/diagnostics",
+ "Microsoft.Compute/locations/diagnosticOperations",
+ "Microsoft.Compute/locations/diskoperations",
+ "Microsoft.Compute/locations/edgeZones",
+ "Microsoft.Compute/locations/edgeZones/vmimages",
+ "Microsoft.Compute/locations/edgeZones/publishers",
+ "Microsoft.Compute/locations/galleries",
+ "Microsoft.Compute/locations/logAnalytics",
+ "Microsoft.Compute/locations/recommendations",
+ "Microsoft.Compute/locations/runCommands",
+ "Microsoft.Compute/locations/sharedGalleries",
+ "Microsoft.Compute/locations/spotEvictionRates",
+ "Microsoft.Compute/locations/spotPriceHistory",
+ "Microsoft.Compute/locations/operations",
+ "Microsoft.Compute/locations/publishers",
+ "Microsoft.Compute/locations/usages",
+ "Microsoft.Compute/locations/vmSizes",
+ "Microsoft.Compute/locations/virtualMachines",
+ "Microsoft.Compute/locations/virtualMachineScaleSets",
+ "Microsoft.Compute/operations",
+ "Microsoft.Compute/restorePointCollections/restorePoints/diskRestorePoints",
+ "Microsoft.Compute/virtualMachines",
+ "Microsoft.Compute/virtualMachines/applications",
+ "Microsoft.Compute/virtualMachines/extensions",
+ "Microsoft.Compute/virtualMachines/metricDefinitions",
+ "Microsoft.Compute/virtualMachines/runCommands",
+ "Microsoft.Compute/virtualMachineScaleSets",
+ "Microsoft.Compute/virtualMachineScaleSets/applications",
+ "Microsoft.Compute/virtualMachineScaleSets/extensions",
+ "Microsoft.Compute/virtualMachineScaleSets/networkInterfaces",
+ "Microsoft.Compute/virtualMachineScaleSets/publicIPAddresses",
+ "Microsoft.Compute/virtualMachineScaleSets/virtualMachines",
+ "Microsoft.Compute/virtualMachineScaleSets/virtualMachines/extensions",
+ "Microsoft.Compute/virtualMachineScaleSets/virtualMachines/networkInterfaces",
+ "Microsoft.Compute/restorePointCollections",
+ "Microsoft.Compute/restorePointCollections/restorePoints",
+ "Microsoft.Compute/proximityPlacementGroups",
+ "Microsoft.Compute/sshPublicKeys",
+ "Microsoft.Compute/sharedVMImages",
+ "Microsoft.Compute/sharedVMImages/versions",
+ "Microsoft.Compute/snapshots",
+ "Microsoft.ConfidentialLedger/checkNameAvailability",
+ "Microsoft.ConfidentialLedger/Ledgers",
+ "Microsoft.ConfidentialLedger/Locations",
+ "Microsoft.ConfidentialLedger/Locations/operations",
+ "Microsoft.ConfidentialLedger/Locations/operationstatuses",
+ "Microsoft.ConfidentialLedger/ManagedCCFs",
+ "Microsoft.ContainerService/managedClusters",
+ "Microsoft.ContainerService/managedClusters/agentPools",
+ "Microsoft.HardwareSecurityModules/dedicatedHSMs",
+ "Microsoft.HardwareSecurityModules/locations",
+ "Microsoft.HardwareSecurityModules/locations/operationResults",
+ "Microsoft.HardwareSecurityModules/operations",
+ "Microsoft.KeyVault/hsmPools",
+ "Microsoft.KeyVault/managedHSMs",
+ "Microsoft.KeyVault/locations/managedHsmOperationResults",
+ "Microsoft.KeyVault/checkMhsmNameAvailability",
+ "Microsoft.KeyVault/checkNameAvailability",
+ "Microsoft.KeyVault/deletedManagedHSMs",
+ "Microsoft.KeyVault/deletedVaults",
+ "Microsoft.KeyVault/locations",
+ "Microsoft.KeyVault/locations/deletedManagedHSMs",
+ "Microsoft.KeyVault/locations/deletedVaults",
+ "Microsoft.KeyVault/locations/notifyNetworkSecurityPerimeterUpdatesAvailable",
+ "Microsoft.KeyVault/locations/operationResults",
+ "Microsoft.KeyVault/managedHSMs/privateEndpointConnections",
+ "Microsoft.KeyVault/operations",
+ "Microsoft.KeyVault/vaults",
+ "Microsoft.KeyVault/vaults/accessPolicies",
+ "Microsoft.KeyVault/vaults/eventGridFilters",
+ "Microsoft.KeyVault/vaults/keys",
+ "Microsoft.KeyVault/vaults/keys/versions",
+ "Microsoft.KeyVault/vaults/privateEndpointConnections",
+ "Microsoft.KeyVault/vaults/secrets",
+ "Microsoft.Kubernetes/connectedClusters",
+ "Microsoft.Kubernetes/locations",
+ "Microsoft.Kubernetes/locations/operationStatuses",
+ "Microsoft.Kubernetes/registeredSubscriptions",
+ "Microsoft.Kubernetes/Operations",
+ "Microsoft.KubernetesConfiguration/sourceControlConfigurations",
+ "Microsoft.KubernetesConfiguration/extensions",
+ "Microsoft.KubernetesConfiguration/fluxConfigurations",
+ "Microsoft.KubernetesConfiguration/operations",
+ "Microsoft.KubernetesConfiguration/privateLinkScopes",
+ "Microsoft.KubernetesConfiguration/privateLinkScopes/privateEndpointConnections",
+ "Microsoft.KubernetesConfiguration/privateLinkScopes/privateEndpointConnectionProxies",
+ "Microsoft.ManagedIdentity/userAssignedIdentities",
+ "Microsoft.Network/ddosProtectionPlans",
+ "Microsoft.Network/loadBalancers",
+ "Microsoft.Network/networkSecurityGroups",
+ "Microsoft.Network/networkInterfaces",
+ "Microsoft.Network/privateDnsZones",
+ "Microsoft.Network/privateDnsZones/virtualNetworkLinks",
+ "Microsoft.Network/privateEndpoints",
+ "Microsoft.Network/privateEndpoints/privateDnsZoneGroups",
+ "Microsoft.Network/publicIPAddresses",
+ "Microsoft.Network/routeTables",
+ "Microsoft.Network/virtualNetworks",
+ "Microsoft.Network/virtualNetworks/subnets",
+ "Microsoft.Resources/deployments",
+ "Microsoft.Sql/locations/syncDatabaseIds",
+ "Microsoft.Sql/locations/longTermRetentionServers",
+ "Microsoft.Sql/locations/longTermRetentionBackups",
+ "Microsoft.Sql/locations/longTermRetentionPolicyOperationResults",
+ "Microsoft.Sql/locations/longTermRetentionPolicyAzureAsyncOperation",
+ "Microsoft.Sql/locations/longTermRetentionBackupOperationResults",
+ "Microsoft.Sql/locations/longTermRetentionBackupAzureAsyncOperation",
+ "Microsoft.Sql/locations/shortTermRetentionPolicyOperationResults",
+ "Microsoft.Sql/locations/shortTermRetentionPolicyAzureAsyncOperation",
+ "Microsoft.Sql/locations/managedShortTermRetentionPolicyOperationResults",
+ "Microsoft.Sql/locations/managedShortTermRetentionPolicyAzureAsyncOperation",
+ "Microsoft.Sql/locations/instanceFailoverGroups",
+ "Microsoft.Sql/locations/instanceFailoverGroupAzureAsyncOperation",
+ "Microsoft.Sql/locations/instanceFailoverGroupOperationResults",
+ "Microsoft.Sql/locations/privateEndpointConnectionProxyOperationResults",
+ "Microsoft.Sql/locations/privateEndpointConnectionProxyAzureAsyncOperation",
+ "Microsoft.Sql/locations/privateEndpointConnectionOperationResults",
+ "Microsoft.Sql/locations/outboundFirewallRulesAzureAsyncOperation",
+ "Microsoft.Sql/locations/outboundFirewallRulesOperationResults",
+ "Microsoft.Sql/locations/privateEndpointConnectionAzureAsyncOperation",
+ "Microsoft.Sql/locations/notifyAzureAsyncOperation",
+ "Microsoft.Sql/locations/serverTrustGroups",
+ "Microsoft.Sql/locations/serverTrustGroupOperationResults",
+ "Microsoft.Sql/locations/serverTrustGroupAzureAsyncOperation",
+ "Microsoft.Sql/locations/managedDatabaseMoveOperationResults",
+ "Microsoft.Sql/locations/managedDatabaseMoveAzureAsyncOperation",
+ "Microsoft.Sql/locations/connectionPoliciesAzureAsyncOperation",
+ "Microsoft.Sql/locations/connectionPoliciesOperationResults",
+ "Microsoft.Sql/locations/notifyNetworkSecurityPerimeterUpdatesAvailable",
+ "Microsoft.Sql/locations/replicationLinksAzureAsyncOperation",
+ "Microsoft.Sql/locations/replicationLinksOperationResults",
+ "Microsoft.Sql/locations/managedInstanceDtcAzureAsyncOperation",
+ "Microsoft.Sql/servers",
+ "Microsoft.Sql/servers/advancedThreatProtectionSettings",
+ "Microsoft.Sql/servers/advisors",
+ "Microsoft.Sql/servers/auditingPolicies",
+ "Microsoft.Sql/servers/auditingSettings",
+ "Microsoft.Sql/servers/connectionPolicies",
+ "Microsoft.Sql/servers/databases",
+ "Microsoft.Sql/servers/databases/advisors",
+ "Microsoft.Sql/servers/databases/advancedThreatProtectionSettings",
+ "Microsoft.Sql/servers/databases/auditingPolicies",
+ "Microsoft.Sql/servers/databases/auditingSettings",
+ "Microsoft.Sql/servers/databases/backupLongTermRetentionPolicies",
+ "Microsoft.Sql/servers/databases/extendedAuditingSettings",
+ "Microsoft.Sql/servers/databases/geoBackupPolicies",
+ "Microsoft.Sql/servers/databases/ledgerDigestUploads",
+ "Microsoft.Sql/servers/databases/securityAlertPolicies",
+ "Microsoft.Sql/servers/databases/transparentDataEncryption",
+ "Microsoft.Sql/servers/databases/transparentDataEncryption",
+ "Microsoft.Sql/servers/databases/vulnerabilityAssessments",
+ "Microsoft.Sql/servers/devOpsAuditingSettings",
+ "Microsoft.Sql/servers/databases/advancedThreatProtectionSettings",
+ "Microsoft.Sql/servers/encryptionProtector",
+ "Microsoft.Sql/servers/extendedAuditingSettings",
+ "Microsoft.Sql/servers/firewallRules",
+ "Microsoft.Sql/servers/keys",
+ "Microsoft.Sql/servers/securityAlertPolicies",
+ "Microsoft.Sql/servers/sqlVulnerabilityAssessments",
+ "Microsoft.Sql/servers/vulnerabilityAssessments"
+ ]
+ },
+ "Virtual Machine SKUs": {
+ "value": [
+ "Standard_DC1s_v2",
+ "Standard_DC2s_v2",
+ "Standard_DC4s_v2",
+ "Standard_DC8_v2",
+ "Standard_DC1s_v3",
+ "Standard_DC2s_v3",
+ "Standard_DC4s_v3",
+ "Standard_DC8s_v3",
+ "Standard_DC16s_v3",
+ "Standard_DC24s_v3",
+ "Standard_DC32s_v3",
+ "Standard_DC48s_v3",
+ "Standard_DC1ds_v3",
+ "Standard_DC2ds_v3",
+ "Standard_DC4ds_v3",
+ "Standard_DC8ds_v3",
+ "Standard_DC16ds_v3",
+ "Standard_DC24ds_v3",
+ "Standard_DC32ds_v3",
+ "Standard_DC48ds_v3",
+ "Standard_DC2ads_v5",
+ "Standard_DC2as_v5",
+ "Standard_DC4ads_v5",
+ "Standard_DC4as_v5",
+ "Standard_DC8ads_v5",
+ "Standard_DC8as_v5",
+ "Standard_DC16ads_v5",
+ "Standard_DC16as_v5",
+ "Standard_DC32ads_v5",
+ "Standard_DC32as_v5",
+ "Standard_DC48ads_v5",
+ "Standard_DC48as_v5",
+ "Standard_DC64ads_v5",
+ "Standard_DC64as_v5",
+ "Standard_DC96ads_v5",
+ "Standard_DC96as_v5",
+ "Standard_EC2ads_v5",
+ "Standard_EC2as_v5",
+ "Standard_EC4ads_v5",
+ "Standard_EC4as_v5",
+ "Standard_EC8ads_v5",
+ "Standard_EC8as_v5",
+ "Standard_EC16ads_v5",
+ "Standard_EC16as_v5",
+ "Standard_EC20ads_v5",
+ "Standard_EC20as_v5",
+ "Standard_EC32ads_v5",
+ "Standard_EC32as_v5",
+ "Standard_EC48ads_v5",
+ "Standard_EC48as_v5",
+ "Standard_EC64ads_v5",
+ "Standard_EC64as_v5",
+ "Standard_EC96ads_v5",
+ "Standard_EC96as_v5",
+ "Standard_EC96iads_v5",
+ "Standard_EC96ias_v5"
+ ]
+ }
+ },
+ "policyDefinitionId": "${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policySetDefinitions/SlzConfidentialPolicies",
+ "scope": null,
+ "enforcementMode": "Default"
+ },
+ "location": null,
+ "identity": {
+ "type": "SystemAssigned"
+ }
+}
diff --git a/modules/compliance/policyAssignments/policy_assignment_deploy_slz_connectivity_defaults.tmpl.json b/modules/compliance/policyAssignments/policy_assignment_deploy_slz_connectivity_defaults.tmpl.json
new file mode 100644
index 00000000..b06743c1
--- /dev/null
+++ b/modules/compliance/policyAssignments/policy_assignment_deploy_slz_connectivity_defaults.tmpl.json
@@ -0,0 +1,18 @@
+{
+ "name": "Deploy-SLZ-Connectivity",
+ "type": "Microsoft.Authorization/policyAssignments",
+ "apiVersion": "2019-09-01",
+ "properties": {
+ "description": "SLZ Connectivity Policies",
+ "displayName": "SLZ Connectivity Policies",
+ "notScopes": [],
+ "parameters": {},
+ "policyDefinitionId": "${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policySetDefinitions/SlzConnectivityPolicies",
+ "scope": null,
+ "enforcementMode": "Default"
+ },
+ "location": null,
+ "identity": {
+ "type": "SystemAssigned"
+ }
+}
diff --git a/modules/compliance/policyAssignments/policy_assignment_deploy_slz_corp_defaults.tmpl.json b/modules/compliance/policyAssignments/policy_assignment_deploy_slz_corp_defaults.tmpl.json
new file mode 100644
index 00000000..d200a167
--- /dev/null
+++ b/modules/compliance/policyAssignments/policy_assignment_deploy_slz_corp_defaults.tmpl.json
@@ -0,0 +1,18 @@
+{
+ "name": "Deploy-SLZ-Corp",
+ "type": "Microsoft.Authorization/policyAssignments",
+ "apiVersion": "2019-09-01",
+ "properties": {
+ "description": "SLZ Corp Policies",
+ "displayName": "SLZ Corp Policies",
+ "notScopes": [],
+ "parameters": {},
+ "policyDefinitionId": "${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policySetDefinitions/SlzCorpPolicies",
+ "scope": null,
+ "enforcementMode": "Default"
+ },
+ "location": null,
+ "identity": {
+ "type": "SystemAssigned"
+ }
+}
diff --git a/modules/compliance/policyAssignments/policy_assignment_deploy_slz_decommissioned_defaults.tmpl.json b/modules/compliance/policyAssignments/policy_assignment_deploy_slz_decommissioned_defaults.tmpl.json
new file mode 100644
index 00000000..eaddbff0
--- /dev/null
+++ b/modules/compliance/policyAssignments/policy_assignment_deploy_slz_decommissioned_defaults.tmpl.json
@@ -0,0 +1,18 @@
+{
+ "name": "Deploy-SLZ-Decom-Deployment",
+ "type": "Microsoft.Authorization/policyAssignments",
+ "apiVersion": "2019-09-01",
+ "properties": {
+ "description": "SLZ Decommissioned Policies",
+ "displayName": "SLZ Decommissioned Policies",
+ "notScopes": [],
+ "parameters": {},
+ "policyDefinitionId": "${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policySetDefinitions/SlzDecommissionedPolicies",
+ "scope": null,
+ "enforcementMode": "Default"
+ },
+ "location": null,
+ "identity": {
+ "type": "SystemAssigned"
+ }
+}
diff --git a/modules/compliance/policyAssignments/policy_assignment_deploy_slz_identity_defaults.tmpl.json b/modules/compliance/policyAssignments/policy_assignment_deploy_slz_identity_defaults.tmpl.json
new file mode 100644
index 00000000..ecac01bc
--- /dev/null
+++ b/modules/compliance/policyAssignments/policy_assignment_deploy_slz_identity_defaults.tmpl.json
@@ -0,0 +1,18 @@
+{
+ "name": "Deploy-SLZ-Identity",
+ "type": "Microsoft.Authorization/policyAssignments",
+ "apiVersion": "2019-09-01",
+ "properties": {
+ "description": "SLZ Identity Policies",
+ "displayName": "SLZ Identity Policies",
+ "notScopes": [],
+ "parameters": {},
+ "policyDefinitionId": "${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policySetDefinitions/SlzIdentityPolicies",
+ "scope": null,
+ "enforcementMode": "Default"
+ },
+ "location": null,
+ "identity": {
+ "type": "SystemAssigned"
+ }
+}
diff --git a/modules/compliance/policyAssignments/policy_assignment_deploy_slz_landing_zones_defaults.tmpl.json b/modules/compliance/policyAssignments/policy_assignment_deploy_slz_landing_zones_defaults.tmpl.json
new file mode 100644
index 00000000..a0d56c36
--- /dev/null
+++ b/modules/compliance/policyAssignments/policy_assignment_deploy_slz_landing_zones_defaults.tmpl.json
@@ -0,0 +1,18 @@
+{
+ "name": "Deploy-SLZ-LZs",
+ "type": "Microsoft.Authorization/policyAssignments",
+ "apiVersion": "2019-09-01",
+ "properties": {
+ "description": "SLZ Landing Zones Policies",
+ "displayName": "SLZ Landing Zones Policies",
+ "notScopes": [],
+ "parameters": {},
+ "policyDefinitionId": "${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policySetDefinitions/SlzLandingZonesPolicies",
+ "scope": null,
+ "enforcementMode": "Default"
+ },
+ "location": null,
+ "identity": {
+ "type": "SystemAssigned"
+ }
+}
diff --git a/modules/compliance/policyAssignments/policy_assignment_deploy_slz_management_defaults.tmpl.json b/modules/compliance/policyAssignments/policy_assignment_deploy_slz_management_defaults.tmpl.json
new file mode 100644
index 00000000..d96fb3f7
--- /dev/null
+++ b/modules/compliance/policyAssignments/policy_assignment_deploy_slz_management_defaults.tmpl.json
@@ -0,0 +1,18 @@
+{
+ "name": "Deploy-SLZ-Management",
+ "type": "Microsoft.Authorization/policyAssignments",
+ "apiVersion": "2019-09-01",
+ "properties": {
+ "description": "SLZ Management Policies",
+ "displayName": "SLZ Management Policies",
+ "notScopes": [],
+ "parameters": {},
+ "policyDefinitionId": "${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policySetDefinitions/SlzManagementPolicies",
+ "scope": null,
+ "enforcementMode": "Default"
+ },
+ "location": null,
+ "identity": {
+ "type": "SystemAssigned"
+ }
+}
diff --git a/modules/compliance/policyAssignments/policy_assignment_deploy_slz_online_defaults.tmpl.json b/modules/compliance/policyAssignments/policy_assignment_deploy_slz_online_defaults.tmpl.json
new file mode 100644
index 00000000..a6a607e6
--- /dev/null
+++ b/modules/compliance/policyAssignments/policy_assignment_deploy_slz_online_defaults.tmpl.json
@@ -0,0 +1,18 @@
+{
+ "name": "Deploy-SLZ-Online",
+ "type": "Microsoft.Authorization/policyAssignments",
+ "apiVersion": "2019-09-01",
+ "properties": {
+ "description": "SLZ Online Policies",
+ "displayName": "SLZ Online Policies",
+ "notScopes": [],
+ "parameters": {},
+ "policyDefinitionId": "${varTargetManagementGroupResourceId}uthorization/policySetDefinitions/SlzGlobalPolicies",
+ "scope": null,
+ "enforcementMode": "Default"
+ },
+ "location": null,
+ "identity": {
+ "type": "SystemAssigned"
+ }
+}
diff --git a/modules/compliance/policyAssignments/policy_assignment_deploy_slz_platform_defaults.tmpl.json b/modules/compliance/policyAssignments/policy_assignment_deploy_slz_platform_defaults.tmpl.json
new file mode 100644
index 00000000..e8da5693
--- /dev/null
+++ b/modules/compliance/policyAssignments/policy_assignment_deploy_slz_platform_defaults.tmpl.json
@@ -0,0 +1,18 @@
+{
+ "name": "Deploy-SLZ-Plat",
+ "type": "Microsoft.Authorization/policyAssignments",
+ "apiVersion": "2019-09-01",
+ "properties": {
+ "description": "SLZ Platform Policies",
+ "displayName": "SLZ Platform Policies",
+ "notScopes": [],
+ "parameters": {},
+ "policyDefinitionId": "${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policySetDefinitions/SlzPlatformPolicies",
+ "scope": null,
+ "enforcementMode": "Default"
+ },
+ "location": null,
+ "identity": {
+ "type": "SystemAssigned"
+ }
+}
diff --git a/modules/compliance/policyAssignments/policy_assignment_deploy_slz_sandbox_defaults.tmpl.json b/modules/compliance/policyAssignments/policy_assignment_deploy_slz_sandbox_defaults.tmpl.json
new file mode 100644
index 00000000..2321d3fa
--- /dev/null
+++ b/modules/compliance/policyAssignments/policy_assignment_deploy_slz_sandbox_defaults.tmpl.json
@@ -0,0 +1,18 @@
+{
+ "name": "Deploy-SLZ-Sand",
+ "type": "Microsoft.Authorization/policyAssignments",
+ "apiVersion": "2019-09-01",
+ "properties": {
+ "description": "SLZ Sandbox Policies",
+ "displayName": "SLZ Sandbox Policies",
+ "notScopes": [],
+ "parameters": {},
+ "policyDefinitionId": "${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policySetDefinitions/SlzSandboxPolicies",
+ "scope": null,
+ "enforcementMode": "Default"
+ },
+ "location": null,
+ "identity": {
+ "type": "SystemAssigned"
+ }
+}
diff --git a/modules/compliance/policyAssignments/policy_assignmnet_deploy_slz_global_defaults.tmpl.json b/modules/compliance/policyAssignments/policy_assignmnet_deploy_slz_global_defaults.tmpl.json
new file mode 100644
index 00000000..af6c1861
--- /dev/null
+++ b/modules/compliance/policyAssignments/policy_assignmnet_deploy_slz_global_defaults.tmpl.json
@@ -0,0 +1,22 @@
+{
+ "name": "Deploy-SLZ-Root",
+ "type": "Microsoft.Authorization/policyAssignments",
+ "apiVersion": "2019-09-01",
+ "properties": {
+ "description": "SLZ Global Policies",
+ "displayName": "SLZ Global Policies",
+ "notScopes": [],
+ "parameters": {
+ "listOfAllowedLocations": {
+ "value": []
+ }
+ },
+ "policyDefinitionId": "${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policySetDefinitions/SlzGlobalPolicies",
+ "scope": null,
+ "enforcementMode": "Default"
+ },
+ "location": null,
+ "identity": {
+ "type": "SystemAssigned"
+ }
+}
diff --git a/modules/compliance/policyExemptions.bicep b/modules/compliance/policyExemptions.bicep
new file mode 100644
index 00000000..59860f0c
--- /dev/null
+++ b/modules/compliance/policyExemptions.bicep
@@ -0,0 +1,55 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+/*
+ SUMMARY : Creates a Policy Exemption for a Policy Assignment in a Management Group
+ AUTHOR/S: Cloud for Sovereignty
+*/
+targetScope = 'managementGroup'
+
+@description('Policy Assignment Name')
+param parPolicyAssignmentName string
+
+@description('Policy Assignment Scope Name')
+param parPolicyAssignmentScopeName string
+
+@description('SLZ Policy Set Assignment id')
+param parPolicyAssignmentId string = '/providers/microsoft.management/managementgroups/${parPolicyAssignmentScopeName}/providers/microsoft.authorization/policyassignments/${parPolicyAssignmentName}'
+
+@allowed([
+ 'Waiver'
+ 'Mitigated'
+])
+@description('Exemption Category Default - Waiver')
+param parExemptionCategory string = 'Waiver'
+
+@description('Description')
+param parDescription string
+
+@allowed([
+ 'Default'
+ 'DoNotValidate'
+])
+@description('Assignment Scope')
+param parAssignmentScopeValidation string = 'Default'
+
+@description('Reference ids of Policies to be exempted')
+param parPolicyDefinitionReferenceIds array
+
+@description('Exemption Name')
+param parExemptionName string
+
+@description('Exemption Display Name')
+param parExemptionDisplayName string
+
+// Create Policy Exemption
+resource resPolicyExemption 'Microsoft.Authorization/policyExemptions@2022-07-01-preview' = {
+ name: parExemptionName
+ properties: {
+ assignmentScopeValidation: parAssignmentScopeValidation
+ description: parDescription
+ displayName: parExemptionDisplayName
+ exemptionCategory: parExemptionCategory
+ policyAssignmentId: parPolicyAssignmentId
+ policyDefinitionReferenceIds: parPolicyDefinitionReferenceIds
+ }
+}
diff --git a/modules/compliance/policyRemediation.bicep b/modules/compliance/policyRemediation.bicep
new file mode 100644
index 00000000..bfcd8c9b
--- /dev/null
+++ b/modules/compliance/policyRemediation.bicep
@@ -0,0 +1,42 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+/*
+ SUMMARY : Creates a Policy Remediation for a Policy Set Assignment or a Policy Assignment in a Management Group
+ AUTHOR/S: Cloud for Sovereignty
+*/
+targetScope = 'managementGroup'
+
+@description('Exemption Name')
+param parPolicyRemediationName string
+
+@description('Policy Set Assignment id')
+param parPolicyAssignmentId string
+
+@description('Reference ids of Policy to be remediated')
+param parPolicyDefinitionReferenceId string
+
+@allowed([
+ 'ExistingNonCompliant'
+ 'ReEvaluateCompliance'
+])
+@description('Remediation Discovery Mode - ExistingNonCompliant')
+param parResourceDiscoveryMode string = 'ExistingNonCompliant'
+
+// Policy Remediation for Policy Set Assignment
+resource resPolicySetRemediation 'Microsoft.PolicyInsights/remediations@2021-10-01' = if (parPolicyDefinitionReferenceId != null) {
+ name: take('${parPolicyRemediationName}-${parPolicyDefinitionReferenceId}', 64)
+ properties: {
+ policyAssignmentId: parPolicyAssignmentId
+ policyDefinitionReferenceId: parPolicyDefinitionReferenceId
+ resourceDiscoveryMode: parResourceDiscoveryMode
+ }
+}
+
+// Policy Remediation for Policy Assignment
+resource resPolicyRemediation 'Microsoft.PolicyInsights/remediations@2021-10-01' = if (parPolicyDefinitionReferenceId == null) {
+ name: parPolicyRemediationName
+ properties: {
+ policyAssignmentId: parPolicyAssignmentId
+ resourceDiscoveryMode: parResourceDiscoveryMode
+ }
+}
diff --git a/modules/compliance/policySetDefinitions/slzConfidentialDefaults.json b/modules/compliance/policySetDefinitions/slzConfidentialDefaults.json
new file mode 100644
index 00000000..8c9c51e9
--- /dev/null
+++ b/modules/compliance/policySetDefinitions/slzConfidentialDefaults.json
@@ -0,0 +1,309 @@
+{
+ "properties": {
+ "displayName": "SLZ Confidential Policies",
+ "policyType": "Custom",
+ "description": "Policies to enforce confidential computing",
+ "metadata": {
+ "category": "Regulatory Compliance",
+ "version": "0.3.0"
+ },
+ "parameters": {
+ "effect": {
+ "type": "string",
+ "metadata": {
+ "displayName": "Effect",
+ "description": "Execution of the policy"
+ },
+ "allowedValues": ["Audit", "Deny", "Disabled", "AuditIfNotExists"],
+ "defaultValue": "Deny"
+ },
+ "listOfAllowedLocations": {
+ "type": "array",
+ "defaultValue": [],
+ "allowedValues": [
+ "asia",
+ "asiapacific",
+ "australia",
+ "australiacentral",
+ "australiacentral2",
+ "australiaeast",
+ "australiasoutheast",
+ "brazil",
+ "brazilsouth",
+ "brazilsoutheast",
+ "canada",
+ "canadacentral",
+ "canadaeast",
+ "centralindia",
+ "centralus",
+ "centraluseuap",
+ "centralusstage",
+ "eastasia",
+ "eastasiastage",
+ "eastus",
+ "eastus2",
+ "eastus2euap",
+ "eastus2stage",
+ "eastusstage",
+ "eastusstg",
+ "europe",
+ "france",
+ "francecentral",
+ "francesouth",
+ "germany",
+ "germanynorth",
+ "germanywestcentral",
+ "global",
+ "india",
+ "japan",
+ "japaneast",
+ "japanwest",
+ "jioindiacentral",
+ "jioindiawest",
+ "korea",
+ "koreacentral",
+ "koreasouth",
+ "northcentralus",
+ "northcentralusstage",
+ "northeurope",
+ "norway",
+ "norwayeast",
+ "norwaywest",
+ "qatarcentral",
+ "singapore",
+ "southafrica",
+ "southafricanorth",
+ "southafricawest",
+ "southcentralus",
+ "southcentralusstage",
+ "southcentralusstg",
+ "southeastasia",
+ "southeastasiastage",
+ "southindia",
+ "swedencentral",
+ "switzerland",
+ "switzerlandnorth",
+ "switzerlandwest",
+ "uae",
+ "uaecentral",
+ "uaenorth",
+ "uk",
+ "uksouth",
+ "ukwest",
+ "unitedstates",
+ "unitedstateseuap",
+ "westcentralus",
+ "westeurope",
+ "westindia",
+ "westus",
+ "westus2",
+ "westus2stage",
+ "westus3",
+ "westusstage"
+ ],
+ "metadata": {
+ "displayName": "Allowed locations",
+ "description": "The list of locations that can be specified when deploying resources",
+ "strongType": "location"
+ }
+ },
+ "Resource Types": {
+ "type": "array",
+ "metadata": {
+ "displayName": "Resource Types",
+ "description": null,
+ "strongType": "resourceTypes"
+ },
+ "defaultValue": []
+ },
+ "Virtual Machine SKUs": {
+ "type": "array",
+ "metadata": {
+ "displayName": "Virtual Machine SKUs",
+ "strongType": "vmSKUs"
+ },
+ "defaultValue": []
+ }
+ },
+ "policyDefinitions": [
+ {
+ "policyDefinitionReferenceId": "AllowedLocationsForResourceGroups",
+ "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/e765b5de-1225-4ba3-bd56-1ac6695af988",
+ "parameters": {
+ "listOfAllowedLocations": {
+ "value": "[[parameters('listOfAllowedLocations')]"
+ }
+ },
+ "groupNames": ["dashboard-Data Residency"]
+ },
+ {
+ "policyDefinitionReferenceId": "AllowedLocations",
+ "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/e56962a6-4747-49cd-b67b-bf8b01975c4c",
+ "parameters": {
+ "listOfAllowedLocations": {
+ "value": "[[parameters('listOfAllowedLocations')]"
+ }
+ },
+ "groupNames": ["dashboard-Data Residency"]
+ },
+ {
+ "policyDefinitionReferenceId": "Azure Cosmos DB allowed locations_1",
+ "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/0473574d-2d43-4217-aefe-941fcdf7e684",
+ "parameters": {
+ "listOfAllowedLocations": {
+ "value": "[[parameters('listOfAllowedLocations')]"
+ }
+ },
+ "groupNames": ["dashboard-Data Residency"]
+ },
+ {
+ "policyDefinitionReferenceId": "[Preview]: Azure Recovery Services vaults should use customer-managed keys for encrypting backup dat_1",
+ "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/2e94d99a-8a36-4563-bc77-810d8893b671",
+ "parameters": {
+ "effect": {
+ "value": "[[parameters('effect')]"
+ }
+ },
+ "groupNames": ["dashboard-Key Management"]
+ },
+ {
+ "policyDefinitionReferenceId": "Managed disks should be double encrypted with both platform-managed and customer-managed keys_1",
+ "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/ca91455f-eace-4f96-be59-e6e2c35b4816",
+ "parameters": {
+ "effect": {
+ "value": "[[parameters('effect')]"
+ }
+ },
+ "groupNames": ["dashboard-Key Management"]
+ },
+ {
+ "policyDefinitionReferenceId": "Both operating systems and data disks in Azure Kubernetes Service clusters should be encrypted by cu_1",
+ "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/7d7be79c-23ba-4033-84dd-45e2a5ccdd67",
+ "parameters": {
+ "effect": {
+ "value": "[[parameters('effect')]"
+ }
+ },
+ "groupNames": ["dashboard-Key Management"]
+ },
+ {
+ "policyDefinitionReferenceId": "SQL servers should use customer-managed keys to encrypt data at rest_1",
+ "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/0a370ff3-6cab-4e85-8995-295fd854c5b8",
+ "parameters": {
+ "effect": {
+ "value": "[[parameters('effect')]"
+ }
+ },
+ "groupNames": ["dashboard-Key Management"]
+ },
+ {
+ "policyDefinitionReferenceId": "PostgreSQL servers should use customer-managed keys to encrypt data at rest_1",
+ "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/18adea5e-f416-4d0f-8aa8-d24321e3e274",
+ "parameters": {},
+ "groupNames": ["dashboard-Key Management"]
+ },
+ {
+ "policyDefinitionReferenceId": "MySQL servers should use customer-managed keys to encrypt data at rest_1",
+ "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/83cef61d-dbd1-4b20-a4fc-5fbc7da10833",
+ "parameters": {},
+ "groupNames": ["dashboard-Key Management"]
+ },
+ {
+ "policyDefinitionReferenceId": "SQL managed instances should use customer-managed keys to encrypt data at rest_1",
+ "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/ac01ad65-10e5-46df-bdd9-6b0cad13e1d2",
+ "parameters": {
+ "effect": {
+ "value": "[[parameters('effect')]"
+ }
+ },
+ "groupNames": ["dashboard-Key Management"]
+ },
+ {
+ "policyDefinitionReferenceId": "Storage accounts should use customer-managed key for encryption_1",
+ "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/6fac406b-40ca-413b-bf8e-0bf964659c25",
+ "parameters": {},
+ "groupNames": ["dashboard-Key Management"]
+ },
+ {
+ "policyDefinitionReferenceId": "Table Storage should use customer-managed key for encryption_1",
+ "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/7c322315-e26d-4174-a99e-f49d351b4688",
+ "parameters": {
+ "effect": {
+ "value": "[[parameters('effect')]"
+ }
+ },
+ "groupNames": ["dashboard-Key Management"]
+ },
+ {
+ "policyDefinitionReferenceId": "HPC Cache accounts should use customer-managed key for encryption_1",
+ "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/970f84d8-71b6-4091-9979-ace7e3fb6dbb",
+ "parameters": {
+ "effect": {
+ "value": "[[parameters('effect')]"
+ }
+ },
+ "groupNames": ["dashboard-Key Management"]
+ },
+ {
+ "policyDefinitionReferenceId": "Storage account encryption scopes should use customer-managed keys to encrypt data at rest_1",
+ "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/b5ec538c-daa0-4006-8596-35468b9148e8",
+ "parameters": {
+ "effect": {
+ "value": "[[parameters('effect')]"
+ }
+ },
+ "groupNames": ["dashboard-Key Management"]
+ },
+ {
+ "policyDefinitionReferenceId": "Queue Storage should use customer-managed key for encryption_1",
+ "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/f0e5abd0-2554-4736-b7c0-4ffef23475ef",
+ "parameters": {
+ "effect": {
+ "value": "[[parameters('effect')]"
+ }
+ },
+ "groupNames": ["dashboard-Key Management"]
+ },
+ {
+ "policyDefinitionReferenceId": "Allowed resource types",
+ "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/a08ec900-254a-4555-9bf5-e42af04b5c5c",
+ "parameters": {
+ "listOfResourceTypesAllowed": {
+ "value": "[[parameters('Resource Types')]"
+ }
+ },
+ "groupNames": ["dashboard-Confidential Computing"]
+ },
+ {
+ "policyDefinitionReferenceId": "Allowed virtual machine size SKUs",
+ "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/cccc23c7-8427-4f53-ad12-b6a63eb452b3",
+ "parameters": {
+ "listOfAllowedSKUs": {
+ "value": "[[parameters('Virtual Machine SKUs')]"
+ }
+ },
+ "groupNames": ["dashboard-Confidential Computing"]
+ }
+ ],
+ "policyDefinitionGroups": [
+ {
+ "name": "dashboard-Data Residency",
+ "category": "Residency",
+ "description": "Control where regional Azure resources are deployed and used"
+ },
+ {
+ "name": "dashboard-Key Management",
+ "category": "Encryption",
+ "description": "Customer should have control of keys used for encryption and decryption while also using best practices for key strength and security."
+ },
+ {
+ "name": "dashboard-Confidential Computing",
+ "category": "Encryption",
+ "description": "Confidential workloads should be protected from unauthorized access while data is in use."
+ }
+ ]
+ },
+ "id": "${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policySetDefinitions/SlzConfidentialPolicies",
+ "type": "Microsoft.Authorization/policySetDefinitions",
+ "name": "SlzConfidentialPolicies"
+}
diff --git a/modules/compliance/policySetDefinitions/slzConnectivityDefaults.json b/modules/compliance/policySetDefinitions/slzConnectivityDefaults.json
new file mode 100644
index 00000000..0910980b
--- /dev/null
+++ b/modules/compliance/policySetDefinitions/slzConnectivityDefaults.json
@@ -0,0 +1,17 @@
+{
+ "properties": {
+ "displayName": "SLZ Connectivity Policies",
+ "description": "SLZ Connectivity Policies",
+ "policyType": "Custom",
+ "metadata": {
+ "category": "Regulatory Compliance",
+ "version": "0.3.0"
+ },
+ "parameters": {},
+ "policyDefinitions": [],
+ "policyDefinitionGroups": []
+ },
+ "id": "${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policySetDefinitions/SlzConnectivityPolicies",
+ "type": "Microsoft.Authorization/policySetDefinitions",
+ "name": "SlzConnectivityPolicies"
+}
diff --git a/modules/compliance/policySetDefinitions/slzCorpDefaults.json b/modules/compliance/policySetDefinitions/slzCorpDefaults.json
new file mode 100644
index 00000000..f5182c64
--- /dev/null
+++ b/modules/compliance/policySetDefinitions/slzCorpDefaults.json
@@ -0,0 +1,17 @@
+{
+ "properties": {
+ "displayName": "SLZ Corp Policies",
+ "description": "SLZ Corp Policies",
+ "policyType": "Custom",
+ "metadata": {
+ "category": "Regulatory Compliance",
+ "version": "0.3.0"
+ },
+ "parameters": {},
+ "policyDefinitions": [],
+ "policyDefinitionGroups": []
+ },
+ "id": "${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policySetDefinitions/SlzCorpPolicies",
+ "type": "Microsoft.Authorization/policySetDefinitions",
+ "name": "SlzCorpPolicies"
+}
diff --git a/modules/compliance/policySetDefinitions/slzDecommissionedDefaults.json b/modules/compliance/policySetDefinitions/slzDecommissionedDefaults.json
new file mode 100644
index 00000000..d267f6f5
--- /dev/null
+++ b/modules/compliance/policySetDefinitions/slzDecommissionedDefaults.json
@@ -0,0 +1,17 @@
+{
+ "properties": {
+ "displayName": "SLZ Decommissioned Policies",
+ "description": "SLZ Decommissioned Policies",
+ "policyType": "Custom",
+ "metadata": {
+ "category": "Regulatory Compliance",
+ "version": "0.3.0"
+ },
+ "parameters": {},
+ "policyDefinitions": [],
+ "policyDefinitionGroups": []
+ },
+ "id": "${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policySetDefinitions/SlzDecommissionedPolicies",
+ "type": "Microsoft.Authorization/policySetDefinitions",
+ "name": "SlzDecommissionedPolicies"
+}
diff --git a/modules/compliance/policySetDefinitions/slzGlobalDefaults.json b/modules/compliance/policySetDefinitions/slzGlobalDefaults.json
new file mode 100644
index 00000000..302537fd
--- /dev/null
+++ b/modules/compliance/policySetDefinitions/slzGlobalDefaults.json
@@ -0,0 +1,151 @@
+{
+ "properties": {
+ "displayName": "SLZ Global Policies",
+ "policyType": "Custom",
+ "description": "Default Sovereign Landing Zone (SLZ) policies",
+ "metadata": {
+ "category": "Regulatory Compliance",
+ "version": "0.3.0"
+ },
+ "parameters": {
+ "listOfAllowedLocations": {
+ "type": "array",
+ "defaultValue": [],
+ "allowedValues": [
+ "asia",
+ "asiapacific",
+ "australia",
+ "australiacentral",
+ "australiacentral2",
+ "australiaeast",
+ "australiasoutheast",
+ "brazil",
+ "brazilsouth",
+ "brazilsoutheast",
+ "canada",
+ "canadacentral",
+ "canadaeast",
+ "centralindia",
+ "centralus",
+ "centraluseuap",
+ "centralusstage",
+ "eastasia",
+ "eastasiastage",
+ "eastus",
+ "eastus2",
+ "eastus2euap",
+ "eastus2stage",
+ "eastusstage",
+ "eastusstg",
+ "europe",
+ "france",
+ "francecentral",
+ "francesouth",
+ "germany",
+ "germanynorth",
+ "germanywestcentral",
+ "global",
+ "india",
+ "japan",
+ "japaneast",
+ "japanwest",
+ "jioindiacentral",
+ "jioindiawest",
+ "korea",
+ "koreacentral",
+ "koreasouth",
+ "northcentralus",
+ "northcentralusstage",
+ "northeurope",
+ "norway",
+ "norwayeast",
+ "norwaywest",
+ "qatarcentral",
+ "singapore",
+ "southafrica",
+ "southafricanorth",
+ "southafricawest",
+ "southcentralus",
+ "southcentralusstage",
+ "southcentralusstg",
+ "southeastasia",
+ "southeastasiastage",
+ "southindia",
+ "swedencentral",
+ "switzerland",
+ "switzerlandnorth",
+ "switzerlandwest",
+ "uae",
+ "uaecentral",
+ "uaenorth",
+ "uk",
+ "uksouth",
+ "ukwest",
+ "unitedstates",
+ "unitedstateseuap",
+ "westcentralus",
+ "westeurope",
+ "westindia",
+ "westus",
+ "westus2",
+ "westus2stage",
+ "westus3",
+ "westusstage"
+ ],
+ "metadata": {
+ "displayName": "Allowed locations",
+ "description": "The list of locations that can be specified when deploying resources",
+ "strongType": "location"
+ }
+ }
+ },
+ "policyDefinitionGroups": [
+ {
+ "name": "dashboard-Data Residency",
+ "category": "Residency",
+ "description": "Control where regional Azure resources are deployed and used"
+ }
+ ],
+ "policyDefinitions": [
+ {
+ "policyDefinitionReferenceId": "AllowedLocationsForResourceGroups",
+ "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/e765b5de-1225-4ba3-bd56-1ac6695af988",
+ "parameters": {
+ "listOfAllowedLocations": {
+ "value": "[[parameters('listOfAllowedLocations')]"
+ }
+ },
+ "groupNames": [
+ "dashboard-Data Residency"
+ ]
+ },
+ {
+ "policyDefinitionReferenceId": "AllowedLocations",
+ "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/e56962a6-4747-49cd-b67b-bf8b01975c4c",
+ "parameters": {
+ "listOfAllowedLocations": {
+ "value": "[[parameters('listOfAllowedLocations')]"
+ }
+ },
+ "groupNames": [
+ "dashboard-Data Residency"
+ ]
+ },
+ {
+ "policyDefinitionReferenceId": "Azure Cosmos DB allowed locations_1",
+ "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/0473574d-2d43-4217-aefe-941fcdf7e684",
+ "parameters": {
+ "listOfAllowedLocations": {
+ "value": "[[parameters('listOfAllowedLocations')]"
+ }
+ },
+ "groupNames": [
+ "dashboard-Data Residency"
+ ]
+ }
+ ]
+ },
+ "id": "${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policySetDefinitions/SlzGlobalPolicies",
+ "type": "Microsoft.Authorization/policySetDefinitions",
+ "name": "SlzGlobalPolicies"
+}
diff --git a/modules/compliance/policySetDefinitions/slzIdentityDefaults.json b/modules/compliance/policySetDefinitions/slzIdentityDefaults.json
new file mode 100644
index 00000000..c12d1690
--- /dev/null
+++ b/modules/compliance/policySetDefinitions/slzIdentityDefaults.json
@@ -0,0 +1,17 @@
+{
+ "properties": {
+ "displayName": "SLZ Identity Policies",
+ "description": "SLZ Identity Policies",
+ "policyType": "Custom",
+ "metadata": {
+ "category": "Regulatory Compliance",
+ "version": "0.3.0"
+ },
+ "parameters": {},
+ "policyDefinitions": [],
+ "policyDefinitionGroups": []
+ },
+ "id": "${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policySetDefinitions/SlzIdentityPolicies",
+ "type": "Microsoft.Authorization/policySetDefinitions",
+ "name": "SlzIdentityPolicies"
+}
diff --git a/modules/compliance/policySetDefinitions/slzLandingZoneDefaults.json b/modules/compliance/policySetDefinitions/slzLandingZoneDefaults.json
new file mode 100644
index 00000000..f4397eb8
--- /dev/null
+++ b/modules/compliance/policySetDefinitions/slzLandingZoneDefaults.json
@@ -0,0 +1,17 @@
+{
+ "properties": {
+ "displayName": "SLZ Landing Zone Policies",
+ "description": "SLZ Landing Zone Policies",
+ "policyType": "Custom",
+ "metadata": {
+ "category": "Regulatory Compliance",
+ "version": "0.3.0"
+ },
+ "parameters": {},
+ "policyDefinitions": [],
+ "policyDefinitionGroups": []
+ },
+ "id": "${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policySetDefinitions/SlzLandingZonesPolicies",
+ "type": "Microsoft.Authorization/policySetDefinitions",
+ "name": "SlzLandingZonesPolicies"
+}
diff --git a/modules/compliance/policySetDefinitions/slzManagementDefaults.json b/modules/compliance/policySetDefinitions/slzManagementDefaults.json
new file mode 100644
index 00000000..ed217d81
--- /dev/null
+++ b/modules/compliance/policySetDefinitions/slzManagementDefaults.json
@@ -0,0 +1,17 @@
+{
+ "properties": {
+ "displayName": "SLZ Management Policies",
+ "description": "SLZ Management Policies",
+ "policyType": "Custom",
+ "metadata": {
+ "category": "Regulatory Compliance",
+ "version": "0.3.0"
+ },
+ "parameters": {},
+ "policyDefinitions": [],
+ "policyDefinitionGroups": []
+ },
+ "id": "${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policySetDefinitions/SlzManagementPolicies",
+ "type": "Microsoft.Authorization/policySetDefinitions",
+ "name": "SlzManagementPolicies"
+}
diff --git a/modules/compliance/policySetDefinitions/slzOnlineDefaults.json b/modules/compliance/policySetDefinitions/slzOnlineDefaults.json
new file mode 100644
index 00000000..d0360efe
--- /dev/null
+++ b/modules/compliance/policySetDefinitions/slzOnlineDefaults.json
@@ -0,0 +1,17 @@
+{
+ "properties": {
+ "displayName": "SLZ Online Policies",
+ "description": "SLZ Online Policies",
+ "policyType": "Custom",
+ "metadata": {
+ "category": "Regulatory Compliance",
+ "version": "0.3.0"
+ },
+ "parameters": {},
+ "policyDefinitions": [],
+ "policyDefinitionGroups": []
+ },
+ "id": "${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policySetDefinitions/SlzOnlinePolicies",
+ "type": "Microsoft.Authorization/policySetDefinitions",
+ "name": "SlzOnlinePolicies"
+}
diff --git a/modules/compliance/policySetDefinitions/slzPlatformDefaults.json b/modules/compliance/policySetDefinitions/slzPlatformDefaults.json
new file mode 100644
index 00000000..724594a6
--- /dev/null
+++ b/modules/compliance/policySetDefinitions/slzPlatformDefaults.json
@@ -0,0 +1,17 @@
+{
+ "properties": {
+ "displayName": "SLZ Platform Policies",
+ "description": "SLZ Platform Policies",
+ "policyType": "Custom",
+ "metadata": {
+ "category": "Regulatory Compliance",
+ "version": "0.3.0"
+ },
+ "parameters": {},
+ "policyDefinitions": [],
+ "policyDefinitionGroups": []
+ },
+ "id": "${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policySetDefinitions/SlzPlatformPolicies",
+ "type": "Microsoft.Authorization/policySetDefinitions",
+ "name": "SlzPlatformPolicies"
+}
diff --git a/modules/compliance/policySetDefinitions/slzSandboxDefaults.json b/modules/compliance/policySetDefinitions/slzSandboxDefaults.json
new file mode 100644
index 00000000..cc153d76
--- /dev/null
+++ b/modules/compliance/policySetDefinitions/slzSandboxDefaults.json
@@ -0,0 +1,17 @@
+{
+ "properties": {
+ "displayName": "SLZ Sandbox Policies",
+ "description": "SLZ Sandbox Policies",
+ "policyType": "Custom",
+ "metadata": {
+ "category": "Regulatory Compliance",
+ "version": "0.3.0"
+ },
+ "parameters": {},
+ "policyDefinitions": [],
+ "policyDefinitionGroups": []
+ },
+ "id": "${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policySetDefinitions/SlzSandboxPolicies",
+ "type": "Microsoft.Authorization/policySetDefinitions",
+ "name": "SlzSandboxPolicies"
+}
diff --git a/modules/customRoles/customRoleAssignment.bicep b/modules/customRoles/customRoleAssignment.bicep
new file mode 100644
index 00000000..671daeee
--- /dev/null
+++ b/modules/customRoles/customRoleAssignment.bicep
@@ -0,0 +1,37 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+/*
+ SUMMARY : Creates a role assignment at the management group scope
+ AUTHOR/S: Cloud for Sovereignty
+*/
+targetScope = 'managementGroup'
+
+@description('Role Definition Id')
+param parRoleDefinitionId string
+
+@description('Principal Id of resource for role assignment')
+param parPrincipalId string
+
+@description('Service principal type')
+@allowed([
+ 'Device'
+ 'ForeignGroup'
+ 'Group'
+ 'ServicePrincipal'
+ 'User'
+])
+param parPrincipalType string
+
+@description('A GUID representing the role assignment name. Default: guid(managementGroup().name, parRoleDefinitionId, parPrincipalId)')
+var varRoleAssignmentName = guid(managementGroup().name, parRoleDefinitionId, parPrincipalId)
+
+// Create role assignment
+resource resRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
+ scope: managementGroup()
+ name: varRoleAssignmentName
+ properties: {
+ roleDefinitionId: parRoleDefinitionId
+ principalId: parPrincipalId
+ principalType: parPrincipalType
+ }
+}
diff --git a/modules/customRoles/customRoleDefinition.bicep b/modules/customRoles/customRoleDefinition.bicep
new file mode 100644
index 00000000..112c4613
--- /dev/null
+++ b/modules/customRoles/customRoleDefinition.bicep
@@ -0,0 +1,42 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+/*
+ SUMMARY : Creates a custom role definition at the management group scope
+ AUTHOR/S: Cloud for Sovereignty
+*/
+targetScope = 'managementGroup'
+
+@description('Array of actions for the roleDefinition')
+param parActions array = []
+
+@description('Array of notActions for the roleDefinition')
+param parNotActions array = []
+
+@description('Friendly name of the role definition')
+param parRoleName string
+
+@description('Detailed description of the role definition')
+param parRoleDescription string
+
+var varRoleDefName = guid(managementGroup().id, parRoleName)
+
+// Create the role definition
+resource resRoleDef 'Microsoft.Authorization/roleDefinitions@2022-04-01' = {
+ name: varRoleDefName
+ properties: {
+ roleName: parRoleName
+ description: parRoleDescription
+ type: 'customRole'
+ permissions: [
+ {
+ actions: parActions
+ notActions: parNotActions
+ }
+ ]
+ assignableScopes: [
+ managementGroup().id
+ ]
+ }
+}
+
+output outRoleDefinitionId string = resRoleDef.id
diff --git a/modules/dashboard/dashboard.bicep b/modules/dashboard/dashboard.bicep
new file mode 100644
index 00000000..a1dc500d
--- /dev/null
+++ b/modules/dashboard/dashboard.bicep
@@ -0,0 +1,942 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+/*
+ SUMMARY : This template deploys a dashboard with all the compliance tiles for the SLZ
+ AUTHOR/S: Cloud for Sovereignty
+*/
+@description('The name of the Dashboard')
+param parDashboardName string
+
+@description('The deployment location.')
+param parLocation string
+
+@description('The name of the country or agency SLZ is being deployed for. DEFAULT: Country')
+param parCountryOrAgencyName string
+
+@description('The prefix that will be added to all resources created by this deployment. E.g. mcfs')
+@minLength(2)
+@maxLength(5)
+param parDeploymentPrefix string
+
+@description('Tags to be added to deployed resources')
+param parTags object
+
+// Header
+var varMarkdownHeaderText = loadTextContent('./templates/markdownPart.md')
+
+// Load Query from Text Files
+var varResourceComplianceScoreText = loadTextContent('./templates/resourceComplianceScore.csl')
+var varResourcesbyComplianceStateText = loadTextContent('./templates/resourcesbyComplianceState.csl')
+var varCompliancebySubscriptionText = loadTextContent('./templates/compliancebySubscription.csl')
+var varCompliancebyPolicyInitiativeText = loadTextContent('./templates/compliancebyPolicyInitiative.csl')
+var varListofNonCompliantResourcesText = loadTextContent('./templates/listofNonCompliantResources.csl')
+var varResourcesOutsideofSafeRegionText = loadTextContent('./templates/resourcesOutsideofSafeRegion.csl')
+var varListofResourcesExemptofDataResidentPolicyText = loadTextContent('./templates/listofResourcesExemptofDataResidentPolicy.csl')
+var varListofResourcesOutsideofSafeRegionText = loadTextContent('./templates/listofResourcesOutsideofSafeRegion.csl')
+var varConfidentialityScoreText = loadTextContent('./templates/confidentialityScore.csl')
+var varDataResidencyScoreText = loadTextContent('./templates/dataResidencyScore.csl')
+var varListOfResourcesExemptOfConfidentialPoliciesText = loadTextContent('./templates/listOfResourcesExemptOfConfidentialPolicies.csl')
+var varComplianceByPolicyGroupText = loadTextContent('./templates/complianceByPolicyGroup.csl')
+var varComplianceScoreForStoragePolicyGroupText = loadTextContent('./templates/complianceScoreForStoragePolicyGroup.csl')
+var varComplianceScoreForTransportPolicyGroupText = loadTextContent('./templates/complianceScoreForTransportPolicyGroup.csl')
+var varComplianceScoreForConfidentialComputingPolicyGroupText = loadTextContent('./templates/complianceScoreForConfidentialComputingPolicyGroup.csl')
+
+// Queries
+var varResourceComplianceScoreQuery = replace(varResourceComplianceScoreText, 'RootPrefix_PLACEHOLDER', parDeploymentPrefix)
+var varResourcesbyComplianceStateQuery = replace(varResourcesbyComplianceStateText, 'RootPrefix_PLACEHOLDER', parDeploymentPrefix)
+var varCompliancebyPolicyInitiativeQuery = replace(varCompliancebyPolicyInitiativeText, 'RootPrefix_PLACEHOLDER', parDeploymentPrefix)
+var varCompliancebySubscriptionQuery = replace(varCompliancebySubscriptionText, 'RootPrefix_PLACEHOLDER', parDeploymentPrefix)
+var varListofNonCompliantResourcesQuery = replace(varListofNonCompliantResourcesText, 'RootPrefix_PLACEHOLDER', parDeploymentPrefix)
+var varResourcesOutsideofSafeRegionQuery = replace(varResourcesOutsideofSafeRegionText, 'RootPrefix_PLACEHOLDER', parDeploymentPrefix)
+var varListofResourcesExemptofDataResidentPolicyQuery = replace(varListofResourcesExemptofDataResidentPolicyText, 'RootPrefix_PLACEHOLDER', parDeploymentPrefix)
+var varListofResourcesOutsideofSafeRegionQuery = replace(varListofResourcesOutsideofSafeRegionText, 'RootPrefix_PLACEHOLDER', parDeploymentPrefix)
+var varConfidentialityScoreQuery = replace(varConfidentialityScoreText, 'RootPrefix_PLACEHOLDER', parDeploymentPrefix)
+var varDataResidencyScoreQuery = replace(varDataResidencyScoreText, 'RootPrefix_PLACEHOLDER', parDeploymentPrefix)
+var varListOfResourcesExemptOfConfidentialPoliciesQuery = replace(varListOfResourcesExemptOfConfidentialPoliciesText, 'RootPrefix_PLACEHOLDER', parDeploymentPrefix)
+var varComplianceByPolicyGroupQuery = replace(varComplianceByPolicyGroupText, 'RootPrefix_PLACEHOLDER', parDeploymentPrefix)
+var varComplianceScoreForStoragePolicyGroupQuery = replace(varComplianceScoreForStoragePolicyGroupText, 'RootPrefix_PLACEHOLDER', parDeploymentPrefix)
+var varComplianceScoreForTransportPolicyGroupQuery = replace(varComplianceScoreForTransportPolicyGroupText, 'RootPrefix_PLACEHOLDER', parDeploymentPrefix)
+var varComplianceScoreForConfidentialComputingPolicyGroupQuery = replace(varComplianceScoreForConfidentialComputingPolicyGroupText, 'RootPrefix_PLACEHOLDER', parDeploymentPrefix)
+
+var varDefaultTitles = [
+ {
+ position: {
+ x: 0
+ y: 0
+ colSpan: 8
+ rowSpan: 2
+ }
+ metadata: {
+ inputs: []
+ type: 'Extension/HubsExtension/PartType/MarkdownPart'
+ settings: {
+ content: {
+ settings: {
+ content: varMarkdownHeaderText
+ title: 'Sovereign landing zone dashboard for ${parDeploymentPrefix}'
+ subtitle: parCountryOrAgencyName
+ markdownSource: 1
+ markdownUri: null
+ }
+ }
+ }
+ partHeader: {}
+ }
+ }
+ {
+ position: {
+ x: 8
+ y: 0
+ colSpan: 8
+ rowSpan: 2
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'chartType'
+ isOptional: true
+ }
+ {
+ name: 'isShared'
+ isOptional: true
+ }
+ {
+ name: 'queryId'
+ isOptional: true
+ }
+ {
+ name: 'partTitle'
+ value: 'Overall resources compliance score'
+ isOptional: true
+ }
+ {
+ name: 'query'
+ value: varResourceComplianceScoreQuery
+ isOptional: true
+ }
+ {
+ name: 'queryScope'
+ value: {
+ scope: 0
+ values: []
+ }
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/ArgQuerySingleValueTile'
+ settings: {}
+ partHeader: {
+ title: 'Overall resources compliance score'
+ subtitle: 'Percent of resources compliant with all policies in the SLZ'
+ }
+ }
+ }
+ {
+ position: {
+ x: 0
+ y: 2
+ colSpan: 8
+ rowSpan: 2
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'chartType'
+ isOptional: true
+ }
+ {
+ name: 'isShared'
+ isOptional: true
+ }
+ {
+ name: 'queryId'
+ isOptional: true
+ }
+ {
+ name: 'partTitle'
+ value: 'Overall data residency compliance score'
+ isOptional: true
+ }
+ {
+ name: 'query'
+ value: varDataResidencyScoreQuery
+ isOptional: true
+ }
+ {
+ name: 'queryScope'
+ value: {
+ scope: 0
+ values: []
+ }
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/ArgQuerySingleValueTile'
+ settings: {}
+ partHeader: {
+ title: 'Overall data residency compliance score'
+ subtitle: 'Percent of resources compliant with data residency policies in the SLZ'
+ }
+ }
+ }
+ {
+ position: {
+ x: 8
+ y: 2
+ colSpan: 8
+ rowSpan: 2
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'chartType'
+ isOptional: true
+ }
+ {
+ name: 'isShared'
+ isOptional: true
+ }
+ {
+ name: 'queryId'
+ isOptional: true
+ }
+ {
+ name: 'partTitle'
+ value: 'Overall confidential compliance score'
+ isOptional: true
+ }
+ {
+ name: 'query'
+ value: varConfidentialityScoreQuery
+ isOptional: true
+ }
+ {
+ name: 'queryScope'
+ value: {
+ scope: 0
+ values: []
+ }
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/ArgQuerySingleValueTile'
+ settings: {}
+ partHeader: {
+ title: 'Overall confidential compliance score'
+ subtitle: 'Percent of resources compliant with encryption and confidential computing policies in the SLZ'
+ }
+ }
+ }
+ {
+ position: {
+ x: 0
+ y: 4
+ colSpan: 16
+ rowSpan: 1
+ }
+ metadata: {
+ inputs: []
+ type: 'Extension/HubsExtension/PartType/MarkdownPart'
+ settings: {
+ content: {
+ settings: {
+ content: ''
+ title: 'Policy compliance'
+ subtitle: ''
+ markdownSource: 1
+ markdownUri: null
+ }
+ }
+ }
+ partHeader: {}
+ }
+ }
+ {
+ position: {
+ x: 0
+ y: 5
+ colSpan: 6
+ rowSpan: 8
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'isShared'
+ isOptional: true
+ }
+ {
+ name: 'queryId'
+ isOptional: true
+ }
+ {
+ name: 'partTitle'
+ value: 'Resource compliance by state'
+ isOptional: true
+ }
+ {
+ name: 'query'
+ value: varResourcesbyComplianceStateQuery
+ isOptional: true
+ }
+ {
+ name: 'chartType'
+ value: 2
+ isOptional: true
+ }
+ {
+ name: 'queryScope'
+ value: {
+ scope: 0
+ values: []
+ }
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/ArgQueryChartTile'
+ settings: {}
+ partHeader: {
+ title: 'Resource compliance by state'
+ subtitle: 'Hover over bar to see percent of resources in each state'
+ }
+ }
+ }
+ {
+ position: {
+ x: 6
+ y: 5
+ colSpan: 10
+ rowSpan: 4
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'isShared'
+ isOptional: true
+ }
+ {
+ name: 'queryId'
+ isOptional: true
+ }
+ {
+ name: 'partTitle'
+ value: 'Resource compliance percentage by subscription'
+ isOptional: true
+ }
+ {
+ name: 'query'
+ value: varCompliancebySubscriptionQuery
+ isOptional: true
+ }
+ {
+ name: 'chartType'
+ value: 1
+ isOptional: true
+ }
+ {
+ name: 'queryScope'
+ value: {
+ scope: 0
+ values: []
+ }
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/ArgQueryChartTile'
+ settings: {}
+ partHeader: {
+ title: 'Resource compliance percentage by subscription'
+ subtitle: 'Hover over bar to see subscription name and its compliance percentage'
+ }
+ }
+ }
+ {
+ position: {
+ x: 6
+ y: 9
+ colSpan: 10
+ rowSpan: 4
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'isShared'
+ isOptional: true
+ }
+ {
+ name: 'queryId'
+ isOptional: true
+ }
+ {
+ name: 'partTitle'
+ value: 'Resource compliance percentage by policy initiative'
+ isOptional: true
+ }
+ {
+ name: 'query'
+ value: varCompliancebyPolicyInitiativeQuery
+ isOptional: true
+ }
+ {
+ name: 'chartType'
+ value: 1
+ isOptional: true
+ }
+ {
+ name: 'queryScope'
+ value: {
+ scope: 0
+ values: []
+ }
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/ArgQueryChartTile'
+ settings: {}
+ partHeader: {
+ title: 'Resource compliance percentage by policy initiative'
+ subtitle: 'Hover over bar to see policy initiative name and its compliance percentage'
+ }
+ }
+ }
+ {
+ position: {
+ x: 0
+ y: 13
+ colSpan: 16
+ rowSpan: 4
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'isShared'
+ isOptional: true
+ }
+ {
+ name: 'queryId'
+ isOptional: true
+ }
+ {
+ name: 'partTitle'
+ value: 'Resources compliance percentage by policy group name'
+ isOptional: true
+ }
+ {
+ name: 'query'
+ value: varComplianceByPolicyGroupQuery
+ isOptional: true
+ }
+ {
+ name: 'chartType'
+ value: 1
+ isOptional: true
+ }
+ {
+ name: 'queryScope'
+ value: {
+ scope: 0
+ values: []
+ }
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/ArgQueryChartTile'
+ settings: {}
+ partHeader: {
+ title: 'Resource compliance percentage by policy group name'
+ subtitle: 'Hover over bar to see policy group name and its compliance percentage'
+ }
+ }
+ }
+ {
+ position: {
+ x: 0
+ y: 17
+ colSpan: 16
+ rowSpan: 5
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'chartType'
+ isOptional: true
+ }
+ {
+ name: 'isShared'
+ isOptional: true
+ }
+ {
+ name: 'queryId'
+ isOptional: true
+ }
+ {
+ name: 'partTitle'
+ value: 'Non-Compliant and exempt resources'
+ isOptional: true
+ }
+ {
+ name: 'query'
+ value: varListofNonCompliantResourcesQuery
+ isOptional: true
+ }
+ {
+ name: 'queryScope'
+ value: {
+ scope: 0
+ values: []
+ }
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/ArgQueryGridTile'
+ settings: {}
+ partHeader: {
+ title: 'Non-Compliant and exempt resources'
+ subtitle: 'List of non-compliant and exempt resources for all policies in the SLZ'
+ }
+ }
+ }
+ {
+ position: {
+ x: 0
+ y: 22
+ colSpan: 16
+ rowSpan: 1
+ }
+ metadata: {
+ inputs: []
+ type: 'Extension/HubsExtension/PartType/MarkdownPart'
+ settings: {
+ content: {
+ settings: {
+ content: ''
+ title: 'Data residency compliance'
+ subtitle: ''
+ markdownSource: 1
+ markdownUri: null
+ }
+ }
+ }
+ partHeader: {}
+ }
+ }
+ {
+ position: {
+ x: 0
+ y: 23
+ colSpan: 5
+ rowSpan: 5
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'isShared'
+ isOptional: true
+ }
+ {
+ name: 'queryId'
+ isOptional: true
+ }
+ {
+ name: 'partTitle'
+ value: 'Non-compliant resources by location'
+ isOptional: true
+ }
+ {
+ name: 'query'
+ value: varResourcesOutsideofSafeRegionQuery
+ isOptional: true
+ }
+ {
+ name: 'chartType'
+ value: 1
+ isOptional: true
+ }
+ {
+ name: 'queryScope'
+ value: {
+ scope: 0
+ values: []
+ }
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/ArgQueryChartTile'
+ settings: {}
+ partHeader: {
+ title: 'Non-Compliant resources by location'
+ subtitle: 'These resources are in non-compliant locations per the data residency policy'
+ }
+ }
+ }
+ {
+ position: {
+ x: 5
+ y: 23
+ colSpan: 11
+ rowSpan: 5
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'chartType'
+ isOptional: true
+ }
+ {
+ name: 'isShared'
+ isOptional: true
+ }
+ {
+ name: 'queryId'
+ isOptional: true
+ }
+ {
+ name: 'partTitle'
+ value: 'Resources exempt from data residency policies'
+ isOptional: true
+ }
+ {
+ name: 'query'
+ value: varListofResourcesExemptofDataResidentPolicyQuery
+ isOptional: true
+ }
+ {
+ name: 'queryScope'
+ value: {
+ scope: 0
+ values: []
+ }
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/ArgQueryGridTile'
+ settings: {}
+ partHeader: {
+ title: 'Resources exempt from data residency policies'
+ subtitle: 'These resources are exempt from data residency policies'
+ }
+ }
+ }
+ {
+ position: {
+ x: 0
+ y: 28
+ colSpan: 16
+ rowSpan: 5
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'chartType'
+ isOptional: true
+ }
+ {
+ name: 'isShared'
+ isOptional: true
+ }
+ {
+ name: 'queryId'
+ isOptional: true
+ }
+ {
+ name: 'partTitle'
+ value: 'Resources outside of approved regions'
+ isOptional: true
+ }
+ {
+ name: 'query'
+ value: varListofResourcesOutsideofSafeRegionQuery
+ isOptional: true
+ }
+ {
+ name: 'queryScope'
+ value: {
+ scope: 0
+ values: []
+ }
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/ArgQueryGridTile'
+ settings: {}
+ partHeader: {
+ title: 'Resources outside of approved regions'
+ subtitle: 'These are the resources deployed outside of an approved region'
+ }
+ }
+ }
+ {
+ position: {
+ x: 0
+ y: 33
+ colSpan: 16
+ rowSpan: 1
+ }
+ metadata: {
+ inputs: []
+ type: 'Extension/HubsExtension/PartType/MarkdownPart'
+ settings: {
+ content: {
+ settings: {
+ content: ''
+ title: 'Confidential computing'
+ subtitle: ''
+ markdownSource: 1
+ markdownUri: null
+ }
+ }
+ }
+ partHeader: {}
+ }
+ }
+ {
+ position: {
+ x: 0
+ y: 34
+ colSpan: 5
+ rowSpan: 2
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'chartType'
+ isOptional: true
+ }
+ {
+ name: 'isShared'
+ isOptional: true
+ }
+ {
+ name: 'queryId'
+ isOptional: true
+ }
+ {
+ name: 'partTitle'
+ value: 'Resource compliance score for encryption at rest policies'
+ isOptional: true
+ }
+ {
+ name: 'query'
+ value: varComplianceScoreForStoragePolicyGroupQuery
+ isOptional: true
+ }
+ {
+ name: 'queryScope'
+ value: {
+ scope: 0
+ values: []
+ }
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/ArgQuerySingleValueTile'
+ settings: {}
+ partHeader: {
+ title: 'Resource compliance score for encryption at rest policies'
+ subtitle: 'Percent of resources compliant with encryption at rest policies in the SLZ'
+ }
+ }
+ }
+ {
+ position: {
+ x: 5
+ y: 34
+ colSpan: 5
+ rowSpan: 2
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'chartType'
+ isOptional: true
+ }
+ {
+ name: 'isShared'
+ isOptional: true
+ }
+ {
+ name: 'queryId'
+ isOptional: true
+ }
+ {
+ name: 'partTitle'
+ value: 'Resource compliance score for encryption in transit policies'
+ isOptional: true
+ }
+ {
+ name: 'query'
+ value: varComplianceScoreForTransportPolicyGroupQuery
+ isOptional: true
+ }
+ {
+ name: 'queryScope'
+ value: {
+ scope: 0
+ values: []
+ }
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/ArgQuerySingleValueTile'
+ settings: {}
+ partHeader: {
+ title: 'Resource compliance score for encryption in transit policies'
+ subtitle: 'Percent of resources compliant with encryption in transit policies in the SLZ'
+ }
+ }
+ }
+ {
+ position: {
+ x: 10
+ y: 34
+ colSpan: 6
+ rowSpan: 2
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'chartType'
+ isOptional: true
+ }
+ {
+ name: 'isShared'
+ isOptional: true
+ }
+ {
+ name: 'queryId'
+ isOptional: true
+ }
+ {
+ name: 'partTitle'
+ value: 'Resource compliance score for confidential computing policies'
+ isOptional: true
+ }
+ {
+ name: 'query'
+ value: varComplianceScoreForConfidentialComputingPolicyGroupQuery
+ isOptional: true
+ }
+ {
+ name: 'queryScope'
+ value: {
+ scope: 0
+ values: []
+ }
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/ArgQuerySingleValueTile'
+ settings: {}
+ partHeader: {
+ title: 'Resource compliance score for confidential computing policies'
+ subtitle: 'Percent of resources compliant with confidential computing policies in the SLZ'
+ }
+ }
+ }
+ {
+ position: {
+ x: 0
+ y: 36
+ colSpan: 16
+ rowSpan: 5
+ }
+ metadata: {
+ inputs: [
+ {
+ name: 'chartType'
+ isOptional: true
+ }
+ {
+ name: 'isShared'
+ isOptional: true
+ }
+ {
+ name: 'queryId'
+ isOptional: true
+ }
+ {
+ name: 'partTitle'
+ value: 'Resources exempt from confidential computing policies'
+ isOptional: true
+ }
+ {
+ name: 'query'
+ value: varListOfResourcesExemptOfConfidentialPoliciesQuery
+ isOptional: true
+ }
+ {
+ name: 'queryScope'
+ value: {
+ scope: 0
+ values: []
+ }
+ isOptional: true
+ }
+ ]
+ #disable-next-line BCP036
+ type: 'Extension/HubsExtension/PartType/ArgQueryGridTile'
+ settings: {}
+ partHeader: {
+ title: 'Resources exempt from confidential computing policies'
+ subtitle: 'These resources are exempt from confidential computing policies'
+ }
+ }
+ }
+]
+
+var varCustomTiles = loadJsonContent('../../custom/dashboard/compliance/tiles.json')
+var varAllTiles = concat(varDefaultTitles, varCustomTiles)
+
+resource resDashboard 'Microsoft.Portal/dashboards@2020-09-01-preview' = {
+ name: parDashboardName
+ location: parLocation
+ tags: parTags
+ properties: {
+ lenses: [
+ {
+ order: 0
+ parts: [for part in varAllTiles: {
+ position: {
+ x: part.position.x
+ y: part.position.y
+ colSpan: part.position.colSpan
+ rowSpan: part.position.rowSpan
+ }
+ metadata: {
+ inputs: part.metadata.inputs
+ #disable-next-line BCP036
+ type: part.metadata.type
+ settings: part.metadata.settings
+ partHeader: empty(part.metadata.partHeader) ? part.metadata.partHeader : {}
+ }
+ }]
+ }
+ ]
+ metadata: {
+ model: {
+ timeRange: {
+ value: {
+ relative: {
+ duration: 24
+ timeUnit: 1
+ }
+ }
+ type: 'MsPortalFx.Composition.Configuration.ValueTypes.TimeRange'
+ }
+ }
+ }
+ }
+}
diff --git a/modules/dashboard/templates/complianceByPolicyGroup.csl b/modules/dashboard/templates/complianceByPolicyGroup.csl
new file mode 100644
index 00000000..cfec6a6a
--- /dev/null
+++ b/modules/dashboard/templates/complianceByPolicyGroup.csl
@@ -0,0 +1,16 @@
+PolicyResources
+| where type == 'microsoft.policyinsights/policystates' and tolower(properties.policyAssignmentScope) has '/providers/Microsoft.Management/managementGroups/RootPrefix_PLACEHOLDER'
+| extend policyDefinitionId = tolower(properties.policyDefinitionId), policyGroups = properties.policyDefinitionGroupNames, policySetDefinitionName = tolower(properties.policySetDefinitionName)
+| mv-expand parsed_policy_groups = policyGroups
+| where parsed_policy_groups hasprefix "dashboard-"
+| extend parsed_policy_groups = trim('dashboard-',tostring(parsed_policy_groups))
+| project properties, policyDefinitionId, parsed_policy_groups
+| extend complianceState = tostring(properties.complianceState), resourceId = tolower(properties.resourceId), stateWeight = tolong(properties.stateWeight)
+| summarize max(stateWeight) by resourceId, tostring(parsed_policy_groups)
+| summarize counts = count() by tostring(parsed_policy_groups), max_stateWeight
+| summarize nonCompliantCount = sumif(counts, max_stateWeight == 300), compliantCount = sumif(counts, max_stateWeight == 200), conflictCount = sumif(counts, max_stateWeight == 100), exemptCount = sumif(counts, max_stateWeight == 50) by tostring(parsed_policy_groups)
+| extend totalResources = todouble(nonCompliantCount + compliantCount + conflictCount + exemptCount)
+| extend totalCompliantResources = todouble(compliantCount + exemptCount)
+| extend compliancePercentage = iff(totalResources == 0 or (totalCompliantResources == 0 and nonCompliantCount == 0), todouble(100), 100 * totalCompliantResources / totalResources)
+| project toupper(parsed_policy_groups), compliancePercentageEx = toint(round(compliancePercentage, 1))
+| order by compliancePercentageEx asc
diff --git a/modules/dashboard/templates/complianceScoreForConfidentialComputingPolicyGroup.csl b/modules/dashboard/templates/complianceScoreForConfidentialComputingPolicyGroup.csl
new file mode 100644
index 00000000..ce700a11
--- /dev/null
+++ b/modules/dashboard/templates/complianceScoreForConfidentialComputingPolicyGroup.csl
@@ -0,0 +1,13 @@
+PolicyResources
+|where type == 'microsoft.policyinsights/policystates' and tolower(properties.policyAssignmentScope) has '/providers/Microsoft.Management/managementGroups/RootPrefix_PLACEHOLDER'
+| extend policyDefinitionId = tolower(properties.policyDefinitionId), policyGroups = tolower(properties.policyDefinitionGroupNames), policySetDefinitionName = tolower(properties.policySetDefinitionName)
+| mv-expand parsed_policy_groups = parse_json(policyGroups)
+| where tostring(parsed_policy_groups) in ("dashboard-confidential computing","dashboard-key management")
+| extend complianceState = tostring(properties.complianceState), resourceId = tolower(properties.resourceId), resourceType = tolower(properties.resourceType), stateWeight = tolong(properties.stateWeight)
+| summarize max(stateWeight) by resourceId, resourceType
+| project resourceId, resourceType, complianceState = iff(max_stateWeight == 300, 'NonCompliant', iff(max_stateWeight == 200, 'Compliant', iff(max_stateWeight == 100 , 'Conflict', iff(max_stateWeight == 50, 'Exempt', 'UnknownResource'))))
+| summarize counts = count() by complianceState
+| summarize compliantCount = sumif(counts, complianceState == 'Compliant' or complianceState == 'Exempt'), nonCompliantCount = sumif(counts, complianceState == 'Conflict' or complianceState == 'NonCompliant')
+| extend totalNum = toint(compliantCount + nonCompliantCount)
+| extend compliancePercentageVal = iff(totalNum == 0, todouble(100), 100 * todouble(compliantCount) / totalNum)
+| project ['Confidentiality compliance percentage (includes compliant and exempt)'] = strcat(tostring(round(compliancePercentageVal, 1)), '% (', tostring(compliantCount),' out of ', tostring(totalNum), ')')
\ No newline at end of file
diff --git a/modules/dashboard/templates/complianceScoreForStoragePolicyGroup.csl b/modules/dashboard/templates/complianceScoreForStoragePolicyGroup.csl
new file mode 100644
index 00000000..9b95ea0a
--- /dev/null
+++ b/modules/dashboard/templates/complianceScoreForStoragePolicyGroup.csl
@@ -0,0 +1,13 @@
+PolicyResources
+|where type == 'microsoft.policyinsights/policystates' and tolower(properties.policyAssignmentScope) has '/providers/Microsoft.Management/managementGroups/RootPrefix_PLACEHOLDER'
+| extend policyDefinitionId = tolower(properties.policyDefinitionId), policyGroups = tolower(properties.policyDefinitionGroupNames)
+| mv-expand parsed_policy_groups = parse_json(policyGroups)
+| where tostring(parsed_policy_groups) == "dashboard-storage security"
+| extend complianceState = tostring(properties.complianceState), resourceId = tolower(properties.resourceId), resourceType = tolower(properties.resourceType), stateWeight = tolong(properties.stateWeight)
+| summarize max(stateWeight) by resourceId, resourceType
+| project resourceId, resourceType, complianceState = iff(max_stateWeight == 300, 'NonCompliant', iff(max_stateWeight == 200, 'Compliant', iff(max_stateWeight == 100 , 'Conflict', iff(max_stateWeight == 50, 'Exempt', 'UnknownResource'))))
+| summarize counts = count() by complianceState
+| summarize compliantCount = sumif(counts, complianceState == 'Compliant' or complianceState == 'Exempt'), nonCompliantCount = sumif(counts, complianceState == 'Conflict' or complianceState == 'NonCompliant')
+| extend totalNum = toint(compliantCount + nonCompliantCount)
+| extend compliancePercentageVal = iff(totalNum == 0, todouble(100), 100 * todouble(compliantCount) / totalNum)
+| project ['Confidentiality compliance percentage (includes compliant and exempt)'] = strcat(tostring(round(compliancePercentageVal, 1)), '% (', tostring(compliantCount),' out of ', tostring(totalNum), ')')
\ No newline at end of file
diff --git a/modules/dashboard/templates/complianceScoreForTransportPolicyGroup.csl b/modules/dashboard/templates/complianceScoreForTransportPolicyGroup.csl
new file mode 100644
index 00000000..a899e81a
--- /dev/null
+++ b/modules/dashboard/templates/complianceScoreForTransportPolicyGroup.csl
@@ -0,0 +1,13 @@
+PolicyResources
+|where type == 'microsoft.policyinsights/policystates' and tolower(properties.policyAssignmentScope) has '/providers/Microsoft.Management/managementGroups/RootPrefix_PLACEHOLDER'
+| extend policyAssignmentScope = tolower(properties.policyAssignmentScope), policyDefinitionId = tolower(properties.policyDefinitionId), policyGroups = tolower(properties.policyDefinitionGroupNames), policySetDefinitionName = tolower(properties.policySetDefinitionName)
+| mv-expand parsed_policy_groups = parse_json(policyGroups)
+| where tostring(parsed_policy_groups) == "dashboard-transport security"
+| extend complianceState = tostring(properties.complianceState), resourceId = tolower(properties.resourceId), resourceType = tolower(properties.resourceType), stateWeight = tolong(properties.stateWeight)
+| summarize max(stateWeight) by resourceId, resourceType
+| project resourceId, resourceType, complianceState = iff(max_stateWeight == 300, 'NonCompliant', iff(max_stateWeight == 200, 'Compliant', iff(max_stateWeight == 100 , 'Conflict', iff(max_stateWeight == 50, 'Exempt', 'UnknownResource'))))
+| summarize counts = count() by complianceState
+| summarize compliantCount = sumif(counts, complianceState == 'Compliant' or complianceState == 'Exempt'), nonCompliantCount = sumif(counts, complianceState == 'Conflict' or complianceState == 'NonCompliant')
+| extend totalNum = toint(compliantCount + nonCompliantCount)
+| extend compliancePercentageVal = iff(totalNum == 0, todouble(100), 100 * todouble(compliantCount) / totalNum)
+| project ['Confidentiality compliance percentage (includes compliant and exempt)'] = strcat(tostring(round(compliancePercentageVal, 1)), '% (', tostring(compliantCount),' out of ', tostring(totalNum), ')')
\ No newline at end of file
diff --git a/modules/dashboard/templates/compliancebyPolicyInitiative.csl b/modules/dashboard/templates/compliancebyPolicyInitiative.csl
new file mode 100644
index 00000000..117f76dc
--- /dev/null
+++ b/modules/dashboard/templates/compliancebyPolicyInitiative.csl
@@ -0,0 +1,11 @@
+PolicyResources
+| where type == 'microsoft.policyinsights/policystates' and tolower(properties.policyAssignmentScope) has '/providers/Microsoft.Management/managementGroups/RootPrefix_PLACEHOLDER'
+| extend policySetInitiative = tostring(properties.policySetDefinitionName), resourceId = tolower(properties.resourceId), stateWeight = tolong(properties.stateWeight)
+| summarize max(stateWeight) by resourceId, policySetInitiative
+| summarize counts = count() by policySetInitiative, max_stateWeight
+| summarize nonCompliantCount = sumif(counts, max_stateWeight == 300), compliantCount = sumif(counts, max_stateWeight == 200), conflictCount = sumif(counts, max_stateWeight == 100), exemptCount = sumif(counts, max_stateWeight == 50) by policySetInitiative
+| extend totalResources = todouble(nonCompliantCount + compliantCount + conflictCount + exemptCount)
+| extend totalCompliantResources = todouble(compliantCount + exemptCount)
+| extend compliancePercentage = iff(totalResources == 0 or (totalCompliantResources == 0 and nonCompliantCount == 0), todouble(100), 100 * totalCompliantResources / totalResources)
+| project policySetInitiative, compliancePercentageEx = toint(round(compliancePercentage, 1))
+| order by compliancePercentageEx asc
\ No newline at end of file
diff --git a/modules/dashboard/templates/compliancebySubscription.csl b/modules/dashboard/templates/compliancebySubscription.csl
new file mode 100644
index 00000000..fd4ca223
--- /dev/null
+++ b/modules/dashboard/templates/compliancebySubscription.csl
@@ -0,0 +1,18 @@
+PolicyResources
+| where type == 'microsoft.policyinsights/policystates'
+| extend policyAssignmentScope = tolower(properties.policyAssignmentScope)
+| where policyAssignmentScope startswith '/providers/Microsoft.Management/managementGroups/RootPrefix_PLACEHOLDER'
+| extend complianceState = tostring(properties.complianceState), resourceId = tolower(properties.resourceId),subscriptionId = tostring(properties.subscriptionId), stateWeight = tolong(properties.stateWeight)
+| summarize max(stateWeight) by resourceId, subscriptionId
+| join kind=inner (
+ resourcecontainers
+ | where type == 'microsoft.resources/subscriptions'
+ | project subscriptionId, subscriptionName = name
+ ) on subscriptionId
+| summarize counts = count() by subscriptionId, subscriptionName, max_stateWeight
+| summarize nonCompliantCount = sumif(counts, max_stateWeight == 300), compliantCount = sumif(counts, max_stateWeight == 200), conflictCount = sumif(counts, max_stateWeight == 100), exemptCount = sumif(counts, max_stateWeight == 50) by subscriptionId, subscriptionName
+| extend totalResources = todouble(nonCompliantCount + compliantCount + conflictCount + exemptCount)
+| extend totalCompliantResources = todouble(compliantCount + exemptCount)
+| extend compliancePercentage = iff(totalResources == 0 or (totalCompliantResources == 0 and nonCompliantCount == 0), todouble(100), 100 * totalCompliantResources / totalResources)
+| project subscriptionName, compliancePercentageEx = toint(round(compliancePercentage, 1))
+| order by compliancePercentageEx asc
\ No newline at end of file
diff --git a/modules/dashboard/templates/confidentialityScore.csl b/modules/dashboard/templates/confidentialityScore.csl
new file mode 100644
index 00000000..7c620bb6
--- /dev/null
+++ b/modules/dashboard/templates/confidentialityScore.csl
@@ -0,0 +1,14 @@
+PolicyResources
+|where type == 'microsoft.policyinsights/policystates' and tolower(properties.policyAssignmentScope) has '/providers/Microsoft.Management/managementGroups/RootPrefix_PLACEHOLDER'
+| extend policyDefinitionId = tolower(properties.policyDefinitionId), policyGroups = tolower(properties.policyDefinitionGroupNames)
+| mv-expand parsed_policy_groups = parse_json(policyGroups)
+| where tostring(parsed_policy_groups) in ("dashboard-storage security", "dashboard-transport security", "dashboard-confidential computing","dashboard-key management")
+| project properties, policyDefinitionId, tostring(parsed_policy_groups)
+| extend complianceState = tostring(properties.complianceState), resourceId = tolower(properties.resourceId), resourceType = tolower(properties.resourceType), stateWeight = tolong(properties.stateWeight)
+| summarize max(stateWeight) by resourceId, resourceType
+| project resourceId, resourceType, complianceState = iff(max_stateWeight == 300, 'NonCompliant', iff(max_stateWeight == 200, 'Compliant', iff(max_stateWeight == 100 , 'Conflict', iff(max_stateWeight == 50, 'Exempt', 'UnknownResource'))))
+| summarize counts = count() by complianceState
+| summarize compliantCount = sumif(counts, complianceState == 'Compliant' or complianceState == 'Exempt'), nonCompliantCount = sumif(counts, complianceState == 'Conflict' or complianceState == 'NonCompliant')
+| extend totalNum = toint(compliantCount + nonCompliantCount)
+| extend compliancePercentageVal = iff(totalNum == 0, todouble(100), 100 * todouble(compliantCount) / totalNum)
+| project ['Confidentiality compliance percentage (includes compliant and exempt)'] = strcat(tostring(round(compliancePercentageVal, 1)), '% (', tostring(compliantCount),' out of ', tostring(totalNum), ')')
\ No newline at end of file
diff --git a/modules/dashboard/templates/dataResidencyScore.csl b/modules/dashboard/templates/dataResidencyScore.csl
new file mode 100644
index 00000000..e8b9b23e
--- /dev/null
+++ b/modules/dashboard/templates/dataResidencyScore.csl
@@ -0,0 +1,13 @@
+PolicyResources
+| where type == 'microsoft.policyinsights/policystates' and tolower(properties.policyAssignmentScope) has '/providers/Microsoft.Management/managementGroups/RootPrefix_PLACEHOLDER'
+| extend policyDefinitionId = tostring(properties.policyDefinitionId), policyGroups = tolower(properties.policyDefinitionGroupNames)
+| mv-expand parsed_policy_groups = parse_json(policyGroups)
+| where tostring(parsed_policy_groups) == "dashboard-data residency"
+| extend complianceState = tostring(properties.complianceState), resourceId = tolower(properties.resourceId), resourceType = tolower(properties.resourceType), stateWeight = tolong(properties.stateWeight)
+| summarize max(stateWeight) by resourceId, resourceType
+| project resourceId, resourceType, complianceState = iff(max_stateWeight == 300, 'NonCompliant', iff(max_stateWeight == 200, 'Compliant', iff(max_stateWeight == 100 , 'Conflict', iff(max_stateWeight == 50, 'Exempt', 'UnknownResource'))))
+| summarize counts = count() by complianceState
+| summarize compliantCount = sumif(counts, complianceState == 'Compliant' or complianceState == 'Exempt'), nonCompliantCount = sumif(counts, complianceState == 'Conflict' or complianceState == 'NonCompliant')
+| extend totalNum = toint(compliantCount + nonCompliantCount)
+| extend compliancePercentageVal = iff(totalNum == 0, todouble(100), 100 * todouble(compliantCount) / totalNum)
+| project ['Data residency compliance percentage (includes compliant and exempt)'] = strcat(tostring(round(compliancePercentageVal, 1)), '% (', tostring(compliantCount),' out of ', tostring(totalNum), ')')
\ No newline at end of file
diff --git a/modules/dashboard/templates/listOfResourcesExemptOfConfidentialPolicies.csl b/modules/dashboard/templates/listOfResourcesExemptOfConfidentialPolicies.csl
new file mode 100644
index 00000000..9bf82fbc
--- /dev/null
+++ b/modules/dashboard/templates/listOfResourcesExemptOfConfidentialPolicies.csl
@@ -0,0 +1,15 @@
+PolicyResources
+| where type == 'microsoft.policyinsights/policystates' and tostring(properties.complianceState) == "Exempt" and tolower(properties.policyAssignmentScope) has '/providers/Microsoft.Management/managementGroups/RootPrefix_PLACEHOLDER'
+| extend policyDefinitionId = tolower(properties.policyDefinitionId),complianceState = tostring(properties.complianceState), resourceId = tolower(properties.resourceId), resourceType = tostring(properties.resourceType), policySetDefinitionName = tostring(properties.policySetDefinitionName),subscriptionId = tostring(properties.subscriptionId), policyGroups = tolower(properties.policyDefinitionGroupNames)
+| mv-expand parsed_policy_groups = parse_json(policyGroups)
+| where tostring(parsed_policy_groups) in ("dashboard-storage security", "dashboard-transport security", "dashboard-confidential computing","dashboard-key management")
+| join kind=leftouter (
+ resources
+ | project resourceId=tolower(id), resourceName=name, resourceGroup
+ ) on resourceId
+| join kind=inner (
+ resourcecontainers
+ | where type == 'microsoft.resources/subscriptions'
+ | project subscriptionId, subscriptionName = name
+ ) on subscriptionId
+| project ['Compliance State']=complianceState, ['Policy initiative']=policySetDefinitionName, ['Policy definition id']=policyDefinitionId, ['Resource type']=resourceType, ['Resource name']=resourceName, ['Subscription id']=subscriptionId, ['Policy group']=tostring(parsed_policy_groups)
\ No newline at end of file
diff --git a/modules/dashboard/templates/listofNonCompliantResources.csl b/modules/dashboard/templates/listofNonCompliantResources.csl
new file mode 100644
index 00000000..54563121
--- /dev/null
+++ b/modules/dashboard/templates/listofNonCompliantResources.csl
@@ -0,0 +1,23 @@
+PolicyResources
+| where type == 'microsoft.policyinsights/policystates' and tolower(properties.policyAssignmentScope) has '/providers/Microsoft.Management/managementGroups/RootPrefix_PLACEHOLDER'
+| where properties.complianceState in ("NonCompliant", "Exempt")
+| extend complianceState = tostring(properties.complianceState),resourceId = tolower(properties.resourceId), resourceType = tostring(properties.resourceType), policySetDefinitionName = tostring(properties.policySetDefinitionName), subscriptionId = tostring(properties.subscriptionId), policyDefinitionName = tostring(properties.policyDefinitionName)
+| distinct resourceId, policySetDefinitionName, complianceState, resourceType, subscriptionId, policyDefinitionName
+| join kind=leftouter (
+ resources
+ | project resourceId=tolower(id), resourceName=name, resourceGroup
+ ) on resourceId
+| join kind=inner (
+ resourcecontainers
+ | where type == 'microsoft.resources/subscriptions'
+ | project subscriptionId, subscriptionName = name
+ ) on subscriptionId
+|join kind=inner (
+ PolicyResources
+ | where type == "microsoft.authorization/policydefinitions"
+ | extend policyName = tostring(properties.displayName)
+ | project policyName, policyDefinitionName = name
+ ) on policyDefinitionName
+| extend ['Resource name']= iff(resourceName=="", subscriptionName, resourceName)
+| project ['Compliance state']=complianceState, ['Policy initiative']=policySetDefinitionName,['Policy definition']=policyName, ['Resource type']=resourceType, ['Resource name'] , ['Resource group']=resourceGroup, ['Subscription']=subscriptionName
+| order by ['Compliance state'] desc, ['Resource type'], ['Resource name'] asc
diff --git a/modules/dashboard/templates/listofResourcesExemptofDataResidentPolicy.csl b/modules/dashboard/templates/listofResourcesExemptofDataResidentPolicy.csl
new file mode 100644
index 00000000..4b91a1fd
--- /dev/null
+++ b/modules/dashboard/templates/listofResourcesExemptofDataResidentPolicy.csl
@@ -0,0 +1,15 @@
+PolicyResources
+| where type == 'microsoft.policyinsights/policystates' and tostring(properties.complianceState) == "Exempt" and tolower(properties.policyAssignmentScope) has '/providers/Microsoft.Management/managementGroups/RootPrefix_PLACEHOLDER'
+| extend policyAssignmentScope = tolower(properties.policyAssignmentScope), complianceState = tostring(properties.complianceState), resourceId = tolower(properties.resourceId), resourceType = tostring(properties.resourceType), subscriptionId = tostring(properties.subscriptionId), policyDefinitionId = tostring(properties.policyDefinitionId), resourceLocation = tolower(properties.resourceLocation), policySetDefinitionName = tostring(properties.policySetDefinitionName), policyGroups = tolower(properties.policyDefinitionGroupNames)
+| mv-expand parsed_policy_groups = parse_json(policyGroups)
+| where tostring(parsed_policy_groups) == "dashboard-data residency"
+| join kind=leftouter (
+ resources
+ | project resourceId=tolower(id), resourceName=name, resourceGroup
+ ) on resourceId
+| join kind=inner (
+ resourcecontainers
+ | where type == 'microsoft.resources/subscriptions'
+ | project subscriptionId, subscriptionName = name
+ ) on subscriptionId
+| project ['Compliance state']=complianceState, ['Policy initiative']=policySetDefinitionName, ['Resource type']=resourceType, ['Resource name']=resourceName, ['Resource location']=resourceLocation
\ No newline at end of file
diff --git a/modules/dashboard/templates/listofResourcesOutsideofSafeRegion.csl b/modules/dashboard/templates/listofResourcesOutsideofSafeRegion.csl
new file mode 100644
index 00000000..ac0fa2b7
--- /dev/null
+++ b/modules/dashboard/templates/listofResourcesOutsideofSafeRegion.csl
@@ -0,0 +1,12 @@
+policyResources
+| where type == 'microsoft.policyinsights/policystates' and tolower(properties.policyAssignmentScope) has '/providers/Microsoft.Management/managementGroups/RootPrefix_PLACEHOLDER'
+| extend complianceState = tostring(properties.complianceState), resourceId = tolower(properties.resourceId), resourceType = tostring(properties.resourceType), resourceLocation = tolower(properties.resourceLocation), policySetDefinitionName = tostring(properties.policySetDefinitionName), policyGroups = tolower(properties.policyDefinitionGroupNames)
+| where (complianceState == 'NonCompliant' or complianceState == 'Exempt')
+| mv-expand parsed_policy_groups = parse_json(policyGroups)
+| where tostring(parsed_policy_groups) == "dashboard-data residency"
+| join kind=leftouter (
+ resources
+ | project resourceId=tolower(id), resourceName=name, resourceGroup
+ ) on resourceId
+| project ['Compliance state']=complianceState, ['Policy initiative']=policySetDefinitionName, ['Resource type']=resourceType, ['Resource name']=resourceName, ['Resource location']=resourceLocation, ['Resource group']=resourceGroup
+| order by ['Compliance state'] desc, ['Resource type'], ['Resource name'] asc
\ No newline at end of file
diff --git a/modules/dashboard/templates/markdownPart.md b/modules/dashboard/templates/markdownPart.md
new file mode 100644
index 00000000..f2de281f
--- /dev/null
+++ b/modules/dashboard/templates/markdownPart.md
@@ -0,0 +1,18 @@
+
diff --git a/modules/dashboard/templates/resourceComplianceScore.csl b/modules/dashboard/templates/resourceComplianceScore.csl
new file mode 100644
index 00000000..14f6530e
--- /dev/null
+++ b/modules/dashboard/templates/resourceComplianceScore.csl
@@ -0,0 +1,17 @@
+PolicyResources
+| where type == 'microsoft.policyinsights/policystates' and tolower(properties.policyAssignmentScope) has '/providers/Microsoft.Management/managementGroups/RootPrefix_PLACEHOLDER'
+| extend complianceState = tostring(properties.complianceState), resourceId = tolower(properties.resourceId), resourceType = tolower(properties.resourceType), stateWeight = tolong(properties.stateWeight)
+| summarize maxStateWeight = max(stateWeight) by resourceId, resourceType
+| project resourceId, resourceType,
+ complianceState = case(
+ maxStateWeight == 300, "NonCompliant",
+ maxStateWeight == 200, "Compliant",
+ maxStateWeight == 100, "Conflict",
+ maxStateWeight == 50, "Exempt",
+ "UnknownResource"
+ )
+| summarize counts = count() by complianceState
+| summarize compliantCount = sumif(counts, complianceState == 'Compliant' or complianceState == 'Exempt'), nonCompliantCount = sumif(counts, complianceState == 'Conflict' or complianceState == 'NonCompliant')
+| extend totalNum = toint(compliantCount + nonCompliantCount)
+| extend compliancePercentageVal = iff(totalNum == 0, todouble(100), 100 * todouble(compliantCount) / totalNum)
+| project ['Compliance percentage (includes compliant and exempt)'] = strcat(tostring(round(compliancePercentageVal, 1)), '% (', tostring(compliantCount),' out of ', tostring(totalNum), ')')
\ No newline at end of file
diff --git a/modules/dashboard/templates/resourcesOutsideofSafeRegion.csl b/modules/dashboard/templates/resourcesOutsideofSafeRegion.csl
new file mode 100644
index 00000000..9297fef9
--- /dev/null
+++ b/modules/dashboard/templates/resourcesOutsideofSafeRegion.csl
@@ -0,0 +1,13 @@
+policyResources
+| where type == 'microsoft.policyinsights/policystates'
+| extend resourceId = tolower(properties.resourceId), policyAssignmentScope = tolower(properties.policyAssignmentScope), complianceState = tostring(properties.complianceState)
+| where policyAssignmentScope startswith '/providers/Microsoft.Management/managementGroups/RootPrefix_PLACEHOLDER' and complianceState == 'NonCompliant'
+| mv-expand parsed_policy_groups = parse_json(tolower(properties.policyDefinitionGroupNames))
+| where tostring(parsed_policy_groups) == "dashboard-data residency"
+| join kind=inner (
+ resources
+ | where isnotnull(location)
+ | project resourceId=tolower(id), resourceName=name, resourceGroup, resourcelocation = location
+ ) on resourceId
+| project resourcelocation, complianceState
+| summarize counts = count() by resourcelocation
\ No newline at end of file
diff --git a/modules/dashboard/templates/resourcesbyComplianceState.csl b/modules/dashboard/templates/resourcesbyComplianceState.csl
new file mode 100644
index 00000000..805190c9
--- /dev/null
+++ b/modules/dashboard/templates/resourcesbyComplianceState.csl
@@ -0,0 +1,6 @@
+PolicyResources
+| where type == 'microsoft.policyinsights/policystates' and tolower(properties.policyAssignmentScope) has '/providers/Microsoft.Management/managementGroups/RootPrefix_PLACEHOLDER'
+| extend complianceState = tostring(properties.complianceState), resourceId = tolower(properties.resourceId), stateWeight = tolong(properties.stateWeight)
+| summarize max(stateWeight) by resourceId
+| project resourceId, complianceState = iff(max_stateWeight == 300, 'NonCompliant', iff(max_stateWeight == 200, 'Compliant', iff(max_stateWeight == 100 , 'Conflict', iff(max_stateWeight == 50, 'Exempt', 'Unknown'))))
+| summarize counts = count() by complianceState
\ No newline at end of file
diff --git a/modules/resourceGroups/connectivityResourceGroups.bicep b/modules/resourceGroups/connectivityResourceGroups.bicep
new file mode 100644
index 00000000..0a757624
--- /dev/null
+++ b/modules/resourceGroups/connectivityResourceGroups.bicep
@@ -0,0 +1,47 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+/*
+ SUMMARY : Deploys the resource groups for the hub network and network watcher.
+ AUTHOR/S: Cloud for Sovereignty
+*/
+targetScope = 'subscription'
+
+@description('Location to deploy resources.')
+param parDeploymentLocation string
+
+@description('Prefix to use for resource naming.')
+param parDeploymentPrefix string
+
+@description('Suffix to use for resource naming.')
+@maxLength(5)
+param parDeploymentSuffix string
+
+@description('Tags to apply to all created resources.')
+param parTags object
+
+@description('Timestamp with format yyyyMMddTHHmmssZ. Default value set to Execution Timestamp to avoid deployment contention.')
+param parTimestamp string = utcNow()
+
+// Deploy resource groups for the hub network
+module modNetworkingHubResourceGroup '../../dependencies/infra-as-code/bicep/modules/resourceGroup/resourceGroup.bicep' = {
+ name: take('deploy-Hub-Network-Resource-Group-${parTimestamp}', 64)
+ params: {
+ parLocation: parDeploymentLocation
+ parResourceGroupName: '${parDeploymentPrefix}-rg-hub-network-${parDeploymentLocation}${parDeploymentSuffix}'
+ parTags: parTags
+ parTelemetryOptOut: true
+ }
+}
+
+// Deploy resource group for network watcher.
+module modNetworkWatcherResourceGroup '../../dependencies/infra-as-code/bicep/modules/resourceGroup/resourceGroup.bicep' = {
+ name: take('deploy-NetworkWatcher-Resource-Group-${parTimestamp}', 64)
+ params: {
+ parLocation: parDeploymentLocation
+ parResourceGroupName: 'NetworkWatcherRG'
+ parTags: parTags
+ parTelemetryOptOut: true
+ }
+}
+
+output outConnectivityDeploymentLocation string = parDeploymentLocation
diff --git a/modules/resourceGroups/dashboardResourceGroups.bicep b/modules/resourceGroups/dashboardResourceGroups.bicep
new file mode 100644
index 00000000..73f48f28
--- /dev/null
+++ b/modules/resourceGroups/dashboardResourceGroups.bicep
@@ -0,0 +1,34 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+/*
+ SUMMARY : Deploys a resource group for the dashboard resources.
+ AUTHOR/S: Cloud for Sovereignty
+*/
+targetScope = 'subscription'
+
+@description('Location to deploy resources.')
+param parDeploymentLocation string
+
+@description('Prefix to use for resource naming.')
+param parDeploymentPrefix string
+
+@description('Tags to apply to all created resources.')
+param parTags object
+
+@description('Timestamp with format yyyyMMddTHHmmssZ. Default value set to Execution Timestamp to avoid deployment contention.')
+param parTimestamp string = utcNow()
+
+@description('Suffix to use for resource naming.')
+@maxLength(5)
+param parDeploymentSuffix string
+
+// Deploy resource group for dashboard resources
+module modDashboardResourceGroup '../../dependencies/infra-as-code/bicep/modules/resourceGroup/resourceGroup.bicep' = {
+ name: take('deploy-Dashboard-Resource-Group-${parTimestamp}', 64)
+ params: {
+ parLocation: parDeploymentLocation
+ parResourceGroupName: '${parDeploymentPrefix}-rg-dashboards-${parDeploymentLocation}${parDeploymentSuffix}'
+ parTags: parTags
+ parTelemetryOptOut: true
+ }
+}
diff --git a/modules/resourceGroups/identityResourceGroups.bicep b/modules/resourceGroups/identityResourceGroups.bicep
new file mode 100644
index 00000000..9c0cc851
--- /dev/null
+++ b/modules/resourceGroups/identityResourceGroups.bicep
@@ -0,0 +1,36 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+/*
+ SUMMARY : Creates a resource group for identity resources.
+ AUTHOR/S: Cloud for Sovereignty
+*/
+targetScope = 'subscription'
+
+@description('Location to deploy resources.')
+param parDeploymentLocation string
+
+@description('Prefix to use for resource naming.')
+param parDeploymentPrefix string
+
+@description('Suffix to use for resource naming.')
+@maxLength(5)
+param parDeploymentSuffix string
+
+@description('Tags to apply to all created resources.')
+param parTags object
+
+@description('Timestamp with format yyyyMMddTHHmmssZ. Default value set to Execution Timestamp to avoid deployment contention.')
+param parTimestamp string = utcNow()
+
+// Creates resource group
+module modManagedIdentitiesResourceGroup '../../dependencies/infra-as-code/bicep/modules/resourceGroup/resourceGroup.bicep' = {
+ name: take('deploy-Managed-Identity-Resource-Group-${parTimestamp}', 64)
+ params: {
+ parLocation: parDeploymentLocation
+ parResourceGroupName: '${parDeploymentPrefix}-rg-managed-identities-${parDeploymentLocation}${parDeploymentSuffix}'
+ parTags: parTags
+ parTelemetryOptOut: true
+ }
+}
+
+output outIdentityDeploymentLocation string = parDeploymentLocation
diff --git a/modules/resourceGroups/managementResourceGroups.bicep b/modules/resourceGroups/managementResourceGroups.bicep
new file mode 100644
index 00000000..8ba78fed
--- /dev/null
+++ b/modules/resourceGroups/managementResourceGroups.bicep
@@ -0,0 +1,36 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+/*
+ SUMMARY : Deploys a resource group for logging resources.
+ AUTHOR/S: Cloud for Sovereignty
+*/
+targetScope = 'subscription'
+
+@description('Location to deploy resources.')
+param parDeploymentLocation string
+
+@description('Prefix to use for resource naming.')
+param parDeploymentPrefix string
+
+@description('Suffix to use for resource naming.')
+@maxLength(5)
+param parDeploymentSuffix string
+
+@description('Tags to apply to all created resources.')
+param parTags object
+
+@description('Timestamp with format yyyyMMddTHHmmssZ. Default value set to Execution Timestamp to avoid deployment contention.')
+param parTimestamp string = utcNow()
+
+// Deploys resource group
+module modAlzLoggingResourceGroup '../../dependencies/infra-as-code/bicep/modules/resourceGroup/resourceGroup.bicep' = {
+ name: take('deploy-Logging-Resource-Group-${parTimestamp}', 64)
+ params: {
+ parLocation: parDeploymentLocation
+ parResourceGroupName: '${parDeploymentPrefix}-rg-logging-${parDeploymentLocation}${parDeploymentSuffix}'
+ parTags: parTags
+ parTelemetryOptOut: true
+ }
+}
+
+output outManagementDeploymentLocation string = parDeploymentLocation
diff --git a/modules/util/Get-FailedDeploymentDetails.ps1 b/modules/util/Get-FailedDeploymentDetails.ps1
new file mode 100644
index 00000000..82f537da
--- /dev/null
+++ b/modules/util/Get-FailedDeploymentDetails.ps1
@@ -0,0 +1,69 @@
+# Copyright (c) Microsoft Corporation.
+# Licensed under the MIT License.
+<#
+.SYNOPSIS
+ The PowerShell scripts aids is generating the logs for the failed deployments.
+ This script only retrieves errors when an Azure deployment is created.
+ Not all errors will be captured by this script. Specifically those that occur before the deployment is created.
+
+.DESCRIPTION
+Execute this script to share the deployment error logs with Microsoft for troubleshooting
+
+#>
+
+param (
+ $parDeploymentPrefix = $(Read-Host -prompt "Please enter the deployment prefix used for the SLZ deployment."),
+ $parDeploymentSuffix = $(Read-Host -prompt "Please enter the deployment suffix used for the SLZ deployment. Press Enter if no suffix was used for deployment.")
+)
+
+<#
+.DESCRIPTION
+ This function retrieves information about failed Tenant deployments.
+ It filters deployments based on provisioning state, deployment name, and generates logs of failed deployment operations.
+#>
+function Get-FailedTenantDeploymentDetails {
+ param ()
+
+ $varFailedTenantDeployments = Get-AzTenantDeployment | Where-Object { $_.ProvisioningState -eq "Failed" -and $_.DeploymentName -like "$parDeploymentPrefix*" }
+
+ if ($null -ne $varFailedTenantDeployments) {
+ if (Test-Path tenantLogs.txt) {
+ Remove-Item tenantLogs.txt
+ }
+
+ $varFailedTenantDeployments | ForEach-Object {
+ Get-AzTenantDeploymentOperation -DeploymentName $_.DeploymentName | Where-Object { $_.ProvisioningState -eq "Failed" } *>> tenantLogs.txt
+ }
+ }
+
+ Write-Information ">>> Tenant deployments log generation completed." -InformationAction Continue
+}
+
+<#
+.DESCRIPTION
+ This function retrieves information about failed Management Group deployments.
+ It filters deployments based on provisioning state and generates logs of failed deployment operations.
+#>
+function Get-FailedManagementGroupDeploymentDetails {
+ param ()
+
+ $varFailedMGDeployments = Get-AzManagementGroupDeployment -ManagementGroupId "$parDeploymentPrefix$parDeploymentSuffix" | Where-Object { $_.ProvisioningState -eq "Failed" }
+
+ if ($null -ne $varFailedMGDeployments) {
+ if (Test-Path managementgroupLogs.txt) {
+ Remove-Item managementgroupLogs.txt
+ }
+
+ foreach ($varDeployment in $varFailedMGDeployments) {
+ Get-AzManagementGroupDeploymentOperation -ManagementGroupId "$parDeploymentPrefix$parDeploymentSuffix" -DeploymentName $varDeployment.DeploymentName | Where-Object { $_.ProvisioningState -eq "Failed" } *>> managementgroupLogs.txt
+ }
+ }
+
+ Write-Information ">>> Management group deployments log generation completed." -InformationAction Continue
+}
+
+Write-Information ">>> Initiating a login" -InformationAction Continue
+Connect-AzAccount
+
+Get-FailedTenantDeploymentDetails
+Get-FailedManagementGroupDeploymentDetails
diff --git a/modules/util/delete-lock.bicep b/modules/util/delete-lock.bicep
new file mode 100644
index 00000000..9a50e3c1
--- /dev/null
+++ b/modules/util/delete-lock.bicep
@@ -0,0 +1,15 @@
+// ----------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+//
+// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
+// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
+// ----------------------------------------------------------------------------------
+
+resource resLock 'Microsoft.Authorization/locks@2020-05-01' = {
+ name: 'DeleteLock'
+ properties: {
+ level: 'CanNotDelete'
+ }
+}
diff --git a/modules/util/deployment-script.bicep b/modules/util/deployment-script.bicep
new file mode 100644
index 00000000..40696bf1
--- /dev/null
+++ b/modules/util/deployment-script.bicep
@@ -0,0 +1,52 @@
+// ----------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+//
+// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
+// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
+// ----------------------------------------------------------------------------------
+
+@description('Location for the deployment.')
+param parLocation string = resourceGroup().location
+
+@description('Deployment Script Name.')
+param parDeploymentScriptName string
+
+@description('Deployment Script')
+param parDeploymentScript string
+
+@description('Identity for the deployment script to execute in Azure Container Instance.')
+param parDeploymentScriptIdentityId string
+
+@description('Azure CLI Version. Default: 2.32.0')
+param parAzCliVersion string = '2.32.0'
+
+@description('Force Update Tag. Default: utcNow()')
+param parForceUpdateTag string = utcNow()
+
+@description('Script timeout in ISO 8601 format. Default is 1 hour.')
+param parTimeout string = 'PT1H'
+
+@description('Script retention in ISO 8601 format. Default is 1 hour.')
+param parRetentionInterval string = 'PT1H'
+
+resource resDs 'Microsoft.Resources/deploymentScripts@2020-10-01' = {
+ name: parDeploymentScriptName
+ location: parLocation
+ kind: 'AzureCLI'
+ identity: {
+ type: 'UserAssigned'
+ userAssignedIdentities: {
+ '${parDeploymentScriptIdentityId}': {}
+ }
+ }
+ properties: {
+ forceUpdateTag: parForceUpdateTag
+ azCliVersion: parAzCliVersion
+ retentionInterval: parRetentionInterval
+ timeout: parTimeout
+ cleanupPreference: 'OnExpiration'
+ scriptContent: parDeploymentScript
+ }
+}
diff --git a/modules/util/wait-on-arm-subscription.bicep b/modules/util/wait-on-arm-subscription.bicep
new file mode 100644
index 00000000..0a0e2b91
--- /dev/null
+++ b/modules/util/wait-on-arm-subscription.bicep
@@ -0,0 +1,15 @@
+// ----------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+//
+// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
+// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
+// ----------------------------------------------------------------------------------
+
+targetScope = 'subscription'
+
+@description('Dummy input to simulate waiting.')
+param parInput string
+
+output output string = parInput
diff --git a/modules/util/wait-on-arm.bicep b/modules/util/wait-on-arm.bicep
new file mode 100644
index 00000000..e7582d7a
--- /dev/null
+++ b/modules/util/wait-on-arm.bicep
@@ -0,0 +1,13 @@
+// ----------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+//
+// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
+// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
+// ----------------------------------------------------------------------------------
+
+@description('Dummy input to simulate waiting.')
+param parInput string
+
+output output string = parInput
diff --git a/modules/util/wait-subscription.bicep b/modules/util/wait-subscription.bicep
new file mode 100644
index 00000000..73f1910d
--- /dev/null
+++ b/modules/util/wait-subscription.bicep
@@ -0,0 +1,28 @@
+// ----------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+//
+// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
+// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
+// ----------------------------------------------------------------------------------
+
+targetScope = 'subscription'
+
+@description('Loop Counter.')
+@minValue(1)
+param parLoopCounter int
+
+@description('Prefix used for loop.')
+@minLength(2)
+@maxLength(50)
+param parWaitNamePrefix string
+
+@batchSize(1)
+module modWait 'wait-on-arm-subscription.bicep' = [for i in range(1, parLoopCounter): {
+ scope: subscription()
+ name: '${parWaitNamePrefix}-${i}'
+ params: {
+ parInput: 'waitOnArm-${i}'
+ }
+}]
diff --git a/modules/util/wait.bicep b/modules/util/wait.bicep
new file mode 100644
index 00000000..453dd184
--- /dev/null
+++ b/modules/util/wait.bicep
@@ -0,0 +1,25 @@
+// ----------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+//
+// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
+// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
+// ----------------------------------------------------------------------------------
+
+@description('Loop Counter.')
+@minValue(1)
+param parLoopCounter int
+
+@description('Prefix used for loop.')
+@minLength(2)
+@maxLength(50)
+param parWaitNamePrefix string
+
+@batchSize(1)
+module modWait 'wait-on-arm.bicep' = [for i in range(1, parLoopCounter): {
+ name: '${parWaitNamePrefix}-${i}'
+ params: {
+ parInput: 'waitOnArm-${i}'
+ }
+}]
diff --git a/orchestration/bootstrap/bootstrap.bicep b/orchestration/bootstrap/bootstrap.bicep
new file mode 100644
index 00000000..7a08302a
--- /dev/null
+++ b/orchestration/bootstrap/bootstrap.bicep
@@ -0,0 +1,120 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+/*
+ SUMMARY : Deploys the Management Groups and Subscriptions for the Sovereign Landing Zone
+ AUTHOR/S: Cloud for Sovereignty
+*/
+targetScope = 'tenant'
+
+@description('The prefix that will be added to all resources created by this deployment.')
+@minLength(2)
+@maxLength(5)
+param parDeploymentPrefix string
+
+@description('The suffix that will be added to management group suffix name the same way to be added to management group prefix names.')
+@maxLength(5)
+param parDeploymentSuffix string = ''
+
+@description('The name of the top level management group.')
+@minLength(2)
+param parTopLevelManagementGroupName string
+
+@description('The full resource ID of billing scope associated to the EA, MCA or MPA account you wish to create the subscription in.')
+param parSubscriptionBillingScope string
+
+@description('Subscription ID for management group.')
+param parManagementSubscriptionId string = ''
+
+@description('Subscription ID for identity group.')
+param parIdentitySubscriptionId string = ''
+
+@description('Subscription ID for connectivity group.')
+param parConnectivitySubscriptionId string = ''
+
+@description('Tags to be added to deployed resources')
+param parTags object = {}
+
+@description('Array to allow additional or different child Management Groups of Landing Zones Management Group to be deployed. Default: Empty Object')
+param parLandingZoneMgChildren array = []
+
+@description('Optional parent for Management Group hierarchy, used as intermediate root Management Group parent, if specified. If empty, default, will deploy beneath Tenant Root Management Group.')
+param parTopLevelManagementGroupParentId string = ''
+
+var varLandingZoneMgChildren = reduce(parLandingZoneMgChildren, {}, (prev, cur) => union(prev, { '${cur.id}': cur }))
+
+var varPlatformMgChildren = {
+ management: {
+ displayName: 'Management'
+ }
+ connectivity: {
+ displayName: 'Connectivity'
+ }
+ identity: {
+ displayName: 'Identity'
+ }
+}
+
+//This module deploys management groups and creates a hierarchy of management groups
+module modManagementGroups '../../dependencies/infra-as-code/bicep/modules/managementGroups/managementGroups.bicep' = {
+ name: take('${parDeploymentPrefix}-deploy-management-groups${parDeploymentSuffix}', 64)
+ params: {
+ parTelemetryOptOut: true
+ parTopLevelManagementGroupDisplayName: parTopLevelManagementGroupName
+ parTopLevelManagementGroupPrefix: parDeploymentPrefix
+ parTopLevelManagementGroupSuffix: parDeploymentSuffix
+ parLandingZoneMgAlzDefaultsEnable: true
+ parLandingZoneMgConfidentialEnable: true
+ parLandingZoneMgChildren: varLandingZoneMgChildren
+ parTopLevelManagementGroupParentId: parTopLevelManagementGroupParentId
+ parPlatformMgAlzDefaultsEnable: false
+ parPlatformMgChildren: varPlatformMgChildren
+ }
+}
+
+//This module deploys a management subscription and creates an alias for it.
+module modManagementSubscription '../../dependencies/infra-as-code/bicep/CRML/subscriptionAlias/subscriptionAlias.bicep' = if (empty(parManagementSubscriptionId)) {
+ name: take('${parDeploymentPrefix}-deploy-management-subscription${parDeploymentSuffix}', 64)
+ params: {
+ parSubscriptionBillingScope: parSubscriptionBillingScope
+ parSubscriptionName: '${parDeploymentPrefix}-management${parDeploymentSuffix}'
+ parManagementGroupId: modManagementGroups.outputs.outPlatformChildrenManagementGroupIds[0]
+ parSubscriptionOfferType: 'Production'
+ parTenantId: tenant().tenantId
+ parTags: parTags
+ }
+}
+
+//This module deploys a connectivity subscription and creates an alias for it
+module modConnectivitySubscription '../../dependencies/infra-as-code/bicep/CRML/subscriptionAlias/subscriptionAlias.bicep' = if (empty(parConnectivitySubscriptionId)) {
+ name: take('${parDeploymentPrefix}-deploy-connectivity-subscription${parDeploymentSuffix}', 64)
+ params: {
+ parSubscriptionBillingScope: parSubscriptionBillingScope
+ parSubscriptionName: '${parDeploymentPrefix}-connectivity${parDeploymentSuffix}'
+ parManagementGroupId: modManagementGroups.outputs.outPlatformChildrenManagementGroupIds[1]
+ parSubscriptionOfferType: 'Production'
+ parTenantId: tenant().tenantId
+ parTags: parTags
+ }
+}
+
+//This module deploys an identity subscription and creates an alias for it.
+module modIdentitySubscription '../../dependencies/infra-as-code/bicep/CRML/subscriptionAlias/subscriptionAlias.bicep' = if (empty(parIdentitySubscriptionId)) {
+ name: take('${parDeploymentPrefix}-deploy-identity-subscription${parDeploymentSuffix}', 64)
+ params: {
+ parSubscriptionBillingScope: parSubscriptionBillingScope
+ parSubscriptionName: '${parDeploymentPrefix}-identity${parDeploymentSuffix}'
+ parManagementGroupId: modManagementGroups.outputs.outPlatformChildrenManagementGroupIds[2]
+ parSubscriptionOfferType: 'Production'
+ parTenantId: tenant().tenantId
+ parTags: parTags
+ }
+}
+
+output outConnectivitySubscriptionId string = empty(parConnectivitySubscriptionId) ? modConnectivitySubscription.outputs.outSubscriptionId : parConnectivitySubscriptionId
+output outManagementSubscriptionId string = empty(parManagementSubscriptionId) ? modManagementSubscription.outputs.outSubscriptionId : parManagementSubscriptionId
+output outIdentitySubscriptionId string = empty(parIdentitySubscriptionId) ? modIdentitySubscription.outputs.outSubscriptionId : parIdentitySubscriptionId
+output outConnectivitySubscriptionName string = empty(parConnectivitySubscriptionId) ? modConnectivitySubscription.outputs.outSubscriptionName : parConnectivitySubscriptionId
+output outManagementSubscriptionName string = empty(parManagementSubscriptionId) ? modManagementSubscription.outputs.outSubscriptionName : parManagementSubscriptionId
+output outIdentitySubscriptionName string = empty(parIdentitySubscriptionId) ? modIdentitySubscription.outputs.outSubscriptionName : parIdentitySubscriptionId
+output outLandingZoneChildrenManagementGroupIds array = modManagementGroups.outputs.outLandingZoneChildrenManagementGroupIds
+output outPlatformChildrenManagementGroupIds array = modManagementGroups.outputs.outPlatformChildrenManagementGroupIds
diff --git a/orchestration/const/doNotRetryErrorCodes.json b/orchestration/const/doNotRetryErrorCodes.json
new file mode 100644
index 00000000..b1546b8a
--- /dev/null
+++ b/orchestration/const/doNotRetryErrorCodes.json
@@ -0,0 +1,29 @@
+{
+ "description": "This file contains all the error codes for while the retry logic would not be triggered",
+ "errorCodes": [
+ {
+ "code": "RequestDisallowedByPolicy",
+ "errorDescription": "A resource deployment was disallowed by policy"
+ },
+ {
+ "code": "MissingSubscriptionRegistration",
+ "errorDescription": "The subscription must be registered to use the namespace."
+ },
+ {
+ "code": "InvalidPolicySetParameterUpdate",
+ "errorDescription": "The policy contains new parameter(s) which are not present in the existing policy and have no default value. New parameters may be added to a policy only if they have a default value."
+ },
+ {
+ "code": "UndefinedPolicyParameter",
+ "errorDescription": "The policy assignment has the parameter(s) which are not defined in the policy definition"
+ },
+ {
+ "code": "ReferencedResourceNotProvisioned",
+ "errorDescription": "Cannot proceed with operation because the resource is not in Succeeded state."
+ },
+ {
+ "code": "UserNotAuthorized",
+ "errorDescription": "User is not authorized to create a particular resource/subscription"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/orchestration/customCompliance/customCompliance.bicep b/orchestration/customCompliance/customCompliance.bicep
new file mode 100644
index 00000000..b95b0ae7
--- /dev/null
+++ b/orchestration/customCompliance/customCompliance.bicep
@@ -0,0 +1,63 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+/*
+ SUMMARY: This is the main entry point for the deployment of the custom compliance initiative. This deployment will create the following resources:
+ - Custom role definitions
+ - Custom policy initiatives
+ - Custom policy assignments
+ AUTHOR/S: Cloud for Sovereignty
+*/
+targetScope = 'managementGroup'
+
+@description('The prefix that will be added to all resources created by this deployment.')
+@minLength(2)
+@maxLength(5)
+param parDeploymentPrefix string
+
+@description('The suffix that will be added to management group suffix name the same way to be added to management group prefix names.')
+@maxLength(5)
+param parDeploymentSuffix string = ''
+
+@description('Set this to true if any policies in the initiative include a modify effect.')
+param parRequireOwnerRolePermission bool = false
+
+@description('Customer specified policy assignments to the root management group of SLZ. No parameters are supported as part of the assignment. DEFAULT: []')
+param parCustomerPolicySets array = []
+
+// RBAC Role Definitions Variables - Used For Policy Assignments
+var varRBACRoleDefinitionIDs = {
+ owner: '8e3af657-a8ff-443c-a75c-2fe8c4bcb635'
+ reader: 'acdd72a7-3385-48ef-bd42-f606fba81ae7'
+}
+
+var varManagementGroupId = '${parDeploymentPrefix}${parDeploymentSuffix}'
+
+//This module will deploy the custom compliance initiative
+module modRegulatoryCompliance '../../modules/compliance/customCompliance.bicep' = {
+ name: take('${parDeploymentPrefix}-deploy-regulatory-compliance${parDeploymentSuffix}', 64)
+ scope: managementGroup(varManagementGroupId)
+ params: {
+ parDeploymentPrefix: parDeploymentPrefix
+ parDeploymentSuffix: parDeploymentSuffix
+ parIdentityRoleAssignmentsSubs: []
+ parRoleDefinitionIds: [
+ (parRequireOwnerRolePermission ? varRBACRoleDefinitionIDs.owner : varRBACRoleDefinitionIDs.reader)
+ ]
+ }
+}
+
+// The following module is used to deploy the customer specified policies
+module modUserPolicyAssignment '../../modules/compliance/customerPolicySetAssignments.bicep' = [for policy in parCustomerPolicySets: {
+ name: take('${parDeploymentPrefix}-deploy-custpolicyset-assignments-${policy.policySetAssignmentName}${parDeploymentSuffix}', 64)
+ params: {
+ parDeploymentPrefix: parDeploymentPrefix
+ parDeploymentSuffix: parDeploymentSuffix
+ parPolicySetDefinitionId: policy.policySetDefinitionId
+ parPolicySetAssignmentName: policy.policySetAssignmentName
+ parPolicySetAssignmentDisplayName: policy.policySetAssignmentDisplayName
+ parPolicySetAssignmentDescription: policy.policySetAssignmentDescription
+ }
+ dependsOn: [
+ modRegulatoryCompliance
+ ]
+}]
diff --git a/orchestration/dashboard/dashboard.bicep b/orchestration/dashboard/dashboard.bicep
new file mode 100644
index 00000000..d04e1050
--- /dev/null
+++ b/orchestration/dashboard/dashboard.bicep
@@ -0,0 +1,144 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+/*
+ SUMMARY: This is the main deployment file for the SLZ dashboard. It will deploy the dashboard resource group and the dashboard itself.
+ AUTHOR/S: Cloud for Sovereignty
+*/
+targetScope = 'managementGroup'
+
+@description('The prefix that will be added to all resources created by this deployment. DEFAULT: mcfs')
+@minLength(2)
+@maxLength(5)
+param parDeploymentPrefix string
+
+@description('The suffix that will be added to management group suffix name the same way to be added to management group prefix names.')
+@maxLength(5)
+param parDeploymentSuffix string = ''
+
+@description('Deployment location')
+@allowed([
+ 'asia'
+ 'asiapacific'
+ 'australia'
+ 'australiacentral'
+ 'australiacentral2'
+ 'australiaeast'
+ 'australiasoutheast'
+ 'brazil'
+ 'brazilsouth'
+ 'brazilsoutheast'
+ 'canada'
+ 'canadacentral'
+ 'canadaeast'
+ 'centralindia'
+ 'centralus'
+ 'centraluseuap'
+ 'centralusstage'
+ 'eastasia'
+ 'eastasiastage'
+ 'eastus'
+ 'eastus2'
+ 'eastus2euap'
+ 'eastus2stage'
+ 'eastusstage'
+ 'eastusstg'
+ 'europe'
+ 'france'
+ 'francecentral'
+ 'francesouth'
+ 'germany'
+ 'germanynorth'
+ 'germanywestcentral'
+ 'global'
+ 'india'
+ 'japan'
+ 'japaneast'
+ 'japanwest'
+ 'jioindiacentral'
+ 'jioindiawest'
+ 'korea'
+ 'koreacentral'
+ 'koreasouth'
+ 'northcentralus'
+ 'northcentralusstage'
+ 'northeurope'
+ 'norway'
+ 'norwayeast'
+ 'norwaywest'
+ 'qatarcentral'
+ 'singapore'
+ 'southafrica'
+ 'southafricanorth'
+ 'southafricawest'
+ 'southcentralus'
+ 'southcentralusstage'
+ 'southcentralusstg'
+ 'southeastasia'
+ 'southeastasiastage'
+ 'southindia'
+ 'swedencentral'
+ 'switzerland'
+ 'switzerlandnorth'
+ 'switzerlandwest'
+ 'uae'
+ 'uaecentral'
+ 'uaenorth'
+ 'uk'
+ 'uksouth'
+ 'ukwest'
+ 'unitedstates'
+ 'unitedstateseuap'
+ 'westcentralus'
+ 'westeurope'
+ 'westindia'
+ 'westus'
+ 'westus2'
+ 'westus2stage'
+ 'westus3'
+ 'westusstage'
+])
+param parDeploymentLocation string
+
+@description('The name of the country or agency SLZ is being deployed for. DEFAULT: Country')
+param parCustomer string = 'Country'
+
+@description('Tags to be added to deployed resources')
+param parTags object = {}
+
+@description('Subscription ID for management group.')
+param parManagementSubscriptionId string
+
+var varDashboardResourceGroupName = '${parDeploymentPrefix}-rg-dashboards-${parDeploymentLocation}${parDeploymentSuffix}'
+
+// Deploy dashboard resource group
+module modDashboardResourceGroup '../../modules/resourceGroups/dashboardResourceGroups.bicep' = {
+ name: take('deploy-Dashboard-Resource-Group-${varDashboardResourceGroupName}', 64)
+ scope: subscription(parManagementSubscriptionId)
+ params: {
+ parDeploymentLocation: parDeploymentLocation
+ parDeploymentPrefix: parDeploymentPrefix
+ parDeploymentSuffix: parDeploymentSuffix
+ parTags: parTags
+ }
+}
+
+var varDashboardDisplayName = '${parDeploymentPrefix}-Sovereign-Landing-Zone-Dashboard-Preview-${parDeploymentLocation}${parDeploymentSuffix}'
+
+// Deploy dashboard
+module modDashboard '../../modules/dashboard/dashboard.bicep' = {
+ name: take('deploy-${parDeploymentPrefix}-dashboard${parDeploymentSuffix}', 64)
+ scope: resourceGroup(parManagementSubscriptionId, varDashboardResourceGroupName)
+ params: {
+ parCountryOrAgencyName: parCustomer
+ parLocation: parDeploymentLocation
+ parDashboardName: varDashboardDisplayName
+ parTags: parTags
+ parDeploymentPrefix: parDeploymentPrefix
+ }
+ dependsOn: [
+ modDashboardResourceGroup
+ ]
+}
+
+output outDashboardResourceGroupName string = varDashboardResourceGroupName
+output outDashboardDisplayName string = varDashboardDisplayName
diff --git a/orchestration/defaultCompliance/defaultCompliance.bicep b/orchestration/defaultCompliance/defaultCompliance.bicep
new file mode 100644
index 00000000..193f8893
--- /dev/null
+++ b/orchestration/defaultCompliance/defaultCompliance.bicep
@@ -0,0 +1,123 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+/*
+ SUMMARY: This file deploys following:
+ - the ALZ default policies if the parDeployAlzDefaultPolicies parameter is set to true
+ - the customer specified policies to the management group. The customer specified policies are specified in the parCustomerPolicies parameter.
+ - the policy exemptions to the management group. The policy exemptions are specified in the parPolicyExemptions parameter.
+ - the policy assignments to the management group. The policy assignments are specified in the parPolicyAssignments parameter.
+ AUTHOR/S: Cloud for Sovereignty
+*/
+targetScope = 'managementGroup'
+
+@description('The prefix that will be added to all resources created by this deployment.')
+@minLength(2)
+@maxLength(5)
+param parDeploymentPrefix string
+
+@description('The suffix that will be added to management group suffix name the same way to be added to management group prefix names.')
+@maxLength(5)
+param parDeploymentSuffix string = ''
+
+@description('The resource ID for the DDoS plan.')
+param parDdosPlanResourceId string = ''
+
+@description('The allowed Azure regions where resources are allowed to be deployed. Allowed values : asia, asiapacific, australia, australiacentral, australiacentral2, australiaeast, australiasoutheast, brazil, brazilsouth, brazilsoutheast, canada, canadacentral, canadaeast, centralindia, centralus, centraluseuap, centralusstage, eastasia, eastasiastage, eastus, eastus2, eastus2euap, eastus2stage, eastusstage, eastusstg, europe, france, francecentral, francesouth, germany, germanynorth, germanywestcentral, global, india, japan, japaneast, japanwest, jioindiacentral, jioindiawest, korea, koreacentral, koreasouth, northcentralus, northcentralusstage, northeurope, norway, norwayeast, norwaywest, qatarcentral, singapore, southafrica, southafricanorth, southafricawest, southcentralus, southcentralusstage, southcentralusstg, southeastasia, southeastasiastage, southindia, swedencentral, switzerland, switzerlandnorth, switzerlandwest, uae, uaecentral, uaenorth, uk, uksouth, ukwest, unitedstates, unitedstateseuap, westcentralus, westeurope, westindia, westus, westus2, westus2stage, westus3, westusstage')
+param parAllowedLocations array
+
+@description('The allowed Azure regions where confidential computing resources are allowed to be deployed. Allowed values : asia, asiapacific, australia, australiacentral, australiacentral2, australiaeast, australiasoutheast, brazil, brazilsouth, brazilsoutheast, canada, canadacentral, canadaeast, centralindia, centralus, centraluseuap, centralusstage, eastasia, eastasiastage, eastus, eastus2, eastus2euap, eastus2stage, eastusstage, eastusstg, europe, france, francecentral, francesouth, germany, germanynorth, germanywestcentral, global, india, japan, japaneast, japanwest, jioindiacentral, jioindiawest, korea, koreacentral, koreasouth, northcentralus, northcentralusstage, northeurope, norway, norwayeast, norwaywest, qatarcentral, singapore, southafrica, southafricanorth, southafricawest, southcentralus, southcentralusstage, southcentralusstg, southeastasia, southeastasiastage, southindia, swedencentral, switzerland, switzerlandnorth, switzerlandwest, uae, uaecentral, uaenorth, uk, uksouth, ukwest, unitedstates, unitedstateseuap, westcentralus, westeurope, westindia, westus, westus2, westus2stage, westus3, westusstage')
+param parAllowedLocationsForConfidentialComputing array
+
+@description('The ID for the Log Analytics workspace that was created to centralize log ingest.')
+param parLogAnalyticsWorkspaceId string = ''
+
+@description('Set to true to deploy ALZ default policies, otherwise false. DEFAULT: false')
+param parDeployAlzDefaultPolicies bool = false
+
+@description('The region where the Log Analytics Workspace & Automation Account are deployed.')
+param parLogAnalyticsWorkSpaceAndAutomationAccountLocation string = ''
+
+@description('Number of days of log retention for Log Analytics Workspace.')
+param parLogAnalyticsWorkspaceLogRetentionInDays string
+
+@description('Automation account name.')
+param parAutomationAccountName string = ''
+
+@description('An e-mail address that you want Microsoft Defender for Cloud alerts to be sent to.')
+param parMsDefenderForCloudEmailSecurityContact string = ''
+
+@description('Resource ID of the Resource Group that conatin the Private DNS Zones. If left empty, the policy Deploy-Private-DNS-Zones will not be assigned to the corp Management Group.')
+param parPrivateDnsResourceGroupId string = ''
+
+@description('Effect type for all policy definitions')
+param parPolicyEffect string = 'Deny'
+
+var varPolicyAssignmentScopeName = '${parDeploymentPrefix}${parDeploymentSuffix}'
+var varPolicyExemptionConfidentialOnlineManagementGroup = '${parDeploymentPrefix}-landingzones-confidential-online${parDeploymentSuffix}'
+var varPolicyExemptionConfidentialCorpManagementGroup = '${parDeploymentPrefix}-landingzones-confidential-corp${parDeploymentSuffix}'
+
+// The following module is used to deploy the SLZ Global Policies and the SLZ Global Assignment
+module modRegulatoryCompliance '../../modules/compliance/defaultCompliance.bicep' = {
+ name: take('${parDeploymentPrefix}-deploy-regulatory-compliance${parDeploymentSuffix}', 64)
+ params: {
+ parDeploymentPrefix: parDeploymentPrefix
+ parDeploymentSuffix: parDeploymentSuffix
+ parAllowedLocations: parAllowedLocations
+ parAllowedLocationsForConfidentialComputing: parAllowedLocationsForConfidentialComputing
+ parPolicyEffect: parPolicyEffect
+ }
+}
+
+// The following module is used to deploy the ALZ default policies
+module modAlzPolicyAssignments '../../dependencies/infra-as-code/bicep/modules/policy/assignments/alzDefaults/alzDefaultPolicyAssignments.bicep' = if (parDeployAlzDefaultPolicies) {
+ name: take('${parDeploymentPrefix}-deploy-alz-default-policies${parDeploymentSuffix}', 64)
+ params: {
+ parTopLevelManagementGroupPrefix: parDeploymentPrefix
+ parTopLevelManagementGroupSuffix: parDeploymentSuffix
+ parLogAnalyticsWorkSpaceAndAutomationAccountLocation: parLogAnalyticsWorkSpaceAndAutomationAccountLocation
+ parLogAnalyticsWorkspaceResourceId: parLogAnalyticsWorkspaceId
+ parLogAnalyticsWorkspaceLogRetentionInDays: parLogAnalyticsWorkspaceLogRetentionInDays
+ parAutomationAccountName: parAutomationAccountName
+ parMsDefenderForCloudEmailSecurityContact: parMsDefenderForCloudEmailSecurityContact
+ parDdosProtectionPlanId: parDdosPlanResourceId
+ parPrivateDnsResourceGroupId: parPrivateDnsResourceGroupId
+ parDisableAlzDefaultPolicies: !parDeployAlzDefaultPolicies
+ }
+ dependsOn: [
+ modRegulatoryCompliance
+ ]
+}
+
+// The following module is used to deploy the policy exemptions
+module modPolicyExemptionsConfidentialOnline '../../modules/compliance/policyExemptions.bicep' = {
+ dependsOn: [
+ modRegulatoryCompliance
+ ]
+ scope: managementGroup(varPolicyExemptionConfidentialOnlineManagementGroup)
+ name: take('${parDeploymentPrefix}-deploy-policy-exemptions${parDeploymentSuffix}', 64)
+ params: {
+ parPolicyAssignmentScopeName: varPolicyAssignmentScopeName
+ parPolicyDefinitionReferenceIds: [ 'AllowedLocationsForResourceGroups', 'AllowedLocations' ]
+ parPolicyAssignmentName: modRegulatoryCompliance.outputs.outSlzGlobalAssignmentName
+ parExemptionName: 'Confidential-Online-Location-Exemption.${modRegulatoryCompliance.outputs.outSlzGlobalVersion}'
+ parExemptionDisplayName: 'Confidential Online Location Exemption ${modRegulatoryCompliance.outputs.outSlzGlobalVersion}'
+ parDescription: 'Exempt the confidential online management group from the SLZ Global Policies location policies. The confidential management groups have their own location restrictions and this may result in a conflict if both sets are included.'
+ }
+}
+
+// The following module is used to deploy the policy exemptions
+module modPolicyExemptionsConfidentialCorp '../../modules/compliance/policyExemptions.bicep' = {
+ dependsOn: [
+ modRegulatoryCompliance
+ ]
+ scope: managementGroup(varPolicyExemptionConfidentialCorpManagementGroup)
+ name: take('${parDeploymentPrefix}-deploy-policy-exemptions${parDeploymentSuffix}', 64)
+ params: {
+ parPolicyAssignmentScopeName: varPolicyAssignmentScopeName
+ parPolicyDefinitionReferenceIds: [ 'AllowedLocationsForResourceGroups', 'AllowedLocations' ]
+ parPolicyAssignmentName: modRegulatoryCompliance.outputs.outSlzGlobalAssignmentName
+ parExemptionName: 'Confidential-Corp-Location-Exemption.${modRegulatoryCompliance.outputs.outSlzGlobalVersion}'
+ parExemptionDisplayName: 'Confidential Corp Location Exemption ${modRegulatoryCompliance.outputs.outSlzGlobalVersion}'
+ parDescription: 'Exempt the confidential corp management group from the SLZ Global Policies location policies. The confidential management groups have their own location restrictions and this may result in a conflict if both sets are included.'
+ }
+}
diff --git a/orchestration/moveSubscription/moveSubscription.bicep b/orchestration/moveSubscription/moveSubscription.bicep
new file mode 100644
index 00000000..e9fb9a78
--- /dev/null
+++ b/orchestration/moveSubscription/moveSubscription.bicep
@@ -0,0 +1,64 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+/*
+ SUMMARY: This file moves the deployed subscriptions to the correct management groups.
+ AUTHOR/S: Cloud for Sovereignty
+*/
+targetScope = 'managementGroup'
+
+@description('The prefix that will be added to all resources created by this deployment.')
+@minLength(2)
+@maxLength(5)
+param parDeploymentPrefix string
+
+@description('The suffix that will be added to management group suffix name the same way to be added to management group prefix names.')
+@maxLength(5)
+param parDeploymentSuffix string = ''
+
+@description('Subscription ID for management group.')
+param parManagementSubscriptionId string
+
+@description('Subscription ID for identity group.')
+param parIdentitySubscriptionId string
+
+@description('Subscription ID for connectivity group.')
+param parConnectivitySubscriptionId string
+
+var varManagementGroupId = '${parDeploymentPrefix}${parDeploymentSuffix}'
+module modConnectivitySubscriptionPlacement '../../dependencies/infra-as-code/bicep/modules/subscriptionPlacement/subscriptionPlacement.bicep' = {
+ name: take('${parDeploymentPrefix}-deploy-Connectivity-Subscription-Placement${parDeploymentSuffix}', 64)
+ scope: managementGroup(varManagementGroupId)
+ params: {
+ parTargetManagementGroupId: '${parDeploymentPrefix}-platform-connectivity${parDeploymentSuffix}'
+ parSubscriptionIds: [
+ parConnectivitySubscriptionId
+ ]
+ parTelemetryOptOut: true
+ }
+}
+
+// Move Subscription to management management group
+module modManagementSubscriptionPlacement '../../dependencies/infra-as-code/bicep/modules/subscriptionPlacement/subscriptionPlacement.bicep' = {
+ name: take('${parDeploymentPrefix}-deploy-Management-Subscription-Placement', 64)
+ scope: managementGroup(varManagementGroupId)
+ params: {
+ parTargetManagementGroupId: '${parDeploymentPrefix}-platform-management${parDeploymentSuffix}'
+ parSubscriptionIds: [
+ parManagementSubscriptionId
+ ]
+ parTelemetryOptOut: true
+ }
+}
+
+// Move Subscription to identity management group
+module modIdentitySubscriptionPlacement '../../dependencies/infra-as-code/bicep/modules/subscriptionPlacement/subscriptionPlacement.bicep' = {
+ name: take('${parDeploymentPrefix}-deploy-Identity-Subscription-Placement${parDeploymentSuffix}', 64)
+ scope: managementGroup(varManagementGroupId)
+ params: {
+ parTargetManagementGroupId: '${parDeploymentPrefix}-platform-identity${parDeploymentSuffix}'
+ parSubscriptionIds: [
+ parIdentitySubscriptionId
+ ]
+ parTelemetryOptOut: true
+ }
+}
diff --git a/orchestration/policyExemption/policyExemption.bicep b/orchestration/policyExemption/policyExemption.bicep
new file mode 100644
index 00000000..09af8d16
--- /dev/null
+++ b/orchestration/policyExemption/policyExemption.bicep
@@ -0,0 +1,51 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+/*
+ SUMMARY: This file deploys policy exemptions to a management group.
+ AUTHOR/S: Cloud for Sovereignty
+*/
+targetScope = 'managementGroup'
+
+@description('The prefix that will be added to all resources created by this deployment.')
+@minLength(2)
+@maxLength(5)
+param parDeploymentPrefix string
+
+@description('The suffix that will be added to management group suffix name the same way to be added to management group prefix names.')
+@maxLength(5)
+param parDeploymentSuffix string = ''
+
+@description('Policy Assignment Name')
+param parPolicyAssignmentName string
+
+@description('Policy Assignment Scope Name')
+param parPolicyAssignmentScopeName string = parPolicyExemptionManagementGroup
+
+@description('Reference ids of Policies to be exempted')
+param parPolicyDefinitionReferenceIds array
+
+@description('Exemption Name')
+param parPolicyExemptionName string
+
+@description('Exemption Display Name')
+param parPolicyExemptionDisplayName string
+
+@description('Description')
+param parDescription string
+
+@description('Management Group for policy exemption')
+param parPolicyExemptionManagementGroup string
+
+// Deploy policy exemptions
+module modPolicyExemptions '../../modules/compliance/policyExemptions.bicep' = {
+ scope: managementGroup(parPolicyExemptionManagementGroup)
+ name: take('${parDeploymentPrefix}-policy-exemptions${parDeploymentSuffix}', 64)
+ params: {
+ parPolicyDefinitionReferenceIds: parPolicyDefinitionReferenceIds
+ parPolicyAssignmentName: parPolicyAssignmentName
+ parPolicyAssignmentScopeName: parPolicyAssignmentScopeName
+ parExemptionName: parPolicyExemptionName
+ parExemptionDisplayName: parPolicyExemptionDisplayName
+ parDescription: parDescription
+ }
+}
diff --git a/orchestration/policyInstallation/alz-DefaultPolicySetDefinitions.txt b/orchestration/policyInstallation/alz-DefaultPolicySetDefinitions.txt
new file mode 100644
index 00000000..94e8d50b
--- /dev/null
+++ b/orchestration/policyInstallation/alz-DefaultPolicySetDefinitions.txt
@@ -0,0 +1,1174 @@
+//This bicep file includes auto-generated code. Please dont make any changes these file manually.
+
+targetScope = 'managementGroup'
+
+@description('The management group scope to which the policy definitions are to be created at. DEFAULT VALUE = "alz"')
+param parTargetManagementGroupId string = 'alz'
+
+var varTargetManagementGroupResourceId = tenantResourceId('Microsoft.Management/managementGroups', parTargetManagementGroupId)
+// // DO NOT Remove This Line !!!
+var varCustomPolicySetDefinitionsArray = [
+{
+ name: 'Deny-PublicPaaSEndpoints'
+ libSetDefinition: loadJsonContent('lib/policy_set_definitions/policy_set_definition_es_Deny-PublicPaaSEndpoints.json')
+ libSetChildDefinitions: [
+ {
+ definitionReferenceId: 'ACRDenyPaasPublicIP'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/0fdf0491-d080-4575-b627-ad0e843cba0f'
+ definitionParameters: varPolicySetDefinitionEsDenyPublicPaaSEndpointsParameters.ACRDenyPaasPublicIP.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'AFSDenyPaasPublicIP'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/21a8cd35-125e-4d13-b82d-2e19b7208bb7'
+ definitionParameters: varPolicySetDefinitionEsDenyPublicPaaSEndpointsParameters.AFSDenyPaasPublicIP.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'AKSDenyPaasPublicIP'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/040732e8-d947-40b8-95d6-854c95024bf8'
+ definitionParameters: varPolicySetDefinitionEsDenyPublicPaaSEndpointsParameters.AKSDenyPaasPublicIP.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'BatchDenyPublicIP'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/74c5a0ae-5e48-4738-b093-65e23a060488'
+ definitionParameters: varPolicySetDefinitionEsDenyPublicPaaSEndpointsParameters.BatchDenyPublicIP.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'CosmosDenyPaasPublicIP'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/797b37f7-06b8-444c-b1ad-fc62867f335a'
+ definitionParameters: varPolicySetDefinitionEsDenyPublicPaaSEndpointsParameters.CosmosDenyPaasPublicIP.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'KeyVaultDenyPaasPublicIP'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/55615ac9-af46-4a59-874e-391cc3dfb490'
+ definitionParameters: varPolicySetDefinitionEsDenyPublicPaaSEndpointsParameters.KeyVaultDenyPaasPublicIP.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'MySQLFlexDenyPublicIP'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/c9299215-ae47-4f50-9c54-8a392f68a052'
+ definitionParameters: varPolicySetDefinitionEsDenyPublicPaaSEndpointsParameters.MySQLFlexDenyPublicIP.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'PostgreSQLFlexDenyPublicIP'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/5e1de0e3-42cb-4ebc-a86d-61d0c619ca48'
+ definitionParameters: varPolicySetDefinitionEsDenyPublicPaaSEndpointsParameters.PostgreSQLFlexDenyPublicIP.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'SqlServerDenyPaasPublicIP'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/1b8ca024-1d5c-4dec-8995-b1a932b41780'
+ definitionParameters: varPolicySetDefinitionEsDenyPublicPaaSEndpointsParameters.SqlServerDenyPaasPublicIP.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'StorageDenyPaasPublicIP'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/34c877ad-507e-4c82-993e-3452a6e0ad3c'
+ definitionParameters: varPolicySetDefinitionEsDenyPublicPaaSEndpointsParameters.StorageDenyPaasPublicIP.parameters
+ definitionGroups: []
+ }
+ ]
+ }
+
+{
+ name: 'Deploy-Diagnostics-LogAnalytics'
+ libSetDefinition: loadJsonContent('lib/policy_set_definitions/policy_set_definition_es_Deploy-Diagnostics-LogAnalytics.json')
+ libSetChildDefinitions: [
+ {
+ definitionReferenceId: 'ACIDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-ACI'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.ACIDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'ACRDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-ACR'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.ACRDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'AKSDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/6c66c325-74c8-42fd-a286-a74b0e2939d8'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.AKSDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'AnalysisServiceDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-AnalysisService'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.AnalysisServiceDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'APIforFHIRDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-ApiForFHIR'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.APIforFHIRDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'APIMgmtDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-APIMgmt'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.APIMgmtDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'ApplicationGatewayDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-ApplicationGateway'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.ApplicationGatewayDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'AppServiceDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-WebServerFarm'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.AppServiceDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'AppServiceWebappDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-Website'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.AppServiceWebappDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'AutomationDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-AA'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.AutomationDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'AVDScalingPlansDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-AVDScalingPlans'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.AVDScalingPlansDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'BastionDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-Bastion'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.BastionDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'BatchDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/c84e5349-db6d-4769-805e-e14037dab9b5'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.BatchDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'CDNEndpointsDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-CDNEndpoints'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.CDNEndpointsDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'CognitiveServicesDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-CognitiveServices'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.CognitiveServicesDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'CosmosDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-CosmosDB'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.CosmosDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DatabricksDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-Databricks'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.DatabricksDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DataExplorerClusterDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-DataExplorerCluster'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.DataExplorerClusterDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DataFactoryDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-DataFactory'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.DataFactoryDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DataLakeAnalyticsDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-DLAnalytics'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.DataLakeAnalyticsDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DataLakeStoreDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/d56a5a7c-72d7-42bc-8ceb-3baf4c0eae03'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.DataLakeStoreDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'EventGridSubDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-EventGridSub'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.EventGridSubDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'EventGridTopicDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-EventGridTopic'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.EventGridTopicDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'EventHubDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/1f6e93e8-6b31-41b1-83f6-36e449a42579'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.EventHubDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'EventSystemTopicDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-EventGridSystemTopic'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.EventSystemTopicDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'ExpressRouteDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-ExpressRoute'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.ExpressRouteDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'FirewallDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-Firewall'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.FirewallDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'FrontDoorDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-FrontDoor'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.FrontDoorDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'FunctionAppDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-Function'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.FunctionAppDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'HDInsightDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-HDInsight'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.HDInsightDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'IotHubDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-iotHub'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.IotHubDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'KeyVaultDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/bef3f64c-5290-43b7-85b0-9b254eef4c47'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.KeyVaultDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'LoadBalancerDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-LoadBalancer'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.LoadBalancerDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'LogAnalyticsDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-LogAnalytics'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.LogAnalyticsDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'LogicAppsISEDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-LogicAppsISE'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.LogicAppsISEDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'LogicAppsWFDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/b889a06c-ec72-4b03-910a-cb169ee18721'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.LogicAppsWFDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'MariaDBDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-MariaDB'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.MariaDBDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'MediaServiceDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-MediaService'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.MediaServiceDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'MlWorkspaceDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-MlWorkspace'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.MlWorkspaceDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'MySQLDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-MySQL'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.MySQLDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'NetworkNICDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-NIC'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.NetworkNICDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'NetworkPublicIPNicDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/752154a7-1e0f-45c6-a880-ac75a7e4f648'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.NetworkPublicIPNicDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'NetworkSecurityGroupsDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-NetworkSecurityGroups'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.NetworkSecurityGroupsDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'PostgreSQLDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-PostgreSQL'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.PostgreSQLDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'PowerBIEmbeddedDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-PowerBIEmbedded'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.PowerBIEmbeddedDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'RecoveryVaultDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/c717fb0c-d118-4c43-ab3d-ece30ac81fb3'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.RecoveryVaultDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'RedisCacheDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-RedisCache'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.RedisCacheDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'RelayDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-Relay'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.RelayDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'SearchServicesDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/08ba64b8-738f-4918-9686-730d2ed79c7d'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.SearchServicesDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'ServiceBusDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/04d53d87-841c-4f23-8a5b-21564380b55e'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.ServiceBusDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'SignalRDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-SignalR'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.SignalRDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'SQLDatabaseDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/b79fa14e-238a-4c2d-b376-442ce508fc84'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.SQLDatabaseDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'SQLElasticPoolsDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-SQLElasticPools'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.SQLElasticPoolsDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'SQLMDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-SQLMI'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.SQLMDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'StorageAccountBlobServicesDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/b4fe1a3b-0715-4c6c-a5ea-ffc33cf823cb'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.StorageAccountBlobServicesDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'StorageAccountDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/59759c62-9a22-4cdf-ae64-074495983fef'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.StorageAccountDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'StorageAccountFileServicesDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/25a70cc8-2bd4-47f1-90b6-1478e4662c96'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.StorageAccountFileServicesDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'StorageAccountQueueServicesDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/7bd000e3-37c7-4928-9f31-86c4b77c5c45'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.StorageAccountQueueServicesDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'StorageAccountTableServicesDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/2fb86bf3-d221-43d1-96d1-2434af34eaa0'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.StorageAccountTableServicesDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'StreamAnalyticsDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/237e0f7e-b0e8-4ec4-ad46-8c12cb66d673'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.StreamAnalyticsDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'TimeSeriesInsightsDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-TimeSeriesInsights'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.TimeSeriesInsightsDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'TrafficManagerDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-TrafficManager'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.TrafficManagerDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'VirtualMachinesDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-VM'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.VirtualMachinesDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'VirtualNetworkDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-VirtualNetwork'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.VirtualNetworkDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'VMSSDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-VMSS'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.VMSSDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'VNetGWDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-VNetGW'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.VNetGWDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'WVDAppGroupDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-WVDAppGroup'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.WVDAppGroupDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'WVDHostPoolsDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-WVDHostPools'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.WVDHostPoolsDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'WVDWorkspaceDeployDiagnosticLogDeployLogAnalytics'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Diagnostics-WVDWorkspace'
+ definitionParameters: varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters.WVDWorkspaceDeployDiagnosticLogDeployLogAnalytics.parameters
+ definitionGroups: []
+ }
+ ]
+ }
+
+{
+ name: 'Deploy-MDFC-Config'
+ libSetDefinition: loadJsonContent('lib/policy_set_definitions/policy_set_definition_es_Deploy-MDFC-Config.json')
+ libSetChildDefinitions: [
+ {
+ definitionReferenceId: 'ascExport'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/ffb6f416-7bd2-4488-8828-56585fef2be9'
+ definitionParameters: varPolicySetDefinitionEsDeployMDFCConfigParameters.ascExport.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'defenderForAppServices'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/b40e7bcd-a1e5-47fe-b9cf-2f534d0bfb7d'
+ definitionParameters: varPolicySetDefinitionEsDeployMDFCConfigParameters.defenderForAppServices.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'defenderForArm'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/b7021b2b-08fd-4dc0-9de7-3c6ece09faf9'
+ definitionParameters: varPolicySetDefinitionEsDeployMDFCConfigParameters.defenderForArm.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'defenderforContainers'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/c9ddb292-b203-4738-aead-18e2716e858f'
+ definitionParameters: varPolicySetDefinitionEsDeployMDFCConfigParameters.defenderforContainers.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'defenderForCosmosDbs'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/82bf5b87-728b-4a74-ba4d-6123845cf542'
+ definitionParameters: varPolicySetDefinitionEsDeployMDFCConfigParameters.defenderForCosmosDbs.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'defenderForDns'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/2370a3c1-4a25-4283-a91a-c9c1a145fb2f'
+ definitionParameters: varPolicySetDefinitionEsDeployMDFCConfigParameters.defenderForDns.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'defenderForKeyVaults'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/1f725891-01c0-420a-9059-4fa46cb770b7'
+ definitionParameters: varPolicySetDefinitionEsDeployMDFCConfigParameters.defenderForKeyVaults.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'defenderForOssDb'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/44433aa3-7ec2-4002-93ea-65c65ff0310a'
+ definitionParameters: varPolicySetDefinitionEsDeployMDFCConfigParameters.defenderForOssDb.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'defenderForSqlPaas'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/b99b73e7-074b-4089-9395-b7236f094491'
+ definitionParameters: varPolicySetDefinitionEsDeployMDFCConfigParameters.defenderForSqlPaas.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'defenderForSqlServerVirtualMachines'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/50ea7265-7d8c-429e-9a7d-ca1f410191c3'
+ definitionParameters: varPolicySetDefinitionEsDeployMDFCConfigParameters.defenderForSqlServerVirtualMachines.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'defenderForStorageAccounts'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/74c30959-af11-47b3-9ed2-a26e03f427a3'
+ definitionParameters: varPolicySetDefinitionEsDeployMDFCConfigParameters.defenderForStorageAccounts.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'defenderForVM'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/8e86a5b6-b9bd-49d1-8e21-4bb8a0862222'
+ definitionParameters: varPolicySetDefinitionEsDeployMDFCConfigParameters.defenderForVM.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'securityEmailContact'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-ASC-SecurityContacts'
+ definitionParameters: varPolicySetDefinitionEsDeployMDFCConfigParameters.securityEmailContact.parameters
+ definitionGroups: []
+ }
+ ]
+ }
+
+{
+ name: 'Deploy-Private-DNS-Zones'
+ libSetDefinition: loadJsonContent('lib/policy_set_definitions/policy_set_definition_es_Deploy-Private-DNS-Zones.json')
+ libSetChildDefinitions: [
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-ACR'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/e9585a95-5b8c-4d03-b193-dc7eb5ac4c32'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-ACR'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-App'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/7a860e27-9ca2-4fc6-822d-c2d248c300df'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-App'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-AppServices'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/b318f84a-b872-429b-ac6d-a01b96814452'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-AppServices'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-Automation-DSCHybrid'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/6dd01e4f-1be1-4e80-9d0b-d109e04cb064'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-Automation-DSCHybrid'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-Automation-Webhook'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/6dd01e4f-1be1-4e80-9d0b-d109e04cb064'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-Automation-Webhook'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-Batch'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/4ec38ebc-381f-45ee-81a4-acbc4be878f8'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-Batch'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-CognitiveSearch'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/fbc14a67-53e4-4932-abcc-2049c6706009'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-CognitiveSearch'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-CognitiveServices'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/c4bc6f10-cb41-49eb-b000-d5ab82e2a091'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-CognitiveServices'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-Cosmos-Cassandra'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/a63cc0bd-cda4-4178-b705-37dc439d3e0f'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-Cosmos-Cassandra'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-Cosmos-Gremlin'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/a63cc0bd-cda4-4178-b705-37dc439d3e0f'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-Cosmos-Gremlin'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-Cosmos-MongoDB'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/a63cc0bd-cda4-4178-b705-37dc439d3e0f'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-Cosmos-MongoDB'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-Cosmos-SQL'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/a63cc0bd-cda4-4178-b705-37dc439d3e0f'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-Cosmos-SQL'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-Cosmos-Table'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/a63cc0bd-cda4-4178-b705-37dc439d3e0f'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-Cosmos-Table'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-DataFactory'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/86cd96e1-1745-420d-94d4-d3f2fe415aa4'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-DataFactory'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-DataFactory-Portal'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/86cd96e1-1745-420d-94d4-d3f2fe415aa4'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-DataFactory-Portal'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-DiskAccess'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/bc05b96c-0b36-4ca9-82f0-5c53f96ce05a'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-DiskAccess'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-EventGridDomains'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/d389df0a-e0d7-4607-833c-75a6fdac2c2d'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-EventGridDomains'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-EventGridTopics'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/baf19753-7502-405f-8745-370519b20483'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-EventGridTopics'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-EventHubNamespace'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/ed66d4f5-8220-45dc-ab4a-20d1749c74e6'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-EventHubNamespace'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-File-Sync'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/06695360-db88-47f6-b976-7500d4297475'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-File-Sync'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-HDInsight'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/43d6e3bd-fc6a-4b44-8b4d-2151d8736a11'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-HDInsight'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-IoT'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/aaa64d2d-2fa3-45e5-b332-0b031b9b30e8'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-IoT'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-IoTHubs'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/c99ce9c1-ced7-4c3e-aca0-10e69ce0cb02'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-IoTHubs'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-KeyVault'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/ac673a9a-f77d-4846-b2d8-a57f8e1c01d4'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-KeyVault'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-MachineLearningWorkspace'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/ee40564d-486e-4f68-a5ca-7a621edae0fb'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-MachineLearningWorkspace'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-MediaServices-Key'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/b4a7f6c1-585e-4177-ad5b-c2c93f4bb991'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-MediaServices-Key'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-MediaServices-Live'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/b4a7f6c1-585e-4177-ad5b-c2c93f4bb991'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-MediaServices-Live'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-MediaServices-Stream'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/b4a7f6c1-585e-4177-ad5b-c2c93f4bb991'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-MediaServices-Stream'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-Migrate'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/7590a335-57cf-4c95-babd-ecbc8fafeb1f'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-Migrate'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-Monitor'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/437914ee-c176-4fff-8986-7e05eb971365'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-Monitor'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-RedisCache'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/e016b22b-e0eb-436d-8fd7-160c4eaed6e2'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-RedisCache'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-ServiceBusNamespace'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/f0fcf93c-c063-4071-9668-c47474bd3564'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-ServiceBusNamespace'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-SignalR'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/b0e86710-7fb7-4a6c-a064-32e9b829509e'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-SignalR'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-Site-Recovery'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/942bd215-1a66-44be-af65-6a1c0318dbe2'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-Site-Recovery'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-Storage-Blob'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/75973700-529f-4de2-b794-fb9b6781b6b0'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-Storage-Blob'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-Storage-Blob-Sec'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/d847d34b-9337-4e2d-99a5-767e5ac9c582'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-Storage-Blob-Sec'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-Storage-DFS'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/83c6fe0f-2316-444a-99a1-1ecd8a7872ca'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-Storage-DFS'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-Storage-DFS-Sec'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/90bd4cb3-9f59-45f7-a6ca-f69db2726671'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-Storage-DFS-Sec'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-Storage-File'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/6df98d03-368a-4438-8730-a93c4d7693d6'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-Storage-File'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-Storage-Queue'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/bcff79fb-2b0d-47c9-97e5-3023479b00d1'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-Storage-Queue'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-Storage-Queue-Sec'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/da9b4ae8-5ddc-48c5-b9c0-25f8abf7a3d6'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-Storage-Queue-Sec'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-Storage-StaticWeb'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/9adab2a5-05ba-4fbd-831a-5bf958d04218'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-Storage-StaticWeb'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-Storage-StaticWeb-Sec'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/d19ae5f1-b303-4b82-9ca8-7682749faf0c'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-Storage-StaticWeb-Sec'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-Synapse-Dev'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/1e5ed725-f16c-478b-bd4b-7bfa2f7940b9'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-Synapse-Dev'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-Synapse-SQL'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/1e5ed725-f16c-478b-bd4b-7bfa2f7940b9'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-Synapse-SQL'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-Synapse-SQL-OnDemand'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/1e5ed725-f16c-478b-bd4b-7bfa2f7940b9'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-Synapse-SQL-OnDemand'].parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DINE-Private-DNS-Azure-Web'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/0b026355-49cb-467b-8ac4-f777874e175a'
+ definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-Web'].parameters
+ definitionGroups: []
+ }
+ ]
+ }
+
+{
+ name: 'Deploy-Sql-Security'
+ libSetDefinition: loadJsonContent('lib/policy_set_definitions/policy_set_definition_es_Deploy-Sql-Security.json')
+ libSetChildDefinitions: [
+ {
+ definitionReferenceId: 'SqlDbAuditingSettingsDeploySqlSecurity'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Sql-AuditingSettings'
+ definitionParameters: varPolicySetDefinitionEsDeploySqlSecurityParameters.SqlDbAuditingSettingsDeploySqlSecurity.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'SqlDbSecurityAlertPoliciesDeploySqlSecurity'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Sql-SecurityAlertPolicies'
+ definitionParameters: varPolicySetDefinitionEsDeploySqlSecurityParameters.SqlDbSecurityAlertPoliciesDeploySqlSecurity.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'SqlDbTdeDeploySqlSecurity'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Sql-Tde'
+ definitionParameters: varPolicySetDefinitionEsDeploySqlSecurityParameters.SqlDbTdeDeploySqlSecurity.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'SqlDbVulnerabilityAssessmentsDeploySqlSecurity'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Sql-vulnerabilityAssessments'
+ definitionParameters: varPolicySetDefinitionEsDeploySqlSecurityParameters.SqlDbVulnerabilityAssessmentsDeploySqlSecurity.parameters
+ definitionGroups: []
+ }
+ ]
+ }
+
+{
+ name: 'Enforce-Encryption-CMK'
+ libSetDefinition: loadJsonContent('lib/policy_set_definitions/policy_set_definition_es_Enforce-Encryption-CMK.json')
+ libSetChildDefinitions: [
+ {
+ definitionReferenceId: 'ACRCmkDeny'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/5b9159ae-1701-4a6f-9a7a-aa9c8ddd0580'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptionCMKParameters.ACRCmkDeny.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'AksCmkDeny'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/7d7be79c-23ba-4033-84dd-45e2a5ccdd67'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptionCMKParameters.AksCmkDeny.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'AzureBatchCMKEffect'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/99e9ccd8-3db9-4592-b0d1-14b1715a4d8a'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptionCMKParameters.AzureBatchCMKEffect.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'CognitiveServicesCMK'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/67121cc7-ff39-4ab8-b7e3-95b84dab487d'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptionCMKParameters.CognitiveServicesCMK.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'CosmosCMKEffect'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/1f905d99-2ab7-462c-a6b0-f709acca6c8f'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptionCMKParameters.CosmosCMKEffect.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'DataBoxCMKEffect'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/86efb160-8de7-451d-bc08-5d475b0aadae'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptionCMKParameters.DataBoxCMKEffect.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'EncryptedVMDisksEffect'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/0961003e-5a0a-4549-abde-af6a37f2724d'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptionCMKParameters.EncryptedVMDisksEffect.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'HealthcareAPIsCMKEffect'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/051cba44-2429-45b9-9649-46cec11c7119'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptionCMKParameters.HealthcareAPIsCMKEffect.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'MySQLCMKEffect'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/83cef61d-dbd1-4b20-a4fc-5fbc7da10833'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptionCMKParameters.MySQLCMKEffect.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'PostgreSQLCMKEffect'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/18adea5e-f416-4d0f-8aa8-d24321e3e274'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptionCMKParameters.PostgreSQLCMKEffect.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'SqlServerTDECMKEffect'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/0d134df8-db83-46fb-ad72-fe0c9428c8dd'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptionCMKParameters.SqlServerTDECMKEffect.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'StorageCMKEffect'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/6fac406b-40ca-413b-bf8e-0bf964659c25'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptionCMKParameters.StorageCMKEffect.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'StreamAnalyticsCMKEffect'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/87ba29ef-1ab3-4d82-b763-87fcd4f531f7'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptionCMKParameters.StreamAnalyticsCMKEffect.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'SynapseWorkspaceCMKEffect'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/f7d52b2d-e161-4dfa-a82b-55e564167385'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptionCMKParameters.SynapseWorkspaceCMKEffect.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'WorkspaceCMK'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/ba769a63-b8cc-4b2d-abf6-ac33c7204be8'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptionCMKParameters.WorkspaceCMK.parameters
+ definitionGroups: []
+ }
+ ]
+ }
+
+{
+ name: 'Enforce-EncryptTransit'
+ libSetDefinition: loadJsonContent('lib/policy_set_definitions/policy_set_definition_es_Enforce-EncryptTransit.json')
+ libSetChildDefinitions: [
+ {
+ definitionReferenceId: 'AKSIngressHttpsOnlyEffect'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/1a5b4dca-0b6f-4cf5-907c-56316bc1bf3d'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptTransitParameters.AKSIngressHttpsOnlyEffect.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'APIAppServiceHttpsEffect'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deny-AppServiceApiApp-http'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptTransitParameters.APIAppServiceHttpsEffect.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'APIAppServiceLatestTlsEffect'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/8cb6aa8b-9e41-4f4e-aa25-089a7ac2581e'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptTransitParameters.APIAppServiceLatestTlsEffect.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'AppServiceHttpEffect'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Append-AppService-httpsonly'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptTransitParameters.AppServiceHttpEffect.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'AppServiceminTlsVersion'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Append-AppService-latestTLS'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptTransitParameters.AppServiceminTlsVersion.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'FunctionLatestTlsEffect'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/f9d614c5-c173-4d56-95a7-b4437057d193'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptTransitParameters.FunctionLatestTlsEffect.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'FunctionServiceHttpsEffect'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deny-AppServiceFunctionApp-http'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptTransitParameters.FunctionServiceHttpsEffect.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'MySQLEnableSSLDeployEffect'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-MySQL-sslEnforcement'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptTransitParameters.MySQLEnableSSLDeployEffect.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'MySQLEnableSSLEffect'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deny-MySql-http'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptTransitParameters.MySQLEnableSSLEffect.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'PostgreSQLEnableSSLDeployEffect'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-PostgreSQL-sslEnforcement'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptTransitParameters.PostgreSQLEnableSSLDeployEffect.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'PostgreSQLEnableSSLEffect'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deny-PostgreSql-http'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptTransitParameters.PostgreSQLEnableSSLEffect.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'RedisDenyhttps'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deny-Redis-http'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptTransitParameters.RedisDenyhttps.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'RedisdisableNonSslPort'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Append-Redis-disableNonSslPort'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptTransitParameters.RedisdisableNonSslPort.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'RedisTLSDeployEffect'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Append-Redis-sslEnforcement'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptTransitParameters.RedisTLSDeployEffect.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'SQLManagedInstanceTLSDeployEffect'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-SqlMi-minTLS'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptTransitParameters.SQLManagedInstanceTLSDeployEffect.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'SQLManagedInstanceTLSEffect'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deny-SqlMi-minTLS'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptTransitParameters.SQLManagedInstanceTLSEffect.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'SQLServerTLSDeployEffect'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-SQL-minTLS'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptTransitParameters.SQLServerTLSDeployEffect.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'SQLServerTLSEffect'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deny-Sql-minTLS'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptTransitParameters.SQLServerTLSEffect.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'StorageDeployHttpsEnabledEffect'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-Storage-sslEnforcement'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptTransitParameters.StorageDeployHttpsEnabledEffect.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'StorageHttpsEnabledEffect'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deny-Storage-minTLS'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptTransitParameters.StorageHttpsEnabledEffect.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'WebAppServiceHttpsEffect'
+ definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deny-AppServiceWebApp-http'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptTransitParameters.WebAppServiceHttpsEffect.parameters
+ definitionGroups: []
+ }
+ {
+ definitionReferenceId: 'WebAppServiceLatestTlsEffect'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/f0e6e85b-9b9f-4a4b-b67b-f730d42f1b0b'
+ definitionParameters: varPolicySetDefinitionEsEnforceEncryptTransitParameters.WebAppServiceLatestTlsEffect.parameters
+ definitionGroups: []
+ }
+ ]
+ }
+]
+
+// Policy Set/Initiative Definition Parameter Variables
+var varPolicySetDefinitionEsDenyPublicPaaSEndpointsParameters = loadJsonContent('lib/policy_set_definitions/policy_set_definition_es_Deny-PublicPaaSEndpoints.parameters.json')
+
+var varPolicySetDefinitionEsDeployDiagnosticsLogAnalyticsParameters = loadJsonContent('lib/policy_set_definitions/policy_set_definition_es_Deploy-Diagnostics-LogAnalytics.parameters.json')
+
+var varPolicySetDefinitionEsDeployMDFCConfigParameters = loadJsonContent('lib/policy_set_definitions/policy_set_definition_es_Deploy-MDFC-Config.parameters.json')
+
+var varPolicySetDefinitionEsDeployPrivateDNSZonesParameters = loadJsonContent('lib/policy_set_definitions/policy_set_definition_es_Deploy-Private-DNS-Zones.parameters.json')
+
+var varPolicySetDefinitionEsDeploySqlSecurityParameters = loadJsonContent('lib/policy_set_definitions/policy_set_definition_es_Deploy-Sql-Security.parameters.json')
+
+var varPolicySetDefinitionEsEnforceEncryptionCMKParameters = loadJsonContent('lib/policy_set_definitions/policy_set_definition_es_Enforce-Encryption-CMK.parameters.json')
+
+var varPolicySetDefinitionEsEnforceEncryptTransitParameters = loadJsonContent('lib/policy_set_definitions/policy_set_definition_es_Enforce-EncryptTransit.parameters.json')
+
+// // DO NOT Remove This Line !!!
+
+resource resPolicySetDefinitions 'Microsoft.Authorization/policySetDefinitions@2021-06-01' = [for policySet in varCustomPolicySetDefinitionsArray: {
+ name: policySet.libSetDefinition.name
+ properties: {
+ description: policySet.libSetDefinition.properties.description
+ displayName: policySet.libSetDefinition.properties.displayName
+ metadata: policySet.libSetDefinition.properties.metadata
+ parameters: policySet.libSetDefinition.properties.parameters
+ policyType: policySet.libSetDefinition.properties.policyType
+ policyDefinitions: [for policySetDef in policySet.libSetChildDefinitions: {
+ policyDefinitionReferenceId: policySetDef.definitionReferenceId
+ policyDefinitionId: policySetDef.definitionId
+ parameters: policySetDef.definitionParameters
+ groupNames: policySetDef.definitionGroups
+ }]
+ policyDefinitionGroups: policySet.libSetDefinition.properties.policyDefinitionGroups
+ }
+}]
diff --git a/orchestration/policyInstallation/policyInstallation.bicep b/orchestration/policyInstallation/policyInstallation.bicep
new file mode 100644
index 00000000..003ddfba
--- /dev/null
+++ b/orchestration/policyInstallation/policyInstallation.bicep
@@ -0,0 +1,138 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+/*
+ SUMMARY: It will deploy the ALZ default policies and the SLZ default policy set definitions.
+ AUTHOR/S: Cloud for Sovereignty
+*/
+targetScope = 'managementGroup'
+
+@description('The prefix that will be added to all resources created by this deployment.')
+@minLength(2)
+@maxLength(5)
+param parDeploymentPrefix string
+
+@description('The suffix that will be added to management group suffix name the same way to be added to management group prefix names.')
+@maxLength(5)
+param parDeploymentSuffix string = ''
+
+@description('Deployment location')
+@allowed([
+ 'asia'
+ 'asiapacific'
+ 'australia'
+ 'australiacentral'
+ 'australiacentral2'
+ 'australiaeast'
+ 'australiasoutheast'
+ 'brazil'
+ 'brazilsouth'
+ 'brazilsoutheast'
+ 'canada'
+ 'canadacentral'
+ 'canadaeast'
+ 'centralindia'
+ 'centralus'
+ 'centraluseuap'
+ 'centralusstage'
+ 'eastasia'
+ 'eastasiastage'
+ 'eastus'
+ 'eastus2'
+ 'eastus2euap'
+ 'eastus2stage'
+ 'eastusstage'
+ 'eastusstg'
+ 'europe'
+ 'france'
+ 'francecentral'
+ 'francesouth'
+ 'germany'
+ 'germanynorth'
+ 'germanywestcentral'
+ 'global'
+ 'india'
+ 'japan'
+ 'japaneast'
+ 'japanwest'
+ 'jioindiacentral'
+ 'jioindiawest'
+ 'korea'
+ 'koreacentral'
+ 'koreasouth'
+ 'northcentralus'
+ 'northcentralusstage'
+ 'northeurope'
+ 'norway'
+ 'norwayeast'
+ 'norwaywest'
+ 'qatarcentral'
+ 'singapore'
+ 'southafrica'
+ 'southafricanorth'
+ 'southafricawest'
+ 'southcentralus'
+ 'southcentralusstage'
+ 'southcentralusstg'
+ 'southeastasia'
+ 'southeastasiastage'
+ 'southindia'
+ 'swedencentral'
+ 'switzerland'
+ 'switzerlandnorth'
+ 'switzerlandwest'
+ 'uae'
+ 'uaecentral'
+ 'uaenorth'
+ 'uk'
+ 'uksouth'
+ 'ukwest'
+ 'unitedstates'
+ 'unitedstateseuap'
+ 'westcentralus'
+ 'westeurope'
+ 'westindia'
+ 'westus'
+ 'westus2'
+ 'westus2stage'
+ 'westus3'
+ 'westusstage'
+])
+param parDeploymentLocation string
+
+@description('Set to true to deploy ALZ default policies. DEFAULT: false')
+param parDeployAlzDefaultPolicies bool = false
+
+@description('Timestamp with format yyyyMMddTHHmmssZ. Default value set to Execution Timestamp to avoid deployment contention.')
+param parTimestamp string = utcNow()
+
+var varManagementGroupId = '${parDeploymentPrefix}${parDeploymentSuffix}'
+
+// Module - create alz default Policy Definitions
+module modAlzDefaultPolicyDefinitions '../../dependencies/infra-as-code/bicep/modules/policy/definitions/slz-defaultandCustomPolicyDefinitions.bicep' = if (parDeployAlzDefaultPolicies) {
+ scope: managementGroup(varManagementGroupId)
+ name: take('${parDeploymentPrefix}-polDefs-${parDeploymentLocation}-${parTimestamp}${parDeploymentSuffix}', 64)
+}
+
+// Module - create ALZ Policy Set Initiatives
+module modAlzPolicySetDefinitions '../../dependencies/infra-as-code/bicep/modules/policy/definitions/alzPolicySetDefinitions.bicep' = if (parDeployAlzDefaultPolicies) {
+ scope: managementGroup(varManagementGroupId)
+ name: take('${parDeploymentPrefix}-alzPolSetDefs-${parDeploymentLocation}-${parTimestamp}${parDeploymentSuffix}', 64)
+ params: {
+ parTargetManagementGroupId: varManagementGroupId
+ }
+ dependsOn: [
+ modAlzDefaultPolicyDefinitions
+ ]
+}
+
+// Module - create default and custom SLZ Policy Set Initiatives
+module modDefaultandCustomSlzPolicySetDefinitions '../../dependencies/infra-as-code/bicep/modules/policy/definitions/slz-defaultandCustomPolicySetDefinitions.bicep' = {
+ scope: managementGroup(varManagementGroupId)
+ name: take('${parDeploymentPrefix}-slzPolSetDefs-${parDeploymentLocation}-${parTimestamp}${parDeploymentSuffix}', 64)
+}
+
+// Module - create default and custom SLZ Global Policy Set Initiatives
+module modDefaultandCustomSlzGlobalPolicySetDefinitions '../../dependencies/infra-as-code/bicep/modules/policy/definitions/slz-defaultandCustomGlobalPolicySetDefinitions.bicep' = {
+ scope: managementGroup(varManagementGroupId)
+ name: take('${parDeploymentPrefix}-slzglobalPolSetDefs-${parDeploymentLocation}-${parTimestamp}${parDeploymentSuffix}', 64)
+}
diff --git a/orchestration/policyInstallation/slz-DefaultandCustomPolicyDefinitions.txt b/orchestration/policyInstallation/slz-DefaultandCustomPolicyDefinitions.txt
new file mode 100644
index 00000000..0dbf1de6
--- /dev/null
+++ b/orchestration/policyInstallation/slz-DefaultandCustomPolicyDefinitions.txt
@@ -0,0 +1,446 @@
+//This bicep file includes auto-generated code. Please dont make any changes these file manually.
+
+targetScope = 'managementGroup'
+
+// This variable contains a number of objects that load in the custom Azure Policy Defintions that are provided as part of the ESLZ/ALZ reference implementation - this is automatically created in the file 'infra-as-code\bicep\modules\policy\lib\policy_definitions\_policyDefinitionsBicepInput.txt' via a GitHub action, that runs on a daily schedule, and is then manually copied into this variable.
+var varCustomPolicyDefinitionsArray = [
+// // DO NOT Remove This Line !!!
+{
+ name: 'Append-AppService-httpsonly'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Append-AppService-httpsonly.json')
+}
+{
+ name: 'Append-AppService-latestTLS'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Append-AppService-latestTLS.json')
+}
+{
+ name: 'Append-KV-SoftDelete'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Append-KV-SoftDelete.json')
+}
+{
+ name: 'Append-Redis-disableNonSslPort'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Append-Redis-disableNonSslPort.json')
+}
+{
+ name: 'Append-Redis-sslEnforcement'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Append-Redis-sslEnforcement.json')
+}
+{
+ name: 'Audit-MachineLearning-PrivateEndpointId'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Audit-MachineLearning-PrivateEndpointId.json')
+}
+{
+ name: 'Deny-AA-child-resources'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deny-AA-child-resources.json')
+}
+{
+ name: 'Deny-AppGW-Without-WAF'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deny-AppGW-Without-WAF.json')
+}
+{
+ name: 'Deny-AppServiceApiApp-http'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deny-AppServiceApiApp-http.json')
+}
+{
+ name: 'Deny-AppServiceFunctionApp-http'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deny-AppServiceFunctionApp-http.json')
+}
+{
+ name: 'Deny-AppServiceWebApp-http'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deny-AppServiceWebApp-http.json')
+}
+{
+ name: 'Deny-Databricks-NoPublicIp'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deny-Databricks-NoPublicIp.json')
+}
+{
+ name: 'Deny-Databricks-Sku'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deny-Databricks-Sku.json')
+}
+{
+ name: 'Deny-Databricks-VirtualNetwork'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deny-Databricks-VirtualNetwork.json')
+}
+{
+ name: 'Deny-MachineLearning-Aks'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deny-MachineLearning-Aks.json')
+}
+{
+ name: 'Deny-MachineLearning-Compute-SubnetId'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deny-MachineLearning-Compute-SubnetId.json')
+}
+{
+ name: 'Deny-MachineLearning-Compute-VmSize'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deny-MachineLearning-Compute-VmSize.json')
+}
+{
+ name: 'Deny-MachineLearning-ComputeCluster-RemoteLoginPortPublicAccess'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deny-MachineLearning-ComputeCluster-RemoteLoginPortPublicAccess.json')
+}
+{
+ name: 'Deny-MachineLearning-ComputeCluster-Scale'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deny-MachineLearning-ComputeCluster-Scale.json')
+}
+{
+ name: 'Deny-MachineLearning-HbiWorkspace'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deny-MachineLearning-HbiWorkspace.json')
+}
+{
+ name: 'Deny-MachineLearning-PublicAccessWhenBehindVnet'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deny-MachineLearning-PublicAccessWhenBehindVnet.json')
+}
+{
+ name: 'Deny-MachineLearning-PublicNetworkAccess'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deny-MachineLearning-PublicNetworkAccess.json')
+}
+{
+ name: 'Deny-MySql-http'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deny-MySql-http.json')
+}
+{
+ name: 'Deny-PostgreSql-http'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deny-PostgreSql-http.json')
+}
+{
+ name: 'Deny-Private-DNS-Zones'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deny-Private-DNS-Zones.json')
+}
+{
+ name: 'Deny-PublicEndpoint-MariaDB'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deny-PublicEndpoint-MariaDB.json')
+}
+{
+ name: 'Deny-PublicIP'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deny-PublicIP.json')
+}
+{
+ name: 'Deny-RDP-From-Internet'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deny-RDP-From-Internet.json')
+}
+{
+ name: 'Deny-Redis-http'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deny-Redis-http.json')
+}
+{
+ name: 'Deny-Sql-minTLS'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deny-Sql-minTLS.json')
+}
+{
+ name: 'Deny-SqlMi-minTLS'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deny-SqlMi-minTLS.json')
+}
+{
+ name: 'Deny-Storage-minTLS'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deny-Storage-minTLS.json')
+}
+{
+ name: 'Deny-Subnet-Without-Nsg'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deny-Subnet-Without-Nsg.json')
+}
+{
+ name: 'Deny-Subnet-Without-Udr'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deny-Subnet-Without-Udr.json')
+}
+{
+ name: 'Deny-VNET-Peer-Cross-Sub'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deny-VNET-Peer-Cross-Sub.json')
+}
+{
+ name: 'Deny-VNET-Peering-To-Non-Approved-VNETs'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deny-VNET-Peering-To-Non-Approved-VNETs.json')
+}
+{
+ name: 'Deny-VNet-Peering'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deny-VNet-Peering.json')
+}
+{
+ name: 'Deploy-ASC-SecurityContacts'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-ASC-SecurityContacts.json')
+}
+{
+ name: 'Deploy-Budget'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Budget.json')
+}
+{
+ name: 'Deploy-Custom-Route-Table'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Custom-Route-Table.json')
+}
+{
+ name: 'Deploy-DDoSProtection'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-DDoSProtection.json')
+}
+{
+ name: 'Deploy-Diagnostics-AA'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-AA.json')
+}
+{
+ name: 'Deploy-Diagnostics-ACI'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-ACI.json')
+}
+{
+ name: 'Deploy-Diagnostics-ACR'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-ACR.json')
+}
+{
+ name: 'Deploy-Diagnostics-AnalysisService'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-AnalysisService.json')
+}
+{
+ name: 'Deploy-Diagnostics-ApiForFHIR'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-ApiForFHIR.json')
+}
+{
+ name: 'Deploy-Diagnostics-APIMgmt'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-APIMgmt.json')
+}
+{
+ name: 'Deploy-Diagnostics-ApplicationGateway'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-ApplicationGateway.json')
+}
+{
+ name: 'Deploy-Diagnostics-AVDScalingPlans'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-AVDScalingPlans.json')
+}
+{
+ name: 'Deploy-Diagnostics-Bastion'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-Bastion.json')
+}
+{
+ name: 'Deploy-Diagnostics-CDNEndpoints'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-CDNEndpoints.json')
+}
+{
+ name: 'Deploy-Diagnostics-CognitiveServices'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-CognitiveServices.json')
+}
+{
+ name: 'Deploy-Diagnostics-CosmosDB'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-CosmosDB.json')
+}
+{
+ name: 'Deploy-Diagnostics-Databricks'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-Databricks.json')
+}
+{
+ name: 'Deploy-Diagnostics-DataExplorerCluster'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-DataExplorerCluster.json')
+}
+{
+ name: 'Deploy-Diagnostics-DataFactory'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-DataFactory.json')
+}
+{
+ name: 'Deploy-Diagnostics-DLAnalytics'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-DLAnalytics.json')
+}
+{
+ name: 'Deploy-Diagnostics-EventGridSub'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-EventGridSub.json')
+}
+{
+ name: 'Deploy-Diagnostics-EventGridSystemTopic'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-EventGridSystemTopic.json')
+}
+{
+ name: 'Deploy-Diagnostics-EventGridTopic'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-EventGridTopic.json')
+}
+{
+ name: 'Deploy-Diagnostics-ExpressRoute'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-ExpressRoute.json')
+}
+{
+ name: 'Deploy-Diagnostics-Firewall'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-Firewall.json')
+}
+{
+ name: 'Deploy-Diagnostics-FrontDoor'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-FrontDoor.json')
+}
+{
+ name: 'Deploy-Diagnostics-Function'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-Function.json')
+}
+{
+ name: 'Deploy-Diagnostics-HDInsight'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-HDInsight.json')
+}
+{
+ name: 'Deploy-Diagnostics-iotHub'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-iotHub.json')
+}
+{
+ name: 'Deploy-Diagnostics-LoadBalancer'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-LoadBalancer.json')
+}
+{
+ name: 'Deploy-Diagnostics-LogicAppsISE'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-LogicAppsISE.json')
+}
+{
+ name: 'Deploy-Diagnostics-MariaDB'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-MariaDB.json')
+}
+{
+ name: 'Deploy-Diagnostics-MediaService'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-MediaService.json')
+}
+{
+ name: 'Deploy-Diagnostics-MlWorkspace'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-MlWorkspace.json')
+}
+{
+ name: 'Deploy-Diagnostics-MySQL'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-MySQL.json')
+}
+{
+ name: 'Deploy-Diagnostics-NetworkSecurityGroups'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-NetworkSecurityGroups.json')
+}
+{
+ name: 'Deploy-Diagnostics-NIC'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-NIC.json')
+}
+{
+ name: 'Deploy-Diagnostics-PostgreSQL'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-PostgreSQL.json')
+}
+{
+ name: 'Deploy-Diagnostics-PowerBIEmbedded'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-PowerBIEmbedded.json')
+}
+{
+ name: 'Deploy-Diagnostics-RedisCache'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-RedisCache.json')
+}
+{
+ name: 'Deploy-Diagnostics-Relay'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-Relay.json')
+}
+{
+ name: 'Deploy-Diagnostics-SignalR'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-SignalR.json')
+}
+{
+ name: 'Deploy-Diagnostics-SQLElasticPools'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-SQLElasticPools.json')
+}
+{
+ name: 'Deploy-Diagnostics-SQLMI'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-SQLMI.json')
+}
+{
+ name: 'Deploy-Diagnostics-TimeSeriesInsights'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-TimeSeriesInsights.json')
+}
+{
+ name: 'Deploy-Diagnostics-TrafficManager'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-TrafficManager.json')
+}
+{
+ name: 'Deploy-Diagnostics-VirtualNetwork'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-VirtualNetwork.json')
+}
+{
+ name: 'Deploy-Diagnostics-VM'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-VM.json')
+}
+{
+ name: 'Deploy-Diagnostics-VMSS'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-VMSS.json')
+}
+{
+ name: 'Deploy-Diagnostics-VNetGW'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-VNetGW.json')
+}
+{
+ name: 'Deploy-Diagnostics-WebServerFarm'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-WebServerFarm.json')
+}
+{
+ name: 'Deploy-Diagnostics-Website'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-Website.json')
+}
+{
+ name: 'Deploy-Diagnostics-WVDAppGroup'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-WVDAppGroup.json')
+}
+{
+ name: 'Deploy-Diagnostics-WVDHostPools'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-WVDHostPools.json')
+}
+{
+ name: 'Deploy-Diagnostics-WVDWorkspace'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-WVDWorkspace.json')
+}
+{
+ name: 'Deploy-FirewallPolicy'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-FirewallPolicy.json')
+}
+{
+ name: 'Deploy-MySQL-sslEnforcement'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-MySQL-sslEnforcement.json')
+}
+{
+ name: 'Deploy-Nsg-FlowLogs-to-LA'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Nsg-FlowLogs-to-LA.json')
+}
+{
+ name: 'Deploy-Nsg-FlowLogs'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Nsg-FlowLogs.json')
+}
+{
+ name: 'Deploy-PostgreSQL-sslEnforcement'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-PostgreSQL-sslEnforcement.json')
+}
+{
+ name: 'Deploy-Sql-AuditingSettings'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Sql-AuditingSettings.json')
+}
+{
+ name: 'Deploy-SQL-minTLS'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-SQL-minTLS.json')
+}
+{
+ name: 'Deploy-Sql-SecurityAlertPolicies'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Sql-SecurityAlertPolicies.json')
+}
+{
+ name: 'Deploy-Sql-Tde'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Sql-Tde.json')
+}
+{
+ name: 'Deploy-Sql-vulnerabilityAssessments'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Sql-vulnerabilityAssessments.json')
+}
+{
+ name: 'Deploy-SqlMi-minTLS'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-SqlMi-minTLS.json')
+}
+{
+ name: 'Deploy-Storage-sslEnforcement'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Storage-sslEnforcement.json')
+}
+{
+ name: 'Deploy-VNET-HubSpoke'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-VNET-HubSpoke.json')
+}
+{
+ name: 'Deploy-Windows-DomainJoin'
+ libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Windows-DomainJoin.json')
+}
+// // DO NOT Remove This Line !!!
+]
+
+resource resPolicyDefinitions 'Microsoft.Authorization/policyDefinitions@2021-06-01' = [for policy in varCustomPolicyDefinitionsArray: {
+ name: policy.libDefinition.name
+ properties: {
+ description: policy.libDefinition.properties.description
+ displayName: policy.libDefinition.properties.displayName
+ metadata: policy.libDefinition.properties.metadata
+ mode: policy.libDefinition.properties.mode
+ parameters: policy.libDefinition.properties.parameters
+ policyType: policy.libDefinition.properties.policyType
+ policyRule: policy.libDefinition.properties.policyRule
+ }
+}]
diff --git a/orchestration/policyInstallation/slz-DefaultandCustomSLZGlobalPolicySetDefinitions.txt b/orchestration/policyInstallation/slz-DefaultandCustomSLZGlobalPolicySetDefinitions.txt
new file mode 100644
index 00000000..51c6452c
--- /dev/null
+++ b/orchestration/policyInstallation/slz-DefaultandCustomSLZGlobalPolicySetDefinitions.txt
@@ -0,0 +1,55 @@
+//This bicep file includes auto-generated code. Please dont make any changes these file manually.
+
+targetScope = 'managementGroup'
+
+// // DO NOT Remove This Line !!!
+var varCustomPolicySetDefinitionsArray = [
+{
+ name: 'SlzGlobalPolicies'
+ libSetDefinition: loadJsonContent('lib/policy_set_definitions/slzGlobalDefaults.json')
+ libSetChildDefinitions: [
+ {
+ definitionReferenceId: 'AllowedLocations'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/e56962a6-4747-49cd-b67b-bf8b01975c4c'
+ definitionParameters: varSlzGlobalDefaultsParameters.AllowedLocations.parameters
+ definitionGroups: ['dashboard-Data Residency']
+ }
+ {
+ definitionReferenceId: 'AllowedLocationsForResourceGroups'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/e765b5de-1225-4ba3-bd56-1ac6695af988'
+ definitionParameters: varSlzGlobalDefaultsParameters.AllowedLocationsForResourceGroups.parameters
+ definitionGroups: ['dashboard-Data Residency']
+ }
+ {
+ definitionReferenceId: 'Azure Cosmos DB allowed locations_1'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/0473574d-2d43-4217-aefe-941fcdf7e684'
+ definitionParameters: varSlzGlobalDefaultsParameters['Azure Cosmos DB allowed locations_1'].parameters
+ definitionGroups: ['dashboard-Data Residency']
+ }
+ ]
+ }
+]
+
+// Policy Set/Initiative Definition Parameter Variables
+
+var varSlzGlobalDefaultsParameters = loadJsonContent('lib/policy_set_definitions/slzGlobalDefaults.parameters.json')
+
+// // DO NOT Remove This Line !!!
+
+resource resPolicySetDefinitions 'Microsoft.Authorization/policySetDefinitions@2021-06-01' = [for policySet in varCustomPolicySetDefinitionsArray: {
+ name: '${policySet.libSetDefinition.name}.v${policySet.libSetDefinition.properties.metadata.version}'
+ properties: {
+ description: '${policySet.libSetDefinition.properties.description} v${policySet.libSetDefinition.properties.metadata.version}'
+ displayName: '${policySet.libSetDefinition.properties.displayName} v${policySet.libSetDefinition.properties.metadata.version}'
+ metadata: policySet.libSetDefinition.properties.metadata
+ parameters: policySet.libSetDefinition.properties.parameters
+ policyType: policySet.libSetDefinition.properties.policyType
+ policyDefinitions: [for policySetDef in policySet.libSetChildDefinitions: {
+ policyDefinitionReferenceId: policySetDef.definitionReferenceId
+ policyDefinitionId: policySetDef.definitionId
+ parameters: policySetDef.definitionParameters
+ groupNames: policySetDef.definitionGroups
+ }]
+ policyDefinitionGroups: policySet.libSetDefinition.properties.policyDefinitionGroups
+ }
+}]
diff --git a/orchestration/policyInstallation/slz-DefaultandCustomSLZPolicySetDefinitions.txt b/orchestration/policyInstallation/slz-DefaultandCustomSLZPolicySetDefinitions.txt
new file mode 100644
index 00000000..3c0222a2
--- /dev/null
+++ b/orchestration/policyInstallation/slz-DefaultandCustomSLZPolicySetDefinitions.txt
@@ -0,0 +1,143 @@
+//This bicep file includes auto-generated code. Please dont make any changes these file manually.
+
+targetScope = 'managementGroup'
+
+/* reserved customer usage attribution
+@description('Set Parameter to true to Opt-out of deployment telemetry')
+param parTelemetryOptOut bool = false
+*/
+
+// // DO NOT Remove This Line !!!
+var varCustomPolicySetDefinitionsArray = [
+{
+ name: 'SlzConfidentialPolicies'
+ libSetDefinition: loadJsonContent('lib/policy_set_definitions/slzConfidentialDefaults.json')
+ libSetChildDefinitions: [
+ {
+ definitionReferenceId: '[Preview]: Azure Recovery Services vaults should use customer-managed keys for encrypting backup dat_1'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/2e94d99a-8a36-4563-bc77-810d8893b671'
+ definitionParameters: varSlzConfidentialDefaultsParameters['[Preview]: Azure Recovery Services vaults should use customer-managed keys for encrypting backup dat_1'].parameters
+ definitionGroups: ['dashboard-Key Management']
+ }
+ {
+ definitionReferenceId: 'Allowed resource types'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/a08ec900-254a-4555-9bf5-e42af04b5c5c'
+ definitionParameters: varSlzConfidentialDefaultsParameters['Allowed resource types'].parameters
+ definitionGroups: ['dashboard-Confidential Computing']
+ }
+ {
+ definitionReferenceId: 'Allowed virtual machine size SKUs'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/cccc23c7-8427-4f53-ad12-b6a63eb452b3'
+ definitionParameters: varSlzConfidentialDefaultsParameters['Allowed virtual machine size SKUs'].parameters
+ definitionGroups: ['dashboard-Confidential Computing']
+ }
+ {
+ definitionReferenceId: 'AllowedLocations'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/e56962a6-4747-49cd-b67b-bf8b01975c4c'
+ definitionParameters: varSlzConfidentialDefaultsParameters.AllowedLocations.parameters
+ definitionGroups: ['dashboard-Data Residency']
+ }
+ {
+ definitionReferenceId: 'AllowedLocationsForResourceGroups'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/e765b5de-1225-4ba3-bd56-1ac6695af988'
+ definitionParameters: varSlzConfidentialDefaultsParameters.AllowedLocationsForResourceGroups.parameters
+ definitionGroups: ['dashboard-Data Residency']
+ }
+ {
+ definitionReferenceId: 'Azure Cosmos DB allowed locations_1'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/0473574d-2d43-4217-aefe-941fcdf7e684'
+ definitionParameters: varSlzConfidentialDefaultsParameters['Azure Cosmos DB allowed locations_1'].parameters
+ definitionGroups: ['dashboard-Data Residency']
+ }
+ {
+ definitionReferenceId: 'Both operating systems and data disks in Azure Kubernetes Service clusters should be encrypted by cu_1'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/7d7be79c-23ba-4033-84dd-45e2a5ccdd67'
+ definitionParameters: varSlzConfidentialDefaultsParameters['Both operating systems and data disks in Azure Kubernetes Service clusters should be encrypted by cu_1'].parameters
+ definitionGroups: ['dashboard-Key Management']
+ }
+ {
+ definitionReferenceId: 'HPC Cache accounts should use customer-managed key for encryption_1'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/970f84d8-71b6-4091-9979-ace7e3fb6dbb'
+ definitionParameters: varSlzConfidentialDefaultsParameters['HPC Cache accounts should use customer-managed key for encryption_1'].parameters
+ definitionGroups: ['dashboard-Key Management']
+ }
+ {
+ definitionReferenceId: 'Managed disks should be double encrypted with both platform-managed and customer-managed keys_1'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/ca91455f-eace-4f96-be59-e6e2c35b4816'
+ definitionParameters: varSlzConfidentialDefaultsParameters['Managed disks should be double encrypted with both platform-managed and customer-managed keys_1'].parameters
+ definitionGroups: ['dashboard-Key Management']
+ }
+ {
+ definitionReferenceId: 'MySQL servers should use customer-managed keys to encrypt data at rest_1'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/83cef61d-dbd1-4b20-a4fc-5fbc7da10833'
+ definitionParameters: varSlzConfidentialDefaultsParameters['MySQL servers should use customer-managed keys to encrypt data at rest_1'].parameters
+ definitionGroups: ['dashboard-Key Management']
+ }
+ {
+ definitionReferenceId: 'PostgreSQL servers should use customer-managed keys to encrypt data at rest_1'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/18adea5e-f416-4d0f-8aa8-d24321e3e274'
+ definitionParameters: varSlzConfidentialDefaultsParameters['PostgreSQL servers should use customer-managed keys to encrypt data at rest_1'].parameters
+ definitionGroups: ['dashboard-Key Management']
+ }
+ {
+ definitionReferenceId: 'Queue Storage should use customer-managed key for encryption_1'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/f0e5abd0-2554-4736-b7c0-4ffef23475ef'
+ definitionParameters: varSlzConfidentialDefaultsParameters['Queue Storage should use customer-managed key for encryption_1'].parameters
+ definitionGroups: ['dashboard-Key Management']
+ }
+ {
+ definitionReferenceId: 'SQL managed instances should use customer-managed keys to encrypt data at rest_1'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/ac01ad65-10e5-46df-bdd9-6b0cad13e1d2'
+ definitionParameters: varSlzConfidentialDefaultsParameters['SQL managed instances should use customer-managed keys to encrypt data at rest_1'].parameters
+ definitionGroups: ['dashboard-Key Management']
+ }
+ {
+ definitionReferenceId: 'SQL servers should use customer-managed keys to encrypt data at rest_1'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/0a370ff3-6cab-4e85-8995-295fd854c5b8'
+ definitionParameters: varSlzConfidentialDefaultsParameters['SQL servers should use customer-managed keys to encrypt data at rest_1'].parameters
+ definitionGroups: ['dashboard-Key Management']
+ }
+ {
+ definitionReferenceId: 'Storage account encryption scopes should use customer-managed keys to encrypt data at rest_1'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/b5ec538c-daa0-4006-8596-35468b9148e8'
+ definitionParameters: varSlzConfidentialDefaultsParameters['Storage account encryption scopes should use customer-managed keys to encrypt data at rest_1'].parameters
+ definitionGroups: ['dashboard-Key Management']
+ }
+ {
+ definitionReferenceId: 'Storage accounts should use customer-managed key for encryption_1'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/6fac406b-40ca-413b-bf8e-0bf964659c25'
+ definitionParameters: varSlzConfidentialDefaultsParameters['Storage accounts should use customer-managed key for encryption_1'].parameters
+ definitionGroups: ['dashboard-Key Management']
+ }
+ {
+ definitionReferenceId: 'Table Storage should use customer-managed key for encryption_1'
+ definitionId: '/providers/Microsoft.Authorization/policyDefinitions/7c322315-e26d-4174-a99e-f49d351b4688'
+ definitionParameters: varSlzConfidentialDefaultsParameters['Table Storage should use customer-managed key for encryption_1'].parameters
+ definitionGroups: ['dashboard-Key Management']
+ }
+ ]
+ }
+]
+
+// Policy Set/Initiative Definition Parameter Variables
+var varSlzConfidentialDefaultsParameters = loadJsonContent('lib/policy_set_definitions/slzConfidentialDefaults.parameters.json')
+
+// // DO NOT Remove This Line !!!
+
+resource resPolicySetDefinitions 'Microsoft.Authorization/policySetDefinitions@2021-06-01' = [for policySet in varCustomPolicySetDefinitionsArray: {
+ name: '${policySet.libSetDefinition.name}.v${policySet.libSetDefinition.properties.metadata.version}'
+ properties: {
+ description: '${policySet.libSetDefinition.properties.description} v${policySet.libSetDefinition.properties.metadata.version}'
+ displayName: '${policySet.libSetDefinition.properties.displayName} v${policySet.libSetDefinition.properties.metadata.version}'
+ metadata: policySet.libSetDefinition.properties.metadata
+ parameters: policySet.libSetDefinition.properties.parameters
+ policyType: policySet.libSetDefinition.properties.policyType
+ policyDefinitions: [for policySetDef in policySet.libSetChildDefinitions: {
+ policyDefinitionReferenceId: policySetDef.definitionReferenceId
+ policyDefinitionId: policySetDef.definitionId
+ parameters: policySetDef.definitionParameters
+ groupNames: policySetDef.definitionGroups
+ }]
+ policyDefinitionGroups: policySet.libSetDefinition.properties.policyDefinitionGroups
+ }
+}]
diff --git a/orchestration/policyRemediation/policyRemediation.bicep b/orchestration/policyRemediation/policyRemediation.bicep
new file mode 100644
index 00000000..8337272a
--- /dev/null
+++ b/orchestration/policyRemediation/policyRemediation.bicep
@@ -0,0 +1,39 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+/*
+ SUMMARY: This file will deploy a policy remediation to a management group.
+ AUTHOR/S: Cloud for Sovereignty
+*/
+targetScope = 'managementGroup'
+
+@description('The prefix that will be added to all resources created by this deployment.')
+@minLength(2)
+@maxLength(5)
+param parDeploymentPrefix string
+
+@description('The suffix that will be added to management group suffix name the same way to be added to management group prefix names.')
+@maxLength(5)
+param parDeploymentSuffix string = ''
+
+@description('Remediation Name.')
+param parPolicyRemediationName string
+
+@description('Policy Assignment Id.')
+param parPolicyAssignmentId string
+
+@description('Reference ids of policy to be remediated.')
+param parPolicyDefinitionReferenceId string
+
+@description('Policy assignment scope.')
+param parManagementGroupScope string
+
+// Deploy the policy remediation
+module modPolicyRemediation '../../modules/compliance/policyRemediation.bicep' = {
+ scope: managementGroup(parManagementGroupScope)
+ name: take('${parDeploymentPrefix}-${parPolicyRemediationName}${parDeploymentSuffix}', 64)
+ params: {
+ parPolicyRemediationName: parPolicyRemediationName
+ parPolicyAssignmentId: parPolicyAssignmentId
+ parPolicyDefinitionReferenceId: parPolicyDefinitionReferenceId
+ }
+}
diff --git a/orchestration/scripts/Confirm-SovereignLandingZonePrerequisites.ps1 b/orchestration/scripts/Confirm-SovereignLandingZonePrerequisites.ps1
new file mode 100644
index 00000000..2c622741
--- /dev/null
+++ b/orchestration/scripts/Confirm-SovereignLandingZonePrerequisites.ps1
@@ -0,0 +1,220 @@
+# Copyright (c) Microsoft Corporation.
+# Licensed under the MIT License.
+<#
+SUMMARY: This PowerShell script executes the below list of prerequisite checks to confirm before execution of the New-SovereignLandingZone.ps1
+
+- Verify PowerShell Verion
+- Verify Azure PowerShell version
+- Verify Azure CLI version
+- Update Bicep version
+- Check the user executing has the owner permission on the root ("/") scope of the tenant and assign root ("/") permission if the user is missing the same
+
+AUTHOR/S: Cloud for Sovereignty
+#>
+
+param (
+ $parIsSLZDeployedAtTenantRoot = $true
+)
+
+$varSignedInUser = $null;
+
+function Confirm-PowerShellVersion {
+ <#
+
+ .SYNOPSIS
+ This function checks the current version of PowerShell and prompts the user to install the latest version if the current version is not compatible with the script.
+ .EXAMPLE
+ Confirm-PowerShellVersion
+ .EXAMPLE
+ Confirm-PowerShellVersion -varMajorVersion 7 -varMinorVersion 1
+ .PARAMETER varMajorVersion
+ The major version of PowerShell to check for
+ .PARAMETER varMinorVersion
+ The minor version of PowerShell to check for
+
+ #>
+ param(
+ [Parameter(Mandatory = $false)]
+ [int]$parMajorVersion = 7,
+
+ [Parameter(Mandatory = $false)]
+ [int]$parMinorVersion = 0
+ )
+ $varVersion = $PSVersionTable.PSVersion
+ Write-Information "`n>>> Checking if the current version of PowerShell $varVersion is compatible with the script- " -InformationAction Continue
+
+ if ($varVersion.Major -eq $parMajorVersion -and $varVersion.Minor -ge $parMinorVersion) {
+ Write-Information "The installed version of PowerShell is compatible with the script." -InformationAction Continue
+ return $true
+ }
+ else {
+ Write-Error "The installed version of PowerShell $varVersion is not compatible with the script. Please upgrade to the latest version ($parMajorVersion.$parMinorVersion or above) by using the command 'winget install --id Microsoft.Powershell --source winget' or follow this documentation : https://aka.ms/install-powershell." -ErrorAction Continue
+ return $false
+ }
+}
+
+#reference to individual scripts
+. ".\Invoke-Helper.ps1"
+
+function Confirm-AZPSVersion {
+ <#
+
+ .SYNOPSIS
+ This function checks the current version of Azure PowerShell module and prompts the user to install the latest version if the current version is not compatible with the script.
+ .EXAMPLE
+ Confirm-AZPSVersion
+ .EXAMPLE
+ Confirm-AZPSVersion -varMajorVersion 10
+ .PARAMETER varMajorVersion
+ The major version of Azure PowerShell module to check for
+
+ #>
+ param(
+ [Parameter(Mandatory = $false)]
+ [int]$parMajorVersion = 10
+ )
+ Write-Information "`n>>> Checking the current verison of azure powershell installed..." -InformationAction Continue
+ try {
+ $varAzpsVersion = (Get-InstalledModule -Name Az).Version
+ }
+ catch {
+ Write-Error "Install the latest version of Azure AZ PowerShell ($parMajorVersion.0 or above) by running this command 'Install-Module -Name Az -AllowClobber -Force'" -ErrorAction Continue
+ return $false
+ }
+ $varCompatibleVersionInstalled = [Version]$varAzpsVersion -ge [Version]"$parMajorVersion.0.0"
+ if ($varCompatibleVersionInstalled) {
+ Write-Information "The installed version of Azure AZ PowerShell module is compatible with the script." -InformationAction Continue
+ return $true
+ }
+ else {
+ Write-Error "The installed version of Azure AZ PowerShell module ($varAzpsVersion) is not compatible with the script. Please upgrade to the latest version ($parMajorVersion.0 or above) by running this command 'Install-Module -Name Az -AllowClobber -Force'" -ErrorAction Continue
+ return $false
+ }
+}
+
+function Confirm-AZCLIVersion {
+ <#
+ .SYNOPSIS
+ This function checks the current version of Azure CLI and prompts the user to install the latest version if the current version is not compatible with the script.
+ .EXAMPLE
+ Confirm-AZCLIVersion
+ .EXAMPLE
+ Confirm-AZCLIVersion -varMajorVersion 2 -varMinorVersion 40
+ .PARAMETER varMajorVersion
+ The major version of Azure CLI to check for
+ .PARAMETER varMinorVersion
+ The minor version of Azure CLI to check for
+ #>
+ param(
+ [Parameter(Mandatory = $false)]
+ [int]$parMajorVersion = 2,
+
+ [Parameter(Mandatory = $false)]
+ [int]$parMinorVersion = 51
+ )
+ Write-Information "`n>>> Checking the current verison of azure cli installed - " -InformationAction Continue
+ if (Get-Command "az" -errorAction SilentlyContinue) {
+ $varAzVersion = ((az version -o tsv) -split "\t")[0] -split "\."
+ $varCompatibleVersionInstalled = $varAzVersion[0] -eq $parMajorVersion -and $varAzVersion[1] -ge $parMinorVersion
+ if ($varCompatibleVersionInstalled) {
+ Write-Information "The installed version of Azure CLI is compatible with the script." -InformationAction Continue
+ return $true
+ }
+ }
+ Write-Error "The installed version of Azure CLI $varAzVersion is not compatible with the script. Please upgrade to the latest version of Azure CLI ($parMajorVersion.$parMinorVersion or above) by following the steps in the link - https://learn.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest." -ErrorAction Continue
+ return $false
+}
+
+function Confirm-BicepVersion {
+ <#
+ .SYNOPSIS
+ This function checks the current version of Bicep and prompts the user to install the latest version
+ .EXAMPLE
+ Confirm-BicepVersion
+ #>
+ param(
+ [Parameter(Mandatory = $false)]
+ [int]$parMajorVersion = 0,
+
+ [Parameter(Mandatory = $false)]
+ [int]$parMinorVersion = 20
+ )
+ Write-Information "`n>>> Checking the current verison of Bicep installed - " -InformationAction Continue
+ $varCurrentBicepVersion = $null
+ try {
+ $varCurrentBicepVersion = ((bicep --version) -split " ")[3]
+ }
+ catch {
+ $varCurrentBicepVersion = $null
+ }
+
+ if (($varCurrentBicepVersion -ne "") -and ($null -ne $varCurrentBicepVersion)) {
+ ##when bicep version command is run, platform already prints the latest version of the Bicep, so no need to print it again
+ $varCompatibleVersionInstalled = [Version]$varCurrentBicepVersion -ge [Version]"$parMajorVersion.$parMinorVersion.0"
+ if ($varCompatibleVersionInstalled) {
+ Write-Information "The installed version of Bicep is latest." -InformationAction Continue
+ return $true
+ }
+ else {
+ Write-Error "Current version of Bicep $varCurrentBicepVersion is not compatible with script. To upgrade to the latest version ($parMajorVersion.$parMinorVersion or above), please use this command 'winget install -e --id Microsoft.Bicep --source winget' " -ErrorAction Continue
+ return $false
+ }
+ }
+ else {
+ Write-Error "Bicep is not installed. To install to the latest version $varLatestAvailableBicepVersion please use this command 'winget install -e --id Microsoft.Bicep --source winget'. Note: If unable to update the bicep, uninstall the current version and retry installation command" -ErrorAction Continue
+ return $false
+ }
+}
+
+<#
+ .SYNOPSIS
+ This function Confirm the pre-requisites for the SLZ to be executed
+ .EXAMPLE
+ Confirm-SLZ-PreRequisites
+#>
+function Confirm-SLZ-PreRequisites {
+ $varPsVersionCompatible = Confirm-PowerShellVersion
+ $varAzPsVersionCompatible = Confirm-AZPSVersion
+ $varAzCliVersionCompatible = Confirm-AZCLIVersion
+ $varBicepVersionCompatible = Confirm-BicepVersion
+
+ if ($varPsVersionCompatible -eq $false -or $varAzPsVersionCompatible -eq $false -or $varAzCliVersionCompatible -eq $false -or $varBicepVersionCompatible -eq $false) {
+ Write-Error "After installing missing dependencies, please restart PowerShell and try again" -ErrorAction Stop
+ }
+
+ $varSignedInUser = Get-SignedInUser
+
+ # if user is not signed in trigger login
+ if ($null -eq $varSignedInUser) {
+ Enter-Login
+ $varSignedInUser = Get-SignedInUser
+ }
+ if ($parIsSLZDeployedAtTenantRoot) {
+ # check user elevated at root scope
+ $varUserElevated = Confirm-UserElevated
+
+ # if user is not elevated at root scope.
+ if ($varUserElevated -ne $true) {
+ Set-UserElevatePermissions
+ Invoke-UserPermissionsConfirmation "Elevate"
+ }
+
+ # check owner permissions of the user
+ $varUserhasOwnerPermissions = Confirm-UserOwnerPermission
+
+ # if user does not have owner permissions.
+ if ($varUserhasOwnerPermissions -ne $true) {
+ Set-UserOwnerPermission
+ Invoke-UserPermissionsConfirmation "Owner"
+ }
+
+ Write-Information "`n>>> Signed in user: $varSignedInUser has the necessary permissions." -InformationAction Continue
+ }
+}
+
+try {
+ Confirm-SLZ-PreRequisites
+}
+catch {
+ Write-Error $_ -ErrorAction Stop
+}
diff --git a/orchestration/scripts/Invoke-Helper.ps1 b/orchestration/scripts/Invoke-Helper.ps1
new file mode 100644
index 00000000..a2bdab9e
--- /dev/null
+++ b/orchestration/scripts/Invoke-Helper.ps1
@@ -0,0 +1,920 @@
+# Copyright (c) Microsoft Corporation.
+# Licensed under the MIT License.
+<#
+.SYNOPSIS
+ The powershell script contains definitions of helper functions to be used across all the deployment scripts.
+#>
+
+#variables
+$varMoveSubscriptionBicepFilePath = '..\moveSubscription\moveSubscription.bicep'
+$varAzPortalLink = 'https://portal.azure.com'
+$varDonotRetryErrorCodes = New-Object Collections.Generic.List[String]
+$vartimeStamp = Get-Date -Format "yyyyMMddTHHmmssffff"
+$varTenantDeployment = 'tenant'
+$varManagementGroupDeployment = 'managementGroup'
+$varParameters = @{}
+
+#variables to support incremental delay for azure resource validation checks (All time in seconds)
+$varMaxWaitTimeResourceExistsCheck = 1800
+$varStartIntervalResourceExistsCheck = 5
+$varMaxIntervalResourceExistsCheck = 60
+$varIntervalMultiplierResourceExistsCheck = 5
+#variables to support retry for known transient errors
+$varMaxRetryAttemptTransientErrorRetry = 6
+$varRetryWaitTimeTransientErrorRetry = 60
+$varReservedIpAddressRange = @(
+ "224.0.0.0/4",
+ "255.255.255.255/32",
+ "127.0.0.0/8",
+ "169.254.0.0/16",
+ "168.63.129.16/32",
+ "192.168.1.0",
+ "192.168.1.1",
+ "192.168.1.2",
+ "192.168.1.3",
+ "192.168.1.255"
+)
+
+
+<#
+.Description
+ Login to Azure portal
+#>
+function Enter-Login {
+ Write-Information ">>> Initiating a login" -InformationAction Continue
+ Connect-AzAccount
+}
+
+<#
+.Description
+ Get details of user
+#>
+function Get-SignedInUser {
+
+ $varSignedInUserDetails = Get-AzADUser -SignedIn
+ if (!$varSignedInUserDetails) {
+ Write-Information ">>> No logged in user found." -InformationAction Continue
+ }
+ else {
+ return $varSignedInUserDetails.UserPrincipalName
+ }
+
+ return $null
+}
+
+<#
+.Description
+ Confirm the user is owner at the root scope
+#>
+function Confirm-UserOwnerPermission {
+ if ($null -ne $varSignedInUser) {
+
+ Write-Information "`n>>> Checking the owner permissions for user: $varSignedInUser at '/' scope" -InformationAction Continue
+ $varRetrieveOwnerPermissions = Get-AzRoleAssignment `
+ -SignInName $varSignedInUser `
+ -Scope "/" `
+ -RoleDefinitionName "Owner"
+
+ if ($varRetrieveOwnerPermissions.RoleDefinitionName -ne "Owner") {
+ Write-Information "Signed in user: $varSignedInUser does not have owner permission to the root '/' scope." -InformationAction Continue
+ return $false
+ }
+ else {
+ Write-Information "Signed in user: $varSignedInUser has owner permissions at the root '/' scope." -InformationAction Continue
+ }
+ return $true
+ }
+ else {
+ Write-Error "Logged in user details are empty." -ErrorAction Stop
+ }
+}
+
+<#
+.Description
+ Assigns the user with Owner permissions at the root scope
+#>
+function Set-UserOwnerPermission {
+ Write-Information ">>> Assigning user with Owner permissions." -InformationAction Continue
+
+ # Assign "Owner" role to the signed-in user at the root scope "/"
+ New-AzRoleAssignment `
+ -SignInName $varSignedInUser `
+ -Scope "/" `
+ -RoleDefinitionName "Owner"
+}
+
+<#
+.Description
+ Confirm the user is elevated at the root scope.
+#>
+function Confirm-UserElevated {
+ if ($null -ne $varSignedInUser) {
+
+ Write-Information "`n>>> Checking user $varSignedInUser is elevated at '/' scope" -InformationAction Continue
+ $varRetrieveUAAPermissions = Get-AzRoleAssignment `
+ -SignInName $varSignedInUser `
+ -Scope "/" `
+ -RoleDefinitionName "User Access Administrator"
+
+ if ($varRetrieveUAAPermissions.RoleDefinitionName -ne "User Access Administrator") {
+ Write-Information "Signed in user: $varSignedInUser is not elevated at '/' scope" -InformationAction Continue
+ return $false
+ }
+
+ Write-Information "Signed in user: $varSignedInUser is elevated at '/' scope" -InformationAction Continue
+ return $true
+ }
+ else {
+ Write-Error "Logged in user details are empty." -ErrorAction Stop
+ }
+}
+<#
+.Description
+ Assigns the user with User Access Administrator permissions at the root scope
+#>
+function Set-UserElevatePermissions {
+ Write-Information ">>> Elevating user at root scope." -InformationAction Continue
+
+ # Elevate access to all Azure Resources for a Global Administrator
+ Invoke-AzRestMethod -Method Post -Uri "https://management.azure.com/providers/Microsoft.Authorization/elevateAccess?api-version=2016-07-01"
+}
+
+<#
+.Description
+ Confirm the user is elevated at the root scope.
+#>
+function Invoke-UserPermissionsConfirmation {
+ param($parPermissionType)
+ Write-Information "`n>>> Confirming user's permissions. This might trigger an auto log out and require the user to login back in a few times" -InformationAction Continue
+
+ $varUserPermissionsElevated = $false
+ $varWaitTime = 10
+ $varLoopCounter = 0
+
+ while ($varTotalWaitTime -lt $varMaxWaitTimeResourceExistsCheck -and $varUserPermissionsElevated -eq $false) {
+ try {
+ # Log out to refresh the session
+ Get-AzContext | Remove-AzContext -Confirm:$false
+ Connect-AzAccount
+
+ if ($parPermissionType -eq "Owner") {
+ # check owner permissions of the user
+ $varUserPermissionsElevated = Confirm-UserOwnerPermission
+ }
+ elseif ($parPermissionType -eq "Elevate") {
+ # check user elevated at root scope
+ $varUserPermissionsElevated = Confirm-UserElevated
+ }
+
+ if ($varUserPermissionsElevated -ne $true) {
+ Write-Information ">>> Checking the permissions after waiting for $varWaitTime secs. Please ensure that you are logged into the appropriate tenant and did not log in to a different tenant during the script execution." -InformationAction Continue
+ $varLoopCounter++
+ $varWaitTime = New-IncrementalDelay $varWaitTime $varLoopCounter
+ $varTotalWaitTime += $varWaitTime
+ Start-Sleep -Seconds $varWaitTime
+ }
+ }
+ catch {
+ $_.Exception
+ Write-Information ">>> Retrying after waiting for $varWaitTime secs. To stop the retry press Ctrl+C." -InformationAction Continue
+ $varLoopCounter++
+ $varWaitTime = New-IncrementalDelay $varWaitTime $varLoopCounter
+ $varTotalWaitTime += $varWaitTime
+ Start-Sleep -Seconds $varWaitTime
+ }
+ }
+}
+
+<#
+.Description
+ Retrieves the error details on failure of deployment from azure
+#>
+function Get-FailedDeploymentErrorCodes {
+ param($parManagementGroupId, $parDeploymentName, $parDeploymentScope)
+
+ $varErrorCodeList = New-Object Collections.Generic.List[String]
+ if ($parDeploymentScope -eq $varTenantDeployment) {
+ $varDeploymentError = Get-AzTenantDeploymentOperation `
+ -DeploymentName $parDeploymentName | Where-Object { $_.ProvisioningState -eq "Failed" }
+ }
+ else {
+ $varDeploymentError = Get-AzManagementGroupDeploymentOperation `
+ -ManagementGroupId $parManagementGroupId `
+ -DeploymentName $parDeploymentName | Where-Object { $_.ProvisioningState -eq "Failed" }
+ }
+
+ if ($null -ne $varDeploymentError) {
+ if ($varDeploymentError.GetType().IsArray -and $varDeploymentError.count -gt 0) {
+ foreach ($error in $varDeploymentError) {
+ $varErrorDetails = $error.StatusMessage
+ if ($varErrorDetails) {
+ $varErrorCode = Get-ErrorCode $varErrorDetails
+ # add to the list if the error code is not null and does not exists already
+ if ($null -ne $varErrorCode -and !($varErrorCodeList -Contains $varErrorCode)) {
+ $varErrorCodeList.Add($varErrorCode)
+ }
+ }
+ }
+ }
+ else {
+ $varErrorDetails = $varDeploymentError.StatusMessage
+ if ($varErrorDetails) {
+ $varErrorCode = Get-ErrorCode $varErrorDetails
+ # add to the list if the error code is not null and does not exists already
+ if ($null -ne $varErrorCode -and !($varErrorCodeList -Contains $varErrorCode)) {
+ $varErrorCodeList.Add($varErrorCode)
+ }
+ }
+ }
+ }
+ else {
+ return $null
+ }
+ return $varErrorCodeList
+}
+
+<#
+.Description
+ Checks whether a transient error or not
+#>
+function Confirm-Retry {
+ param ($parDeploymentErrorCodes)
+
+ $varRetry = $true
+
+ foreach ($varErrorCode in $parDeploymentErrorCodes) {
+ if ($varDonotRetryErrorCodes -contains $varErrorCode) {
+ $varRetry = $false
+ break
+ }
+ }
+ return $varRetry
+}
+
+<#
+.Description
+ Converts the object to array
+#>
+function Convert-ToArray {
+ param ($parObjectToConvert)
+ if ($null -eq $parObjectToConvert -or $parObjectToConvert.Length -eq "0") {
+ return @()
+ }
+
+ $varObjArray = @()
+ foreach ($varObject in $parObjectToConvert) {
+ $varMap = @{}
+ $varObject.psobject.properties | ForEach-Object { $varMap[$_.Name] = $_.Value }
+ $varObjArray += $varMap
+ }
+
+ return , $varObjArray
+}
+
+<#
+.Description
+ Converts the object to a hash table
+#>
+function Convert-ToHashTable {
+ param ($parObjectToConvert)
+ if ($null -eq $parObjectToConvert) {
+ return @{}
+ }
+
+ $varHashTable = @{}
+ $parObjectToConvert.PSObject.properties | ForEach-Object { $varHashTable[$_.Name] = $_.Value }
+
+ return $varHashTable
+}
+
+<#
+.Description
+ Moves the Subscriptions from root management group to platform
+#>
+function Move-Subscription {
+ param($parParameters, $modDeployBootstrapOutputs)
+
+ if ($modDeployBootstrapOutputs) {
+ $varConnectivitySubscriptionId = $modDeployBootstrapOutputs.outputs.outConnectivitySubscriptionId.value
+ $varIdentitySubscriptionId = $modDeployBootstrapOutputs.outputs.outIdentitySubscriptionId.value
+ $varManagementSubscriptionId = $modDeployBootstrapOutputs.outputs.outManagementSubscriptionId.value
+ }
+ else {
+ $varConnectivitySubscriptionId = $parParameters.parConnectivitySubscriptionId.value
+ $varIdentitySubscriptionId = $parParameters.parIdentitySubscriptionId.value
+ $varManagementSubscriptionId = $parParameters.parManagementSubscriptionId.value
+ }
+
+ $parDeploymentPrefix = $parParameters.parDeploymentPrefix.value
+ $parDeploymentSuffix = $parParameters.parDeploymentSuffix.value
+ $varManagementGroupId = "$parDeploymentPrefix$parDeploymentSuffix"
+ $parDeploymentLocation = $parParameters.parDeploymentLocation.value
+ $parameters = @{
+ parDeploymentPrefix = $parDeploymentPrefix
+ parDeploymentSuffix = $parDeploymentSuffix
+ parConnectivitySubscriptionId = $varConnectivitySubscriptionId
+ parIdentitySubscriptionId = $varIdentitySubscriptionId
+ parManagementSubscriptionId = $varManagementSubscriptionId
+ }
+ $varDeploymentName = "deploy-move-$vartimeStamp"
+ $varLoopCounter = 0
+ $varRetry = $true
+
+ while ($varRetry -and $varLoopCounter -lt $varMaxRetryAttemptTransientErrorRetry) {
+ try {
+ Write-Information ">>> Move subscription started" -InformationAction Continue
+
+ $modMoveSubscription = New-AzManagementGroupDeployment `
+ -Name $varDeploymentName `
+ -ManagementGroupId $varManagementGroupId `
+ -Location $parDeploymentLocation `
+ -TemplateFile $varMoveSubscriptionBicepFilePath `
+ -TemplateParameterObject $parameters `
+ -WarningAction Ignore
+
+ if (!$modMoveSubscription) {
+ $varRetry = $false
+ Write-Error "Error while executing move subscription" -ErrorAction Stop
+ }
+
+ Write-Information ">>> Move subscription completed`n" -InformationAction Continue
+ return;
+ }
+ catch {
+ if (!$varRetry) {
+ Write-Error ">>> Error occurred during execution. Please try after addressing the above error." -ErrorAction Stop
+ }
+ else {
+ $varDeploymentErrorCodes = Get-FailedDeploymentErrorCodes $varManagementGroupId $varDeploymentName $varManagementGroupDeployment
+ if ($null -eq $varDeploymentErrorCodes) {
+ $varRetry = $false
+ }
+ else {
+ $varLoopCounter++
+ $varRetry = Confirm-Retry $varDeploymentErrorCodes
+ if ($varRetry -and $varLoopCounter -lt $varMaxRetryAttemptTransientErrorRetry) {
+ Write-Information ">>> Retrying deployment after waiting for $varRetryWaitTimeTransientErrorRetry secs" -InformationAction Continue
+ Start-Sleep -Seconds $varRetryWaitTimeTransientErrorRetry
+ }
+ else {
+ $varRetry = $false
+ Write-Error ">>> Error occurred in move subscription deployment. Please try after addressing the above error." -ErrorAction Stop
+ }
+ }
+ }
+ }
+ }
+}
+
+<#
+.Description
+ Caclulates and returns the number of seconds to wait
+#>
+function New-IncrementalDelay {
+ param($parDelay, $parDelayIterator)
+ $parDelay = $parDelay + ($parDelayIterator * $varIntervalMultiplierResourceExistsCheck)
+ if ($parDelay -ge $varMaxIntervalResourceExistsCheck) {
+ $parDelay = $varMaxIntervalResourceExistsCheck
+ }
+ return $parDelay
+}
+
+<#
+.Description
+ Load all the errors from the json file in a hashtable
+#>
+function Get-DonotRetryErrorCodes {
+ param ()
+ $varErrorFile = Get-Content -Path '../const/doNotRetryErrorCodes.json' | ConvertFrom-Json
+ $varErrorFile.errorCodes | ForEach-Object {
+ $varDonotRetryErrorCodes.add($_.code)
+ }
+}
+<#
+.Description
+ Retrieves the error code on failure of deployment from json object
+#>
+function Get-ErrorCode {
+ param ($parErrorString)
+
+ $varLastIndexOfCode = $parErrorString.LastIndexOf("(Code:")
+
+ # Find the position of the closing parenthesis after "Code:"
+ $varClosingParenthesisIndex = $parErrorString.IndexOf(")", $varLastIndexOfCode)
+
+ # Extract the value of 'Code'
+ $varErrorCode = $parErrorString.Substring($varLastIndexOfCode + 6, $varClosingParenthesisIndex - $varLastIndexOfCode - 6).Trim()
+
+ return $varErrorCode
+}
+
+<#
+.Description
+ Checks the required parameters are passed based on the deployment
+#>
+function Confirm-Parameters($parParameters) {
+ $varMissingParameters = New-Object Collections.Generic.List[String]
+ $varArrayParameters = @("parAllowedLocations", "parAllowedLocationsForConfidentialComputing", "parPolicyDefinitionReferenceIds")
+ Foreach ($varParameter in $parParameters) {
+ if ($varParameter -in $varArrayParameters -and $varParameters.$varParameter.value.count -eq 0) {
+ if (!$parAttendedLogin) {
+ $varMissingParameters.add($varParameter)
+ }
+ else {
+ [string[]] $varArray = @()
+ $varArray = Read-Host "Please enter the list of $varParameter with a comma between each"
+ if ($varArray[0] -eq "") {
+ Write-Error "$varParameter value not found" -ErrorAction Stop
+ }
+ $varParameters.$varParameter.value = $varArray.Split(',')
+ }
+ }
+ elseif (($null -eq $varParameters.$varParameter.value) -or [string]::IsNullOrEmpty($varParameters.$varParameter.value) -or ($varParameters.$varParameter.value -eq "{}")) {
+ $varParameters.$varParameter.value = $null
+ if (!$parAttendedLogin) {
+ $varMissingParameters.add($varParameter)
+ }
+ else {
+ $varParameters.$varParameter.value = $(Read-Host -prompt "Please provide the value for $varParameter")
+ if ($varParameters.$varParameter.value -eq "") {
+ Write-Error "$varParameter value not found" -ErrorAction Stop
+ }
+ }
+ }
+ elseif ($varParameters.$varParameter.value.count -gt 1) {
+ $varValue = $varParameters.$varParameter.value
+ if ($varValue -is [array]) {
+ foreach ($val in $varValue) {
+ $result = Confirm-ObjectType($val)
+ if ($result -eq $false) {
+ $varMissingParameters.add($varParameter)
+ }
+ }
+ }
+ elseif ($varValue -is [object]) {
+ $result = Confirm-ObjectType($varValue)
+ if ($result -eq $false) {
+ $varMissingParameters.add($varParameter)
+ }
+ }
+ elseif (($null -eq $varValue) -or [string]::IsNullOrEmpty($varValue) -or ($varValue -eq "{}")) {
+ $varParameters.$varParameter.value = $null
+ return $false
+ }
+ }
+ }
+ if ($varMissingParameters.count -gt 0) {
+ Write-Error "Following parameters are missing : $varMissingParameters" -ErrorAction Stop
+ }
+
+ # Check Gateway subnet is in the reserved Ip address list.
+ $varGatewaySubnet = $parParameters.parGatewaySubnet.value
+ $varIsGatewayReservedIpAddress = Confirm-IPAddressIsReserved($varGatewaySubnet)
+ if (($null -ne $varGatewaySubnet) -and ($true -eq $varIsGatewayReservedIpAddress)) {
+ Show-IpAddressError("The Gatewary Subnet Ip", $varGatewaySubnet)
+ }
+
+ # Check Azure Firewall Subnet is in the reserved Ip address list.
+ $varAzureFirewallSubnet = $parParameters.parAzureFirewallSubnet.value
+ $varIsFirewallReservedIpAddress = Confirm-IPAddressIsReserved($varAzureFirewallSubnet)
+ if (($null -ne $varAzureFirewallSubnet) -and ($true -eq $varIsFirewallReservedIpAddress)) {
+ Show-IpAddressError("The Azure Firewall Subnet Ip", $varAzureFirewallSubnet)
+ }
+}
+
+<#
+.Description
+ Show Ip Address error which is in reserved Ip Address range list.
+#>
+function Show-IpAddressError($parMessage, $parIp) {
+ Write-Information "$parMessage $parIp is in the reserved IP address list:" -InformationAction Continue
+ foreach ($varIp in $varReservedIpAddressRange) {
+ Write-Information $varIp -InformationAction Continue
+ }
+
+ Write-Error "Please do not use reserved IP addresses. Update parameters and try again." -ErrorAction Stop
+}
+
+<#
+.Description
+ Checks/confirms whether the value of Ip Address range is in reserved Ip Address range list.
+#>
+function Confirm-IPAddressIsReserved($parIp) {
+ if ($null -eq $parIp) {
+ return $false
+ }
+
+ Foreach ($varReservedIpAddress in $varReservedIpAddressRange) {
+ try {
+ # Parse the IP address and subnet
+ $varReservedIp = [IPAddress]::Parse($varReservedIpAddress.Split("/")[0])
+ $varReservedIpRange = $varReservedIpAddress.Split("/")[1]
+ $varIp = [IPAddress]::Parse($parIp.Split("/")[0])
+ $varIpRange = $parIp.Split("/")[1]
+
+ # Check if the IP address falls within the reserved IP address
+ $varIsReservedIp = (($varReservedIp.Address -eq $varIp.Address) -and ($varReservedIpRange -eq $varIpRange))
+
+ if ($varIsReservedIp) {
+ return $true
+ }
+ }
+ catch {
+ Write-Error $_ -ErrorAction Stop
+ }
+ }
+
+ return $false
+}
+
+<#
+.Description
+ Checks the required Object type parameters are passed based on the deployment.
+#>
+function Confirm-ObjectType($parParameter) {
+ if (($null -eq $parParameter)) {
+ return $false
+ }
+
+ $varMembers = $parParameter.PSObject.Properties | Select-Object Name, Value
+ foreach ($varMember in $varMembers) {
+ if (($null -eq $varMember.value) -or [string]::IsNullOrEmpty($varMember.value) -or ($varMember.value -eq "")) {
+ return $false
+ }
+ }
+
+ return $true
+}
+
+<#
+.Description
+ Checks that the policy sets are available before assigning
+#>
+function Confirm-PolicySetExists {
+ param ($parManagementGroupId, $parPolicySetType)
+
+ if ($parPolicySetType -eq 'custom') {
+ $varPolicySetsPath = "../../custom/policies/definitions"
+ }
+ else {
+ $varPolicySetsPath = "../../modules/compliance/policySetDefinitions"
+ }
+
+ $varLoopCounter = 0
+ $varWaitTime = $varStartIntervalResourceExistsCheck
+ $varTotalWaitTime = 0
+
+ while ($varTotalWaitTime -lt $varMaxWaitTimeResourceExistsCheck) {
+ try {
+ Get-ChildItem -Recurse -Path "$varPolicySetsPath" -Filter "*.json" | ForEach-Object {
+
+ $varPolicyDef = Get-Content $_.PSPath | ConvertFrom-Json -Depth 100
+
+ if (($varPolicyDef.properties.policyDefinitions).Count -ne 0) {
+ $parPolicyName = $varPolicyDef.name + ".v" + $varPolicyDef.properties.metadata.version
+
+ $varPolicySet = Get-AzPolicySetDefinition -Name $parPolicyName -ManagementGroupName $parManagementGroupId
+ if (!$varPolicySet) {
+ Write-Error "$parPolicyName policy set not found." -ErrorAction stop
+ }
+ }
+ }
+
+ Write-Information ">>> All required policy sets were found." -InformationAction Continue
+ return $true
+ }
+ catch {
+ $varLoopCounter++
+ $varWaitTime = New-IncrementalDelay $varWaitTime $varLoopCounter
+ Write-Information ">>> Searching for the required policy sets after waiting for $varWaitTime seconds." -InformationAction Continue
+ $varTotalWaitTime += $varWaitTime
+ Start-Sleep -Seconds $varWaitTime
+ }
+ }
+
+ return $false
+}
+
+<#
+.Description
+ Checks whether subscriptions are created or not.
+#>
+function Confirm-SubscriptionsExists() {
+ param($parConnectivitySubscriptionId, $parIdentitySubscriptionId, $parManagementSubscriptionId)
+ $varLoopCounter = 0
+ $varWaitTime = $varStartIntervalResourceExistsCheck
+ $varTotalWaitTime = 0
+ $varSubscriptionExists = $false
+ while ($varTotalWaitTime -lt $varMaxWaitTimeResourceExistsCheck -and $varSubscriptionExists -eq $false) {
+ try {
+ $varConnectivityID = Get-AzSubscription -SubscriptionId $parConnectivitySubscriptionId -WarningAction Ignore
+ $varManagementID = Get-AzSubscription -SubscriptionId $parManagementSubscriptionId -WarningAction Ignore
+ $varIdentityID = Get-AzSubscription -SubscriptionId $parIdentitySubscriptionId -WarningAction Ignore
+ if ((!$varConnectivityID) -or (!$varManagementID) -or (!$varIdentityID)) {
+ Write-Error "Subscription Not Found" -ErrorAction stop
+ }
+ $varSubscriptionExists = $true
+ }
+ catch {
+ $varLoopCounter++
+ $varWaitTime = New-IncrementalDelay $varWaitTime $varLoopCounter
+ Write-Information ">>>One or more subscription not found. Retrying after $varWaitTime seconds" -InformationAction Continue
+ $varTotalWaitTime += $varWaitTime
+ Start-Sleep -Seconds $varWaitTime
+ }
+ }
+
+ return $varSubscriptionExists
+}
+
+<#
+.Description
+ Processing parameters from JSON and creating a hash table
+#>
+function Read-ParametersValue($parJsonParamFilePath) {
+ $varSlzParameters = Get-Content -Path $parJsonParamFilePath | ConvertFrom-Json
+ $varAllowEmptyParameters = @("parExpressRouteGatewayConfig", "parVpnGatewayConfig", "parCustomerPolicies")
+ $varSlzParameters.parameters.psobject.properties | ForEach-Object {
+ if (($null -eq $_.value.Value -or $_.value.Value.count -eq 0) -and ($varAllowEmptyParameters -NotContains $_.Name)) {
+ $varParameters.add($_.Name, (new-Object PsObject -property @{value = $_.value.defaultValue; defaultValue = $_.value.defaultValue }))
+ }
+ else {
+ $varParameters.add($_.Name, (new-Object PsObject -property @{value = $_.value.Value; defaultValue = $_.value.defaultValue }))
+ }
+ }
+ return $varParameters
+}
+
+<#
+.Description
+ Checks Sovereign Landing Zone Prerequisites for the deployment.
+#>
+function Confirm-Prerequisites {
+ param($parIsSLZDeployedAtTenantRoot)
+ Write-Information ">>> Checking Sovereign Landing Zone Prerequisites for the deployment" -InformationAction Continue
+ $varConfirmPrerequisites = '.\Confirm-SovereignLandingZonePrerequisites.ps1'
+ & $varConfirmPrerequisites -parAttendedLogin $parAttendedLogin -parIsSLZDeployedAtTenantRoot $parIsSLZDeployedAtTenantRoot -ErrorAction Stop
+ Write-Information ">>> Checking Sovereign Landing Zone Prerequisites is complete." -InformationAction Continue
+ return
+}
+
+<#
+.Description
+ Show management group information with a link to management group's azure portal
+#>
+function Show-ManagementGroupInfo {
+ param($parParameters)
+
+ if (!$parAttendedLogin) {
+ return
+ }
+
+ $parDeploymentPrefix = $parParameters.parDeploymentPrefix.value
+ $parTopLevelManagementGroupName = $parParameters.parTopLevelManagementGroupName.value
+ $parDeploymentSuffix = $parParameters.parDeploymentSuffix.value
+ $varTenantId = (Get-AzTenant).Id
+ $varMgName = $parTopLevelManagementGroupName -replace ' ', '%20'
+ $varManagementGroupLink = "$varAzPortalLink/#view/Microsoft_Azure_ManagementGroups/ManagmentGroupDrilldownMenuBlade/~/overview/tenantId/$varTenantId"
+ $varManagementGroupLink = "$varManagementGroupLink/mgId/$parDeploymentPrefix$parDeploymentSuffix/mgDisplayName/$varMgName/mgCanAddOrMoveSubscription~/true/mgParentAccessLevel/Owner/defaultMenuItemId/overview/drillDownMode~/true"
+ $varManagementGroupInfo = "If you want to learn more about your management group, please click following link.`n`n"
+ $varManagementGroupInfo = "$varManagementGroupInfo$varManagementGroupLink`n`n"
+
+ Write-Information ">>> $varManagementGroupInfo" -InformationAction Continue
+}
+
+<#
+.Description
+ Show dashboard information with a link to portal dashboard.
+#>
+function Show-DashboardInfo {
+ param($parParameters, $modDeployBootstrapOutputs)
+
+ if ($modDeployBootstrapOutputs) {
+ $varManagementSubscriptionId = $modDeployBootstrapOutputs.outputs.outManagementSubscriptionId.value
+ }
+ else {
+ $varManagementSubscriptionId = $parParameters.parManagementSubscriptionId.value
+ }
+
+ if (!$parAttendedLogin) {
+ return
+ }
+
+ $parDeploymentLocation = $parParameters.parDeploymentLocation.value
+ $parDeploymentPrefix = $parParameters.parDeploymentPrefix.value
+ $parDeploymentSuffix = $parParameters.parDeploymentSuffix.value
+ $varSignedInUser = Get-SignedInUser
+ $varResourceGroupName = "$parDeploymentPrefix-rg-dashboards-$parDeploymentLocation$parDeploymentSuffix"
+ $varDashboardName = "$parDeploymentPrefix-Sovereign-Landing-Zone-Dashboard-Preview-$parDeploymentLocation$parDeploymentSuffix"
+ $varUserDomain = $varSignedInUser.Substring($varSignedInUser.IndexOf("@"))
+ $varDashboardLink = "$varAzPortalLink/#$varUserDomain/dashboard/arm/subscriptions/$varManagementSubscriptionId"
+ $varDashboardLink = "$varDashboardLink/resourceGroups/$varResourceGroupName/providers/Microsoft.Portal/dashboards/$varDashboardName"
+ $varDashboardInfo = "Now your compliance dashboard is ready for you to get insights. If you want to learn more, please click following link.`n`n$varDashboardLink`n`n"
+
+ Write-Information ">>> $varDashboardInfo" -InformationAction Continue
+}
+
+<#
+.Description
+ Register resource provider.
+#>
+function Register-ResourceProvider {
+ param($parProviderNamespace)
+
+ $varResourceProvider = $null
+ $varLoopCounter = 0
+
+ Register-AzResourceProvider -ProviderNamespace $parProviderNamespace
+ $varResourceProvider = Get-AzResourceProvider -ProviderNamespace $parProviderNamespace
+ while ($null -eq $varResourceProvider -and $varLoopCounter -lt $varMaxRetryAttemptTransientErrorRetry) {
+ Start-Sleep -Seconds $varRetryWaitTimeTransientErrorRetry
+ $varResourceProvider = Get-AzResourceProvider -ProviderNamespace $parProviderNamespace
+ $varLoopCounter++
+ }
+}
+
+<#
+.Description
+ Build Subnet Json object.
+#>
+function Build-SubnetJsonObject {
+ param($parKeyValue)
+ if (![string]::IsNullOrEmpty($parKeyValue[1])) {
+ $varSubnetObject = @(
+ @{
+ name = $parKeyValue[0]
+ ipAddressRange = $parKeyValue[1]
+ })
+
+ return , $varSubnetObject
+ }
+}
+
+<#
+.Description
+ Check the bastion subnet value is provided if the deploy bastion is true.
+#>
+function Confirm-BastionRequiredValue {
+ param ($parDeployBastion, $parSubnets)
+
+ if ($parDeployBastion) {
+ $varAzureBastionSubnet = ($parSubnets | Where-Object { $_.name -eq 'AzureBastionSubnet' }).ipAddressRange
+ if ([string]::IsNullOrEmpty($varAzureBastionSubnet)) {
+ Write-Error ">>> Missing parameter value for Azure Bastion subnet IP address range. Please try after addressing the above error." -ErrorAction Stop
+ }
+ }
+}
+<#
+.Description
+Get Private DNS Resource Group Id from the Private DNS Zones output
+#>
+function Get-PrivateDnsResourceGroupId {
+ param ($parPrivateDnsZones, $parParameters)
+ $varPrivateDnsResourceGroupId = ""
+ $varDNSZonesResourceId = $parPrivateDnsZones.Count -gt 0 ? ($parPrivateDnsZones[0].id).ToString() : ""
+ if (-not [string]::IsNullOrEmpty($varDNSZonesResourceId)) {
+ $parDeploymentLocation = $parParameters.parDeploymentLocation.value
+ $varPattern = "(.*)(?<=$([regex]::escape($parDeploymentLocation)))"
+ $varRegExResult = $varDNSZonesResourceId | Select-String -Pattern $varPattern
+ $varPrivateDnsResourceGroupId = $varRegExResult.Matches[0].Value
+ }
+ return $varPrivateDnsResourceGroupId
+}
+<#
+.Description
+Get Resource Name from Resource Id
+#>
+function Get-ResourceNameFromId {
+ param($parResourceId)
+ $varResourceName = ""
+ if (-not [string]::IsNullOrEmpty($parResourceId)) {
+ $parResourceId = $parResourceId -split '/'
+ $varResourceName = $parResourceId[$parResourceId.Length - 1]
+ }
+ return $varResourceName
+}
+<#
+.Description
+Get Resource Type from Resource Id
+#>
+function Get-ResourceTypefromId {
+ param($parResourceId)
+ $varResourceType = ""
+ if (-not [string]::IsNullOrEmpty($parResourceId)) {
+ $parResourceId = $parResourceId -split '/'
+ $varResourceType = $parResourceId[$parResourceId.Length - 2]
+ }
+ return $varResourceType
+}
+
+<#
+.DESCRIPTION
+Create a new object with the output data
+#>
+function New-OutputObject {
+ param($parResourceName, $parResourceType, $parResourceId, $parDeploymentName, $parComments)
+ $varDeploymentData = [PSCustomObject]@{
+ "Resource Name" = $parResourceName
+ "Resource Type" = $parResourceType
+ "Resource Id" = $parResourceId
+ "Deployment Module" = $parDeploymentName
+ "Comments" = $parComments
+ }
+ return $varDeploymentData
+}
+
+<#
+.Description
+ Update parameter file after deployment
+#>
+function Out-DeploymentParameters {
+ param($parDeploymentName, $modDeploymentOutputs, $parManagementGroupId, $parParameters)
+ $varFilename = $parManagementGroupId + "_" + $parParameters.parDeploymentStartTime + ".csv"
+ # Set the path of the folder you want to check/create
+ $varFolderPath = "outputs"
+
+ # Check if the folder exists
+ if (-Not (Test-Path -Path $varFolderPath -PathType Container)) {
+ # If the folder does not exist, create it
+ New-Item -ItemType Directory -Path $varFolderPath -Force
+ Write-Information "Folder created: $varFolderPath" -InformationAction Continue
+ }
+ $varExistingCsvFilePath = $varFolderPath + "\" + $varFilename
+
+ $varCsvData = @()
+ if ($parDeploymentName -eq "bootstrap") {
+ $varDeploymentData = New-OutputObject $modDeploymentOutputs.outputs.outManagementSubscriptionName.value "Subscription" $modDeploymentOutputs.outputs.outManagementSubscriptionId.value $parDeploymentName "Used by platform as parManagementSubscriptionId"
+ $varCsvData += $varDeploymentData
+ $varDeploymentData = New-OutputObject $modDeploymentOutputs.outputs.outIdentitySubscriptionName.value "Subscription" $modDeploymentOutputs.outputs.outIdentitySubscriptionId.value $parDeploymentName "Used by platform as parIdentitySubscriptionId"
+ $varCsvData += $varDeploymentData
+ $varDeploymentData = New-OutputObject $modDeploymentOutputs.outputs.outConnectivitySubscriptionName.value "Subscription" $modDeploymentOutputs.outputs.outConnectivitySubscriptionId.value $parDeploymentName "Used by platform as parConnectivitySubscriptionId"
+ $varCsvData += $varDeploymentData
+ $varDeploymentData = New-OutputObject "Billing Scope" "billingScope" $parParameters.parSubscriptionBillingScope.value $parDeploymentName "Can be used for ALZ Vending module as subscriptionBillingScope"
+ $varCsvData += $varDeploymentData
+ foreach ($child in $modDeploymentOutputs.outputs.outLandingZoneChildrenManagementGroupIds.value) {
+ $varResourceName = Get-ResourceNameFromId $child
+ $varResourceType = Get-ResourceTypefromId $child
+ $varDeploymentData = New-OutputObject $varResourceName $varResourceType $child $parDeploymentName ""
+ $varCsvData += $varDeploymentData
+ }
+ foreach ($child in $modDeploymentOutputs.outputs.outPlatformChildrenManagementGroupIds.value) {
+ $varResourceName = Get-ResourceNameFromId $child
+ $varResourceType = Get-ResourceTypefromId $child
+ $varDeploymentData = New-OutputObject $varResourceName $varResourceType $child $parDeploymentName ""
+ $varCsvData += $varDeploymentData
+ }
+ }
+ elseif ($parDeploymentName -eq "platform") {
+ $varPrivateDnsResourceGroupId = Get-PrivateDnsResourceGroupId $modDeploymentOutputs.outputs.outPrivateDNSZones.value $parParameters
+ $varDdosProtectionResourceId = $modDeploymentOutputs.outputs.outDdosProtectionResourceId.value
+ $varLogAnalyticsResourceId = $modDeploymentOutputs.outputs.outLogAnalyticsWorkspaceId.value
+ $varAutomationAccountId = $modDeploymentOutputs.outputs.outAutomationAccountName.value
+ $varHubNetworkId = $modDeploymentOutputs.outputs.outHubVirtualNetworkId.value
+ if (-not [string]::IsNullOrEmpty($varDdosProtectionResourceId)) {
+ $varResourceName = Get-ResourceNameFromId $varDdosProtectionResourceId
+ $varResourceType = Get-ResourceTypefromId $varDdosProtectionResourceId
+ $varDeploymentData = New-OutputObject $varResourceName $varResourceType $varDdosProtectionResourceId $parDeploymentName "Used by platform as parDdosProtectionResourceId"
+ $varCsvData += $varDeploymentData
+ }
+ if (-not [string]::IsNullOrEmpty($varLogAnalyticsResourceId)) {
+ $varResourceName = Get-ResourceNameFromId $varLogAnalyticsResourceId
+ $varResourceType = Get-ResourceTypefromId $varLogAnalyticsResourceId
+ $varDeploymentData = New-OutputObject $varResourceName $varResourceType $varLogAnalyticsResourceId $parDeploymentName "Used by platform as parLogAnalyticsWorkspaceId"
+ $varCsvData += $varDeploymentData
+ }
+ if (-not [string]::IsNullOrEmpty($varPrivateDnsResourceGroupId)) {
+ $varResourceName = Get-ResourceNameFromId $varPrivateDnsResourceGroupId
+ $varResourceType = Get-ResourceTypefromId $varPrivateDnsResourceGroupId
+ $varDeploymentData = New-OutputObject $varResourceName $varResourceType $varPrivateDnsResourceGroupId $parDeploymentName "Used by platform as parPrivateDnsResourceGroupId"
+ $varCsvData += $varDeploymentData
+ }
+
+ if (-not [string]::isNullOrEmpty($varAutomationAccountId)) {
+ $varResourceName = $varAutomationAccountId
+ $varResourceType = "AutomationAccount"
+ $varDeploymentData = New-OutputObject $varResourceName $varResourceType $varAutomationAccountId $parDeploymentName "Used by platform as parAutomationAccountName"
+ $varCsvData += $varDeploymentData
+ }
+ if (-not [string]::IsNullOrEmpty($varHubNetworkId)) {
+ $varResourceName = Get-ResourceNameFromId $varHubNetworkId
+ $varResourceType = Get-ResourceTypefromId $varHubNetworkId
+ $varDeploymentData = New-OutputObject $varResourceName $varResourceType $varHubNetworkId $parDeploymentName "Used by platform as parHubVirtualNetworkId"
+ $varCsvData += $varDeploymentData
+ }
+ $varDeploymentData = New-OutputObject "DeploymentLocation" "Location" $parParameters.parDeploymentLocation.value $parDeploymentName "Can be used for ALZ Vending module as virtualNetworkLocation"
+ $varCsvData += $varDeploymentData
+ }
+ # If the existing CSV file exists, read its content
+ if (Test-Path -Path $varExistingCsvFilePath) {
+ $varExistingData = Import-Csv -Path $varExistingCsvFilePath
+ }
+ else {
+ # If the file doesn't exist, create an empty array
+ $varExistingData = @()
+ }
+ # Append the new data to the existing data
+ $varUpdatedData = $varExistingData + $varCsvData
+
+ # Save the updated data to the CSV file
+ $varUpdatedData | Export-Csv -Path $varExistingCsvFilePath -NoTypeInformation
+}
diff --git a/orchestration/scripts/Invoke-SlzDefaultandCustomPolicyToBicep.ps1 b/orchestration/scripts/Invoke-SlzDefaultandCustomPolicyToBicep.ps1
new file mode 100644
index 00000000..50d0efaa
--- /dev/null
+++ b/orchestration/scripts/Invoke-SlzDefaultandCustomPolicyToBicep.ps1
@@ -0,0 +1,693 @@
+# Copyright (c) Microsoft Corporation.
+# Licensed under the MIT License.
+<#
+SUMMARY: This PowerShell script leverages ALZ's invoke-PolicyToBicep.ps1 to generate new slz-defaultandCustomPolicyDefinitions.bicep with SLZ defaulat and
+custom policies. It mainly performs the following steps:
+
+- copy policy set definitions files that have atleast one policy from current definitions folder to ..\..\dependencies\infra-as-code\bicep\modules\policy\definitions\lib\policy_set_definitions folder
+
+- call ..\..\dependencies\scripts\Invoke-PolicyToBicep.ps1
+
+- merge ..\..\dependencies\infra-as-code\bicep\modules\policy\definitions\lib\policy_definitions\_policyDefinitionsBicepInput.txt
+ with ..\..\dependencies\infra-as-code\bicep\modules\policy\definitions\lib\policy_set_definitions\_policySetDefinitionsBicepInput.txt
+ into newCustomPolicyDefinitions.bicep
+
+- replace ..\dependencies\infra-as-code\bicep\modules\policy\definitions\slz-defaultandCustomPolicyDefinitions.bicep with updated slz-defaultandCustomPolicyDefinitions.bicep
+
+This design is based on ALZ automation that syncs new policies from enterprise-scale repo
+for more details please check this link https://github.com/Azure/ALZ-Bicep/wiki/PolicyDeepDive
+
+AUTHOR/S: Cloud for Sovereignty
+VERSION: 1.0.0
+#>
+[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSReviewUnusedParameter", "", Justification = "False Positive")]
+
+[CmdletBinding(SupportsShouldProcess)]
+param (
+ [Parameter()]
+ [string]
+ $parDestRootPath = "../../dependencies/infra-as-code/bicep/modules/policy",
+ [string]
+ $parDefinitionsPath = "definitions/lib/policy_definitions",
+ [string]
+ $parDefinitionsLongPath = "$parDestRootPath/$parDefinitionsPath",
+ [string]
+ $parDefinitionsSetPath = "definitions/lib/policy_set_definitions",
+ [string]
+ $parDefinitionsSetLongPath = "$parDestRootPath/$parDefinitionsSetPath",
+ [string]
+ $parDefaultPoliciesRootPath = "../../modules/compliance/policySetDefinitions",
+ [string]
+ $parCustomPoliciesRootPath = "../../custom/policies/definitions",
+ [string]
+ $parSlzPolicyPattern = "([Cc]onfidential|[Cc]orp|[Gg]lobal|[Oo]nline|[Cc]onnectivity|[Dd]ecommissioned|[Ii]dentity|[Ll]andingzone|[Mm]anagement|[Pp]latform|[Ss]andbox)",
+ [string]
+ $parSlzCustomPolicyDefinitionSetFilePattern = "slz$parSlzPolicyPattern" + "Custom",
+ [string]
+ $parSlzDefaultPolicyDefinitionSetFilePattern = "slz$parSlzPolicyPattern" + "Defaults",
+ [string]
+ $parSlzGlobalPolicySetDefinitonTxtFile = "$parDefinitionsSetLongPath/_slzGlobalPolicySetDefinitionsBicepInput.txt",
+ [string]
+ $parSlzPolicySetDefinitonTxtFile = "$parDefinitionsSetLongPath/_slzPolicySetDefinitionsBicepInput.txt",
+ [string]
+ $parAlzPolicySetDefinitonTxtFile = "$parDefinitionsSetLongPath/_alzPolicySetDefinitionsBicepInput.txt",
+ [string]
+ $parTempPolicyDefinitionOutput = "tempDefaultandCustomPolicyDefinitions.bicep",
+ [string]
+ $parTempSLZGlobalPolicySetDefinitionOutput = "slzTempGlobalDefaultandCustomPolicySetDefinitions.bicep",
+ [string]
+ $parTempSLZPolicySetDefinitionOutput = "slzTempDefaultandCustomPolicySetDefinitions.bicep",
+ [string]
+ $parTempALZPolicySetDefinitionOutput = "alzTempPolicySetDefinitions.bicep",
+ [bool]
+ $parAttendedLogin = $true
+)
+
+<#
+.Description
+Move all SLZ default and custom policy json files to destPath
+#>
+function Move-PolicySetDefinitions {
+ [CmdletBinding(SupportsShouldProcess)]
+ param([string] $parRootPath)
+
+ $varDefaultDefinitionFiles = Get-ChildItem -Path "$parRootPath/*.json"
+ foreach ($varFile in $varDefaultDefinitionFiles) {
+ Write-Debug "Processing $varFile.Name"
+
+ $varFilePath = $parRootPath + "/" + $varFile.Name
+ $varJsonContent = Get-Content $varFilePath | ConvertFrom-Json
+
+ if ($varJsonContent.properties.policyDefinitions.Length -gt 0) {
+ Copy-Item $varFilePath -Destination "$parDefinitionsSetLongPath"
+ Write-Debug ">>> copied $varFilePath to $parDefinitionsSetLongPath"
+ }
+ else {
+ Write-Debug ">>> $varFile.Name not copied to $parDefinitionsSetLongPath"
+ }
+ }
+}
+
+<#
+.Description
+ Copy files to destination path
+#>
+function Copy-SlzDefaultandCustomPolicyDefinitionsBicep {
+ [CmdletBinding(SupportsShouldProcess)]
+ param()
+
+ $varDestinationFolder = "$parDestRootPath/definitions/"
+ Write-Information ">>> Initiating copy of slz-defaultandCustomPolicyDefinitions.bicep, slz-defaultandCustomGlobalPolicySetDefinitions.bicep, slz-defaultandCustomPolicySetDefinitions.bicep and alzPolicySetDefinitions.bicep to $varDestinationFolder" -InformationAction Continue
+ Copy-Item "../policyInstallation/slz-DefaultandCustomPolicyDefinitions.txt" -Destination "$varDestinationFolder\slz-defaultandCustomPolicyDefinitions.bicep"
+ Copy-Item "../policyInstallation/slz-DefaultandCustomSLZGlobalPolicySetDefinitions.txt" -Destination "$varDestinationFolder\slz-defaultandCustomGlobalPolicySetDefinitions.bicep"
+ Copy-Item "../policyInstallation/slz-DefaultandCustomSLZPolicySetDefinitions.txt" -Destination "$varDestinationFolder\slz-defaultandCustomPolicySetDefinitions.bicep"
+ Copy-Item "../policyInstallation/alz-DefaultPolicySetDefinitions.txt" -Destination "$varDestinationFolder\alzPolicySetDefinitions.bicep"
+ Write-Information ">>> copied slz-defaultandCustomPolicyDefinitions.bicep, slz-defaultandCustomGlobalPolicySetDefinitions.bicep, slz-defaultandCustomPolicySetDefinitions.bicep and alzPolicySetDefinitions.bicep to $varDestinationFolder" -InformationAction Continue
+}
+
+<#
+.Description
+Remove existing policy set files.
+#>
+function Remove-ExistingPolicySetFiles {
+ [CmdletBinding(SupportsShouldProcess)]
+ param()
+
+ <# For slz default policies #>
+ Write-Information ">>> filtering slz default policy sets using $parSlzDefaultPolicyDefinitionSetFilePattern" -InformationAction Continue
+ Get-ChildItem -Path "$parDefinitionsSetLongPath" -Filter *.json | Where-Object { $_.Name -match $parSlzDefaultPolicyDefinitionSetFilePattern } | Remove-Item
+ Write-Information ">>> removed $parDefinitionsSetLongPath/slz*Defaults*" -InformationAction Continue
+
+ <# For slz custom policies #>
+ Write-Information ">>> filtering custom policy using $parSlzCustomPolicyDefinitionSetFilePattern" -InformationAction Continue
+ Get-ChildItem -Path "$parDefinitionsSetLongPath" -Filter *.json | Where-Object { $_.Name -match $parSlzCustomPolicyDefinitionSetFilePattern } | Remove-Item
+ Write-Information ">>> removed $parDefinitionsSetLongPath/slz*Custom*" -InformationAction Continue
+
+}
+
+<#
+.Description
+Create new policy definition bicep file.
+#>
+function Invoke-ALZScript {
+ # leverage ALZ script to add new policies/policy-sets into its bicep which slz depends on
+ Write-Information ">>> call Invoke-PolicyToBicep.ps1 to regenerate .txt reference files" -InformationAction Continue
+ & ..\..\dependencies\scripts\Invoke-PolicyToBicep.ps1 -rootPath "$parDestRootPath"
+}
+
+<#
+.Description
+Create new policy definition bicep file.
+#>
+function New-DefaultandCustomPolicyDefinitionsBicepFile {
+ [CmdletBinding(SupportsShouldProcess)]
+ param()
+
+ $varPolicyDefinitionsBicepInput = "$parDefinitionsLongPath/_policyDefinitionsBicepInput.txt"
+ $varDefaultandCustomPolicyDefinitionsBicepFile = "$parDestRootPath/definitions/slz-defaultandCustomPolicyDefinitions.bicep"
+ $varKeepCopying = $true
+
+ # processing animation for attended run
+ if ($parAttendedLogin) {
+ $varDelay = 1000
+ $varStartLeft = [Console]::CursorLeft
+ $varStartTop = [Console]::CursorTop
+ $varOriginalColor = [Console]::ForegroundColor
+ $varLoadingChars = @('-', '\', '|', '/')
+ $varPos = 0
+ }
+
+ try {
+ Set-Content -Path $parTempPolicyDefinitionOutput -Value "//`r`n// auto-generated-slz-policy-bicep-file by Cloud for Sovereignty team`r`n//"
+ Get-Content $varDefaultandCustomPolicyDefinitionsBicepFile | ForEach-Object {
+ if ($_ -match '') {
+ if ($_ -match '.+([Ss]tart)\s*-->') {
+ $varKeepCopying = $false
+
+ Add-Content -Path $parTempPolicyDefinitionOutput -Value "// start"
+ # copy $varPolicyDefinitionsBicepInput
+ Get-Content $varPolicyDefinitionsBicepInput | Add-Content -Path $parTempPolicyDefinitionOutput
+ Add-Content -Path $parTempPolicyDefinitionOutput -Value "// end"
+
+ if ($parAttendedLogin) {
+ Flush_Output "[*] loading from auto-gen file..." $varDelay $varStartLeft $varStartTop $varOriginalColor
+ }
+ }
+ elseif ($_ -match ".+([Ee]nd)\s*-->") {
+ $varKeepCopying = $true
+ }
+ }
+ else {
+ # write line to $parTempPolicyDefinitionOutput
+ if ($varKeepCopying) {
+ Add-Content -Path $parTempPolicyDefinitionOutput -Value $_
+
+ if ($parAttendedLogin) {
+ $varPos = $varPos + 1
+ $varLoadingCh = $varLoadingChars[$($varPos % $varLoadingChars.Length)]
+ Flush_Output "[$varLoadingCh] loading from original file..." 0 $varStartLeft $varStartTop Blue
+ }
+ }
+ }
+ } #end of Foreach
+ if ($parAttendedLogin) {
+ [Console]::ForegroundColor = $varOriginalColor
+ }
+ }
+ catch {
+ Write-Error "Error in merging new policy/policy-set: $_.Exception.Message"
+ }
+ #replace $varDefaultandCustomPolicyDefinitionsBicepFile with $parTempPolicyDefinitionOutput
+ Copy-Item $parTempPolicyDefinitionOutput -Destination $varDefaultandCustomPolicyDefinitionsBicepFile -force
+}
+<#
+.Description
+Create 2 slz policy files one with global policies and other with remainder slz policies from _policySetDefinitionsBicepInput.txt
+#>
+function New-SLZPolicySetDefinitonsBicepInputFiles {
+ [CmdletBinding(SupportsShouldProcess)]
+ param()
+
+ $varPolicySetDefTextFile = Get-Content "$parDefinitionsSetLongPath/_policySetDefinitionsBicepInput.txt"
+ #arraylist that will contain each slz policy set json as an array
+ $varSlzPolicySetList = New-Object -TypeName 'System.Collections.ArrayList'
+ #arraylist that will contain each slz policy set parameters
+ $varSlzPolicyParams = New-Object -TypeName 'System.Collections.ArrayList'
+ #initializing array to contain slz policy set.
+ <# Once a policy set parsing is complete, the array will be appended to 'slzPolicySetList' #>
+ [String[]] $varSlzPolicySet = @()
+
+ #arraylist that will contain each alz policy set json as an array
+ $varAlzPolicySetList = New-Object -TypeName 'System.Collections.ArrayList'
+ #arraylist that will contain each alz policy set parameters
+ $varAlzPolicyParams = New-Object -TypeName 'System.Collections.ArrayList'
+ #initializing array to contain alz policy set.
+ <# Once a policy set parsing is complete, the array will be appended to 'alzPolicySetList' #>
+ [String[]] $varAlzPolicySet = @()
+
+ <# declaring patterns #>
+ $varNameString = 'name:'
+ $varPolicyNamePattern = '(?<=name: )(.*)'
+ $varSlzPolicyNamePrefix = 'Slz'
+ $varPolicySetDefVarComment = '// Policy Set/Initiative Definition Parameter Variables'
+
+ for ($count = 0; $count -lt $varPolicySetDefTextFile.Length; $count++) {
+ $varLine = $varPolicySetDefTextFile[$count]
+
+ <#line matching 'varCustomPolicySetDefinitionsArray' represents start of the json.
+ Append this line to policyset defintion text files, as it will contain the jsons#>
+ if ($varLine -match 'varCustomPolicySetDefinitionsArray') {
+ Set-Content $parSlzGlobalPolicySetDefinitonTxtFile $varLine
+ Set-Content $parSlzPolicySetDefinitonTxtFile $varLine
+ Set-Content $parAlzPolicySetDefinitonTxtFile $varLine
+ continue
+ }
+
+ <# line matching the var 'policySetDefVarComment' indicates end of json.
+ The arrayList containing json can be added to corresponding policyset defintion text files #>
+ if ($varLine -match $varPolicySetDefVarComment) {
+ #fetch the var name of the last parsed slz policy set and add the polic set to the slz policy set list
+ $varPolicyParamVarName = Get-PolicySetParamVariableName $varSlzPolicySet
+ [void]$varSlzPolicyParams.Add($varPolicyParamVarName)
+ [void]$varSlzPolicySetList.Add($varSlzPolicySet)
+ $varSlzPolicySet = @()
+
+ #create the set definition text files, with the slz policy sets
+ Add-SlzPolicySetDefinitionTxtFiles $varLine $varSlzPolicySetList
+
+ if (Confirm-AddEndBracket $parSlzGlobalPolicySetDefinitonTxtFile) {
+ Add-Content $parSlzGlobalPolicySetDefinitonTxtFile "]`r`n$varLine"
+ }
+ else {
+ Add-Content $parSlzGlobalPolicySetDefinitonTxtFile "`r`n$varLine"
+ }
+
+ if (Confirm-AddEndBracket $parSlzPolicySetDefinitonTxtFile) {
+ Add-Content $parSlzPolicySetDefinitonTxtFile "]`r`n$varLine"
+ }
+ else {
+ Add-Content $parSlzPolicySetDefinitonTxtFile "`r`n$varLine"
+ }
+
+ #create the set definition text files, with the alz policy sets
+ Add-Content $parAlzPolicySetDefinitonTxtFile $varAlzPolicySetList
+ if (Confirm-AddEndBracket $parAlzPolicySetDefinitonTxtFile) {
+ Add-Content $parAlzPolicySetDefinitonTxtFile "]`r`n$varLine"
+ }
+ else {
+ Add-Content $parAlzPolicySetDefinitonTxtFile "`r`n$varLine"
+ }
+ continue
+ }
+
+ <# check for line containing Policy Set Parameter Variables staring with 'var'
+ and compare with vars in list 'slzPolicyParams' and 'alzPolicyParams', to add to the final bicep file #>
+ if ($varLine -match 'var ()') {
+ $varSlzGlobalPolicyParam = 'varSlzGlobal'
+ $varSlzPolicyParams | ForEach-Object {
+ if ($varLine -match $_) {
+ if ($_ -match $varSlzGlobalPolicyParam) {
+ Add-Content $parSlzGlobalPolicySetDefinitonTxtFile $varLine
+ }
+ else {
+ Add-Content $parSlzPolicySetDefinitonTxtFile $varLine
+ }
+ }
+ }
+ $varAlzPolicyParams | ForEach-Object {
+ if ($varLine -match $_) {
+ Add-Content $parAlzPolicySetDefinitonTxtFile $varLine
+ }
+ }
+ continue
+ }
+
+ <#line doesn't match 'nameString' and array slzPolicySet or alzPolicySet has size greater than zero,
+ then we are parsing a slz policy set. Add the lines to array slzPolicySet and alzPolicySet#>
+ if ($varLine -notmatch $varNameString) {
+ if ($varSlzPolicySet.Count -gt 0) {
+ $varSlzPolicySet += $varLine
+ continue
+ }
+ elseif ($varAlzPolicySet.Count -gt 0) {
+ $varAlzPolicySet += $varLine
+ continue
+ }
+ }
+
+ if ($varLine -match $varNameString) {
+ <# line matches with a name string and array alzPolicySet has size greater than zero,
+ it indicates, the end of an alz policy set json. The array can be added to 'alzPolicySetList' and reset
+ to contain next policy set #>
+ if ($varAlzPolicySet.Count -gt 0 -And $varAlzPolicySet[$varAlzPolicySet.Count - 2] -match '}') {
+ $varAlzPolicySet[$varAlzPolicySet.Count - 1] = ""
+
+ <# parsing array 'alzPolicySet' to fetch Policy Set Parameter Variable
+ and add to list 'alzPolicyParams' #>
+ $varPolicyParamVarName = Get-PolicySetParamVariableName $varAlzPolicySet
+ [void]$varAlzPolicyParams.Add($varPolicyParamVarName)
+ [void]$varAlzPolicySetList.Add($varAlzPolicySet)
+ $varAlzPolicySet = @()
+ }
+ <# line matches with a name string and array slzPolicySet has size greater than zero,
+ it indicates, the end of an slz policy set json. The array can be added to 'slzPolicySetList' and reset
+ to contain next policy set #>
+ if ($varSlzPolicySet.Count -gt 0 -And $varSlzPolicySet[$varSlzPolicySet.Count - 2] -match '}') {
+ $varSlzPolicySet[$varSlzPolicySet.Count - 1] = ""
+
+ <# parsing array 'slzPolicySet' to fetch Policy Set Parameter Variable
+ and add to list 'slzPolicyParams' #>
+ $varPolicyParamVarName = Get-PolicySetParamVariableName $varSlzPolicySet
+ [void]$varSlzPolicyParams.Add($varPolicyParamVarName)
+ [void]$varSlzPolicySetList.Add($varSlzPolicySet)
+ $varSlzPolicySet = @()
+ }
+ $varPolicySetName = ("$varLine" | Select-String -Pattern $varPolicyNamePattern).Matches[0].Value
+ <# fetch policysetname and check if its prefixed with 'SLZ'
+ to consider the policy set for newly created policy SLZ set definition files #>
+ if ($varPolicySetName.Substring(1, 3) -eq $varSlzPolicyNamePrefix) {
+ if ($varSlzPolicySet.Count -eq 0) {
+ $varSlzPolicySet = "{"
+ }
+ $varSlzPolicySet += $varLine
+ }
+ else {
+ if ($varAlzPolicySet.Count -eq 0) {
+ $varAlzPolicySet = "{"
+ }
+ $varAlzPolicySet += $varLine
+ }
+ }
+ }
+}
+
+<#
+.Description
+Get the policy set parameter variable name from the policy set json
+#>
+function Get-PolicySetParamVariableName {
+ param ($parPolicySet)
+ $varDefinitionParametersString = 'definitionParameters:'
+ $varParamPattern = 'var(.*)Parameters'
+
+ foreach ($varLine in $parPolicySet) {
+ if ($varLine -match $varDefinitionParametersString) {
+ $varRegex = [Regex]::new($varParamPattern)
+ $varMatch = $varRegex.Match($varLine)
+ return $varMatch.Value
+ }
+ }
+}
+
+<#
+.Description
+Checks whether to add an end bracket to the policy set definition file
+#>
+function Confirm-AddEndBracket {
+ param ($parPolicySetfilePath)
+ $varPolicySetFileContent = Get-Content $parPolicySetfilePath
+
+ $varIterationCounter = $varPolicySetFileContent.Count
+
+ do {
+ if ($varPolicySetFileContent[$varIterationCounter] -match '}') {
+ return $true
+ }
+
+ if ($varPolicySetFileContent[$varIterationCounter] -match ']') {
+ return $false
+ }
+
+ $varIterationCounter--;
+ } while ($varIterationCounter -gt 0)
+}
+
+<#
+.Description
+Add slz policy set definition to slz policy set definition text file
+#>
+function Add-SlzPolicySetDefinitionTxtFiles {
+ param ($parLine, $parSlzPolicySetList)
+
+ $varSlzGlobalPolicySet = 'SlzGlobal'
+ $varSlzPolicySets = @()
+
+ foreach ($varPolicySet in $parSlzPolicySetList) {
+ if ($varPolicySet[1] -match $varSlzGlobalPolicySet) {
+ #adding SLZGlobalPolicy to a separate policy set definition file
+ Add-Content $parSlzGlobalPolicySetDefinitonTxtFile $varPolicySet
+ }
+ else {
+ $varSlzPolicySets += $varPolicySet
+ }
+ }
+ #add other slz policy sets to a different policy set definition file
+ Add-Content $parSlzPolicySetDefinitonTxtFile $varSlzPolicySets
+}
+
+<#
+.Description
+Creating slz global policyset defintion bicep file
+#>
+function New-DefaultandCustomSlzGlobalPolicySetDefinitionBicepFile {
+ [CmdletBinding(SupportsShouldProcess)]
+ param()
+
+ # processing animation for attended run
+ if ($parAttendedLogin) {
+ $varDelay = 1000
+ $varStartLeft = [Console]::CursorLeft
+ $varStartTop = [Console]::CursorTop
+ $varOriginalColor = [Console]::ForegroundColor
+ $varLoadingChars = @('-', '\', '|', '/')
+ $varPos = 0
+ }
+
+ $varSlzGlobalPolicyDefinitionsSetBicepInput = "$parSlzGlobalPolicySetDefinitonTxtFile"
+ $varDefaultandCustomSLZGlobalPolicyDefinitionsBicepFile = "$parDestRootPath/definitions/slz-defaultandCustomGlobalPolicySetDefinitions.bicep"
+ $varKeepCopying = $true
+
+ try {
+ Set-Content -Path $parTempSLZGlobalPolicySetDefinitionOutput -Value "//`r`n// auto-generated-slz-policy-bicep-file by Cloud for Sovereignty team`r`n//"
+ Get-Content $varDefaultandCustomSLZGlobalPolicyDefinitionsBicepFile | ForEach-Object {
+ if ($_ -match '') {
+ if ($_ -match '.+([Ss]tart)\s*-->') {
+ $varKeepCopying = $false
+
+ Add-Content -Path $parTempSLZGlobalPolicySetDefinitionOutput -Value "// start"
+ # copy $varSlzGlobalPolicyDefinitionsSetBicepInput
+ Get-Content $varSlzGlobalPolicyDefinitionsSetBicepInput | Add-Content -Path $parTempSLZGlobalPolicySetDefinitionOutput
+ Add-Content -Path $parTempSLZGlobalPolicySetDefinitionOutput -Value "// end"
+
+ if ($parAttendedLogin) {
+ Flush_Output "[*] loading from auto-gen file..." $varDelay $varStartLeft $varStartTop $varOriginalColor
+ }
+ }
+ elseif ($_ -match ".+([Ee]nd)\s*-->") {
+ $varKeepCopying = $true
+ }
+ }
+ else {
+ # write line to $parTempSLZGlobalPolicySetDefinitionOutput
+ if ($varKeepCopying) {
+ Add-Content -Path $parTempSLZGlobalPolicySetDefinitionOutput -Value $_
+
+ if ($parAttendedLogin) {
+ $varPos = $varPos + 1
+ $varLoadingCh = $varLoadingChars[$($varPos % $varLoadingChars.Length)]
+ Flush_Output "[$varLoadingCh] loading from original file..." 0 $varStartLeft $varStartTop Blue
+ }
+ }
+ }
+ } #end of Foreach
+ if ($parAttendedLogin) {
+ [Console]::ForegroundColor = $varOriginalColor
+ }
+ }
+ catch {
+ Write-Error "Error in creating new policy/policy-set: $_.Exception.Message"
+ }
+
+ #replace $varDefaultandCustomSLZGlobalPolicyDefinitionsBicepFile with $parTempSLZGlobalPolicySetDefinitionOutput
+ Copy-Item $parTempSLZGlobalPolicySetDefinitionOutput -Destination $varDefaultandCustomSLZGlobalPolicyDefinitionsBicepFile -force
+}
+
+<#
+.Description
+Creating slz policy set defintion bicep file
+#>
+function New-DefaultandCustomSlzPolicySetDefinitionBicepFile {
+ [CmdletBinding(SupportsShouldProcess)]
+ param()
+
+ # processing animation for attended run
+ if ($parAttendedLogin) {
+ $varDelay = 1000
+ $varStartLeft = [Console]::CursorLeft
+ $varStartTop = [Console]::CursorTop
+ $varOriginalColor = [Console]::ForegroundColor
+ $varLoadingChars = @('-', '\', '|', '/')
+ $varPos = 0
+ }
+
+ $varSlzPolicyDefinitionsSetBicepInput = "$parSlzPolicySetDefinitonTxtFile"
+ $varDefaultandCustomSLZPolicyDefinitionsBicepFile = "$parDestRootPath/definitions/slz-defaultandCustomPolicySetDefinitions.bicep"
+ $varKeepCopying = $true
+
+ try {
+ Set-Content -Path $parTempSLZPolicySetDefinitionOutput -Value "//`r`n// auto-generated-slz-policy-bicep-file by Cloud for Sovereignty team`r`n//"
+ Get-Content $varDefaultandCustomSLZPolicyDefinitionsBicepFile | ForEach-Object {
+ if ($_ -match '') {
+ if ($_ -match '.+([Ss]tart)\s*-->') {
+ $varKeepCopying = $false
+
+ Add-Content -Path $parTempSLZPolicySetDefinitionOutput -Value "// start"
+ # copy $varSlzPolicyDefinitionsSetBicepInput
+ Get-Content $varSlzPolicyDefinitionsSetBicepInput | Add-Content -Path $parTempSLZPolicySetDefinitionOutput
+ Add-Content -Path $parTempSLZPolicySetDefinitionOutput -Value "// end"
+
+ if ($parAttendedLogin) {
+ Flush_Output "[*] loading from auto-gen file..." $varDelay $varStartLeft $varStartTop $varOriginalColor
+ }
+ }
+ elseif ($_ -match ".+([Ee]nd)\s*-->") {
+ $varKeepCopying = $true
+ }
+ }
+ else {
+ # write line to $parTempSLZPolicySetDefinitionOutput
+ if ($varKeepCopying) {
+ Add-Content -Path $parTempSLZPolicySetDefinitionOutput -Value $_
+
+ if ($parAttendedLogin) {
+ $varPos = $varPos + 1
+ $varLoadingCh = $varLoadingChars[$($varPos % $varLoadingChars.Length)]
+ Flush_Output "[$varLoadingCh] loading from original file..." 0 $varStartLeft $varStartTop Blue
+ }
+ }
+ }
+ } #end of Foreach
+ if ($parAttendedLogin) {
+ [Console]::ForegroundColor = $varOriginalColor
+ }
+ }
+ catch {
+ Write-Error "Error in creating new policy/policy-set: $_.Exception.Message"
+ }
+
+ #replace $varDefaultandCustomSLZPolicyDefinitionsBicepFile with $parTempSLZPolicySetDefinitionOutput
+ Copy-Item $parTempSLZPolicySetDefinitionOutput -Destination $varDefaultandCustomSLZPolicyDefinitionsBicepFile -force
+}
+
+<#
+.Description
+Creating alz policyset defintion bicep file
+#>
+function New-AlzPolicySetDefinitionBicepFile {
+ [CmdletBinding(SupportsShouldProcess)]
+ param()
+
+ # processing animation for attended run
+ if ($parAttendedLogin) {
+ $varDelay = 1000
+ $varStartLeft = [Console]::CursorLeft
+ $varStartTop = [Console]::CursorTop
+ $varOriginalColor = [Console]::ForegroundColor
+ $varLoadingChars = @('-', '\', '|', '/')
+ $varPos = 0
+ }
+
+ $alzPolicyDefinitionsSetBicepInput = "$parAlzPolicySetDefinitonTxtFile"
+ $varAlzPolicyDefinitionsBicepFile = "$parDestRootPath/definitions/alzPolicySetDefinitions.bicep"
+ $varKeepCopying = $true
+
+ try {
+ Set-Content -Path $parTempALZPolicySetDefinitionOutput -Value "//`r`n// auto-generated-slz-policy-bicep-file by Cloud for Sovereignty team`r`n//"
+ Get-Content $varAlzPolicyDefinitionsBicepFile | ForEach-Object {
+ if ($_ -match '') {
+ if ($_ -match '.+([Ss]tart)\s*-->') {
+ $varKeepCopying = $false
+
+ Add-Content -Path $parTempSLZPolicySetDefinitionOutput -Value "// start"
+ # copy $alzPolicyDefinitionsSetBicepInput
+ Get-Content $alzPolicyDefinitionsSetBicepInput | Add-Content -Path $parTempALZPolicySetDefinitionOutput
+ Add-Content -Path $parTempALZPolicySetDefinitionOutput -Value "// end"
+
+ if ($parAttendedLogin) {
+ Flush_Output "[*] loading from auto-gen file..." $varDelay $varStartLeft $varStartTop $varOriginalColor
+ }
+ }
+ elseif ($_ -match ".+([Ee]nd)\s*-->") {
+ $varKeepCopying = $true
+ }
+ }
+ else {
+ # write line to $parTempALZPolicySetDefinitionOutput
+ if ($varKeepCopying) {
+ Add-Content -Path $parTempALZPolicySetDefinitionOutput -Value $_
+
+ if ($parAttendedLogin) {
+ $varPos = $varPos + 1
+ $varLoadingCh = $varLoadingChars[$($varPos % $varLoadingChars.Length)]
+ Flush_Output "[$varLoadingCh] loading from original file..." 0 $varStartLeft $varStartTop Blue
+ }
+ }
+ }
+ } #end of Foreach
+ if ($parAttendedLogin) {
+ Flush_Output "[*] Completed loading from original files and auto-gen files." 0 $varStartLeft $varStartTop Blue $true
+ [Console]::ForegroundColor = $varOriginalColor
+ }
+ }
+ catch {
+ Write-Error "Error in creating new policy/policy-set: $_.Exception.Message"
+ }
+
+ #replace $varAlzPolicyDefinitionsBicepFile with $parTempALZPolicySetDefinitionOutput
+ Copy-Item $parTempALZPolicySetDefinitionOutput -Destination $varAlzPolicyDefinitionsBicepFile -force
+}
+
+<#
+.Description
+Remove temp files created during the slz deployment
+#>
+function Remove-TempFile {
+ [CmdletBinding(SupportsShouldProcess)]
+ param()
+
+ Write-Information "Removing tempDefaultandCustomPolicyDefinitions.bicep, slzTempGlobalDefaultandCustomPolicySetDefinitions.bicep and slzTempDefaultandCustomPolicySetDefinitions.bicep files" -InformationAction Continue
+ Get-Item -Path ".\tempDefaultandCustomPolicyDefinitions.bicep" | Remove-Item
+ Get-Item -Path ".\slzTempGlobalDefaultandCustomPolicySetDefinitions.bicep" | Remove-Item
+ Get-Item -Path ".\slzTempDefaultandCustomPolicySetDefinitions.bicep" | Remove-Item
+ Get-Item -Path ".\alzTempPolicySetDefinitions.bicep" | Remove-Item
+ Write-Information "Removed tempDefaultandCustomPolicyDefinitions.bicep, slzTempGlobalDefaultandCustomPolicySetDefinitions.bicep and slzTempDefaultandCustomPolicySetDefinitions.bicep files" -InformationAction Continue
+}
+
+<#
+.Description
+Utility function to flush output to console
+#>
+function Flush_Output {
+ param([String]$parMessage, [int]$parDelay, [int]$parStartLeft, [int]$parStartTop, [ConsoleColor]$parStartColor, [bool]$parNewLine = $false)
+
+ $varCursorTop = [Console]::CursorTop
+ [Console]::ForegroundColor = $parStartColor
+ [Console]::CursorLeft = $parStartLeft
+ [Console]::CursorTop = $parStartTop
+
+ if ($parNewLine) {
+ Write-Host $parMessage
+ }
+ else {
+ Write-Host $parMessage -NoNewline
+ }
+
+ [Console]::SetCursorPosition(0, $varCursorTop)
+ if ($parDelay -gt 0) {
+ Start-Sleep -Milliseconds $parDelay
+ }
+}
+
+Remove-ExistingPolicySetFiles
+Copy-SlzDefaultandCustomPolicyDefinitionsBicep
+<# For slz default policies #>
+Write-Information ">>> Processing default policy set definitions" -InformationAction Continue
+Move-PolicySetDefinitions $parDefaultPoliciesRootPath
+Write-Information ">>> Processed and copied SLZ default policy definition sets" -InformationAction Continue
+<# For custom policies #>
+Write-Information ">>> Processing custom policy set definitions" -InformationAction Continue
+Move-PolicySetDefinitions $parCustomPoliciesRootPath
+Write-Information ">>> Processed and copied custom policy definition sets" -InformationAction Continue
+<# Invoke ALZ Script - InvokePolicyToBicep to create files containing policy definition and policy set definition #>
+Invoke-ALZScript
+<# The function will create alz policy definition bicep file #>
+New-DefaultandCustomPolicyDefinitionsBicepFile
+<# The function will create a file containing slz global policy set, file containing remainder of the slz policies and a file for alz policies #>
+New-SLZPolicySetDefinitonsBicepInputFiles
+<# The function will create SLZ global policy set definition bicep file #>
+New-DefaultandCustomSlzGlobalPolicySetDefinitionBicepFile
+<# The function will create SLZ policy set definition bicep file #>
+New-DefaultandCustomSlzPolicySetDefinitionBicepFile
+<# The function will create ALZ policy set definition bicep file #>
+New-AlzPolicySetDefinitionBicepFile
+Remove-TempFile
diff --git a/orchestration/scripts/New-Bootstrap.ps1 b/orchestration/scripts/New-Bootstrap.ps1
new file mode 100644
index 00000000..e07c1153
--- /dev/null
+++ b/orchestration/scripts/New-Bootstrap.ps1
@@ -0,0 +1,116 @@
+# Copyright (c) Microsoft Corporation.
+# Licensed under the MIT License.
+<#
+.SYNOPSIS
+ The powershell script deploys bootstrap as part of SLZ deployment.
+#>
+
+param (
+ $parAttendedLogin = $true
+)
+
+. ".\Invoke-Helper.ps1"
+
+#variables
+$varBootstrapBicepFilePath = '..\bootstrap\bootstrap.bicep'
+$varBootstrapRequiredParams = @('parDeploymentPrefix', 'parTopLevelManagementGroupName', 'parSubscriptionBillingScope', 'parDeploymentLocation')
+
+<#
+.Description
+ Creates the management group hierarchy and subscriptions at tenant level
+ Parameters:
+ parBootstrapParametersFilePath -> path to the parameter file containing required parameters to deploy bootstrap
+ parParameters -> hash table containing parameter name and value
+#>
+function New-Bootstrap {
+ param($parBootstrapParametersFilePath, $parParameters)
+
+ if (!$parParameters) {
+ $parParameters = Read-ParametersValue($parBootstrapParametersFilePath)
+ Confirm-Parameters($varBootstrapRequiredParams)
+ Get-DonotRetryErrorCodes
+ }
+
+ $parDeploymentPrefix = $parParameters.parDeploymentPrefix.value
+ $parDeploymentSuffix = $parParameters.parDeploymentSuffix.value
+ $varManagementGroupId = "$parDeploymentPrefix$parDeploymentSuffix"
+ $parDeploymentLocation = $parParameters.parDeploymentLocation.value
+ $varDeploymentName = "deploy-bootstrap-$vartimeStamp"
+ $varParams = @{
+ parDeploymentPrefix = $parDeploymentPrefix
+ parDeploymentSuffix = $parDeploymentSuffix
+ parSubscriptionBillingScope = $parParameters.parSubscriptionBillingScope.value
+ parTopLevelManagementGroupName = $parParameters.parTopLevelManagementGroupName.value
+ parManagementSubscriptionId = $parParameters.parManagementSubscriptionId.value
+ parIdentitySubscriptionId = $parParameters.parIdentitySubscriptionId.value
+ parConnectivitySubscriptionId = $parParameters.parConnectivitySubscriptionId.value
+ parLandingZoneMgChildren = Convert-ToArray($parParameters.parLandingZoneMgChildren.value)
+ parTopLevelManagementGroupParentId = $parParameters.parTopLevelManagementGroupParentId.value
+ parTags = Convert-ToHashTable($parParameters.parTags.value)
+ }
+ $varLoopCounter = 0;
+ $varRetry = $true
+ while ($varRetry -and $varLoopCounter -lt $varMaxRetryAttemptTransientErrorRetry) {
+ $modDeployBootstrap = $null
+ try {
+ Write-Information ">>> Bootstrap deployment started" -InformationAction Continue
+
+ $modDeployBootstrap = New-AzTenantDeployment `
+ -Name $varDeploymentName `
+ -Location $parDeploymentLocation `
+ -TemplateFile $varBootstrapBicepFilePath `
+ -TemplateParameterObject $varParams `
+ -WarningAction Ignore
+
+ if (!$modDeployBootstrap) {
+ $varRetry = $false
+ Write-Error "Error while executing bootstrap deployment command" -ErrorAction Stop
+ }
+
+ if ($modDeployBootstrap.ProvisioningState -eq "Failed") {
+ Write-Error "Error occurred during bootstrap deployment." -ErrorAction Stop
+ }
+
+ Write-Information ">>> Bootstrap deployment completed`n" -InformationAction Continue
+ # Have to register Microsoft.Network early to avoid error "Subscription not registered with NRP"
+ # caused by registration delay that occurs during deployments.
+ $varConnectivitySubscriptionId = $modDeployBootstrap.Outputs.outConnectivitySubscriptionId.Value
+ Write-Information "Registering Microsoft.Network resource provider for subscription id: $varConnectivitySubscriptionId...." -InformationAction Continue
+ Set-AzContext -Subscription "$varConnectivitySubscriptionId"
+ Register-ResourceProvider "Microsoft.Network"
+ # update parameters
+ Out-DeploymentParameters "bootstrap" $modDeployBootstrap $varManagementGroupId $parParameters
+
+ return $modDeployBootstrap
+ }
+ catch {
+ $varException = $_.Exception
+ $varErrorDetails = $_.ErrorDetails
+ $varTrace = $_.ScriptStackTrace
+ if (!$varRetry) {
+ Write-Error ">>> Validation error occurred during execution . Please try after addressing the error : $varException \n $varErrorDetails \n $varTrace" -ErrorAction Stop
+ }
+ if (!$modDeployBootstrap) {
+ Write-Error ">>> Error occurred during execution . Please try after addressing the error : $varException \n $varErrorDetails \n $varTrace" -ErrorAction Stop
+ }
+ else {
+ $varDeploymentErrorCodes = Get-FailedDeploymentErrorCodes $varManagementGroupId $varDeploymentName $varTenantDeployment
+ if ($null -eq $varDeploymentErrorCodes) {
+ $varRetry = $false
+ }
+ else {
+ $varLoopCounter++
+ $varRetry = Confirm-Retry $varDeploymentErrorCodes
+ if ($varRetry -and $varLoopCounter -lt $varMaxRetryAttemptTransientErrorRetry) {
+ Write-Information ">>> Retrying deployment after waiting for $varRetryWaitTimeTransientErrorRetry secs" -InformationAction Continue
+ Start-Sleep -Seconds $varRetryWaitTimeTransientErrorRetry
+ }
+ else {
+ $varRetry = $false
+ Write-Error ">>> Error occurred in bootstrap deployment. Please try after addressing the above error." -ErrorAction Stop
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/orchestration/scripts/New-Compliance.ps1 b/orchestration/scripts/New-Compliance.ps1
new file mode 100644
index 00000000..8c39e9c6
--- /dev/null
+++ b/orchestration/scripts/New-Compliance.ps1
@@ -0,0 +1,619 @@
+# Copyright (c) Microsoft Corporation.
+# Licensed under the MIT License.
+<#
+.SYNOPSIS
+ The powershell script deploys policies as part of SLZ deployment.
+#>
+param (
+ $parAttendedLogin = $true
+)
+. ".\Invoke-Helper.ps1"
+. ".\New-PolicyExemption.ps1" -parAttendedLogin $parAttendedLogin
+. ".\New-PolicyRemediation.ps1" -parAttendedLogin $parAttendedLogin
+
+#variables
+$varDefaultComplianceBicepFilePath = '..\defaultCompliance\defaultCompliance.bicep'
+$varCustomComplianceBicepFilePath = '..\customCompliance\customCompliance.bicep'
+$varPolicyInstallationBicepFilePath = '..\policyInstallation\policyInstallation.bicep'
+$varComplianceRequiredParams = @('parDeploymentPrefix', 'parAllowedLocations', 'parAllowedLocationsForConfidentialComputing', 'parDeploymentLocation')
+$varAlzDefaultPolicyRequiredParams = @('parLogAnalyticsWorkspaceId', 'parAutomationAccountName', 'parPrivateDnsResourceGroupId')
+<#
+.Description
+ Deletes the custom and default policy assignments for each of the SLZ management groups.
+#>
+function Get-PolicyAssignmentsandExemptions {
+ param ($parParameters)
+
+ $varLoopCounter = 0;
+ while ($varLoopCounter -lt $varMaxRetryAttemptTransientErrorRetry) {
+ try {
+ Write-Information ">>> Verifying policy assignments are present in SLZ" -InformationAction Continue
+ $parDeploymentPrefix = $parParameters.parDeploymentPrefix.value
+ $parDeploymentSuffix = $parParameters.parDeploymentSuffix.value
+ $varManagementGroupId = "$parDeploymentPrefix$parDeploymentSuffix"
+ $varScope = "/providers/Microsoft.Management/managementGroups/" + $varManagementGroupId
+ $varPolicyAssignmentsList = Get-AzPolicyAssignment -Scope $varScope -WarningAction Ignore
+ if ($null -eq $varPolicyAssignmentsList) {
+ Write-Information ">>> Policy assignments are not deployed in the env." -InformationAction Continue
+ return
+ }
+
+ Write-Information ">>> Policy assignments found. Fetching policy set definition files for version check" -InformationAction Continue
+ $varPolicySetDefinitionDict = Get-PolicySetDefinitionVersion
+
+ Write-Information ">>> For deployed SLZ Policy Sets, checking if there's a version update" -InformationAction Continue
+ [System.Collections.ArrayList]$varListOfUpdatedPolicySetDefinitionIds = @()
+
+ $varPolicySetDefinitions = Get-AzPolicySetDefinition -ManagementGroupName $varManagementGroupId -WarningAction Ignore
+ foreach ($varUpcomingPolicySet in $varPolicySetDefinitionDict.GetEnumerator()) {
+ $varPolicySetDefinition = $varPolicySetDefinitions | Where-Object { $_.Name -eq $varUpcomingPolicySet.Key -or $_.Name -match "$($varUpcomingPolicySet.Key).v" }
+ $varPolicySetDefinitionVersion = $varUpcomingPolicySet.Value
+ foreach ($varPolicyset in $varPolicySetDefinition) {
+ $varDeployedPolicySetDefinitonVersion = $varPolicyset.Properties.Metadata.version
+ if ($varPolicySetDefinitionVersion -gt $varDeployedPolicySetDefinitonVersion) {
+ $varListOfUpdatedPolicySetDefinitionIds.add($varPolicyset.Name) >> $null
+ }
+ }
+ }
+
+ return $varListOfUpdatedPolicySetDefinitionIds
+ }
+ catch {
+ $varLoopCounter++
+ $varException = $_.Exception
+ $varErrorDetails = $_.ErrorDetails
+ $varTrace = $_.ScriptStackTrace
+ Write-Error "$varException \n $varErrorDetails \n $varTrace" -ErrorAction Continue
+
+ if ($varLoopCounter -eq $varMaxTransientErrorRetryAttempts) {
+ Write-Information ">>> Maximum number of retry attempts reached. Cancelling deployment." -InformationAction Continue
+ Write-Error ">>> Error ocurred during getting policy assignment. Please try after addressing the error : $varException \n $varErrorDetails \n $varTrace" -ErrorAction Stop
+ }
+ }
+ }
+}
+
+<#
+.Description
+ Deletes the custom and default policy assignments for each of the SLZ management groups.
+#>
+function Remove-PolicyAssignmentsandExemptions {
+ param ($varListOfUpdatedPolicySetDefinitionIds)
+
+ $varLoopCounter = 0;
+ $parDeploymentPrefix = $parParameters.parDeploymentPrefix.value
+ $parDeploymentSuffix = $parParameters.parDeploymentSuffix.value
+ $varManagementGroupId = "$parDeploymentPrefix$parDeploymentSuffix"
+
+ while ($varLoopCounter -lt $varMaxRetryAttemptTransientErrorRetry) {
+ try {
+ Write-Information ">>> Cleaning old policy assignments in SLZ" -InformationAction Continue
+ if (!$varListOfUpdatedPolicySetDefinitionIds) {
+ Write-Information ">>> No updates to policy set definiton id version." -InformationAction Continue
+ }
+ else {
+ Write-Information ">>> Policy assignment and exemption clean up started" -InformationAction Continue
+ $varManagementGroupNames = $varManagementGroupId, "decommissioned", "landingzones", "landingzones-confidential-corp", "landingzones-confidential-online", "landingzones-corp", "landingzones-online", "platform", "platform-connectivity", "platform-identity", "platform-management", "sandbox"
+ $varManagementGroupNames | ForEach-Object {
+ if ($_ -eq $varManagementGroupId) {
+ $varScope = "/providers/Microsoft.Management/managementGroups/" + $varManagementGroupId
+ }
+ else {
+ $varScope = "/providers/Microsoft.Management/managementGroups/" + $parDeploymentPrefix + "-" + $_ + $parDeploymentSuffix
+ }
+
+ [System.Collections.ArrayList]$varListOfUpdatedPolicyAssignmentNames = @()
+ $varAssignments = Get-AzPolicyAssignment -Scope $varScope -WarningAction Ignore
+ if ($null -ne $varAssignments) {
+ $varAssignments | ForEach-Object {
+ $varPolicyDefinitionId = $_.Properties.PolicyDefinitionId.Substring($_.Properties.PolicyDefinitionId.LastIndexOf('/') + 1)
+ if ($varListOfUpdatedPolicySetDefinitionIds.Contains($varPolicyDefinitionId)) {
+ $varListOfUpdatedPolicyAssignmentNames.Add($_.name) >> $null
+ Remove-AzPolicyAssignment -Scope $varScope -Name $_.name -WarningAction Ignore >> $null
+ }
+ }
+ }
+
+ $varExemptions = Get-AzPolicyExemption -Scope $varScope -WarningAction Ignore
+ if ($null -ne $varExemptions) {
+ $varExemptions | ForEach-Object {
+ if ($varListOfUpdatedPolicyAssignmentNames.Contains($_.name)) {
+ Remove-AzPolicyExemption -Scope $varScope -Name $_.name -WarningAction Ignore -Confirm:$false >> $null
+ }
+ }
+ }
+ }
+
+ Write-Information ">>> Policy assignment and exemption clean up completed. Executing the next steps after waiting for $varRetryWaitTimeTransientErrorRetry seconds." -InformationAction Continue
+ }
+
+ return
+ }
+ catch {
+ $varLoopCounter++
+ $varException = $_.Exception
+ $varErrorDetails = $_.ErrorDetails
+ $varTrace = $_.ScriptStackTrace
+ Write-Error "$varException \n $varErrorDetails \n $varTrace" -ErrorAction Continue
+
+ if ($varLoopCounter -eq $varMaxTransientErrorRetryAttempts) {
+ Write-Information ">>> Maximum number of retry attempts reached. Cancelling deployment." -InformationAction Continue
+ Write-Error ">>> An error occurred during Remove-PolicyAssignmentsandExemptions. Please try after addressing the error : $varException \n $varErrorDetails \n $varTrace" -ErrorAction Stop
+ }
+ }
+ }
+}
+
+<#
+.Description
+ Installs the custom and default policy sets at the root of the SLZ management group.
+#>
+function New-InstallPolicySets {
+ param ()
+ $parDeploymentPrefix = $parParameters.parDeploymentPrefix.value
+ $parDeploymentSuffix = $parParameters.parDeploymentSuffix.value
+ $varManagementGroupId = "$parDeploymentPrefix$parDeploymentSuffix"
+ $parDeploymentLocation = $parParameters.parDeploymentLocation.value
+ $varDeploymentName = "deploy-policyinstallation-$vartimeStamp"
+ $varParams = @{
+ parDeploymentPrefix = $parDeploymentPrefix
+ parDeploymentSuffix = $parDeploymentSuffix
+ parDeploymentLocation = $parDeploymentLocation
+ parDeployAlzDefaultPolicies = $parParameters.parDeployAlzDefaultPolicies.value
+ }
+ $varLoopCounter = 0;
+ $varRetry = $true
+ while ($varRetry -and $varLoopCounter -lt $varMaxRetryAttemptTransientErrorRetry) {
+ $modDeployPolicyInstallation = $null
+ try {
+ Write-Information ">>> Policy Installation started" -InformationAction Continue
+ $modDeployPolicyInstallation = New-AzManagementGroupDeployment `
+ -Name $varDeploymentName `
+ -Location $parDeploymentLocation `
+ -TemplateFile $varPolicyInstallationBicepFilePath `
+ -ManagementGroupId $varManagementGroupId `
+ -TemplateParameterObject $varParams `
+ -WarningAction Ignore
+
+ if (!$modDeployPolicyInstallation) {
+ $varRetry = $false
+ Write-Error "`n Error while executing policy installation" -ErrorAction Stop
+ }
+ if ($modDeployPolicyInstallation.ProvisioningState -eq "Failed") {
+ Write-Error "`n Error while executing policy installation" -ErrorAction Stop
+ }
+
+ Write-Information ">>> Policy installation completed" -InformationAction Continue
+ return
+ }
+ catch {
+ $varException = $_.Exception
+ $varErrorDetails = $_.ErrorDetails
+ $varTrace = $_.ScriptStackTrace
+ if (!$varRetry) {
+ Write-Error ">>> Validation error occurred during execution . Please try after addressing the error : $varException \n $varErrorDetails \n $varTrace" -ErrorAction Stop
+ }
+ if (!$modDeployPolicyInstallation) {
+ Write-Error ">>> Error occurred during execution . Please try after addressing the error : $varException \n $varErrorDetails \n $varTrace" -ErrorAction Stop
+ }
+ else {
+ $varDeploymentErrorCodes = Get-FailedDeploymentErrorCodes $varManagementGroupId $varDeploymentName $varManagementGroupDeployment
+ if ($null -eq $varDeploymentErrorCodes) {
+ $varRetry = $false
+ }
+ else {
+ $varLoopCounter++
+ $varRetry = Confirm-Retry $varDeploymentErrorCodes
+ if ($varRetry -and $varLoopCounter -lt $varMaxRetryAttemptTransientErrorRetry) {
+ Write-Information ">>> Retrying deployment after waiting for $varRetryWaitTimeTransientErrorRetry secs" -InformationAction Continue
+ Start-Sleep -Seconds $varRetryWaitTimeTransientErrorRetry
+ }
+ else {
+ $varRetry = $false
+ Write-Error ">>> Error occurred in install policy sets. Please try after addressing the above error." -ErrorAction Stop
+ }
+ }
+ }
+ }
+ }
+}
+
+
+
+<#
+.Description
+ Assigns the custom policy sets to the SLZ management groups based on convention
+#>
+function New-CustomCompliance {
+ param()
+ $parDeploymentPrefix = $parParameters.parDeploymentPrefix.value
+ $parDeploymentSuffix = $parParameters.parDeploymentSuffix.value
+ $varManagementGroupId = "$parDeploymentPrefix$parDeploymentSuffix"
+ $parDeploymentLocation = $parParameters.parDeploymentLocation.value
+ $varCustomerPolicySets = Convert-ToArray($parParameters.parCustomerPolicySets.value)
+ $varParams = @{
+ parDeploymentPrefix = $parDeploymentPrefix
+ parDeploymentSuffix = $parDeploymentSuffix
+ parRequireOwnerRolePermission = $parParameters.parRequireOwnerRolePermission.value
+ parCustomerPolicySets = $varCustomerPolicySets
+ }
+
+ $varDeploymentName = "deploy-customcompliance-$vartimeStamp"
+ $varCustomPolicySetExists = Confirm-PolicySetExists $varManagementGroupId "custom"
+ if ($varCustomPolicySetExists -eq $true) {
+ $varLoopCounter = 0;
+ $varRetry = $true
+ while ($varRetry -and $varLoopCounter -lt $varMaxRetryAttemptTransientErrorRetry) {
+ $modDeployCustomCompliance = $null
+ try {
+ Write-Information ">>> Custom compliance deployment started" -InformationAction Continue
+
+ $modDeployCustomCompliance = New-AzManagementGroupDeployment `
+ -Name $varDeploymentName `
+ -Location $parDeploymentLocation `
+ -TemplateFile $varCustomComplianceBicepFilePath `
+ -ManagementGroupId $varManagementGroupId `
+ -TemplateParameterObject $varParams `
+ -WarningAction Ignore
+
+ if (!$modDeployCustomCompliance) {
+ Write-Error "`n>>> Error occurred in custom policy set assignment." -ErrorAction Stop
+ }
+ if ($modDeployCustomCompliance.ProvisioningState -eq "Failed") {
+ Write-Error "Error occurred during custom compliance deployment." -ErrorAction Stop
+ }
+
+ Write-Information ">>> Custom compliance completed `n" -InformationAction Continue
+ return $modDeployCustomCompliance
+ }
+ catch {
+ $varException = $_.Exception
+ $varErrorDetails = $_.ErrorDetails
+ $varTrace = $_.ScriptStackTrace
+ if (!$varRetry) {
+ Write-Error ">>> Validation error occurred during execution . Please try after addressing the error : $varException \n $varErrorDetails \n $varTrace" -ErrorAction Stop
+ }
+ if (!$modDeployCustomCompliance) {
+ Write-Error ">>> Error occurred during execution . Please try after addressing the error : $varException \n $varErrorDetails \n $varTrace" -ErrorAction Stop
+ }
+ else {
+ $varDeploymentErrorCodes = Get-FailedDeploymentErrorCodes $varManagementGroupId $varDeploymentName $varManagementGroupDeployment
+ if ($null -eq $varDeploymentErrorCodes) {
+ $varRetry = $false
+ }
+ else {
+ $varLoopCounter++
+ $varRetry = Confirm-Retry $varDeploymentErrorCodes
+ if ($varRetry -and $varLoopCounter -lt $varMaxRetryAttemptTransientErrorRetry) {
+ Write-Information ">>> Retrying deployment after waiting for $varRetryWaitTimeTransientErrorRetry secs" -InformationAction Continue
+ Start-Sleep -Seconds $varRetryWaitTimeTransientErrorRetry
+ }
+ else {
+ $varRetry = $false
+ Write-Error ">>> Error occurred in custom compliance deployment. Please try after addressing the above error." -ErrorAction Stop
+ }
+ }
+ }
+ }
+ }
+ }
+ else {
+ Write-Error ">>> The required custom policy sets were not found. Please try again after some time." -ErrorAction Stop
+ }
+}
+
+<#
+.Description
+ Assigns the default policy sets to the SLZ management groups based on convention
+#>
+function New-DefaultCompliance {
+ param($parDdosProtectionResourceId, $parLogAnalyticsWorkspaceId, $parAutomationAccountName, $parPrivateDnsResourceGroupId)
+ $parDeploymentPrefix = $parParameters.parDeploymentPrefix.value
+ $parDeploymentSuffix = $parParameters.parDeploymentSuffix.value
+ $varManagementGroupId = "$parDeploymentPrefix$parDeploymentSuffix"
+ $parDeploymentLocation = $parParameters.parDeploymentLocation.value
+ $parAllowedLocations = $parParameters.parAllowedLocations.value
+ $parAllowedLocationsForConfidentialComputing = $parParameters.parAllowedLocationsForConfidentialComputing.value
+
+ if ($parAllowedLocations -is [string]) {
+ $parAllowedLocations = -split $parAllowedLocations
+ }
+
+ if ($parAllowedLocationsForConfidentialComputing -is [string]) {
+ $parAllowedLocationsForConfidentialComputing = -split $parAllowedLocationsForConfidentialComputing
+ }
+
+ $varParams = @{
+ parDeploymentPrefix = $parDeploymentPrefix
+ parDeploymentSuffix = $parDeploymentSuffix
+ parAllowedLocations = $parAllowedLocations
+ parAllowedLocationsForConfidentialComputing = $parAllowedLocationsForConfidentialComputing
+ parDeployAlzDefaultPolicies = $parParameters.parDeployAlzDefaultPolicies.value
+ parDdosPlanResourceId = $parDdosProtectionResourceId
+ parLogAnalyticsWorkspaceId = $parLogAnalyticsWorkspaceId
+ parAutomationAccountName = $parAutomationAccountName
+ parLogAnalyticsWorkSpaceAndAutomationAccountLocation = $parDeploymentLocation
+ parPrivateDnsResourceGroupId = $parPrivateDnsResourceGroupId
+ parLogAnalyticsWorkspaceLogRetentionInDays = ($parParameters.parLogRetentionInDays.value).ToString()
+ parMsDefenderForCloudEmailSecurityContact = $parParameters.parMsDefenderForCloudEmailSecurityContact.value
+ parPolicyEffect = $parParameters.parPolicyEffect.value
+ }
+
+ $varDeploymentName = "deploy-defaultcompliance-$vartimeStamp"
+ $varDefaultPolicySetExists = Confirm-PolicySetExists $varManagementGroupId "default"
+ if ($varDefaultPolicySetExists -eq $true) {
+ $varRetry = $true
+ while ($varRetry -and $varLoopCounter -lt $varMaxRetryAttemptTransientErrorRetry) {
+ $modDeployDefaultCompliance = $null;
+ try {
+ Write-Information ">>> Default compliance deployment started" -InformationAction Continue
+
+ $modDeployDefaultCompliance = New-AzManagementGroupDeployment `
+ -Name $varDeploymentName `
+ -Location $parDeploymentLocation `
+ -TemplateFile $varDefaultComplianceBicepFilePath `
+ -ManagementGroupId $varManagementGroupId `
+ -TemplateParameterObject $varParams `
+ -WarningAction Ignore
+
+ if (!$modDeployDefaultCompliance) {
+ $varRetry = $false
+ Write-Error "`n>>> Error occurred in default policy set assignment." -ErrorAction Stop
+ }
+
+ if ($modDeployDefaultCompliance.ProvisioningState -eq "Failed") {
+ Write-Error "Error occurred during default compliance deployment." -ErrorAction Stop
+ }
+
+ Write-Information ">>> Default compliance completed" -InformationAction Continue
+ return $modDeployDefaultCompliance
+ }
+ catch {
+ $varException = $_.Exception
+ $varErrorDetails = $_.ErrorDetails
+ $varTrace = $_.ScriptStackTrace
+ if (!$varRetry) {
+ Write-Error ">>> Validation error occurred during execution . Please try after addressing the error : $varException \n $varErrorDetails \n $varTrace" -ErrorAction Stop
+ }
+ if (!$modDeployDefaultCompliance) {
+ Write-Error ">>> Error occurred during execution . Please try after addressing the error : $varException \n $varErrorDetails \n $varTrace" -ErrorAction Stop
+ }
+ else {
+ $varDeploymentErrorCodes = Get-FailedDeploymentErrorCodes $varManagementGroupId $varDeploymentName $varManagementGroupDeployment
+ if ($null -eq $varDeploymentErrorCodes) {
+ $varRetry = $false
+ }
+ else {
+ $varLoopCounter++
+ $varRetry = Confirm-Retry $varDeploymentErrorCodes
+ if ($varRetry -and $varLoopCounter -lt $varMaxRetryAttemptTransientErrorRetry) {
+ Write-Information ">>> Retrying deployment after waiting for $varRetryWaitTimeTransientErrorRetry secs" -InformationAction Continue
+ Start-Sleep -Seconds $varRetryWaitTimeTransientErrorRetry
+ }
+ else {
+ $varRetry = $false
+ Write-Error ">>> Error occurred in default compliance deployment. Please try after addressing the above error." -ErrorAction Stop
+ }
+ }
+ }
+ }
+ }
+ }
+ else {
+ Write-Error ">>> The required default policy sets were not found. Please try again after some time." -ErrorAction Stop
+ return $false
+ }
+}
+
+<#
+.Description
+ On demand policy evaluation
+#>
+function Invoke-PolicyEvaluation {
+ param()
+ if ($parAttendedLogin) {
+ Write-Information ">>> In order to reflect the latest compliance data of policies, you will now be logged out of Azure and asked to re-login. Please authenticate when prompted." -InformationAction Continue
+ Disconnect-AzAccount
+ Connect-AzAccount
+ }
+ else {
+ return
+ }
+ Write-Information ">>> Trigerring policy scan." -InformationAction Continue
+ try {
+ $parDeploymentPrefix = $parParameters.parDeploymentPrefix.value
+ $parDeploymentSuffix = $parParameters.parDeploymentSuffix.value
+ $varSubscriptions = $null;
+ if (!$parParameters.parIdentitySubscriptionId.value -and !$parParameters.parConnectivitySubscriptionId.value -and !$parParameters.parManagementSubscriptionId.value) {
+ $varSubscriptions = Get-AzSubscription | Where-Object { $_.Name -like "$parDeploymentPrefix*$parDeploymentSuffix" -and $_.State -eq 'Enabled' }
+ }
+ else {
+ $varIdentitySubscriptionId = $parParameters.parIdentitySubscriptionId.value
+ $parConnectivitySubscriptionId = $parParameters.parConnectivitySubscriptionId.value
+ $varManagementSubscriptionId = $parParameters.parManagementSubscriptionId.value
+ $varSubscriptions = Get-AzSubscription | Where-Object { ($_.Id -eq "$varIdentitySubscriptionId" -or $_.Id -eq "$parConnectivitySubscriptionId" -or $_.Id -eq "$varManagementSubscriptionId") -and $_.State -eq 'Enabled' }
+ }
+
+ if (!$varSubscriptions) {
+ Write-Error "Error while executing subscription list command" -ErrorAction Stop
+ }
+ $varSubscriptionCount = $varSubscriptions.count
+ if ($varSubscriptionCount -eq 0) {
+ Write-Information ">>> No subscriptions found" -InformationAction Continue
+ }
+
+ $parInvokePolicyScanSync = $parParameters.parInvokePolicyScanSync.value
+ if ($parInvokePolicyScanSync) {
+ Write-Information ">>> Policy scan will be executed in synchronous mode. The process may take up to an hour." -InformationAction Continue
+ }
+ else {
+ Write-Information ">>> Policy scan will be executed in asynchronous mode." -InformationAction Continue
+ }
+
+ $varSubscriptionCounter = 1
+ foreach ($varSubscription in $varSubscriptions) {
+ $varSubscriptionId = $varSubscription.Id;
+ Write-Information "Executing policy evaluation scan for subscription id: $varSubscriptionId . Processing $varSubscriptionCounter out of $varSubscriptionCount. " -InformationAction Continue
+ $varSubscriptionCounter++
+
+ # This is not logic requirement, but have to register Microsoft.Network early to avoid Subscription XXXXX-XXXXX-XXXXXXX-XXXXXXX is not registered with NRP because of registration delay.
+ Write-Information ">>> Registering Microsoft.Network resource provider for existing subscriptions..." -InformationAction Continue
+ Set-AzContext -Subscription "$varSubscriptionId"
+ Register-AzResourceProvider -ProviderNamespace Microsoft.Network
+
+ Write-Information "Registering policy insights resource provider for subscription id: $varSubscriptionId (May take upto 2 minutes)...." -InformationAction Continue
+ Set-AZContext -Subscription $varSubscriptionId
+ $varJob = Register-AzResourceProvider `
+ -ProviderNamespace 'Microsoft.PolicyInsights' `
+ -AsJob
+ $varJob | Wait-Job
+
+ if ($parInvokePolicyScanSync) {
+ $varJob = Start-AzPolicyComplianceScan -AsJob
+ $varJob | Wait-Job
+ }
+ else {
+ Start-AzPolicyComplianceScan
+ }
+ }
+ Write-Information "Policy scan completed." -InformationAction Continue
+ }
+ catch {
+ $_
+ Write-Error ">>> Error occurred during policy evaluation. Please try after addressing the above error." -ErrorAction Stop
+ }
+}
+
+<#
+.Description
+ Generates the Policies.
+#>
+function Invoke-PolicyGeneration {
+
+ try {
+
+ Write-Information ">>> Initiating Policy generation script" -InformationAction Continue
+
+ $varInvokeSLZDefaultandCustomPolicy = '.\Invoke-SlzDefaultandCustomPolicyToBicep.ps1'
+ & $varInvokeSLZDefaultandCustomPolicy -parAttendedLogin $parAttendedLogin -ErrorAction Stop
+
+ Write-Information ">>> Policy generation complete" -InformationAction Continue
+ return
+ }
+ catch {
+ $varTrace = $_.ScriptStackTrace
+ Write-Error ">>> Error occurred during executing policy generation script. Please try after addressing the below error: $_ $varTrace" -ErrorAction Stop
+ }
+}
+
+<#
+.Description
+ Gets the default and custom policy set definition name and versions.
+#>
+function Get-PolicySetDefinitionVersion {
+ $varTargetDirectories = "../../modules/compliance/policySetDefinitions", "../../custom/policies/definitions"
+ $varPolicySetDefinitionDict = @{}
+ foreach ($varDirectory in $varTargetDirectories) {
+ $varSlzPolicySetDefinitionFiles = Get-ChildItem -Path "$varDirectory/*.json"
+ foreach ($varFile in $varSlzPolicySetDefinitionFiles) {
+ $varFileName = $varFile.Name
+ Write-Debug "Processing $varFileName"
+
+ $varFilePath = $varDirectory + "/" + $varFileName
+ $varJsonContent = Get-Content $varFilePath | ConvertFrom-Json
+ if ($varJsonContent.properties.policyDefinitions.Length -gt 0 -and $varJsonContent.name) {
+ $varPolicySetDefinitionDict[$varJsonContent.name] = $varJsonContent.properties.metadata.version
+ }
+ else {
+ Write-Information ">>> $varFileName not checked for version" -InformationAction Continue
+ }
+ }
+ return $varPolicySetDefinitionDict
+ }
+
+}
+
+<#
+.Description
+ Creates the management group hierarchy and subscriptions at tenant level
+ Parameters:
+ parComplianceParametersFilePath -> path to the parameter file containing required parameters to deploy policies
+ varParameters -> hash table containing parameter name and value
+ modDeploySovereignPlatformOutputs -> hash table containing parameter outputs from platform deployment
+#>
+function New-Compliance {
+ param($parComplianceParametersFilePath, $parParameters, $parDeploySovereignPlatformOutputs)
+
+ if (!$parParameters -and !$parDeploySovereignPlatformOutputs) {
+ $parParameters = Read-ParametersValue($parComplianceParametersFilePath)
+ $parDeployAlzDefaultPolicies = $parParameters.parDeployAlzDefaultPolicies.value
+ if ($parDeployAlzDefaultPolicies) {
+ $varComplianceRequiredParams = $varComplianceRequiredParams + $varAlzDefaultPolicyRequiredParams
+ }
+ Confirm-Parameters($varComplianceRequiredParams)
+ Get-DonotRetryErrorCodes
+ }
+
+ if ($parDeploySovereignPlatformOutputs) {
+ $varDeployHubNetwork = $parParameters.parDeployHubNetwork.value
+ $varDeployDdosProtection = $parParameters.parDeployDdosProtection.value
+ if ($varDeployHubNetwork -and $varDeployDdosProtection) {
+ $varDdosProtectionResourceId = $parDeploySovereignPlatformOutputs.outputs.outDdosProtectionResourceId.value
+ }
+ else {
+ $varDdosProtectionResourceId = $parParameters.parDdosProtectionResourceId.value
+ }
+
+ $varDeployLogAnalyticsWorkspace = $parParameters.parDeployLogAnalyticsWorkspace.value
+ if ($varDeployLogAnalyticsWorkspace) {
+ $parLogAnalyticsWorkspaceId = $parDeploySovereignPlatformOutputs.outputs.outLogAnalyticsWorkspaceId.value
+ }
+ else {
+ $parLogAnalyticsWorkspaceId = $parParameters.parLogAnalyticsWorkspaceId.value
+ }
+
+ $varAutomationAccountName = $parDeploySovereignPlatformOutputs.outputs.outAutomationAccountName.value
+ $varPrivateDnsZones = $parDeploySovereignPlatformOutputs.outputs.outPrivateDNSZones.value
+ $varPrivateDnsResourceGroupId = Get-PrivateDnsResourceGroupId $varPrivateDnsZones $parParameters
+ }
+ else {
+ $varDdosProtectionResourceId = $parParameters.parDdosProtectionResourceId.value
+ $parLogAnalyticsWorkspaceId = $parParameters.parLogAnalyticsWorkspaceId.value
+ $varAutomationAccountName = $parParameters.parAutomationAccountName.value
+ $varPrivateDnsResourceGroupId = $parParameters.parPrivateDnsResourceGroupId.value
+ }
+
+ # Get the old policy assignments
+ $varListOfUpdatedPolicySetDefinitionIds = Get-PolicyAssignmentsandExemptions $parParameters
+
+ # Generate Default and custom policy sets
+ Invoke-PolicyGeneration
+ #Install default and custom policy sets
+ New-InstallPolicySets
+ # Assign default policy sets
+ $modDeployDefaultCompliance = New-DefaultCompliance $varDdosProtectionResourceId $parLogAnalyticsWorkspaceId $varAutomationAccountName $varPrivateDnsResourceGroupId
+ if (!$modDeployDefaultCompliance) {
+ Write-Error "Default compliance deployment script failed." -ErrorAction Stop
+ }
+ # Assign custom policy sets
+ $modDeployCustomCompliance = New-CustomCompliance
+ if (!$modDeployCustomCompliance) {
+ Write-Error "Custom compliance deployment script failed." -ErrorAction Stop
+ }
+
+ #Run policy exemption
+ Invoke-PolicyExemption $null $parParameters
+ #Run policy evaluation to update policy compliance state
+ Invoke-PolicyEvaluation
+ $parInvokePolicyScanSync = $parParameters.parInvokePolicyScanSync.value
+ if (!$parInvokePolicyScanSync) {
+ Write-Information ">>> Currently it is not possible to track progress of policy scan when executed asynchronously. Please execute the policy remediation after 24 hours by selecting the 'policyremediation' deployment option." -InformationAction Continue
+ }
+ else {
+ #Run policy remediation to reflect policy compliance state
+ Invoke-PolicyRemediation $null $parParameters
+ }
+
+ #Removes the old policy assignments
+ Remove-PolicyAssignmentsandExemptions $varListOfUpdatedPolicySetDefinitionIds
+}
diff --git a/orchestration/scripts/New-Dashboard.ps1 b/orchestration/scripts/New-Dashboard.ps1
new file mode 100644
index 00000000..b33cc142
--- /dev/null
+++ b/orchestration/scripts/New-Dashboard.ps1
@@ -0,0 +1,115 @@
+# Copyright (c) Microsoft Corporation.
+# Licensed under the MIT License.
+<#
+.SYNOPSIS
+ The powershell script deploys dashboard as part of SLZ deployment.
+#>
+param (
+ $parAttendedLogin = $true
+)
+. ".\Invoke-Helper.ps1"
+
+#variables
+$varDashboardBicepFilePath = '..\dashboard\dashboard.bicep'
+$varDashboardRequiredParams = @('parDeploymentPrefix', 'parDeploymentLocation', 'parManagementSubscriptionId')
+
+<#
+.Description
+ Creates the SLZ Dashboard under the management group
+ Parameters:
+ parDashboardParametersFilePath -> path to the parameter file containing required parameters to deploy dashboard
+ varParameters -> hash table containing parameter name and value
+ modDeployBootstrapOutputs -> hash table containing parameter outputs from bootstrap deployment
+#>
+function New-Dashboard {
+ param($parDashboardParametersFilePath, $parParameters, $parDeployBootstrapOutputs)
+
+ if (!$parParameters -and !$parDeployBootstrapOutputs) {
+ $parParameters = Read-ParametersValue($parDashboardParametersFilePath)
+ Confirm-Parameters($varDashboardRequiredParams)
+ Get-DonotRetryErrorCodes
+ }
+
+ if ($parDeployBootstrapOutputs) {
+ $varManagementSubscriptionId = $parDeployBootstrapOutputs.outputs.outManagementSubscriptionId.value
+ }
+ else {
+ $varManagementSubscriptionId = $parParameters.parManagementSubscriptionId.value
+ }
+
+ $parDeploymentPrefix = $parParameters.parDeploymentPrefix.value
+ $parDeploymentSuffix = $parParameters.parDeploymentSuffix.value
+ $varManagementGroupId = "$parDeploymentPrefix$parDeploymentSuffix"
+ $parDeploymentLocation = $parParameters.parDeploymentLocation.value
+ $varDeploymentName = "deploy-dashboard-$vartimeStamp"
+
+ $varParams = @{
+ parDeploymentLocation = $parDeploymentLocation
+ parDeploymentPrefix = $parDeploymentPrefix
+ parDeploymentSuffix = $parDeploymentSuffix
+ parManagementSubscriptionId = $varManagementSubscriptionId
+ parCustomer = $parParameters.parCustomer.value
+ parTags = Convert-ToHashTable($parParameters.parTags.value)
+ }
+ $varLoopCounter = 0;
+ $varRetry = $true
+ while ($varRetry -and $varLoopCounter -lt $varMaxRetryAttemptTransientErrorRetry) {
+ $modDeployDashboard = $null
+ try {
+ Write-Information ">>> Dashboard deployment started" -InformationAction Continue
+
+ $modDeployDashboard = New-AzManagementGroupDeployment `
+ -Name $varDeploymentName `
+ -Location $parDeploymentLocation `
+ -TemplateFile $varDashboardBicepFilePath `
+ -ManagementGroupId $varManagementGroupId `
+ -TemplateParameterObject $varParams `
+ -WarningAction Ignore
+
+ if (!$modDeployDashboard) {
+ $varRetry = $false
+ Write-Error "Error while executing dashboard deployment" -ErrorAction Stop
+ }
+ if ($modDeployDashboard.ProvisioningState -eq "Failed") {
+ Write-Error "Error occurred during dashboard deployment." -ErrorAction Stop
+ }
+
+ Write-Information ">>> Dashboard deployment completed `n" -InformationAction Continue
+
+ if (!$parAttendedLogin) {
+ Write-Information ">>> Please note: it can take up to 24 hours for the dashboard to reflect the latest data." -InformationAction Continue
+ }
+
+ return $modDeployDashboard
+ }
+ catch {
+ $varException = $_.Exception
+ $varErrorDetails = $_.ErrorDetails
+ $varTrace = $_.ScriptStackTrace
+ if (!$varRetry) {
+ Write-Error ">>> Validation error occurred during execution . Please try after addressing the error : $varException \n $varErrorDetails \n $varTrace" -ErrorAction Stop
+ }
+ if (!$modDeployDashboard) {
+ Write-Error ">>> Error occurred during execution . Please try after addressing the error : $varException \n $varErrorDetails \n $varTrace" -ErrorAction Stop
+ }
+ else {
+ $varDeploymentErrorCodes = Get-FailedDeploymentErrorCodes $varManagementGroupId $varDeploymentName $varManagementGroupDeployment
+ if ($null -eq $varDeploymentErrorCodes) {
+ $varRetry = $false
+ }
+ else {
+ $varLoopCounter++
+ $varRetry = Confirm-Retry $varDeploymentErrorCodes
+ if ($varRetry -and $varLoopCounter -lt $varMaxRetryAttemptTransientErrorRetry) {
+ Write-Information ">>> Retrying deployment after waiting for $varRetryWaitTimeTransientErrorRetry secs" -InformationAction Continue
+ Start-Sleep -Seconds $varRetryWaitTimeTransientErrorRetry
+ }
+ else {
+ $varRetry = $false
+ Write-Error ">>> Error occurred in dashboard deployment. Please try after addressing the above error." -ErrorAction Stop
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/orchestration/scripts/New-Platform.ps1 b/orchestration/scripts/New-Platform.ps1
new file mode 100644
index 00000000..d1ac5df7
--- /dev/null
+++ b/orchestration/scripts/New-Platform.ps1
@@ -0,0 +1,164 @@
+# Copyright (c) Microsoft Corporation.
+# Licensed under the MIT License.
+<#
+.SYNOPSIS
+ The powershell script deploys platform as part of SLZ deployment.
+#>
+param (
+ $parAttendedLogin = $true
+)
+. ".\Invoke-Helper.ps1"
+
+#variables
+$varSovereignPlatformBicepFilePath = '..\sovereignPlatform\sovereignPlatform.bicep'
+$varPlatformRequiredParams = @('parDeploymentPrefix', 'parDeploymentLocation', 'parManagementSubscriptionId', 'parIdentitySubscriptionId', 'parConnectivitySubscriptionId')
+<#
+.Description
+ Deploys resources and resource groups to subscriptions
+ Parameters:
+ parPlatformParametersFilePath -> path to the parameter file containing required parameters to deploy platform
+ varParameters -> hash table containing parameter name and value
+ modDeployBootstrapOutputs -> hash table containing parameter outputs from bootstrap deployment
+#>
+function New-Platform {
+ param($parPlatformParametersFilePath, $parParameters, $parDeployBootstrapOutputs)
+
+ if (!$parParameters -and !$parDeployBootstrapOutputs) {
+ $parParameters = Read-ParametersValue($parPlatformParametersFilePath)
+ Confirm-Parameters($varPlatformRequiredParams)
+ Get-DonotRetryErrorCodes
+ }
+
+ if ($parDeployBootstrapOutputs) {
+ $varConnectivitySubscriptionId = $parDeployBootstrapOutputs.outputs.outConnectivitySubscriptionId.value
+ $varIdentitySubscriptionId = $parDeployBootstrapOutputs.outputs.outIdentitySubscriptionId.value
+ $varManagementSubscriptionId = $parDeployBootstrapOutputs.outputs.outManagementSubscriptionId.value
+ }
+ else {
+ $varConnectivitySubscriptionId = $parParameters.parConnectivitySubscriptionId.value
+ $varIdentitySubscriptionId = $parParameters.parIdentitySubscriptionId.value
+ $varManagementSubscriptionId = $parParameters.parManagementSubscriptionId.value
+ }
+ if ([string]::IsNullOrEmpty($varConnectivitySubscriptionId) -or [string]::IsNullOrEmpty($varIdentitySubscriptionId) -or [string]::IsNullOrEmpty($varManagementSubscriptionId)) {
+ Write-Error "One or more subscription id is missing. Please rerun the deployment." -ErrorAction stop
+ }
+
+ $modCheckSubscriptionsExistsOutput = Confirm-SubscriptionsExists $varConnectivitySubscriptionId $varManagementSubscriptionId $varIdentitySubscriptionId
+ if ($modCheckSubscriptionsExistsOutput) {
+ Write-Information ">>>Subscriptions found" -InformationAction Continue
+ }
+ else {
+ Write-Error "One or more subscription not found. Please rerun the deployment." -ErrorAction stop
+ }
+
+ $parDeploymentPrefix = $parParameters.parDeploymentPrefix.value
+ $parDeploymentSuffix = $parParameters.parDeploymentSuffix.value
+ $varManagementGroupId = "$parDeploymentPrefix$parDeploymentSuffix"
+ $parDeploymentLocation = $parParameters.parDeploymentLocation.value
+ $parDeployBastion = $parParameters.parDeployBastion.value
+ $varSubnets = Convert-ToArray($parParameters.parCustomSubnets.value)
+ $varSubnets += Build-SubnetJsonObject("AzureBastionSubnet", $parParameters.parAzureBastionSubnet.value)
+ $varSubnets += Build-SubnetJsonObject("GatewaySubnet", $parParameters.parGatewaySubnet.value)
+ $varSubnets += Build-SubnetJsonObject("AzureFirewallSubnet", $parParameters.parAzureFirewallSubnet.value)
+
+ Confirm-BastionRequiredValue $parDeployBastion $varSubnets
+ $deploymentName = "deploy-platform-$vartimeStamp"
+ $varParams = @{
+ parConnectivitySubscriptionId = $varConnectivitySubscriptionId
+ parIdentitySubscriptionId = $varIdentitySubscriptionId
+ parManagementSubscriptionId = $varManagementSubscriptionId
+ parDeploymentPrefix = $parParameters.parDeploymentPrefix.value
+ parDeploymentSuffix = $parParameters.parDeploymentSuffix.value
+ parDeployDdosProtection = $parParameters.parDeployDdosProtection.value
+ parDeployHubNetwork = $parParameters.parDeployHubNetwork.value
+ parUsePremiumFirewall = $parParameters.parUsePremiumFirewall.value
+ parEnableFirewall = $parParameters.parEnableFirewall.value
+ parLogRetentionInDays = $parParameters.parLogRetentionInDays.value
+ parDeploymentLocation = $parParameters.parDeploymentLocation.value
+ parHubNetworkAddressPrefix = $parParameters.parHubNetworkAddressPrefix.value
+ parDeployBastion = $parParameters.parDeployBastion.value
+ parSubnets = $varSubnets
+ parExpressGatewaySku = $parParameters.parExpressRouteGatewayConfig.value.sku
+ parExpressGatewayVpntype = $parParameters.parExpressRouteGatewayConfig.value.vpntype
+ parExpressGatewayGeneration = $parParameters.parExpressRouteGatewayConfig.value.vpnGatewayGeneration
+ parExpressGatewayEnableBgp = $parParameters.parExpressRouteGatewayConfig.value.enableBgp
+ parExpressGatewayActiveActive = $parParameters.parExpressRouteGatewayConfig.value.activeActive
+ parExpressGatewayEnableBgpRouteTranslationForNat = $parParameters.parExpressRouteGatewayConfig.value.enableBgpRouteTranslationForNat
+ parExpressGatewayEnableDnsForwarding = $parParameters.parExpressRouteGatewayConfig.value.enableDnsForwarding
+ parExpressGatewayAsn = [string]::IsNullOrEmpty($parParameters.parExpressRouteGatewayConfig.value.asn) ? 65515 : $parParameters.parExpressRouteGatewayConfig.value.asn
+ parExpressGatewayBgpPeeringAddress = $parParameters.parExpressRouteGatewayConfig.value.bgpPeeringAddress
+ parExpressGatewayPeerWeight = [string]::IsNullOrEmpty($parParameters.parExpressRouteGatewayConfig.value.peerWeight) ? 5 : $parParameters.parExpressRouteGatewayConfig.value.peerWeight
+ parVpnGatewaySku = $parParameters.parVpnGatewayConfig.value.sku
+ parVpnGatewayVpntype = $parParameters.parVpnGatewayConfig.value.vpntype
+ parVpnGatewayGeneration = $parParameters.parVpnGatewayConfig.value.generation
+ parVpnGatewayEnableBgp = $parParameters.parVpnGatewayConfig.value.enableBgp
+ parVpnGatewayActiveActive = $parParameters.parVpnGatewayConfig.value.activeActive
+ parVpnGatewayEnableBgpRouteTranslationForNat = $parParameters.parVpnGatewayConfig.value.enableBgpRouteTranslationForNat
+ parVpnGatewayEnableDnsForwarding = $parParameters.parVpnGatewayConfig.value.enableDnsForwarding
+ parVpnGatewayAsn = [string]::IsNullOrEmpty($parParameters.parVpnGatewayConfig.value.asn) ? 65515 : $parParameters.parVpnGatewayConfig.value.asn
+ parVpnGatewayBgpPeeringAddress = $parParameters.parVpnGatewayConfig.value.bgpPeeringAddress
+ parVpnGatewayPeerWeight = [string]::IsNullOrEmpty($parParameters.parVpnGatewayConfig.value.peerWeight) ? 5 : $parParameters.parVpnGatewayConfig.value.peerWeight
+ parBastionOutboundSshRdpPorts = $parParameters.parBastionOutboundSshRdpPorts.value
+ parDeployLogAnalyticsWorkspace = $parParameters.parDeployLogAnalyticsWorkspace.value
+ parTags = Convert-ToHashTable($parParameters.parTags.value)
+ }
+ $varLoopCounter = 0;
+ $varRetry = $true
+ while ($varRetry -and $varLoopCounter -lt $varMaxRetryAttemptTransientErrorRetry) {
+ $modDeploySovereignPlatform = $null
+ try {
+ Write-Information ">>> Platform deployment started" -InformationAction Continue
+
+ $modDeploySovereignPlatform = New-AzManagementGroupDeployment `
+ -Name $deploymentName `
+ -Location $parDeploymentLocation `
+ -TemplateFile $varSovereignPlatformBicepFilePath `
+ -ManagementGroupId $varManagementGroupId `
+ -TemplateParameterObject $varParams `
+ -WarningAction Ignore
+
+ if (!$modDeploySovereignPlatform) {
+ $varRetry = $false
+ Write-Error "Error while executing platform deployment script" -ErrorAction Stop
+ }
+
+ if ($modDeploySovereignPlatform.ProvisioningState -eq "Failed") {
+ Write-Error "`n Error while executing platform deployment" -ErrorAction Stop
+ }
+
+ Write-Information ">>> Platform deployment completed" -InformationAction Continue
+ # update parameters
+ Out-DeploymentParameters "platform" $modDeploySovereignPlatform $varManagementGroupId $parParameters
+ return $modDeploySovereignPlatform
+ }
+ catch {
+ $varException = $_.Exception
+ $varErrorDetails = $_.ErrorDetails
+ $varTrace = $_.ScriptStackTrace
+ if (!$varRetry) {
+ Write-Error ">>> Validation error occurred during execution . Please try after addressing the error : $varException \n $varErrorDetails \n $varTrace" -ErrorAction Stop
+ }
+ if (!$modDeploySovereignPlatform) {
+ Write-Error ">>> Error occurred during execution . Please try after addressing the error : $varException \n $varErrorDetails \n $varTrace" -ErrorAction Stop
+ }
+ else {
+ $varDeploymentErrorCodes = Get-FailedDeploymentErrorCodes $varManagementGroupId $deploymentName $varManagementGroupDeployment
+ if ($null -eq $varDeploymentErrorCodes) {
+ $varRetry = $false
+ }
+ else {
+ $varLoopCounter++
+ $varRetry = Confirm-Retry $varDeploymentErrorCodes
+ if ($varRetry -and $varLoopCounter -lt $varMaxRetryAttemptTransientErrorRetry) {
+ Write-Information ">>> Retrying deployment after waiting for $varRetryWaitTimeTransientErrorRetry secs" -InformationAction Continue
+ Start-Sleep -Seconds $varRetryWaitTimeTransientErrorRetry
+ }
+ else {
+ $varRetry = $false
+ Write-Error ">>> Error occurred in platform deployment. Please try after addressing the above error." -ErrorAction Stop
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/orchestration/scripts/New-PolicyExemption.ps1 b/orchestration/scripts/New-PolicyExemption.ps1
new file mode 100644
index 00000000..98b6bade
--- /dev/null
+++ b/orchestration/scripts/New-PolicyExemption.ps1
@@ -0,0 +1,120 @@
+# Copyright (c) Microsoft Corporation.
+# Licensed under the MIT License.
+<#
+.SYNOPSIS
+ The powershell script creates policy exemptions.
+#>
+param (
+ $parAttendedLogin = $true
+)
+. ".\Invoke-Helper.ps1"
+
+#variables
+$varPolicyExemptionRequiredParams = @('parDeploymentPrefix', 'parDeploymentLocation', 'parPolicyExemptions')
+$varPolicyExemptionBicepFilePath = '..\policyExemption\policyExemption.bicep'
+
+<#
+.Description
+ The function call is to create policy exmeptions for the policies that needs to be exempted
+ Parameters:
+ parPolicyExemptionParametersFilePath -> path to the parameter file containing required parameters to create policy exemptions
+ parParameters -> hash table containing parameter name and value
+#>
+function Invoke-PolicyExemption {
+ param($parPolicyExemptionParametersFilePath, $parParameters)
+
+ if (!$parParameters) {
+ $parParameters = Read-ParametersValue($parPolicyExemptionParametersFilePath)
+ Get-DonotRetryErrorCodes
+ }
+
+ if (($null -eq $parParameters.parPolicyExemptions.value) -or ($parParameters.parPolicyExemptions.value.count -eq 0)) {
+ return
+ }
+
+ Confirm-Parameters($varPolicyExemptionRequiredParams)
+ $varPolicyExemptions = $parParameters.parPolicyExemptions.value
+ foreach ($varPolicyExemption in $varPolicyExemptions) {
+ New-Exemption $varPolicyExemption
+ }
+}
+
+<#
+.Description
+ deploys Policy Exemptions
+#>
+function New-Exemption {
+ param($parPolicyExemption)
+ $parDeploymentPrefix = $parParameters.parDeploymentPrefix.value
+ $parDeploymentSuffix = $parParameters.parDeploymentSuffix.value
+ $varManagementGroupId = "$parDeploymentPrefix$parDeploymentSuffix"
+ $parDeploymentLocation = $parParameters.parDeploymentLocation.value
+ $varParams = @{
+ parDeploymentPrefix = $parDeploymentPrefix
+ parDeploymentSuffix = $parDeploymentSuffix
+ parPolicyAssignmentName = $parPolicyExemption.parPolicyAssignmentName
+ parPolicyAssignmentScopeName = $parPolicyExemption.parPolicyAssignmentScopeName
+ parPolicyExemptionName = $parPolicyExemption.parPolicyExemptionName
+ parPolicyExemptionDisplayName = $parPolicyExemption.parPolicyExemptionDisplayName
+ parDescription = $parPolicyExemption.parPolicyExemptionDescription
+ parPolicyExemptionManagementGroup = $parPolicyExemption.parPolicyExemptionManagementGroup
+ parPolicyDefinitionReferenceIds = $parPolicyExemption.parPolicyDefinitionReferenceIds
+ }
+
+ $varDeploymentName = "deploy-policyExemptions-$vartimeStamp"
+ $varLoopCounter = 0;
+ $varRetry = $true
+ while ($varRetry -and $varLoopCounter -lt $varMaxRetryAttemptTransientErrorRetry) {
+ $modDeployPolicyExemption = $null
+ try {
+ Write-Information ">>> Policy exemption deployment started" -InformationAction Continue
+
+ $modDeployPolicyExemption = New-AzManagementGroupDeployment `
+ -Name $varDeploymentName `
+ -Location $parDeploymentLocation `
+ -TemplateFile $varPolicyExemptionBicepFilePath `
+ -ManagementGroupId $varManagementGroupId `
+ -TemplateParameterObject $varParams `
+ -WarningAction Ignore
+
+ if (!$modDeployPolicyExemption) {
+ Write-Error "`n>>> Error occured in policy exemption" -ErrorAction Stop
+ }
+ if ($modDeployPolicyExemption.ProvisioningState -eq "Failed") {
+ Write-Error "`n Error while executing policy exemption deployment" -ErrorAction Stop
+ }
+
+ Write-Information ">>> Policy exemption completed" -InformationAction Continue
+ return
+ }
+ catch {
+ $varException = $_.Exception
+ $varErrorDetails = $_.ErrorDetails
+ $varTrace = $_.ScriptStackTrace
+ if (!$varRetry) {
+ Write-Error ">>> Validation error occurred during execution . Please try after addressing the error : $varException \n $varErrorDetails \n $varTrace" -ErrorAction Stop
+ }
+ if (!$modDeployPolicyExemption) {
+ Write-Error ">>> Error occurred during execution . Please try after addressing the error : $varException \n $varErrorDetails \n $varTrace" -ErrorAction Stop
+ }
+ else {
+ $varDeploymentErrorCodes = Get-FailedDeploymentErrorCodes $varManagementGroupId $varDeploymentName $varManagementGroupDeployment
+ if ($null -eq $varDeploymentErrorCodes) {
+ $varRetry = $false
+ }
+ else {
+ $varLoopCounter++
+ $varRetry = Confirm-Retry $varDeploymentErrorCodes
+ if ($varRetry -and $varLoopCounter -lt $varMaxRetryAttemptTransientErrorRetry) {
+ Write-Information ">>> Retrying deployment after waiting for $varRetryWaitTimeTransientErrorRetry secs" -InformationAction Continue
+ Start-Sleep -Seconds $varRetryWaitTimeTransientErrorRetry
+ }
+ else {
+ $varRetry = $false
+ Write-Error ">>> Error occurred in policy exemption deployment. Please try after addressing the above error." -ErrorAction Stop
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/orchestration/scripts/New-PolicyRemediation.ps1 b/orchestration/scripts/New-PolicyRemediation.ps1
new file mode 100644
index 00000000..949b9331
--- /dev/null
+++ b/orchestration/scripts/New-PolicyRemediation.ps1
@@ -0,0 +1,159 @@
+# Copyright (c) Microsoft Corporation.
+# Licensed under the MIT License.
+<#
+.SYNOPSIS
+ The powershell script creates policy remediations.
+#>
+param (
+ $parAttendedLogin = $true
+)
+. ".\Invoke-Helper.ps1"
+
+#variables
+$varPolicyRemediationRequiredParams = @('parDeploymentPrefix', 'parDeploymentLocation')
+$varPolicyRemediationBicepFilePath = '..\policyRemediation\policyRemediation.bicep'
+
+<#
+.Description
+ The function call is to create policy remediations for the policies that needs to be remediated
+ Parameters:
+ parPolicyExemptionParametersFilePath -> path to the parameter file containing required parameters to create policy remediations
+ parParameters -> hash table containing parameter name and value
+#>
+function Invoke-PolicyRemediation {
+ param($parPolicyRemediationParametersFilePath, $parParameters)
+
+ if (!$parParameters) {
+ $parParameters = Read-ParametersValue $parPolicyRemediationParametersFilePath
+ Confirm-Parameters $varPolicyRemediationRequiredParams
+ }
+
+ $parDeploymentPrefix = $parParameters.parDeploymentPrefix.value
+ $parDeploymentSuffix = $parParameters.parDeploymentSuffix.value
+ $varManagementGroupId = "$parDeploymentPrefix$parDeploymentSuffix"
+
+ $varPolicyStateList = Get-AzPolicyState -ManagementGroupName $varManagementGroupId -Filter "(PolicyDefinitionAction eq 'deployifnotexists' or PolicyDefinitionAction eq 'modify') and ComplianceState eq 'NonCompliant'"
+
+ if ( $null -ne $varPolicyStateList) {
+ $varPolicyCount = $varPolicyStateList.Count
+ Write-Information ">>> Starting policy remediation deployment" -InformationAction Continue
+
+ $varPolicyCounter = 1
+ foreach ($varPolicy in $varPolicyStateList) {
+ Write-Information "Remediating policy $varPolicyCounter out of $varPolicyCount policies." -InformationAction Continue
+ $varPolicyCounter++
+ New-Remediation $varPolicy
+ }
+ }
+ else {
+ Write-Information "No policies found for remediation." -InformationAction Continue
+ }
+}
+
+<#
+.Description
+ Deploys Policy Remediation
+#>
+function New-Remediation {
+ param($parPolicy)
+
+ $varPolicySetDefinitionName = $parPolicy.policySetDefinitionName
+ $varGuid = New-Guid
+ $varDeploymentName = ("$varGuid" + $varPolicySetDefinitionName)
+ $varDeploymentName = $varDeploymentName.Length -ge 64 ? $varDeploymentName.Substring(0, 64) : $varDeploymentName
+ $parDeploymentPrefix = $parParameters.parDeploymentPrefix.value
+ $parDeploymentSuffix = $parParameters.parDeploymentSuffix.value
+ $varManagementGroupId = "$parDeploymentPrefix$parDeploymentSuffix"
+ $parDeploymentLocation = $parParameters.parDeploymentLocation.value
+ $parPolicyAssignmentScope = $parPolicy.policyAssignmentScope
+ $varPattern = "$([regex]::escape($parDeploymentPrefix))(.*)"
+ $varRegExResult = $parPolicyAssignmentScope | Select-String -Pattern $varPattern
+ $parManagementGroupScope = $varRegExResult.Matches[0].Value
+ $parParams = @{
+ parDeploymentPrefix = $parDeploymentPrefix
+ parDeploymentSuffix = $parDeploymentSuffix
+ parPolicyRemediationName = "rem-" + $varDeploymentName
+ parPolicyAssignmentId = $parPolicy.policyAssignmentId
+ parPolicyDefinitionReferenceId = $parPolicy.policyDefinitionReferenceId
+ parManagementGroupScope = $parManagementGroupScope
+ }
+
+ $parInvokePolicyRemediationSync = $parParameters.parInvokePolicyRemediationSync.value
+ $varRetry = $true
+ while ($varRetry -and $varLoopCounter -lt $varMaxRetryAttemptTransientErrorRetry) {
+ $modDeployPolicyRemediation = $null
+ try {
+ if ($parInvokePolicyRemediationSync) {
+ $varJob = $modDeployPolicyRemediation = New-AzManagementGroupDeployment `
+ -Name $varDeploymentName `
+ -Location $parDeploymentLocation `
+ -TemplateFile $varPolicyRemediationBicepFilePath `
+ -ManagementGroupId $varManagementGroupId `
+ -TemplateParameterObject $parParams `
+ -WarningAction Ignore `
+ -AsJob
+ $varJob | Wait-Job
+
+
+ if (!$modDeployPolicyRemediation) {
+ Write-Error "`n>>> Error occured in policy remediation" -ErrorAction Stop
+ }
+
+ if ($modDeployPolicyRemediation.ProvisioningState -eq "Failed") {
+ Write-Error "`n Error while executing policy remediation deployment" -ErrorAction Stop
+ }
+
+ Write-Information ">>> Policy remediation $parRemediationName completed." -InformationAction Continue
+ return
+ }
+ else {
+ $modDeployPolicyRemediation = New-AzManagementGroupDeployment `
+ -Name $varDeploymentName `
+ -Location $parDeploymentLocation `
+ -TemplateFile $varPolicyRemediationBicepFilePath `
+ -ManagementGroupId $varManagementGroupId `
+ -TemplateParameterObject $parParams `
+ -WarningAction Ignore
+
+ if ($modDeployPolicyRemediation) {
+ Write-Error "`n>>> Error occured in policy remediation" -ErrorAction Stop
+ }
+ if ($modDeployPolicyRemediation.ProvisioningState -eq "Failed") {
+ Write-Error "`n Error while executing policy remediation deployment" -ErrorAction Stop
+ }
+
+ Write-Information ">>> Policy remediation $parRemediationName scheduled." -InformationAction Continue
+ return
+ }
+ }
+ catch {
+ $varException = $_.Exception
+ $varErrorDetails = $_.ErrorDetails
+ $varTrace = $_.ScriptStackTrace
+ if (!$varRetry) {
+ Write-Error ">>> Validation error occurred during execution . Please try after addressing the error : $varException \n $varErrorDetails \n $varTrace" -ErrorAction Stop
+ }
+ if (!$modDeployPolicyRemediation) {
+ Write-Error ">>> Error occurred during execution . Please try after addressing the error : $varException \n $varErrorDetails \n $varTrace" -ErrorAction Stop
+ }
+ else {
+ $varDeploymentErrorCodes = Get-FailedDeploymentErrorCodes $varManagementGroupId $varDeploymentName $varManagementGroupDeployment
+ if ($null -eq $varDeploymentErrorCodes) {
+ $varRetry = $false
+ }
+ else {
+ $varLoopCounter++
+ $varRetry = Confirm-Retry $varDeploymentErrorCodes
+ if ($varRetry -and $varLoopCounter -lt $varMaxRetryAttemptTransientErrorRetry) {
+ Write-Information ">>> Retrying deployment after waiting for $varRetryWaitTimeTransientErrorRetry secs" -InformationAction Continue
+ Start-Sleep -Seconds $varRetryWaitTimeTransientErrorRetry
+ }
+ else {
+ $varRetry = $false
+ Write-Error ">>> Error occurred in policy remediation deployment. Please try after addressing the above error." -ErrorAction Stop
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/orchestration/scripts/New-SovereignLandingZone.ps1 b/orchestration/scripts/New-SovereignLandingZone.ps1
new file mode 100644
index 00000000..7deb2977
--- /dev/null
+++ b/orchestration/scripts/New-SovereignLandingZone.ps1
@@ -0,0 +1,138 @@
+# Copyright (c) Microsoft Corporation.
+# Licensed under the MIT License.
+<#
+.SYNOPSIS
+This PowerShell script serves as the overarching script to deploy SLZ either in its entirety or in a piecemeal manner the below individual modules.
+
+.DESCRIPTION
+- Executes the individual modules - bootstrap, platform, compliance, policyexemption, dashboard or all
+- bootstrap deploys the management groups and subscriptions
+- platform deploys the resource groups in each of the subscriptions along with the networking resources.
+- compliance installs the policy sets and assigns them to the individual management groups based on convention
+- dashboard deploys the SLZ specific dashboard in the management subscription
+- policyexemption exempts the policies defined in parameter parPolicyExemptions.
+- policy remediation remediates policies that can be remediated and updates compliance status
+#>
+
+using namespace System.Collections
+
+param (
+ $parDeployment = $(Read-Host -prompt "Please choose the deployment type from - all, bootstrap, platform, compliance, dashboard, policyexemption, policyremediation"),
+ $parParametersFilePath = ".\parameters\sovereignLandingZone.parameters.json",
+ $parAttendedLogin = $true
+)
+
+$varDeploy = @("all", "bootstrap", "platform", "compliance", "dashboard", "policyexemption", "policyremediation")
+if ($parDeployment -notin $varDeploy) {
+ Write-Error "Invalid Input. Please choose from the given options" -ErrorAction Stop
+}
+Write-Information ">>> If you are running this deployment in admin mode and left mouse click in the PowerShell window, a text selection rectangle will appear and deployment will halt. Press the Enter key to continue the deployment." -InformationAction Continue
+
+
+#reference to individual scripts
+. ".\Invoke-Helper.ps1"
+. ".\New-Bootstrap.ps1" -parAttendedLogin $parAttendedLogin
+. ".\New-Platform.ps1" -parAttendedLogin $parAttendedLogin
+. ".\New-PolicyExemption.ps1" -parAttendedLogin $parAttendedLogin
+. ".\New-PolicyRemediation.ps1" -parAttendedLogin $parAttendedLogin
+. ".\New-Compliance.ps1" -parAttendedLogin $parAttendedLogin
+. ".\New-Dashboard.ps1" -parAttendedLogin $parAttendedLogin
+
+$varAllRequiredParams = @('parDeploymentPrefix', 'parTopLevelManagementGroupName', 'parSubscriptionBillingScope', 'parCustomer', 'parDeploymentLocation', 'parAllowedLocations', 'parAllowedLocationsForConfidentialComputing')
+
+# Code execution starts here and is the entry point to the function invocations
+Get-DonotRetryErrorCodes
+$varParameters = Read-ParametersValue($parParametersFilePath)
+
+if ($parAttendedLogin) {
+
+ $parIsSLZDeployedAtTenantRoot = $true
+ if ($null -ne $varParameters.parTopLevelManagementGroupParentId.value) {
+ $parIsSLZDeployedAtTenantRoot = $false
+ }
+
+ # Confirm Sovereign Landing Zone Prerequisites
+ Confirm-Prerequisites $parIsSLZDeployedAtTenantRoot
+}
+
+$vartimeStamp = Get-Date -Format "yyyyMMddHHmmss"
+$varParameters.add('parDeploymentStartTime', $vartimeStamp)
+switch ($parDeployment) {
+ 'bootstrap' {
+ Confirm-Parameters($varBootstrapRequiredParams)
+ $modDeployBootstrap = New-Bootstrap $null $varParameters
+ if ($modDeployBootstrap) {
+ Show-ManagementGroupInfo $varParameters
+ }
+
+ return $modDeployBootstrap
+ }
+
+ 'platform' {
+ Confirm-Parameters($varPlatformRequiredParams)
+ New-Platform $null $varParameters $null
+ Move-Subscription $varParameters $null
+
+ }
+
+ 'compliance' {
+ $parDeployAlzDefaultPolicies = $varParameters.parDeployAlzDefaultPolicies.value
+ if ($parDeployAlzDefaultPolicies) {
+ $varComplianceRequiredParams = $varComplianceRequiredParams + $varAlzDefaultPolicyRequiredParams
+ }
+ Confirm-Parameters($varComplianceRequiredParams)
+ New-Compliance $null $varParameters $null
+ }
+
+ 'dashboard' {
+ Confirm-Parameters($varDashboardRequiredParams)
+ $modDashboard = New-Dashboard $null $varParameters $null
+ if ($modDashboard) {
+ Show-DashboardInfo $varParameters $null
+ }
+
+ return $modDashboard
+ }
+
+ 'policyexemption' {
+ #Run policy exemption
+ Invoke-PolicyExemption $null $varParameters
+ }
+
+ 'policyremediation' {
+ Confirm-Parameters($varPolicyRemediationRequiredParams)
+ Invoke-PolicyRemediation $null $varParameters
+ }
+
+ 'all' {
+ #Validate Parameters
+ Confirm-Parameters($varAllRequiredParams)
+
+ #bootstrap
+ $modDeployBootstrapOutputs = New-bootstrap $null $varParameters
+ if (!$modDeployBootstrapOutputs) {
+ Write-Error "Bootstrap deployment script failed." -ErrorAction Stop
+ }
+
+ #Platform
+ $modDeploySovereignPlatformOutputs = New-Platform $null $varParameters $modDeployBootstrapOutputs
+ if (!$modDeploySovereignPlatformOutputs) {
+ Write-Error "Platform deployment script failed." -ErrorAction Stop
+ }
+
+ #Move Subscription
+ Move-Subscription $varParameters $modDeployBootstrapOutputs
+
+ #Compliance
+ New-Compliance $null $varParameters $modDeploySovereignPlatformOutputs
+
+ #Dashboard
+ $modDashboard = New-Dashboard $null $varParameters $modDeployBootstrapOutputs
+ if (!$modDashboard) {
+ Write-Error "Dashboard deployment script failed." -ErrorAction Stop
+ }
+
+ Show-ManagementGroupInfo $varParameters
+ Show-DashboardInfo $varParameters $modDeployBootstrapOutputs
+ }
+}
diff --git a/orchestration/scripts/parameters/sovereignLandingZone.parameters.json b/orchestration/scripts/parameters/sovereignLandingZone.parameters.json
new file mode 100644
index 00000000..1324ea34
--- /dev/null
+++ b/orchestration/scripts/parameters/sovereignLandingZone.parameters.json
@@ -0,0 +1,494 @@
+{
+ "contentVersion": "1.0.0.0",
+ "description": "",
+ "parameters": {
+ "parDeploymentPrefix": {
+ "type": "string",
+ "usedBy": "all, bootstrap, compliance, platform, and dashboard",
+ "minLength": 2,
+ "maxLength": 5,
+ "defaultValue": "mcfs",
+ "value": null,
+ "description": "Prefix added to all Azure resources created by the SLZ Preview."
+ },
+ "parTopLevelManagementGroupName": {
+ "type": "string",
+ "usedBy": "all and bootstrap",
+ "defaultValue": "Microsoft Cloud for Sovereignty",
+ "value": null,
+ "description": "The name of the top-level management group for the SLZ Preview."
+ },
+ "parDeploymentSuffix": {
+ "type": "string",
+ "usedBy": "all, bootstrap, compliance, platform, dashboard",
+ "maxLength": 5,
+ "defaultValue": null,
+ "value": null,
+ "description": "Optional suffix that will be added to all Azure resources created by the the SLZ Preview. Use a '-' at the start of the suffix value if a dash is needed."
+ },
+ "parTopLevelManagementGroupParentId": {
+ "type": "string",
+ "usedBy": "all and bootstrap",
+ "sampleValue": "/providers/Microsoft.Management/managementGroups/replace_with_parent_management_group_id",
+ "defaultValue": null,
+ "value": null,
+ "description": "Optional parent for Management Group hierarchy, used as intermediate root Management Group parent, if specified. If empty (default) will deploy beneath Tenant Root Management Group."
+ },
+ "parSubscriptionBillingScope": {
+ "type": "string",
+ "usedBy": "all and bootstrap",
+ "sampleValue": "Format for EA - /providers/Microsoft.Billing/BillingAccounts/{BillingAccountId}/enrollmentAccounts/{EnrollmentAccountId}",
+ "defaultValue": null,
+ "value": null,
+ "description": "The full resource ID of billing scope associated to the EA, MCA or MPA account you wish to create the subscription in."
+ },
+ "parCustomer": {
+ "type": "string",
+ "usedBy": "all and dashboard",
+ "defaultValue": "Country/Region",
+ "value": null,
+ "description": "The name of the organization deploying the SLZ Preview to brand the compliance dashboard appropriately."
+ },
+ "parDeploymentLocation": {
+ "type": "string",
+ "usedBy": "all, platform, and dashboard",
+ "defaultValue": null,
+ "value": null,
+ "allowedValues": [
+ "australiacentral",
+ "australiacentral2",
+ "australiaeast",
+ "australiasoutheast",
+ "brazilsouth",
+ "canadacentral",
+ "canadaeast",
+ "centralindia",
+ "centralus",
+ "eastasia",
+ "eastus",
+ "eastus2",
+ "francecentral",
+ "germanywestcentral",
+ "japaneast",
+ "japanwest",
+ "jioindiawest",
+ "koreacentral",
+ "koreasouth",
+ "northcentralus",
+ "northeurope",
+ "norwayeast",
+ "qatarcentral",
+ "southafricanorth",
+ "southcentralus",
+ "southeastasia",
+ "southindia",
+ "swedencentral",
+ "switzerlandnorth",
+ "uaenorth",
+ "uksouth",
+ "ukwest",
+ "westcentralus",
+ "westeurope",
+ "westindia",
+ "westus",
+ "westus2",
+ "westus3"
+ ],
+ "description": "Location used for deploying Azure resources."
+ },
+ "parAllowedLocations": {
+ "type": "array",
+ "usedBy": "all and compliance",
+ "defaultValue": [],
+ "value": [],
+ "allowedValues": [
+ "australiacentral",
+ "australiacentral2",
+ "australiaeast",
+ "australiasoutheast",
+ "brazilsouth",
+ "canadacentral",
+ "canadaeast",
+ "centralindia",
+ "centralus",
+ "eastasia",
+ "eastus",
+ "eastus2",
+ "francecentral",
+ "germanywestcentral",
+ "japaneast",
+ "japanwest",
+ "jioindiawest",
+ "koreacentral",
+ "koreasouth",
+ "northcentralus",
+ "northeurope",
+ "norwayeast",
+ "qatarcentral",
+ "southafricanorth",
+ "southcentralus",
+ "southeastasia",
+ "southindia",
+ "swedencentral",
+ "switzerlandnorth",
+ "uaenorth",
+ "uksouth",
+ "ukwest",
+ "westcentralus",
+ "westeurope",
+ "westindia",
+ "westus",
+ "westus2",
+ "westus3"
+ ],
+ "description": "Full list of Azure regions allowed by policy where resources can be deployed that should include at least the parDeploymentLocation."
+ },
+ "parAllowedLocationsForConfidentialComputing": {
+ "type": "array",
+ "usedBy": "all and compliance",
+ "defaultValue": [],
+ "value": [],
+ "allowedValues": [
+ "australiacentral",
+ "australiacentral2",
+ "australiaeast",
+ "australiasoutheast",
+ "brazilsouth",
+ "canadacentral",
+ "canadaeast",
+ "centralindia",
+ "centralus",
+ "eastasia",
+ "eastus",
+ "eastus2",
+ "francecentral",
+ "germanywestcentral",
+ "japaneast",
+ "japanwest",
+ "jioindiawest",
+ "koreacentral",
+ "koreasouth",
+ "northcentralus",
+ "northeurope",
+ "norwayeast",
+ "qatarcentral",
+ "southafricanorth",
+ "southcentralus",
+ "southeastasia",
+ "southindia",
+ "swedencentral",
+ "switzerlandnorth",
+ "uaenorth",
+ "uksouth",
+ "ukwest",
+ "westcentralus",
+ "westeurope",
+ "westindia",
+ "westus",
+ "westus2",
+ "westus3"
+ ],
+ "description": "Full list of Azure regions allowed by policy where Confidential computing resources can be deployed. This may be a completely different list from parAllowedLocations."
+ },
+ "parDeployDdosProtection": {
+ "type": "bool",
+ "usedBy": "all, platform and compliance",
+ "defaultValue": true,
+ "value": null,
+ "description": "Toggles deployment of Azure DDOS protection. True to deploy, otherwise false."
+ },
+ "parDeployHubNetwork": {
+ "type": "bool",
+ "usedBy": "all and platform",
+ "defaultValue": true,
+ "value": null,
+ "description": "Toggles deployment of the hub VNET. True to deploy, otherwise false."
+ },
+ "parEnableFirewall": {
+ "type": "bool",
+ "usedBy": "all and platform",
+ "defaultValue": true,
+ "value": null,
+ "description": "Toggles deployment of Azure Firewall. True to deploy, otherwise false."
+ },
+ "parUsePremiumFirewall": {
+ "type": "bool",
+ "usedBy": "all and platform",
+ "defaultValue": true,
+ "value": null,
+ "description": "Toggles deployment of the Premium SKU for Azure Firewall and only used if parEnableFirewall is enabled. True to use Premium SKU, otherwise false."
+ },
+ "parHubNetworkAddressPrefix": {
+ "type": "string",
+ "usedBy": "all and platform",
+ "defaultValue": "10.20.0.0/16",
+ "value": null,
+ "description": "CIDR range for the hub VNET."
+ },
+ "parAzureBastionSubnet": {
+ "type": "string",
+ "usedBy": "all and platform",
+ "defaultValue": "10.20.15.0/24",
+ "value": null,
+ "description": "CIDR range for the Azure Bastion subnet."
+ },
+ "parGatewaySubnet": {
+ "type": "string",
+ "usedBy": "all and platform",
+ "defaultValue": "10.20.252.0/24",
+ "value": null,
+ "description": "CIDR range for the Gateway subnet."
+ },
+ "parAzureFirewallSubnet": {
+ "type": "string",
+ "usedBy": "all and platform",
+ "defaultValue": "10.20.254.0/24",
+ "value": null,
+ "description": "CIDR range for the Azure Firewall subnet."
+ },
+ "parCustomSubnets": {
+ "type": "array",
+ "usedBy": "all and platform",
+ "sampleValue": [
+ {
+ "name": "CustomSubnet1",
+ "ipAddressRange": "xx.xx.xx.xx/xx"
+ },
+ {
+ "name": "CustomSubnet2",
+ "ipAddressRange": "xxx.xxx.xxx.xxx/xx"
+ }
+ ],
+ "defaultValue": [],
+ "value": [],
+ "description": "List of other subnets to deploy on the hub VNET and their CIDR ranges."
+ },
+ "parLogRetentionInDays": {
+ "type": "int",
+ "usedBy": "all, compliance, and platform",
+ "minValue": 30,
+ "maxValue": 730,
+ "defaultValue": 365,
+ "value": null,
+ "description": "Length of time, in days, to retain log files with usage enforced by ALZ policies."
+ },
+ "parManagementSubscriptionId": {
+ "type": "string",
+ "usedBy": "bootstrap, platform and dashboard",
+ "defaultValue": null,
+ "value": null,
+ "description": "Optional management subscription ID when using an existing subscription."
+ },
+ "parIdentitySubscriptionId": {
+ "type": "string",
+ "usedBy": "bootstrap and platform",
+ "defaultValue": null,
+ "value": null,
+ "description": "Optional identity subscription ID when using an existing subscription."
+ },
+ "parConnectivitySubscriptionId": {
+ "type": "string",
+ "usedBy": "bootstrap and platform",
+ "defaultValue": null,
+ "value": null,
+ "description": "Optional connectivity subscription ID when using an existing subscription."
+ },
+ "parDdosProtectionResourceId": {
+ "type": "string",
+ "usedBy": "platform",
+ "defaultValue": null,
+ "value": null,
+ "description": "Optional resource ID for an existing DDoS plan with usage enforced by ALZ policies."
+ },
+ "parLogAnalyticsWorkspaceId": {
+ "type": "string",
+ "usedBy": "compliance",
+ "defaultValue": null,
+ "value": null,
+ "description": "Optional resource ID for an existing Log Analytics Workspace with usage enforced by ALZ policies."
+ },
+ "parRequireOwnerRolePermission": {
+ "type": "bool",
+ "usedBy": "all and compliance",
+ "defaultValue": false,
+ "value": null,
+ "description": "Set this to true if any policies in the initiative include a modify effect."
+ },
+ "parPolicyExemptions": {
+ "type": "array of objects",
+ "usedBy": "policyexemptions",
+ "valueFormat": [
+ {
+ "parPolicyExemptionManagementGroup": null,
+ "parPolicyAssignmentName": null,
+ "parPolicyAssignmentScopeName": null,
+ "parPolicyDefinitionReferenceIds": [],
+ "parPolicyExemptionName": null,
+ "parPolicyExemptionDisplayName": null,
+ "parPolicyExemptionDescription": null
+ }
+ ],
+ "defaultValue": [],
+ "value": [],
+ "description": "Optional list of policy exemptions."
+ },
+ "parExpressRouteGatewayConfig": {
+ "type": "Object",
+ "usedBy": "all and platform",
+ "sampleValue": {
+ "sku": "standard",
+ "vpntype": "RouteBased",
+ "vpnGatewayGeneration": null,
+ "enableBgp": false,
+ "activeActive": false,
+ "enableBgpRouteTranslationForNat": false,
+ "enableDnsForwarding": false,
+ "asn": 65515,
+ "bgpPeeringAddress": "",
+ "peerWeight": 5
+ },
+ "value": null,
+ "description": "Optional configuration options for the ExpressRoute Gateway."
+ },
+ "parVpnGatewayConfig": {
+ "type": "Object",
+ "usedBy": "all and platform",
+ "sampleValue": {
+ "sku": "VpnGw1",
+ "vpntype": "RouteBased",
+ "generation": "Generation1",
+ "enableBgp": false,
+ "activeActive": false,
+ "enableBgpRouteTranslationForNat": false,
+ "enableDnsForwarding": false,
+ "asn": 65515,
+ "bgpPeeringAddress": "",
+ "peerWeight": 5
+ },
+ "value": null,
+ "description": "Optional configuration options for the VPN Gateway."
+ },
+ "parDeployBastion": {
+ "type": "bool",
+ "usedBy": "all and platform",
+ "defaultValue": true,
+ "value": null,
+ "description": "Toggles deployment of Azure Bastion. True to deploy, otherwise false."
+ },
+ "parLandingZoneMgChildren": {
+ "type": "array of objects",
+ "usedBy": "all and bootstrap",
+ "sampleValue": [
+ {
+ "id": "MG1",
+ "displayName": "Child MG 1"
+ },
+ {
+ "id": "MG2",
+ "displayName": "Child MG 2"
+ }
+ ],
+ "defaultValue": [],
+ "value": [],
+ "description": "Optional array of child management groups to deploy under the SLZ Preview Landing Zones management group."
+ },
+ "parDeployAlzDefaultPolicies": {
+ "type": "bool",
+ "usedBy": "all and compliance",
+ "defaultValue": true,
+ "value": null,
+ "description": "Toggles assignment of ALZ policies. True to deploy, otherwise false."
+ },
+ "parAutomationAccountName": {
+ "type": "string",
+ "usedBy": "all and compliance",
+ "defaultValue": null,
+ "value": null,
+ "description": "Optional resource name for an existing Azure Automation account with usage enforced by ALZ policies."
+ },
+ "parPrivateDnsResourceGroupId": {
+ "type": "string",
+ "usedBy": "all and compliance",
+ "defaultValue": null,
+ "value": null,
+ "description": "Optional resource ID of the Azure Resource Group that contains the Private DNS Zones with usage enforced by ALZ policies."
+ },
+ "parMsDefenderForCloudEmailSecurityContact": {
+ "type": "string",
+ "usedBy": "all and compliance",
+ "defaultValue": null,
+ "value": null,
+ "description": "An e-mail address that you want Microsoft Defender for Cloud alerts to be sent to."
+ },
+ "parBastionOutboundSshRdpPorts": {
+ "type": "array",
+ "usedBy": "all and platform",
+ "defaultValue": ["22", "3389"],
+ "value": [],
+ "description": "Array of outbound destination ports and ranges for Azure Bastion."
+ },
+ "parInvokePolicyScanSync": {
+ "type": "bool",
+ "usedBy": "all and compliance",
+ "defaultValue": true,
+ "value": null,
+ "description": "Toggles executing the policy scan in synchronous mode. True to run policy scan in synchronous mode, False for asynchronous. When set to false, policy remediation needs to be manually triggered once the scan is complete. Note that when policy scan is run asynchronously, there isn't a way to track its progress."
+ },
+ "parInvokePolicyRemediationSync": {
+ "type": "bool",
+ "usedBy": "all and compliance",
+ "defaultValue": true,
+ "value": null,
+ "description": "Toggles executing the policy scan in synchronous mode. True to run policy remediation in synchronous mode, False for asynchronous."
+ },
+ "parPolicyEffect": {
+ "type": "string",
+ "usedBy": "all and compliance",
+ "defaultValue": "Deny",
+ "value": null,
+ "allowedValues": [
+ "Audit",
+ "Deny",
+ "Disabled",
+ "DeployIfNotExists",
+ "Modify",
+ "Append",
+ "AuditIfNotExists"
+ ],
+ "description": "The policy effect used in all assignments for the Sovereignty Policy Baseline."
+ },
+ "parDeployLogAnalyticsWorkspace": {
+ "type": "bool",
+ "usedBy": "all, platform",
+ "defaultValue": true,
+ "value": null,
+ "description": "True to deploy LogAnalyticsWorkspace, otherwise false."
+ },
+ "parCustomerPolicySets": {
+ "type": "array of objects",
+ "usedBy": "all and compliance",
+ "defaultValue": [],
+ "sampleValue": [
+ {
+ "policySetDefinitionId": "/providers/Microsoft.Authorization/policySetDefinitions/179d1daa-458f-4e47-8086-2a68d0d6c38f",
+ "policySetAssignmentName": "NIST-SP-800-53-Rev.-5",
+ "policySetAssignmentDisplayName": "NIST 800-53 Initiative",
+ "policySetAssignmentDescription": "NIST 800-53 Initiative"
+ }
+ ],
+ "value": [],
+ "description": "Toggles deployment of Log Analytics Workspace. True to deploy, otherwise false."
+ },
+ "parTags": {
+ "type": "object",
+ "usedBy": "all, bootstrap, platform, and dashboard",
+ "sampleValue": {
+ "tag1": "value1",
+ "tag2": "value2"
+ },
+ "value": null,
+ "defaultValue": null,
+ "description": "Tags that will be assigned to subscription and resources created by this deployment script."
+ }
+ }
+}
diff --git a/orchestration/sovereignPlatform/sovereignPlatform.bicep b/orchestration/sovereignPlatform/sovereignPlatform.bicep
new file mode 100644
index 00000000..44aa7f4a
--- /dev/null
+++ b/orchestration/sovereignPlatform/sovereignPlatform.bicep
@@ -0,0 +1,454 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+/*
+ SUMMARY: This is the main file for the deployment of the management group resources. It will deploy the following resources:
+ - Management group resource groups
+ - Management group managed identity
+ - Management group role assignment
+ - Management group logging
+ - Management group hub networking
+ AUTHOR/S: Cloud for Sovereignty
+*/
+targetScope = 'managementGroup'
+
+@description('The prefix that will be added to all resources created by this deployment.')
+@minLength(2)
+@maxLength(5)
+param parDeploymentPrefix string
+
+@description('The suffix that will be added to management group suffix name the same way to be added to management group prefix names.')
+@maxLength(5)
+param parDeploymentSuffix string = ''
+
+@description('Deployment location')
+@allowed([
+ 'asia'
+ 'asiapacific'
+ 'australia'
+ 'australiacentral'
+ 'australiacentral2'
+ 'australiaeast'
+ 'australiasoutheast'
+ 'brazil'
+ 'brazilsouth'
+ 'brazilsoutheast'
+ 'canada'
+ 'canadacentral'
+ 'canadaeast'
+ 'centralindia'
+ 'centralus'
+ 'centraluseuap'
+ 'centralusstage'
+ 'eastasia'
+ 'eastasiastage'
+ 'eastus'
+ 'eastus2'
+ 'eastus2euap'
+ 'eastus2stage'
+ 'eastusstage'
+ 'eastusstg'
+ 'europe'
+ 'france'
+ 'francecentral'
+ 'francesouth'
+ 'germany'
+ 'germanynorth'
+ 'germanywestcentral'
+ 'global'
+ 'india'
+ 'japan'
+ 'japaneast'
+ 'japanwest'
+ 'jioindiacentral'
+ 'jioindiawest'
+ 'korea'
+ 'koreacentral'
+ 'koreasouth'
+ 'northcentralus'
+ 'northcentralusstage'
+ 'northeurope'
+ 'norway'
+ 'norwayeast'
+ 'norwaywest'
+ 'qatarcentral'
+ 'singapore'
+ 'southafrica'
+ 'southafricanorth'
+ 'southafricawest'
+ 'southcentralus'
+ 'southcentralusstage'
+ 'southcentralusstg'
+ 'southeastasia'
+ 'southeastasiastage'
+ 'southindia'
+ 'swedencentral'
+ 'switzerland'
+ 'switzerlandnorth'
+ 'switzerlandwest'
+ 'uae'
+ 'uaecentral'
+ 'uaenorth'
+ 'uk'
+ 'uksouth'
+ 'ukwest'
+ 'unitedstates'
+ 'unitedstateseuap'
+ 'westcentralus'
+ 'westeurope'
+ 'westindia'
+ 'westus'
+ 'westus2'
+ 'westus2stage'
+ 'westus3'
+ 'westusstage'
+])
+param parDeploymentLocation string
+
+@description('Set how long logs are retained for, in days. DEFAULT: 365')
+@minValue(30)
+@maxValue(730)
+param parLogRetentionInDays int = 365
+
+@description('Subscription ID for management group.')
+param parManagementSubscriptionId string
+
+@description('Subscription ID for identity group.')
+param parIdentitySubscriptionId string
+
+@description('Subscription ID for connectivity group.')
+param parConnectivitySubscriptionId string
+
+@description('Testing variable, set to false to skip deploying the hub network resources. DEFAULT: true')
+param parDeployHubNetwork bool = true
+
+@description('Set to true to deploy Azure Bastion service, otherwise false. DEFAULT: true')
+param parDeployBastion bool = true
+
+@description('Set to true for DDoS protection, otherwise false. DEFAULT: true')
+param parDeployDdosProtection bool = true
+
+@description('Set to true for premium firewall, otherwise false. DEFAULT: true')
+param parUsePremiumFirewall bool = true
+
+@description('Tags to be added to deployed resources')
+param parTags object = {}
+
+@description('Hub network subnet. DEFAULT: 10.20.0.0/16')
+param parHubNetworkAddressPrefix string = '10.20.0.0/16'
+
+@description('The name and IP address range for each subnet in the virtual networks.')
+param parSubnets array = [
+ {
+ name: 'AzureBastionSubnet'
+ ipAddressRange: '10.20.15.0/24'
+ }
+ {
+ name: 'GatewaySubnet'
+ ipAddressRange: '10.20.252.0/24'
+ }
+ {
+ name: 'AzureFirewallSubnet'
+ ipAddressRange: '10.20.254.0/24'
+ }
+]
+
+@description('The SKU for the Express Route Gateway. Default: standard')
+param parExpressGatewaySku string = 'standard'
+
+@description('Express route gateway vpn type. Default:RouteBased')
+param parExpressGatewayVpntype string = 'RouteBased'
+
+@description('Express route gateway generation. Default:null')
+param parExpressGatewayGeneration string = ''
+
+@description('Express route border gateway protocol. Default: false')
+param parExpressGatewayEnableBgp bool = false
+
+@description('Create highly available active-active gateways. Default: false')
+param parExpressGatewayActiveActive bool = false
+
+@description('Gets or sets enable BGP routes translation for NAT on this gateway. Default:false')
+param parExpressGatewayEnableBgpRouteTranslationForNat bool = false
+
+@description('Configure DNS forwarding for gateway. Default: false')
+param parExpressGatewayEnableDnsForwarding bool = false
+
+@description('Express Gateway ASN. Default: 65515')
+param parExpressGatewayAsn int = 65515
+
+@description('Bgp peer address. Default:""')
+param parExpressGatewayBgpPeeringAddress string = ''
+
+@description('Bgp peer weight. Default:5')
+param parExpressGatewayPeerWeight int = 5
+
+@description('The SKU for the VPN Gateway. Default:VpnGw1')
+param parVpnGatewaySku string = 'VpnGw1'
+
+@description('VPN type. Default: RouteBased')
+param parVpnGatewayVpntype string = 'RouteBased'
+
+@description('VPN gateway generation. Default: Generation1')
+param parVpnGatewayGeneration string = 'Generation1'
+
+@description('VPN gateway border gateway protocol. Default: false')
+param parVpnGatewayEnableBgp bool = false
+
+@description('Create highly available active-active gateways. Default: false')
+param parVpnGatewayActiveActive bool = false
+
+@description('Gets or sets enable BGP routes translation for NAT on this gateway. Default: false')
+param parVpnGatewayEnableBgpRouteTranslationForNat bool = false
+
+@description('Configure DNS forwarding for gateway. Default: false')
+param parVpnGatewayEnableDnsForwarding bool = false
+
+@description('VPN gateway ASN. Default: 65515')
+param parVpnGatewayAsn int = 65515
+
+@description('Bgp peer address. Default: ""')
+param parVpnGatewayBgpPeeringAddress string = ''
+
+@description('Bgp peer weight. Default: 5')
+param parVpnGatewayPeerWeight int = 5
+
+@description('Enable Firewall. Default:True')
+param parEnableFirewall bool = true
+
+@description('Define outbound destination ports or ranges for SSH or RDP that you want to access from Azure Bastion.')
+param parBastionOutboundSshRdpPorts array = [ '22', '3389' ]
+
+@description('Testing variable, set to false to skip deploying the log analytics workspace. DEFAULT: true')
+param parDeployLogAnalyticsWorkspace bool = true
+
+var varManagementGroupId = '${parDeploymentPrefix}${parDeploymentSuffix}'
+
+// Deploy management group resource groups
+module modManagementResourceGroups '../../modules/resourceGroups/managementResourceGroups.bicep' = {
+ name: take('${parDeploymentPrefix}-deploy-Management-Resource-Groups${parDeploymentSuffix}', 64)
+ scope: subscription(parManagementSubscriptionId)
+ params: {
+ parTags: parTags
+ parDeploymentLocation: parDeploymentLocation
+ parDeploymentPrefix: parDeploymentPrefix
+ parDeploymentSuffix: parDeploymentSuffix
+ }
+}
+
+// Deploy connectivity resource groups
+module modConnectivityResourceGroups '../../modules/resourceGroups/connectivityResourceGroups.bicep' = {
+ name: take('${parDeploymentPrefix}-deploy-Connectivity-Resource-Groups${parDeploymentSuffix}', 64)
+ scope: subscription(parConnectivitySubscriptionId)
+ params: {
+ parTags: parTags
+ parDeploymentLocation: parDeploymentLocation
+ parDeploymentPrefix: parDeploymentPrefix
+ parDeploymentSuffix: parDeploymentSuffix
+ }
+}
+
+// Deploy identity resource groups
+module modIdentityResourceGroups '../../modules/resourceGroups/identityResourceGroups.bicep' = {
+ name: take('${parDeploymentPrefix}-deploy-Identity-Resource-Groups${parDeploymentSuffix}', 64)
+ scope: subscription(parIdentitySubscriptionId)
+ params: {
+ parTags: parTags
+ parDeploymentLocation: parDeploymentLocation
+ parDeploymentPrefix: parDeploymentPrefix
+ parDeploymentSuffix: parDeploymentSuffix
+ }
+}
+
+// Deploy managed identity
+module modManagedIdentity '../../modules/Microsoft.ManagedIdentity/userAssignedIdentities/deploy.bicep' = {
+ name: take('${parDeploymentPrefix}-deploy-Managed-Identity${parDeploymentSuffix}', 64)
+ scope: resourceGroup(parIdentitySubscriptionId, '${parDeploymentPrefix}-rg-managed-identities-${parDeploymentLocation}${parDeploymentSuffix}')
+ params: {
+ parLocation: parDeploymentLocation
+ parName: '${parDeploymentPrefix}-managed-identity-${parDeploymentLocation}${parDeploymentSuffix}'
+ parTags: parTags
+ }
+ dependsOn: [
+ modIdentityResourceGroups
+ ]
+}
+
+// Deploy role assignments
+module modRoleAssignmentManagementGroup '../../dependencies/infra-as-code/bicep/modules/roleAssignments/roleAssignmentManagementGroup.bicep' = {
+ name: take('${parDeploymentPrefix}-deploy-Role-Assignment-Management-Group${parDeploymentSuffix}', 64)
+ scope: managementGroup(varManagementGroupId)
+ params: {
+ parAssigneeObjectId: modManagedIdentity.outputs.outPrincipalId
+ parAssigneePrincipalType: 'ServicePrincipal'
+ parRoleDefinitionId: 'acdd72a7-3385-48ef-bd42-f606fba81ae7'
+ parTelemetryOptOut: true
+ }
+ dependsOn: [
+ modIdentityResourceGroups
+ modManagedIdentity
+ ]
+}
+
+// Deploy logging resources
+module modLogging '../../dependencies/infra-as-code/bicep/modules/logging/logging.bicep' = if (parDeployLogAnalyticsWorkspace) {
+ name: take('${parDeploymentPrefix}-deploy-Logging${parDeploymentSuffix}', 64)
+ scope: resourceGroup(parManagementSubscriptionId, '${parDeploymentPrefix}-rg-logging-${parDeploymentLocation}${parDeploymentSuffix}')
+ params: {
+ parAutomationAccountLocation: parDeploymentLocation
+ parLogAnalyticsWorkspaceLocation: parDeploymentLocation
+ parAutomationAccountName: '${parDeploymentPrefix}-automation-account-${parDeploymentLocation}${parDeploymentSuffix}'
+ parLogAnalyticsWorkspaceLogRetentionInDays: parLogRetentionInDays
+ parLogAnalyticsWorkspaceName: '${parDeploymentPrefix}-log-analytics-${parDeploymentLocation}${parDeploymentSuffix}'
+ parLogAnalyticsWorkspaceSolutions: [
+ 'AgentHealthAssessment'
+ 'AntiMalware'
+ 'ChangeTracking'
+ 'Security'
+ 'SecurityInsights'
+ 'ServiceMap'
+ 'SQLAssessment'
+ 'Updates'
+ 'VMInsights'
+ ]
+ parTags: parTags
+ parTelemetryOptOut: true
+ }
+ dependsOn: [
+ modManagementResourceGroups
+ ]
+}
+
+// Deploy hub networking resources
+module modHubNetworking '../../dependencies/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep' = if (parDeployHubNetwork) {
+ name: take('${parDeploymentPrefix}-deploy-Hub-Network${parDeploymentSuffix}', 64)
+ scope: resourceGroup(parConnectivitySubscriptionId, '${parDeploymentPrefix}-rg-hub-network-${parDeploymentLocation}${parDeploymentSuffix}')
+ params: {
+ parAzFirewallEnabled: parEnableFirewall
+ parAzFirewallName: '${parDeploymentPrefix}-afw-${parDeploymentLocation}${parDeploymentSuffix}'
+ parAzFirewallTier: parUsePremiumFirewall ? 'Premium' : 'Standard'
+ parAzBastionEnabled: parDeployBastion
+ parAzBastionName: '${parDeploymentPrefix}-bas-${parDeploymentLocation}${parDeploymentSuffix}'
+ parAzBastionSku: 'Standard'
+ parCompanyPrefix: parDeploymentPrefix
+ parDdosEnabled: parDeployDdosProtection
+ parDdosPlanName: '${parDeploymentPrefix}-ddos-plan-${parDeploymentLocation}${parDeploymentSuffix}'
+ parDisableBgpRoutePropagation: false
+ parAzBastionNsgName: '${parDeploymentPrefix}-nsg-AzureBastionSubnet-${parDeploymentLocation}${parDeploymentSuffix}'
+ parDnsServerIps: []
+ parExpressRouteGatewayConfig: (empty(parExpressGatewaySku) || parExpressGatewaySku == null) ? {} : {
+ name: '${parDeploymentPrefix}-erg-${parDeploymentLocation}${parDeploymentSuffix}'
+ gatewaytype: 'ExpressRoute'
+ sku: parExpressGatewaySku
+ vpntype: parExpressGatewayVpntype
+ vpnGatewayGeneration: parExpressGatewayGeneration
+ enableBgp: parExpressGatewayEnableBgp
+ activeActive: parExpressGatewayActiveActive
+ enableBgpRouteTranslationForNat: parExpressGatewayEnableBgpRouteTranslationForNat
+ enableDnsForwarding: parExpressGatewayEnableDnsForwarding
+ asn: parExpressGatewayAsn
+ bgpPeeringAddress: parExpressGatewayBgpPeeringAddress
+ bgpsettings: {
+ asn: parExpressGatewayAsn
+ bgpPeeringAddress: parExpressGatewayBgpPeeringAddress
+ peerWeight: parExpressGatewayPeerWeight
+ }
+ }
+ parHubNetworkAddressPrefix: parHubNetworkAddressPrefix
+ parHubNetworkName: '${parDeploymentPrefix}-hub-${parDeploymentLocation}${parDeploymentSuffix}'
+ parHubRouteTableName: '${parDeploymentPrefix}-rt-${parDeploymentLocation}${parDeploymentSuffix}'
+ parLocation: parDeploymentLocation
+ parAzFirewallDnsProxyEnabled: true
+ parPrivateDnsZones: [
+ 'privatelink.azure-automation.net'
+ 'privatelink${environment().suffixes.sqlServerHostname}'
+ 'privatelink.sql.azuresynapse.net'
+ 'privatelink.dev.azuresynapse.net'
+ 'privatelink.azuresynapse.net'
+ 'privatelink.blob.${environment().suffixes.storage}'
+ 'privatelink.table.${environment().suffixes.storage}'
+ 'privatelink.queue.${environment().suffixes.storage}'
+ 'privatelink.file.${environment().suffixes.storage}'
+ 'privatelink.web.${environment().suffixes.storage}'
+ 'privatelink.dfs.${environment().suffixes.storage}'
+ 'privatelink.documents.azure.com'
+ 'privatelink.mongo.cosmos.azure.com'
+ 'privatelink.cassandra.cosmos.azure.com'
+ 'privatelink.gremlin.cosmos.azure.com'
+ 'privatelink.table.cosmos.azure.com'
+ 'privatelink.${parDeploymentLocation}.batch.azure.com'
+ 'privatelink.postgres.database.azure.com'
+ 'privatelink.mysql.database.azure.com'
+ 'privatelink.mariadb.database.azure.com'
+ 'privatelink.vaultcore.azure.net'
+ 'privatelink.managedhsm.azure.net'
+ 'privatelink.${parDeploymentLocation}.azmk8s.io'
+ 'privatelink.${parDeploymentLocation}.backup.windowsazure.com'
+ 'privatelink.siterecovery.windowsazure.com'
+ 'privatelink.servicebus.windows.net'
+ 'privatelink.azure-devices.net'
+ 'privatelink.eventgrid.azure.net'
+ 'privatelink.azurewebsites.net'
+ 'privatelink.api.azureml.ms'
+ 'privatelink.notebooks.azure.net'
+ 'privatelink.service.signalr.net'
+ 'privatelink.monitor.azure.com'
+ 'privatelink.oms.opinsights.azure.com'
+ 'privatelink.ods.opinsights.azure.com'
+ 'privatelink.agentsvc.azure-automation.net'
+ 'privatelink.afs.azure.net'
+ 'privatelink.datafactory.azure.net'
+ 'privatelink.adf.azure.com'
+ 'privatelink.redis.cache.windows.net'
+ 'privatelink.redisenterprise.cache.azure.net'
+ 'privatelink.purview.azure.com'
+ 'privatelink.purviewstudio.azure.com'
+ 'privatelink.digitaltwins.azure.net'
+ 'privatelink.azconfig.io'
+ 'privatelink.cognitiveservices.azure.com'
+ 'privatelink${environment().suffixes.acrLoginServer}'
+ 'privatelink.search.windows.net'
+ 'privatelink.azurehdinsight.net'
+ 'privatelink.media.azure.net'
+ 'privatelink.his.arc.azure.com'
+ 'privatelink.guestconfiguration.azure.com'
+ ]
+ parPrivateDnsZonesEnabled: true
+ parPrivateDnsZonesResourceGroup: '${parDeploymentPrefix}-rg-hub-network-${parDeploymentLocation}${parDeploymentSuffix}'
+ parPublicIpSku: 'Standard'
+ parPublicIpSuffix: '-PublicIP${parDeploymentSuffix}'
+ parSubnets: parSubnets
+ parTags: parTags
+ parTelemetryOptOut: true
+ parBastionOutboundSshRdpPorts: parBastionOutboundSshRdpPorts
+ parVpnGatewayConfig: (empty(parVpnGatewaySku) || parVpnGatewaySku == null) ? {} : {
+ name: '${parDeploymentPrefix}-vpng-${parDeploymentLocation}${parDeploymentSuffix}'
+ gatewaytype: 'Vpn'
+ sku: parVpnGatewaySku
+ vpntype: parVpnGatewayVpntype
+ generation: parVpnGatewayGeneration
+ enableBgp: parVpnGatewayEnableBgp
+ activeActive: parVpnGatewayActiveActive
+ enableBgpRouteTranslationForNat: parVpnGatewayEnableBgpRouteTranslationForNat
+ enableDnsForwarding: parVpnGatewayEnableDnsForwarding
+ asn: parVpnGatewayAsn
+ bgpPeeringAddress: parVpnGatewayBgpPeeringAddress
+ bgpsettings: {
+ asn: parVpnGatewayAsn
+ bgpPeeringAddress: parVpnGatewayBgpPeeringAddress
+ peerWeight: parVpnGatewayPeerWeight
+ }
+ }
+ }
+ dependsOn: [
+ modConnectivityResourceGroups
+ ]
+}
+
+output outConnectivitySubscriptionId string = parConnectivitySubscriptionId
+output outDeploymentLocation string = parDeploymentLocation
+output outDeploymentPrefix string = parDeploymentPrefix
+output outDdosProtectionResourceId string = parDeployHubNetwork ? modHubNetworking.outputs.outDdosPlanResourceId : ''
+output outLogAnalyticsWorkspaceId string = modLogging.outputs.outLogAnalyticsWorkspaceId
+output outAutomationAccountName string = modLogging.outputs.outAutomationAccountName
+output outPrivateDNSZones array = parDeployHubNetwork ? modHubNetworking.outputs.outPrivateDnsZones : []
+output outHubVirtualNetworkId string = parDeployHubNetwork ? modHubNetworking.outputs.outHubVirtualNetworkId : ''