From cbac46414ed7aa7dd90217e383598b417d3e642d Mon Sep 17 00:00:00 2001 From: VeronicaSea <69697690+VeronicaSea@users.noreply.github.com> Date: Wed, 3 Apr 2024 10:01:34 -0700 Subject: [PATCH] Release 1.1.0 (#18) * Release 1.1.0 * Release 1.1.0 * Release 1.1.0 --------- Co-authored-by: Microsoft Open Source --- .gitignore | 2 + dependencies/Alz.Tools/Alz.Tools.psd1 | 4 +- .../bicep/modules/hubNetworking/README.md | 2 + .../generateddocs/hubNetworking.bicep.md | 198 ++++++- .../modules/hubNetworking/hubNetworking.bicep | 225 +++++++- .../hubNetworking.parameters.all.json | 54 ++ .../hubNetworking.parameters.az.all.json | 312 +++++++++++ .../hubNetworking.parameters.min.json | 6 + .../mc-hubNetworking.parameters.all.json | 54 ++ .../mc-hubNetworking.parameters.min.json | 6 + .../logging/generateddocs/logging.bicep.md | 104 ++++ .../bicep/modules/logging/logging.bicep | 100 +++- .../parameters/logging.parameters.all.json | 30 ++ .../parameters/mc-logging.parameters.all.json | 30 ++ .../bicep/modules/managementGroups/README.md | 4 +- .../generateddocs/mgDiagSettings.bicep.md | 12 + .../mgDiagSettings/mgDiagSettings.bicep | 5 +- .../mgDiagSettings.parameters.all.json | 3 + .../alzDefaultPolicyAssignments.bicep | 202 +++++++ .../alzDefaultPolicyAssignments.bicep.md | 58 ++ ...faultPolicyAssignments.parameters.all.json | 15 + ...t_res_location_match_rg_location.tmpl.json | 18 + ...signment_es_audit_zoneresiliency.tmpl.json | 25 + ...assignment_es_deploy_mdfc_config.tmpl.json | 2 +- ...ssignment_es_enforce_alz_sandbox.tmpl.json | 7 +- ...nforce_sovereignty_baseline_conf.tmpl.json | 78 ++- ...orce_sovereignty_baseline_global.tmpl.json | 80 +++ .../policyAssignmentManagementGroup.bicep | 10 +- .../definitions/customPolicyDefinitions.bicep | 136 ++++- ...ition_es_Deny-MgmtPorts-From-Internet.json | 4 +- ...inition_es_Deploy-Diagnostics-MariaDB.json | 7 +- ...s_Deploy-MDFC-Arc-SQL-DCR-Association.json | 200 +++++++ ...s_Deploy-MDFC-Arc-Sql-DefenderSQL-DCR.json | 404 ++++++++++++++ ...icy_definition_es_Deploy-MDFC-SQL-AMA.json | 175 ++++++ ...on_es_Deploy-MDFC-SQL-DefenderSQL-DCR.json | 463 ++++++++++++++++ ...nition_es_Deploy-MDFC-SQL-DefenderSQL.json | 240 +++++++++ ...serAssignedManagedIdentity-VMInsights.json | 404 ++++++++++++++ ...efinition_es_Deny-PublicPaaSEndpoints.json | 25 +- ...s_Deny-PublicPaaSEndpoints.parameters.json | 7 + ...definition_es_Deploy-AUM-CheckUpdates.json | 153 ++++++ ...es_Deploy-AUM-CheckUpdates.parameters.json | 78 +++ ..._set_definition_es_Deploy-MDFC-Config.json | 8 +- ...tion_es_Deploy-MDFC-Config.parameters.json | 3 + ...nition_es_Deploy-MDFC-DefenderSQL-AMA.json | 237 +++++++++ ...eploy-MDFC-DefenderSQL-AMA.parameters.json | 117 ++++ ...efinition_es_Deploy-Private-DNS-Zones.json | 6 +- ...s_Deploy-Private-DNS-Zones.parameters.json | 4 +- ..._definition_es_Enforce-EncryptTransit.json | 25 +- ..._es_Enforce-EncryptTransit.parameters.json | 7 + .../mc-customPolicyDefinitions.bicep | 4 +- .../privateDnsZoneLinks.bicep.md | 20 + .../privateDnsZoneLinks.bicep | 31 ++ .../generateddocs/privateDnsZones.bicep.md | 20 + .../privateDnsZones/privateDnsZones.bicep | 58 +- .../publicIp/generateddocs/publicIp.bicep.md | 21 + .../bicep/modules/publicIp/publicIp.bicep | 34 +- .../generateddocs/resourceGroup.bicep.md | 20 + .../generateddocs/resourceGroupLock.bicep.md | 54 ++ .../resourceGroup.parameters.all.json | 6 + .../modules/resourceGroup/resourceGroup.bicep | 32 ++ .../resourceGroup/resourceGroupLock.bicep | 36 ++ .../generateddocs/spokeNetworking.bicep.md | 60 +++ .../spokeNetworking.parameters.all.json | 18 + .../spokeNetworking/spokeNetworking.bicep | 64 +++ .../subscriptionPlacement.bicep | 2 +- .../bicep/modules/vwanConnectivity/README.md | 24 +- .../generateddocs/vwanConnectivity.bicep.md | 176 +++++- .../mc-vwanConnectivity.parameters.all.json | 48 ++ .../vwanConnectivity.parameters.all.json | 48 ++ .../vwanConnectivity.parameters.az.all.json | 218 ++++++++ .../samples/baseline.sample.bicep | 4 +- .../vwanConnectivity/vwanConnectivity.bicep | 234 +++++++- .../generateddocs/hubPeeredSpoke.bicep.md | 95 ++++ .../hubPeeredSpoke/hubPeeredSpoke.bicep | 67 +++ .../hubPeeredSpoke.parameters.all.json | 30 ++ .../hubPeeredSpoke.vwan.parameters.all.json | 30 ++ .../generateddocs/mgDiagSettingsAll.bicep.md | 12 + .../mgDiagSettingsAll/mgDiagSettingsAll.bicep | 8 + .../mgDiagSettingsAll.parameters.all.json | 3 + .../scripts/Invoke-LibraryUpdate-China.ps1 | 16 +- .../scripts/Invoke-PolicyToBicep-China.ps1 | 13 +- dependencies/scripts/Invoke-PolicyToBicep.ps1 | 15 +- dependencies/scripts/Wipe-AlzTenant.ps1 | 102 ++++ dependencies/scripts/mc-Wipe-AlzTenant.ps1 | 102 ++++ docs/07-Deployment-Parameters.md | 19 +- docs/12-FAQ.md | 6 + docs/13-Troubleshooting.md | 4 + docs/scenarios/Custom-Policies.md | 41 +- docs/scenarios/Removing-Policy-Assignments.md | 14 + docs/scenarios/Using-Policy-Portfolio.md | 4 +- modules/compliance/customCompliance.bicep | 31 +- .../customerPolicySetAssignments.bicep | 17 +- modules/compliance/defaultCompliance.bicep | 503 ------------------ ...deploy_slz_connectivity_defaults.tmpl.json | 18 - ...ignment_deploy_slz_corp_defaults.tmpl.json | 18 - ...ploy_slz_decommissioned_defaults.tmpl.json | 18 - ...ent_deploy_slz_identity_defaults.tmpl.json | 18 - ...eploy_slz_landing_zones_defaults.tmpl.json | 18 - ...t_deploy_slz_management_defaults.tmpl.json | 18 - ...nment_deploy_slz_online_defaults.tmpl.json | 18 - ...ent_deploy_slz_platform_defaults.tmpl.json | 18 - ...ment_deploy_slz_sandbox_defaults.tmpl.json | 18 - ...nmnet_deploy_slz_global_defaults.tmpl.json | 22 - .../slzConfidentialDefaults.json | 287 ---------- .../slzConnectivityDefaults.json | 17 - .../policySetDefinitions/slzCorpDefaults.json | 17 - .../slzDecommissionedDefaults.json | 17 - .../slzGlobalDefaults.json | 132 ----- .../slzIdentityDefaults.json | 17 - .../slzLandingZoneDefaults.json | 17 - .../slzManagementDefaults.json | 17 - .../slzOnlineDefaults.json | 17 - .../slzPlatformDefaults.json | 17 - .../slzSandboxDefaults.json | 17 - modules/dashboard/dashboard.bicep | 14 +- orchestration/const/doNotRetryErrorCodes.json | 6 +- .../customCompliance/customCompliance.bicep | 7 + .../defaultCompliance/defaultCompliance.bicep | 125 +++-- ...initions.txt => alz-PolicyDefinitions.txt} | 4 +- .../policyInstallation.bicep | 10 +- .../slz-CustomSLZPolicySetDefinitions.txt | 34 ++ ...andCustomSLZGlobalPolicySetDefinitions.txt | 55 -- ...efaultandCustomSLZPolicySetDefinitions.txt | 143 ----- orchestration/scripts/Invoke-Helper.ps1 | 17 +- ....ps1 => Invoke-SlzCustomPolicyToBicep.ps1} | 201 ++----- orchestration/scripts/New-Compliance.ps1 | 120 +++-- orchestration/scripts/New-Platform.ps1 | 2 +- .../policySetParameterSampleFile.json | 11 + .../sovereignLandingZone.parameters.json | 20 +- 129 files changed, 6371 insertions(+), 1867 deletions(-) create mode 100644 dependencies/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.az.all.json create mode 100644 dependencies/infra-as-code/bicep/modules/policy/assignments/lib/policy_assignments/policy_assignment_es_audit_res_location_match_rg_location.tmpl.json create mode 100644 dependencies/infra-as-code/bicep/modules/policy/assignments/lib/policy_assignments/policy_assignment_es_audit_zoneresiliency.tmpl.json rename modules/compliance/policyAssignments/policy_assignment_deploy_slz_confidential_defaults.tmpl.json => dependencies/infra-as-code/bicep/modules/policy/assignments/lib/policy_assignments/policy_assignment_es_enforce_sovereignty_baseline_conf.tmpl.json (85%) create mode 100644 dependencies/infra-as-code/bicep/modules/policy/assignments/lib/policy_assignments/policy_assignment_es_enforce_sovereignty_baseline_global.tmpl.json create mode 100644 dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deploy-MDFC-Arc-SQL-DCR-Association.json create mode 100644 dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deploy-MDFC-Arc-Sql-DefenderSQL-DCR.json create mode 100644 dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deploy-MDFC-SQL-AMA.json create mode 100644 dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deploy-MDFC-SQL-DefenderSQL-DCR.json create mode 100644 dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deploy-MDFC-SQL-DefenderSQL.json create mode 100644 dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deploy-UserAssignedManagedIdentity-VMInsights.json create mode 100644 dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-AUM-CheckUpdates.json create mode 100644 dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-AUM-CheckUpdates.parameters.json create mode 100644 dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-MDFC-DefenderSQL-AMA.json create mode 100644 dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-MDFC-DefenderSQL-AMA.parameters.json create mode 100644 dependencies/infra-as-code/bicep/modules/resourceGroup/generateddocs/resourceGroupLock.bicep.md create mode 100644 dependencies/infra-as-code/bicep/modules/resourceGroup/resourceGroupLock.bicep create mode 100644 dependencies/infra-as-code/bicep/modules/vwanConnectivity/parameters/vwanConnectivity.parameters.az.all.json create mode 100644 dependencies/scripts/Wipe-AlzTenant.ps1 create mode 100644 dependencies/scripts/mc-Wipe-AlzTenant.ps1 delete mode 100644 modules/compliance/defaultCompliance.bicep delete mode 100644 modules/compliance/policyAssignments/policy_assignment_deploy_slz_connectivity_defaults.tmpl.json delete mode 100644 modules/compliance/policyAssignments/policy_assignment_deploy_slz_corp_defaults.tmpl.json delete mode 100644 modules/compliance/policyAssignments/policy_assignment_deploy_slz_decommissioned_defaults.tmpl.json delete mode 100644 modules/compliance/policyAssignments/policy_assignment_deploy_slz_identity_defaults.tmpl.json delete mode 100644 modules/compliance/policyAssignments/policy_assignment_deploy_slz_landing_zones_defaults.tmpl.json delete mode 100644 modules/compliance/policyAssignments/policy_assignment_deploy_slz_management_defaults.tmpl.json delete mode 100644 modules/compliance/policyAssignments/policy_assignment_deploy_slz_online_defaults.tmpl.json delete mode 100644 modules/compliance/policyAssignments/policy_assignment_deploy_slz_platform_defaults.tmpl.json delete mode 100644 modules/compliance/policyAssignments/policy_assignment_deploy_slz_sandbox_defaults.tmpl.json delete mode 100644 modules/compliance/policyAssignments/policy_assignmnet_deploy_slz_global_defaults.tmpl.json delete mode 100644 modules/compliance/policySetDefinitions/slzConfidentialDefaults.json delete mode 100644 modules/compliance/policySetDefinitions/slzConnectivityDefaults.json delete mode 100644 modules/compliance/policySetDefinitions/slzCorpDefaults.json delete mode 100644 modules/compliance/policySetDefinitions/slzDecommissionedDefaults.json delete mode 100644 modules/compliance/policySetDefinitions/slzGlobalDefaults.json delete mode 100644 modules/compliance/policySetDefinitions/slzIdentityDefaults.json delete mode 100644 modules/compliance/policySetDefinitions/slzLandingZoneDefaults.json delete mode 100644 modules/compliance/policySetDefinitions/slzManagementDefaults.json delete mode 100644 modules/compliance/policySetDefinitions/slzOnlineDefaults.json delete mode 100644 modules/compliance/policySetDefinitions/slzPlatformDefaults.json delete mode 100644 modules/compliance/policySetDefinitions/slzSandboxDefaults.json rename orchestration/policyInstallation/{slz-DefaultandCustomPolicyDefinitions.txt => alz-PolicyDefinitions.txt} (98%) create mode 100644 orchestration/policyInstallation/slz-CustomSLZPolicySetDefinitions.txt delete mode 100644 orchestration/policyInstallation/slz-DefaultandCustomSLZGlobalPolicySetDefinitions.txt delete mode 100644 orchestration/policyInstallation/slz-DefaultandCustomSLZPolicySetDefinitions.txt rename orchestration/scripts/{Invoke-SlzDefaultandCustomPolicyToBicep.ps1 => Invoke-SlzCustomPolicyToBicep.ps1} (70%) create mode 100644 orchestration/scripts/parameters/policyParameters/policySetParameterSampleFile.json diff --git a/.gitignore b/.gitignore index 24ad4da..13cd700 100644 --- a/.gitignore +++ b/.gitignore @@ -17,10 +17,12 @@ modules/**/*.json orchestration/**/*.json !orchestration/const/*.json !orchestration/**/parameters/*.parameters.json +!orchestration/**/parameters/policyParameters/*.json orchestration/scripts/outputs/* # ignore all files added or modified by Invoke-SlzDefaultandCustomPolicyToBicep.ps1 dependencies/infra-as-code/bicep/modules/policy/assignments/lib/policy_assignments/_*.txt dependencies/infra-as-code/bicep/modules/policy/definitions/alzPolicySetDefinitions.bicep +dependencies/infra-as-code/bicep/modules/policy/definitions/alz-PolicyDefinitions.bicep dependencies/infra-as-code/bicep/modules/policy/definitions/slz-*.bicep dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/_*.txt dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/_*.txt diff --git a/dependencies/Alz.Tools/Alz.Tools.psd1 b/dependencies/Alz.Tools/Alz.Tools.psd1 index b08678b..ed86990 100644 --- a/dependencies/Alz.Tools/Alz.Tools.psd1 +++ b/dependencies/Alz.Tools/Alz.Tools.psd1 @@ -58,10 +58,10 @@ ModuleName = 'Az.Accounts' ModuleVersion = '2.9.0' } - @{ + <#@{ ModuleName = 'Az.Resources' ModuleVersion = '5.6.0' - } + }#> ) # Assemblies that must be loaded prior to importing this module diff --git a/dependencies/infra-as-code/bicep/modules/hubNetworking/README.md b/dependencies/infra-as-code/bicep/modules/hubNetworking/README.md index 8cbc58f..1ae2f13 100644 --- a/dependencies/infra-as-code/bicep/modules/hubNetworking/README.md +++ b/dependencies/infra-as-code/bicep/modules/hubNetworking/README.md @@ -21,6 +21,8 @@ Module deploys the following resources: > **NOTE:** > - Although there are generated parameter markdowns for Azure Commercial Cloud, this same module can still be used in Azure China. Example parameter are in the [parameters](./parameters/) folder. > +> - The file `parameters/hubNetworking.parameters.az.all.json` contains parameter values for SKUs that are compatible with availability zones for relevant resource types. In cases where you are deploying to a region that does not support availability zones, you should opt for the `parameters/hubNetworking.parameters.all.json` file. +> > - When deploying using the `parameters/hubNetworking.parameters.all.json` you must update the `parPrivateDnsZones` parameter by replacing the `xxxxxx` placeholders with the deployment region or geo code, for Azure Backup. Failure to do so will cause these services to be unreachable over private endpoints. > > For example, if deploying to East US the following zone entries: diff --git a/dependencies/infra-as-code/bicep/modules/hubNetworking/generateddocs/hubNetworking.bicep.md b/dependencies/infra-as-code/bicep/modules/hubNetworking/generateddocs/hubNetworking.bicep.md index bab8c10..893d1b5 100644 --- a/dependencies/infra-as-code/bicep/modules/hubNetworking/generateddocs/hubNetworking.bicep.md +++ b/dependencies/infra-as-code/bicep/modules/hubNetworking/generateddocs/hubNetworking.bicep.md @@ -9,9 +9,11 @@ Parameter name | Required | Description parLocation | No | The Azure Region to deploy the resources into. parCompanyPrefix | No | Prefix value which will be prepended to all resource names. parHubNetworkName | No | Name for Hub Network. +parGlobalResourceLock | No | Global Resource Lock Configuration used for all resources deployed in this module. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. parHubNetworkAddressPrefix | No | The IP address range for Hub Network. parSubnets | No | The name, IP address range, network security group, route table and delegation serviceName for each subnet in the virtual networks. parDnsServerIps | No | Array of DNS Server IP addresses for VNet. +parVirtualNetworkLock | No | Resource Lock Configuration for Virtual Network. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. parPublicIpSku | No | Public IP Address SKU. parPublicIpPrefix | No | Optional Prefix for Public IPs. Include a succedent dash if required. Example: prefix- parPublicIpSuffix | No | Optional Suffix for Public IPs. Include a preceding dash if required. Example: -suffix @@ -20,8 +22,10 @@ parAzBastionName | No | Name Associated with Bastion Service. parAzBastionSku | No | Azure Bastion SKU. parAzBastionTunneling | No | Switch to enable/disable Bastion native client support. This is only supported when the Standard SKU is used for Bastion as documented here: https://learn.microsoft.com/azure/bastion/native-client parAzBastionNsgName | No | Name for Azure Bastion Subnet NSG. +parBastionLock | No | Resource Lock Configuration for Bastion. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. parDdosEnabled | No | Switch to enable/disable DDoS Network Protection deployment. parDdosPlanName | No | DDoS Plan Name. +parDdosLock | No | Resource Lock Configuration for DDoS Plan. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. parAzFirewallEnabled | No | Switch to enable/disable Azure Firewall deployment. parAzFirewallName | No | Azure Firewall Name. parAzFirewallPoliciesName | No | Azure Firewall Policies Name. @@ -32,15 +36,21 @@ parAzErGatewayAvailabilityZones | No | Availability Zones to deploy the VP parAzVpnGatewayAvailabilityZones | No | Availability Zones to deploy the VPN/ER PIP across. Region must support Availability Zones to use. If it does not then leave empty. Ensure that you select a zonal SKU for the ER/VPN Gateway if using Availability Zones for the PIP. parAzFirewallDnsProxyEnabled | No | Switch to enable/disable Azure Firewall DNS Proxy. parAzFirewallDnsServers | No | Array of custom DNS servers used by Azure Firewall +parAzureFirewallLock | No | Resource Lock Configuration for Azure Firewall. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. parHubRouteTableName | No | Name of Route table to create for the default route of Hub. parDisableBgpRoutePropagation | No | Switch to enable/disable BGP Propagation on route table. +parHubRouteTableLock | No | Resource Lock Configuration for Hub Route Table. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. parPrivateDnsZonesEnabled | No | Switch to enable/disable Private DNS Zones deployment. parPrivateDnsZonesResourceGroup | No | Resource Group Name for Private DNS Zones. parPrivateDnsZones | No | Array of DNS Zones to provision in Hub Virtual Network. Default: All known Azure Private DNS Zones parPrivateDnsZoneAutoMergeAzureBackupZone | No | Set Parameter to false to skip the addition of a Private DNS Zone for Azure Backup. parVirtualNetworkIdToLinkFailover | No | Resource ID of Failover VNet for Private DNS Zone VNet Failover Links -parVpnGatewayConfig | No | Configuration for VPN virtual network gateway to be deployed. If a VPN virtual network gateway is not desired an empty object should be used as the input parameter in the parameter file, i.e. "parVpnGatewayConfig": { "value": {} } -parExpressRouteGatewayConfig | No | Configuration for ExpressRoute virtual network gateway to be deployed. If a ExpressRoute virtual network gateway is not desired an empty object should be used as the input parameter in the parameter file, i.e. "parExpressRouteGatewayConfig": { "value": {} } +parPrivateDNSZonesLock | No | Resource Lock Configuration for Private DNS Zone(s). - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. +parVpnGatewayEnabled | No | Switch to enable/disable VPN virtual network gateway deployment. +parVpnGatewayConfig | No | Configuration for VPN virtual network gateway to be deployed. +parExpressRouteGatewayEnabled | No | Switch to enable/disable ExpressRoute virtual network gateway deployment. +parExpressRouteGatewayConfig | No | Configuration for ExpressRoute virtual network gateway to be deployed. +parVirtualNetworkGatewayLock | No | Resource Lock Configuration for ExpressRoute Virtual Network Gateway. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. parTags | No | Tags you would like to be applied to all resources in this module. parTelemetryOptOut | No | Set Parameter to true to Opt-out of deployment telemetry. parBastionOutboundSshRdpPorts | No | Define outbound destination ports or ranges for SSH or RDP that you want to access from Azure Bastion. @@ -69,6 +79,19 @@ Name for Hub Network. - Default value: `[format('{0}-hub-{1}', parameters('parCompanyPrefix'), parameters('parLocation'))]` +### parGlobalResourceLock + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Global Resource Lock Configuration used for all resources deployed in this module. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep Hub Networking Module.}` + ### parHubNetworkAddressPrefix ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) @@ -91,6 +114,19 @@ The name, IP address range, network security group, route table and delegation s Array of DNS Server IP addresses for VNet. +### parVirtualNetworkLock + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Resource Lock Configuration for Virtual Network. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep Hub Networking Module.}` + ### parPublicIpSku ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) @@ -157,6 +193,19 @@ Name for Azure Bastion Subnet NSG. - Default value: `nsg-AzureBastionSubnet` +### parBastionLock + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Resource Lock Configuration for Bastion. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep Hub Networking Module.}` + ### parDdosEnabled ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) @@ -173,6 +222,19 @@ DDoS Plan Name. - Default value: `[format('{0}-ddos-plan', parameters('parCompanyPrefix'))]` +### parDdosLock + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Resource Lock Configuration for DDoS Plan. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep Hub Networking Module.}` + ### parAzFirewallEnabled ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) @@ -255,6 +317,19 @@ Switch to enable/disable Azure Firewall DNS Proxy. Array of custom DNS servers used by Azure Firewall +### parAzureFirewallLock + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + + Resource Lock Configuration for Azure Firewall. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep Hub Networking Module.}` + ### parHubRouteTableName ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) @@ -271,6 +346,19 @@ Switch to enable/disable BGP Propagation on route table. - Default value: `False` +### parHubRouteTableLock + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Resource Lock Configuration for Hub Route Table. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep Hub Networking Module.}` + ### parPrivateDnsZonesEnabled ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) @@ -309,28 +397,64 @@ Set Parameter to false to skip the addition of a Private DNS Zone for Azure Back Resource ID of Failover VNet for Private DNS Zone VNet Failover Links +### parPrivateDNSZonesLock + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Resource Lock Configuration for Private DNS Zone(s). + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep Hub Networking Module.}` + +### parVpnGatewayEnabled + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Switch to enable/disable VPN virtual network gateway deployment. + +- Default value: `True` + ### parVpnGatewayConfig ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) -Configuration for VPN virtual network gateway to be deployed. If a VPN virtual network gateway is not desired an empty object should be used as the input parameter in the parameter file, i.e. -"parVpnGatewayConfig": { - "value": {} -} +Configuration for VPN virtual network gateway to be deployed. - Default value: `@{name=[format('{0}-Vpn-Gateway', parameters('parCompanyPrefix'))]; gatewayType=Vpn; sku=VpnGw1; vpnType=RouteBased; generation=Generation1; enableBgp=False; activeActive=False; enableBgpRouteTranslationForNat=False; enableDnsForwarding=False; bgpPeeringAddress=; bgpsettings=; vpnClientConfiguration=}` +### parExpressRouteGatewayEnabled + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Switch to enable/disable ExpressRoute virtual network gateway deployment. + +- Default value: `True` + ### parExpressRouteGatewayConfig ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) -Configuration for ExpressRoute virtual network gateway to be deployed. If a ExpressRoute virtual network gateway is not desired an empty object should be used as the input parameter in the parameter file, i.e. -"parExpressRouteGatewayConfig": { - "value": {} -} +Configuration for ExpressRoute virtual network gateway to be deployed. - Default value: `@{name=[format('{0}-ExpressRoute-Gateway', parameters('parCompanyPrefix'))]; gatewayType=ExpressRoute; sku=ErGw1AZ; vpnType=RouteBased; vpnGatewayGeneration=None; enableBgp=False; activeActive=False; enableBgpRouteTranslationForNat=False; enableDnsForwarding=False; bgpPeeringAddress=; bgpsettings=}` +### parVirtualNetworkGatewayLock + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Resource Lock Configuration for ExpressRoute Virtual Network Gateway. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep Hub Networking Module.}` + ### parTags ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) @@ -386,6 +510,12 @@ outHubVirtualNetworkId | string | "parHubNetworkName": { "value": "[format('{0}-hub-{1}', parameters('parCompanyPrefix'), parameters('parLocation'))]" }, + "parGlobalResourceLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, "parHubNetworkAddressPrefix": { "value": "10.10.0.0/16" }, @@ -420,6 +550,12 @@ outHubVirtualNetworkId | string | "parDnsServerIps": { "value": [] }, + "parVirtualNetworkLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, "parPublicIpSku": { "value": "Standard" }, @@ -444,12 +580,24 @@ outHubVirtualNetworkId | string | "parAzBastionNsgName": { "value": "nsg-AzureBastionSubnet" }, + "parBastionLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, "parDdosEnabled": { "value": true }, "parDdosPlanName": { "value": "[format('{0}-ddos-plan', parameters('parCompanyPrefix'))]" }, + "parDdosLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, "parAzFirewallEnabled": { "value": true }, @@ -480,12 +628,24 @@ outHubVirtualNetworkId | string | "parAzFirewallDnsServers": { "value": [] }, + "parAzureFirewallLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, "parHubRouteTableName": { "value": "[format('{0}-hub-routetable', parameters('parCompanyPrefix'))]" }, "parDisableBgpRoutePropagation": { "value": false }, + "parHubRouteTableLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, "parPrivateDnsZonesEnabled": { "value": true }, @@ -569,6 +729,15 @@ outHubVirtualNetworkId | string | "parVirtualNetworkIdToLinkFailover": { "value": "" }, + "parPrivateDNSZonesLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, + "parVpnGatewayEnabled": { + "value": true + }, "parVpnGatewayConfig": { "value": { "name": "[format('{0}-Vpn-Gateway', parameters('parCompanyPrefix'))]", @@ -589,6 +758,9 @@ outHubVirtualNetworkId | string | "vpnClientConfiguration": {} } }, + "parExpressRouteGatewayEnabled": { + "value": true + }, "parExpressRouteGatewayConfig": { "value": { "name": "[format('{0}-ExpressRoute-Gateway', parameters('parCompanyPrefix'))]", @@ -608,6 +780,12 @@ outHubVirtualNetworkId | string | } } }, + "parVirtualNetworkGatewayLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, "parTags": { "value": {} }, diff --git a/dependencies/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep b/dependencies/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep index e6e10cb..c7e0e1f 100644 --- a/dependencies/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep +++ b/dependencies/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep @@ -1,6 +1,34 @@ metadata name = 'ALZ Bicep - Hub Networking Module' metadata description = 'ALZ Bicep Module used to set up Hub Networking' +type subnetOptionsType = ({ + @description('Name of subnet.') + name: string + + @description('IP-address range for subnet.') + ipAddressRange: string + + @description('Id of Network Security Group to associate with subnet.') + networkSecurityGroupId: string? + + @description('Id of Route Table to associate with subnet.') + routeTableId: string? + + @description('Name of the delegation to create for the subnet.') + delegation: string? +})[] + +type lockType = { + @description('Optional. Specify the name of lock.') + name: string? + + @description('Optional. The lock settings of the service.') + kind: ('CanNotDelete' | 'ReadOnly' | 'None') + + @description('Optional. Notes about this lock.') + notes: string? +} + @sys.description('The Azure Region to deploy the resources into.') param parLocation string = resourceGroup().location @@ -10,11 +38,22 @@ param parCompanyPrefix string = 'alz' @sys.description('Name for Hub Network.') param parHubNetworkName string = '${parCompanyPrefix}-hub-${parLocation}' +@sys.description('''Global Resource Lock Configuration used for all resources deployed in this module. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parGlobalResourceLock lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep Hub Networking Module.' +} + @sys.description('The IP address range for Hub Network.') param parHubNetworkAddressPrefix string = '10.10.0.0/16' @sys.description('The name, IP address range, network security group, route table and delegation serviceName for each subnet in the virtual networks.') -param parSubnets array = [ +param parSubnets subnetOptionsType = [ { name: 'AzureBastionSubnet' ipAddressRange: '10.10.15.0/24' @@ -44,6 +83,17 @@ param parSubnets array = [ @sys.description('Array of DNS Server IP addresses for VNet.') param parDnsServerIps array = [] +@sys.description('''Resource Lock Configuration for Virtual Network. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parVirtualNetworkLock lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep Hub Networking Module.' +} + @sys.description('Public IP Address SKU.') @allowed([ 'Basic' @@ -76,12 +126,34 @@ param parAzBastionTunneling bool = false @sys.description('Name for Azure Bastion Subnet NSG.') param parAzBastionNsgName string = 'nsg-AzureBastionSubnet' +@sys.description('''Resource Lock Configuration for Bastion. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parBastionLock lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep Hub Networking Module.' +} + @sys.description('Switch to enable/disable DDoS Network Protection deployment.') param parDdosEnabled bool = true @sys.description('DDoS Plan Name.') param parDdosPlanName string = '${parCompanyPrefix}-ddos-plan' +@sys.description('''Resource Lock Configuration for DDoS Plan. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parDdosLock lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep Hub Networking Module.' +} + @sys.description('Switch to enable/disable Azure Firewall deployment.') param parAzFirewallEnabled bool = true @@ -137,12 +209,34 @@ param parAzFirewallDnsProxyEnabled bool = true @sys.description('Array of custom DNS servers used by Azure Firewall') param parAzFirewallDnsServers array = [] +@sys.description(''' Resource Lock Configuration for Azure Firewall. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parAzureFirewallLock lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep Hub Networking Module.' +} + @sys.description('Name of Route table to create for the default route of Hub.') param parHubRouteTableName string = '${parCompanyPrefix}-hub-routetable' @sys.description('Switch to enable/disable BGP Propagation on route table.') param parDisableBgpRoutePropagation bool = false +@sys.description('''Resource Lock Configuration for Hub Route Table. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parHubRouteTableLock lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep Hub Networking Module.' +} + @sys.description('Switch to enable/disable Private DNS Zones deployment.') param parPrivateDnsZonesEnabled bool = true @@ -226,11 +320,22 @@ param parPrivateDnsZoneAutoMergeAzureBackupZone bool = true @sys.description('Resource ID of Failover VNet for Private DNS Zone VNet Failover Links') param parVirtualNetworkIdToLinkFailover string = '' +@sys.description('''Resource Lock Configuration for Private DNS Zone(s). + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parPrivateDNSZonesLock lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep Hub Networking Module.' +} + +@sys.description('Switch to enable/disable VPN virtual network gateway deployment.') +param parVpnGatewayEnabled bool = true + //ASN must be 65515 if deploying VPN & ER for co-existence to work: https://docs.microsoft.com/en-us/azure/expressroute/expressroute-howto-coexist-resource-manager#limits-and-limitations -@sys.description('''Configuration for VPN virtual network gateway to be deployed. If a VPN virtual network gateway is not desired an empty object should be used as the input parameter in the parameter file, i.e. -"parVpnGatewayConfig": { - "value": {} -}''') +@sys.description('Configuration for VPN virtual network gateway to be deployed.') param parVpnGatewayConfig object = { name: '${parCompanyPrefix}-Vpn-Gateway' gatewayType: 'Vpn' @@ -250,10 +355,10 @@ param parVpnGatewayConfig object = { vpnClientConfiguration: {} } -@sys.description('''Configuration for ExpressRoute virtual network gateway to be deployed. If a ExpressRoute virtual network gateway is not desired an empty object should be used as the input parameter in the parameter file, i.e. -"parExpressRouteGatewayConfig": { - "value": {} -}''') +@sys.description('Switch to enable/disable ExpressRoute virtual network gateway deployment.') +param parExpressRouteGatewayEnabled bool = true + +@sys.description('Configuration for ExpressRoute virtual network gateway to be deployed.') param parExpressRouteGatewayConfig object = { name: '${parCompanyPrefix}-ExpressRoute-Gateway' gatewayType: 'ExpressRoute' @@ -272,6 +377,17 @@ param parExpressRouteGatewayConfig object = { } } +@sys.description('''Resource Lock Configuration for ExpressRoute Virtual Network Gateway. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parVirtualNetworkGatewayLock lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep Hub Networking Module.' +} + @sys.description('Tags you would like to be applied to all resources in this module.') param parTags object = {} @@ -315,9 +431,9 @@ var varSubnetProperties = [for subnet in varSubnetMap: { } }] -var varVpnGwConfig = ((!empty(parVpnGatewayConfig)) ? parVpnGatewayConfig : json('{"name": "noconfigVpn"}')) +var varVpnGwConfig = ((parVpnGatewayEnabled) && (!empty(parVpnGatewayConfig)) ? parVpnGatewayConfig : json('{"name": "noconfigVpn"}')) -var varErGwConfig = ((!empty(parExpressRouteGatewayConfig)) ? parExpressRouteGatewayConfig : json('{"name": "noconfigEr"}')) +var varErGwConfig = ((parExpressRouteGatewayEnabled) && !empty(parExpressRouteGatewayConfig) ? parExpressRouteGatewayConfig : json('{"name": "noconfigEr"}')) var varGwConfig = [ varVpnGwConfig @@ -338,6 +454,16 @@ resource resDdosProtectionPlan 'Microsoft.Network/ddosProtectionPlans@2023-02-01 tags: parTags } +// Create resource lock if parDdosEnabled is true and parGlobalResourceLock.kind != 'None' or if parDdosLock.kind != 'None' +resource resDDoSProtectionPlanLock 'Microsoft.Authorization/locks@2020-05-01' = if (parDdosEnabled && (parDdosLock.kind != 'None' || parGlobalResourceLock.kind != 'None')) { + scope: resDdosProtectionPlan + name: parDdosLock.?name ?? '${resDdosProtectionPlan.name}-lock' + properties: { + level: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.kind : parDdosLock.kind + notes: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.?notes : parDdosLock.?notes + } +} + resource resHubVnet 'Microsoft.Network/virtualNetworks@2023-02-01' = { dependsOn: [ resBastionNsg @@ -362,6 +488,16 @@ resource resHubVnet 'Microsoft.Network/virtualNetworks@2023-02-01' = { } } +// Create a virtual network resource lock if parGlobalResourceLock.kind != 'None' or if parVirtualNetworkLock.kind != 'None' +resource resVirtualNetworkLock 'Microsoft.Authorization/locks@2020-05-01' = if (parVirtualNetworkLock.kind != 'None' || parGlobalResourceLock.kind != 'None') { + scope: resHubVnet + name: parVirtualNetworkLock.?name ?? '${resHubVnet.name}-lock' + properties: { + level: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.kind : parVirtualNetworkLock.kind + notes: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.?notes : parVirtualNetworkLock.?notes + } +} + module modBastionPublicIp '../publicIp/publicIp.bicep' = if (parAzBastionEnabled) { name: 'deploy-Bastion-Public-IP' params: { @@ -374,12 +510,13 @@ module modBastionPublicIp '../publicIp/publicIp.bicep' = if (parAzBastionEnabled publicIpAddressVersion: 'IPv4' publicIpAllocationMethod: 'Static' } + parResourceLockConfig: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock : parBastionLock parTags: parTags parTelemetryOptOut: parTelemetryOptOut } } -resource resBastionSubnetRef 'Microsoft.Network/virtualNetworks/subnets@2023-02-01' existing = { +resource resBastionSubnetRef 'Microsoft.Network/virtualNetworks/subnets@2023-02-01' existing = if (parAzBastionEnabled) { parent: resHubVnet name: 'AzureBastionSubnet' } @@ -533,6 +670,16 @@ resource resBastionNsg 'Microsoft.Network/networkSecurityGroups@2023-02-01' = if } } +// Create bastion nsg resource lock if parAzBastionEnbled is true and parGlobalResourceLock.kind != 'None' or if parBastionLock.kind != 'None' +resource resBastionNsgLock 'Microsoft.Authorization/locks@2020-05-01' = if (parAzBastionEnabled && (parBastionLock.kind != 'None' || parGlobalResourceLock.kind != 'None')) { + scope: resBastionNsg + name: parBastionLock.?name ?? '${resBastionNsg.name}-lock' + properties: { + level: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.kind : parBastionLock.kind + notes: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.?notes : parBastionLock.?notes + } +} + // AzureBastionSubnet is required to deploy Bastion service. This subnet must exist in the parsubnets array if you enable Bastion Service. // There is a minimum subnet requirement of /27 prefix. // If you are deploying standard this needs to be larger. https://docs.microsoft.com/en-us/azure/bastion/configuration-settings#subnet @@ -562,6 +709,16 @@ resource resBastion 'Microsoft.Network/bastionHosts@2023-02-01' = if (parAzBasti } } +// Create Bastion resource lock if parAzBastionEnabled is true and parGlobalResourceLock.kind != 'None' or if parBastionLock.kind != 'None' +resource resBastionLock 'Microsoft.Authorization/locks@2020-05-01' = if (parAzBastionEnabled && (parBastionLock.kind != 'None' || parGlobalResourceLock.kind != 'None')) { + scope: resBastion + name: parBastionLock.?name ?? '${resBastion.name}-lock' + properties: { + level: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.kind : parBastionLock.kind + notes: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.?notes : parBastionLock.?notes + } +} + resource resGatewaySubnetRef 'Microsoft.Network/virtualNetworks/subnets@2023-02-01' existing = { parent: resHubVnet name: 'GatewaySubnet' @@ -580,6 +737,7 @@ module modGatewayPublicIp '../publicIp/publicIp.bicep' = [for (gateway, i) in va parPublicIpSku: { name: parPublicIpSku } + parResourceLockConfig: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock : parVirtualNetworkGatewayLock parTags: parTags parTelemetryOptOut: parTelemetryOptOut } @@ -631,6 +789,16 @@ resource resGateway 'Microsoft.Network/virtualNetworkGateways@2023-02-01' = [for } }] +// Create a Virtual Network Gateway resource lock if gateway.name is not equal to noconfigVpn or noconfigEr and parGlobalResourceLock.kind != 'None' or if parVirtualNetworkGatewayLock.kind != 'None' +resource resVirtualNetworkGatewayLock 'Microsoft.Authorization/locks@2020-05-01' = [for (gateway, i) in varGwConfig: if ((gateway.name != 'noconfigVpn') && (gateway.name != 'noconfigEr') && (parVirtualNetworkGatewayLock.kind != 'None' || parGlobalResourceLock.kind != 'None')) { + scope: resGateway[i] + name: parVirtualNetworkGatewayLock.?name ?? '${resGateway[i].name}-lock' + properties: { + level: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.kind : parVirtualNetworkGatewayLock.kind + notes: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.?notes : parVirtualNetworkGatewayLock.?notes + } +}] + resource resAzureFirewallSubnetRef 'Microsoft.Network/virtualNetworks/subnets@2023-02-01' existing = { parent: resHubVnet name: 'AzureFirewallSubnet' @@ -654,6 +822,7 @@ module modAzureFirewallPublicIp '../publicIp/publicIp.bicep' = if (parAzFirewall parPublicIpSku: { name: parPublicIpSku } + parResourceLockConfig: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock : parAzureFirewallLock parTags: parTags parTelemetryOptOut: parTelemetryOptOut } @@ -672,6 +841,7 @@ module modAzureFirewallMgmtPublicIp '../publicIp/publicIp.bicep' = if (parAzFire parPublicIpSku: { name: 'Standard' } + parResourceLockConfig: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock : parAzureFirewallLock parTags: parTags parTelemetryOptOut: parTelemetryOptOut } @@ -698,6 +868,16 @@ resource resFirewallPolicies 'Microsoft.Network/firewallPolicies@2023-02-01' = i } } +// Create Azure Firewall Policy resource lock if parAzFirewallEnabled is true and parGlobalResourceLock.kind != 'None' or if parAzureFirewallLock.kind != 'None' +resource resFirewallPoliciesLock 'Microsoft.Authorization/locks@2020-05-01' = if (parAzFirewallEnabled && (parAzureFirewallLock.kind != 'None' || parGlobalResourceLock.kind != 'None')) { + scope: resFirewallPolicies + name: parAzureFirewallLock.?name ?? '${resFirewallPolicies.name}-lock' + properties: { + level: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.kind : parAzureFirewallLock.kind + notes: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.?notes : parAzureFirewallLock.?notes + } +} + // AzureFirewallSubnet is required to deploy Azure Firewall . This subnet must exist in the parsubnets array if you deploy. // There is a minimum subnet requirement of /26 prefix. resource resAzureFirewall 'Microsoft.Network/azureFirewalls@2023-02-01' = if (parAzFirewallEnabled) { @@ -764,6 +944,16 @@ resource resAzureFirewall 'Microsoft.Network/azureFirewalls@2023-02-01' = if (pa } } +// Create Azure Firewall resource lock if parAzFirewallEnabled is true and parGlobalResourceLock.kind != 'None' or if parAzureFirewallLock.kind != 'None' +resource resAzureFirewallLock 'Microsoft.Authorization/locks@2020-05-01' = if (parAzFirewallEnabled && (parAzureFirewallLock.kind != 'None' || parGlobalResourceLock.kind != 'None')) { + scope: resAzureFirewall + name: parAzureFirewallLock.?name ?? '${resAzureFirewall.name}-lock' + properties: { + level: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.kind : parAzureFirewallLock.kind + notes: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.?notes : parAzureFirewallLock.?notes + } +} + //If Azure Firewall is enabled we will deploy a RouteTable to redirect Traffic to the Firewall. resource resHubRouteTable 'Microsoft.Network/routeTables@2023-02-01' = if (parAzFirewallEnabled) { name: parHubRouteTableName @@ -784,6 +974,16 @@ resource resHubRouteTable 'Microsoft.Network/routeTables@2023-02-01' = if (parAz } } +// Create a Route Table if parAzFirewallEnabled is true and parGlobalResourceLock.kind != 'None' or if parHubRouteTableLock.kind != 'None' +resource resHubRouteTableLock 'Microsoft.Authorization/locks@2020-05-01' = if (parAzFirewallEnabled && (parHubRouteTableLock.kind != 'None' || parGlobalResourceLock.kind != 'None')) { + scope: resHubRouteTable + name: parHubRouteTableLock.?name ?? '${resHubRouteTable.name}-lock' + properties: { + level: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.kind : parHubRouteTableLock.kind + notes: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.?notes : parHubRouteTableLock.?notes + } +} + module modPrivateDnsZones '../privateDnsZones/privateDnsZones.bicep' = if (parPrivateDnsZonesEnabled) { name: 'deploy-Private-DNS-Zones' scope: resourceGroup(parPrivateDnsZonesResourceGroup) @@ -794,6 +994,7 @@ module modPrivateDnsZones '../privateDnsZones/privateDnsZones.bicep' = if (parPr parVirtualNetworkIdToLinkFailover: parVirtualNetworkIdToLinkFailover parPrivateDnsZones: parPrivateDnsZones parPrivateDnsZoneAutoMergeAzureBackupZone: parPrivateDnsZoneAutoMergeAzureBackupZone + parResourceLockConfig: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock : parPrivateDNSZonesLock parTelemetryOptOut: parTelemetryOptOut } } diff --git a/dependencies/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.all.json b/dependencies/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.all.json index 2bad685..3776166 100644 --- a/dependencies/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.all.json +++ b/dependencies/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.all.json @@ -189,6 +189,9 @@ "parPrivateDnsZoneAutoMergeAzureBackupZone": { "value": true }, + "parVpnGatewayEnabled": { + "value": true + }, "parVpnGatewayConfig": { "value": { "name": "alz-Vpn-Gateway", @@ -209,6 +212,9 @@ "vpnClientConfiguration": {} } }, + "parExpressRouteGatewayEnabled": { + "value": true + }, "parExpressRouteGatewayConfig": { "value": { "name": "alz-ExpressRoute-Gateway", @@ -241,6 +247,54 @@ "22", "3389" ] + }, + "parGlobalResourceLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, + "parVirtualNetworkLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, + "parBastionLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, + "parDdosLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, + "parAzureFirewallLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, + "parHubRouteTableLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, + "parPrivateDNSZonesLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, + "parVirtualNetworkGatewayLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } } } } diff --git a/dependencies/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.az.all.json b/dependencies/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.az.all.json new file mode 100644 index 0000000..b16730b --- /dev/null +++ b/dependencies/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.az.all.json @@ -0,0 +1,312 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "parLocation": { + "value": "eastus" + }, + "parCompanyPrefix": { + "value": "alz" + }, + "parHubNetworkName": { + "value": "alz-hub-eastus" + }, + "parHubNetworkAddressPrefix": { + "value": "10.20.0.0/16" + }, + "parSubnets": { + "value": [ + { + "name": "AzureBastionSubnet", + "ipAddressRange": "10.20.0.0/24", + "networkSecurityGroupId": "", + "routeTableId": "" + }, + { + "name": "GatewaySubnet", + "ipAddressRange": "10.20.254.0/24", + "networkSecurityGroupId": "", + "routeTableId": "" + }, + { + "name": "AzureFirewallSubnet", + "ipAddressRange": "10.20.255.0/24", + "networkSecurityGroupId": "", + "routeTableId": "" + }, + { + "name": "AzureFirewallManagementSubnet", + "ipAddressRange": "10.20.253.0/24", + "networkSecurityGroupId": "", + "routeTableId": "" + } + ] + }, + "parDnsServerIps": { + "value": [] + }, + "parPublicIpSku": { + "value": "Standard" + }, + "parPublicIpPrefix": { + "value": "" + }, + "parPublicIpSuffix": { + "value": "-PublicIP" + }, + "parAzBastionEnabled": { + "value": true + }, + "parAzBastionName": { + "value": "alz-bastion" + }, + "parAzBastionSku": { + "value": "Standard" + }, + "parAzBastionTunneling": { + "value": false + }, + "parAzBastionNsgName": { + "value": "nsg-AzureBastionSubnet" + }, + "parDdosEnabled": { + "value": true + }, + "parDdosPlanName": { + "value": "alz-ddos-plan" + }, + "parAzFirewallEnabled": { + "value": true + }, + "parAzFirewallName": { + "value": "alz-azfw-eastus" + }, + "parAzFirewallPoliciesName": { + "value": "alz-azfwpolicy-eastus" + }, + "parAzFirewallTier": { + "value": "Standard" + }, + "parAzFirewallIntelMode": { + "value": "Alert" + }, + "parAzFirewallAvailabilityZones": { + "value": [ + "1", + "2", + "3" + ] + }, + "parAzErGatewayAvailabilityZones": { + "value": [ + "1", + "2", + "3" + ] + }, + "parAzVpnGatewayAvailabilityZones": { + "value": [ + "1", + "2", + "3" + ] + }, + "parAzFirewallDnsProxyEnabled": { + "value": true + }, + "parAzFirewallDnsServers": { + "value": [] + }, + "parHubRouteTableName": { + "value": "alz-hub-routetable" + }, + "parDisableBgpRoutePropagation": { + "value": false + }, + "parPrivateDnsZonesEnabled": { + "value": true + }, + "parPrivateDnsZones": { + "value": [ + "privatelink.xxxxxx.azmk8s.io", // Replace xxxxxx with target region (i.e. eastus) + "privatelink.xxxxxx.batch.azure.com", // Replace xxxxxx with target region (i.e. eastus) + "privatelink.xxxxxx.kusto.windows.net", // Replace xxxxxx with target region (i.e. eastus) + "privatelink.xxxxxx.backup.windowsazure.com", // Replace xxxxxx with target region geo code (i.e. for eastus, the geo code is eus) + "privatelink.adf.azure.com", + "privatelink.afs.azure.net", + "privatelink.agentsvc.azure-automation.net", + "privatelink.analysis.windows.net", + "privatelink.api.azureml.ms", + "privatelink.azconfig.io", + "privatelink.azure-api.net", + "privatelink.azure-automation.net", + "privatelink.azurecr.io", + "privatelink.azure-devices.net", + "privatelink.azure-devices-provisioning.net", + "privatelink.azuredatabricks.net", + "privatelink.azurehdinsight.net", + "privatelink.azurehealthcareapis.com", + "privatelink.azurestaticapps.net", + "privatelink.azuresynapse.net", + "privatelink.azurewebsites.net", + "privatelink.batch.azure.com", + "privatelink.blob.core.windows.net", + "privatelink.cassandra.cosmos.azure.com", + "privatelink.cognitiveservices.azure.com", + "privatelink.database.windows.net", + "privatelink.datafactory.azure.net", + "privatelink.dev.azuresynapse.net", + "privatelink.dfs.core.windows.net", + "privatelink.dicom.azurehealthcareapis.com", + "privatelink.digitaltwins.azure.net", + "privatelink.directline.botframework.com", + "privatelink.documents.azure.com", + "privatelink.eventgrid.azure.net", + "privatelink.file.core.windows.net", + "privatelink.gremlin.cosmos.azure.com", + "privatelink.guestconfiguration.azure.com", + "privatelink.his.arc.azure.com", + "privatelink.kubernetesconfiguration.azure.com", + "privatelink.managedhsm.azure.net", + "privatelink.mariadb.database.azure.com", + "privatelink.media.azure.net", + "privatelink.mongo.cosmos.azure.com", + "privatelink.monitor.azure.com", + "privatelink.mysql.database.azure.com", + "privatelink.notebooks.azure.net", + "privatelink.ods.opinsights.azure.com", + "privatelink.oms.opinsights.azure.com", + "privatelink.pbidedicated.windows.net", + "privatelink.postgres.database.azure.com", + "privatelink.prod.migration.windowsazure.com", + "privatelink.purview.azure.com", + "privatelink.purviewstudio.azure.com", + "privatelink.queue.core.windows.net", + "privatelink.redis.cache.windows.net", + "privatelink.redisenterprise.cache.azure.net", + "privatelink.search.windows.net", + "privatelink.service.signalr.net", + "privatelink.servicebus.windows.net", + "privatelink.siterecovery.windowsazure.com", + "privatelink.sql.azuresynapse.net", + "privatelink.table.core.windows.net", + "privatelink.table.cosmos.azure.com", + "privatelink.tip1.powerquery.microsoft.com", + "privatelink.token.botframework.com", + "privatelink.vaultcore.azure.net", + "privatelink.web.core.windows.net", + "privatelink.webpubsub.azure.com" + ] + }, + "parPrivateDnsZoneAutoMergeAzureBackupZone": { + "value": true + }, + "parVpnGatewayEnabled": { + "value": true + }, + "parVpnGatewayConfig": { + "value": { + "name": "alz-Vpn-Gateway", + "gatewayType": "Vpn", + "sku": "VpnGw1AZ", + "vpnType": "RouteBased", + "generation": "Generation1", + "enableBgp": false, + "activeActive": false, + "enableBgpRouteTranslationForNat": false, + "enableDnsForwarding": false, + "bgpPeeringAddress": "", + "bgpsettings": { + "asn": "65515", + "bgpPeeringAddress": "", + "peerWeight": "5" + }, + "vpnClientConfiguration": {} + } + }, + "parExpressRouteGatewayEnabled": { + "value": true + }, + "parExpressRouteGatewayConfig": { + "value": { + "name": "alz-ExpressRoute-Gateway", + "gatewayType": "ExpressRoute", + "sku": "ErGw1Az", + "vpnType": "RouteBased", + "generation": "None", + "enableBgp": false, + "activeActive": false, + "enableBgpRouteTranslationForNat": false, + "enableDnsForwarding": false, + "bgpPeeringAddress": "", + "bgpsettings": { + "asn": "65515", + "bgpPeeringAddress": "", + "peerWeight": "5" + } + } + }, + "parTags": { + "value": { + "Environment": "Live" + } + }, + "parTelemetryOptOut": { + "value": false + }, + "parBastionOutboundSshRdpPorts": { + "value": [ + "22", + "3389" + ] + }, + "parGlobalResourceLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, + "parVirtualNetworkLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, + "parBastionLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, + "parDdosLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, + "parAzureFirewallLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, + "parHubRouteTableLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, + "parPrivateDNSZonesLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, + "parVirtualNetworkGatewayLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + } + } +} diff --git a/dependencies/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.min.json b/dependencies/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.min.json index fcf5450..c59fbe5 100644 --- a/dependencies/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.min.json +++ b/dependencies/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.min.json @@ -75,6 +75,9 @@ "parPrivateDnsZonesEnabled": { "value": true }, + "parVpnGatewayEnabled": { + "value": true + }, "parVpnGatewayConfig": { "value": { "name": "alz-Vpn-Gateway", @@ -94,6 +97,9 @@ } } }, + "parExpressRouteGatewayEnabled": { + "value": true + }, "parExpressRouteGatewayConfig": { "value": { "name": "alz-ExpressRoute-Gateway", diff --git a/dependencies/infra-as-code/bicep/modules/hubNetworking/parameters/mc-hubNetworking.parameters.all.json b/dependencies/infra-as-code/bicep/modules/hubNetworking/parameters/mc-hubNetworking.parameters.all.json index 0d0bd59..80b17f4 100644 --- a/dependencies/infra-as-code/bicep/modules/hubNetworking/parameters/mc-hubNetworking.parameters.all.json +++ b/dependencies/infra-as-code/bicep/modules/hubNetworking/parameters/mc-hubNetworking.parameters.all.json @@ -150,6 +150,9 @@ "parPrivateDnsZoneAutoMergeAzureBackupZone": { "value": true }, + "parVpnGatewayEnabled": { + "value": true + }, "parVpnGatewayConfig": { "value": { "name": "alz-Vpn-Gateway", @@ -170,6 +173,9 @@ "vpnClientConfiguration": {} } }, + "parExpressRouteGatewayEnabled": { + "value": true + }, "parExpressRouteGatewayConfig": { "value": { "name": "alz-ExpressRoute-Gateway", @@ -202,6 +208,54 @@ "22", "3389" ] + }, + "parGlobalResourceLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, + "parVirtualNetworkLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, + "parBastionLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, + "parDdosLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, + "parAzureFirewallLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, + "parHubRouteTableLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, + "parPrivateDNSZonesLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, + "parVirtualNetworkGatewayLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } } } } diff --git a/dependencies/infra-as-code/bicep/modules/hubNetworking/parameters/mc-hubNetworking.parameters.min.json b/dependencies/infra-as-code/bicep/modules/hubNetworking/parameters/mc-hubNetworking.parameters.min.json index fe76ea4..463ae0d 100644 --- a/dependencies/infra-as-code/bicep/modules/hubNetworking/parameters/mc-hubNetworking.parameters.min.json +++ b/dependencies/infra-as-code/bicep/modules/hubNetworking/parameters/mc-hubNetworking.parameters.min.json @@ -111,6 +111,9 @@ "privatelink.redis.cache.chinacloudapi.cn" ] }, + "parVpnGatewayEnabled": { + "value": true + }, "parVpnGatewayConfig": { "value": { "name": "alz-Vpn-Gateway", @@ -130,6 +133,9 @@ } } }, + "parExpressRouteGatewayEnabled": { + "value": true + }, "parExpressRouteGatewayConfig": { "value": { "name": "alz-ExpressRoute-Gateway", diff --git a/dependencies/infra-as-code/bicep/modules/logging/generateddocs/logging.bicep.md b/dependencies/infra-as-code/bicep/modules/logging/generateddocs/logging.bicep.md index 3f6feef..abe4804 100644 --- a/dependencies/infra-as-code/bicep/modules/logging/generateddocs/logging.bicep.md +++ b/dependencies/infra-as-code/bicep/modules/logging/generateddocs/logging.bicep.md @@ -6,22 +6,41 @@ ALZ Bicep Module used to set up Logging Parameter name | Required | Description -------------- | -------- | ----------- +parGlobalResourceLock | No | Global Resource Lock Configuration used for all resources deployed in this module. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. parLogAnalyticsWorkspaceName | No | Log Analytics Workspace name. parLogAnalyticsWorkspaceLocation | No | Log Analytics region name - Ensure the regions selected is a supported mapping as per: https://docs.microsoft.com/azure/automation/how-to/region-mappings. parLogAnalyticsWorkspaceSkuName | No | Log Analytics Workspace sku name. parLogAnalyticsWorkspaceCapacityReservationLevel | No | Log Analytics Workspace Capacity Reservation Level. Only used if parLogAnalyticsWorkspaceSkuName is set to CapacityReservation. parLogAnalyticsWorkspaceLogRetentionInDays | No | Number of days of log retention for Log Analytics Workspace. +parLogAnalyticsWorkspaceLock | No | Resource Lock Configuration for Log Analytics Workspace. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. parLogAnalyticsWorkspaceSolutions | No | Solutions that will be added to the Log Analytics Workspace. +parLogAnalyticsWorkspaceSolutionsLock | No | Resource Lock Configuration for Log Analytics Workspace Solutions. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. parLogAnalyticsWorkspaceLinkAutomationAccount | No | Log Analytics Workspace should be linked with the automation account. parAutomationAccountName | No | Automation account name. parAutomationAccountLocation | No | Automation Account region name. - Ensure the regions selected is a supported mapping as per: https://docs.microsoft.com/azure/automation/how-to/region-mappings. parAutomationAccountUseManagedIdentity | No | Automation Account - use managed identity. +parAutomationAccountPublicNetworkAccess | No | Automation Account - Public network access. +parAutomationAccountLock | No | Resource Lock Configuration for Automation Account. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. parTags | No | Tags you would like to be applied to all resources in this module. parAutomationAccountTags | No | Tags you would like to be applied to Automation Account. parLogAnalyticsWorkspaceTags | No | Tags you would like to be applied to Log Analytics Workspace. parUseSentinelClassicPricingTiers | No | Set Parameter to true to use Sentinel Classic Pricing Tiers, following changes introduced in July 2023 as documented here: https://learn.microsoft.com/azure/sentinel/enroll-simplified-pricing-tier. +parLogAnalyticsLinkedServiceAutomationAccountName | No | Log Analytics LinkedService name for Automation Account. parTelemetryOptOut | No | Set Parameter to true to Opt-out of deployment telemetry +### parGlobalResourceLock + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Global Resource Lock Configuration used for all resources deployed in this module. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep Logging Module.}` + ### parLogAnalyticsWorkspaceName ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) @@ -66,6 +85,19 @@ Number of days of log retention for Log Analytics Workspace. - Default value: `365` +### parLogAnalyticsWorkspaceLock + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Resource Lock Configuration for Log Analytics Workspace. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep Logging Module.}` + ### parLogAnalyticsWorkspaceSolutions ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) @@ -76,6 +108,19 @@ Solutions that will be added to the Log Analytics Workspace. - Allowed values: `AgentHealthAssessment`, `AntiMalware`, `ChangeTracking`, `Security`, `SecurityInsights`, `ServiceMap`, `SQLAdvancedThreatProtection`, `SQLVulnerabilityAssessment`, `SQLAssessment`, `Updates`, `VMInsights` +### parLogAnalyticsWorkspaceSolutionsLock + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Resource Lock Configuration for Log Analytics Workspace Solutions. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep Logging Module.}` + ### parLogAnalyticsWorkspaceLinkAutomationAccount ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) @@ -108,6 +153,27 @@ Automation Account - use managed identity. - Default value: `True` +### parAutomationAccountPublicNetworkAccess + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Automation Account - Public network access. + +- Default value: `True` + +### parAutomationAccountLock + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Resource Lock Configuration for Automation Account. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep Logging Module.}` + ### parTags ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) @@ -138,6 +204,14 @@ Set Parameter to true to use Sentinel Classic Pricing Tiers, following changes i - Default value: `False` +### parLogAnalyticsLinkedServiceAutomationAccountName + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Log Analytics LinkedService name for Automation Account. + +- Default value: `Automation` + ### parTelemetryOptOut ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) @@ -169,6 +243,12 @@ outAutomationAccountId | string | "template": "infra-as-code/bicep/modules/logging/logging.json" }, "parameters": { + "parGlobalResourceLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Logging Module." + } + }, "parLogAnalyticsWorkspaceName": { "value": "alz-log-analytics" }, @@ -184,6 +264,12 @@ outAutomationAccountId | string | "parLogAnalyticsWorkspaceLogRetentionInDays": { "value": 365 }, + "parLogAnalyticsWorkspaceLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Logging Module." + } + }, "parLogAnalyticsWorkspaceSolutions": { "value": [ "AgentHealthAssessment", @@ -198,6 +284,12 @@ outAutomationAccountId | string | "VMInsights" ] }, + "parLogAnalyticsWorkspaceSolutionsLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Logging Module." + } + }, "parLogAnalyticsWorkspaceLinkAutomationAccount": { "value": true }, @@ -210,6 +302,15 @@ outAutomationAccountId | string | "parAutomationAccountUseManagedIdentity": { "value": true }, + "parAutomationAccountPublicNetworkAccess": { + "value": true + }, + "parAutomationAccountLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Logging Module." + } + }, "parTags": { "value": {} }, @@ -222,6 +323,9 @@ outAutomationAccountId | string | "parUseSentinelClassicPricingTiers": { "value": false }, + "parLogAnalyticsLinkedServiceAutomationAccountName": { + "value": "Automation" + }, "parTelemetryOptOut": { "value": false } diff --git a/dependencies/infra-as-code/bicep/modules/logging/logging.bicep b/dependencies/infra-as-code/bicep/modules/logging/logging.bicep index 9171621..9dcc8a5 100644 --- a/dependencies/infra-as-code/bicep/modules/logging/logging.bicep +++ b/dependencies/infra-as-code/bicep/modules/logging/logging.bicep @@ -1,6 +1,28 @@ metadata name = 'ALZ Bicep - Logging Module' metadata description = 'ALZ Bicep Module used to set up Logging' +type lockType = { + @description('Optional. Specify the name of lock.') + name: string? + + @description('Optional. The lock settings of the service.') + kind: ('CanNotDelete' | 'ReadOnly' | 'None') + + @description('Optional. Notes about this lock.') + notes: string? +} + +@sys.description('''Global Resource Lock Configuration used for all resources deployed in this module. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parGlobalResourceLock lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep Logging Module.' +} + @sys.description('Log Analytics Workspace name.') param parLogAnalyticsWorkspaceName string = 'alz-log-analytics' @@ -38,6 +60,17 @@ param parLogAnalyticsWorkspaceCapacityReservationLevel int = 100 @sys.description('Number of days of log retention for Log Analytics Workspace.') param parLogAnalyticsWorkspaceLogRetentionInDays int = 365 +@sys.description('''Resource Lock Configuration for Log Analytics Workspace. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parLogAnalyticsWorkspaceLock lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep Logging Module.' +} + @allowed([ 'AgentHealthAssessment' 'AntiMalware' @@ -65,6 +98,17 @@ param parLogAnalyticsWorkspaceSolutions array = [ 'VMInsights' ] +@sys.description('''Resource Lock Configuration for Log Analytics Workspace Solutions. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parLogAnalyticsWorkspaceSolutionsLock lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep Logging Module.' +} + @sys.description('Log Analytics Workspace should be linked with the automation account.') param parLogAnalyticsWorkspaceLinkAutomationAccount bool = true @@ -77,6 +121,20 @@ param parAutomationAccountLocation string = resourceGroup().location @sys.description('Automation Account - use managed identity.') param parAutomationAccountUseManagedIdentity bool = true +@sys.description('Automation Account - Public network access.') +param parAutomationAccountPublicNetworkAccess bool = true + +@sys.description('''Resource Lock Configuration for Automation Account. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parAutomationAccountLock lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep Logging Module.' +} + @sys.description('Tags you would like to be applied to all resources in this module.') param parTags object = {} @@ -89,6 +147,9 @@ param parLogAnalyticsWorkspaceTags object = parTags @sys.description('Set Parameter to true to use Sentinel Classic Pricing Tiers, following changes introduced in July 2023 as documented here: https://learn.microsoft.com/azure/sentinel/enroll-simplified-pricing-tier.') param parUseSentinelClassicPricingTiers bool = false +@sys.description('Log Analytics LinkedService name for Automation Account.') +param parLogAnalyticsLinkedServiceAutomationAccountName string = 'Automation' + @sys.description('Set Parameter to true to Opt-out of deployment telemetry') param parTelemetryOptOut bool = false @@ -103,12 +164,23 @@ resource resAutomationAccount 'Microsoft.Automation/automationAccounts@2022-08-0 type: 'SystemAssigned' } : null properties: { - sku: { - name: 'Basic' - } encryption: { keySource: 'Microsoft.Automation' } + publicNetworkAccess: parAutomationAccountPublicNetworkAccess + sku: { + name: 'Basic' + } + } +} + +// Create a resource lock for the automation account if parGlobalResourceLock.kind != 'None' or if parAutomationAccountLock.kind != 'None' +resource resAutomationAccountLock 'Microsoft.Authorization/locks@2020-05-01' = if (parAutomationAccountLock.kind != 'None' || parGlobalResourceLock.kind != 'None') { + scope: resAutomationAccount + name: parAutomationAccountLock.?name ?? '${resAutomationAccount.name}-lock' + properties: { + level: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.kind : parAutomationAccountLock.kind + notes: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.?notes : parAutomationAccountLock.?notes } } @@ -125,6 +197,16 @@ resource resLogAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022 } } +// Create a resource lock for the log analytics workspace if parGlobalResourceLock.kind != 'None' or if parLogAnalyticsWorkspaceLock.kind != 'None' +resource resLogAnalyticsWorkspaceLock 'Microsoft.Authorization/locks@2020-05-01' = if (parLogAnalyticsWorkspaceLock.kind != 'None' || parGlobalResourceLock.kind != 'None') { + scope: resLogAnalyticsWorkspace + name: parLogAnalyticsWorkspaceLock.?name ?? '${resLogAnalyticsWorkspace.name}-lock' + properties: { + level: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.kind : parLogAnalyticsWorkspaceLock.kind + notes: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.?notes : parLogAnalyticsWorkspaceLock.?notes + } +} + resource resLogAnalyticsWorkspaceSolutions 'Microsoft.OperationsManagement/solutions@2015-11-01-preview' = [for solution in parLogAnalyticsWorkspaceSolutions: { name: '${solution}(${resLogAnalyticsWorkspace.name})' location: parLogAnalyticsWorkspaceLocation @@ -145,9 +227,19 @@ resource resLogAnalyticsWorkspaceSolutions 'Microsoft.OperationsManagement/solut } }] +// Create a resource lock for each log analytics workspace solutions in parLogAnalyticsWorkspaceSolutions if parGlobalResourceLock.kind != 'None' or if parLogAnalyticsWorkspaceSolutionsLock.kind != 'None' +resource resLogAnalyticsWorkspaceSolutionsLock 'Microsoft.Authorization/locks@2020-05-01' = [for (solution, index) in parLogAnalyticsWorkspaceSolutions: if (parLogAnalyticsWorkspaceSolutionsLock.kind != 'None' || parGlobalResourceLock.kind != 'None') { + scope: resLogAnalyticsWorkspaceSolutions[index] + name: parLogAnalyticsWorkspaceSolutionsLock.?name ?? '${resLogAnalyticsWorkspaceSolutions[index].name}-lock' + properties: { + level: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.kind : parLogAnalyticsWorkspaceSolutionsLock.kind + notes: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.?notes : parLogAnalyticsWorkspaceSolutionsLock.?notes + } +}] + resource resLogAnalyticsLinkedServiceForAutomationAccount 'Microsoft.OperationalInsights/workspaces/linkedServices@2020-08-01' = if (parLogAnalyticsWorkspaceLinkAutomationAccount) { parent: resLogAnalyticsWorkspace - name: 'Automation' + name: parLogAnalyticsLinkedServiceAutomationAccountName properties: { resourceId: resAutomationAccount.id } diff --git a/dependencies/infra-as-code/bicep/modules/logging/parameters/logging.parameters.all.json b/dependencies/infra-as-code/bicep/modules/logging/parameters/logging.parameters.all.json index 51abbf1..73fe7eb 100644 --- a/dependencies/infra-as-code/bicep/modules/logging/parameters/logging.parameters.all.json +++ b/dependencies/infra-as-code/bicep/modules/logging/parameters/logging.parameters.all.json @@ -43,6 +43,9 @@ "parAutomationAccountUseManagedIdentity": { "value": true }, + "parAutomationAccountPublicNetworkAccess": { + "value": true + }, "parTags": { "value": { "Environment": "Live" @@ -51,8 +54,35 @@ "parUseSentinelClassicPricingTiers": { "value": false }, + "parLogAnalyticsLinkedServiceAutomationAccountName": { + "value": "Automation" + }, "parTelemetryOptOut": { "value": false + }, + "parGlobalResourceLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Logging Module." + } + }, + "parAutomationAccountLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Logging Module." + } + }, + "parLogAnalyticsWorkspaceLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Logging Module." + } + }, + "parLogAnalyticsWorkspaceSolutionsLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Logging Module." + } } } } diff --git a/dependencies/infra-as-code/bicep/modules/logging/parameters/mc-logging.parameters.all.json b/dependencies/infra-as-code/bicep/modules/logging/parameters/mc-logging.parameters.all.json index 5881fbc..360454d 100644 --- a/dependencies/infra-as-code/bicep/modules/logging/parameters/mc-logging.parameters.all.json +++ b/dependencies/infra-as-code/bicep/modules/logging/parameters/mc-logging.parameters.all.json @@ -40,13 +40,43 @@ "parAutomationAccountUseManagedIdentity": { "value": true }, + "parAutomationAccountPublicNetworkAccess": { + "value": true + }, "parTags": { "value": { "Environment": "Live" } }, + "parLogAnalyticsLinkedServiceAutomationAccountName": { + "value": "Automation" + }, "parTelemetryOptOut": { "value": false + }, + "parGlobalResourceLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Logging Module." + } + }, + "parAutomationAccountLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Logging Module." + } + }, + "parLogAnalyticsWorkspaceLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Logging Module." + } + }, + "parLogAnalyticsWorkspaceSolutionsLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Logging Module." + } } } } diff --git a/dependencies/infra-as-code/bicep/modules/managementGroups/README.md b/dependencies/infra-as-code/bicep/modules/managementGroups/README.md index d94f100..0018b98 100644 --- a/dependencies/infra-as-code/bicep/modules/managementGroups/README.md +++ b/dependencies/infra-as-code/bicep/modules/managementGroups/README.md @@ -182,7 +182,7 @@ TEMPLATEFILE="infra-as-code/bicep/modules/managementGroups/managementGroupsScope PARAMETERS="@infra-as-code/bicep/modules/managementGroups/parameters/managementGroups.parameters.all.json" MGID="alz" -az deployment tenant create --name ${NAME:0:63} --location $LOCATION --template-file $TEMPLATEFILE --parameters $PARAMETERS --management-group-id $MGID +az deployment mg create --name ${NAME:0:63} --location $LOCATION --template-file $TEMPLATEFILE --parameters $PARAMETERS --management-group-id $MGID ``` OR ```bash @@ -195,7 +195,7 @@ TEMPLATEFILE="infra-as-code/bicep/modules/managementGroups/managementGroupsScope PARAMETERS="@infra-as-code/bicep/modules/managementGroups/parameters/managementGroups.parameters.all.json" MGID="alz" -az deployment tenant create --name ${NAME:0:63} --location $LOCATION --template-file $TEMPLATEFILE --parameters $PARAMETERS --management-group-id $MGID +az deployment mg create --name ${NAME:0:63} --location $LOCATION --template-file $TEMPLATEFILE --parameters $PARAMETERS --management-group-id $MGID ``` ### PowerShell - `managementGroups.bicep` diff --git a/dependencies/infra-as-code/bicep/modules/mgDiagSettings/generateddocs/mgDiagSettings.bicep.md b/dependencies/infra-as-code/bicep/modules/mgDiagSettings/generateddocs/mgDiagSettings.bicep.md index 4119720..4535aa0 100644 --- a/dependencies/infra-as-code/bicep/modules/mgDiagSettings/generateddocs/mgDiagSettings.bicep.md +++ b/dependencies/infra-as-code/bicep/modules/mgDiagSettings/generateddocs/mgDiagSettings.bicep.md @@ -7,6 +7,7 @@ Module used to set up Diagnostic Settings for Management Groups Parameter name | Required | Description -------------- | -------- | ----------- parLogAnalyticsWorkspaceResourceId | Yes | Log Analytics Workspace Resource ID. +parDiagnosticSettingsName | No | Diagnostic Settings Name. parTelemetryOptOut | No | Set Parameter to true to Opt-out of deployment telemetry ### parLogAnalyticsWorkspaceResourceId @@ -15,6 +16,14 @@ parTelemetryOptOut | No | Set Parameter to true to Opt-out of deployment t Log Analytics Workspace Resource ID. +### parDiagnosticSettingsName + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Diagnostic Settings Name. + +- Default value: `toLa` + ### parTelemetryOptOut ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) @@ -38,6 +47,9 @@ Set Parameter to true to Opt-out of deployment telemetry "parLogAnalyticsWorkspaceResourceId": { "value": "" }, + "parDiagnosticSettingsName": { + "value": "toLa" + }, "parTelemetryOptOut": { "value": false } diff --git a/dependencies/infra-as-code/bicep/modules/mgDiagSettings/mgDiagSettings.bicep b/dependencies/infra-as-code/bicep/modules/mgDiagSettings/mgDiagSettings.bicep index 0cf1e74..45114b5 100644 --- a/dependencies/infra-as-code/bicep/modules/mgDiagSettings/mgDiagSettings.bicep +++ b/dependencies/infra-as-code/bicep/modules/mgDiagSettings/mgDiagSettings.bicep @@ -6,6 +6,9 @@ metadata description = 'Module used to set up Diagnostic Settings for Management @sys.description('Log Analytics Workspace Resource ID.') param parLogAnalyticsWorkspaceResourceId string +@sys.description('Diagnostic Settings Name.') +param parDiagnosticSettingsName string = 'toLa' + @sys.description('Set Parameter to true to Opt-out of deployment telemetry') param parTelemetryOptOut bool = false @@ -13,7 +16,7 @@ param parTelemetryOptOut bool = false var varCuaid = '5d17f1c2-f17b-4426-9712-0cd2652c4435' resource mgDiagSet 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = { - name: 'toLa' + name: parDiagnosticSettingsName properties: { workspaceId: parLogAnalyticsWorkspaceResourceId logs: [ diff --git a/dependencies/infra-as-code/bicep/modules/mgDiagSettings/parameters/mgDiagSettings.parameters.all.json b/dependencies/infra-as-code/bicep/modules/mgDiagSettings/parameters/mgDiagSettings.parameters.all.json index e20f3a3..1ac7275 100644 --- a/dependencies/infra-as-code/bicep/modules/mgDiagSettings/parameters/mgDiagSettings.parameters.all.json +++ b/dependencies/infra-as-code/bicep/modules/mgDiagSettings/parameters/mgDiagSettings.parameters.all.json @@ -5,6 +5,9 @@ "parLogAnalyticsWorkspaceResourceId": { "value": "" }, + "parDiagnosticSettingsName": { + "value": "toLa" + }, "parTelemetryOptOut": { "value": false } diff --git a/dependencies/infra-as-code/bicep/modules/policy/assignments/alzDefaults/alzDefaultPolicyAssignments.bicep b/dependencies/infra-as-code/bicep/modules/policy/assignments/alzDefaults/alzDefaultPolicyAssignments.bicep index 1e445db..3b2929b 100644 --- a/dependencies/infra-as-code/bicep/modules/policy/assignments/alzDefaults/alzDefaultPolicyAssignments.bicep +++ b/dependencies/infra-as-code/bicep/modules/policy/assignments/alzDefaults/alzDefaultPolicyAssignments.bicep @@ -1,6 +1,31 @@ metadata name = 'ALZ Bicep - ALZ Default Policy Assignments' metadata description = 'This module will assign the ALZ Default Policy Assignments to the ALZ Management Group hierarchy' +type policyAssignmentSovereigntyGlobalOptionsType = { + @sys.description('Switch to enable/disable deployment of the Sovereignty Baseline - Global Policies Assignment to the intermediate root management group.') + parTopLevelSovereigntyGlobalPoliciesEnable: bool + + @sys.description('The list of locations that your organization can use to restrict deploying resources to. If left empty, only the deployment location will be allowed.') + parListOfAllowedLocations: string[] + + @sys.description('The effect type for the Sovereignty Baseline - Global Policies Assignment.') + parPolicyEffect: ('Audit' | 'Deny' | 'Disabled' | 'AuditIfNotExists') +} + +type policyAssignmentSovereigntyConfidentialOptionsType = { + @sys.description('The list of Azure resource types approved for usage, which is the set of resource types that have a SKU backed by Azure Confidential Computing or resource types that do not process customer data. Leave empty to allow all relevant resource types.') + parAllowedResourceTypes: string[] + + @sys.description('The list of locations that your organization can use to restrict deploying resources to. If left empty, only the deployment location will be allowed.') + parListOfAllowedLocations: string[] + + @sys.description('The list of VM SKUs approved approved for usage, which is the set of SKUs backed by Azure Confidential Computing. Leave empty to allow all relevant SKUs.') + parAllowedVirtualMachineSKUs: string[] + + @sys.description('The effect type for the Sovereignty Baseline - Confidential Policies Assignment.') + parPolicyEffect: ('Audit' | 'Deny' | 'Disabled' | 'AuditIfNotExists') +} + @sys.description('Prefix used for the management group hierarchy.') @minLength(2) @maxLength(10) @@ -10,6 +35,34 @@ param parTopLevelManagementGroupPrefix string = 'alz' @maxLength(10) param parTopLevelManagementGroupSuffix string = '' +@sys.description('''Object used to assign Sovereignty Baseline - Global Policies to the intermediate root management group.' + +- `parTopLevelSovereignGlobalPoliciesEnable` - Switch to enable/disable deployment of the Sovereignty Baseline - Global Policies Assignment to the intermediate root management group. +- `parListOfAllowedLocations` - The list of locations that your organization can use to restrict deploying resources to. If left empty, only the deployment location will be allowed. +- `parPolicyEffect` - The effect type for the Sovereignty Baseline - Global Policies Assignment. + +''') +param parTopLevelPolicyAssignmentSovereigntyGlobal policyAssignmentSovereigntyGlobalOptionsType = { + parTopLevelSovereigntyGlobalPoliciesEnable: false + parListOfAllowedLocations: [] + parPolicyEffect: 'Deny' +} + +@sys.description('''Object used to assign Sovereignty Baseline - Confidential Policies to the confidential landing zone management groups.' + +- `parAllowedResourceTypes` - The list of Azure resource types approved for usage, which is the set of resource types that have a SKU backed by Azure Confidential Computing or resource types that do not process customer data. Leave empty to allow all relevant resource types. +- `parListOfAllowedLocations` - The list of locations that your organization can use to restrict deploying resources to. If left empty, only the deployment location will be allowed. +- `parallowedVirtualMachineSKUs` - The list of VM SKUs approved approved for usage, which is the set of SKUs backed by Azure Confidential Computing. Leave empty to allow all relevant SKUs. +- `parPolicyEffect` - The effect type for the Sovereignty Baseline - Confidential Policies Assignment. + +''') +param parPolicyAssignmentSovereigntyConfidential policyAssignmentSovereigntyConfidentialOptionsType = { + parAllowedResourceTypes: [] + parListOfAllowedLocations: [] + parAllowedVirtualMachineSKUs: [] + parPolicyEffect: 'Deny' +} + @sys.description('Management, Identity and Connectivity Management Groups beneath Platform Management Group have been deployed. If set to false, platform policies are assigned to the Platform Management Group; otherwise policies are assigned to the child management groups.') param parPlatformMgAlzDefaultsEnable bool = true @@ -46,6 +99,9 @@ param parPrivateDnsZonesNamesToAuditInCorp array = [] @sys.description('Set Enforcement Mode of all default Policies assignments to Do Not Enforce.') param parDisableAlzDefaultPolicies bool = false +@sys.description('Set Enforcement Mode of all default sovereign Policies assignments to Do Not Enforce.') +param parDisableSlzDefaultPolicies bool = false + @sys.description('Name of the tag to use for excluding VMs from the scope of this policy. This should be used along with the Exclusion Tag Value parameter.') param parVmBackupExclusionTagName string = '' @@ -80,6 +136,7 @@ var varDeploymentNameWrappers = { } var varModuleDeploymentNames = { + modPolicyAssignmentIntRootEnforceSovereigntyGlobal: take('${varDeploymentNameWrappers.basePrefix}-polAssi-enforceSovereigntyGlobal-intRoot-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}', 64) modPolicyAssignmentIntRootDeployMdfcConfig: take('${varDeploymentNameWrappers.basePrefix}-polAssi-deployMDFCConfig-intRoot-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}', 64) modPolicyAssignmentIntRootDeployAzActivityLog: take('${varDeploymentNameWrappers.basePrefix}-polAssi-deployAzActivityLog-intRoot-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}', 64) modPolicyAssignmentIntRootDeployAscMonitoring: take('${varDeploymentNameWrappers.basePrefix}-polAssi-deployASCMonitoring-intRoot-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}', 64) @@ -90,6 +147,8 @@ var varModuleDeploymentNames = { modPolicyAssignmentIntRootEnforceAcsb: take('${varDeploymentNameWrappers.basePrefix}-polAssi-enforceAcsb-intRoot-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}', 64) modPolicyAssignmentIntRootDeployMdfcOssDb: take('${varDeploymentNameWrappers.basePrefix}-polAssi-deployMdfcOssDb-intRoot-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}', 64) modPolicyAssignmentIntRootDeployMdfcSqlAtp: take('${varDeploymentNameWrappers.basePrefix}-polAssi-deployMdfcSqlAtp-intRoot-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}', 64) + modPolicyAssignmentIntRootAuditLocationMatch: take('${varDeploymentNameWrappers.basePrefix}-polAssi-auditLocationMatch-intRoot-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}', 64) + modPolicyAssignmentIntRootAuditZoneResiliency: take('${varDeploymentNameWrappers.basePrefix}-polAssi-auditZoneResiliency-intRoot-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}', 64) modPolicyAssignmentIntRootAuditUnusedRes: take('${varDeploymentNameWrappers.basePrefix}-polAssi-auditUnusedRes-intRoot-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}', 64) modPolicyAssignmentIntRootDenyClassicRes: take('${varDeploymentNameWrappers.basePrefix}-polAssi-denyClassicRes-intRoot-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}', 64) modPolicyAssignmentIntRootDenyUnmanagedDisks: take('${varDeploymentNameWrappers.basePrefix}-polAssi-denyUnmanagedDisks-intRoot-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}', 64) @@ -117,9 +176,11 @@ var varModuleDeploymentNames = { modPolicyAssignmentLzsDeploySqlTde: take('${varDeploymentNameWrappers.basePrefix}-polAssi-deploySQLTde-lz-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}', 64) modPolicyAssignmentLzsEnforceGrKeyVault: take('${varDeploymentNameWrappers.basePrefix}-polAssi-enforceGrKeyVault-lz-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}', 64) modPolicyAssignmentLzsAuditAppGwWaf: take('${varDeploymentNameWrappers.basePrefix}-polAssi-auditAppGwWaf-lz-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}', 64) + modPolicyAssignmentLzsConfidentialOnlineEnforceSovereigntyConf: take('${varDeploymentNameWrappers.basePrefix}-polAssi-enforceSovereigntyConf-confidential-online-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}', 64) modPolicyAssignmentLzsCorpDenyPublicEndpoints: take('${varDeploymentNameWrappers.basePrefix}-polAssi-denyPublicEndpoints-corp-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}', 64) modPolicyAssignmentLzsConfidentialCorpDenyPublicEndpoints: take('${varDeploymentNameWrappers.basePrefix}-polAssi-denyPublicEndpoints-confidential-corp-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}', 64) modPolicyAssignmentLzsCorpDeployPrivateDnsZones: take('${varDeploymentNameWrappers.basePrefix}-polAssi-deployPrivateDNS-corp-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}', 64) + modPolicyAssignmentLzsConfidentialCorpEnforceSovereigntyConf: take('${varDeploymentNameWrappers.basePrefix}-polAssi-enforceSovereigntyConf-confidential-corp-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}', 64) modPolicyAssignmentLzsConfidentialCorpDeployPrivateDnsZones: take('${varDeploymentNameWrappers.basePrefix}-polAssi-deployPrivateDNS-confidential-corp-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}', 64) modPolicyAssignmentLzsCorpDenyPipOnNic: take('${varDeploymentNameWrappers.basePrefix}-polAssi-denyPipOnNic-corp-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}', 64) modPolicyAssignmentLzsConfidentialCorpDenyPipOnNic: take('${varDeploymentNameWrappers.basePrefix}-polAssi-denyPipOnNic-confidential-corp-${varDeploymentNameWrappers.baseSuffixTenantAndManagementGroup}', 64) @@ -143,11 +204,21 @@ var varPolicyAssignmentAuditPeDnsZones = { libDefinition: loadJsonContent('../../../policy/assignments/lib/policy_assignments/policy_assignment_es_audit_pednszones.tmpl.json') } +var varPolicyAssignmentAuditLocationMatch = { + definitionId: '/providers/Microsoft.Authorization/policyDefinitions/0a914e76-4921-4c19-b460-a2d36003525a' + libDefinition: loadJsonContent('../../../policy/assignments/lib/policy_assignments/policy_assignment_es_audit_res_location_match_rg_location.tmpl.json') +} + var varPolicyAssignmentAuditUnusedResources = { definitionId: '${varTopLevelManagementGroupResourceId}/providers/Microsoft.Authorization/policySetDefinitions/Audit-UnusedResourcesCostOptimization' libDefinition: loadJsonContent('../../../policy/assignments/lib/policy_assignments/policy_assignment_es_audit_unusedresources.tmpl.json') } +var varPolicyAssignmentAuditZoneResiliency = { + definitionId: '/providers/Microsoft.Authorization/policySetDefinitions/130fb88f-0fc9-4678-bfe1-31022d71c7d5' + libDefinition: loadJsonContent('../../../policy/assignments/lib/policy_assignments/policy_assignment_es_audit_zoneresiliency.tmpl.json') +} + var varPolicyAssignmentDenyClassicResources = { definitionId: '/providers/Microsoft.Authorization/policyDefinitions/6c112d4e-5bc7-47ae-a041-ea2d9dccd749' libDefinition: loadJsonContent('../../../policy/assignments/lib/policy_assignments/policy_assignment_es_deny_classic-resources.tmpl.json') @@ -198,6 +269,16 @@ var varPolicyAssignmentDenyPublicIP = { libDefinition: loadJsonContent('../../../policy/assignments/lib/policy_assignments/policy_assignment_es_deny_public_ip.tmpl.json') } +var varPolicyAssignmentEnforceSovereignConf = { + definitionId: '/providers/Microsoft.Authorization/policySetDefinitions/03de05a4-c324-4ccd-882f-a814ea8ab9ea' + libDefinition: loadJsonContent('../../../policy/assignments/lib/policy_assignments/policy_assignment_es_enforce_sovereignty_baseline_conf.tmpl.json') +} + +var varPolicyAssignmentEnforceSovereignGlobal = { + definitionId: '/providers/Microsoft.Authorization/policySetDefinitions/c1cbff38-87c0-4b9f-9f70-035c7a3b5523' + libDefinition: loadJsonContent('../../../policy/assignments/lib/policy_assignments/policy_assignment_es_enforce_sovereignty_baseline_global.tmpl.json') +} + var varPolicyAssignmentDenyStoragehttp = { definitionId: '/providers/Microsoft.Authorization/policyDefinitions/404c3081-a854-4457-ae30-26a93ef643f9' libDefinition: loadJsonContent('../../../policy/assignments/lib/policy_assignments/policy_assignment_es_deny_storage_http.tmpl.json') @@ -441,6 +522,31 @@ module modCustomerUsageAttributionZtnP1 '../../../../CRML/customerUsageAttributi } // Modules - Policy Assignments - Intermediate Root Management Group +// Module - Policy Assignment - Enforce-Sovereign-Global +module modPolicyAssignmentIntRootEnforceSovereigntyGlobal '../../../policy/assignments/policyAssignmentManagementGroup.bicep' = if (!contains(parExcludedPolicyAssignments, varPolicyAssignmentEnforceSovereignGlobal.libDefinition.name) && parTopLevelPolicyAssignmentSovereigntyGlobal.parTopLevelSovereigntyGlobalPoliciesEnable) { + scope: managementGroup(varManagementGroupIds.intRoot) + name: varModuleDeploymentNames.modPolicyAssignmentIntRootEnforceSovereigntyGlobal + params: { + parPolicyAssignmentDefinitionId: varPolicyAssignmentEnforceSovereignGlobal.definitionId + parPolicyAssignmentName: varPolicyAssignmentEnforceSovereignGlobal.libDefinition.name + parPolicyAssignmentDisplayName: varPolicyAssignmentEnforceSovereignGlobal.libDefinition.properties.displayName + parPolicyAssignmentDescription: varPolicyAssignmentEnforceSovereignGlobal.libDefinition.properties.description + parPolicyAssignmentParameters: varPolicyAssignmentEnforceSovereignGlobal.libDefinition.properties.parameters + parPolicyAssignmentParameterOverrides: { + listOfAllowedLocations: { + #disable-next-line no-loc-expr-outside-params + value: !(empty(parTopLevelPolicyAssignmentSovereigntyGlobal.parListOfAllowedLocations)) ? parTopLevelPolicyAssignmentSovereigntyGlobal.parListOfAllowedLocations : array(deployment().location) + } + effect: { + value: parTopLevelPolicyAssignmentSovereigntyGlobal.parPolicyEffect + } + } + parPolicyAssignmentIdentityType: varPolicyAssignmentEnforceSovereignGlobal.libDefinition.identity.type + parPolicyAssignmentEnforcementMode: parDisableSlzDefaultPolicies ? 'DoNotEnforce' : varPolicyAssignmentEnforceSovereignGlobal.libDefinition.properties.enforcementMode + parTelemetryOptOut: parTelemetryOptOut + } +} + // Module - Policy Assignment - Deploy-MDFC-Config module modPolicyAssignmentIntRootDeployMdfcConfig '../../../policy/assignments/policyAssignmentManagementGroup.bicep' = if (!contains(parExcludedPolicyAssignments, varPolicyAssignmentDeployMDFCConfig.libDefinition.name)) { scope: managementGroup(varManagementGroupIds.intRoot) @@ -661,6 +767,38 @@ module modPolicyAssignmentIntRootDeployMdfcSqlAtp '../../../policy/assignments/p } } +// Module - Policy Assignment - Audit Location Match +module modPolicyAssignmentIntRootAuditLocationMatch '../../../policy/assignments/policyAssignmentManagementGroup.bicep' = if (!contains(parExcludedPolicyAssignments, varPolicyAssignmentAuditLocationMatch.libDefinition.name)) { + scope: managementGroup(varManagementGroupIds.intRoot) + name: varModuleDeploymentNames.modPolicyAssignmentIntRootAuditLocationMatch + params: { + parPolicyAssignmentDefinitionId: varPolicyAssignmentAuditLocationMatch.definitionId + parPolicyAssignmentName: varPolicyAssignmentAuditLocationMatch.libDefinition.name + parPolicyAssignmentDisplayName: varPolicyAssignmentAuditLocationMatch.libDefinition.properties.displayName + parPolicyAssignmentDescription: varPolicyAssignmentAuditLocationMatch.libDefinition.properties.description + parPolicyAssignmentParameters: varPolicyAssignmentAuditLocationMatch.libDefinition.properties.parameters + parPolicyAssignmentIdentityType: varPolicyAssignmentAuditLocationMatch.libDefinition.identity.type + parPolicyAssignmentEnforcementMode: parDisableAlzDefaultPolicies ? 'DoNotEnforce' : varPolicyAssignmentAuditLocationMatch.libDefinition.properties.enforcementMode + parTelemetryOptOut: parTelemetryOptOut + } +} + +// Module - Policy Assignment - Audit Zone Resiliency +module modPolicyAssignmentIntRootAuditZoneResiliency '../../../policy/assignments/policyAssignmentManagementGroup.bicep' = if (!contains(parExcludedPolicyAssignments, varPolicyAssignmentAuditZoneResiliency.libDefinition.name)) { + scope: managementGroup(varManagementGroupIds.intRoot) + name: varModuleDeploymentNames.modPolicyAssignmentIntRootAuditZoneResiliency + params: { + parPolicyAssignmentDefinitionId: varPolicyAssignmentAuditZoneResiliency.definitionId + parPolicyAssignmentName: varPolicyAssignmentAuditZoneResiliency.libDefinition.name + parPolicyAssignmentDisplayName: varPolicyAssignmentAuditZoneResiliency.libDefinition.properties.displayName + parPolicyAssignmentDescription: varPolicyAssignmentAuditZoneResiliency.libDefinition.properties.description + parPolicyAssignmentParameters: varPolicyAssignmentAuditZoneResiliency.libDefinition.properties.parameters + parPolicyAssignmentIdentityType: varPolicyAssignmentAuditZoneResiliency.libDefinition.identity.type + parPolicyAssignmentEnforcementMode: parDisableAlzDefaultPolicies ? 'DoNotEnforce' : varPolicyAssignmentAuditZoneResiliency.libDefinition.properties.enforcementMode + parTelemetryOptOut: parTelemetryOptOut + } +} + // Module - Policy Assignment - Audit-UnusedResources module modPolicyAssignmentIntRootAuditUnusedRes '../../../policy/assignments/policyAssignmentManagementGroup.bicep' = if (!contains(parExcludedPolicyAssignments, varPolicyAssignmentAuditUnusedResources.libDefinition.name)) { scope: managementGroup(varManagementGroupIds.intRoot) @@ -1416,6 +1554,70 @@ module modPolicyAssignmentLzsCorpAuditPeDnsZones '../../../policy/assignments/po } }] +// Modules - Policy Assignments - Confidential Online Management Group +// Module - Policy Assignment - Enforce-Sovereign-Conf +module modPolicyAssignmentLzsConfidentialOnlineEnforceSovereigntyConf '../../../policy/assignments/policyAssignmentManagementGroup.bicep' = if (!contains(parExcludedPolicyAssignments, varPolicyAssignmentEnforceSovereignConf.libDefinition.name) && parLandingZoneMgConfidentialEnable) { + scope: managementGroup(varManagementGroupIds.landingZonesConfidentialOnline) + name: varModuleDeploymentNames.modPolicyAssignmentLzsConfidentialOnlineEnforceSovereigntyConf + params: { + parPolicyAssignmentDefinitionId: varPolicyAssignmentEnforceSovereignConf.definitionId + parPolicyAssignmentName: varPolicyAssignmentEnforceSovereignConf.libDefinition.name + parPolicyAssignmentDisplayName: varPolicyAssignmentEnforceSovereignConf.libDefinition.properties.displayName + parPolicyAssignmentDescription: varPolicyAssignmentEnforceSovereignConf.libDefinition.properties.description + parPolicyAssignmentParameters: varPolicyAssignmentEnforceSovereignConf.libDefinition.properties.parameters + parPolicyAssignmentParameterOverrides: { + allowedResourceTypes: { + value: !(empty(parPolicyAssignmentSovereigntyConfidential.parAllowedResourceTypes)) ? parPolicyAssignmentSovereigntyConfidential.parAllowedResourceTypes : varPolicyAssignmentEnforceSovereignConf.libDefinition.properties.parameters.allowedResourceTypes.value + } + listOfAllowedLocations: { + #disable-next-line no-loc-expr-outside-params + value: !(empty(parPolicyAssignmentSovereigntyConfidential.parListOfAllowedLocations)) ? parPolicyAssignmentSovereigntyConfidential.parListOfAllowedLocations : array(deployment().location) + } + allowedVirtualMachineSKUs: { + value: !(empty(parPolicyAssignmentSovereigntyConfidential.parAllowedVirtualMachineSKUs)) ? parPolicyAssignmentSovereigntyConfidential.parAllowedVirtualMachineSKUs : varPolicyAssignmentEnforceSovereignConf.libDefinition.properties.parameters.allowedVirtualMachineSKUs.value + } + effect: { + value: parPolicyAssignmentSovereigntyConfidential.parPolicyEffect + } + } + parPolicyAssignmentIdentityType: varPolicyAssignmentEnforceSovereignConf.libDefinition.identity.type + parPolicyAssignmentEnforcementMode: parDisableSlzDefaultPolicies ? 'DoNotEnforce' : varPolicyAssignmentEnforceSovereignConf.libDefinition.properties.enforcementMode + parTelemetryOptOut: parTelemetryOptOut + } +} + +// Modules - Policy Assignments - Confidential Corp Management Group +// Module - Policy Assignment - Enforce-Sovereign-Conf +module modPolicyAssignmentLzsConfidentialCorpEnforceSovereigntyConf '../../../policy/assignments/policyAssignmentManagementGroup.bicep' = if (!contains(parExcludedPolicyAssignments, varPolicyAssignmentEnforceSovereignConf.libDefinition.name) && parLandingZoneMgConfidentialEnable) { + scope: managementGroup(varManagementGroupIds.landingZonesConfidentialCorp) + name: varModuleDeploymentNames.modPolicyAssignmentLzsConfidentialCorpEnforceSovereigntyConf + params: { + parPolicyAssignmentDefinitionId: varPolicyAssignmentEnforceSovereignConf.definitionId + parPolicyAssignmentName: varPolicyAssignmentEnforceSovereignConf.libDefinition.name + parPolicyAssignmentDisplayName: varPolicyAssignmentEnforceSovereignConf.libDefinition.properties.displayName + parPolicyAssignmentDescription: varPolicyAssignmentEnforceSovereignConf.libDefinition.properties.description + parPolicyAssignmentParameters: varPolicyAssignmentEnforceSovereignConf.libDefinition.properties.parameters + parPolicyAssignmentParameterOverrides: { + allowedResourceTypes: { + value: !(empty(parPolicyAssignmentSovereigntyConfidential.parAllowedResourceTypes)) ? parPolicyAssignmentSovereigntyConfidential.parAllowedResourceTypes : varPolicyAssignmentEnforceSovereignConf.libDefinition.properties.parameters.allowedResourceTypes.value + } + listOfAllowedLocations: { + #disable-next-line no-loc-expr-outside-params + value: !(empty(parPolicyAssignmentSovereigntyConfidential.parListOfAllowedLocations)) ? parPolicyAssignmentSovereigntyConfidential.parListOfAllowedLocations : array(deployment().location) + } + allowedVirtualMachineSKUs: { + value: !(empty(parPolicyAssignmentSovereigntyConfidential.parAllowedVirtualMachineSKUs)) ? parPolicyAssignmentSovereigntyConfidential.parAllowedVirtualMachineSKUs : varPolicyAssignmentEnforceSovereignConf.libDefinition.properties.parameters.allowedVirtualMachineSKUs.value + } + effect: { + value: parPolicyAssignmentSovereigntyConfidential.parPolicyEffect + } + } + parPolicyAssignmentIdentityType: varPolicyAssignmentEnforceSovereignConf.libDefinition.identity.type + parPolicyAssignmentEnforcementMode: parDisableSlzDefaultPolicies ? 'DoNotEnforce' : varPolicyAssignmentEnforceSovereignConf.libDefinition.properties.enforcementMode + parTelemetryOptOut: parTelemetryOptOut + } +} + // Modules - Policy Assignments - Decommissioned Management Group // Module - Policy Assignment - Enforce-ALZ-Decomm module modPolicyAssignmentDecommEnforceAlz '../../../policy/assignments/policyAssignmentManagementGroup.bicep' = if (!contains(parExcludedPolicyAssignments, varPolicyAssignmentEnforceALZDecomm.libDefinition.name)) { diff --git a/dependencies/infra-as-code/bicep/modules/policy/assignments/alzDefaults/generateddocs/alzDefaultPolicyAssignments.bicep.md b/dependencies/infra-as-code/bicep/modules/policy/assignments/alzDefaults/generateddocs/alzDefaultPolicyAssignments.bicep.md index 81f9c5f..b098125 100644 --- a/dependencies/infra-as-code/bicep/modules/policy/assignments/alzDefaults/generateddocs/alzDefaultPolicyAssignments.bicep.md +++ b/dependencies/infra-as-code/bicep/modules/policy/assignments/alzDefaults/generateddocs/alzDefaultPolicyAssignments.bicep.md @@ -8,6 +8,8 @@ Parameter name | Required | Description -------------- | -------- | ----------- parTopLevelManagementGroupPrefix | No | Prefix used for the management group hierarchy. parTopLevelManagementGroupSuffix | No | Optional suffix for the management group hierarchy. This suffix will be appended to management group names/IDs. Include a preceding dash if required. Example: -suffix +parTopLevelPolicyAssignmentSovereigntyGlobal | No | Object used to assign Sovereignty Baseline - Global Policies to the intermediate root management group.' - `parTopLevelSovereignGlobalPoliciesEnable` - Switch to enable/disable deployment of the Sovereignty Baseline - Global Policies Assignment to the intermediate root management group. - `parListOfAllowedLocations` - The list of locations that your organization can use to restrict deploying resources to. If left empty, only the deployment location will be allowed. - `parPolicyEffect` - The effect type for the Sovereignty Baseline - Global Policies Assignment. +parPolicyAssignmentSovereigntyConfidential | No | Object used to assign Sovereignty Baseline - Confidential Policies to the confidential landing zone management groups.' - `parAllowedResourceTypes` - The list of Azure resource types approved for usage, which is the set of resource types that have a SKU backed by Azure Confidential Computing or resource types that do not process customer data. Leave empty to allow all relevant resource types. - `parListOfAllowedLocations` - The list of locations that your organization can use to restrict deploying resources to. If left empty, only the deployment location will be allowed. - `parallowedVirtualMachineSKUs` - The list of VM SKUs approved approved for usage, which is the set of SKUs backed by Azure Confidential Computing. Leave empty to allow all relevant SKUs. - `parPolicyEffect` - The effect type for the Sovereignty Baseline - Confidential Policies Assignment. parPlatformMgAlzDefaultsEnable | No | Management, Identity and Connectivity Management Groups beneath Platform Management Group have been deployed. If set to false, platform policies are assigned to the Platform Management Group; otherwise policies are assigned to the child management groups. parLandingZoneChildrenMgAlzDefaultsEnable | No | Corp & Online Management Groups beneath Landing Zones Management Groups have been deployed. If set to false, policies will not try to be assigned to corp or online Management Groups. parLandingZoneMgConfidentialEnable | No | Confidential Corp & Confidential Online Management Groups beneath Landing Zones Management Group have been deployed. If set to false, policies will not try to be assigned to Confidential Corp & Confidential Online Management Groups @@ -20,6 +22,7 @@ parDdosProtectionPlanId | No | ID of the DdosProtectionPlan which will be parPrivateDnsResourceGroupId | No | 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. parPrivateDnsZonesNamesToAuditInCorp | No | Provide an array/list of Private DNS Zones that you wish to audit if deployed into Subscriptions in the Corp Management Group. NOTE: The policy default values include all the static Private Link Private DNS Zones, e.g. all the DNS Zones that dont have a region or region shortcode in them. If you wish for these to be audited also you must provide a complete array/list to this parameter for ALL Private DNS Zones you wish to audit, including the static Private Link ones, as this parameter performs an overwrite operation. You can get all the Private DNS Zone Names form the `outPrivateDnsZonesNames` output in the Hub Networking or Private DNS Zone modules. parDisableAlzDefaultPolicies | No | Set Enforcement Mode of all default Policies assignments to Do Not Enforce. +parDisableSlzDefaultPolicies | No | Set Enforcement Mode of all default sovereign Policies assignments to Do Not Enforce. parVmBackupExclusionTagName | No | Name of the tag to use for excluding VMs from the scope of this policy. This should be used along with the Exclusion Tag Value parameter. parVmBackupExclusionTagValue | No | Value of the tag to use for excluding VMs from the scope of this policy (in case of multiple values, use a comma-separated list). This should be used along with the Exclusion Tag Name parameter. parExcludedPolicyAssignments | No | Adding assignment definition names to this array will exclude the specific policies from assignment. Find the correct values to this array in the following documentation: https://github.com/Azure/ALZ-Bicep/wiki/AssigningPolicies#what-if-i-want-to-exclude-specific-policy-assignments-from-alz-default-policy-assignments @@ -39,6 +42,35 @@ Prefix used for the management group hierarchy. Optional suffix for the management group hierarchy. This suffix will be appended to management group names/IDs. Include a preceding dash if required. Example: -suffix +### parTopLevelPolicyAssignmentSovereigntyGlobal + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Object used to assign Sovereignty Baseline - Global Policies to the intermediate root management group.' + +- `parTopLevelSovereignGlobalPoliciesEnable` - Switch to enable/disable deployment of the Sovereignty Baseline - Global Policies Assignment to the intermediate root management group. +- `parListOfAllowedLocations` - The list of locations that your organization can use to restrict deploying resources to. If left empty, only the deployment location will be allowed. +- `parPolicyEffect` - The effect type for the Sovereignty Baseline - Global Policies Assignment. + + + +- Default value: `@{parTopLevelSovereigntyGlobalPoliciesEnable=False; parListOfAllowedLocations=System.Object[]; parPolicyEffect=Deny}` + +### parPolicyAssignmentSovereigntyConfidential + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Object used to assign Sovereignty Baseline - Confidential Policies to the confidential landing zone management groups.' + +- `parAllowedResourceTypes` - The list of Azure resource types approved for usage, which is the set of resource types that have a SKU backed by Azure Confidential Computing or resource types that do not process customer data. Leave empty to allow all relevant resource types. +- `parListOfAllowedLocations` - The list of locations that your organization can use to restrict deploying resources to. If left empty, only the deployment location will be allowed. +- `parallowedVirtualMachineSKUs` - The list of VM SKUs approved approved for usage, which is the set of SKUs backed by Azure Confidential Computing. Leave empty to allow all relevant SKUs. +- `parPolicyEffect` - The effect type for the Sovereignty Baseline - Confidential Policies Assignment. + + + +- Default value: `@{parAllowedResourceTypes=System.Object[]; parListOfAllowedLocations=System.Object[]; parAllowedVirtualMachineSKUs=System.Object[]; parPolicyEffect=Deny}` + ### parPlatformMgAlzDefaultsEnable ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) @@ -127,6 +159,14 @@ Set Enforcement Mode of all default Policies assignments to Do Not Enforce. - Default value: `False` +### parDisableSlzDefaultPolicies + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Set Enforcement Mode of all default sovereign Policies assignments to Do Not Enforce. + +- Default value: `False` + ### parVmBackupExclusionTagName ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) @@ -171,6 +211,21 @@ Set Parameter to true to Opt-out of deployment telemetry "parTopLevelManagementGroupSuffix": { "value": "" }, + "parTopLevelPolicyAssignmentSovereigntyGlobal": { + "value": { + "parTopLevelSovereigntyGlobalPoliciesEnable": false, + "parListOfAllowedLocations": [], + "parPolicyEffect": "Deny" + } + }, + "parPolicyAssignmentSovereigntyConfidential": { + "value": { + "parAllowedResourceTypes": [], + "parListOfAllowedLocations": [], + "parAllowedVirtualMachineSKUs": [], + "parPolicyEffect": "Deny" + } + }, "parPlatformMgAlzDefaultsEnable": { "value": true }, @@ -207,6 +262,9 @@ Set Parameter to true to Opt-out of deployment telemetry "parDisableAlzDefaultPolicies": { "value": false }, + "parDisableSlzDefaultPolicies": { + "value": false + }, "parVmBackupExclusionTagName": { "value": "" }, diff --git a/dependencies/infra-as-code/bicep/modules/policy/assignments/alzDefaults/parameters/alzDefaultPolicyAssignments.parameters.all.json b/dependencies/infra-as-code/bicep/modules/policy/assignments/alzDefaults/parameters/alzDefaultPolicyAssignments.parameters.all.json index 29a786e..6f500b8 100644 --- a/dependencies/infra-as-code/bicep/modules/policy/assignments/alzDefaults/parameters/alzDefaultPolicyAssignments.parameters.all.json +++ b/dependencies/infra-as-code/bicep/modules/policy/assignments/alzDefaults/parameters/alzDefaultPolicyAssignments.parameters.all.json @@ -8,6 +8,13 @@ "parTopLevelManagementGroupSuffix": { "value": "" }, + "parTopLevelPolicyAssignmentSovereigntyGlobal": { + "value": { + "parTopLevelSovereigntyGlobalPoliciesEnable": false, + "parListOfAllowedLocations": [], + "parPolicyEffect": "Deny" + } + }, "parPlatformMgAlzDefaultsEnable": { "value": true }, @@ -17,6 +24,14 @@ "parLandingZoneMgConfidentialEnable": { "value": false }, + "parPolicyAssignmentSovereigntyConfidential": { + "value": { + "parAllowedResourceTypes": [], + "parListOfAllowedLocations": [], + "parAllowedVirtualMachineSKUs": [], + "parPolicyEffect": "Deny" + } + }, "parLogAnalyticsWorkSpaceAndAutomationAccountLocation": { "value": "eastus" }, diff --git a/dependencies/infra-as-code/bicep/modules/policy/assignments/lib/policy_assignments/policy_assignment_es_audit_res_location_match_rg_location.tmpl.json b/dependencies/infra-as-code/bicep/modules/policy/assignments/lib/policy_assignments/policy_assignment_es_audit_res_location_match_rg_location.tmpl.json new file mode 100644 index 0000000..422e544 --- /dev/null +++ b/dependencies/infra-as-code/bicep/modules/policy/assignments/lib/policy_assignments/policy_assignment_es_audit_res_location_match_rg_location.tmpl.json @@ -0,0 +1,18 @@ +{ + "name": "Audit-Location-Match", + "type": "Microsoft.Authorization/policyAssignments", + "apiVersion": "2019-09-01", + "properties": { + "description": "Audit resource location matches resource group location", + "displayName": "Audit that the resource location matches its resource group location", + "notScopes": [], + "parameters": {}, + "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/0a914e76-4921-4c19-b460-a2d36003525a", + "scope": null, + "enforcementMode": "Default" + }, + "location": null, + "identity": { + "type": "None" + } +} diff --git a/dependencies/infra-as-code/bicep/modules/policy/assignments/lib/policy_assignments/policy_assignment_es_audit_zoneresiliency.tmpl.json b/dependencies/infra-as-code/bicep/modules/policy/assignments/lib/policy_assignments/policy_assignment_es_audit_zoneresiliency.tmpl.json new file mode 100644 index 0000000..4bb302c --- /dev/null +++ b/dependencies/infra-as-code/bicep/modules/policy/assignments/lib/policy_assignments/policy_assignment_es_audit_zoneresiliency.tmpl.json @@ -0,0 +1,25 @@ +{ + "name": "Audit-ZoneResiliency", + "type": "Microsoft.Authorization/policyAssignments", + "apiVersion": "2019-09-01", + "properties": { + "description": "Resources should be Zone Resilient.", + "displayName": "Resources should be Zone Resilient", + "notScopes": [], + "parameters": { + "effect": { + "value": "Audit" + }, + "allow": { + "value": "Both" + } + }, + "policyDefinitionId": "/providers/Microsoft.Authorization/policySetDefinitions/130fb88f-0fc9-4678-bfe1-31022d71c7d5", + "scope": null, + "enforcementMode": "Default" + }, + "location": null, + "identity": { + "type": "None" + } +} diff --git a/dependencies/infra-as-code/bicep/modules/policy/assignments/lib/policy_assignments/policy_assignment_es_deploy_mdfc_config.tmpl.json b/dependencies/infra-as-code/bicep/modules/policy/assignments/lib/policy_assignments/policy_assignment_es_deploy_mdfc_config.tmpl.json index 8ad348a..238f736 100644 --- a/dependencies/infra-as-code/bicep/modules/policy/assignments/lib/policy_assignments/policy_assignment_es_deploy_mdfc_config.tmpl.json +++ b/dependencies/infra-as-code/bicep/modules/policy/assignments/lib/policy_assignments/policy_assignment_es_deploy_mdfc_config.tmpl.json @@ -26,7 +26,7 @@ "value": "DeployIfNotExists" }, "vulnerabilityAssessmentProvider": { - "value": "default" + "value": "mdeTvm" }, "enableAscForSql": { "value": "DeployIfNotExists" diff --git a/dependencies/infra-as-code/bicep/modules/policy/assignments/lib/policy_assignments/policy_assignment_es_enforce_alz_sandbox.tmpl.json b/dependencies/infra-as-code/bicep/modules/policy/assignments/lib/policy_assignments/policy_assignment_es_enforce_alz_sandbox.tmpl.json index 906a9f8..856c5ec 100644 --- a/dependencies/infra-as-code/bicep/modules/policy/assignments/lib/policy_assignments/policy_assignment_es_enforce_alz_sandbox.tmpl.json +++ b/dependencies/infra-as-code/bicep/modules/policy/assignments/lib/policy_assignments/policy_assignment_es_enforce_alz_sandbox.tmpl.json @@ -11,10 +11,13 @@ "value": [ "microsoft.network/expressroutecircuits", "microsoft.network/expressroutegateways", + "microsoft.network/expressrouteports", "microsoft.network/virtualwans", "microsoft.network/virtualhubs", "microsoft.network/vpngateways", - "microsoft.network/vpnsites" + "microsoft.network/p2svpngateways", + "microsoft.network/vpnsites", + "microsoft.network/virtualnetworkgateways" ] } }, @@ -26,4 +29,4 @@ "identity": { "type": "None" } -} \ No newline at end of file +} diff --git a/modules/compliance/policyAssignments/policy_assignment_deploy_slz_confidential_defaults.tmpl.json b/dependencies/infra-as-code/bicep/modules/policy/assignments/lib/policy_assignments/policy_assignment_es_enforce_sovereignty_baseline_conf.tmpl.json similarity index 85% rename from modules/compliance/policyAssignments/policy_assignment_deploy_slz_confidential_defaults.tmpl.json rename to dependencies/infra-as-code/bicep/modules/policy/assignments/lib/policy_assignments/policy_assignment_es_enforce_sovereignty_baseline_conf.tmpl.json index f7461d8..946ec70 100644 --- a/modules/compliance/policyAssignments/policy_assignment_deploy_slz_confidential_defaults.tmpl.json +++ b/dependencies/infra-as-code/bicep/modules/policy/assignments/lib/policy_assignments/policy_assignment_es_enforce_sovereignty_baseline_conf.tmpl.json @@ -1,16 +1,13 @@ { - "name": "Deploy-SLZ-Conf", + "name": "Enforce-Sovereign-Conf", "type": "Microsoft.Authorization/policyAssignments", "apiVersion": "2019-09-01", "properties": { - "description": "SLZ Confidential Policies", - "displayName": "SLZ Confidential Policies", + "description": "The Microsoft Cloud for Sovereignty recommends confidential policies to help organizations achieve their sovereignty goals by default denying the creation of resources outside of approved regions, denying resources that are not backed by Azure Confidential Computing, and denying data storage resources that are not using Customer-Managed Keys. More details can be found here: https://aka.ms/SovereigntyBaselinePolicies", + "displayName": "[Preview]: Sovereignty Baseline - Confidential Policies", "notScopes": [], "parameters": { - "listOfAllowedLocations": { - "value": [] - }, - "Resource Types": { + "allowedResourceTypes": { "value": [ "Microsoft.Attestation/attestationProviders", "Microsoft.Compute/availabilitySets", @@ -202,7 +199,7 @@ "Microsoft.Sql/servers/vulnerabilityAssessments" ] }, - "Virtual Machine SKUs": { + "allowedVirtualMachineSKUs": { "value": [ "Standard_DC1s_v2", "Standard_DC2s_v2", @@ -261,14 +258,75 @@ "Standard_EC96iads_v5", "Standard_EC96ias_v5" ] + }, + "effect": { + "value": "Deny" + }, + "listOfAllowedLocations": { + "value": [ + "australiacentral", + "australiacentral2", + "australiaeast", + "australiasoutheast", + "brazilsouth", + "brazilsoutheast", + "brazilus", + "canadacentral", + "canadaeast", + "centralindia", + "centralus", + "centraluseuap", + "eastasia", + "eastus", + "eastus2", + "eastus2euap", + "eastusstg", + "francecentral", + "francesouth", + "germanynorth", + "germanywestcentral", + "israelcentral", + "italynorth", + "japaneast", + "japanwest", + "jioindiacentral", + "jioindiawest", + "koreacentral", + "koreasouth", + "northcentralus", + "northeurope", + "norwayeast", + "norwaywest", + "polandcentral", + "qatarcentral", + "southafricanorth", + "southafricawest", + "southcentralus", + "southcentralusstg", + "southeastasia", + "southindia", + "swedencentral", + "switzerlandnorth", + "switzerlandwest", + "uaecentral", + "uaenorth", + "uksouth", + "ukwest", + "westcentralus", + "westeurope", + "westindia", + "westus", + "westus2", + "westus3" + ] } }, - "policyDefinitionId": "${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policySetDefinitions/SlzConfidentialPolicies", + "policyDefinitionId": "/providers/Microsoft.Authorization/policySetDefinitions/03de05a4-c324-4ccd-882f-a814ea8ab9ea", "scope": null, "enforcementMode": "Default" }, "location": null, "identity": { - "type": "SystemAssigned" + "type": "None" } } diff --git a/dependencies/infra-as-code/bicep/modules/policy/assignments/lib/policy_assignments/policy_assignment_es_enforce_sovereignty_baseline_global.tmpl.json b/dependencies/infra-as-code/bicep/modules/policy/assignments/lib/policy_assignments/policy_assignment_es_enforce_sovereignty_baseline_global.tmpl.json new file mode 100644 index 0000000..260d951 --- /dev/null +++ b/dependencies/infra-as-code/bicep/modules/policy/assignments/lib/policy_assignments/policy_assignment_es_enforce_sovereignty_baseline_global.tmpl.json @@ -0,0 +1,80 @@ +{ + "name": "Enforce-Sovereign-Global", + "type": "Microsoft.Authorization/policyAssignments", + "apiVersion": "2019-09-01", + "properties": { + "description": "The Microsoft Cloud for Sovereignty recommends global policies to help organizations achieve their sovereignty goals by default denying the creation of resources outside of approved regions. More details can be found here: https://aka.ms/SovereigntyBaselinePolicies", + "displayName": "[Preview]: Sovereignty Baseline - Global Policies", + "notScopes": [], + "parameters": { + "effect": { + "value": "Deny" + }, + "listOfAllowedLocations": { + "value": [ + "australiacentral", + "australiacentral2", + "australiaeast", + "australiasoutheast", + "brazilsouth", + "brazilsoutheast", + "brazilus", + "canadacentral", + "canadaeast", + "centralindia", + "centralus", + "centraluseuap", + "eastasia", + "eastus", + "eastus2", + "eastus2euap", + "eastusstg", + "francecentral", + "francesouth", + "germanynorth", + "germanywestcentral", + "israelcentral", + "italynorth", + "japaneast", + "japanwest", + "jioindiacentral", + "jioindiawest", + "koreacentral", + "koreasouth", + "northcentralus", + "northeurope", + "norwayeast", + "norwaywest", + "polandcentral", + "qatarcentral", + "southafricanorth", + "southafricawest", + "southcentralus", + "southcentralusstg", + "southeastasia", + "southindia", + "swedencentral", + "switzerlandnorth", + "switzerlandwest", + "uaecentral", + "uaenorth", + "uksouth", + "ukwest", + "westcentralus", + "westeurope", + "westindia", + "westus", + "westus2", + "westus3" + ] + } + }, + "policyDefinitionId": "/providers/Microsoft.Authorization/policySetDefinitions/c1cbff38-87c0-4b9f-9f70-035c7a3b5523", + "scope": null, + "enforcementMode": "Default" + }, + "location": null, + "identity": { + "type": "None" + } +} diff --git a/dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep b/dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep index c91359a..b62e812 100644 --- a/dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep +++ b/dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep @@ -3,6 +3,14 @@ targetScope = 'managementGroup' metadata name = 'ALZ Bicep - Management Group Policy Assignments' metadata description = 'Module used to assign policy definitions to management groups' +type nonComplianceMessageType = { + @description('The message to display when the policy is non-compliant.') + message: string + + @description('The reference ID of the policy definition.') + policyDefinitionReferenceId: string +}[] + @minLength(1) @maxLength(24) @sys.description('The name of the policy assignment. e.g. "Deny-Public-IP"') @@ -24,7 +32,7 @@ param parPolicyAssignmentParameters object = {} param parPolicyAssignmentParameterOverrides object = {} @sys.description('An array containing object/s for the non-compliance messages for the policy to be assigned. See https://docs.microsoft.com/en-us/azure/governance/policy/concepts/assignment-structure#non-compliance-messages for more details on use.') -param parPolicyAssignmentNonComplianceMessages array = [] +param parPolicyAssignmentNonComplianceMessages nonComplianceMessageType = [] @sys.description('An array containing a list of scope Resource IDs to be excluded for the policy assignment. e.g. [\'/providers/Microsoft.Management/managementgroups/alz\', \'/providers/Microsoft.Management/managementgroups/alz-sandbox\' ].') param parPolicyAssignmentNotScopes array = [] diff --git a/dependencies/infra-as-code/bicep/modules/policy/definitions/customPolicyDefinitions.bicep b/dependencies/infra-as-code/bicep/modules/policy/definitions/customPolicyDefinitions.bicep index 27e51d8..5643d34 100644 --- a/dependencies/infra-as-code/bicep/modules/policy/definitions/customPolicyDefinitions.bicep +++ b/dependencies/infra-as-code/bicep/modules/policy/definitions/customPolicyDefinitions.bicep @@ -457,6 +457,26 @@ var varCustomPolicyDefinitionsArray = [ name: 'Deploy-FirewallPolicy' libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-FirewallPolicy.json') } + { + name: 'Deploy-MDFC-Arc-SQL-DCR-Association' + libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-MDFC-Arc-SQL-DCR-Association.json') + } + { + name: 'Deploy-MDFC-Arc-Sql-DefenderSQL-DCR' + libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-MDFC-Arc-Sql-DefenderSQL-DCR.json') + } + { + name: 'Deploy-MDFC-SQL-AMA' + libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-MDFC-SQL-AMA.json') + } + { + name: 'Deploy-MDFC-SQL-DefenderSQL-DCR' + libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-MDFC-SQL-DefenderSQL-DCR.json') + } + { + name: 'Deploy-MDFC-SQL-DefenderSQL' + libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-MDFC-SQL-DefenderSQL.json') + } { name: 'Deploy-MySQL-sslEnforcement' libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-MySQL-sslEnforcement.json') @@ -505,6 +525,10 @@ var varCustomPolicyDefinitionsArray = [ name: 'Deploy-Storage-sslEnforcement' libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Storage-sslEnforcement.json') } + { + name: 'Deploy-UserAssignedManagedIdentity-VMInsights' + libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-UserAssignedManagedIdentity-VMInsights.json') + } { name: 'Deploy-Vm-autoShutdown' libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Vm-autoShutdown.json') @@ -615,6 +639,12 @@ var varCustomPolicySetDefinitionsArray = [ definitionParameters: varPolicySetDefinitionEsDenyPublicPaaSEndpointsParameters.BotServiceDenyPublicIP.parameters definitionGroups: [] } + { + definitionReferenceId: 'ContainerAppsEnvironmentDenyPublicIP' + definitionId: '/providers/Microsoft.Authorization/policyDefinitions/d074ddf8-01a5-4b5e-a2b8-964aed452c0a' + definitionParameters: varPolicySetDefinitionEsDenyPublicPaaSEndpointsParameters.ContainerAppsEnvironmentDenyPublicIP.parameters + definitionGroups: [] + } { definitionReferenceId: 'CosmosDenyPaasPublicIP' definitionId: '/providers/Microsoft.Authorization/policyDefinitions/797b37f7-06b8-444c-b1ad-fc62867f335a' @@ -695,6 +725,36 @@ var varCustomPolicySetDefinitionsArray = [ } ] } + { + name: 'Deploy-AUM-CheckUpdates' + libSetDefinition: loadJsonContent('lib/policy_set_definitions/policy_set_definition_es_Deploy-AUM-CheckUpdates.json') + libSetChildDefinitions: [ + { + definitionReferenceId: 'azureUpdateManagerVmArcCheckUpdateLinux' + definitionId: '/providers/Microsoft.Authorization/policyDefinitions/bfea026e-043f-4ff4-9d1b-bf301ca7ff46' + definitionParameters: varPolicySetDefinitionEsDeployAUMCheckUpdatesParameters.azureUpdateManagerVmArcCheckUpdateLinux.parameters + definitionGroups: [] + } + { + definitionReferenceId: 'azureUpdateManagerVmArcCheckUpdateWindows' + definitionId: '/providers/Microsoft.Authorization/policyDefinitions/bfea026e-043f-4ff4-9d1b-bf301ca7ff46' + definitionParameters: varPolicySetDefinitionEsDeployAUMCheckUpdatesParameters.azureUpdateManagerVmArcCheckUpdateWindows.parameters + definitionGroups: [] + } + { + definitionReferenceId: 'azureUpdateManagerVmCheckUpdateLinux' + definitionId: '/providers/Microsoft.Authorization/policyDefinitions/59efceea-0c96-497e-a4a1-4eb2290dac15' + definitionParameters: varPolicySetDefinitionEsDeployAUMCheckUpdatesParameters.azureUpdateManagerVmCheckUpdateLinux.parameters + definitionGroups: [] + } + { + definitionReferenceId: 'azureUpdateManagerVmCheckUpdateWindows' + definitionId: '/providers/Microsoft.Authorization/policyDefinitions/59efceea-0c96-497e-a4a1-4eb2290dac15' + definitionParameters: varPolicySetDefinitionEsDeployAUMCheckUpdatesParameters.azureUpdateManagerVmCheckUpdateWindows.parameters + definitionGroups: [] + } + ] + } { name: 'Deploy-Diagnostics-LogAnalytics' libSetDefinition: loadJsonContent('lib/policy_set_definitions/policy_set_definition_es_Deploy-Diagnostics-LogAnalytics.json') @@ -1227,6 +1287,12 @@ var varCustomPolicySetDefinitionsArray = [ definitionParameters: varPolicySetDefinitionEsDeployMDFCConfigParameters.defenderForVMVulnerabilityAssessment.parameters definitionGroups: [] } + { + definitionReferenceId: 'migrateToMdeTvm' + definitionId: '/providers/Microsoft.Authorization/policyDefinitions/766e621d-ba95-4e43-a6f2-e945db3d7888' + definitionParameters: varPolicySetDefinitionEsDeployMDFCConfigParameters.migrateToMdeTvm.parameters + definitionGroups: [] + } { definitionReferenceId: 'securityEmailContact' definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-ASC-SecurityContacts' @@ -1235,6 +1301,54 @@ var varCustomPolicySetDefinitionsArray = [ } ] } + { + name: 'Deploy-MDFC-DefenderSQL-AMA' + libSetDefinition: loadJsonContent('lib/policy_set_definitions/policy_set_definition_es_Deploy-MDFC-DefenderSQL-AMA.json') + libSetChildDefinitions: [ + { + definitionReferenceId: 'defenderForSqlAma' + definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-MDFC-SQL-AMA' + definitionParameters: varPolicySetDefinitionEsDeployMDFCDefenderSQLAMAParameters.defenderForSqlAma.parameters + definitionGroups: [] + } + { + definitionReferenceId: 'defenderForSqlArcAma' + definitionId: '/providers/Microsoft.Authorization/policyDefinitions/3592ff98-9787-443a-af59-4505d0fe0786' + definitionParameters: varPolicySetDefinitionEsDeployMDFCDefenderSQLAMAParameters.defenderForSqlArcAma.parameters + definitionGroups: [] + } + { + definitionReferenceId: 'defenderForSqlArcDcrAssociation' + definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-MDFC-Arc-SQL-DCR-Association' + definitionParameters: varPolicySetDefinitionEsDeployMDFCDefenderSQLAMAParameters.defenderForSqlArcDcrAssociation.parameters + definitionGroups: [] + } + { + definitionReferenceId: 'defenderForSqlArcMdsql' + definitionId: '/providers/Microsoft.Authorization/policyDefinitions/65503269-6a54-4553-8a28-0065a8e6d929' + definitionParameters: varPolicySetDefinitionEsDeployMDFCDefenderSQLAMAParameters.defenderForSqlArcMdsql.parameters + definitionGroups: [] + } + { + definitionReferenceId: 'defenderForSqlArcMdsqlDcr' + definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-MDFC-Arc-Sql-DefenderSQL-DCR' + definitionParameters: varPolicySetDefinitionEsDeployMDFCDefenderSQLAMAParameters.defenderForSqlArcMdsqlDcr.parameters + definitionGroups: [] + } + { + definitionReferenceId: 'defenderForSqlMdsql' + definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-MDFC-SQL-DefenderSQL' + definitionParameters: varPolicySetDefinitionEsDeployMDFCDefenderSQLAMAParameters.defenderForSqlMdsql.parameters + definitionGroups: [] + } + { + definitionReferenceId: 'defenderForSqlMdsqlDcr' + definitionId: '${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-MDFC-SQL-DefenderSQL-DCR' + definitionParameters: varPolicySetDefinitionEsDeployMDFCDefenderSQLAMAParameters.defenderForSqlMdsqlDcr.parameters + definitionGroups: [] + } + ] + } { name: 'Deploy-Private-DNS-Zones' libSetDefinition: loadJsonContent('lib/policy_set_definitions/policy_set_definition_es_Deploy-Private-DNS-Zones.json') @@ -1318,15 +1432,15 @@ var varCustomPolicySetDefinitionsArray = [ definitionGroups: [] } { - definitionReferenceId: 'DINE-Private-DNS-Azure-Databrics-Browser-AuthN' + definitionReferenceId: 'DINE-Private-DNS-Azure-Databricks-Browser-AuthN' definitionId: '/providers/Microsoft.Authorization/policyDefinitions/0eddd7f3-3d9b-4927-a07a-806e8ac9486c' - definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-Databrics-Browser-AuthN'].parameters + definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-Databricks-Browser-AuthN'].parameters definitionGroups: [] } { - definitionReferenceId: 'DINE-Private-DNS-Azure-Databrics-UI-Api' + definitionReferenceId: 'DINE-Private-DNS-Azure-Databricks-UI-Api' definitionId: '/providers/Microsoft.Authorization/policyDefinitions/0eddd7f3-3d9b-4927-a07a-806e8ac9486c' - definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-Databrics-UI-Api'].parameters + definitionParameters: varPolicySetDefinitionEsDeployPrivateDNSZonesParameters['DINE-Private-DNS-Azure-Databricks-UI-Api'].parameters definitionGroups: [] } { @@ -1761,6 +1875,12 @@ var varCustomPolicySetDefinitionsArray = [ definitionParameters: varPolicySetDefinitionEsEnforceEncryptTransitParameters.AppServiceminTlsVersion.parameters definitionGroups: [] } + { + definitionReferenceId: 'ContainerAppsHttpsOnlyEffect' + definitionId: '/providers/Microsoft.Authorization/policyDefinitions/0e80e269-43a4-4ae9-b5bc-178126b8a5cb' + definitionParameters: varPolicySetDefinitionEsEnforceEncryptTransitParameters.ContainerAppsHttpsOnlyEffect.parameters + definitionGroups: [] + } { definitionReferenceId: 'FunctionLatestTlsEffect' definitionId: '/providers/Microsoft.Authorization/policyDefinitions/f9d614c5-c173-4d56-95a7-b4437057d193' @@ -1929,10 +2049,14 @@ var varPolicySetDefinitionEsDenyPublicPaaSEndpointsParameters = loadJsonContent( var varPolicySetDefinitionEsDenyActionDeleteProtectionParameters = loadJsonContent('lib/policy_set_definitions/policy_set_definition_es_DenyAction-DeleteProtection.parameters.json') +var varPolicySetDefinitionEsDeployAUMCheckUpdatesParameters = loadJsonContent('lib/policy_set_definitions/policy_set_definition_es_Deploy-AUM-CheckUpdates.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 varPolicySetDefinitionEsDeployMDFCDefenderSQLAMAParameters = loadJsonContent('lib/policy_set_definitions/policy_set_definition_es_Deploy-MDFC-DefenderSQL-AMA.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') @@ -1952,7 +2076,7 @@ var varPolicySetDefinitionEsEnforceGuardrailsKeyVaultParameters = loadJsonConten // Customer Usage Attribution Id var varCuaid = '2b136786-9881-412e-84ba-f4c2822e1ac9' -resource resPolicyDefinitions 'Microsoft.Authorization/policyDefinitions@2021-06-01' = [for policy in varCustomPolicyDefinitionsArray: { +resource resPolicyDefinitions 'Microsoft.Authorization/policyDefinitions@2023-04-01' = [for policy in varCustomPolicyDefinitionsArray: { name: policy.libDefinition.name properties: { description: policy.libDefinition.properties.description @@ -1965,7 +2089,7 @@ resource resPolicyDefinitions 'Microsoft.Authorization/policyDefinitions@2021-06 } }] -resource resPolicySetDefinitions 'Microsoft.Authorization/policySetDefinitions@2021-06-01' = [for policySet in varCustomPolicySetDefinitionsArray: { +resource resPolicySetDefinitions 'Microsoft.Authorization/policySetDefinitions@2023-04-01' = [for policySet in varCustomPolicySetDefinitionsArray: { dependsOn: [ resPolicyDefinitions // Must wait for policy definitons to be deployed before starting the creation of Policy Set/Initiative Defininitions ] diff --git a/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deny-MgmtPorts-From-Internet.json b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deny-MgmtPorts-From-Internet.json index 731cbbc..ecdff67 100644 --- a/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deny-MgmtPorts-From-Internet.json +++ b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deny-MgmtPorts-From-Internet.json @@ -7,9 +7,9 @@ "policyType": "Custom", "mode": "All", "displayName": "Management port access from the Internet should be blocked", - "description": "This policy denies any network security rule that allows management port access from the Internet", + "description": "This policy denies any network security rule that allows management port access from the Internet, by default blocking SSH/RDP ports.", "metadata": { - "version": "2.1.0", + "version": "2.1.1", "category": "Network", "source": "https://github.com/Azure/Enterprise-Scale/", "replacesPolicy": "Deny-RDP-From-Internet", diff --git a/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-MariaDB.json b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-MariaDB.json index 773ef7f..fb0f323 100644 --- a/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-MariaDB.json +++ b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deploy-Diagnostics-MariaDB.json @@ -6,12 +6,13 @@ "properties": { "policyType": "Custom", "mode": "Indexed", - "displayName": "Deploy Diagnostic Settings for MariaDB to Log Analytics workspace", - "description": "Deploys the diagnostic settings for MariaDB to stream to a Log Analytics workspace when any MariaDB which is missing this diagnostic settings is created or updated. The Policy will set the diagnostic with all metrics and category enabled", + "displayName": "[Deprecated] Diagnostic Settings for MariaDB to Log Analytics Workspace", + "description": "Deploys the diagnostic settings for MariaDB to stream to a Log Analytics workspace when any MariaDB which is missing this diagnostic settings is created or updated. The Policy will set the diagnostic with all metrics and category enabled. Deprecating due to service retirement, https://learn.microsoft.com/en-us/azure/mariadb/whats-happening-to-mariadb", "metadata": { - "version": "1.1.0", + "version": "1.1.0-deprecated", "category": "Monitoring", "source": "https://github.com/Azure/Enterprise-Scale/", + "deprecated": true, "alzCloudEnvironments": [ "AzureCloud", "AzureChinaCloud", diff --git a/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deploy-MDFC-Arc-SQL-DCR-Association.json b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deploy-MDFC-Arc-SQL-DCR-Association.json new file mode 100644 index 0000000..dd506c8 --- /dev/null +++ b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deploy-MDFC-Arc-SQL-DCR-Association.json @@ -0,0 +1,200 @@ +{ + "name": "Deploy-MDFC-Arc-SQL-DCR-Association", + "type": "Microsoft.Authorization/policyDefinitions", + "apiVersion": "2021-06-01", + "scope": null, + "properties": { + "policyType": "Custom", + "mode": "Indexed", + "displayName": "Configure Arc-enabled SQL Servers with Data Collection Rule Association to Microsoft Defender for SQL user-defined DCR", + "description": "Configure association between Arc-enabled SQL Servers and the Microsoft Defender for SQL user-defined DCR. Deleting this association will break the detection of security vulnerabilities for this Arc-enabled SQL Servers.", + "metadata": { + "version": "1.0.0", + "category": "Security Center", + "source": "https://github.com/Azure/Enterprise-Scale/", + "alzCloudEnvironments": [ + "AzureCloud", + "AzureChinaCloud", + "AzureUSGovernment" + ] + }, + "parameters": { + "effect": { + "type": "String", + "metadata": { + "displayName": "Effect", + "description": "Enable or disable the execution of the policy" + }, + "allowedValues": [ + "DeployIfNotExists", + "Disabled" + ], + "defaultValue": "DeployIfNotExists" + }, + "workspaceRegion": { + "type": "String", + "metadata": { + "displayName": "Workspace region", + "description": "Region of the Log Analytics workspace destination for the Data Collection Rule.", + "strongType": "location" + } + }, + "dcrName": { + "type": "String", + "metadata": { + "displayName": "Data Collection Rule Name", + "description": "Name of the Data Collection Rule." + } + }, + "dcrResourceGroup": { + "type": "String", + "metadata": { + "displayName": "Data Collection Rule Resource Group", + "description": "Resource Group of the Data Collection Rule." + } + }, + "dcrId": { + "type": "String", + "metadata": { + "displayName": "Data Collection Rule Id", + "description": "Id of the Data Collection Rule." + } + } + }, + "policyRule": { + "if": { + "allOf": [ + { + "field": "type", + "equals": "Microsoft.HybridCompute/machines" + }, + { + "field": "Microsoft.HybridCompute/machines/osName", + "equals": "Windows" + }, + { + "field": "Microsoft.HybridCompute/machines/mssqlDiscovered", + "equals": "true" + } + ] + }, + "then": { + "effect": "[parameters('effect')]", + "details": { + "type": "Microsoft.Insights/dataCollectionRuleAssociations", + "name": "MicrosoftDefenderForSQL-RulesAssociation", + "roleDefinitionIds": [ + "/providers/microsoft.authorization/roleDefinitions/749f88d5-cbae-40b8-bcfc-e573ddc772fa", + "/providers/microsoft.authorization/roleDefinitions/92aaf0da-9dab-42b6-94a3-d43ce8d16293" + ], + "deployment": { + "properties": { + "mode": "incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "resourceGroup": { + "type": "string" + }, + "vmName": { + "type": "string" + }, + "workspaceRegion": { + "type": "string" + }, + "dcrName": { + "type": "string" + }, + "dcrResourceGroup": { + "type": "string" + }, + "dcrId": { + "type": "string" + } + }, + "variables": { + "locationLongNameToShortMap": { + "australiacentral": "CAU", + "australiaeast": "EAU", + "australiasoutheast": "SEAU", + "brazilsouth": "CQ", + "canadacentral": "CCA", + "canadaeast": "CCA", + "centralindia": "CIN", + "centralus": "CUS", + "eastasia": "EA", + "eastus2euap": "eus2p", + "eastus": "EUS", + "eastus2": "EUS2", + "francecentral": "PAR", + "germanywestcentral": "DEWC", + "japaneast": "EJP", + "jioindiawest": "CIN", + "koreacentral": "SE", + "koreasouth": "SE", + "northcentralus": "NCUS", + "northeurope": "NEU", + "norwayeast": "NOE", + "southafricanorth": "JNB", + "southcentralus": "SCUS", + "southeastasia": "SEA", + "southindia": "CIN", + "swedencentral": "SEC", + "switzerlandnorth": "CHN", + "switzerlandwest": "CHW", + "uaenorth": "DXB", + "uksouth": "SUK", + "ukwest": "WUK", + "westcentralus": "WCUS", + "westeurope": "WEU", + "westindia": "CIN", + "westus": "WUS", + "westus2": "WUS2" + }, + "locationCode": "[if(contains(variables('locationLongNameToShortMap'), parameters('workspaceRegion')), variables('locationLongNameToShortMap')[parameters('workspaceRegion')], parameters('workspaceRegion'))]", + "subscriptionId": "[subscription().subscriptionId]", + "defaultRGName": "[parameters('resourceGroup')]", + "dcrName": "[parameters('dcrName')]", + "dcrId": "[parameters('dcrId')]", + "dcraName": "[concat(parameters('vmName'),'/Microsoft.Insights/MicrosoftDefenderForSQL-RulesAssociation')]" + }, + "resources": [ + { + "type": "Microsoft.HybridCompute/machines/providers/dataCollectionRuleAssociations", + "name": "[variables('dcraName')]", + "apiVersion": "2021-04-01", + "properties": { + "description": "Configure association between Arc-enabled SQL Server and the Microsoft Defender for SQL user-defined DCR. Deleting this association will break the detection of security vulnerabilities for this Arc-enabled SQL Server.", + "dataCollectionRuleId": "[variables('dcrId')]" + } + } + ] + }, + "parameters": { + "resourceGroup": { + "value": "[parameters('dcrResourceGroup')]" + }, + "vmName": { + "value": "[field('name')]" + }, + "workspaceRegion": { + "value": "[parameters('workspaceRegion')]" + }, + "dcrName": { + "value": "[parameters('dcrName')]" + }, + "dcrResourceGroup": { + "value": "[parameters('dcrResourceGroup')]" + }, + "dcrId": { + "value": "[parameters('dcrId')]" + } + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deploy-MDFC-Arc-Sql-DefenderSQL-DCR.json b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deploy-MDFC-Arc-Sql-DefenderSQL-DCR.json new file mode 100644 index 0000000..c4aa4fd --- /dev/null +++ b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deploy-MDFC-Arc-Sql-DefenderSQL-DCR.json @@ -0,0 +1,404 @@ +{ + "name": "Deploy-MDFC-Arc-Sql-DefenderSQL-DCR", + "type": "Microsoft.Authorization/policyDefinitions", + "apiVersion": "2021-06-01", + "scope": null, + "properties": { + "policyType": "Custom", + "mode": "Indexed", + "displayName": "Configure Arc-enabled SQL Servers to automatically install Microsoft Defender for SQL and DCR with a user-defined LA workspace", + "description": "Microsoft Defender for SQL collects events from the agent and uses them to provide security alerts and tailored hardening tasks (recommendations). Create a resource group and a Data Collection Rule in the same region as the user-defined Log Analytics workspace.", + "metadata": { + "version": "1.0.0", + "category": "Security Center", + "source": "https://github.com/Azure/Enterprise-Scale/", + "alzCloudEnvironments": [ + "AzureCloud", + "AzureChinaCloud", + "AzureUSGovernment" + ] + }, + "parameters": { + "effect": { + "type": "String", + "metadata": { + "displayName": "Effect", + "description": "Enable or disable the execution of the policy" + }, + "allowedValues": [ + "DeployIfNotExists", + "Disabled" + ], + "defaultValue": "DeployIfNotExists" + }, + "userWorkspaceResourceId": { + "type": "String", + "metadata": { + "displayName": "Workspace Resource Id", + "description": "Workspace resource Id of the Log Analytics workspace destination for the Data Collection Rule.", + "strongType": "omsWorkspace" + } + }, + "workspaceRegion": { + "type": "String", + "metadata": { + "displayName": "Workspace region", + "description": "Region of the Log Analytics workspace destination for the Data Collection Rule.", + "strongType": "location" + } + }, + "enableCollectionOfSqlQueriesForSecurityResearch": { + "type": "Boolean", + "metadata": { + "displayName": "Enable collection of SQL queries for security research", + "description": "Enable or disable the collection of SQL queries for security research." + }, + "allowedValues": [ + true, + false + ], + "defaultValue": false + }, + "dcrName": { + "type": "String", + "metadata": { + "displayName": "Data Collection Rule Name", + "description": "Name of the Data Collection Rule." + } + }, + "dcrResourceGroup": { + "type": "String", + "metadata": { + "displayName": "Data Collection Rule Resource Group", + "description": "Resource Group of the Data Collection Rule." + } + }, + "dcrId": { + "type": "String", + "metadata": { + "displayName": "Data Collection Rule Id", + "description": "Id of the Data Collection Rule." + } + } + }, + "policyRule": { + "if": { + "allOf": [ + { + "field": "type", + "equals": "Microsoft.HybridCompute/machines" + }, + { + "field": "Microsoft.HybridCompute/machines/osName", + "equals": "Windows" + }, + { + "field": "Microsoft.HybridCompute/machines/mssqlDiscovered", + "equals": "true" + } + ] + }, + "then": { + "effect": "[parameters('effect')]", + "details": { + "type": "Microsoft.Insights/dataCollectionRules", + "deploymentScope": "subscription", + "roleDefinitionIds": [ + "/providers/microsoft.authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c" + ], + "existenceScope": "subscription", + "existenceCondition": { + "allOf": [ + { + "field": "location", + "equals": "[parameters('workspaceRegion')]" + }, + { + "field": "name", + "equals": "[parameters('dcrName')]" + } + ] + }, + "deployment": { + "location": "eastus", + "properties": { + "mode": "incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "resourceGroup": { + "type": "string" + }, + "vmName": { + "type": "string" + }, + "userWorkspaceResourceId": { + "type": "string" + }, + "workspaceRegion": { + "type": "string" + }, + "enableCollectionOfSqlQueriesForSecurityResearch": { + "type": "bool" + }, + "dcrName": { + "type": "string" + }, + "dcrResourceGroup": { + "type": "string" + }, + "dcrId": { + "type": "string" + } + }, + "variables": { + "locationLongNameToShortMap": { + "australiacentral": "CAU", + "australiaeast": "EAU", + "australiasoutheast": "SEAU", + "brazilsouth": "CQ", + "canadacentral": "CCA", + "canadaeast": "CCA", + "centralindia": "CIN", + "centralus": "CUS", + "eastasia": "EA", + "eastus2euap": "eus2p", + "eastus": "EUS", + "eastus2": "EUS2", + "francecentral": "PAR", + "germanywestcentral": "DEWC", + "japaneast": "EJP", + "jioindiawest": "CIN", + "koreacentral": "SE", + "koreasouth": "SE", + "northcentralus": "NCUS", + "northeurope": "NEU", + "norwayeast": "NOE", + "southafricanorth": "JNB", + "southcentralus": "SCUS", + "southeastasia": "SEA", + "southindia": "CIN", + "swedencentral": "SEC", + "switzerlandnorth": "CHN", + "switzerlandwest": "CHW", + "uaenorth": "DXB", + "uksouth": "SUK", + "ukwest": "WUK", + "westcentralus": "WCUS", + "westeurope": "WEU", + "westindia": "CIN", + "westus": "WUS", + "westus2": "WUS2" + }, + "locationCode": "[if(contains(variables('locationLongNameToShortMap'), parameters('workspaceRegion')), variables('locationLongNameToShortMap')[parameters('workspaceRegion')], parameters('workspaceRegion'))]", + "subscriptionId": "[subscription().subscriptionId]", + "defaultRGName": "[parameters('resourceGroup')]", + "defaultRGLocation": "[parameters('workspaceRegion')]", + "dcrName": "[parameters('dcrName')]", + "dcrId": "[parameters('dcrId')]", + "dcraName": "[concat(parameters('vmName'),'/Microsoft.Insights/MicrosoftDefenderForSQL-RulesAssociation')]", + "deployDataCollectionRules": "[concat('deployDataCollectionRules-', uniqueString(deployment().name))]", + "deployDataCollectionRulesAssociation": "[concat('deployDataCollectionRulesAssociation-', uniqueString(deployment().name))]" + }, + "resources": [ + { + "condition": "[empty(parameters('dcrResourceGroup'))]", + "type": "Microsoft.Resources/resourceGroups", + "name": "[variables('defaultRGName')]", + "apiVersion": "2022-09-01", + "location": "[variables('defaultRGLocation')]", + "tags": { + "createdBy": "MicrosoftDefenderForSQL" + } + }, + { + "condition": "[empty(parameters('dcrId'))]", + "type": "Microsoft.Resources/deployments", + "name": "[variables('deployDataCollectionRules')]", + "apiVersion": "2022-09-01", + "resourceGroup": "[variables('defaultRGName')]", + "dependsOn": [ + "[variables('defaultRGName')]" + ], + "properties": { + "mode": "Incremental", + "expressionEvaluationOptions": { + "scope": "inner" + }, + "parameters": { + "defaultRGLocation": { + "value": "[variables('defaultRGLocation')]" + }, + "workspaceResourceId": { + "value": "[parameters('userWorkspaceResourceId')]" + }, + "dcrName": { + "value": "[variables('dcrName')]" + }, + "dcrId": { + "value": "[variables('dcrId')]" + }, + "enableCollectionOfSqlQueriesForSecurityResearch": { + "value": "[parameters('enableCollectionOfSqlQueriesForSecurityResearch')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "defaultRGLocation": { + "type": "string" + }, + "workspaceResourceId": { + "type": "string" + }, + "dcrName": { + "type": "string" + }, + "dcrId": { + "type": "string" + }, + "enableCollectionOfSqlQueriesForSecurityResearch": { + "type": "bool" + } + }, + "variables": {}, + "resources": [ + { + "type": "Microsoft.Insights/dataCollectionRules", + "name": "[parameters('dcrName')]", + "apiVersion": "2021-04-01", + "location": "[parameters('defaultRGLocation')]", + "tags": { + "createdBy": "MicrosoftDefenderForSQL" + }, + "properties": { + "description": "Data collection rule for Microsoft Defender for SQL. Deleting this rule will break the detection of security vulnerabilities.", + "dataSources": { + "extensions": [ + { + "extensionName": "MicrosoftDefenderForSQL", + "name": "MicrosoftDefenderForSQL", + "streams": [ + "Microsoft-DefenderForSqlAlerts", + "Microsoft-DefenderForSqlLogins", + "Microsoft-DefenderForSqlTelemetry", + "Microsoft-DefenderForSqlScanEvents", + "Microsoft-DefenderForSqlScanResults" + ], + "extensionSettings": { + "enableCollectionOfSqlQueriesForSecurityResearch": "[parameters('enableCollectionOfSqlQueriesForSecurityResearch')]" + } + } + ] + }, + "destinations": { + "logAnalytics": [ + { + "workspaceResourceId": "[parameters('workspaceResourceId')]", + "name": "LogAnalyticsDest" + } + ] + }, + "dataFlows": [ + { + "streams": [ + "Microsoft-DefenderForSqlAlerts", + "Microsoft-DefenderForSqlLogins", + "Microsoft-DefenderForSqlTelemetry", + "Microsoft-DefenderForSqlScanEvents", + "Microsoft-DefenderForSqlScanResults" + ], + "destinations": [ + "LogAnalyticsDest" + ] + } + ] + } + } + ] + } + } + }, + { + "type": "Microsoft.Resources/deployments", + "name": "[variables('deployDataCollectionRulesAssociation')]", + "apiVersion": "2022-09-01", + "resourceGroup": "[parameters('resourceGroup')]", + "dependsOn": [ + "[variables('deployDataCollectionRules')]" + ], + "properties": { + "mode": "Incremental", + "expressionEvaluationOptions": { + "scope": "inner" + }, + "parameters": { + "dcrId": { + "value": "[variables('dcrId')]" + }, + "dcraName": { + "value": "[variables('dcraName')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "dcrId": { + "type": "string" + }, + "dcraName": { + "type": "string" + } + }, + "resources": [ + { + "type": "Microsoft.HybridCompute/machines/providers/dataCollectionRuleAssociations", + "name": "[parameters('dcraName')]", + "apiVersion": "2021-04-01", + "properties": { + "description": "Configure association between Arc-enabled SQL Server and the Microsoft Defender for SQL user-defined DCR. Deleting this association will break the detection of security vulnerabilities for this Arc-enabled SQL Server.", + "dataCollectionRuleId": "[parameters('dcrId')]" + } + } + ] + } + } + } + ] + }, + "parameters": { + "resourceGroup": { + "value": "[parameters('dcrResourceGroup')]" + }, + "vmName": { + "value": "[field('name')]" + }, + "userWorkspaceResourceId": { + "value": "[parameters('userWorkspaceResourceId')]" + }, + "workspaceRegion": { + "value": "[parameters('workspaceRegion')]" + }, + "enableCollectionOfSqlQueriesForSecurityResearch": { + "value": "[parameters('enableCollectionOfSqlQueriesForSecurityResearch')]" + }, + "dcrName": { + "value": "[parameters('dcrName')]" + }, + "dcrResourceGroup": { + "value": "[parameters('dcrResourceGroup')]" + }, + "dcrId": { + "value": "[parameters('dcrId')]" + } + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deploy-MDFC-SQL-AMA.json b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deploy-MDFC-SQL-AMA.json new file mode 100644 index 0000000..fec4492 --- /dev/null +++ b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deploy-MDFC-SQL-AMA.json @@ -0,0 +1,175 @@ +{ + "name": "Deploy-MDFC-SQL-AMA", + "type": "Microsoft.Authorization/policyDefinitions", + "apiVersion": "2021-06-01", + "scope": null, + "properties": { + "policyType": "Custom", + "mode": "Indexed", + "displayName": "Configure SQL Virtual Machines to automatically install Azure Monitor Agent", + "description": "Automate the deployment of Azure Monitor Agent extension on your Windows SQL Virtual Machines. Learn more: https://aka.ms/AMAOverview.", + "metadata": { + "version": "1.0.0", + "category": "Security Center", + "source": "https://github.com/Azure/Enterprise-Scale/", + "alzCloudEnvironments": [ + "AzureCloud", + "AzureChinaCloud", + "AzureUSGovernment" + ] + }, + "parameters": { + "effect": { + "type": "String", + "metadata": { + "displayName": "Effect", + "description": "Enable or disable the execution of the policy" + }, + "allowedValues": [ + "DeployIfNotExists", + "Disabled" + ], + "defaultValue": "DeployIfNotExists" + }, + "identityResourceGroup": { + "type": "String", + "metadata": { + "displayName": "Identity Resource Group", + "description": "The name of the resource group created by the policy." + }, + "defaultValue": "" + }, + "userAssignedIdentityName": { + "type": "String", + "metadata": { + "displayName": "User Assigned Managed Identity Name", + "description": "The name of the user assigned managed identity." + }, + "defaultValue": "" + } + }, + "policyRule": { + "if": { + "allOf": [ + { + "field": "type", + "equals": "Microsoft.Compute/virtualMachines" + }, + { + "field": "Microsoft.Compute/virtualMachines/storageProfile.osDisk.osType", + "like": "Windows*" + }, + { + "field": "Microsoft.Compute/imagePublisher", + "equals": "microsoftsqlserver" + } + ] + }, + "then": { + "effect": "[parameters('effect')]", + "details": { + "type": "Microsoft.Compute/virtualMachines/extensions", + "evaluationDelay": "AfterProvisioning", + "roleDefinitionIds": [ + "/providers/microsoft.authorization/roleDefinitions/9980e02c-c2be-4d73-94e8-173b1dc7cf3c" + ], + "name": "[concat(field('fullName'), '/AzureMonitorWindowsAgent')]", + "existenceCondition": { + "allOf": [ + { + "field": "Microsoft.Compute/virtualMachines/extensions/type", + "equals": "AzureMonitorWindowsAgent" + }, + { + "field": "Microsoft.Compute/virtualMachines/extensions/publisher", + "equals": "Microsoft.Azure.Monitor" + }, + { + "field": "Microsoft.Compute/virtualMachines/extensions/provisioningState", + "in": [ + "Succeeded", + "Provisioning succeeded" + ] + } + ] + }, + "deployment": { + "properties": { + "mode": "incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "vmName": { + "type": "string" + }, + "location": { + "type": "string" + }, + "userAssignedManagedIdentity": { + "type": "string" + }, + "userAssignedIdentityName": { + "type": "string" + }, + "identityResourceGroup": { + "type": "string" + } + }, + "variables": { + "extensionName": "AzureMonitorWindowsAgent", + "extensionPublisher": "Microsoft.Azure.Monitor", + "extensionType": "AzureMonitorWindowsAgent", + "extensionTypeHandlerVersion": "1.2" + }, + "resources": [ + { + "name": "[concat(parameters('vmName'), '/', variables('extensionName'))]", + "type": "Microsoft.Compute/virtualMachines/extensions", + "location": "[parameters('location')]", + "tags": { + "createdBy": "MicrosoftDefenderForSQL" + }, + "apiVersion": "2023-03-01", + "properties": { + "publisher": "[variables('extensionPublisher')]", + "type": "[variables('extensionType')]", + "typeHandlerVersion": "[variables('extensionTypeHandlerVersion')]", + "autoUpgradeMinorVersion": true, + "enableAutomaticUpgrade": true, + "settings": { + "authentication": { + "managedIdentity": { + "identifier-name": "mi_res_id", + "identifier-value": "[parameters('userAssignedManagedIdentity')]" + } + } + } + } + } + ] + }, + "parameters": { + "vmName": { + "value": "[field('name')]" + }, + "location": { + "value": "[field('location')]" + }, + "userAssignedManagedIdentity": { + "value": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', trim(parameters('identityResourceGroup')), '/providers/Microsoft.ManagedIdentity/userAssignedIdentities/', trim(parameters('userAssignedIdentityName')))]" + }, + "userAssignedIdentityName": { + "value": "[parameters('userAssignedIdentityName')]" + }, + "identityResourceGroup": { + "value": "[parameters('identityResourceGroup')]" + } + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deploy-MDFC-SQL-DefenderSQL-DCR.json b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deploy-MDFC-SQL-DefenderSQL-DCR.json new file mode 100644 index 0000000..b683aff --- /dev/null +++ b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deploy-MDFC-SQL-DefenderSQL-DCR.json @@ -0,0 +1,463 @@ +{ + "name": "Deploy-MDFC-SQL-DefenderSQL-DCR", + "type": "Microsoft.Authorization/policyDefinitions", + "apiVersion": "2021-06-01", + "scope": null, + "properties": { + "policyType": "Custom", + "mode": "Indexed", + "displayName": "Configure SQL Virtual Machines to automatically install Microsoft Defender for SQL and DCR with a user-defined LA workspace", + "description": "Microsoft Defender for SQL collects events from the agent and uses them to provide security alerts and tailored hardening tasks (recommendations). Create a resource group and a Data Collection Rule in the same region as the user-defined Log Analytics workspace.", + "metadata": { + "version": "1.0.1", + "category": "Security Center", + "source": "https://github.com/Azure/Enterprise-Scale/", + "alzCloudEnvironments": [ + "AzureCloud", + "AzureChinaCloud", + "AzureUSGovernment" + ] + }, + "parameters": { + "effect": { + "type": "String", + "metadata": { + "displayName": "Effect", + "description": "Enable or disable the execution of the policy" + }, + "allowedValues": [ + "DeployIfNotExists", + "Disabled" + ], + "defaultValue": "DeployIfNotExists" + }, + "userWorkspaceResourceId": { + "type": "String", + "metadata": { + "displayName": "Workspace Resource Id", + "description": "Workspace resource Id of the Log Analytics workspace destination for the Data Collection Rule.", + "strongType": "omsWorkspace" + } + }, + "workspaceRegion": { + "type": "String", + "metadata": { + "displayName": "Workspace region", + "description": "Region of the Log Analytics workspace destination for the Data Collection Rule.", + "strongType": "location" + } + }, + "enableCollectionOfSqlQueriesForSecurityResearch": { + "type": "Boolean", + "metadata": { + "displayName": "Enable collection of SQL queries for security research", + "description": "Enable or disable the collection of SQL queries for security research." + }, + "allowedValues": [ + true, + false + ], + "defaultValue": false + }, + "dcrName": { + "type": "String", + "metadata": { + "displayName": "Data Collection Rule Name", + "description": "Name of the Data Collection Rule." + } + }, + "dcrResourceGroup": { + "type": "String", + "metadata": { + "displayName": "Data Collection Rule Resource Group", + "description": "Resource Group of the Data Collection Rule." + } + }, + "dcrId": { + "type": "String", + "metadata": { + "displayName": "Data Collection Rule Id", + "description": "Id of the Data Collection Rule." + } + } + }, + "policyRule": { + "if": { + "allOf": [ + { + "field": "type", + "equals": "Microsoft.Compute/virtualMachines" + }, + { + "field": "Microsoft.Compute/virtualMachines/storageProfile.osDisk.osType", + "like": "Windows*" + }, + { + "field": "Microsoft.Compute/imagePublisher", + "equals": "microsoftsqlserver" + } + ] + }, + "then": { + "effect": "[parameters('effect')]", + "details": { + "type": "Microsoft.Insights/dataCollectionRules", + "evaluationDelay": "AfterProvisioning", + "deploymentScope": "subscription", + "roleDefinitionIds": [ + "/providers/microsoft.authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c" + ], + "existenceScope": "subscription", + "existenceCondition": { + "allOf": [ + { + "field": "location", + "equals": "[parameters('workspaceRegion')]" + }, + { + "field": "name", + "equals": "[parameters('dcrName')]" + } + ] + }, + "deployment": { + "location": "eastus", + "properties": { + "mode": "incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "resourceGroup": { + "type": "string" + }, + "location": { + "type": "string" + }, + "vmName": { + "type": "string" + }, + "userWorkspaceResourceId": { + "type": "string" + }, + "workspaceRegion": { + "type": "string" + }, + "enableCollectionOfSqlQueriesForSecurityResearch": { + "type": "bool" + }, + "dcrName": { + "type": "string" + }, + "dcrResourceGroup": { + "type": "string" + }, + "dcrId": { + "type": "string" + } + }, + "variables": { + "locationLongNameToShortMap": { + "australiacentral": "CAU", + "australiaeast": "EAU", + "australiasoutheast": "SEAU", + "brazilsouth": "CQ", + "canadacentral": "CCA", + "canadaeast": "CCA", + "centralindia": "CIN", + "centralus": "CUS", + "eastasia": "EA", + "eastus2euap": "eus2p", + "eastus": "EUS", + "eastus2": "EUS2", + "francecentral": "PAR", + "germanywestcentral": "DEWC", + "japaneast": "EJP", + "jioindiawest": "CIN", + "koreacentral": "SE", + "koreasouth": "SE", + "northcentralus": "NCUS", + "northeurope": "NEU", + "norwayeast": "NOE", + "southafricanorth": "JNB", + "southcentralus": "SCUS", + "southeastasia": "SEA", + "southindia": "CIN", + "swedencentral": "SEC", + "switzerlandnorth": "CHN", + "switzerlandwest": "CHW", + "uaenorth": "DXB", + "uksouth": "SUK", + "ukwest": "WUK", + "westcentralus": "WCUS", + "westeurope": "WEU", + "westindia": "CIN", + "westus": "WUS", + "westus2": "WUS2" + }, + "locationCode": "[if(contains(variables('locationLongNameToShortMap'), parameters('workspaceRegion')), variables('locationLongNameToShortMap')[parameters('workspaceRegion')], parameters('workspaceRegion'))]", + "subscriptionId": "[subscription().subscriptionId]", + "defaultRGName": "[parameters('dcrResourceGroup')]", + "defaultRGLocation": "[parameters('workspaceRegion')]", + "dcrName": "[parameters('dcrName')]", + "dcrId": "[parameters('dcrId')]", + "dcraName": "[concat(parameters('vmName'),'/Microsoft.Insights/MicrosoftDefenderForSQL-RulesAssociation')]", + "deployDataCollectionRules": "[concat('deployDataCollectionRules-', uniqueString(deployment().name))]", + "deployDataCollectionRulesAssociation": "[concat('deployDataCollectionRulesAssociation-', uniqueString(deployment().name))]", + "deployDefenderForSQL": "[concat('deployDefenderForSQL-', uniqueString(deployment().name))]" + }, + "resources": [ + { + "condition": "[empty(parameters('dcrResourceGroup'))]", + "type": "Microsoft.Resources/resourceGroups", + "name": "[variables('defaultRGName')]", + "apiVersion": "2022-09-01", + "location": "[variables('defaultRGLocation')]", + "tags": { + "createdBy": "MicrosoftDefenderForSQL" + } + }, + { + "type": "Microsoft.Resources/deployments", + "name": "[variables('deployDefenderForSQL')]", + "apiVersion": "2022-09-01", + "resourceGroup": "[parameters('resourceGroup')]", + "properties": { + "mode": "Incremental", + "expressionEvaluationOptions": { + "scope": "inner" + }, + "parameters": { + "location": { + "value": "[parameters('location')]" + }, + "vmName": { + "value": "[parameters('vmName')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "location": { + "type": "string" + }, + "vmName": { + "type": "string" + } + }, + "variables": {}, + "resources": [ + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "name": "[concat(parameters('vmName'), '/', 'MicrosoftDefenderForSQL')]", + "apiVersion": "2023-03-01", + "location": "[parameters('location')]", + "tags": { + "createdBy": "MicrosoftDefenderForSQL" + }, + "properties": { + "publisher": "Microsoft.Azure.AzureDefenderForSQL", + "type": "AdvancedThreatProtection.Windows", + "typeHandlerVersion": "2.0", + "autoUpgradeMinorVersion": true, + "enableAutomaticUpgrade": true + } + } + ] + } + } + }, + { + "condition": "[empty(parameters('dcrId'))]", + "type": "Microsoft.Resources/deployments", + "name": "[variables('deployDataCollectionRules')]", + "apiVersion": "2022-09-01", + "resourceGroup": "[variables('defaultRGName')]", + "dependsOn": [ + "[variables('defaultRGName')]" + ], + "properties": { + "mode": "Incremental", + "expressionEvaluationOptions": { + "scope": "inner" + }, + "parameters": { + "defaultRGLocation": { + "value": "[variables('defaultRGLocation')]" + }, + "workspaceResourceId": { + "value": "[parameters('userWorkspaceResourceId')]" + }, + "dcrName": { + "value": "[variables('dcrName')]" + }, + "dcrId": { + "value": "[variables('dcrId')]" + }, + "enableCollectionOfSqlQueriesForSecurityResearch": { + "value": "[parameters('enableCollectionOfSqlQueriesForSecurityResearch')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "defaultRGLocation": { + "type": "string" + }, + "workspaceResourceId": { + "type": "string" + }, + "dcrName": { + "type": "string" + }, + "dcrId": { + "type": "string" + }, + "enableCollectionOfSqlQueriesForSecurityResearch": { + "type": "bool" + } + }, + "variables": {}, + "resources": [ + { + "type": "Microsoft.Insights/dataCollectionRules", + "name": "[parameters('dcrName')]", + "apiVersion": "2021-04-01", + "location": "[parameters('defaultRGLocation')]", + "tags": { + "createdBy": "MicrosoftDefenderForSQL" + }, + "properties": { + "description": "Data collection rule for Microsoft Defender for SQL. Deleting this rule will break the detection of security vulnerabilities.", + "dataSources": { + "extensions": [ + { + "extensionName": "MicrosoftDefenderForSQL", + "name": "MicrosoftDefenderForSQL", + "streams": [ + "Microsoft-DefenderForSqlAlerts", + "Microsoft-DefenderForSqlLogins", + "Microsoft-DefenderForSqlTelemetry", + "Microsoft-DefenderForSqlScanEvents", + "Microsoft-DefenderForSqlScanResults" + ], + "extensionSettings": { + "enableCollectionOfSqlQueriesForSecurityResearch": "[parameters('enableCollectionOfSqlQueriesForSecurityResearch')]" + } + } + ] + }, + "destinations": { + "logAnalytics": [ + { + "workspaceResourceId": "[parameters('workspaceResourceId')]", + "name": "LogAnalyticsDest" + } + ] + }, + "dataFlows": [ + { + "streams": [ + "Microsoft-DefenderForSqlAlerts", + "Microsoft-DefenderForSqlLogins", + "Microsoft-DefenderForSqlTelemetry", + "Microsoft-DefenderForSqlScanEvents", + "Microsoft-DefenderForSqlScanResults" + ], + "destinations": [ + "LogAnalyticsDest" + ] + } + ] + } + } + ] + } + } + }, + { + "type": "Microsoft.Resources/deployments", + "name": "[variables('deployDataCollectionRulesAssociation')]", + "apiVersion": "2022-09-01", + "resourceGroup": "[parameters('resourceGroup')]", + "dependsOn": [ + "[variables('deployDataCollectionRules')]" + ], + "properties": { + "mode": "Incremental", + "expressionEvaluationOptions": { + "scope": "inner" + }, + "parameters": { + "dcrId": { + "value": "[variables('dcrId')]" + }, + "dcraName": { + "value": "[variables('dcraName')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "dcrId": { + "type": "string" + }, + "dcraName": { + "type": "string" + } + }, + "resources": [ + { + "type": "Microsoft.Compute/virtualMachines/providers/dataCollectionRuleAssociations", + "name": "[parameters('dcraName')]", + "apiVersion": "2021-04-01", + "properties": { + "description": "Configure association between SQL Virtual Machine and the Microsoft Defender for SQL user-defined DCR. Deleting this association will break the detection of security vulnerabilities for this SQL Virtual Machine.", + "dataCollectionRuleId": "[parameters('dcrId')]" + } + } + ] + } + } + } + ] + }, + "parameters": { + "resourceGroup": { + "value": "[resourceGroup().name]" + }, + "location": { + "value": "[field('location')]" + }, + "vmName": { + "value": "[field('name')]" + }, + "userWorkspaceResourceId": { + "value": "[parameters('userWorkspaceResourceId')]" + }, + "workspaceRegion": { + "value": "[parameters('workspaceRegion')]" + }, + "enableCollectionOfSqlQueriesForSecurityResearch": { + "value": "[parameters('enableCollectionOfSqlQueriesForSecurityResearch')]" + }, + "dcrName": { + "value": "[parameters('dcrName')]" + }, + "dcrResourceGroup": { + "value": "[parameters('dcrResourceGroup')]" + }, + "dcrId": { + "value": "[parameters('dcrId')]" + } + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deploy-MDFC-SQL-DefenderSQL.json b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deploy-MDFC-SQL-DefenderSQL.json new file mode 100644 index 0000000..6ee701b --- /dev/null +++ b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deploy-MDFC-SQL-DefenderSQL.json @@ -0,0 +1,240 @@ +{ + "name": "Deploy-MDFC-SQL-DefenderSQL", + "type": "Microsoft.Authorization/policyDefinitions", + "apiVersion": "2021-06-01", + "scope": null, + "properties": { + "policyType": "Custom", + "mode": "Indexed", + "displayName": "Configure SQL Virtual Machines to automatically install Microsoft Defender for SQL", + "description": "Configure Windows SQL Virtual Machines to automatically install the Microsoft Defender for SQL extension. Microsoft Defender for SQL collects events from the agent and uses them to provide security alerts and tailored hardening tasks (recommendations).", + "metadata": { + "version": "1.0.0", + "category": "Security Center", + "source": "https://github.com/Azure/Enterprise-Scale/", + "alzCloudEnvironments": [ + "AzureCloud", + "AzureChinaCloud", + "AzureUSGovernment" + ] + }, + "parameters": { + "effect": { + "type": "String", + "metadata": { + "displayName": "Effect", + "description": "Enable or disable the execution of the policy" + }, + "allowedValues": [ + "DeployIfNotExists", + "Disabled" + ], + "defaultValue": "DeployIfNotExists" + }, + "workspaceRegion": { + "type": "String", + "metadata": { + "displayName": "Workspace region", + "description": "Region of the Log Analytics workspace destination for the Data Collection Rule.", + "strongType": "location" + } + }, + "dcrName": { + "type": "String", + "metadata": { + "displayName": "Data Collection Rule Name", + "description": "Name of the Data Collection Rule." + } + }, + "dcrResourceGroup": { + "type": "String", + "metadata": { + "displayName": "Data Collection Rule Resource Group", + "description": "Resource Group of the Data Collection Rule." + } + }, + "dcrId": { + "type": "String", + "metadata": { + "displayName": "Data Collection Rule Id", + "description": "Id of the Data Collection Rule." + } + } + }, + "policyRule": { + "if": { + "allOf": [ + { + "field": "type", + "equals": "Microsoft.Compute/virtualMachines" + }, + { + "field": "Microsoft.Compute/virtualMachines/storageProfile.osDisk.osType", + "like": "Windows*" + }, + { + "field": "Microsoft.Compute/imagePublisher", + "equals": "microsoftsqlserver" + } + ] + }, + "then": { + "effect": "[parameters('effect')]", + "details": { + "type": "Microsoft.Compute/virtualMachines/extensions", + "name": "[concat(field('fullName'), '/MicrosoftDefenderForSQL')]", + "evaluationDelay": "AfterProvisioning", + "existenceCondition": { + "allOf": [ + { + "field": "Microsoft.Compute/virtualMachines/extensions/type", + "equals": "AdvancedThreatProtection.Windows" + }, + { + "field": "Microsoft.Compute/virtualMachines/extensions/publisher", + "equals": "Microsoft.Azure.AzureDefenderForSQL" + }, + { + "field": "Microsoft.Compute/virtualMachines/extensions/provisioningState", + "in": [ + "Succeeded", + "Provisioning succeeded" + ] + } + ] + }, + "roleDefinitionIds": [ + "/providers/microsoft.authorization/roleDefinitions/749f88d5-cbae-40b8-bcfc-e573ddc772fa", + "/providers/microsoft.authorization/roleDefinitions/92aaf0da-9dab-42b6-94a3-d43ce8d16293" + ], + "deployment": { + "properties": { + "mode": "incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "location": { + "type": "string" + }, + "vmName": { + "type": "string" + }, + "workspaceRegion": { + "type": "string" + }, + "dcrResourceGroup": { + "type": "string" + }, + "dcrName": { + "type": "string" + }, + "dcrId": { + "type": "string" + } + }, + "variables": { + "locationLongNameToShortMap": { + "australiacentral": "CAU", + "australiaeast": "EAU", + "australiasoutheast": "SEAU", + "brazilsouth": "CQ", + "canadacentral": "CCA", + "canadaeast": "CCA", + "centralindia": "CIN", + "centralus": "CUS", + "eastasia": "EA", + "eastus2euap": "eus2p", + "eastus": "EUS", + "eastus2": "EUS2", + "francecentral": "PAR", + "germanywestcentral": "DEWC", + "japaneast": "EJP", + "jioindiawest": "CIN", + "koreacentral": "SE", + "koreasouth": "SE", + "northcentralus": "NCUS", + "northeurope": "NEU", + "norwayeast": "NOE", + "southafricanorth": "JNB", + "southcentralus": "SCUS", + "southeastasia": "SEA", + "southindia": "CIN", + "swedencentral": "SEC", + "switzerlandnorth": "CHN", + "switzerlandwest": "CHW", + "uaenorth": "DXB", + "uksouth": "SUK", + "ukwest": "WUK", + "westcentralus": "WCUS", + "westeurope": "WEU", + "westindia": "CIN", + "westus": "WUS", + "westus2": "WUS2" + }, + "actualLocation": "[if(empty(parameters('workspaceRegion')), parameters('location'), parameters('workspaceRegion'))]", + "locationCode": "[if(contains(variables('locationLongNameToShortMap'), variables('actualLocation')), variables('locationLongNameToShortMap')[variables('actualLocation')], variables('actualLocation'))]", + "subscriptionId": "[subscription().subscriptionId]", + "defaultRGName": "[parameters('dcrResourceGroup')]", + "dcrName": "[parameters('dcrName')]", + "dcrId": "[parameters('dcrId')]", + "dcraName": "[concat(parameters('vmName'),'/Microsoft.Insights/MicrosoftDefenderForSQL-RulesAssociation')]" + }, + "resources": [ + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "name": "[concat(parameters('vmName'), '/', 'MicrosoftDefenderForSQL')]", + "apiVersion": "2023-03-01", + "location": "[parameters('location')]", + "tags": { + "createdBy": "MicrosoftDefenderForSQL" + }, + "properties": { + "publisher": "Microsoft.Azure.AzureDefenderForSQL", + "type": "AdvancedThreatProtection.Windows", + "typeHandlerVersion": "2.0", + "autoUpgradeMinorVersion": true, + "enableAutomaticUpgrade": true + }, + "dependsOn": [ + "[extensionResourceId(concat('/subscriptions/', variables('subscriptionId'), '/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Compute/virtualMachines/', parameters('vmName')), 'Microsoft.Insights/dataCollectionRuleAssociations','MicrosoftDefenderForSQL-RulesAssociation')]" + ] + }, + { + "type": "Microsoft.Compute/virtualMachines/providers/dataCollectionRuleAssociations", + "name": "[variables('dcraName')]", + "apiVersion": "2021-04-01", + "properties": { + "description": "Configure association between SQL Virtual Machine and the Microsoft Defender for SQL DCR. Deleting this association will break the detection of security vulnerabilities for this SQL Virtual Machine.", + "dataCollectionRuleId": "[variables('dcrId')]" + } + } + ] + }, + "parameters": { + "location": { + "value": "[field('location')]" + }, + "vmName": { + "value": "[field('name')]" + }, + "workspaceRegion": { + "value": "[parameters('workspaceRegion')]" + }, + "dcrResourceGroup": { + "value": "[parameters('dcrResourceGroup')]" + }, + "dcrName": { + "value": "[parameters('dcrName')]" + }, + "dcrId": { + "value": "[parameters('dcrId')]" + } + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deploy-UserAssignedManagedIdentity-VMInsights.json b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deploy-UserAssignedManagedIdentity-VMInsights.json new file mode 100644 index 0000000..06d9b8e --- /dev/null +++ b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_definitions/policy_definition_es_Deploy-UserAssignedManagedIdentity-VMInsights.json @@ -0,0 +1,404 @@ +{ + "name": "Deploy-UserAssignedManagedIdentity-VMInsights", + "type": "Microsoft.Authorization/policyDefinitions", + "apiVersion": "2021-06-01", + "scope": null, + "properties": { + "policyType": "Custom", + "mode": "Indexed", + "displayName": "Deploy User Assigned Managed Identity for VM Insights", + "description": "Create and assign a User Assigned Managed Identity to Virtual Machines for VM Insights", + "metadata": { + "version": "1.0.0", + "category": "Managed Identity", + "source": "https://github.com/Azure/Enterprise-Scale/", + "alzCloudEnvironments": [ + "AzureCloud", + "AzureChinaCloud", + "AzureUSGovernment" + ] + }, + "parameters": { + "bringYourOwnUserAssignedManagedIdentity": { + "type": "Boolean", + "metadata": { + "displayName": "Bring Your Own User-Assigned Identity", + "description": "Enable this to use your pre-created user-assigned managed identity. The pre-created identity MUST exist within the subscription otherwise the policy deployment will fail. If enabled, ensure that the User-Assigned Identity Name and Identity Resource Group Name parameters match the pre-created identity. If not enabled, the policy will create per subscription, per resource user-assigned managed identities in a new resource group named 'Built-In-Identity-RG'." + }, + "allowedValues": [ + true, + false + ] + }, + "userAssignedIdentityName": { + "type": "String", + "metadata": { + "displayName": "User-Assigned Managed Identity Name", + "description": "The name of the pre-created user-assigned managed identity." + }, + "defaultValue": "" + }, + "identityResourceGroup": { + "type": "String", + "metadata": { + "displayName": "User-Assigned Managed Identity Resource Group Name", + "description": "The resource group in which the pre-created user-assigned managed identity resides." + }, + "defaultValue": "" + }, + "builtInIdentityResourceGroupLocation": { + "type": "String", + "metadata": { + "displayName": "Built-In-Identity-RG Location", + "description": "The location of the resource group 'Built-In-Identity-RG' created by the policy. This parameter is only used when 'Bring Your Own User Assigned Identity' parameter is false." + }, + "defaultValue": "eastus" + }, + "effect": { + "type": "String", + "metadata": { + "displayName": "Policy Effect", + "description": "The effect determines what happens when the policy rule is evaluated to match." + }, + "allowedValues": [ + "AuditIfNotExists", + "DeployIfNotExists", + "Disabled" + ], + "defaultValue": "DeployIfNotExists" + } + }, + "policyRule": { + "if": { + "allOf": [ + { + "field": "type", + "equals": "Microsoft.Compute/virtualMachines" + }, + { + "value": "[requestContext().apiVersion]", + "greaterOrEquals": "2018-10-01" + } + ] + }, + "then": { + "effect": "[parameters('effect')]", + "details": { + "type": "Microsoft.Compute/virtualMachines", + "name": "[field('name')]", + "evaluationDelay": "AfterProvisioning", + "deploymentScope": "subscription", + "existenceCondition": { + "anyOf": [ + { + "allOf": [ + { + "field": "identity.type", + "contains": "UserAssigned" + }, + { + "field": "identity.userAssignedIdentities", + "containsKey": "[if(parameters('bringYourOwnUserAssignedManagedIdentity'), concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', trim(parameters('identityResourceGroup')), '/providers/Microsoft.ManagedIdentity/userAssignedIdentities/', trim(parameters('userAssignedIdentityName'))), concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/Built-In-Identity-RG/providers/Microsoft.ManagedIdentity/userAssignedIdentities/Built-In-Identity-', field('location')))]" + } + ] + }, + { + "allOf": [ + { + "field": "identity.type", + "equals": "UserAssigned" + }, + { + "value": "[string(length(field('identity.userAssignedIdentities')))]", + "equals": "1" + } + ] + } + ] + }, + "roleDefinitionIds": [ + "/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c" + ], + "deployment": { + "location": "eastus", + "properties": { + "mode": "incremental", + "parameters": { + "bringYourOwnUserAssignedManagedIdentity": { + "value": "[parameters('bringYourOwnUserAssignedManagedIdentity')]" + }, + "location": { + "value": "[field('location')]" + }, + "uaName": { + "value": "[if(parameters('bringYourOwnUserAssignedManagedIdentity'), parameters('userAssignedIdentityName'), 'Built-In-Identity')]" + }, + "identityResourceGroup": { + "value": "[if(parameters('bringYourOwnUserAssignedManagedIdentity'), parameters('identityResourceGroup'), 'Built-In-Identity-RG')]" + }, + "builtInIdentityResourceGroupLocation": { + "value": "[parameters('builtInIdentityResourceGroupLocation')]" + }, + "vmName": { + "value": "[field('name')]" + }, + "vmResourceGroup": { + "value": "[resourceGroup().name]" + }, + "resourceId": { + "value": "[field('id')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#", + "contentVersion": "1.0.0.1", + "parameters": { + "bringYourOwnUserAssignedManagedIdentity": { + "type": "bool" + }, + "location": { + "type": "string" + }, + "uaName": { + "type": "string" + }, + "identityResourceGroup": { + "type": "string" + }, + "builtInIdentityResourceGroupLocation": { + "type": "string" + }, + "vmName": { + "type": "string" + }, + "vmResourceGroup": { + "type": "string" + }, + "resourceId": { + "type": "string" + } + }, + "variables": { + "uaNameWithLocation": "[concat(parameters('uaName'),'-', parameters('location'))]", + "precreatedUaId": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', trim(parameters('identityResourceGroup')), '/providers/Microsoft.ManagedIdentity/userAssignedIdentities/', trim(parameters('uaName')))]", + "autocreatedUaId": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', trim(parameters('identityResourceGroup')), '/providers/Microsoft.ManagedIdentity/userAssignedIdentities/', trim(parameters('uaName')), '-', parameters('location'))]", + "deployUALockName": "[concat('deployUALock-', uniqueString(deployment().name))]", + "deployUAName": "[concat('deployUA-', uniqueString(deployment().name))]", + "deployGetResourceProperties": "[concat('deployGetResourceProperties-', uniqueString(deployment().name))]", + "deployAssignUAName": "[concat('deployAssignUA-', uniqueString(deployment().name))]" + }, + "resources": [ + { + "type": "Microsoft.Resources/resourceGroups", + "apiVersion": "2020-06-01", + "name": "[parameters('identityResourceGroup')]", + "location": "[parameters('builtInIdentityResourceGroupLocation')]" + }, + { + "condition": "[parameters('bringYourOwnUserAssignedManagedIdentity')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-06-01", + "name": "[variables('deployUALockName')]", + "resourceGroup": "[parameters('identityResourceGroup')]", + "dependsOn": [ + "[resourceId('Microsoft.Resources/resourceGroups', parameters('identityResourceGroup'))]" + ], + "properties": { + "mode": "Incremental", + "expressionEvaluationOptions": { + "scope": "inner" + }, + "parameters": { + "uaName": { + "value": "[parameters('uaName')]" + }, + "location": { + "value": "[parameters('location')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "uaName": { + "type": "string" + }, + "location": { + "type": "string" + } + }, + "variables": {}, + "resources": [ + { + "type": "Microsoft.ManagedIdentity/userAssignedIdentities", + "name": "[parameters('uaName')]", + "apiVersion": "2018-11-30", + "location": "[parameters('location')]" + } + ] + } + } + }, + { + "condition": "[not(parameters('bringYourOwnUserAssignedManagedIdentity'))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-06-01", + "name": "[variables('deployUAName')]", + "resourceGroup": "[parameters('identityResourceGroup')]", + "dependsOn": [ + "[resourceId('Microsoft.Resources/resourceGroups', parameters('identityResourceGroup'))]" + ], + "properties": { + "mode": "Incremental", + "expressionEvaluationOptions": { + "scope": "inner" + }, + "parameters": { + "uaName": { + "value": "[variables('uaNameWithLocation')]" + }, + "location": { + "value": "[parameters('location')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "uaName": { + "type": "string" + }, + "location": { + "type": "string" + } + }, + "variables": {}, + "resources": [ + { + "type": "Microsoft.ManagedIdentity/userAssignedIdentities", + "name": "[parameters('uaName')]", + "apiVersion": "2018-11-30", + "location": "[parameters('location')]" + }, + { + "type": "Microsoft.ManagedIdentity/userAssignedIdentities/providers/locks", + "apiVersion": "2016-09-01", + "name": "[concat(parameters('uaName'), '/Microsoft.Authorization/', 'CanNotDeleteLock-', parameters('uaName'))]", + "dependsOn": [ + "[parameters('uaName')]" + ], + "properties": { + "level": "CanNotDelete", + "notes": "Please do not delete this User-Assigned Identity since extensions enabled by Azure Policy are relying on their existence." + } + } + ] + } + } + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-06-01", + "name": "[variables('deployGetResourceProperties')]", + "location": "[parameters('location')]", + "dependsOn": [ + "[resourceId('Microsoft.Resources/resourceGroups', parameters('identityResourceGroup'))]", + "[variables('deployUAName')]" + ], + "properties": { + "mode": "Incremental", + "template": { + "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "resource": { + "type": "object", + "value": "[reference(parameters('resourceId'), '2019-07-01', 'Full')]" + } + } + } + } + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2020-06-01", + "name": "[concat(variables('deployAssignUAName'))]", + "resourceGroup": "[parameters('vmResourceGroup')]", + "dependsOn": [ + "[resourceId('Microsoft.Resources/resourceGroups', parameters('identityResourceGroup'))]", + "[variables('deployUAName')]", + "[variables('deployGetResourceProperties')]" + ], + "properties": { + "mode": "Incremental", + "expressionEvaluationOptions": { + "scope": "inner" + }, + "parameters": { + "uaId": { + "value": "[if(parameters('bringYourOwnUserAssignedManagedIdentity'), variables('precreatedUaId'), variables('autocreatedUaId'))]" + }, + "vmName": { + "value": "[parameters('vmName')]" + }, + "location": { + "value": "[parameters('location')]" + }, + "identityType": { + "value": "[if(contains(reference(variables('deployGetResourceProperties')).outputs.resource.value, 'identity'), reference(variables('deployGetResourceProperties')).outputs.resource.value.identity.type, '')]" + }, + "userAssignedIdentities": { + "value": "[if(and(contains(reference(variables('deployGetResourceProperties')).outputs.resource.value, 'identity'), contains(reference(variables('deployGetResourceProperties')).outputs.resource.value.identity, 'userAssignedIdentities')), reference(variables('deployGetResourceProperties')).outputs.resource.value.identity.userAssignedIdentities, createObject())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "uaId": { + "type": "string" + }, + "vmName": { + "type": "string" + }, + "location": { + "type": "string" + }, + "identityType": { + "type": "string" + }, + "userAssignedIdentities": { + "type": "object" + } + }, + "variables": { + "identityTypeValue": "[if(contains(parameters('identityType'), 'SystemAssigned'), 'SystemAssigned,UserAssigned', 'UserAssigned')]", + "userAssignedIdentitiesValue": "[union(parameters('userAssignedIdentities'), createObject(parameters('uaId'), createObject()))]", + "resourceWithSingleUAI": "[and(equals(parameters('identityType'), 'UserAssigned'), equals(string(length(parameters('userAssignedIdentities'))), '1'))]" + }, + "resources": [ + { + "condition": "[not(variables('resourceWithSingleUAI'))]", + "apiVersion": "2019-07-01", + "type": "Microsoft.Compute/virtualMachines", + "name": "[parameters('vmName')]", + "location": "[parameters('location')]", + "identity": { + "type": "[variables('identityTypeValue')]", + "userAssignedIdentities": "[variables('userAssignedIdentitiesValue')]" + } + } + ] + } + } + } + ] + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deny-PublicPaaSEndpoints.json b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deny-PublicPaaSEndpoints.json index c97e68d..fa63ce3 100644 --- a/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deny-PublicPaaSEndpoints.json +++ b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deny-PublicPaaSEndpoints.json @@ -8,7 +8,7 @@ "displayName": "Public network access should be disabled for PaaS services", "description": "This policy initiative is a group of policies that prevents creation of Azure PaaS services with exposed public endpoints", "metadata": { - "version": "3.1.0", + "version": "3.2.0", "category": "Network", "source": "https://github.com/Azure/Enterprise-Scale/", "alzCloudEnvironments": [ @@ -274,6 +274,19 @@ "Disabled" ], "defaultValue": "AuditIfNotExists" + }, + "ContainerAppsEnvironmentDenyEffect": { + "type": "String", + "metadata": { + "displayName": "Container Apps environment should disable public network access", + "description": "This policy denies creation of Container Apps Environment with exposed public endpoints" + }, + "allowedValues": [ + "Audit", + "Deny", + "Disabled" + ], + "defaultValue": "Deny" } }, "policyDefinitions": [ @@ -476,6 +489,16 @@ } }, "groupNames": [] + }, + { + "policyDefinitionReferenceId": "ContainerAppsEnvironmentDenyPublicIP", + "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/d074ddf8-01a5-4b5e-a2b8-964aed452c0a", + "parameters": { + "effect": { + "value": "[[parameters('ContainerAppsEnvironmentDenyEffect')]" + } + }, + "groupNames": [] } ], "policyDefinitionGroups": null diff --git a/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deny-PublicPaaSEndpoints.parameters.json b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deny-PublicPaaSEndpoints.parameters.json index 46e51dd..19246f7 100644 --- a/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deny-PublicPaaSEndpoints.parameters.json +++ b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deny-PublicPaaSEndpoints.parameters.json @@ -69,6 +69,13 @@ } } }, + "ContainerAppsEnvironmentDenyPublicIP": { + "parameters": { + "effect": { + "value": "[[parameters('ContainerAppsEnvironmentDenyEffect')]" + } + } + }, "CosmosDenyPaasPublicIP": { "parameters": { "effect": { diff --git a/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-AUM-CheckUpdates.json b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-AUM-CheckUpdates.json new file mode 100644 index 0000000..a9cbb8e --- /dev/null +++ b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-AUM-CheckUpdates.json @@ -0,0 +1,153 @@ +{ + "name": "Deploy-AUM-CheckUpdates", + "type": "Microsoft.Authorization/policySetDefinitions", + "apiVersion": "2021-06-01", + "scope": null, + "properties": { + "policyType": "Custom", + "displayName": "Configure periodic checking for missing system updates on azure virtual machines and Arc-enabled virtual machines", + "description": "Configure auto-assessment (every 24 hours) for OS updates. You can control the scope of assignment according to machine subscription, resource group, location or tag. Learn more about this for Windows: https://aka.ms/computevm-windowspatchassessmentmode, for Linux: https://aka.ms/computevm-linuxpatchassessmentmode.", + "metadata": { + "version": "1.0.0", + "category": "Security Center", + "source": "https://github.com/Azure/Enterprise-Scale/", + "alzCloudEnvironments": [ + "AzureCloud" + ] + }, + "parameters": { + "assessmentMode": { + "type": "String", + "metadata": { + "displayName": "Assessment mode", + "description": "Assessment mode for the machines." + }, + "allowedValues": [ + "ImageDefault", + "AutomaticByPlatform" + ], + "defaultValue": "AutomaticByPlatform" + }, + "locations": { + "type": "Array", + "metadata": { + "displayName": "Machines locations", + "description": "The list of locations from which machines need to be targeted.", + "strongType": "location" + }, + "defaultValue": [] + }, + "tagValues": { + "type": "Object", + "metadata": { + "displayName": "Tags on machines", + "description": "The list of tags that need to matched for getting target machines." + }, + "defaultValue": {} + }, + "tagOperator": { + "type": "String", + "metadata": { + "displayName": "Tag operator", + "description": "Matching condition for resource tags" + }, + "allowedValues": [ + "All", + "Any" + ], + "defaultValue": "Any" + } + }, + "policyDefinitions": [ + { + "policyDefinitionReferenceId": "azureUpdateManagerVmCheckUpdateWindows", + "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/59efceea-0c96-497e-a4a1-4eb2290dac15", + "parameters": { + "assessmentMode": { + "value": "[[parameters('assessmentMode')]" + }, + "osType": { + "value": "Windows" + }, + "locations": { + "value": "[[parameters('locations')]" + }, + "tagValues": { + "value": "[[parameters('tagValues')]" + }, + "tagOperator": { + "value": "[[parameters('tagOperator')]" + } + }, + "groupNames": [] + }, + { + "policyDefinitionReferenceId": "azureUpdateManagerVmCheckUpdateLinux", + "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/59efceea-0c96-497e-a4a1-4eb2290dac15", + "parameters": { + "assessmentMode": { + "value": "[[parameters('assessmentMode')]" + }, + "osType": { + "value": "Linux" + }, + "locations": { + "value": "[[parameters('locations')]" + }, + "tagValues": { + "value": "[[parameters('tagValues')]" + }, + "tagOperator": { + "value": "[[parameters('tagOperator')]" + } + }, + "groupNames": [] + }, + { + "policyDefinitionReferenceId": "azureUpdateManagerVmArcCheckUpdateWindows", + "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/bfea026e-043f-4ff4-9d1b-bf301ca7ff46", + "parameters": { + "assessmentMode": { + "value": "[[parameters('assessmentMode')]" + }, + "osType": { + "value": "Windows" + }, + "locations": { + "value": "[[parameters('locations')]" + }, + "tagValues": { + "value": "[[parameters('tagValues')]" + }, + "tagOperator": { + "value": "[[parameters('tagOperator')]" + } + }, + "groupNames": [] + }, + { + "policyDefinitionReferenceId": "azureUpdateManagerVmArcCheckUpdateLinux", + "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/bfea026e-043f-4ff4-9d1b-bf301ca7ff46", + "parameters": { + "assessmentMode": { + "value": "[[parameters('assessmentMode')]" + }, + "osType": { + "value": "Linux" + }, + "locations": { + "value": "[[parameters('locations')]" + }, + "tagValues": { + "value": "[[parameters('tagValues')]" + }, + "tagOperator": { + "value": "[[parameters('tagOperator')]" + } + }, + "groupNames": [] + } + ], + "policyDefinitionGroups": null + } +} \ No newline at end of file diff --git a/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-AUM-CheckUpdates.parameters.json b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-AUM-CheckUpdates.parameters.json new file mode 100644 index 0000000..d303c59 --- /dev/null +++ b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-AUM-CheckUpdates.parameters.json @@ -0,0 +1,78 @@ +{ + "azureUpdateManagerVmArcCheckUpdateLinux": { + "parameters": { + "assessmentMode": { + "value": "[[parameters('assessmentMode')]" + }, + "osType": { + "value": "Linux" + }, + "locations": { + "value": "[[parameters('locations')]" + }, + "tagValues": { + "value": "[[parameters('tagValues')]" + }, + "tagOperator": { + "value": "[[parameters('tagOperator')]" + } + } + }, + "azureUpdateManagerVmArcCheckUpdateWindows": { + "parameters": { + "assessmentMode": { + "value": "[[parameters('assessmentMode')]" + }, + "osType": { + "value": "Windows" + }, + "locations": { + "value": "[[parameters('locations')]" + }, + "tagValues": { + "value": "[[parameters('tagValues')]" + }, + "tagOperator": { + "value": "[[parameters('tagOperator')]" + } + } + }, + "azureUpdateManagerVmCheckUpdateLinux": { + "parameters": { + "assessmentMode": { + "value": "[[parameters('assessmentMode')]" + }, + "osType": { + "value": "Linux" + }, + "locations": { + "value": "[[parameters('locations')]" + }, + "tagValues": { + "value": "[[parameters('tagValues')]" + }, + "tagOperator": { + "value": "[[parameters('tagOperator')]" + } + } + }, + "azureUpdateManagerVmCheckUpdateWindows": { + "parameters": { + "assessmentMode": { + "value": "[[parameters('assessmentMode')]" + }, + "osType": { + "value": "Windows" + }, + "locations": { + "value": "[[parameters('locations')]" + }, + "tagValues": { + "value": "[[parameters('tagValues')]" + }, + "tagOperator": { + "value": "[[parameters('tagOperator')]" + } + } + } +} diff --git a/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-MDFC-Config.json b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-MDFC-Config.json index f3c056f..222ad52 100644 --- a/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-MDFC-Config.json +++ b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-MDFC-Config.json @@ -8,7 +8,7 @@ "displayName": "Deploy Microsoft Defender for Cloud configuration", "description": "Deploy Microsoft Defender for Cloud configuration", "metadata": { - "version": "6.0.1", + "version": "7.0.0", "category": "Security Center", "source": "https://github.com/Azure/Enterprise-Scale/", "alzCloudEnvironments": [ @@ -434,6 +434,12 @@ } }, "groupNames": [] + }, + { + "policyDefinitionReferenceId": "migrateToMdeTvm", + "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/766e621d-ba95-4e43-a6f2-e945db3d7888", + "parameters": {}, + "groupNames": [] } ], "policyDefinitionGroups": null diff --git a/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-MDFC-Config.parameters.json b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-MDFC-Config.parameters.json index 38f85e2..db48af3 100644 --- a/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-MDFC-Config.parameters.json +++ b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-MDFC-Config.parameters.json @@ -130,6 +130,9 @@ } } }, + "migrateToMdeTvm": { + "parameters": {} + }, "securityEmailContact": { "parameters": { "emailSecurityContact": { diff --git a/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-MDFC-DefenderSQL-AMA.json b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-MDFC-DefenderSQL-AMA.json new file mode 100644 index 0000000..9b0d468 --- /dev/null +++ b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-MDFC-DefenderSQL-AMA.json @@ -0,0 +1,237 @@ +{ + "name": "Deploy-MDFC-DefenderSQL-AMA", + "type": "Microsoft.Authorization/policySetDefinitions", + "apiVersion": "2021-06-01", + "scope": null, + "properties": { + "policyType": "Custom", + "displayName": "Configure SQL VMs and Arc-enabled SQL Servers to install Microsoft Defender for SQL and AMA with a user-defined LA workspace", + "description": "Microsoft Defender for SQL collects events from the agents and uses them to provide security alerts and tailored hardening tasks (recommendations). Creates a resource group and a Data Collection Rule in the same region as the user-defined Log Analytics workspace.", + "metadata": { + "version": "1.0.1", + "category": "Security Center", + "source": "https://github.com/Azure/Enterprise-Scale/", + "alzCloudEnvironments": [ + "AzureCloud" + ] + }, + "parameters": { + "effect": { + "type": "String", + "metadata": { + "displayName": "Effect", + "description": "Enable or disable the execution of the policy" + }, + "allowedValues": [ + "DeployIfNotExists", + "Disabled" + ], + "defaultValue": "DeployIfNotExists" + }, + "workspaceRegion": { + "type": "String", + "metadata": { + "displayName": "Workspace region", + "description": "Region of the Log Analytics workspace destination for the Data Collection Rule.", + "strongType": "location" + } + }, + "dcrName": { + "type": "String", + "metadata": { + "displayName": "Data Collection Rule Name", + "description": "Name of the Data Collection Rule." + } + }, + "dcrResourceGroup": { + "type": "String", + "metadata": { + "displayName": "Data Collection Rule Resource Group", + "description": "Resource Group of the Data Collection Rule." + } + }, + "dcrId": { + "type": "String", + "metadata": { + "displayName": "Data Collection Rule Id", + "description": "Id of the Data Collection Rule." + } + }, + "userWorkspaceResourceId": { + "type": "String", + "metadata": { + "displayName": "Workspace Resource Id", + "description": "Workspace resource Id of the Log Analytics workspace destination for the Data Collection Rule.", + "strongType": "omsWorkspace" + } + }, + "enableCollectionOfSqlQueriesForSecurityResearch": { + "type": "Boolean", + "metadata": { + "displayName": "Enable collection of SQL queries for security research", + "description": "Enable or disable the collection of SQL queries for security research." + }, + "allowedValues": [ + true, + false + ], + "defaultValue": false + }, + "identityResourceGroup": { + "type": "String", + "metadata": { + "displayName": "Identity Resource Group", + "description": "The name of the resource group created by the policy." + }, + "defaultValue": "" + }, + "userAssignedIdentityName": { + "type": "String", + "metadata": { + "displayName": "User Assigned Managed Identity Name", + "description": "The name of the user assigned managed identity." + }, + "defaultValue": "" + } + }, + "policyDefinitions": [ + { + "policyDefinitionReferenceId": "defenderForSqlArcAma", + "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/3592ff98-9787-443a-af59-4505d0fe0786", + "parameters": { + "effect": { + "value": "[[parameters('effect')]" + } + }, + "groupNames": [] + }, + { + "policyDefinitionReferenceId": "defenderForSqlArcMdsql", + "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/65503269-6a54-4553-8a28-0065a8e6d929", + "parameters": { + "effect": { + "value": "[[parameters('effect')]" + } + }, + "groupNames": [] + }, + { + "policyDefinitionReferenceId": "defenderForSqlArcMdsqlDcr", + "policyDefinitionId": "${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-MDFC-Arc-Sql-DefenderSQL-DCR", + "parameters": { + "effect": { + "value": "[[parameters('effect')]" + }, + "userWorkspaceResourceId": { + "value": "[[parameters('userWorkspaceResourceId')]" + }, + "workspaceRegion": { + "value": "[[parameters('workspaceRegion')]" + }, + "enableCollectionOfSqlQueriesForSecurityResearch": { + "value": "[[parameters('enableCollectionOfSqlQueriesForSecurityResearch')]" + }, + "dcrName": { + "value": "[[parameters('dcrName')]" + }, + "dcrResourceGroup": { + "value": "[[parameters('dcrResourceGroup')]" + }, + "dcrId": { + "value": "[[parameters('dcrId')]" + } + }, + "groupNames": [] + }, + { + "policyDefinitionReferenceId": "defenderForSqlArcDcrAssociation", + "policyDefinitionId": "${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-MDFC-Arc-SQL-DCR-Association", + "parameters": { + "effect": { + "value": "[[parameters('effect')]" + }, + "workspaceRegion": { + "value": "[[parameters('workspaceRegion')]" + }, + "dcrName": { + "value": "[[parameters('dcrName')]" + }, + "dcrResourceGroup": { + "value": "[[parameters('dcrResourceGroup')]" + }, + "dcrId": { + "value": "[[parameters('dcrId')]" + } + }, + "groupNames": [] + }, + { + "policyDefinitionReferenceId": "defenderForSqlAma", + "policyDefinitionId": "${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-MDFC-SQL-AMA", + "parameters": { + "effect": { + "value": "[[parameters('effect')]" + }, + "identityResourceGroup": { + "value": "[[parameters('identityResourceGroup')]" + }, + "userAssignedIdentityName": { + "value": "[[parameters('userAssignedIdentityName')]" + } + }, + "groupNames": [] + }, + { + "policyDefinitionReferenceId": "defenderForSqlMdsql", + "policyDefinitionId": "${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-MDFC-SQL-DefenderSQL", + "parameters": { + "effect": { + "value": "[[parameters('effect')]" + }, + "workspaceRegion": { + "value": "[[parameters('workspaceRegion')]" + }, + "dcrResourceGroup": { + "value": "[[parameters('dcrResourceGroup')]" + }, + "dcrName": { + "value": "[[parameters('dcrName')]" + }, + "dcrId": { + "value": "[[parameters('dcrId')]" + } + }, + "groupNames": [] + }, + { + "policyDefinitionReferenceId": "defenderForSqlMdsqlDcr", + "policyDefinitionId": "${varTargetManagementGroupResourceId}/providers/Microsoft.Authorization/policyDefinitions/Deploy-MDFC-SQL-DefenderSQL-DCR", + "parameters": { + "effect": { + "value": "Disabled" + }, + "userWorkspaceResourceId": { + "value": "[[parameters('userWorkspaceResourceId')]" + }, + "workspaceRegion": { + "value": "[[parameters('workspaceRegion')]" + }, + "enableCollectionOfSqlQueriesForSecurityResearch": { + "value": "[[parameters('enableCollectionOfSqlQueriesForSecurityResearch')]" + }, + "dcrName": { + "value": "[[parameters('dcrName')]" + }, + "dcrResourceGroup": { + "value": "[[parameters('dcrResourceGroup')]" + }, + "dcrId": { + "value": "[[parameters('dcrId')]" + } + }, + "groupNames": [] + } + ], + "policyDefinitionGroups": null + } +} \ No newline at end of file diff --git a/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-MDFC-DefenderSQL-AMA.parameters.json b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-MDFC-DefenderSQL-AMA.parameters.json new file mode 100644 index 0000000..6269297 --- /dev/null +++ b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-MDFC-DefenderSQL-AMA.parameters.json @@ -0,0 +1,117 @@ +{ + "defenderForSqlAma": { + "parameters": { + "effect": { + "value": "[[parameters('effect')]" + }, + "identityResourceGroup": { + "value": "[[parameters('identityResourceGroup')]" + }, + "userAssignedIdentityName": { + "value": "[[parameters('userAssignedIdentityName')]" + } + } + }, + "defenderForSqlArcAma": { + "parameters": { + "effect": { + "value": "[[parameters('effect')]" + } + } + }, + "defenderForSqlArcDcrAssociation": { + "parameters": { + "effect": { + "value": "[[parameters('effect')]" + }, + "workspaceRegion": { + "value": "[[parameters('workspaceRegion')]" + }, + "dcrName": { + "value": "[[parameters('dcrName')]" + }, + "dcrResourceGroup": { + "value": "[[parameters('dcrResourceGroup')]" + }, + "dcrId": { + "value": "[[parameters('dcrId')]" + } + } + }, + "defenderForSqlArcMdsql": { + "parameters": { + "effect": { + "value": "[[parameters('effect')]" + } + } + }, + "defenderForSqlArcMdsqlDcr": { + "parameters": { + "effect": { + "value": "[[parameters('effect')]" + }, + "userWorkspaceResourceId": { + "value": "[[parameters('userWorkspaceResourceId')]" + }, + "workspaceRegion": { + "value": "[[parameters('workspaceRegion')]" + }, + "enableCollectionOfSqlQueriesForSecurityResearch": { + "value": "[[parameters('enableCollectionOfSqlQueriesForSecurityResearch')]" + }, + "dcrName": { + "value": "[[parameters('dcrName')]" + }, + "dcrResourceGroup": { + "value": "[[parameters('dcrResourceGroup')]" + }, + "dcrId": { + "value": "[[parameters('dcrId')]" + } + } + }, + "defenderForSqlMdsql": { + "parameters": { + "effect": { + "value": "[[parameters('effect')]" + }, + "workspaceRegion": { + "value": "[[parameters('workspaceRegion')]" + }, + "dcrResourceGroup": { + "value": "[[parameters('dcrResourceGroup')]" + }, + "dcrName": { + "value": "[[parameters('dcrName')]" + }, + "dcrId": { + "value": "[[parameters('dcrId')]" + } + } + }, + "defenderForSqlMdsqlDcr": { + "parameters": { + "effect": { + "value": "Disabled" + }, + "userWorkspaceResourceId": { + "value": "[[parameters('userWorkspaceResourceId')]" + }, + "workspaceRegion": { + "value": "[[parameters('workspaceRegion')]" + }, + "enableCollectionOfSqlQueriesForSecurityResearch": { + "value": "[[parameters('enableCollectionOfSqlQueriesForSecurityResearch')]" + }, + "dcrName": { + "value": "[[parameters('dcrName')]" + }, + "dcrResourceGroup": { + "value": "[[parameters('dcrResourceGroup')]" + }, + "dcrId": { + "value": "[[parameters('dcrId')]" + } + } + } +} diff --git a/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-Private-DNS-Zones.json b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-Private-DNS-Zones.json index d633aa9..1c664da 100644 --- a/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-Private-DNS-Zones.json +++ b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-Private-DNS-Zones.json @@ -8,7 +8,7 @@ "displayName": "Configure Azure PaaS services to use private DNS zones", "description": "This policy initiative is a group of policies that ensures private endpoints to Azure PaaS services are integrated with Azure Private DNS zones", "metadata": { - "version": "2.1.1", + "version": "2.1.2", "category": "Network", "source": "https://github.com/Azure/Enterprise-Scale/", "alzCloudEnvironments": [ @@ -672,7 +672,7 @@ "groupNames": [] }, { - "policyDefinitionReferenceId": "DINE-Private-DNS-Azure-Databrics-UI-Api", + "policyDefinitionReferenceId": "DINE-Private-DNS-Azure-Databricks-UI-Api", "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/0eddd7f3-3d9b-4927-a07a-806e8ac9486c", "parameters": { "privateDnsZoneId": { @@ -688,7 +688,7 @@ "groupNames": [] }, { - "policyDefinitionReferenceId": "DINE-Private-DNS-Azure-Databrics-Browser-AuthN", + "policyDefinitionReferenceId": "DINE-Private-DNS-Azure-Databricks-Browser-AuthN", "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/0eddd7f3-3d9b-4927-a07a-806e8ac9486c", "parameters": { "privateDnsZoneId": { diff --git a/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-Private-DNS-Zones.parameters.json b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-Private-DNS-Zones.parameters.json index ea78797..2224284 100644 --- a/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-Private-DNS-Zones.parameters.json +++ b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Deploy-Private-DNS-Zones.parameters.json @@ -150,7 +150,7 @@ } } }, - "DINE-Private-DNS-Azure-Databrics-Browser-AuthN": { + "DINE-Private-DNS-Azure-Databricks-Browser-AuthN": { "parameters": { "privateDnsZoneId": { "value": "[[parameters('azureDatabricksPrivateDnsZoneId')]" @@ -163,7 +163,7 @@ } } }, - "DINE-Private-DNS-Azure-Databrics-UI-Api": { + "DINE-Private-DNS-Azure-Databricks-UI-Api": { "parameters": { "privateDnsZoneId": { "value": "[[parameters('azureDatabricksPrivateDnsZoneId')]" diff --git a/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Enforce-EncryptTransit.json b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Enforce-EncryptTransit.json index 0e79140..4b9f1d5 100644 --- a/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Enforce-EncryptTransit.json +++ b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Enforce-EncryptTransit.json @@ -8,7 +8,7 @@ "displayName": "Deny or Deploy and append TLS requirements and SSL enforcement on resources without Encryption in transit", "description": "Choose either Deploy if not exist and append in combination with audit or Select Deny in the Policy effect. Deny polices shift left. Deploy if not exist and append enforce but can be changed, and because missing existence condition require then the combination of Audit. ", "metadata": { - "version": "2.0.0", + "version": "2.1.0", "category": "Encryption", "source": "https://github.com/Azure/Enterprise-Scale/", "alzCloudEnvironments": [ @@ -360,6 +360,19 @@ "Deny", "Disabled" ] + }, + "ContainerAppsHttpsOnlyEffect": { + "metadata": { + "displayName": "Container Apps should only be accessible over HTTPS", + "description": "Use of HTTPS ensures server/service authentication and protects data in transit from network layer eavesdropping attacks. Disabling 'allowInsecure' will result in the automatic redirection of requests from HTTP to HTTPS connections for container apps." + }, + "type": "String", + "defaultValue": "Deny", + "allowedValues": [ + "Audit", + "Deny", + "Disabled" + ] } }, "policyDefinitions": [ @@ -611,6 +624,16 @@ } }, "groupNames": [] + }, + { + "policyDefinitionReferenceId": "ContainerAppsHttpsOnlyEffect", + "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/0e80e269-43a4-4ae9-b5bc-178126b8a5cb", + "parameters": { + "effect": { + "value": "[[parameters('ContainerAppsHttpsOnlyEffect')]" + } + }, + "groupNames": [] } ], "policyDefinitionGroups": null diff --git a/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Enforce-EncryptTransit.parameters.json b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Enforce-EncryptTransit.parameters.json index 7dca494..16ac02b 100644 --- a/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Enforce-EncryptTransit.parameters.json +++ b/dependencies/infra-as-code/bicep/modules/policy/definitions/lib/policy_set_definitions/policy_set_definition_es_Enforce-EncryptTransit.parameters.json @@ -30,6 +30,13 @@ } } }, + "ContainerAppsHttpsOnlyEffect": { + "parameters": { + "effect": { + "value": "[[parameters('ContainerAppsHttpsOnlyEffect')]" + } + } + }, "FunctionLatestTlsEffect": { "parameters": { "effect": { diff --git a/dependencies/infra-as-code/bicep/modules/policy/definitions/mc-customPolicyDefinitions.bicep b/dependencies/infra-as-code/bicep/modules/policy/definitions/mc-customPolicyDefinitions.bicep index 9262bc3..1fac5dc 100644 --- a/dependencies/infra-as-code/bicep/modules/policy/definitions/mc-customPolicyDefinitions.bicep +++ b/dependencies/infra-as-code/bicep/modules/policy/definitions/mc-customPolicyDefinitions.bicep @@ -1326,7 +1326,7 @@ var varPolicySetDefinitionEsMcEnforceEncryptTransitParameters = loadJsonContent( // Customer Usage Attribution Id var varCuaid = '2b136786-9881-412e-84ba-f4c2822e1ac9' -resource resPolicyDefinitions 'Microsoft.Authorization/policyDefinitions@2021-06-01' = [for policy in varCustomPolicyDefinitionsArray: { +resource resPolicyDefinitions 'Microsoft.Authorization/policyDefinitions@2023-04-01' = [for policy in varCustomPolicyDefinitionsArray: { name: policy.libDefinition.name properties: { description: policy.libDefinition.properties.description @@ -1339,7 +1339,7 @@ resource resPolicyDefinitions 'Microsoft.Authorization/policyDefinitions@2021-06 } }] -resource resPolicySetDefinitions 'Microsoft.Authorization/policySetDefinitions@2021-06-01' = [for policySet in varCustomPolicySetDefinitionsArray: { +resource resPolicySetDefinitions 'Microsoft.Authorization/policySetDefinitions@2023-04-01' = [for policySet in varCustomPolicySetDefinitionsArray: { dependsOn: [ resPolicyDefinitions // Must wait for policy definitons to be deployed before starting the creation of Policy Set/Initiative Defininitions ] diff --git a/dependencies/infra-as-code/bicep/modules/privateDnsZoneLinks/generateddocs/privateDnsZoneLinks.bicep.md b/dependencies/infra-as-code/bicep/modules/privateDnsZoneLinks/generateddocs/privateDnsZoneLinks.bicep.md index d8e1c99..4346903 100644 --- a/dependencies/infra-as-code/bicep/modules/privateDnsZoneLinks/generateddocs/privateDnsZoneLinks.bicep.md +++ b/dependencies/infra-as-code/bicep/modules/privateDnsZoneLinks/generateddocs/privateDnsZoneLinks.bicep.md @@ -6,6 +6,7 @@ Parameter name | Required | Description -------------- | -------- | ----------- parSpokeVirtualNetworkResourceId | No | The Spoke Virtual Network Resource ID. parPrivateDnsZoneResourceId | No | The Private DNS Zone Resource IDs to associate with the spoke Virtual Network. +parResourceLockConfig | No | Resource Lock Configuration for Private DNS Zone Links. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. ### parSpokeVirtualNetworkResourceId @@ -19,6 +20,19 @@ The Spoke Virtual Network Resource ID. The Private DNS Zone Resource IDs to associate with the spoke Virtual Network. +### parResourceLockConfig + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Resource Lock Configuration for Private DNS Zone Links. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep Private DNS Zone Links Module.}` + ## Snippets ### Parameter file @@ -36,6 +50,12 @@ The Private DNS Zone Resource IDs to associate with the spoke Virtual Network. }, "parPrivateDnsZoneResourceId": { "value": "" + }, + "parResourceLockConfig": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Private DNS Zone Links Module." + } } } } diff --git a/dependencies/infra-as-code/bicep/modules/privateDnsZoneLinks/privateDnsZoneLinks.bicep b/dependencies/infra-as-code/bicep/modules/privateDnsZoneLinks/privateDnsZoneLinks.bicep index b36c5e6..b24df08 100644 --- a/dependencies/infra-as-code/bicep/modules/privateDnsZoneLinks/privateDnsZoneLinks.bicep +++ b/dependencies/infra-as-code/bicep/modules/privateDnsZoneLinks/privateDnsZoneLinks.bicep @@ -1,11 +1,33 @@ targetScope = 'resourceGroup' +type lockType = { + @description('Optional. Specify the name of lock.') + name: string? + + @description('Optional. The lock settings of the service.') + kind: ('CanNotDelete' | 'ReadOnly' | 'None') + + @description('Optional. Notes about this lock.') + notes: string? +} + @sys.description('The Spoke Virtual Network Resource ID.') param parSpokeVirtualNetworkResourceId string = '' @sys.description('The Private DNS Zone Resource IDs to associate with the spoke Virtual Network.') param parPrivateDnsZoneResourceId string = '' +@sys.description('''Resource Lock Configuration for Private DNS Zone Links. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parResourceLockConfig lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep Private DNS Zone Links Module.' +} + var varSpokeVirtualNetworkName = split(parSpokeVirtualNetworkResourceId, '/')[8] resource resPrivateDnsZoneLinkToSpoke 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = if (!empty(parPrivateDnsZoneResourceId)) { @@ -18,3 +40,12 @@ resource resPrivateDnsZoneLinkToSpoke 'Microsoft.Network/privateDnsZones/virtual } } } + +resource lock 'Microsoft.Authorization/locks@2020-05-01' = if (parResourceLockConfig.kind != 'None') { + scope: resPrivateDnsZoneLinkToSpoke + name: parResourceLockConfig.?name ?? 'link-to-${varSpokeVirtualNetworkName}-${uniqueString(parPrivateDnsZoneResourceId)}-lock' + properties: { + level: parResourceLockConfig.kind + notes: parResourceLockConfig.?notes ?? '' + } +} diff --git a/dependencies/infra-as-code/bicep/modules/privateDnsZones/generateddocs/privateDnsZones.bicep.md b/dependencies/infra-as-code/bicep/modules/privateDnsZones/generateddocs/privateDnsZones.bicep.md index 19094cf..cca6b62 100644 --- a/dependencies/infra-as-code/bicep/modules/privateDnsZones/generateddocs/privateDnsZones.bicep.md +++ b/dependencies/infra-as-code/bicep/modules/privateDnsZones/generateddocs/privateDnsZones.bicep.md @@ -12,6 +12,7 @@ parPrivateDnsZoneAutoMergeAzureBackupZone | No | Set Parameter to false to parTags | No | Tags you would like to be applied to all resources in this module. parVirtualNetworkIdToLink | No | Resource ID of VNet for Private DNS Zone VNet Links. parVirtualNetworkIdToLinkFailover | No | Resource ID of VNet for Failover Private DNS Zone VNet Links. +parResourceLockConfig | No | Resource Lock Configuration for Private DNS Zones. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. parTelemetryOptOut | No | Set Parameter to true to Opt-out of deployment telemetry. ### parLocation @@ -56,6 +57,19 @@ Resource ID of VNet for Private DNS Zone VNet Links. Resource ID of VNet for Failover Private DNS Zone VNet Links. +### parResourceLockConfig + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Resource Lock Configuration for Private DNS Zones. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep Private DNS Zones Module.}` + ### parTelemetryOptOut ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) @@ -169,6 +183,12 @@ outPrivateDnsZonesNames | array | "parVirtualNetworkIdToLinkFailover": { "value": "" }, + "parResourceLockConfig": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Private DNS Zones Module." + } + }, "parTelemetryOptOut": { "value": false } diff --git a/dependencies/infra-as-code/bicep/modules/privateDnsZones/privateDnsZones.bicep b/dependencies/infra-as-code/bicep/modules/privateDnsZones/privateDnsZones.bicep index 5f4c661..6779abe 100644 --- a/dependencies/infra-as-code/bicep/modules/privateDnsZones/privateDnsZones.bicep +++ b/dependencies/infra-as-code/bicep/modules/privateDnsZones/privateDnsZones.bicep @@ -1,6 +1,17 @@ metadata name = 'ALZ Bicep - Private DNS Zones' metadata description = 'Module used to set up Private DNS Zones in accordance to Azure Landing Zones' +type lockType = { + @description('Optional. Specify the name of lock.') + name: string? + + @description('Optional. The lock settings of the service.') + kind: ('CanNotDelete' | 'ReadOnly' | 'None') + + @description('Optional. Notes about this lock.') + notes: string? +} + @sys.description('The Azure Region to deploy the resources into.') param parLocation string = resourceGroup().location @@ -87,6 +98,17 @@ param parVirtualNetworkIdToLink string = '' @sys.description('Resource ID of VNet for Failover Private DNS Zone VNet Links.') param parVirtualNetworkIdToLinkFailover string = '' +@sys.description('''Resource Lock Configuration for Private DNS Zones. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parResourceLockConfig lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep Private DNS Zones Module.' +} + @sys.description('Set Parameter to true to Opt-out of deployment telemetry.') param parTelemetryOptOut bool = false @@ -107,8 +129,12 @@ var varAzBackupGeoCodes = { eastus2: 'eus2' francecentral: 'frc' francesouth: 'frs' + germanycentral: 'gec' germanynorth: 'gn' + germanynortheast: 'gne' germanywestcentral: 'gwc' + israelcentral: 'ilc' + italynorth: 'itn' centralindia: 'inc' southindia: 'ins' westindia: 'inw' @@ -122,6 +148,7 @@ var varAzBackupGeoCodes = { northeurope: 'ne' norwayeast: 'nwe' norwaywest: 'nww' + polandcentral: 'plc' qatarcentral: 'qac' southafricanorth: 'san' southafricawest: 'saw' @@ -156,8 +183,6 @@ var varAzBackupGeoCodes = { chinaeast: 'sha' chinaeast2: 'sha2' chinaeast3: 'sha3' - germanycentral: 'gec' - germanynortheast: 'gne' } // If region entered in parLocation and matches a lookup to varAzBackupGeoCodes then insert Azure Backup Private DNS Zone with appropriate geo code inserted alongside zones in parPrivateDnsZones. If not just return parPrivateDnsZones @@ -172,6 +197,15 @@ resource resPrivateDnsZones 'Microsoft.Network/privateDnsZones@2020-06-01' = [fo tags: parTags }] +resource resPrivateDnsZonesLock 'Microsoft.Authorization/locks@2020-05-01' = [for (privateDnsZone, index) in varPrivateDnsZonesMerge: if (parResourceLockConfig.kind != 'None') { + scope: resPrivateDnsZones[index] + name: parResourceLockConfig.?name ?? '${privateDnsZone}-lock' + properties: { + level: parResourceLockConfig.kind + notes: parResourceLockConfig.?notes ?? '' + } +}] + resource resVirtualNetworkLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = [for privateDnsZoneName in varPrivateDnsZonesMerge: if (!empty(parVirtualNetworkIdToLink)) { name: '${privateDnsZoneName}/${take('link-${uniqueString(parVirtualNetworkIdToLink)}', 80)}' location: 'global' @@ -182,6 +216,16 @@ resource resVirtualNetworkLink 'Microsoft.Network/privateDnsZones/virtualNetwork } } dependsOn: resPrivateDnsZones + tags: parTags +}] + +resource resVirtualNetworkLinkLock 'Microsoft.Authorization/locks@2020-05-01' = [for (privateDnsZone, index) in varPrivateDnsZonesMerge: if (!empty(parVirtualNetworkIdToLink) && !empty(parResourceLockConfig ?? {}) && parResourceLockConfig.kind != 'None') { + scope: resVirtualNetworkLink[index] + name: parResourceLockConfig.?name ?? 'link-${uniqueString(parVirtualNetworkIdToLink)}-${privateDnsZone}-lock' + properties: { + level: parResourceLockConfig.kind + notes: parResourceLockConfig.?notes ?? '' + } }] resource resVirtualNetworkLinkFailover 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = [for privateDnsZoneName in varPrivateDnsZonesMerge: if (!empty(parVirtualNetworkIdToLinkFailover)) { @@ -194,6 +238,16 @@ resource resVirtualNetworkLinkFailover 'Microsoft.Network/privateDnsZones/virtua } } dependsOn: resPrivateDnsZones + tags: parTags +}] + +resource resVirtualNetworkLinkFailoverLock 'Microsoft.Authorization/locks@2020-05-01' = [for (privateDnsZone, index) in varPrivateDnsZonesMerge: if (!empty(parVirtualNetworkIdToLinkFailover) && !empty(parResourceLockConfig ?? {}) && parResourceLockConfig.kind != 'None') { + scope: resVirtualNetworkLinkFailover[index] + name: parResourceLockConfig.?name ?? 'failbacklink-${uniqueString(parVirtualNetworkIdToLink)}-${privateDnsZone}-lock' + properties: { + level: parResourceLockConfig.kind + notes: parResourceLockConfig.?notes ?? '' + } }] module modCustomerUsageAttribution '../../CRML/customerUsageAttribution/cuaIdResourceGroup.bicep' = if (!parTelemetryOptOut) { diff --git a/dependencies/infra-as-code/bicep/modules/publicIp/generateddocs/publicIp.bicep.md b/dependencies/infra-as-code/bicep/modules/publicIp/generateddocs/publicIp.bicep.md index 4942e5c..7908934 100644 --- a/dependencies/infra-as-code/bicep/modules/publicIp/generateddocs/publicIp.bicep.md +++ b/dependencies/infra-as-code/bicep/modules/publicIp/generateddocs/publicIp.bicep.md @@ -11,6 +11,7 @@ parPublicIpName | Yes | Name of Public IP to create in Azure. parPublicIpSku | Yes | Public IP Address SKU. parPublicIpProperties | Yes | Properties of Public IP to be deployed. parAvailabilityZones | No | Availability Zones to deploy the Public IP across. Region must support Availability Zones to use. If it does not then leave empty. +parResourceLockConfig | No | Resource Lock Configuration for Public IPs. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. parTags | No | Tags to be applied to resource when deployed. parTelemetryOptOut | No | Set Parameter to true to Opt-out of deployment telemetry. @@ -48,6 +49,19 @@ Availability Zones to deploy the Public IP across. Region must support Availabil - Allowed values: `1`, `2`, `3` +### parResourceLockConfig + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Resource Lock Configuration for Public IPs. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep Public IP Module.}` + ### parTags ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) @@ -67,6 +81,7 @@ Set Parameter to true to Opt-out of deployment telemetry. Name | Type | Description ---- | ---- | ----------- outPublicIpId | string | +outPublicIpName | string | ## Snippets @@ -95,6 +110,12 @@ outPublicIpId | string | "parAvailabilityZones": { "value": [] }, + "parResourceLockConfig": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Public IP Module." + } + }, "parTags": { "value": {} }, diff --git a/dependencies/infra-as-code/bicep/modules/publicIp/publicIp.bicep b/dependencies/infra-as-code/bicep/modules/publicIp/publicIp.bicep index 2c4cc2d..c7fc3ef 100644 --- a/dependencies/infra-as-code/bicep/modules/publicIp/publicIp.bicep +++ b/dependencies/infra-as-code/bicep/modules/publicIp/publicIp.bicep @@ -1,6 +1,17 @@ metadata name = 'ALZ Bicep - Public IP creation module' metadata description = 'Module used to set up Public IP for Azure Landing Zones' +type lockType = { + @description('Optional. Specify the name of lock.') + name: string? + + @description('Optional. The lock settings of the service.') + kind: ('CanNotDelete' | 'ReadOnly' | 'None') + + @description('Optional. Notes about this lock.') + notes: string? +} + @sys.description('Azure Region to deploy Public IP Address to.') param parLocation string = resourceGroup().location @@ -21,6 +32,17 @@ param parPublicIpProperties object @sys.description('Availability Zones to deploy the Public IP across. Region must support Availability Zones to use. If it does not then leave empty.') param parAvailabilityZones array = [] +@sys.description('''Resource Lock Configuration for Public IPs. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parResourceLockConfig lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep Public IP Module.' +} + @sys.description('Tags to be applied to resource when deployed.') param parTags object = {} @@ -30,7 +52,7 @@ param parTelemetryOptOut bool = false // Customer Usage Attribution Id var varCuaid = '3f85b84c-6bad-4c42-86bf-11c233241c22' -resource resPublicIp 'Microsoft.Network/publicIPAddresses@2023-02-01' ={ +resource resPublicIp 'Microsoft.Network/publicIPAddresses@2023-02-01' = { name: parPublicIpName tags: parTags location: parLocation @@ -39,6 +61,15 @@ resource resPublicIp 'Microsoft.Network/publicIPAddresses@2023-02-01' ={ properties: parPublicIpProperties } +resource resPublicIpLock 'Microsoft.Authorization/locks@2020-05-01' = if (!empty(parResourceLockConfig ?? {}) && parResourceLockConfig.kind != 'None') { + scope: resPublicIp + name: parResourceLockConfig.?name ?? '${resPublicIp.name}-lock' + properties: { + level: parResourceLockConfig.kind + notes: parResourceLockConfig.?notes ?? '' + } +} + // Optional Deployment for Customer Usage Attribution module modCustomerUsageAttribution '../../CRML/customerUsageAttribution/cuaIdResourceGroup.bicep' = if (!parTelemetryOptOut) { #disable-next-line no-loc-expr-outside-params //Only to ensure telemetry data is stored in same location as deployment. 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 @@ -47,3 +78,4 @@ module modCustomerUsageAttribution '../../CRML/customerUsageAttribution/cuaIdRes } output outPublicIpId string = resPublicIp.id +output outPublicIpName string = resPublicIp.name diff --git a/dependencies/infra-as-code/bicep/modules/resourceGroup/generateddocs/resourceGroup.bicep.md b/dependencies/infra-as-code/bicep/modules/resourceGroup/generateddocs/resourceGroup.bicep.md index 5dbeae7..666c2ce 100644 --- a/dependencies/infra-as-code/bicep/modules/resourceGroup/generateddocs/resourceGroup.bicep.md +++ b/dependencies/infra-as-code/bicep/modules/resourceGroup/generateddocs/resourceGroup.bicep.md @@ -8,6 +8,7 @@ Parameter name | Required | Description -------------- | -------- | ----------- parLocation | Yes | Azure Region where Resource Group will be created. parResourceGroupName | Yes | Name of Resource Group to be created. +parResourceLockConfig | No | Resource Lock Configuration for Resource Groups. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. parTags | No | Tags you would like to be applied to all resources in this module. parTelemetryOptOut | No | Set Parameter to true to Opt-out of deployment telemetry. @@ -23,6 +24,19 @@ Azure Region where Resource Group will be created. Name of Resource Group to be created. +### parResourceLockConfig + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Resource Lock Configuration for Resource Groups. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep Resource Group Module.}` + ### parTags ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) @@ -62,6 +76,12 @@ outResourceGroupId | string | "parResourceGroupName": { "value": "" }, + "parResourceLockConfig": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Resource Group Module." + } + }, "parTags": { "value": {} }, diff --git a/dependencies/infra-as-code/bicep/modules/resourceGroup/generateddocs/resourceGroupLock.bicep.md b/dependencies/infra-as-code/bicep/modules/resourceGroup/generateddocs/resourceGroupLock.bicep.md new file mode 100644 index 0000000..14e11e6 --- /dev/null +++ b/dependencies/infra-as-code/bicep/modules/resourceGroup/generateddocs/resourceGroupLock.bicep.md @@ -0,0 +1,54 @@ +# ALZ Bicep - Resource Group lock module + +Module used to lock Resource Groups for Azure Landing Zones + +## Parameters + +Parameter name | Required | Description +-------------- | -------- | ----------- +parResourceLockConfig | No | Resource Lock Configuration for Resource Groups. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. +parResourceGroupName | Yes | Resource Group Name + +### parResourceLockConfig + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Resource Lock Configuration for Resource Groups. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep Resource Group Module.}` + +### parResourceGroupName + +![Parameter Setting](https://img.shields.io/badge/parameter-required-orange?style=flat-square) + +Resource Group Name + +## Snippets + +### Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "template": "infra-as-code/bicep/modules/resourceGroup/resourceGroupLock.json" + }, + "parameters": { + "parResourceLockConfig": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Resource Group Module." + } + }, + "parResourceGroupName": { + "value": "" + } + } +} +``` diff --git a/dependencies/infra-as-code/bicep/modules/resourceGroup/parameters/resourceGroup.parameters.all.json b/dependencies/infra-as-code/bicep/modules/resourceGroup/parameters/resourceGroup.parameters.all.json index 6dcf98f..06c5212 100644 --- a/dependencies/infra-as-code/bicep/modules/resourceGroup/parameters/resourceGroup.parameters.all.json +++ b/dependencies/infra-as-code/bicep/modules/resourceGroup/parameters/resourceGroup.parameters.all.json @@ -15,6 +15,12 @@ }, "parTelemetryOptOut": { "value": false + }, + "parResourceLockConfig": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep resourceGroup Module" + } } } } diff --git a/dependencies/infra-as-code/bicep/modules/resourceGroup/resourceGroup.bicep b/dependencies/infra-as-code/bicep/modules/resourceGroup/resourceGroup.bicep index a383c46..76b8f3b 100644 --- a/dependencies/infra-as-code/bicep/modules/resourceGroup/resourceGroup.bicep +++ b/dependencies/infra-as-code/bicep/modules/resourceGroup/resourceGroup.bicep @@ -3,12 +3,34 @@ targetScope = 'subscription' metadata name = 'ALZ Bicep - Resource Group creation module' metadata description = 'Module used to create Resource Groups for Azure Landing Zones' +type lockType = { + @description('Optional. Specify the name of lock.') + name: string? + + @description('Optional. The lock settings of the service.') + kind: ('CanNotDelete' | 'ReadOnly' | 'None') + + @description('Optional. Notes about this lock.') + notes: string? +} + @sys.description('Azure Region where Resource Group will be created.') param parLocation string @sys.description('Name of Resource Group to be created.') param parResourceGroupName string +@sys.description('''Resource Lock Configuration for Resource Groups. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parResourceLockConfig lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep Resource Group Module.' +} + @sys.description('Tags you would like to be applied to all resources in this module.') param parTags object = {} @@ -24,6 +46,16 @@ resource resResourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = { tags: parTags } +// Create a resource lock at the resource group level +module modResourceGroupLock 'resourceGroupLock.bicep' = if (!empty(parResourceLockConfig ?? {}) && parResourceLockConfig.?kind != 'None') { + scope: resourceGroup(resResourceGroup.name) + name: 'deploy-${resResourceGroup.name}-lock' + params: { + parResourceGroupName: resResourceGroup.name + parResourceLockConfig: parResourceLockConfig + } +} + module modCustomerUsageAttribution '../../CRML/customerUsageAttribution/cuaIdSubscription.bicep' = if (!parTelemetryOptOut) { name: 'pid-${varCuaid}-${uniqueString(subscription().subscriptionId, parResourceGroupName)}' params: {} diff --git a/dependencies/infra-as-code/bicep/modules/resourceGroup/resourceGroupLock.bicep b/dependencies/infra-as-code/bicep/modules/resourceGroup/resourceGroupLock.bicep new file mode 100644 index 0000000..ca4cea7 --- /dev/null +++ b/dependencies/infra-as-code/bicep/modules/resourceGroup/resourceGroupLock.bicep @@ -0,0 +1,36 @@ +metadata name = 'ALZ Bicep - Resource Group lock module' +metadata description = 'Module used to lock Resource Groups for Azure Landing Zones' + +type lockType = { + @description('Optional. Specify the name of lock.') + name: string? + + @description('Optional. The lock settings of the service.') + kind: ('CanNotDelete' | 'ReadOnly' | 'None') + + @description('Optional. Notes about this lock.') + notes: string? +} + +@sys.description('''Resource Lock Configuration for Resource Groups. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parResourceLockConfig lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep Resource Group Module.' +} + +@sys.description('Resource Group Name') +param parResourceGroupName string + +// Create a resource lock at the resource group level +resource resResourceGroupLock 'Microsoft.Authorization/locks@2020-05-01' = if (!empty(parResourceLockConfig ?? {}) && parResourceLockConfig.?kind != 'None') { + name: parResourceLockConfig.?name ?? '${parResourceGroupName}-lock' + properties: { + level: parResourceLockConfig.kind + notes: parResourceLockConfig.?notes + } +} diff --git a/dependencies/infra-as-code/bicep/modules/spokeNetworking/generateddocs/spokeNetworking.bicep.md b/dependencies/infra-as-code/bicep/modules/spokeNetworking/generateddocs/spokeNetworking.bicep.md index fa92ea9..b852fe0 100644 --- a/dependencies/infra-as-code/bicep/modules/spokeNetworking/generateddocs/spokeNetworking.bicep.md +++ b/dependencies/infra-as-code/bicep/modules/spokeNetworking/generateddocs/spokeNetworking.bicep.md @@ -9,11 +9,14 @@ Parameter name | Required | Description parLocation | No | The Azure Region to deploy the resources into. parDisableBgpRoutePropagation | No | Switch to enable/disable BGP Propagation on route table. parDdosProtectionPlanId | No | Id of the DdosProtectionPlan which will be applied to the Virtual Network. +parGlobalResourceLock | No | Global Resource Lock Configuration used for all resources deployed in this module. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. parSpokeNetworkAddressPrefix | No | The IP address range for all virtual networks to use. parSpokeNetworkName | No | The Name of the Spoke Virtual Network. +parSpokeNetworkLock | No | Resource Lock Configuration for Spoke Network - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. parDnsServerIps | No | Array of DNS Server IP addresses for VNet. parNextHopIpAddress | No | IP Address where network traffic should route to leveraged with DNS Proxy. parSpokeToHubRouteTableName | No | Name of Route table to create for the default route of Hub. +parSpokeRouteTableLock | No | Resource Lock Configuration for Spoke Network Route Table. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. parTags | No | Tags you would like to be applied to all resources in this module. parTelemetryOptOut | No | Set Parameter to true to Opt-out of deployment telemetry. @@ -39,6 +42,19 @@ Switch to enable/disable BGP Propagation on route table. Id of the DdosProtectionPlan which will be applied to the Virtual Network. +### parGlobalResourceLock + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Global Resource Lock Configuration used for all resources deployed in this module. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep Hub Networking Module.}` + ### parSpokeNetworkAddressPrefix ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) @@ -55,6 +71,19 @@ The Name of the Spoke Virtual Network. - Default value: `vnet-spoke` +### parSpokeNetworkLock + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Resource Lock Configuration for Spoke Network + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep Spoke Networking Module.}` + ### parDnsServerIps ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) @@ -75,6 +104,19 @@ Name of Route table to create for the default route of Hub. - Default value: `rtb-spoke-to-hub` +### parSpokeRouteTableLock + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Resource Lock Configuration for Spoke Network Route Table. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep Spoke Networking Module.}` + ### parTags ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) @@ -117,12 +159,24 @@ outSpokeVirtualNetworkId | string | "parDdosProtectionPlanId": { "value": "" }, + "parGlobalResourceLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, "parSpokeNetworkAddressPrefix": { "value": "10.11.0.0/16" }, "parSpokeNetworkName": { "value": "vnet-spoke" }, + "parSpokeNetworkLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Spoke Networking Module." + } + }, "parDnsServerIps": { "value": [] }, @@ -132,6 +186,12 @@ outSpokeVirtualNetworkId | string | "parSpokeToHubRouteTableName": { "value": "rtb-spoke-to-hub" }, + "parSpokeRouteTableLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Spoke Networking Module." + } + }, "parTags": { "value": {} }, diff --git a/dependencies/infra-as-code/bicep/modules/spokeNetworking/parameters/spokeNetworking.parameters.all.json b/dependencies/infra-as-code/bicep/modules/spokeNetworking/parameters/spokeNetworking.parameters.all.json index 112b11a..84490f1 100644 --- a/dependencies/infra-as-code/bicep/modules/spokeNetworking/parameters/spokeNetworking.parameters.all.json +++ b/dependencies/infra-as-code/bicep/modules/spokeNetworking/parameters/spokeNetworking.parameters.all.json @@ -33,6 +33,24 @@ }, "parTelemetryOptOut": { "value": false + }, + "parGlobalResourceLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Spoke Networking Module." + } + }, + "parSpokeNetworkLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Spoke Networking Module." + } + }, + "parSpokeRouteTableLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Spoke Networking Module." + } } } } diff --git a/dependencies/infra-as-code/bicep/modules/spokeNetworking/spokeNetworking.bicep b/dependencies/infra-as-code/bicep/modules/spokeNetworking/spokeNetworking.bicep index 67946db..29b1fa2 100644 --- a/dependencies/infra-as-code/bicep/modules/spokeNetworking/spokeNetworking.bicep +++ b/dependencies/infra-as-code/bicep/modules/spokeNetworking/spokeNetworking.bicep @@ -1,6 +1,17 @@ metadata name = 'ALZ Bicep - Spoke Networking module' metadata description = 'This module creates spoke networking resources' +type lockType = { + @description('Optional. Specify the name of lock.') + name: string? + + @description('Optional. The lock settings of the service.') + kind: ('CanNotDelete' | 'ReadOnly' | 'None') + + @description('Optional. Notes about this lock.') + notes: string? +} + @sys.description('The Azure Region to deploy the resources into.') param parLocation string = resourceGroup().location @@ -10,12 +21,34 @@ param parDisableBgpRoutePropagation bool = false @sys.description('Id of the DdosProtectionPlan which will be applied to the Virtual Network.') param parDdosProtectionPlanId string = '' +@sys.description('''Global Resource Lock Configuration used for all resources deployed in this module. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parGlobalResourceLock lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep Hub Networking Module.' +} + @sys.description('The IP address range for all virtual networks to use.') param parSpokeNetworkAddressPrefix string = '10.11.0.0/16' @sys.description('The Name of the Spoke Virtual Network.') param parSpokeNetworkName string = 'vnet-spoke' +@sys.description('''Resource Lock Configuration for Spoke Network + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parSpokeNetworkLock lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep Spoke Networking Module.' +} + @sys.description('Array of DNS Server IP addresses for VNet.') param parDnsServerIps array = [] @@ -25,6 +58,17 @@ param parNextHopIpAddress string = '' @sys.description('Name of Route table to create for the default route of Hub.') param parSpokeToHubRouteTableName string = 'rtb-spoke-to-hub' +@sys.description('''Resource Lock Configuration for Spoke Network Route Table. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parSpokeRouteTableLock lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep Spoke Networking Module.' +} + @sys.description('Tags you would like to be applied to all resources in this module.') param parTags object = {} @@ -56,6 +100,16 @@ resource resSpokeVirtualNetwork 'Microsoft.Network/virtualNetworks@2023-02-01' = } } +// Create a virtual network resource lock if parGlobalResourceLock.kind != 'None' or if parSpokeNetworkLock.kind != 'None' +resource resSpokeVirtualNetworkLock 'Microsoft.Authorization/locks@2020-05-01' = if (parSpokeNetworkLock.kind != 'None' || parGlobalResourceLock.kind != 'None') { + scope: resSpokeVirtualNetwork + name: parSpokeNetworkLock.?name ?? '${resSpokeVirtualNetwork.name}-lock' + properties: { + level: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.kind : parSpokeNetworkLock.kind + notes: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.?notes : parSpokeNetworkLock.?notes + } +} + resource resSpokeToHubRouteTable 'Microsoft.Network/routeTables@2023-02-01' = if (!empty(parNextHopIpAddress)) { name: parSpokeToHubRouteTableName location: parLocation @@ -75,6 +129,16 @@ resource resSpokeToHubRouteTable 'Microsoft.Network/routeTables@2023-02-01' = if } } +// Create a Route Table if parAzFirewallEnabled is true and parGlobalResourceLock.kind != 'None' or if parHubRouteTableLock.kind != 'None' +resource resSpokeToHubRouteTableLock 'Microsoft.Authorization/locks@2020-05-01' = if (!empty(parNextHopIpAddress) && (parSpokeRouteTableLock.kind != 'None' || parGlobalResourceLock.kind != 'None')) { + scope: resSpokeToHubRouteTable + name: parSpokeRouteTableLock.?name ?? '${resSpokeToHubRouteTable.name}-lock' + properties: { + level: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.kind : parSpokeRouteTableLock.kind + notes: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.?notes : parSpokeRouteTableLock.?notes + } +} + // Optional Deployment for Customer Usage Attribution module modCustomerUsageAttribution '../../CRML/customerUsageAttribution/cuaIdResourceGroup.bicep' = if (!parTelemetryOptOut) { name: 'pid-${varCuaid}-${uniqueString(resourceGroup().id)}' diff --git a/dependencies/infra-as-code/bicep/modules/subscriptionPlacement/subscriptionPlacement.bicep b/dependencies/infra-as-code/bicep/modules/subscriptionPlacement/subscriptionPlacement.bicep index d75174d..05afee5 100644 --- a/dependencies/infra-as-code/bicep/modules/subscriptionPlacement/subscriptionPlacement.bicep +++ b/dependencies/infra-as-code/bicep/modules/subscriptionPlacement/subscriptionPlacement.bicep @@ -15,7 +15,7 @@ param parTelemetryOptOut bool = false // Customer Usage Attribution Id var varCuaid = '3dfa9e81-f0cf-4b25-858e-167937fd380b' -resource resSubscriptionPlacement 'Microsoft.Management/managementGroups/subscriptions@2021-04-01' = [for subscriptionId in parSubscriptionIds: { +resource resSubscriptionPlacement 'Microsoft.Management/managementGroups/subscriptions@2023-04-01' = [for subscriptionId in parSubscriptionIds: { scope: tenant() name: '${parTargetManagementGroupId}/${subscriptionId}' }] diff --git a/dependencies/infra-as-code/bicep/modules/vwanConnectivity/README.md b/dependencies/infra-as-code/bicep/modules/vwanConnectivity/README.md index 0d99c1a..8b9c231 100644 --- a/dependencies/infra-as-code/bicep/modules/vwanConnectivity/README.md +++ b/dependencies/infra-as-code/bicep/modules/vwanConnectivity/README.md @@ -17,19 +17,25 @@ Module deploys the following resources which can be configured by parameters: - [Parameters for Azure Commercial Cloud](generateddocs/vwanConnectivity.bicep.md) -> **NOTE:** Although there are generated parameter markdowns for Azure Commercial Cloud, this same module can still be used in Azure China. Example parameter are in the [parameters](./parameters/) folder. +> **NOTE:** +> - Within the `parVirtualWanHubs` parameter, the following keys (parVpnGatewayCustomName, parExpressRouteGatewayCustomName, parAzFirewallCustomName, and parVirtualWanHubCustomName) can be added to create custom names for the associated resources. +> +> - Although there are generated parameter markdowns for Azure Commercial Cloud, this same module can still be used in Azure China. Example parameter are in the [parameters](./parameters/) folder. +> +> - The file `parameters/vwanConnectivity.parameters.az.all.json` contains parameter values for SKUs that are compatible with availability zones for relevant resource types. In cases where you are deploying to a region that does not support availability zones, you should opt for the `parameters/vwanConnectivity.parameters.all.json` file. +> -> NOTE: When deploying using the `parameters/vwanConnectivity.parameters.all.json` you must update the `parPrivateDnsZones` parameter by replacing the `xxxxxx` placeholders with the deployment region. Failure to do so will cause these services to be unreachable over private endpoints. +> - When deploying using the `parameters/vwanConnectivity.parameters.all.json` you must update the `parPrivateDnsZones` parameter by replacing the `xxxxxx` placeholders with the deployment region. Failure to do so will cause these services to be unreachable over private endpoints. > For example, if deploying to East US the following zone entries: -> - `privatelink.xxxxxx.azmk8s.io` -> - `privatelink.xxxxxx.backup.windowsazure.com` -> - `privatelink.xxxxxx.batch.azure.com` +> - `privatelink.xxxxxx.azmk8s.io` +> - `privatelink.xxxxxx.backup.windowsazure.com` +> - `privatelink.xxxxxx.batch.azure.com` > -> Will become: -> - `privatelink.eastus.azmk8s.io` -> - `privatelink.eastus.backup.windowsazure.com` -> - `privatelink.eastus.batch.azure.com` +> Will become: +> - `privatelink.eastus.azmk8s.io` +> - `privatelink.eastus.backup.windowsazure.com` +> - `privatelink.eastus.batch.azure.com` ## Outputs diff --git a/dependencies/infra-as-code/bicep/modules/vwanConnectivity/generateddocs/vwanConnectivity.bicep.md b/dependencies/infra-as-code/bicep/modules/vwanConnectivity/generateddocs/vwanConnectivity.bicep.md index c86a03b..6bb9c2b 100644 --- a/dependencies/infra-as-code/bicep/modules/vwanConnectivity/generateddocs/vwanConnectivity.bicep.md +++ b/dependencies/infra-as-code/bicep/modules/vwanConnectivity/generateddocs/vwanConnectivity.bicep.md @@ -8,29 +8,37 @@ Parameter name | Required | Description -------------- | -------- | ----------- parLocation | No | Region in which the resource group was created. parCompanyPrefix | No | Prefix value which will be prepended to all resource names. +parGlobalResourceLock | No | Global Resource Lock Configuration used for all resources deployed in this module. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. parAzFirewallTier | No | Azure Firewall Tier associated with the Firewall to deploy. -parAzFirewallIntelMode | No | The Azure Firewall Threat Intelligence Mode. If not set, the default value is Alert. +parAzFirewallIntelMode | No | The Azure Firewall Threat Intelligence Mode. parVirtualHubEnabled | No | Switch to enable/disable Virtual Hub deployment. parAzFirewallDnsProxyEnabled | No | Switch to enable/disable Azure Firewall DNS Proxy. -parAzFirewallDnsServers | No | Array of custom DNS servers used by Azure Firewall +parAzFirewallDnsServers | No | Array of custom DNS servers used by Azure Firewall. parVirtualWanName | No | Prefix Used for Virtual WAN. +parVirtualWanLock | No | Resource Lock Configuration for Virtual WAN. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. parVirtualWanHubName | No | Prefix Used for Virtual WAN Hub. parVirtualWanHubs | No | Array Used for multiple Virtual WAN Hubs deployment. Each object in the array represents an individual Virtual WAN Hub configuration. Add/remove additional objects in the array to meet the number of Virtual WAN Hubs required. - `parVpnGatewayEnabled` - Switch to enable/disable VPN Gateway deployment on the respective Virtual WAN Hub. - `parExpressRouteGatewayEnabled` - Switch to enable/disable ExpressRoute Gateway deployment on the respective Virtual WAN Hub. - `parAzFirewallEnabled` - Switch to enable/disable Azure Firewall deployment on the respective Virtual WAN Hub. - `parVirtualHubAddressPrefix` - The IP address range in CIDR notation for the vWAN virtual Hub to use. - `parHubLocation` - The Virtual WAN Hub location. - `parHubRoutingPreference` - The Virtual WAN Hub routing preference. The allowed values are `ASN`, `VpnGateway`, `ExpressRoute`. - `parVirtualRouterAutoScaleConfiguration` - The Virtual WAN Hub capacity. The value should be between 2 to 50. - `parVirtualHubRoutingIntentDestinations` - The Virtual WAN Hub routing intent destinations, leave empty if not wanting to enable routing intent. The allowed values are `Internet`, `PrivateTraffic`. -parVpnGatewayName | No | Prefix Used for VPN Gateway. -parExpressRouteGatewayName | No | Prefix Used for ExpressRoute Gateway. +parVpnGatewayLock | No | Resource Lock Configuration for Virtual WAN Hub VPN Gateway. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. +parExpressRouteGatewayLock | No | Resource Lock Configuration for Virtual WAN Hub ExpressRoute Gateway. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. +parVirtualWanHubsLock | No | Resource Lock Configuration for Virtual WAN Hub. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. +parVpnGatewayName | No | VPN Gateway Name. +parExpressRouteGatewayName | No | ExpressRoute Gateway Name. parAzFirewallName | No | Azure Firewall Name. parAzFirewallAvailabilityZones | No | Availability Zones to deploy the Azure Firewall across. Region must support Availability Zones to use. If it does not then leave empty. parAzFirewallPoliciesName | No | Azure Firewall Policies Name. +parAzureFirewallLock | No | Resource Lock Configuration for Azure Firewall. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. parVpnGatewayScaleUnit | No | The scale unit for this VPN Gateway. parExpressRouteGatewayScaleUnit | No | The scale unit for this ExpressRoute Gateway. parDdosEnabled | No | Switch to enable/disable DDoS Network Protection deployment. parDdosPlanName | No | DDoS Plan Name. +parDdosLock | No | Resource Lock Configuration for DDoS Plan. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. parPrivateDnsZonesEnabled | No | Switch to enable/disable Private DNS Zones deployment. parPrivateDnsZonesResourceGroup | No | Resource Group Name for Private DNS Zones. parPrivateDnsZones | No | Array of DNS Zones to provision in Hub Virtual Network. parPrivateDnsZoneAutoMergeAzureBackupZone | No | Set Parameter to false to skip the addition of a Private DNS Zone for Azure Backup. parVirtualNetworkIdToLink | No | Resource ID of VNet for Private DNS Zone VNet Links parVirtualNetworkIdToLinkFailover | No | Resource ID of Failover VNet for Private DNS Zone VNet Failover Links +parPrivateDNSZonesLock | No | Resource Lock Configuration for Private DNS Zone(s). - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. parTags | No | Tags you would like to be applied to all resources in this module. parTelemetryOptOut | No | Set Parameter to true to Opt-out of deployment telemetry @@ -50,6 +58,19 @@ Prefix value which will be prepended to all resource names. - Default value: `alz` +### parGlobalResourceLock + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Global Resource Lock Configuration used for all resources deployed in this module. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep vWAN Connectivity Module.}` + ### parAzFirewallTier ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) @@ -64,7 +85,7 @@ Azure Firewall Tier associated with the Firewall to deploy. ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) -The Azure Firewall Threat Intelligence Mode. If not set, the default value is Alert. +The Azure Firewall Threat Intelligence Mode. - Default value: `Alert` @@ -90,7 +111,7 @@ Switch to enable/disable Azure Firewall DNS Proxy. ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) -Array of custom DNS servers used by Azure Firewall +Array of custom DNS servers used by Azure Firewall. ### parVirtualWanName @@ -100,6 +121,19 @@ Prefix Used for Virtual WAN. - Default value: `[format('{0}-vwan-{1}', parameters('parCompanyPrefix'), parameters('parLocation'))]` +### parVirtualWanLock + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Resource Lock Configuration for Virtual WAN. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep vWAN Connectivity Module.}` + ### parVirtualWanHubName ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) @@ -125,11 +159,50 @@ Array Used for multiple Virtual WAN Hubs deployment. Each object in the array re +### parVpnGatewayLock + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Resource Lock Configuration for Virtual WAN Hub VPN Gateway. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep vWAN Connectivity Module.}` + +### parExpressRouteGatewayLock + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Resource Lock Configuration for Virtual WAN Hub ExpressRoute Gateway. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep vWAN Connectivity Module.}` + +### parVirtualWanHubsLock + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Resource Lock Configuration for Virtual WAN Hub. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep vWAN Connectivity Module.}` + ### parVpnGatewayName ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) -Prefix Used for VPN Gateway. +VPN Gateway Name. - Default value: `[format('{0}-vpngw', parameters('parCompanyPrefix'))]` @@ -137,7 +210,7 @@ Prefix Used for VPN Gateway. ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) -Prefix Used for ExpressRoute Gateway. +ExpressRoute Gateway Name. - Default value: `[format('{0}-ergw', parameters('parCompanyPrefix'))]` @@ -165,6 +238,19 @@ Azure Firewall Policies Name. - Default value: `[format('{0}-azfwpolicy-{1}', parameters('parCompanyPrefix'), parameters('parLocation'))]` +### parAzureFirewallLock + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Resource Lock Configuration for Azure Firewall. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep vWAN Connectivity Module.}` + ### parVpnGatewayScaleUnit ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) @@ -197,6 +283,19 @@ DDoS Plan Name. - Default value: `[format('{0}-ddos-plan', parameters('parCompanyPrefix'))]` +### parDdosLock + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Resource Lock Configuration for DDoS Plan. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep vWAN Connectivity Module.}` + ### parPrivateDnsZonesEnabled ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) @@ -241,6 +340,19 @@ Resource ID of VNet for Private DNS Zone VNet Links Resource ID of Failover VNet for Private DNS Zone VNet Failover Links +### parPrivateDNSZonesLock + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Resource Lock Configuration for Private DNS Zone(s). + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep vWAN Connectivity Module.}` + ### parTags ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) @@ -286,6 +398,12 @@ outAzFwPrivateIps | array | "parCompanyPrefix": { "value": "alz" }, + "parGlobalResourceLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } + }, "parAzFirewallTier": { "value": "Standard" }, @@ -304,6 +422,12 @@ outAzFwPrivateIps | array | "parVirtualWanName": { "value": "[format('{0}-vwan-{1}', parameters('parCompanyPrefix'), parameters('parLocation'))]" }, + "parVirtualWanLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } + }, "parVirtualWanHubName": { "value": "[format('{0}-vhub', parameters('parCompanyPrefix'))]" }, @@ -321,6 +445,24 @@ outAzFwPrivateIps | array | } ] }, + "parVpnGatewayLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } + }, + "parExpressRouteGatewayLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } + }, + "parVirtualWanHubsLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } + }, "parVpnGatewayName": { "value": "[format('{0}-vpngw', parameters('parCompanyPrefix'))]" }, @@ -336,6 +478,12 @@ outAzFwPrivateIps | array | "parAzFirewallPoliciesName": { "value": "[format('{0}-azfwpolicy-{1}', parameters('parCompanyPrefix'), parameters('parLocation'))]" }, + "parAzureFirewallLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } + }, "parVpnGatewayScaleUnit": { "value": 1 }, @@ -348,6 +496,12 @@ outAzFwPrivateIps | array | "parDdosPlanName": { "value": "[format('{0}-ddos-plan', parameters('parCompanyPrefix'))]" }, + "parDdosLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } + }, "parPrivateDnsZonesEnabled": { "value": true }, @@ -434,6 +588,12 @@ outAzFwPrivateIps | array | "parVirtualNetworkIdToLinkFailover": { "value": "" }, + "parPrivateDNSZonesLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } + }, "parTags": { "value": {} }, diff --git a/dependencies/infra-as-code/bicep/modules/vwanConnectivity/parameters/mc-vwanConnectivity.parameters.all.json b/dependencies/infra-as-code/bicep/modules/vwanConnectivity/parameters/mc-vwanConnectivity.parameters.all.json index d61076f..0693e34 100644 --- a/dependencies/infra-as-code/bicep/modules/vwanConnectivity/parameters/mc-vwanConnectivity.parameters.all.json +++ b/dependencies/infra-as-code/bicep/modules/vwanConnectivity/parameters/mc-vwanConnectivity.parameters.all.json @@ -119,6 +119,54 @@ }, "parTelemetryOptOut": { "value": false + }, + "parGlobalResourceLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } + }, + "parVirtualWanLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } + }, + "parVirtualWanHubsLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } + }, + "parDdosLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } + }, + "parAzureFirewallLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } + }, + "parVpnGatewayLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } + }, + "parPrivateDNSZonesLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } + }, + "parExpressRouteGatewayLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } } } } diff --git a/dependencies/infra-as-code/bicep/modules/vwanConnectivity/parameters/vwanConnectivity.parameters.all.json b/dependencies/infra-as-code/bicep/modules/vwanConnectivity/parameters/vwanConnectivity.parameters.all.json index 34c8261..a35264e 100644 --- a/dependencies/infra-as-code/bicep/modules/vwanConnectivity/parameters/vwanConnectivity.parameters.all.json +++ b/dependencies/infra-as-code/bicep/modules/vwanConnectivity/parameters/vwanConnectivity.parameters.all.json @@ -161,6 +161,54 @@ }, "parTelemetryOptOut": { "value": false + }, + "parGlobalResourceLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } + }, + "parVirtualWanLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } + }, + "parVirtualWanHubsLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } + }, + "parDdosLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } + }, + "parAzureFirewallLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } + }, + "parVpnGatewayLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } + }, + "parPrivateDNSZonesLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } + }, + "parExpressRouteGatewayLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } } } } diff --git a/dependencies/infra-as-code/bicep/modules/vwanConnectivity/parameters/vwanConnectivity.parameters.az.all.json b/dependencies/infra-as-code/bicep/modules/vwanConnectivity/parameters/vwanConnectivity.parameters.az.all.json new file mode 100644 index 0000000..2b46305 --- /dev/null +++ b/dependencies/infra-as-code/bicep/modules/vwanConnectivity/parameters/vwanConnectivity.parameters.az.all.json @@ -0,0 +1,218 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "parLocation": { + "value": "eastus" + }, + "parCompanyPrefix": { + "value": "alz" + }, + "parAzFirewallTier": { + "value": "Standard" + }, + "parAzFirewallIntelMode": { + "value": "Alert" + }, + "parVirtualHubEnabled": { + "value": true + }, + "parAzFirewallDnsProxyEnabled": { + "value": true + }, + "parAzFirewallDnsServers": { + "value": [] + }, + "parVirtualWanName": { + "value": "alz-vwan-eastus" + }, + "parVirtualWanHubName": { + "value": "alz-vhub" + }, + "parVpnGatewayName": { + "value": "alz-vpngw" + }, + "parExpressRouteGatewayName": { + "value": "alz-ergw" + }, + "parAzFirewallName": { + "value": "alz-fw" + }, + "parAzFirewallAvailabilityZones": { + "value": [ + "1", + "2", + "3" + ] + }, + "parAzFirewallPoliciesName": { + "value": "alz-azfwpolicy-eastus" + }, + "parVirtualWanHubs": { + "value": [ + { + "parVpnGatewayEnabled": true, + "parExpressRouteGatewayEnabled": true, + "parAzFirewallEnabled": true, + "parVirtualHubAddressPrefix": "10.100.0.0/23", + "parHubLocation": "eastus", + "parHubRoutingPreference": "ExpressRoute", + "parVirtualRouterAutoScaleConfiguration": 2, + "parVirtualHubRoutingIntentDestinations": [] + } + ] + }, + "parVpnGatewayScaleUnit": { + "value": 1 + }, + "parExpressRouteGatewayScaleUnit": { + "value": 1 + }, + "parDdosEnabled": { + "value": true + }, + "parDdosPlanName": { + "value": "alz-ddos-plan" + }, + "parPrivateDnsZonesEnabled": { + "value": true + }, + "parPrivateDnsZones": { + "value": [ + "privatelink.xxxxxx.azmk8s.io", // Replace xxxxxx with target region (i.e. eastus) + "privatelink.xxxxxx.batch.azure.com", // Replace xxxxxx with target region (i.e. eastus) + "privatelink.xxxxxx.kusto.windows.net", // Replace xxxxxx with target region (i.e. eastus) + "privatelink.xxxxxx.backup.windowsazure.com", // Replace xxxxxx with target region geo code (i.e. for eastus, the geo code is eus) + "privatelink.adf.azure.com", + "privatelink.afs.azure.net", + "privatelink.agentsvc.azure-automation.net", + "privatelink.analysis.windows.net", + "privatelink.api.azureml.ms", + "privatelink.azconfig.io", + "privatelink.azure-api.net", + "privatelink.azure-automation.net", + "privatelink.azurecr.io", + "privatelink.azure-devices.net", + "privatelink.azure-devices-provisioning.net", + "privatelink.azuredatabricks.net", + "privatelink.azurehdinsight.net", + "privatelink.azurehealthcareapis.com", + "privatelink.azurestaticapps.net", + "privatelink.azuresynapse.net", + "privatelink.azurewebsites.net", + "privatelink.batch.azure.com", + "privatelink.blob.core.windows.net", + "privatelink.cassandra.cosmos.azure.com", + "privatelink.cognitiveservices.azure.com", + "privatelink.database.windows.net", + "privatelink.datafactory.azure.net", + "privatelink.dev.azuresynapse.net", + "privatelink.dfs.core.windows.net", + "privatelink.dicom.azurehealthcareapis.com", + "privatelink.digitaltwins.azure.net", + "privatelink.directline.botframework.com", + "privatelink.documents.azure.com", + "privatelink.eventgrid.azure.net", + "privatelink.file.core.windows.net", + "privatelink.gremlin.cosmos.azure.com", + "privatelink.guestconfiguration.azure.com", + "privatelink.his.arc.azure.com", + "privatelink.kubernetesconfiguration.azure.com", + "privatelink.managedhsm.azure.net", + "privatelink.mariadb.database.azure.com", + "privatelink.media.azure.net", + "privatelink.mongo.cosmos.azure.com", + "privatelink.monitor.azure.com", + "privatelink.mysql.database.azure.com", + "privatelink.notebooks.azure.net", + "privatelink.ods.opinsights.azure.com", + "privatelink.oms.opinsights.azure.com", + "privatelink.pbidedicated.windows.net", + "privatelink.postgres.database.azure.com", + "privatelink.prod.migration.windowsazure.com", + "privatelink.purview.azure.com", + "privatelink.purviewstudio.azure.com", + "privatelink.queue.core.windows.net", + "privatelink.redis.cache.windows.net", + "privatelink.redisenterprise.cache.azure.net", + "privatelink.search.windows.net", + "privatelink.service.signalr.net", + "privatelink.servicebus.windows.net", + "privatelink.siterecovery.windowsazure.com", + "privatelink.sql.azuresynapse.net", + "privatelink.table.core.windows.net", + "privatelink.table.cosmos.azure.com", + "privatelink.tip1.powerquery.microsoft.com", + "privatelink.token.botframework.com", + "privatelink.vaultcore.azure.net", + "privatelink.web.core.windows.net", + "privatelink.webpubsub.azure.com" + ] + }, + "parPrivateDnsZoneAutoMergeAzureBackupZone": { + "value": true + }, + "parVirtualNetworkIdToLink": { + "value": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/HUB_Networking_POC/providers/Microsoft.Network/virtualNetworks/alz-hub-eastus" + }, + "parTags": { + "value": { + "Environment": "Live" + } + }, + "parVirtualNetworkIdToLinkFailover": { + "value": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/HUB_Networking_POC/providers/Microsoft.Network/virtualNetworks/alz-hub-eastus-failover" + }, + "parTelemetryOptOut": { + "value": false + }, + "parGlobalResourceLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } + }, + "parVirtualWanLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } + }, + "parVirtualWanHubsLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } + }, + "parDdosLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } + }, + "parAzureFirewallLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } + }, + "parVpnGatewayLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } + }, + "parPrivateDNSZonesLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } + }, + "parExpressRouteGatewayLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep vWAN Connectivity Module." + } + } + } +} diff --git a/dependencies/infra-as-code/bicep/modules/vwanConnectivity/samples/baseline.sample.bicep b/dependencies/infra-as-code/bicep/modules/vwanConnectivity/samples/baseline.sample.bicep index 1b7bfb3..62c363c 100644 --- a/dependencies/infra-as-code/bicep/modules/vwanConnectivity/samples/baseline.sample.bicep +++ b/dependencies/infra-as-code/bicep/modules/vwanConnectivity/samples/baseline.sample.bicep @@ -29,8 +29,8 @@ module minimum_vwan_conn '../vwanConnectivity.bicep' = { parAzFirewallEnabled: true parVirtualHubAddressPrefix: '10.100.0.0/23' parHubLocation: 'centralus' - parhubRoutingPreference: 'ExpressRoute' //allowed values are 'ASN','VpnGateway','ExpressRoute' - parvirtualRouterAutoScaleConfiguration: 2 //minimum capacity should be between 2 to 50 + parHubRoutingPreference: 'ExpressRoute' //allowed values are 'ASN','VpnGateway','ExpressRoute' + parVirtualRouterAutoScaleConfiguration: 2 //minimum capacity should be between 2 to 50 parVirtualHubRoutingIntentDestinations: [] } ] parAzFirewallDnsProxyEnabled: true diff --git a/dependencies/infra-as-code/bicep/modules/vwanConnectivity/vwanConnectivity.bicep b/dependencies/infra-as-code/bicep/modules/vwanConnectivity/vwanConnectivity.bicep index 84e683c..955f575 100644 --- a/dependencies/infra-as-code/bicep/modules/vwanConnectivity/vwanConnectivity.bicep +++ b/dependencies/infra-as-code/bicep/modules/vwanConnectivity/vwanConnectivity.bicep @@ -1,12 +1,74 @@ metadata name = 'ALZ Bicep - Azure vWAN Connectivity Module' metadata description = 'Module used to set up vWAN Connectivity' +type virtualWanOptionsType = ({ + @sys.description('Switch to enable/disable VPN Gateway deployment on the respective Virtual WAN Hub.') + parVpnGatewayEnabled: bool + + @sys.description('Switch to enable/disable ExpressRoute Gateway deployment on the respective Virtual WAN Hub.') + parExpressRouteGatewayEnabled: bool + + @sys.description('Switch to enable/disable Azure Firewall deployment on the respective Virtual WAN Hub.') + parAzFirewallEnabled: bool + + @sys.description('The IP address range in CIDR notation for the vWAN virtual Hub to use.') + parVirtualHubAddressPrefix: string + + @sys.description('The Virtual WAN Hub location.') + parHubLocation: string + + @sys.description('The Virtual WAN Hub routing preference. The allowed values are `ASN`, `VpnGateway`, `ExpressRoute`.') + parHubRoutingPreference: ('ExpressRoute' | 'VpnGateway' | 'ASN') + + @sys.description('The Virtual WAN Hub capacity. The value should be between 2 to 50.') + @minValue(2) + @maxValue(50) + parVirtualRouterAutoScaleConfiguration: int + + @sys.description('The Virtual WAN Hub routing intent destinations, leave empty if not wanting to enable routing intent. The allowed values are `Internet`, `PrivateTraffic`.') + parVirtualHubRoutingIntentDestinations: ('Internet' | 'PrivateTraffic')[] + + @sys.description('This parameter is used to specify a custom name for the VPN Gateway.') + parVpnGatewayCustomName: string? + + @sys.description('This parameter is used to specify a custom name for the ExpressRoute Gateway.') + parExpressRouteGatewayCustomName: string? + + @sys.description('This parameter is used to specify a custom name for the Azure Firewall.') + parAzFirewallCustomName: string? + + @sys.description('This parameter is used to specify a custom name for the Virtual WAN Hub.') + parVirtualWanHubCustomName: string? +})[] + +type lockType = { + @description('Optional. Specify the name of lock.') + name: string? + + @description('Optional. The lock settings of the service.') + kind: ('CanNotDelete' | 'ReadOnly' | 'None') + + @description('Optional. Notes about this lock.') + notes: string? +} + @sys.description('Region in which the resource group was created.') param parLocation string = resourceGroup().location @sys.description('Prefix value which will be prepended to all resource names.') param parCompanyPrefix string = 'alz' +@sys.description('''Global Resource Lock Configuration used for all resources deployed in this module. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parGlobalResourceLock lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep vWAN Connectivity Module.' +} + @sys.description('Azure Firewall Tier associated with the Firewall to deploy.') @allowed([ 'Basic' @@ -15,7 +77,7 @@ param parCompanyPrefix string = 'alz' ]) param parAzFirewallTier string = 'Standard' -@sys.description('The Azure Firewall Threat Intelligence Mode. If not set, the default value is Alert.') +@sys.description('The Azure Firewall Threat Intelligence Mode.') @allowed([ 'Alert' 'Deny' @@ -29,12 +91,23 @@ param parVirtualHubEnabled bool = true @sys.description('Switch to enable/disable Azure Firewall DNS Proxy.') param parAzFirewallDnsProxyEnabled bool = true -@sys.description('Array of custom DNS servers used by Azure Firewall') +@sys.description('Array of custom DNS servers used by Azure Firewall.') param parAzFirewallDnsServers array = [] @sys.description('Prefix Used for Virtual WAN.') param parVirtualWanName string = '${parCompanyPrefix}-vwan-${parLocation}' +@sys.description('''Resource Lock Configuration for Virtual WAN. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parVirtualWanLock lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep vWAN Connectivity Module.' +} + @sys.description('Prefix Used for Virtual WAN Hub.') param parVirtualWanHubName string = '${parCompanyPrefix}-vhub' @@ -50,22 +123,55 @@ param parVirtualWanHubName string = '${parCompanyPrefix}-vhub' - `parVirtualHubRoutingIntentDestinations` - The Virtual WAN Hub routing intent destinations, leave empty if not wanting to enable routing intent. The allowed values are `Internet`, `PrivateTraffic`. ''') -param parVirtualWanHubs array = [ { +param parVirtualWanHubs virtualWanOptionsType = [ { parVpnGatewayEnabled: true parExpressRouteGatewayEnabled: true parAzFirewallEnabled: true parVirtualHubAddressPrefix: '10.100.0.0/23' parHubLocation: parLocation - parHubRoutingPreference: 'ExpressRoute' //allowed values are 'ASN','VpnGateway','ExpressRoute'. - parVirtualRouterAutoScaleConfiguration: 2 //minimum capacity should be between 2 to 50 + parHubRoutingPreference: 'ExpressRoute' + parVirtualRouterAutoScaleConfiguration: 2 parVirtualHubRoutingIntentDestinations: [] } ] -@sys.description('Prefix Used for VPN Gateway.') +@sys.description('''Resource Lock Configuration for Virtual WAN Hub VPN Gateway. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parVpnGatewayLock lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep vWAN Connectivity Module.' +} + +@sys.description('''Resource Lock Configuration for Virtual WAN Hub ExpressRoute Gateway. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parExpressRouteGatewayLock lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep vWAN Connectivity Module.' +} + +@sys.description('''Resource Lock Configuration for Virtual WAN Hub. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parVirtualWanHubsLock lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep vWAN Connectivity Module.' +} + +@sys.description('VPN Gateway Name.') param parVpnGatewayName string = '${parCompanyPrefix}-vpngw' -@sys.description('Prefix Used for ExpressRoute Gateway.') +@sys.description('ExpressRoute Gateway Name.') param parExpressRouteGatewayName string = '${parCompanyPrefix}-ergw' @sys.description('Azure Firewall Name.') @@ -82,6 +188,17 @@ param parAzFirewallAvailabilityZones array = [] @sys.description('Azure Firewall Policies Name.') param parAzFirewallPoliciesName string = '${parCompanyPrefix}-azfwpolicy-${parLocation}' +@sys.description('''Resource Lock Configuration for Azure Firewall. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parAzureFirewallLock lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep vWAN Connectivity Module.' +} + @sys.description('The scale unit for this VPN Gateway.') param parVpnGatewayScaleUnit int = 1 @@ -94,6 +211,17 @@ param parDdosEnabled bool = true @sys.description('DDoS Plan Name.') param parDdosPlanName string = '${parCompanyPrefix}-ddos-plan' +@sys.description('''Resource Lock Configuration for DDoS Plan. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parDdosLock lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep vWAN Connectivity Module.' +} + @sys.description('Switch to enable/disable Private DNS Zones deployment.') param parPrivateDnsZonesEnabled bool = true @@ -180,6 +308,17 @@ param parVirtualNetworkIdToLink string = '' @sys.description('Resource ID of Failover VNet for Private DNS Zone VNet Failover Links') param parVirtualNetworkIdToLinkFailover string = '' +@sys.description('''Resource Lock Configuration for Private DNS Zone(s). + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parPrivateDNSZonesLock lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep vWAN Connectivity Module.' +} + @sys.description('Tags you would like to be applied to all resources in this module.') param parTags object = {} @@ -209,8 +348,18 @@ resource resVwan 'Microsoft.Network/virtualWans@2023-04-01' = { } } +// Create a Virtual WAN resource lock if parGlobalResourceLock.kind is not set to None and if parVirtualWanLock.kind is not set to None +resource resVwanLock 'Microsoft.Authorization/locks@2020-05-01' = if (parGlobalResourceLock.kind != 'None' && parVirtualWanLock.kind != 'None') { + scope: resVwan + name: parVirtualWanLock.?name ?? '${resVwan.name}-lock' + properties: { + level: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.kind : parVirtualWanLock.kind + notes: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.?notes : parVirtualWanLock.?notes + } +} + resource resVhub 'Microsoft.Network/virtualHubs@2023-04-01' = [for hub in parVirtualWanHubs: if (parVirtualHubEnabled && !empty(hub.parVirtualHubAddressPrefix)) { - name: '${parVirtualWanHubName}-${hub.parHubLocation}' + name: hub.?parVirtualWanHubCustomName ?? '${parVirtualWanHubName}-${hub.parHubLocation}' location: hub.parHubLocation tags: parTags properties: { @@ -226,6 +375,16 @@ resource resVhub 'Microsoft.Network/virtualHubs@2023-04-01' = [for hub in parVir } }] +// Create a Virtual WAN Hub resource lock for each Virtual WAN Hub in parVirtualWanHubs if parGlobalResourceLock.kind is not set to None and if parVirtualWanHubsLock.kind is not set to None +resource resVhubLock 'Microsoft.Authorization/locks@2020-05-01' = [for (hub, i) in parVirtualWanHubs: if (parGlobalResourceLock.kind != 'None' && parVirtualWanHubsLock.kind != 'None') { + scope: resVhub[i] + name: parVirtualWanHubsLock.?name ?? '${resVhub[i].name}-lock' + properties: { + level: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.kind : parVirtualWanHubsLock.kind + notes: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.?notes : parVirtualWanHubsLock.?notes + } +}] + resource resVhubRouteTable 'Microsoft.Network/virtualHubs/hubRouteTables@2023-04-01' = [for (hub, i) in parVirtualWanHubs: if (parVirtualHubEnabled && hub.parAzFirewallEnabled && empty(hub.parVirtualHubRoutingIntentDestinations)) { parent: resVhub[i] name: 'defaultRouteTable' @@ -249,7 +408,7 @@ resource resVhubRouteTable 'Microsoft.Network/virtualHubs/hubRouteTables@2023-04 resource resVhubRoutingIntent 'Microsoft.Network/virtualHubs/routingIntent@2023-04-01' = [for (hub, i) in parVirtualWanHubs: if (parVirtualHubEnabled && hub.parAzFirewallEnabled && !empty(hub.parVirtualHubRoutingIntentDestinations)) { parent: resVhub[i] - name: '${parVirtualWanHubName}-${hub.parHubLocation}-Routing-Intent' + name: !empty(hub.?parVirtualWanHubCustomName) ? '${hub.parVirtualWanHubCustomName}-Routing-Intent' : '${parVirtualWanHubName}-${hub.parHubLocation}-Routing-Intent' properties: { routingPolicies: [for destination in hub.parVirtualHubRoutingIntentDestinations: { name: destination == 'Internet' ? 'PublicTraffic' : destination == 'PrivateTraffic' ? 'PrivateTraffic' : 'N/A' @@ -263,7 +422,7 @@ resource resVhubRoutingIntent 'Microsoft.Network/virtualHubs/routingIntent@2023- resource resVpnGateway 'Microsoft.Network/vpnGateways@2023-02-01' = [for (hub, i) in parVirtualWanHubs: if ((parVirtualHubEnabled) && (hub.parVpnGatewayEnabled)) { dependsOn: resVhub - name: '${parVpnGatewayName}-${hub.parHubLocation}' + name: hub.?parVpnGatewayCustomName ?? '${parVpnGatewayName}-${hub.parHubLocation}' location: hub.parHubLocation tags: parTags properties: { @@ -279,9 +438,19 @@ resource resVpnGateway 'Microsoft.Network/vpnGateways@2023-02-01' = [for (hub, i } }] +// Create a Virtual Network Gateway resource lock if gateway.name is not equal to noconfigVpn or noconfigEr and parGlobalResourceLock.kind != 'None' or if parVpnGatewayLock.kind != 'None' +resource resVpnGatewayLock 'Microsoft.Authorization/locks@2020-05-01' = [for (hub, i) in parVirtualWanHubs: if ((parVirtualHubEnabled) && (hub.parVpnGatewayEnabled) && (parVpnGatewayLock.kind != 'None' || parGlobalResourceLock.kind != 'None')) { + scope: resVpnGateway[i] + name: parVpnGatewayLock.?name ?? '${resVpnGateway[i].name}-lock' + properties: { + level: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.kind : parVpnGatewayLock.kind + notes: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.?notes : parVpnGatewayLock.?notes + } +}] + resource resErGateway 'Microsoft.Network/expressRouteGateways@2023-02-01' = [for (hub, i) in parVirtualWanHubs: if ((parVirtualHubEnabled) && (hub.parExpressRouteGatewayEnabled)) { dependsOn: resVhub - name: '${parExpressRouteGatewayName}-${hub.parHubLocation}' + name: hub.?parExpressRouteGatewayCustomName ?? '${parExpressRouteGatewayName}-${hub.parHubLocation}' location: hub.parHubLocation tags: parTags properties: { @@ -296,6 +465,16 @@ resource resErGateway 'Microsoft.Network/expressRouteGateways@2023-02-01' = [for } }] +// Create a Virtual Network Gateway resource lock if gateway.name is not equal to noconfigVpn or noconfigEr and parGlobalResourceLock.kind != 'None' or if parVpnGatewayLock.kind != 'None' +resource resErGatewayLock 'Microsoft.Authorization/locks@2020-05-01' = [for (hub, i) in parVirtualWanHubs: if ((parVirtualHubEnabled) && (hub.parExpressRouteGatewayEnabled) && (parExpressRouteGatewayLock.kind != 'None' || parGlobalResourceLock.kind != 'None')) { + scope: resVpnGateway[i] + name: parExpressRouteGatewayLock.?name ?? '${resErGateway[i].name}-lock' + properties: { + level: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.kind : parExpressRouteGatewayLock.kind + notes: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.?notes : parExpressRouteGatewayLock.?notes + } +}] + resource resFirewallPolicies 'Microsoft.Network/firewallPolicies@2023-02-01' = if (parVirtualHubEnabled && parVirtualWanHubs[0].parAzFirewallEnabled) { name: parAzFirewallPoliciesName location: parLocation @@ -317,8 +496,18 @@ resource resFirewallPolicies 'Microsoft.Network/firewallPolicies@2023-02-01' = i } } +// Create Azure Firewall Policy resource lock if parAzFirewallEnabled is true and parGlobalResourceLock.kind != 'None' or if parAzureFirewallLock.kind != 'None' +resource resFirewallPoliciesLock 'Microsoft.Authorization/locks@2020-05-01' = if ((parVirtualHubEnabled && parVirtualWanHubs[0].parAzFirewallEnabled) && (parAzureFirewallLock.kind != 'None' || parGlobalResourceLock.kind != 'None')) { + scope: resFirewallPolicies + name: parAzureFirewallLock.?name ?? '${resFirewallPolicies.name}-lock' + properties: { + level: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.kind : parAzureFirewallLock.kind + notes: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.?notes : parAzureFirewallLock.?notes + } +} + resource resAzureFirewall 'Microsoft.Network/azureFirewalls@2023-02-01' = [for (hub, i) in parVirtualWanHubs: if ((parVirtualHubEnabled) && (hub.parAzFirewallEnabled)) { - name: '${parAzFirewallName}-${hub.parHubLocation}' + name: hub.?parAzFirewallCustomName ?? '${parAzFirewallName}-${hub.parHubLocation}' location: hub.parHubLocation tags: parTags zones: (!empty(parAzFirewallAvailabilityZones) ? parAzFirewallAvailabilityZones : null) @@ -341,6 +530,16 @@ resource resAzureFirewall 'Microsoft.Network/azureFirewalls@2023-02-01' = [for ( } }] +// Create Azure Firewall resource lock if parAzFirewallEnabled is true and parGlobalResourceLock.kind != 'None' or if parAzureFirewallLock.kind != 'None' +resource resAzureFirewallLock 'Microsoft.Authorization/locks@2020-05-01' = [for (hub, i) in parVirtualWanHubs: if ((parVirtualHubEnabled) && (hub.parAzFirewallEnabled) && (parAzureFirewallLock.kind != 'None' || parGlobalResourceLock.kind != 'None')) { + scope: resAzureFirewall[i] + name: parAzureFirewallLock.?name ?? '${resAzureFirewall[i].name}-lock' + properties: { + level: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.kind : parAzureFirewallLock.kind + notes: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.?notes : parAzureFirewallLock.?notes + } +}] + // DDoS plan is deployed even though not supported to attach to Virtual WAN today as per https://docs.microsoft.com/azure/firewall-manager/overview#known-issues - However, it can still be linked via policy to spoke VNets etc. resource resDdosProtectionPlan 'Microsoft.Network/ddosProtectionPlans@2023-02-01' = if (parDdosEnabled) { name: parDdosPlanName @@ -348,6 +547,16 @@ resource resDdosProtectionPlan 'Microsoft.Network/ddosProtectionPlans@2023-02-01 tags: parTags } +// Create resource lock if parDdosEnabled is true and parGlobalResourceLock.kind != 'None' or if parDdosLock.kind != 'None' +resource resDDoSProtectionPlanLock 'Microsoft.Authorization/locks@2020-05-01' = if (parDdosEnabled && (parDdosLock.kind != 'None' || parGlobalResourceLock.kind != 'None')) { + scope: resDdosProtectionPlan + name: parDdosLock.?name ?? '${resDdosProtectionPlan.name}-lock' + properties: { + level: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.kind : parDdosLock.kind + notes: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock.?notes : parDdosLock.?notes + } +} + // Private DNS Zones cannot be linked to the Virtual WAN Hub today however, they can be linked to spokes as they are normal VNets as per https://docs.microsoft.com/azure/virtual-wan/howto-private-link module modPrivateDnsZones '../privateDnsZones/privateDnsZones.bicep' = if (parPrivateDnsZonesEnabled) { name: 'deploy-Private-DNS-Zones' @@ -359,6 +568,7 @@ module modPrivateDnsZones '../privateDnsZones/privateDnsZones.bicep' = if (parPr parPrivateDnsZoneAutoMergeAzureBackupZone: parPrivateDnsZoneAutoMergeAzureBackupZone parVirtualNetworkIdToLink: parVirtualNetworkIdToLink parVirtualNetworkIdToLinkFailover: parVirtualNetworkIdToLinkFailover + parResourceLockConfig: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock : parPrivateDNSZonesLock } } diff --git a/dependencies/infra-as-code/bicep/orchestration/hubPeeredSpoke/generateddocs/hubPeeredSpoke.bicep.md b/dependencies/infra-as-code/bicep/orchestration/hubPeeredSpoke/generateddocs/hubPeeredSpoke.bicep.md index cde35c4..106f167 100644 --- a/dependencies/infra-as-code/bicep/orchestration/hubPeeredSpoke/generateddocs/hubPeeredSpoke.bicep.md +++ b/dependencies/infra-as-code/bicep/orchestration/hubPeeredSpoke/generateddocs/hubPeeredSpoke.bicep.md @@ -12,8 +12,10 @@ parTopLevelManagementGroupSuffix | No | Optional suffix for the management parPeeredVnetSubscriptionId | No | Subscription Id to the Virtual Network Hub object. Default: Empty String parTags | No | Array of Tags to be applied to all resources in module. Default: Empty Object parTelemetryOptOut | No | Set Parameter to true to Opt-out of deployment telemetry. +parGlobalResourceLock | No | Global Resource Lock Configuration used for all resources deployed in this module. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. parPeeredVnetSubscriptionMgPlacement | No | The Management Group Id to place the subscription in. Default: Empty String parResourceGroupNameForSpokeNetworking | No | Name of Resource Group to be created to contain spoke networking resources like the virtual network. +parResourceGroupLock | No | Resource Group Lock Configuration. parDdosProtectionPlanId | No | Existing DDoS Protection plan to utilize. Default: Empty string parPrivateDnsZoneResourceIds | No | The Resource IDs of the Private DNS Zones to associate with spokes. Default: Empty Array parSpokeNetworkName | No | The Name of the Spoke Virtual Network. @@ -22,6 +24,9 @@ parDnsServerIps | No | Array of DNS Server IP addresses for VNet. Default: parNextHopIpAddress | No | IP Address where network traffic should route to. Default: Empty string parDisableBgpRoutePropagation | No | Switch which allows BGP Route Propogation to be disabled on the route table. parSpokeToHubRouteTableName | No | Name of Route table to create for the default route of Hub. +parSpokeNetworkLock | No | Resource Lock Configuration for Spoke Network. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. +parSpokeRouteTableLock | No | Resource Lock Configuration for Spoke Network Route Table. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. +parPrivateDnsZoneVirtualNetworkLinkLock | No | Resource Lock Configuration for Private DNS Virtual Network Network Links. - `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. - `notes` - Notes about this lock. parHubVirtualNetworkId | Yes | Virtual Network ID of Hub Virtual Network, or Azure Virtuel WAN hub ID. parAllowSpokeForwardedTraffic | No | Switch to enable/disable forwarded Traffic from outside spoke network. parAllowHubVpnGatewayTransit | No | Switch to enable/disable VPN Gateway for the hub network peering. @@ -71,6 +76,19 @@ Set Parameter to true to Opt-out of deployment telemetry. - Default value: `False` +### parGlobalResourceLock + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Global Resource Lock Configuration used for all resources deployed in this module. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep Hub Peered Spoke Orchestration Networking Module.}` + ### parPeeredVnetSubscriptionMgPlacement ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) @@ -85,6 +103,14 @@ Name of Resource Group to be created to contain spoke networking resources like - Default value: `[format('{0}-{1}-spoke-networking', parameters('parTopLevelManagementGroupPrefix'), parameters('parLocation'))]` +### parResourceGroupLock + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Resource Group Lock Configuration. + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep Hub Peered Spoke Orchestration Networking Module.}` + ### parDdosProtectionPlanId ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) @@ -141,6 +167,45 @@ Name of Route table to create for the default route of Hub. - Default value: `rtb-spoke-to-hub` +### parSpokeNetworkLock + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Resource Lock Configuration for Spoke Network. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep Hub Peered Spoke Orchestration Networking Module.}` + +### parSpokeRouteTableLock + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Resource Lock Configuration for Spoke Network Route Table. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep Hub Peered Spoke Orchestration Networking Module.}` + +### parPrivateDnsZoneVirtualNetworkLinkLock + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Resource Lock Configuration for Private DNS Virtual Network Network Links. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + + + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep Hub Peered Spoke Orchestration Networking Module.}` + ### parHubVirtualNetworkId ![Parameter Setting](https://img.shields.io/badge/parameter-required-orange?style=flat-square) @@ -222,12 +287,24 @@ outSpokeVirtualNetworkId | string | "parTelemetryOptOut": { "value": false }, + "parGlobalResourceLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Peered Spoke Orchestration Networking Module." + } + }, "parPeeredVnetSubscriptionMgPlacement": { "value": "" }, "parResourceGroupNameForSpokeNetworking": { "value": "[format('{0}-{1}-spoke-networking', parameters('parTopLevelManagementGroupPrefix'), parameters('parLocation'))]" }, + "parResourceGroupLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Peered Spoke Orchestration Networking Module." + } + }, "parDdosProtectionPlanId": { "value": "" }, @@ -252,6 +329,24 @@ outSpokeVirtualNetworkId | string | "parSpokeToHubRouteTableName": { "value": "rtb-spoke-to-hub" }, + "parSpokeNetworkLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Peered Spoke Orchestration Networking Module." + } + }, + "parSpokeRouteTableLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Peered Spoke Orchestration Networking Module." + } + }, + "parPrivateDnsZoneVirtualNetworkLinkLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Peered Spoke Orchestration Networking Module." + } + }, "parHubVirtualNetworkId": { "value": "" }, diff --git a/dependencies/infra-as-code/bicep/orchestration/hubPeeredSpoke/hubPeeredSpoke.bicep b/dependencies/infra-as-code/bicep/orchestration/hubPeeredSpoke/hubPeeredSpoke.bicep index e59e337..5296990 100644 --- a/dependencies/infra-as-code/bicep/orchestration/hubPeeredSpoke/hubPeeredSpoke.bicep +++ b/dependencies/infra-as-code/bicep/orchestration/hubPeeredSpoke/hubPeeredSpoke.bicep @@ -3,6 +3,17 @@ targetScope = 'managementGroup' metadata name = 'ALZ Bicep - Orchestration - Hub Peered Spoke' metadata description = 'Orchestration module used to create and configure a spoke network to deliver the Azure Landing Zone Hub & Spoke architecture' +type lockType = { + @description('Optional. Specify the name of lock.') + name: string? + + @description('Optional. The lock settings of the service.') + kind: ('CanNotDelete' | 'ReadOnly' | 'None') + + @description('Optional. Notes about this lock.') + notes: string? +} + // **Parameters** // Generic Parameters - Used in multiple modules @sys.description('The region to deploy all resources into.') @@ -26,6 +37,17 @@ param parTags object = {} @sys.description('Set Parameter to true to Opt-out of deployment telemetry.') param parTelemetryOptOut bool = false +@sys.description('''Global Resource Lock Configuration used for all resources deployed in this module. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parGlobalResourceLock lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep Hub Peered Spoke Orchestration Networking Module.' +} + // Subscription Module Parameters @sys.description('The Management Group Id to place the subscription in. Default: Empty String') param parPeeredVnetSubscriptionMgPlacement string = '' @@ -34,6 +56,12 @@ param parPeeredVnetSubscriptionMgPlacement string = '' @sys.description('Name of Resource Group to be created to contain spoke networking resources like the virtual network.') param parResourceGroupNameForSpokeNetworking string = '${parTopLevelManagementGroupPrefix}-${parLocation}-spoke-networking' +@sys.description('Resource Group Lock Configuration.') +param parResourceGroupLock lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep Hub Peered Spoke Orchestration Networking Module.' +} + // Spoke Networking Module Parameters @sys.description('Existing DDoS Protection plan to utilize. Default: Empty string') param parDdosProtectionPlanId string = '' @@ -59,6 +87,40 @@ param parDisableBgpRoutePropagation bool = false @sys.description('Name of Route table to create for the default route of Hub.') param parSpokeToHubRouteTableName string = 'rtb-spoke-to-hub' +@sys.description('''Resource Lock Configuration for Spoke Network. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parSpokeNetworkLock lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep Hub Peered Spoke Orchestration Networking Module.' +} + +@sys.description('''Resource Lock Configuration for Spoke Network Route Table. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parSpokeRouteTableLock lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep Hub Peered Spoke Orchestration Networking Module.' +} + +// Private DNS Link Module Parameters +@sys.description('''Resource Lock Configuration for Private DNS Virtual Network Network Links. + +- `kind` - The lock settings of the service which can be CanNotDelete, ReadOnly, or None. +- `notes` - Notes about this lock. + +''') +param parPrivateDnsZoneVirtualNetworkLinkLock lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep Hub Peered Spoke Orchestration Networking Module.' +} + // Peering Modules Parameters @sys.description('Virtual Network ID of Hub Virtual Network, or Azure Virtuel WAN hub ID.') param parHubVirtualNetworkId string @@ -146,6 +208,7 @@ module modResourceGroup '../../modules/resourceGroup/resourceGroup.bicep' = { parResourceGroupName: parResourceGroupNameForSpokeNetworking parTags: parTags parTelemetryOptOut: parTelemetryOptOut + parResourceLockConfig: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock : parResourceGroupLock } } @@ -167,6 +230,9 @@ module modSpokeNetworking '../../modules/spokeNetworking/spokeNetworking.bicep' parTags: parTags parTelemetryOptOut: parTelemetryOptOut parLocation: parLocation + parGlobalResourceLock: parGlobalResourceLock + parSpokeNetworkLock: parSpokeNetworkLock + parSpokeRouteTableLock: parSpokeRouteTableLock } } @@ -177,6 +243,7 @@ module modPrivateDnsZoneLinkToSpoke '../../modules/privateDnsZoneLinks/privateDn params: { parPrivateDnsZoneResourceId: zone parSpokeVirtualNetworkResourceId: modSpokeNetworking.outputs.outSpokeVirtualNetworkId + parResourceLockConfig: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock : parPrivateDnsZoneVirtualNetworkLinkLock } }] diff --git a/dependencies/infra-as-code/bicep/orchestration/hubPeeredSpoke/parameters/hubPeeredSpoke.parameters.all.json b/dependencies/infra-as-code/bicep/orchestration/hubPeeredSpoke/parameters/hubPeeredSpoke.parameters.all.json index 65328cd..6e7acd3 100644 --- a/dependencies/infra-as-code/bicep/orchestration/hubPeeredSpoke/parameters/hubPeeredSpoke.parameters.all.json +++ b/dependencies/infra-as-code/bicep/orchestration/hubPeeredSpoke/parameters/hubPeeredSpoke.parameters.all.json @@ -66,6 +66,36 @@ }, "parTelemetryOptOut": { "value": false + }, + "parGlobalResourceLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Peered Spoke Orchestration Networking Module." + } + }, + "parResourceGroupLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Peered Spoke Orchestration Networking Module." + } + }, + "parSpokeNetworkLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Peered Spoke Orchestration Networking Module." + } + }, + "parSpokeRouteTableLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Peered Spoke Orchestration Networking Module." + } + }, + "parPrivateDnsZoneVirtualNetworkLinkLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Peered Spoke Orchestration Networking Module." + } } } } diff --git a/dependencies/infra-as-code/bicep/orchestration/hubPeeredSpoke/parameters/hubPeeredSpoke.vwan.parameters.all.json b/dependencies/infra-as-code/bicep/orchestration/hubPeeredSpoke/parameters/hubPeeredSpoke.vwan.parameters.all.json index 0b147eb..8a3ccd8 100644 --- a/dependencies/infra-as-code/bicep/orchestration/hubPeeredSpoke/parameters/hubPeeredSpoke.vwan.parameters.all.json +++ b/dependencies/infra-as-code/bicep/orchestration/hubPeeredSpoke/parameters/hubPeeredSpoke.vwan.parameters.all.json @@ -63,6 +63,36 @@ }, "parTelemetryOptOut": { "value": false + }, + "parGlobalResourceLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Peered Spoke Orchestration Networking Module." + } + }, + "parResourceGroupLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Peered Spoke Orchestration Networking Module." + } + }, + "parSpokeNetworkLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Peered Spoke Orchestration Networking Module." + } + }, + "parSpokeRouteTableLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Peered Spoke Orchestration Networking Module." + } + }, + "parPrivateDnsZoneVirtualNetworkLinkLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Peered Spoke Orchestration Networking Module." + } } } } diff --git a/dependencies/infra-as-code/bicep/orchestration/mgDiagSettingsAll/generateddocs/mgDiagSettingsAll.bicep.md b/dependencies/infra-as-code/bicep/orchestration/mgDiagSettingsAll/generateddocs/mgDiagSettingsAll.bicep.md index c079b87..20d8f7c 100644 --- a/dependencies/infra-as-code/bicep/orchestration/mgDiagSettingsAll/generateddocs/mgDiagSettingsAll.bicep.md +++ b/dependencies/infra-as-code/bicep/orchestration/mgDiagSettingsAll/generateddocs/mgDiagSettingsAll.bicep.md @@ -11,6 +11,7 @@ parTopLevelManagementGroupSuffix | No | Optional suffix for the management parLandingZoneMgChildren | No | Array of strings to allow additional or different child Management Groups of the Landing Zones Management Group. parPlatformMgChildren | No | Array of strings to allow additional or different child Management Groups of the Platform Management Group. parLogAnalyticsWorkspaceResourceId | Yes | Log Analytics Workspace Resource ID. +parDiagnosticSettingsName | No | Diagnostic Settings Name. parLandingZoneMgAlzDefaultsEnable | No | Deploys Diagnostic Settings on Corp & Online Management Groups beneath Landing Zones Management Group if set to true. parPlatformMgAlzDefaultsEnable | No | Deploys Diagnostic Settings on Management, Connectivity and Identity Management Groups beneath Platform Management Group if set to true. parLandingZoneMgConfidentialEnable | No | Deploys Diagnostic Settings on Confidential Corp & Confidential Online Management Groups beneath Landing Zones Management Group if set to true. @@ -48,6 +49,14 @@ Array of strings to allow additional or different child Management Groups of the Log Analytics Workspace Resource ID. +### parDiagnosticSettingsName + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Diagnostic Settings Name. + +- Default value: `toLa` + ### parLandingZoneMgAlzDefaultsEnable ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) @@ -107,6 +116,9 @@ Set Parameter to true to Opt-out of deployment telemetry. "parLogAnalyticsWorkspaceResourceId": { "value": "" }, + "parDiagnosticSettingsName": { + "value": "toLa" + }, "parLandingZoneMgAlzDefaultsEnable": { "value": true }, diff --git a/dependencies/infra-as-code/bicep/orchestration/mgDiagSettingsAll/mgDiagSettingsAll.bicep b/dependencies/infra-as-code/bicep/orchestration/mgDiagSettingsAll/mgDiagSettingsAll.bicep index efdaecb..463a1c6 100644 --- a/dependencies/infra-as-code/bicep/orchestration/mgDiagSettingsAll/mgDiagSettingsAll.bicep +++ b/dependencies/infra-as-code/bicep/orchestration/mgDiagSettingsAll/mgDiagSettingsAll.bicep @@ -21,6 +21,9 @@ param parPlatformMgChildren array = [] @sys.description('Log Analytics Workspace Resource ID.') param parLogAnalyticsWorkspaceResourceId string +@sys.description('Diagnostic Settings Name.') +param parDiagnosticSettingsName string = 'toLa' + @sys.description('Deploys Diagnostic Settings on Corp & Online Management Groups beneath Landing Zones Management Group if set to true.') param parLandingZoneMgAlzDefaultsEnable bool = true @@ -84,6 +87,7 @@ module modMgDiagSet '../../modules/mgDiagSettings/mgDiagSettings.bicep' = [for m name: 'mg-diag-set-${mgId.value}' params: { parLogAnalyticsWorkspaceResourceId: parLogAnalyticsWorkspaceResourceId + parDiagnosticSettingsName: parDiagnosticSettingsName parTelemetryOptOut: parTelemetryOptOut } }] @@ -94,6 +98,7 @@ module modMgLandingZonesDiagSet '../../modules/mgDiagSettings/mgDiagSettings.bic name: 'mg-diag-set-${childMg.value}' params: { parLogAnalyticsWorkspaceResourceId: parLogAnalyticsWorkspaceResourceId + parDiagnosticSettingsName: parDiagnosticSettingsName parTelemetryOptOut: parTelemetryOptOut } }] @@ -104,6 +109,7 @@ module modMgPlatformDiagSet '../../modules/mgDiagSettings/mgDiagSettings.bicep' name: 'mg-diag-set-${childMg.value}' params: { parLogAnalyticsWorkspaceResourceId: parLogAnalyticsWorkspaceResourceId + parDiagnosticSettingsName: parDiagnosticSettingsName parTelemetryOptOut: parTelemetryOptOut } }] @@ -114,6 +120,7 @@ module modMgChildrenDiagSet '../../modules/mgDiagSettings/mgDiagSettings.bicep' name: 'mg-diag-set-${childMg.mgId}' params: { parLogAnalyticsWorkspaceResourceId: parLogAnalyticsWorkspaceResourceId + parDiagnosticSettingsName: parDiagnosticSettingsName parTelemetryOptOut: parTelemetryOptOut } }] @@ -124,6 +131,7 @@ module modPlatformMgChildrenDiagSet '../../modules/mgDiagSettings/mgDiagSettings name: 'mg-diag-set-${childMg.mgId}' params: { parLogAnalyticsWorkspaceResourceId: parLogAnalyticsWorkspaceResourceId + parDiagnosticSettingsName: parDiagnosticSettingsName parTelemetryOptOut: parTelemetryOptOut } }] diff --git a/dependencies/infra-as-code/bicep/orchestration/mgDiagSettingsAll/parameters/mgDiagSettingsAll.parameters.all.json b/dependencies/infra-as-code/bicep/orchestration/mgDiagSettingsAll/parameters/mgDiagSettingsAll.parameters.all.json index 47a5ee1..c03bb09 100644 --- a/dependencies/infra-as-code/bicep/orchestration/mgDiagSettingsAll/parameters/mgDiagSettingsAll.parameters.all.json +++ b/dependencies/infra-as-code/bicep/orchestration/mgDiagSettingsAll/parameters/mgDiagSettingsAll.parameters.all.json @@ -20,6 +20,9 @@ "parLogAnalyticsWorkspaceResourceId": { "value": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/alz-logging/providers/microsoft.operationalinsights/workspaces/alz-log-analytics" }, + "parDiagnosticSettingsName": { + "value": "toLa" + }, "parLandingZoneMgChildren": { "value": [] }, diff --git a/dependencies/scripts/Invoke-LibraryUpdate-China.ps1 b/dependencies/scripts/Invoke-LibraryUpdate-China.ps1 index 12aa523..e49f883 100644 --- a/dependencies/scripts/Invoke-LibraryUpdate-China.ps1 +++ b/dependencies/scripts/Invoke-LibraryUpdate-China.ps1 @@ -60,16 +60,16 @@ $defaultConfig = @{ # File locations from Enterprise-scale repository for # resources, organised by type $policyDefinitionFilePaths = ( - Get-ChildItem -Path "$SourcePath/src/resources/Microsoft.Authorization/policyDefinitions/*" ` - -File ` - -Include "*.json", "*.AzureChinaCloud.json" ` - -Exclude "*.AzureUSGovernment.json" + Get-ChildItem -Path "$SourcePath/src/resources/Microsoft.Authorization/policyDefinitions/*" ` + -File ` + -Include "*.json", "*.AzureChinaCloud.json" ` + -Exclude "*.AzureUSGovernment.json" ).FullName $policySetDefinitionFilePaths = ( - Get-ChildItem -Path "$SourcePath/src/resources/Microsoft.Authorization/policySetDefinitions/*" ` - -File ` - -Include "*.json", "*.AzureChinaCloud.json" ` - -Exclude "*.AzureUSGovernment.json" + Get-ChildItem -Path "$SourcePath/src/resources/Microsoft.Authorization/policySetDefinitions/*" ` + -File ` + -Include "*.json", "*.AzureChinaCloud.json" ` + -Exclude "*.AzureUSGovernment.json" ).FullName # The exportConfig array controls the foreach loop used to run # Export-LibraryArtifact. Each object provides a set of values diff --git a/dependencies/scripts/Invoke-PolicyToBicep-China.ps1 b/dependencies/scripts/Invoke-PolicyToBicep-China.ps1 index e629ee5..e1e659c 100644 --- a/dependencies/scripts/Invoke-PolicyToBicep-China.ps1 +++ b/dependencies/scripts/Invoke-PolicyToBicep-China.ps1 @@ -13,8 +13,6 @@ param ( [string] $rootPath = "./infra-as-code/bicep/modules/policy", [string] - $alzToolsPath = "$PWD/../Enterprise-Scale/src/Alz.Tools", - [string] $definitionsRoot = "definitions", [string] $lineEnding = "unix", @@ -43,8 +41,15 @@ param ( ) # This script relies on a custom set of classes and functions -# defined within the Alz.Tools PowerShell module. -Import-Module $alzToolsPath -ErrorAction Stop +# defined within the [ALZ-PowerShell-Module](https://github.com/Azure/Alz-powershell-module). +if (-not (Get-Module -ListAvailable -Name ALZ)) { + # Module doesn't exist, so install it + Write-Information "====> ALZ module isn't already installed. Installing..." -InformationAction Continue + Install-Module -Name ALZ -Force -Scope CurrentUser -ErrorAction Stop + Write-Information "====> ALZ module now installed." -InformationAction Continue +} else { + Write-Information "====> ALZ module is already installed." -InformationAction Continue +} # Line Endings function to be used in three functions below function Update-FileLineEndingType { diff --git a/dependencies/scripts/Invoke-PolicyToBicep.ps1 b/dependencies/scripts/Invoke-PolicyToBicep.ps1 index c1a3b76..42c0680 100644 --- a/dependencies/scripts/Invoke-PolicyToBicep.ps1 +++ b/dependencies/scripts/Invoke-PolicyToBicep.ps1 @@ -13,8 +13,6 @@ param ( [string] $rootPath = "./infra-as-code/bicep/modules/policy", [string] - $alzToolsPath = "$PWD/../../dependencies/Alz.Tools", - [string] $definitionsRoot = "definitions", [string] $lineEnding = "unix", @@ -41,8 +39,15 @@ param ( ) # This script relies on a custom set of classes and functions -# defined within the Alz.Tools PowerShell module. -Import-Module $alzToolsPath -ErrorAction Stop +# defined within the [ALZ-PowerShell-Module](https://github.com/Azure/Alz-powershell-module). +if (-not (Get-Module -ListAvailable -Name ALZ)) { + # Module doesn't exist, so install it + Write-Information "====> ALZ module isn't already installed. Installing..." -InformationAction Continue + Install-Module -Name ALZ -Force -Scope CurrentUser -ErrorAction Stop + Write-Information "====> ALZ module now installed." -InformationAction Continue +} else { + Write-Information "====> ALZ module is already installed." -InformationAction Continue +} # Line Endings function to be used in three functions below function Update-FileLineEndingType { @@ -52,7 +57,7 @@ function Update-FileLineEndingType { $filePath ) - (Get-Content $filePath | Edit-LineEndings -LineEnding $LineEnding) | Out-File $filePath + (Get-Content $filePath | Edit-LineEnding -LineEnding $LineEnding) | Out-File $filePath } #region Policy Definitions diff --git a/dependencies/scripts/Wipe-AlzTenant.ps1 b/dependencies/scripts/Wipe-AlzTenant.ps1 new file mode 100644 index 0000000..9c11f56 --- /dev/null +++ b/dependencies/scripts/Wipe-AlzTenant.ps1 @@ -0,0 +1,102 @@ +[CmdletBinding()] +param ( + #Added this back into parameters as error occurs if multiple tenants are found when using Get-AzTenant + [Parameter(Mandatory = $true, Position = 1, HelpMessage = "Please the Insert Tenant ID (GUID) of your Microsoft Entra tenant e.g.'f73a2b89-6c0e-4382-899f-ea227cd6b68f'")] + [string] + $tenantRootGroupID = "", + + [Parameter(Mandatory = $true, Position = 2, HelpMessage = "Insert the name of your intermediate root Management Group e.g. 'Contoso'")] + [string] + $intermediateRootGroupID = "", + + [Parameter(Mandatory = $true, Position = 4, HelpMessage = "Insert the subscription name of the subscription to wipe e.g. sub-unit-test-pr-108")] + [string] + $subscriptionName = "" +) + + +# Start timer +$StopWatch = New-Object -TypeName System.Diagnostics.Stopwatch +$StopWatch.Start() + +$subToMove = Get-AzSubscription -SubscriptionName $subscriptionName + +if ($subToMove.State -ne "Disabled") { + Write-Information "Moving Subscription: '$($subscriptionName)' under Tenant Root Management Group: '$tenantRootGroupID'" + New-AzManagementGroupSubscription -GroupId $tenantRootGroupID -SubscriptionId $subToMove.Id +} + + +# For each Subscription in the Intermediate Root Management Group's hierarchy tree, remove all Resources, Resource Groups and Deployments +Write-Information "Removing all Azure Resources, Resource Groups and Deployments from subscription $($subscriptionName)" +Write-Information "Set context to SubscriptionId: '$($subToMove.Id)'" +Set-AzContext -Subscription $subToMove.Id #| Out-Null + +# Get all Resource Groups in Subscription +$resources = Get-AzResourceGroup + +$resources | ForEach-Object -Parallel { + Write-Information "Deleting $_.ResourceGroupName ..." + Remove-AzResourceGroup -Name $_.ResourceGroupName -Force | Out-Null +} + +# Get Deployments for Subscription +$subDeployments = Get-AzSubscriptionDeployment + +Write-Information "Removing All Subscription Deployments for: $($subscriptionName)" + +# For each Subscription level deployment, remove it +$subDeployments | ForEach-Object -Parallel { + Write-Information "Removing $($_.DeploymentName) ..." + Remove-AzSubscriptionDeployment -Id $_.Id +} + + +# Get all Microsoft Entra Tenant level deployments +$tenantDeployments = Get-AzTenantDeployment + +Write-Information "Removing all Tenant level deployments" + +# For each Microsoft Entra Tenant level deployment, remove it +$tenantDeployments | ForEach-Object -Parallel { + Write-Information "Removing $($_.DeploymentName) ..." + Remove-AzTenantDeployment -Id $_.Id +} + +# This function only deletes Management Groups in the Intermediate Root Management Group's hierarchy tree and will NOT delete other Intermediate Root level Management Groups and their children e.g. in the case of "canary" +function Remove-Recursively { + [CmdletBinding(SupportsShouldProcess)] + param($name) + # Enters the parent Level + Write-Information "Entering the scope with $name" + $parent = Get-AzManagementGroup -GroupId $name -Expand -Recurse + + # Checks if there is any parent level + if ($null -ne $parent.Children) { + Write-Information "Found the following Children :" + Write-Information ($parent.Children | Select-Object Name).Name + + foreach ($children in $parent.Children) { + # Tries to recur to each child item + if ($PSCmdlet.ShouldProcess($children.Name)) { + Remove-Recursively($children.Name) + } + } + } + + # If no children are found at each scope + Write-Information "No children found in scope $name" + Write-Information "Removing the scope $name" + + Remove-AzManagementGroup -InputObject $parent -ErrorAction SilentlyContinue +} + +# Remove all the Management Groups in Intermediate Root Management Group's hierarchy tree, including itself +Remove-Recursively($intermediateRootGroupID) + +# Stop timer +$StopWatch.Stop() + +# Display timer output as table +Write-Information "Time taken to complete task:" +$StopWatch.Elapsed | Format-Table diff --git a/dependencies/scripts/mc-Wipe-AlzTenant.ps1 b/dependencies/scripts/mc-Wipe-AlzTenant.ps1 new file mode 100644 index 0000000..5da09b3 --- /dev/null +++ b/dependencies/scripts/mc-Wipe-AlzTenant.ps1 @@ -0,0 +1,102 @@ +[CmdletBinding()] +param ( + #Added this back into parameters as error occurs if multiple tenants are found when using Get-AzTenant + [Parameter(Mandatory = $true, Position = 1, HelpMessage = "Please the Insert Tenant ID (GUID) of your Microsoft Entra ID tenant e.g.'f73a2b89-6c0e-4382-899f-ea227cd6b68f'")] + [string] + $tenantRootGroupID = "", + + [Parameter(Mandatory = $true, Position = 2, HelpMessage = "Insert the name of your intermediate root Management Group e.g. 'Contoso'")] + [string] + $intermediateRootGroupID = "", + + [Parameter(Mandatory = $true, Position = 4, HelpMessage = "Insert the subscription name of the subscription to wipe e.g. sub-unit-test-pr-108")] + [string] + $subscriptionName = "" +) + + +# Start timer +$StopWatch = New-Object -TypeName System.Diagnostics.Stopwatch +$StopWatch.Start() + +$subToMove = Get-AzSubscription -SubscriptionName $subscriptionName + +if ($subToMove.State -ne "Disabled") { + Write-Output "Moving Subscription: '$($subscriptionName)' under Tenant Root Management Group: '$tenantRootGroupID'" + New-AzManagementGroupSubscription -GroupId $tenantRootGroupID -SubscriptionId $subToMove.Id +} + + +# For each Subscription in the Intermediate Root Management Group's hierarchy tree, remove all Resources, Resource Groups and Deployments +Write-Output "Removing all Azure Resources, Resource Groups and Deployments from subscription $($subscriptionName)" +Write-Output "Set context to SubscriptionId: '$($subToMove.Id)'" +Set-AzContext -Subscription $subToMove.Id #| Out-Null + +# Get all Resource Groups in Subscription +$resources = Get-AzResourceGroup + +$resources | ForEach-Object -Parallel { + Write-Output "Deleting $($_.ResourceGroupName) ..." + Remove-AzResourceGroup -Name $_.ResourceGroupName -Force | Out-Null +} + +# Get Deployments for Subscription +$subDeployments = Get-AzSubscriptionDeployment + +Write-Output "Removing All Subscription Deployments for: $($subscriptionName)" + +# For each Subscription level deployment, remove it +$subDeployments | ForEach-Object -Parallel { + Write-Output "Removing $($_.DeploymentName) ..." + Remove-AzSubscriptionDeployment -Id $_.Id +} + + +# Get all Microsoft Entra ID Tenant level deployments +$tenantDeployments = Get-AzTenantDeployment | Where-Object { $PSItem.DeploymentName -like "$intermediateRootGroupID*" } + +Write-Output "Removing all Tenant level deployments prefixed with $intermediateRootGroupID" + +# For each Microsoft Entra ID Tenant level deployment, remove it +$tenantDeployments | ForEach-Object -Parallel { + Write-Output "Removing $($_.DeploymentName) ..." + Remove-AzTenantDeployment -Id $_.Id +} + +# This function only deletes Management Groups in the Intermediate Root Management Group's hierarchy tree and will NOT delete other Intermediate Root level Management Groups and their children e.g. in the case of "canary" +function Remove-Recursively { + [CmdletBinding(SupportsShouldProcess)] + param($name) + # Enters the parent Level + Write-Output "Entering the scope with $name" + $parent = Get-AzManagementGroup -GroupId $name -Expand -Recurse + + # Checks if there is any parent level + if ($null -ne $parent.Children) { + Write-Output "Found the following Children :" + Write-Output ($parent.Children | Select-Object Name).Name + + foreach ($children in $parent.Children) { + # Tries to recur to each child item + if ($PSCmdlet.ShouldProcess($children.Name)) { + Remove-Recursively($children.Name) + } + } + } + + # If no children are found at each scope + Write-Output "No children found in scope $name" + Write-Output "Removing the scope $name" + + Remove-AzManagementGroup -InputObject $parent -ErrorAction SilentlyContinue +} + +# Remove all the Management Groups in Intermediate Root Management Group's hierarchy tree, including itself +Remove-Recursively($intermediateRootGroupID) + +# Stop timer +$StopWatch.Stop() + +# Display timer output as table +Write-Output "Time taken to complete task:" +$StopWatch.Elapsed | Format-Table diff --git a/docs/07-Deployment-Parameters.md b/docs/07-Deployment-Parameters.md index 94d05a9..ac19c3e 100644 --- a/docs/07-Deployment-Parameters.md +++ b/docs/07-Deployment-Parameters.md @@ -36,13 +36,13 @@ This section contains descriptions and accepted values for all parameters within | 17 | parAzureFirewallSubnet | CIDR range for the Azure Firewall subnet. | CIDR range | all, platform | | 18 | parCustomSubnets | List of other subnets to deploy on the hub VNET and their CIDR ranges. | Sample Format: [{"name": "CustomSubnet1", "ipAddressRange": "xx.xx.xx.xx/xx"}, {"name": "CustomSubnet2", "ipAddressRange": "xx.xx.xx.xx/xx"}] | all, platform | | 19 | parLogRetentionInDays | Length of time, in days, to retain log files with usage enforced by ALZ policies. | Number of days
e.g.: 365 | all, compliance, platform | - | 20 | parManagementSubscriptionId | Optional management subscription ID when using an existing subscription. | Azure Subscription Id
e.g.: /providers/Microsoft.Management/managementGroups/slz-platform-management1 | bootstrap, platform, dashboard | - | 21 | parIdentitySubscriptionId | Optional identity subscription ID when using an existing subscription. | Azure Subscription Id
e.g.: /providers/Microsoft.Management/managementGroups/slz-platform-identity1 | bootstrap, platform | - | 22 | parConnectivitySubscriptionId | Optional connectivity subscription ID when using an existing subscription. | Azure Subscription Id
e.g.: /providers/Microsoft.Management/managementGroups/slz-platform-connectivity1 | bootstrap, platform | - | 23 | parDdosProtectionResourceId | Optional resource ID for an existing DDoS plan with usage enforced by ALZ policies. | DDoS Plan Resource Id
e.g.:/subscriptions/{subId}/resourceGroups/{rgId}/providers/Microsoft.Network/ddosProtectionPlans/slz-ddos-plan-westus21 | platform | - | 24 | parLogAnalyticsWorkspaceId | Optional resource ID for an existing Log Analytics Workspace with usage enforced by ALZ policies. | Log Analytics Workspace Resource Id
e.g.: /subscriptions/{subId}/resourceGroups/{rgId}/providers/Microsoft.OperationalInsights/workspaces/slz-log-analytics-westus21 | compliance | + | 20 | parManagementSubscriptionId | Optional management subscription ID when using an existing subscription. | Azure Subscription Id
e.g.: /providers/Microsoft.Management/managementGroups/slz-platform-management1 | all, bootstrap, platform, dashboard | + | 21 | parIdentitySubscriptionId | Optional identity subscription ID when using an existing subscription. | Azure Subscription Id
e.g.: /providers/Microsoft.Management/managementGroups/slz-platform-identity1 | all, bootstrap, platform | + | 22 | parConnectivitySubscriptionId | Optional connectivity subscription ID when using an existing subscription. | Azure Subscription Id
e.g.: /providers/Microsoft.Management/managementGroups/slz-platform-connectivity1 | all, bootstrap, platform | + | 23 | parDdosProtectionResourceId | Optional resource ID for an existing DDoS plan with usage enforced by ALZ policies. | DDoS Plan Resource Id
e.g.:/subscriptions/{subId}/resourceGroups/{rgId}/providers/Microsoft.Network/ddosProtectionPlans/slz-ddos-plan-westus21 | all, platform | + | 24 | parLogAnalyticsWorkspaceId | Optional resource ID for an existing Log Analytics Workspace with usage enforced by ALZ policies. | Log Analytics Workspace Resource Id
e.g.: /subscriptions/{subId}/resourceGroups/{rgId}/providers/Microsoft.OperationalInsights/workspaces/slz-log-analytics-westus21 | all, compliance | | 25 | parRequireOwnerRolePermission | Set this to true if any policies in the initiative include a modify effect. | true; false | all, compliance | - | 26 | parPolicyExemptions | Optional list of policy exemptions. | Sample Format:

[{
"parPolicyExemptionManagementGroup":`value`,
"parPolicyAssignmentName":`value`,
"parPolicyAssignmentScopeName":`value`, 
"parPolicyDefinitionReferenceIds":`[]`, 
"parPolicyExemptionName":`value`,
"parPolicyExemptionDisplayName":`value`, 
"parPolicyExemptionDescription":`value` 
}]

`parPolicyExemptionManagementGroup` - Management group being exempted from the assignment scope, e.g.: slz-landingzones-confidential-corp
`parPolicyAssignmentName` - Name of the original policy assignment, e.g.: Deploy-SLZ-Root
`parPolicyAssignmentScopeName` - Top-level management group where policy was assigned, e.g.: slz
`parPolicyDefinitionReferenceIds` - Array of reference IDs of the policies being exempted, e.g.: "['AllowedLocation']" 
`parPolicyExemptionName` - Customized name for exemption, e.g.: Disable-locations
`parPolicyExemptionDisplayName` - Human readable customized name for exemption, e.g.: Disable Locations from Scope 
`parPolicyExemptionDescription` - Description of the exemption, e.g.: Disabling location restrictions defined on the top-level management group to the slz-landingzones-confidential-corp MG | policyexemptions | + | 26 | parPolicyExemptions | Optional list of policy exemptions. | Sample Format:

[{
"parPolicyExemptionManagementGroup":`value`,
"parPolicyAssignmentName":`value`,
"parPolicyAssignmentScopeName":`value`, 
"parPolicyDefinitionReferenceIds":`[]`, 
"parPolicyExemptionName":`value`,
"parPolicyExemptionDisplayName":`value`, 
"parPolicyExemptionDescription":`value` 
}]

`parPolicyExemptionManagementGroup` - Management group being exempted from the assignment scope, e.g.: slz-landingzones-confidential-corp
`parPolicyAssignmentName` - Name of the original policy assignment, e.g.: Deploy-SLZ-Root
`parPolicyAssignmentScopeName` - Top-level management group where policy was assigned, e.g.: slz
`parPolicyDefinitionReferenceIds` - Array of reference IDs of the policies being exempted, e.g.: "['AllowedLocation']" 
`parPolicyExemptionName` - Customized name for exemption, e.g.: Disable-locations
`parPolicyExemptionDisplayName` - Human readable customized name for exemption, e.g.: Disable Locations from Scope 
`parPolicyExemptionDescription` - Description of the exemption, e.g.: Disabling location restrictions defined on the top-level management group to the slz-landingzones-confidential-corp MG | all, policyexemptions | | 27 | parExpressRouteGatewayConfig | Optional configuration options for the ExpressRoute Gateway. | ExpressRoute Gateway Configuration

Sample Format:
{
"sku": "standard",
"vpntype": "RouteBased",
"vpnGatewayGeneration": null,
"enableBgp": false,
"activeActive": false,
"enableBgpRouteTranslationForNat": false,
"enableDnsForwarding": false,
"asn": 65515,
"bgpPeeringAddress": "",
"peerWeight": 5
} | all, platform | | 28 | parVpnGatewayConfig | Optional configuration options for the VPN Gateway. | VPN Gateway Configuration

Sample Format:
{
"sku": "VpnGw1",
"vpntype": "RouteBased",
"generation": "Generation1",
"enableBgp": false,
"activeActive": false,
"enableBgpRouteTranslationForNat": false,
"enableDnsForwarding": false,
"asn": 65515,
"bgpPeeringAddress": "",
"peerWeight": 5
} | all, platform | | 29 | parDeployBastion | Toggles deployment of Azure Bastion. True to deploy, otherwise false. | true; false | all, platform | @@ -55,9 +55,10 @@ This section contains descriptions and accepted values for all parameters within | 36 | parInvokePolicyScanSync | 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. | true; false | all, compliance | | 37 | parInvokePolicyRemediationSync | Toggles executing the policy scan in synchronous mode. True to run policy remediation in synchronous mode, False for asynchronous. | true; false | all, compliance | | 38 | parPolicyEffect | The policy effect used in all assignments for the Sovereignty Baseline policy initiatives. | Choose one: "Audit", "Deny", "Disabled" | all, compliance | - | 39 | parDeployLogAnalyticsWorkspace | Toggles deployment of Log Analytics Workspace. True to deploy, otherwise false. | true; false | all, platform | - | 40 | parCustomerPolicySets | Customer specified policy assignments to the top-level management group of the SLZ. No parameters are supported as part of the assignment. | Name field can only be a letter, digit, '-', '.' or '_' and cannot have any trailing special character.
See the SLZ parameter file for a sample configuration. | all, compliance | - | 41 | parTags | Tags that will be assigned to subscription and resources created by this deployment script. | See the SLZ parameter file for a sample configuration. | all, bootstrap, platform, and dashboard | + | 39 | parPolicyAssignmentEnforcementMode | The enforcement mode used in all policy and initiative assignments. | Choose one: "Default", "DoNotEnforce" | all, compliance | + | 40 | parDeployLogAnalyticsWorkspace | Toggles deployment of Log Analytics Workspace. True to deploy, otherwise false. | true; false | all, platform | + | 41 | parCustomerPolicySets | Optional additional policy initiatives to assign. | Sample Format:

[{
"policySetDefinitionId":`value`,
"policySetAssignmentName":`value`,
"policySetAssignmentDisplayName":`value`, 
"policySetAssignmentDescription":`value`, 
"policySetManagementGroupAssignmentScope":`value`,
"policyParameterFilePath":`value` 
}]

`policySetDefinitionId` - Definition ID for the policy initiative to assign, e.g.: /providers/Microsoft.Authorization/policySetDefinitions/1f3afdf9-d0c9-4c3d-847f-89da613e70a8
`policySetAssignmentName` - Custom name for the assignment, e.g.: Microsoft-Cloud-Security-Benchmark
`policySetAssignmentDisplayName` - Custom display name for the assignment, e.g.: Microsoft Cloud Security Benchmark
`policySetAssignmentDescription` - Custom description for the assignment, e.g.: "e.g.: Microsoft-Cloud-Security-Benchmark 
`policySetManagementGroupAssignmentScope` - Management group ID to assign the initiative on, e.g.: slz
`policyParameterFilePath` - (Optional) Path to the assignment parameter file, e.g.: ./parameters/policyParameters/nist800Parameter.json | all, compliance | + | 42 | parTags | Tags that will be assigned to subscription and resources created by this deployment script. | See the SLZ parameter file for a sample configuration. | all, bootstrap, platform, and dashboard | ## Next step diff --git a/docs/12-FAQ.md b/docs/12-FAQ.md index bea8de0..7eab475 100644 --- a/docs/12-FAQ.md +++ b/docs/12-FAQ.md @@ -213,6 +213,12 @@ An organization with multiple SLZ deployments each with a unique parameter file Reference our [pipeline deployments](./scenarios/Pipeline-Deployments.md) document for additional details. +### Why are my Route Tables and NSGs Being Removed? + +It is common for customers to make changes to resources deployed by the SLZ orchestration as post-deployment steps. However, when the SLZ orchestration is executed a second time it will attempt to reset these resources back to the original state inadvertently changing routing and network security groups. + +While we are working on a resolution, users can mitigate this by setting the `parDeployHubNetwork` to `false` in the parameter file. This will not cause the SLZ orchestration to delete any networking resources, but will instead instruct the orchestration to not modify any existing networking resources. + ## Compliance Dashboard ### How can I give 'read only' access to a user in my organization to the dashboard? diff --git a/docs/13-Troubleshooting.md b/docs/13-Troubleshooting.md index e031963..e25fff6 100644 --- a/docs/13-Troubleshooting.md +++ b/docs/13-Troubleshooting.md @@ -52,6 +52,10 @@ This error means that the SLZ Global Defaults policy assignment has been configu Once a valid value is provided, run the SLZ compliance deployment step to update the policy assignment, then rerun the SLZ deployment. This error is related to the other ones where policy is blocking the resource. +### Put on Firewall Policy [AFW POLICY] Failed with 1 faulted referenced firewalls + +This error occurs when the SLZ orchestration is ran a second time after post-deployment modifications have been made to the AFW Policy. While we are working on a resolution, users can mitigate this by setting the `parEnableFirewall` to `false` in the parameter file. This will not cause the SLZ orchestration to delete any firewall resources, but will instead instruct the orchestration to not modify any existing firewall resources. + ## Dashboard Errors ### Resource [DASHBOARD RESOURCE GROUP NAME] was disallowed by policy. diff --git a/docs/scenarios/Custom-Policies.md b/docs/scenarios/Custom-Policies.md index e7cc3d3..80b1e20 100644 --- a/docs/scenarios/Custom-Policies.md +++ b/docs/scenarios/Custom-Policies.md @@ -2,9 +2,27 @@ Once the SLZ is deployed, the management group structure, subscriptions, and the [Sovereignty Baseline policy initiatives](Sovereignty-Baseline-Policy-Initiatives.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. +## Assigning existing initiatives + +The SLZ allows for both builtin and custom initiatives to be assigned during deployment at a specified scope and with custom parameters. This option is most useful for the following cases: + +1. When the policy initiative definitions are common across multiple SLZ deployments and need to be created at the tenant root group. +2. When the policy initiative definition needs to be tested and validated before an SLZ deployment. +3. When there are variable parameters could be needed during assignment. + +Many users may find this option to be the most flexible. + +This capability can be used in a deployment by setting the `parCustomerPolicySets` value in the parameter file. Review the parameter file or the [Deployment Parameters](../07-Deployment-Parameters.md) for additional details about the structure for this object. + ## Customization step by step -The SLZ allows for custom policy initiatives to be deployed within the standard management group scopes for each deployment through the following: +The SLZ allows for custom policy initiatives to be deployed and within the standard management group scopes. This option is most useful for the following cases: + +1. When the policy initiative definitions are unique to an individual SLZ deployment. +2. When the policy initiative definition lifecycle should be the same as the SLZ deployment. +3. When there are no variable parameters needed during assignment. + +This capability can be used in a 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 management group hierarchy: @@ -35,8 +53,25 @@ The SLZ allows for custom policy initiatives to be deployed within the standard **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 +## Using Compliance Outside an SLZ Deployment + +For ALZ customers, it is recommended to deploy the relevant Azure Policy and Initiative definitions and assignments using the [ALZ recommended path](https://github.com/Azure/ALZ-Bicep/wiki/PolicyDeepDive). + +For customers that aren't using the ALZ or the SLZ, they may still use the SLZ compliance modules to deploy the relevant policies. To use these modules, the customer landing zone must still have the same management group structure and IDs as an SLZ deployment would create. Specifically, the Management Group parent and child IDs must be: + +* `[PREFIX][SUFFIX]` + * `[PREFIX]`-decommissioned`[SUFFIX]` + * `[PREFIX]`-landingzones`[SUFFIX]` + * `[PREFIX]`-landingzones-confidentialcorp`[SUFFIX]` + * `[PREFIX]`-landingzones-confidentialonline`[SUFFIX]` + * `[PREFIX]`-landingzones-corp`[SUFFIX]` + * `[PREFIX]`-landingzones-online`[SUFFIX]` + * `[PREFIX]`-platform`[SUFFIX]` + * `[PREFIX]`-platform-connectivity`[SUFFIX]` + * `[PREFIX]`-platform-identity`[SUFFIX]` + * `[PREFIX]`-platform-management`[SUFFIX]` + * `[PREFIX]`-sandbox`[SUFFIX]` -[View your compliance dashboard.](../10-Compliance-Dashboard.md) +Then the [compliance deployment step](./Pipeline-Deployments.md#individual-deployment-steps) can be executed directly to create the relevant definitions and assignments. ### [Microsoft Legal Notice](../NOTICE.md) diff --git a/docs/scenarios/Removing-Policy-Assignments.md b/docs/scenarios/Removing-Policy-Assignments.md index 5a09c26..8d4c51e 100644 --- a/docs/scenarios/Removing-Policy-Assignments.md +++ b/docs/scenarios/Removing-Policy-Assignments.md @@ -75,4 +75,18 @@ For further details refer to the [ALZ Assignment Deletion](https://github.com/Az |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 | +## Removing the Custom Sovereignty Baseline Policy Initiatives + +Starting with v1.1.0 of the SLZ, the delivery mechanism for the Sovereignty Baseline Policy initiatives has changed. Prior to this version they were delivered by the SLZ orchestration as custom initiatives, but starting with this version and going forward the orchestration will use the builtin Azure Policy definitions. + +This is only a change to the delivery mechanism, functionally the initiatives are identical but by leveraging the builtin Azure Policy definitions, it becomes easier to deliver and consume of updates to the baseline. + +However, after upgrading an existing SLZ deployment to v1.1.0, the old assignments and definitions will need to be manually removed. The above process described for removing ALZ policy assignments should be followed with these assignments: + +| **Assignment Name** | **Scope** | **Definition Name** | +|--------------------------|---------------------------|-------------------------------| +|SLZ Global Policies|Top-Level Management Group|Default Sovereign Landing Zone (SLZ) policies| +|SLZ Confidential Policies|Confidential Corp|Policies to enforce confidential computing| +|SLZ Confidential Policies|Confidential Online|Policies to enforce confidential computing| + ### [Microsoft Legal Notice](../NOTICE.md) diff --git a/docs/scenarios/Using-Policy-Portfolio.md b/docs/scenarios/Using-Policy-Portfolio.md index 499b98e..5584193 100644 --- a/docs/scenarios/Using-Policy-Portfolio.md +++ b/docs/scenarios/Using-Policy-Portfolio.md @@ -1,9 +1,9 @@ # 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. +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/region 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. 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 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 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. +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 specified management group scope, and with the optional parameters provided in the `policyParameterFilePath` field within the `parCustomerPolicySets` parameter. See [Custom Policies](./Custom-Policies.md#Assigning-existing-initiatives) for more details. ### [Microsoft Legal Notice](../NOTICE.md) diff --git a/modules/compliance/customCompliance.bicep b/modules/compliance/customCompliance.bicep index e72ee78..e6a1b44 100644 --- a/modules/compliance/customCompliance.bicep +++ b/modules/compliance/customCompliance.bicep @@ -14,6 +14,9 @@ param parDeploymentPrefix string @maxLength(5) param parDeploymentSuffix string +@description('Enforcement mode for all policy assignments.') +param parPolicyAssignmentEnforcementMode 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 @@ -163,7 +166,7 @@ module modPolicyAssignmentGlobalCustom '../../dependencies/infra-as-code/bicep/m parPolicyAssignmentDescription: '${varGlobalCustomPolicies.libAssignment.properties.description} ${varGlobalCustomPolicies.version}' parPolicyAssignmentDisplayName: '${varGlobalCustomPolicies.libAssignment.properties.displayName} ${varGlobalCustomPolicies.version}' parPolicyAssignmentName: take('${varGlobalCustomPolicies.libAssignment.name}${varGlobalCustomPolicies.version}', 24) - parPolicyAssignmentEnforcementMode: 'Default' + parPolicyAssignmentEnforcementMode: parPolicyAssignmentEnforcementMode parPolicyAssignmentIdentityRoleAssignmentsSubs: parIdentityRoleAssignmentsSubs parPolicyAssignmentIdentityRoleDefinitionIds: parRoleDefinitionIds parPolicyAssignmentIdentityType: 'SystemAssigned' @@ -180,7 +183,7 @@ module modPolicyAssignmentDecommissionedCustom '../../dependencies/infra-as-code parPolicyAssignmentDescription: '${varDecommissionedCustomPolicies.libAssignment.properties.description} ${varDecommissionedCustomPolicies.version}' parPolicyAssignmentDisplayName: '${varDecommissionedCustomPolicies.libAssignment.properties.displayName} ${varDecommissionedCustomPolicies.version}' parPolicyAssignmentName: take('${varDecommissionedCustomPolicies.libAssignment.name}${varDecommissionedCustomPolicies.version}', 24) - parPolicyAssignmentEnforcementMode: 'Default' + parPolicyAssignmentEnforcementMode: parPolicyAssignmentEnforcementMode parPolicyAssignmentIdentityRoleAssignmentsSubs: parIdentityRoleAssignmentsSubs parPolicyAssignmentIdentityRoleDefinitionIds: parRoleDefinitionIds parPolicyAssignmentIdentityType: 'SystemAssigned' @@ -197,7 +200,7 @@ module modPolicyAssignmentLandingZoneCustom '../../dependencies/infra-as-code/bi parPolicyAssignmentDescription: '${varLandingZonesPolicies.libAssignment.properties.description} ${varLandingZonesPolicies.version}' parPolicyAssignmentDisplayName: '${varLandingZonesPolicies.libAssignment.properties.displayName} ${varLandingZonesPolicies.version}' parPolicyAssignmentName: take('${varLandingZonesPolicies.libAssignment.name}${varLandingZonesPolicies.version}', 24) - parPolicyAssignmentEnforcementMode: 'Default' + parPolicyAssignmentEnforcementMode: parPolicyAssignmentEnforcementMode parPolicyAssignmentIdentityRoleAssignmentsSubs: parIdentityRoleAssignmentsSubs parPolicyAssignmentIdentityRoleDefinitionIds: parRoleDefinitionIds parPolicyAssignmentIdentityType: 'SystemAssigned' @@ -214,7 +217,7 @@ module modPolicyAssignmentConfidentialCorpCustom_Confidential '../../dependencie parPolicyAssignmentDescription: '${varConfidentialCustomPolicies.libAssignment.properties.description} ${varConfidentialCustomPolicies.version}' parPolicyAssignmentDisplayName: '${varConfidentialCustomPolicies.libAssignment.properties.displayName} ${varConfidentialCustomPolicies.version}' parPolicyAssignmentName: take('${varConfidentialCustomPolicies.libAssignment.name}${varConfidentialCustomPolicies.version}', 24) - parPolicyAssignmentEnforcementMode: 'Default' + parPolicyAssignmentEnforcementMode: parPolicyAssignmentEnforcementMode parPolicyAssignmentIdentityRoleAssignmentsAdditionalMgs: [] parPolicyAssignmentIdentityRoleAssignmentsSubs: parIdentityRoleAssignmentsSubs parPolicyAssignmentIdentityRoleDefinitionIds: parRoleDefinitionIds @@ -233,7 +236,7 @@ module modPolicyAssignmentConfidentialCorpCustom_Corp '../../dependencies/infra- parPolicyAssignmentDescription: '${varCorpCustomPolicies.libAssignment.properties.description} ${varCorpCustomPolicies.version}' parPolicyAssignmentDisplayName: '${varCorpCustomPolicies.libAssignment.properties.displayName} ${varCorpCustomPolicies.version}' parPolicyAssignmentName: take('${varCorpCustomPolicies.libAssignment.name}${varCorpCustomPolicies.version}', 24) - parPolicyAssignmentEnforcementMode: 'Default' + parPolicyAssignmentEnforcementMode: parPolicyAssignmentEnforcementMode parPolicyAssignmentIdentityRoleAssignmentsAdditionalMgs: [] parPolicyAssignmentIdentityRoleAssignmentsSubs: parIdentityRoleAssignmentsSubs parPolicyAssignmentIdentityRoleDefinitionIds: parRoleDefinitionIds @@ -253,7 +256,7 @@ module modPolicyAssignmentConfidentialOnlineCustom_Confidential '../../dependenc parPolicyAssignmentDescription: '${varConfidentialCustomPolicies.libAssignment.properties.description} ${varConfidentialCustomPolicies.version}' parPolicyAssignmentDisplayName: '${varConfidentialCustomPolicies.libAssignment.properties.displayName} ${varConfidentialCustomPolicies.version}' parPolicyAssignmentName: take('${varConfidentialCustomPolicies.libAssignment.name}${varConfidentialCustomPolicies.version}', 24) - parPolicyAssignmentEnforcementMode: 'Default' + parPolicyAssignmentEnforcementMode: parPolicyAssignmentEnforcementMode parPolicyAssignmentIdentityRoleAssignmentsAdditionalMgs: [] parPolicyAssignmentIdentityRoleAssignmentsSubs: parIdentityRoleAssignmentsSubs parPolicyAssignmentIdentityRoleDefinitionIds: parRoleDefinitionIds @@ -273,7 +276,7 @@ module modPolicyAssignmentConfidentialOnlineCustom_Online '../../dependencies/in parPolicyAssignmentDescription: '${varOnlineCustomPolicies.libAssignment.properties.description} ${varOnlineCustomPolicies.version}' parPolicyAssignmentDisplayName: '${varOnlineCustomPolicies.libAssignment.properties.displayName} ${varOnlineCustomPolicies.version}' parPolicyAssignmentName: take('${varOnlineCustomPolicies.libAssignment.name}${varOnlineCustomPolicies.version}', 24) - parPolicyAssignmentEnforcementMode: 'Default' + parPolicyAssignmentEnforcementMode: parPolicyAssignmentEnforcementMode parPolicyAssignmentIdentityRoleAssignmentsAdditionalMgs: [] parPolicyAssignmentIdentityRoleAssignmentsSubs: parIdentityRoleAssignmentsSubs parPolicyAssignmentIdentityRoleDefinitionIds: parRoleDefinitionIds @@ -293,7 +296,7 @@ module modPolicyAssignmentCorpCustom '../../dependencies/infra-as-code/bicep/mod parPolicyAssignmentDescription: '${varCorpCustomPolicies.libAssignment.properties.description} ${varOnlineCustomPolicies.version}' parPolicyAssignmentDisplayName: '${varCorpCustomPolicies.libAssignment.properties.displayName} ${varOnlineCustomPolicies.version}' parPolicyAssignmentName: take('${varCorpCustomPolicies.libAssignment.name}${varOnlineCustomPolicies.version}', 24) - parPolicyAssignmentEnforcementMode: 'Default' + parPolicyAssignmentEnforcementMode: parPolicyAssignmentEnforcementMode parPolicyAssignmentIdentityRoleAssignmentsAdditionalMgs: [] parPolicyAssignmentIdentityRoleAssignmentsSubs: parIdentityRoleAssignmentsSubs parPolicyAssignmentIdentityRoleDefinitionIds: parRoleDefinitionIds @@ -313,7 +316,7 @@ module modPolicyAssignmentOnlineCustom '../../dependencies/infra-as-code/bicep/m parPolicyAssignmentDescription: '${varOnlineCustomPolicies.libAssignment.properties.description} ${varOnlineCustomPolicies.version}' parPolicyAssignmentDisplayName: '${varOnlineCustomPolicies.libAssignment.properties.displayName} ${varOnlineCustomPolicies.version}' parPolicyAssignmentName: take('${varOnlineCustomPolicies.libAssignment.name}${varOnlineCustomPolicies.version}', 24) - parPolicyAssignmentEnforcementMode: 'Default' + parPolicyAssignmentEnforcementMode: parPolicyAssignmentEnforcementMode parPolicyAssignmentIdentityRoleAssignmentsAdditionalMgs: [] parPolicyAssignmentIdentityRoleAssignmentsSubs: parIdentityRoleAssignmentsSubs parPolicyAssignmentIdentityRoleDefinitionIds: parRoleDefinitionIds @@ -333,7 +336,7 @@ module modPolicyAssignmentPlatformCustom '../../dependencies/infra-as-code/bicep parPolicyAssignmentDescription: '${varPlatformCustomPolicies.libAssignment.properties.description} ${varPlatformCustomPolicies.version}' parPolicyAssignmentDisplayName: '${varPlatformCustomPolicies.libAssignment.properties.displayName} ${varPlatformCustomPolicies.version}' parPolicyAssignmentName: take('${varPlatformCustomPolicies.libAssignment.name}${varPlatformCustomPolicies.version}', 24) - parPolicyAssignmentEnforcementMode: 'Default' + parPolicyAssignmentEnforcementMode: parPolicyAssignmentEnforcementMode parPolicyAssignmentIdentityRoleAssignmentsAdditionalMgs: [] parPolicyAssignmentIdentityRoleAssignmentsSubs: parIdentityRoleAssignmentsSubs parPolicyAssignmentIdentityRoleDefinitionIds: parRoleDefinitionIds @@ -353,7 +356,7 @@ module modPolicyAssignmentConnectivityCustom '../../dependencies/infra-as-code/b parPolicyAssignmentDescription: '${varConnectivityCustomPolicies.libAssignment.properties.description} ${varConnectivityCustomPolicies.version}' parPolicyAssignmentDisplayName: '${varConnectivityCustomPolicies.libAssignment.properties.displayName} ${varConnectivityCustomPolicies.version}' parPolicyAssignmentName: take('${varConnectivityCustomPolicies.libAssignment.name}${varConnectivityCustomPolicies.version}', 24) - parPolicyAssignmentEnforcementMode: 'Default' + parPolicyAssignmentEnforcementMode: parPolicyAssignmentEnforcementMode parPolicyAssignmentIdentityRoleAssignmentsAdditionalMgs: [] parPolicyAssignmentIdentityRoleAssignmentsSubs: parIdentityRoleAssignmentsSubs parPolicyAssignmentIdentityRoleDefinitionIds: parRoleDefinitionIds @@ -373,7 +376,7 @@ module modPolicyAssignmentIdentityCustom '../../dependencies/infra-as-code/bicep parPolicyAssignmentDescription: '${varIdentityCustomPolicies.libAssignment.properties.description} ${varIdentityCustomPolicies.version}' parPolicyAssignmentDisplayName: '${varIdentityCustomPolicies.libAssignment.properties.displayName} ${varIdentityCustomPolicies.version}' parPolicyAssignmentName: take('${varIdentityCustomPolicies.libAssignment.name}${varIdentityCustomPolicies.version}', 24) - parPolicyAssignmentEnforcementMode: 'Default' + parPolicyAssignmentEnforcementMode: parPolicyAssignmentEnforcementMode parPolicyAssignmentIdentityRoleAssignmentsAdditionalMgs: [] parPolicyAssignmentIdentityRoleAssignmentsSubs: parIdentityRoleAssignmentsSubs parPolicyAssignmentIdentityRoleDefinitionIds: parRoleDefinitionIds @@ -393,7 +396,7 @@ module modPolicyAssignmentManagementCustom '../../dependencies/infra-as-code/bic parPolicyAssignmentDescription: '${varManagementCustomPolicies.libAssignment.properties.description} ${varManagementCustomPolicies.version}' parPolicyAssignmentDisplayName: '${varManagementCustomPolicies.libAssignment.properties.displayName} ${varManagementCustomPolicies.version}' parPolicyAssignmentName: take('${varManagementCustomPolicies.libAssignment.name}${varManagementCustomPolicies.version}', 24) - parPolicyAssignmentEnforcementMode: 'Default' + parPolicyAssignmentEnforcementMode: parPolicyAssignmentEnforcementMode parPolicyAssignmentIdentityRoleAssignmentsAdditionalMgs: [] parPolicyAssignmentIdentityRoleAssignmentsSubs: parIdentityRoleAssignmentsSubs parPolicyAssignmentIdentityRoleDefinitionIds: parRoleDefinitionIds @@ -413,7 +416,7 @@ module modPolicyAssignmentSandboxCustom '../../dependencies/infra-as-code/bicep/ parPolicyAssignmentDescription: '${varSandboxCustomPolicies.libAssignment.properties.description} ${varSandboxCustomPolicies.version}' parPolicyAssignmentDisplayName: '${varSandboxCustomPolicies.libAssignment.properties.displayName} ${varSandboxCustomPolicies.version}' parPolicyAssignmentName: take('${varSandboxCustomPolicies.libAssignment.name}${varSandboxCustomPolicies.version}', 24) - parPolicyAssignmentEnforcementMode: 'Default' + parPolicyAssignmentEnforcementMode: parPolicyAssignmentEnforcementMode parPolicyAssignmentIdentityRoleAssignmentsAdditionalMgs: [] parPolicyAssignmentIdentityRoleAssignmentsSubs: parIdentityRoleAssignmentsSubs parPolicyAssignmentIdentityRoleDefinitionIds: parRoleDefinitionIds diff --git a/modules/compliance/customerPolicySetAssignments.bicep b/modules/compliance/customerPolicySetAssignments.bicep index c0602ce..d5207b3 100644 --- a/modules/compliance/customerPolicySetAssignments.bicep +++ b/modules/compliance/customerPolicySetAssignments.bicep @@ -17,6 +17,9 @@ param parDeploymentPrefix string @maxLength(5) param parDeploymentSuffix string +@description('Enforcement mode for all policy assignments.') +param parPolicyAssignmentEnforcementMode string + @description('Deployed policy set definition id ') param parPolicySetDefinitionId string @@ -30,7 +33,14 @@ param parPolicySetAssignmentDisplayName string @description('descritpion for the policy set assignment') param parPolicySetAssignmentDescription string -var varRootManagementGroupId = '${parDeploymentPrefix}${parDeploymentSuffix}' +@description('An object containing the parameter values for the policy to be assigned.') +param parPolicyAssignmentParameters object = {} + +@description('Management group scope for the policy assignment') +param parPolicySetManagementGroupAssignmentScope string = '' + +var varManagementGroupId = empty(parPolicySetManagementGroupAssignmentScope) ? '${parDeploymentPrefix}${parDeploymentSuffix}' : contains(toLower(parPolicySetManagementGroupAssignmentScope), '/providers/microsoft.management/managementgroups/') ? replace(toLower(parPolicySetManagementGroupAssignmentScope), '/providers/microsoft.management/managementgroups/', '') : parPolicySetManagementGroupAssignmentScope + var varRbacRoleDefinitionIds = { owner: '8e3af657-a8ff-443c-a75c-2fe8c4bcb635' contributor: 'b24988ac-6180-42a0-ab88-20f7382dd24c' @@ -40,18 +50,19 @@ var varRbacRoleDefinitionIds = { // Module - Policy Assignments - Root Management Group module modUserPolicyAssignment '../../dependencies/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep' = { - scope: managementGroup(varRootManagementGroupId) + scope: managementGroup(varManagementGroupId) name: take('${parDeploymentPrefix}-polAssi-CustomerPolicySet-intRoot-${parPolicySetAssignmentName}${parDeploymentSuffix}', 64) params: { parPolicyAssignmentDefinitionId: parPolicySetDefinitionId parPolicyAssignmentName: take('${parPolicySetAssignmentName}', 24) parPolicyAssignmentDisplayName: parPolicySetAssignmentDisplayName parPolicyAssignmentDescription: parPolicySetAssignmentDescription + parPolicyAssignmentParameters: parPolicyAssignmentParameters parPolicyAssignmentIdentityType: 'SystemAssigned' parPolicyAssignmentIdentityRoleDefinitionIds: [ varRbacRoleDefinitionIds.owner ] - parPolicyAssignmentEnforcementMode: 'Default' + parPolicyAssignmentEnforcementMode: parPolicyAssignmentEnforcementMode parTelemetryOptOut: true } } diff --git a/modules/compliance/defaultCompliance.bicep b/modules/compliance/defaultCompliance.bicep deleted file mode 100644 index fa03eaf..0000000 --- a/modules/compliance/defaultCompliance.bicep +++ /dev/null @@ -1,503 +0,0 @@ -// 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 - } - effect: { - value: parPolicyEffect - } - } - 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_connectivity_defaults.tmpl.json b/modules/compliance/policyAssignments/policy_assignment_deploy_slz_connectivity_defaults.tmpl.json deleted file mode 100644 index b06743c..0000000 --- a/modules/compliance/policyAssignments/policy_assignment_deploy_slz_connectivity_defaults.tmpl.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "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 deleted file mode 100644 index d200a16..0000000 --- a/modules/compliance/policyAssignments/policy_assignment_deploy_slz_corp_defaults.tmpl.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "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 deleted file mode 100644 index eaddbff..0000000 --- a/modules/compliance/policyAssignments/policy_assignment_deploy_slz_decommissioned_defaults.tmpl.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "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 deleted file mode 100644 index ecac01b..0000000 --- a/modules/compliance/policyAssignments/policy_assignment_deploy_slz_identity_defaults.tmpl.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "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 deleted file mode 100644 index a0d56c3..0000000 --- a/modules/compliance/policyAssignments/policy_assignment_deploy_slz_landing_zones_defaults.tmpl.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "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 deleted file mode 100644 index d96fb3f..0000000 --- a/modules/compliance/policyAssignments/policy_assignment_deploy_slz_management_defaults.tmpl.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "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 deleted file mode 100644 index a6a607e..0000000 --- a/modules/compliance/policyAssignments/policy_assignment_deploy_slz_online_defaults.tmpl.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "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 deleted file mode 100644 index e8da569..0000000 --- a/modules/compliance/policyAssignments/policy_assignment_deploy_slz_platform_defaults.tmpl.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "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 deleted file mode 100644 index 2321d3f..0000000 --- a/modules/compliance/policyAssignments/policy_assignment_deploy_slz_sandbox_defaults.tmpl.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "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 deleted file mode 100644 index af6c186..0000000 --- a/modules/compliance/policyAssignments/policy_assignmnet_deploy_slz_global_defaults.tmpl.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "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/policySetDefinitions/slzConfidentialDefaults.json b/modules/compliance/policySetDefinitions/slzConfidentialDefaults.json deleted file mode 100644 index 54cd1dd..0000000 --- a/modules/compliance/policySetDefinitions/slzConfidentialDefaults.json +++ /dev/null @@ -1,287 +0,0 @@ -{ - "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": [ - "australiacentral", - "australiacentral2", - "australiaeast", - "australiasoutheast", - "brazilsouth", - "brazilsoutheast", - "brazilus", - "canadacentral", - "canadaeast", - "centralindia", - "centralus", - "centraluseuap", - "eastasia", - "eastus", - "eastus2", - "eastus2euap", - "eastusstg", - "francecentral", - "francesouth", - "germanynorth", - "germanywestcentral", - "israelcentral", - "italynorth", - "japaneast", - "japanwest", - "jioindiacentral", - "jioindiawest", - "koreacentral", - "koreasouth", - "northcentralus", - "northeurope", - "norwayeast", - "norwaywest", - "polandcentral", - "qatarcentral", - "southafricanorth", - "southafricawest", - "southcentralus", - "southcentralusstg", - "southeastasia", - "southindia", - "swedencentral", - "switzerlandnorth", - "switzerlandwest", - "uaecentral", - "uaenorth", - "uksouth", - "ukwest", - "westcentralus", - "westeurope", - "westindia", - "westus", - "westus2", - "westus3" - ], - "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')]" - }, - "policyEffect": { - "value": "[[parameters('effect')]" - } - }, - "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 deleted file mode 100644 index 0910980..0000000 --- a/modules/compliance/policySetDefinitions/slzConnectivityDefaults.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "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 deleted file mode 100644 index f5182c6..0000000 --- a/modules/compliance/policySetDefinitions/slzCorpDefaults.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "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 deleted file mode 100644 index d267f6f..0000000 --- a/modules/compliance/policySetDefinitions/slzDecommissionedDefaults.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "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 deleted file mode 100644 index 721801a..0000000 --- a/modules/compliance/policySetDefinitions/slzGlobalDefaults.json +++ /dev/null @@ -1,132 +0,0 @@ -{ - "properties": { - "displayName": "SLZ Global Policies", - "policyType": "Custom", - "description": "Default Sovereign Landing Zone (SLZ) policies", - "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": [ - "australiacentral", - "australiacentral2", - "australiaeast", - "australiasoutheast", - "brazilsouth", - "brazilsoutheast", - "brazilus", - "canadacentral", - "canadaeast", - "centralindia", - "centralus", - "centraluseuap", - "eastasia", - "eastus", - "eastus2", - "eastus2euap", - "eastusstg", - "francecentral", - "francesouth", - "germanynorth", - "germanywestcentral", - "israelcentral", - "italynorth", - "japaneast", - "japanwest", - "jioindiacentral", - "jioindiawest", - "koreacentral", - "koreasouth", - "northcentralus", - "northeurope", - "norwayeast", - "norwaywest", - "polandcentral", - "qatarcentral", - "southafricanorth", - "southafricawest", - "southcentralus", - "southcentralusstg", - "southeastasia", - "southindia", - "swedencentral", - "switzerlandnorth", - "switzerlandwest", - "uaecentral", - "uaenorth", - "uksouth", - "ukwest", - "westcentralus", - "westeurope", - "westindia", - "westus", - "westus2", - "westus3" - ], - "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')]" - }, - "policyEffect": { - "value": "[[parameters('effect')]" - } - }, - "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 deleted file mode 100644 index c12d169..0000000 --- a/modules/compliance/policySetDefinitions/slzIdentityDefaults.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "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 deleted file mode 100644 index f4397eb..0000000 --- a/modules/compliance/policySetDefinitions/slzLandingZoneDefaults.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "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 deleted file mode 100644 index ed217d8..0000000 --- a/modules/compliance/policySetDefinitions/slzManagementDefaults.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "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 deleted file mode 100644 index d0360ef..0000000 --- a/modules/compliance/policySetDefinitions/slzOnlineDefaults.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "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 deleted file mode 100644 index 724594a..0000000 --- a/modules/compliance/policySetDefinitions/slzPlatformDefaults.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "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 deleted file mode 100644 index cc153d7..0000000 --- a/modules/compliance/policySetDefinitions/slzSandboxDefaults.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "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/dashboard/dashboard.bicep b/modules/dashboard/dashboard.bicep index b65ae79..1d0fd65 100644 --- a/modules/dashboard/dashboard.bicep +++ b/modules/dashboard/dashboard.bicep @@ -84,7 +84,6 @@ var varDefaultTitles = [ } } } - partHeader: {} } } { @@ -255,7 +254,6 @@ var varDefaultTitles = [ } } } - partHeader: {} } } { @@ -528,7 +526,6 @@ var varDefaultTitles = [ } } } - partHeader: {} } } { @@ -700,7 +697,6 @@ var varDefaultTitles = [ } } } - partHeader: {} } } { @@ -919,12 +915,16 @@ resource resDashboard 'Microsoft.Portal/dashboards@2020-09-01-preview' = { colSpan: part.position.colSpan rowSpan: part.position.rowSpan } - metadata: { + #disable-next-line BCP037 + metadata: contains(part.metadata.type, 'MarkdownPart') ? { inputs: part.metadata.inputs - #disable-next-line BCP036 type: part.metadata.type settings: part.metadata.settings - partHeader: empty(part.metadata.partHeader) ? part.metadata.partHeader : {} + } : { + inputs: part.metadata.inputs + type: part.metadata.type + settings: part.metadata.settings + partHeader: part.metadata.partHeader } }] } diff --git a/orchestration/const/doNotRetryErrorCodes.json b/orchestration/const/doNotRetryErrorCodes.json index ffde31d..91be7d0 100644 --- a/orchestration/const/doNotRetryErrorCodes.json +++ b/orchestration/const/doNotRetryErrorCodes.json @@ -27,7 +27,11 @@ }, { "code": "InvalidRequestContent", - "errorDescription": " The request content was invalid and could not be deserialized" + "errorDescription": "The request content was invalid and could not be deserialized" + }, + { + "code": "MissingPolicyParameter", + "errorDescription": "The policy assignment is missing the parameter(s) as defined in the policy definition." } ] } diff --git a/orchestration/customCompliance/customCompliance.bicep b/orchestration/customCompliance/customCompliance.bicep index b95b0ae..4bf58bc 100644 --- a/orchestration/customCompliance/customCompliance.bicep +++ b/orchestration/customCompliance/customCompliance.bicep @@ -18,6 +18,9 @@ param parDeploymentPrefix string @maxLength(5) param parDeploymentSuffix string = '' +@description('Enforcement mode for all policy assignments.') +param parPolicyAssignmentEnforcementMode string + @description('Set this to true if any policies in the initiative include a modify effect.') param parRequireOwnerRolePermission bool = false @@ -39,6 +42,7 @@ module modRegulatoryCompliance '../../modules/compliance/customCompliance.bicep' params: { parDeploymentPrefix: parDeploymentPrefix parDeploymentSuffix: parDeploymentSuffix + parPolicyAssignmentEnforcementMode: parPolicyAssignmentEnforcementMode parIdentityRoleAssignmentsSubs: [] parRoleDefinitionIds: [ (parRequireOwnerRolePermission ? varRBACRoleDefinitionIDs.owner : varRBACRoleDefinitionIDs.reader) @@ -52,10 +56,13 @@ module modUserPolicyAssignment '../../modules/compliance/customerPolicySetAssign params: { parDeploymentPrefix: parDeploymentPrefix parDeploymentSuffix: parDeploymentSuffix + parPolicyAssignmentEnforcementMode: parPolicyAssignmentEnforcementMode parPolicySetDefinitionId: policy.policySetDefinitionId parPolicySetAssignmentName: policy.policySetAssignmentName parPolicySetAssignmentDisplayName: policy.policySetAssignmentDisplayName parPolicySetAssignmentDescription: policy.policySetAssignmentDescription + parPolicySetManagementGroupAssignmentScope: policy.policySetManagementGroupAssignmentScope + parPolicyAssignmentParameters: json(policy.policyAssignmentParameters) } dependsOn: [ modRegulatoryCompliance diff --git a/orchestration/defaultCompliance/defaultCompliance.bicep b/orchestration/defaultCompliance/defaultCompliance.bicep index 193f889..30ea933 100644 --- a/orchestration/defaultCompliance/defaultCompliance.bicep +++ b/orchestration/defaultCompliance/defaultCompliance.bicep @@ -19,6 +19,9 @@ param parDeploymentPrefix string @maxLength(5) param parDeploymentSuffix string = '' +@description('Enforcement mode for all policy assignments.') +param parPolicyAssignmentEnforcementMode string + @description('The resource ID for the DDoS plan.') param parDdosPlanResourceId string = '' @@ -49,27 +52,80 @@ 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('Set to true to deploy SLZ builtin policies, otherwise false. DEFAULT: false') +var varDeploySlzBuiltInPolicies = true + @description('Effect type for all policy definitions') -param parPolicyEffect string = 'Deny' +param parPolicyEffect string + +var varDeployPolicies = parPolicyAssignmentEnforcementMode == 'Default' ? true : false + +var varExcludedALZPolicyAssignments = [ + 'Audit-AppGW-WAF' + 'Audit-PeDnsZones' + 'Audit-Location-Match' + 'Audit-UnusedResources' + 'Audit-ZoneResiliency' + 'Deny-AppGW-Without-WAF' + 'Deny-Classic-Resources' + 'Deny-DataB-Pip' + 'Deny-DataB-Sku' + 'Deny-DataB-Vnet' + 'Enforce-AKS-HTTPS' + 'Deny-HybridNetworking' + 'Deny-IP-Forwarding' + 'Deny-MgmtPorts-Internet' + 'Deny-Priv-Containers-AKS' + 'Deny-Priv-Escalation-AKS' + 'Deny-Public-Endpoints' + 'Deny-Public-IP-On-NIC' + 'Deny-Public-IP' + 'Deny-RDP-From-Internet' + 'Deny-Resource-Locations' + 'Deny-Resource-Types' + 'Deny-RSG-Locations' + 'Deny-Storage-http' + 'Deny-Subnet-Without-Nsg' + 'Deny-Subnet-Without-Udr' + 'Deny-UnmanagedDisk' + 'Deploy-AKS-Policy' + 'Deploy-ASC-Monitoring' + 'Deploy-AzActivity-Log' + 'Deploy-AzSqlDb-Auditing' + 'Deploy-Log-Analytics' + 'Deploy-LX-Arc-Monitoring' + 'Deploy-MDEndpoints' + 'Deploy-MDFC-Config' + 'Deploy-MDFC-OssDb' + 'Deploy-MDFC-SqlAtp' + 'Deploy-Private-DNS-Zones' + 'Deploy-Resource-Diag' + 'Deploy-SQL-DB-Auditing' + 'Deploy-SQL-Security' + 'Deploy-SQL-TDE' + 'Deploy-SQL-Threat' + 'Deploy-VM-Backup' + 'Deploy-VM-Monitoring' + 'Deploy-VMSS-Monitoring' + 'Deploy-WS-Arc-Monitoring' + 'Enable-DDoS-VNET' + 'Enforce-ACSB' + 'Enforce-ALZ-Decomm' + 'Enforce-ALZ-Sandbox' + 'Enforce-GR-KeyVault' + 'Enforce-TLS-SSL' +] +var varExcludedPolicyAssignments = parDeployAlzDefaultPolicies ? [] : varExcludedALZPolicyAssignments 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 - } -} +var varSlzGlobalLibDef = loadJsonContent('../../dependencies/infra-as-code/bicep/modules/policy/assignments/lib/policy_assignments/policy_assignment_es_enforce_sovereignty_baseline_global.tmpl.json') +var varSlzGlobalAssignmentName = toLower(varSlzGlobalLibDef.name) // 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) { +module modAlzPolicyAssignments '../../dependencies/infra-as-code/bicep/modules/policy/assignments/alzDefaults/alzDefaultPolicyAssignments.bicep' = { name: take('${parDeploymentPrefix}-deploy-alz-default-policies${parDeploymentSuffix}', 64) params: { parTopLevelManagementGroupPrefix: parDeploymentPrefix @@ -81,43 +137,50 @@ module modAlzPolicyAssignments '../../dependencies/infra-as-code/bicep/modules/p parMsDefenderForCloudEmailSecurityContact: parMsDefenderForCloudEmailSecurityContact parDdosProtectionPlanId: parDdosPlanResourceId parPrivateDnsResourceGroupId: parPrivateDnsResourceGroupId - parDisableAlzDefaultPolicies: !parDeployAlzDefaultPolicies + parDisableAlzDefaultPolicies: !varDeployPolicies + parDisableSlzDefaultPolicies: !varDeployPolicies + parExcludedPolicyAssignments: varExcludedPolicyAssignments + parTopLevelPolicyAssignmentSovereigntyGlobal: { + parTopLevelSovereigntyGlobalPoliciesEnable: varDeploySlzBuiltInPolicies + parListOfAllowedLocations: parAllowedLocations + parPolicyEffect: parPolicyEffect + } + parPolicyAssignmentSovereigntyConfidential: { + parAllowedResourceTypes: [] + parListOfAllowedLocations: parAllowedLocationsForConfidentialComputing + parAllowedVirtualMachineSKUs: [] + parPolicyEffect: parPolicyEffect + } + parLandingZoneMgConfidentialEnable: varDeploySlzBuiltInPolicies } - 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}' + parPolicyDefinitionReferenceIds: ['AllowedLocationsForResourceGroups', 'AllowedLocations'] + parPolicyAssignmentName: varSlzGlobalAssignmentName + parExemptionName: 'Confidential-Online-Location-Exemption' + parExemptionDisplayName: 'Confidential Online Location Exemption' 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.' } + dependsOn: [modAlzPolicyAssignments] } // 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}' + parPolicyDefinitionReferenceIds: ['AllowedLocationsForResourceGroups', 'AllowedLocations'] + parPolicyAssignmentName: varSlzGlobalAssignmentName + parExemptionName: 'Confidential-Corp-Location-Exemption' + parExemptionDisplayName: 'Confidential Corp Location Exemption' 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.' } + dependsOn: [modAlzPolicyAssignments] } diff --git a/orchestration/policyInstallation/slz-DefaultandCustomPolicyDefinitions.txt b/orchestration/policyInstallation/alz-PolicyDefinitions.txt similarity index 98% rename from orchestration/policyInstallation/slz-DefaultandCustomPolicyDefinitions.txt rename to orchestration/policyInstallation/alz-PolicyDefinitions.txt index 0dbf1de..bf89587 100644 --- a/orchestration/policyInstallation/slz-DefaultandCustomPolicyDefinitions.txt +++ b/orchestration/policyInstallation/alz-PolicyDefinitions.txt @@ -4,7 +4,7 @@ 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 !!! +// // DO NOT Remove This Line !!! { name: 'Append-AppService-httpsonly' libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Append-AppService-httpsonly.json') @@ -429,7 +429,7 @@ var varCustomPolicyDefinitionsArray = [ name: 'Deploy-Windows-DomainJoin' libDefinition: loadJsonContent('lib/policy_definitions/policy_definition_es_Deploy-Windows-DomainJoin.json') } -// // DO NOT Remove This Line !!! +// // DO NOT Remove This Line !!! ] resource resPolicyDefinitions 'Microsoft.Authorization/policyDefinitions@2021-06-01' = [for policy in varCustomPolicyDefinitionsArray: { diff --git a/orchestration/policyInstallation/policyInstallation.bicep b/orchestration/policyInstallation/policyInstallation.bicep index 8bdb1c5..f80145d 100644 --- a/orchestration/policyInstallation/policyInstallation.bicep +++ b/orchestration/policyInstallation/policyInstallation.bicep @@ -83,7 +83,7 @@ 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' = { +module modAlzDefaultPolicyDefinitions '../../dependencies/infra-as-code/bicep/modules/policy/definitions/alz-PolicyDefinitions.bicep' = { scope: managementGroup(varManagementGroupId) name: take('${parDeploymentPrefix}-polDefs-${parDeploymentLocation}-${parTimestamp}${parDeploymentSuffix}', 64) } @@ -101,13 +101,7 @@ module modAlzPolicySetDefinitions '../../dependencies/infra-as-code/bicep/module } // Module - create default and custom SLZ Policy Set Initiatives -module modDefaultandCustomSlzPolicySetDefinitions '../../dependencies/infra-as-code/bicep/modules/policy/definitions/slz-defaultandCustomPolicySetDefinitions.bicep' = { +module modDefaultandCustomSlzPolicySetDefinitions '../../dependencies/infra-as-code/bicep/modules/policy/definitions/slz-CustomPolicySetDefinitions.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-CustomSLZPolicySetDefinitions.txt b/orchestration/policyInstallation/slz-CustomSLZPolicySetDefinitions.txt new file mode 100644 index 0000000..72cdbd4 --- /dev/null +++ b/orchestration/policyInstallation/slz-CustomSLZPolicySetDefinitions.txt @@ -0,0 +1,34 @@ +//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 = [ +] + +// Policy Set/Initiative Definition Parameter Variables + +// // 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-DefaultandCustomSLZGlobalPolicySetDefinitions.txt b/orchestration/policyInstallation/slz-DefaultandCustomSLZGlobalPolicySetDefinitions.txt deleted file mode 100644 index 51c6452..0000000 --- a/orchestration/policyInstallation/slz-DefaultandCustomSLZGlobalPolicySetDefinitions.txt +++ /dev/null @@ -1,55 +0,0 @@ -//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 deleted file mode 100644 index 3c0222a..0000000 --- a/orchestration/policyInstallation/slz-DefaultandCustomSLZPolicySetDefinitions.txt +++ /dev/null @@ -1,143 +0,0 @@ -//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/scripts/Invoke-Helper.ps1 b/orchestration/scripts/Invoke-Helper.ps1 index e201fd3..184dde4 100644 --- a/orchestration/scripts/Invoke-Helper.ps1 +++ b/orchestration/scripts/Invoke-Helper.ps1 @@ -669,13 +669,12 @@ function Show-ManagementGroupInfo { return } - $parDeploymentPrefix = $parParameters.parDeploymentPrefix.value - $parTopLevelManagementGroupName = $parParameters.parTopLevelManagementGroupName.value - $parDeploymentSuffix = $parParameters.parDeploymentSuffix.value + $parDeploymentPrefix = [System.Uri]::EscapeDataString($parParameters.parDeploymentPrefix.value) + $parTopLevelManagementGroupName = [System.Uri]::EscapeDataString($parParameters.parTopLevelManagementGroupName.value) + $parDeploymentSuffix = [System.Uri]::EscapeDataString($parParameters.parDeploymentSuffix.value) $varTenantId = (Get-AzContext).Tenant.Id $varManagementGroupLink = "$varAzPortalLink/#view/Microsoft_Azure_ManagementGroups/ManagmentGroupDrilldownMenuBlade/~/overview/tenantId/$varTenantId" $varManagementGroupLink = "$varManagementGroupLink/mgId/$parDeploymentPrefix$parDeploymentSuffix/mgDisplayName/$parTopLevelManagementGroupName/mgCanAddOrMoveSubscription~/true/mgParentAccessLevel/Owner/defaultMenuItemId/overview/drillDownMode~/true" - $varManagementGroupLink = [System.Uri]::EscapeUriString($varManagementGroupLink) $varManagementGroupInfo = "If you want to learn more about your management group, please click following link.`n`n" $varManagementGroupInfo = "$varManagementGroupInfo$varManagementGroupLink`n`n" @@ -918,3 +917,13 @@ function Out-DeploymentParameters { # Save the updated data to the CSV file $varUpdatedData | Export-Csv -Path $varExistingCsvFilePath -NoTypeInformation } + +<# +.Description + Checks whether the Az Resources's version is later than or equal version 7.0.0, which contains breaking changes and could break existing SLZ scripts. +#> +function Confirm-AzResourceVersion { + $varAzResourcesVersion = (Get-InstalledModule -Name Az.Resources).Version.replace("-preview", "") + $varVersion = [Version]$varAzResourcesVersion -ge [Version]"7.0.0" + return $varVersion +} diff --git a/orchestration/scripts/Invoke-SlzDefaultandCustomPolicyToBicep.ps1 b/orchestration/scripts/Invoke-SlzCustomPolicyToBicep.ps1 similarity index 70% rename from orchestration/scripts/Invoke-SlzDefaultandCustomPolicyToBicep.ps1 rename to orchestration/scripts/Invoke-SlzCustomPolicyToBicep.ps1 index 954dbc4..270fe55 100644 --- a/orchestration/scripts/Invoke-SlzDefaultandCustomPolicyToBicep.ps1 +++ b/orchestration/scripts/Invoke-SlzCustomPolicyToBicep.ps1 @@ -44,19 +44,13 @@ param ( [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", + $parTempPolicyDefinitionOutput = "tempCustomPolicyDefinitions.bicep", [string] - $parTempSLZPolicySetDefinitionOutput = "slzTempDefaultandCustomPolicySetDefinitions.bicep", + $parTempSLZPolicySetDefinitionOutput = "slzTempCustomPolicySetDefinitions.bicep", [string] $parTempALZPolicySetDefinitionOutput = "alzTempPolicySetDefinitions.bicep", $parAttendedLogin = $true @@ -70,8 +64,8 @@ function Move-PolicySetDefinitions { [CmdletBinding(SupportsShouldProcess)] param([string] $parRootPath) - $varDefaultDefinitionFiles = Get-ChildItem -Path "$parRootPath/*.json" - foreach ($varFile in $varDefaultDefinitionFiles) { + $varPolicySetDefinitionFiles = Get-ChildItem -Path "$parRootPath/*.json" + foreach ($varFile in $varPolicySetDefinitionFiles) { Write-Debug "Processing $varFile.Name" $varFilePath = $parRootPath + "/" + $varFile.Name @@ -91,17 +85,16 @@ function Move-PolicySetDefinitions { .Description Copy files to destination path #> -function Copy-SlzDefaultandCustomPolicyDefinitionsBicep { +function Copy-SlzCustomPolicyDefinitionsBicep { [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" + Write-Information ">>> Initiating copy of alz-PolicyDefinitions.bicep, slz-CustomPolicySetDefinitions.bicep and alzPolicySetDefinitions.bicep to $varDestinationFolder" -InformationAction Continue + Copy-Item "../policyInstallation/alz-PolicyDefinitions.txt" -Destination "$varDestinationFolder\alz-PolicyDefinitions.bicep" + Copy-Item "../policyInstallation/slz-CustomSLZPolicySetDefinitions.txt" -Destination "$varDestinationFolder\slz-CustomPolicySetDefinitions.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 + Write-Information ">>> copied alz-PolicyDefinitions.bicep, slz-CustomPolicySetDefinitions.bicep and alzPolicySetDefinitions.bicep to $varDestinationFolder" -InformationAction Continue } <# @@ -112,11 +105,6 @@ 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 @@ -138,12 +126,12 @@ function Invoke-ALZScript { .Description Create new policy definition bicep file. #> -function New-DefaultandCustomPolicyDefinitionsBicepFile { +function New-AlzPolicyDefinitionsBicepFile { [CmdletBinding(SupportsShouldProcess)] param() $varPolicyDefinitionsBicepInput = "$parDefinitionsLongPath/_policyDefinitionsBicepInput.txt" - $varDefaultandCustomPolicyDefinitionsBicepFile = "$parDestRootPath/definitions/slz-defaultandCustomPolicyDefinitions.bicep" + $varCustomPolicyDefinitionsBicepFile = "$parDestRootPath/definitions/alz-PolicyDefinitions.bicep" $varKeepCopying = $true # processing animation for attended run @@ -158,8 +146,8 @@ function New-DefaultandCustomPolicyDefinitionsBicepFile { 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 '') { + Get-Content $varCustomPolicyDefinitionsBicepFile | ForEach-Object { + if ($_ -match '') { if ($_ -match '.+([Ss]tart)\s*-->') { $varKeepCopying = $false @@ -196,8 +184,8 @@ function New-DefaultandCustomPolicyDefinitionsBicepFile { catch { Write-Error "Error in merging new policy/policy-set: $_.Exception.Message" } - #replace $varDefaultandCustomPolicyDefinitionsBicepFile with $parTempPolicyDefinitionOutput - Copy-Item $parTempPolicyDefinitionOutput -Destination $varDefaultandCustomPolicyDefinitionsBicepFile -force + #replace $varCustomPolicyDefinitionsBicepFile with $parTempPolicyDefinitionOutput + Copy-Item $parTempPolicyDefinitionOutput -Destination $varCustomPolicyDefinitionsBicepFile -force } <# .Description @@ -236,7 +224,6 @@ function New-SLZPolicySetDefinitonsBicepInputFiles { <#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 @@ -245,22 +232,23 @@ function New-SLZPolicySetDefinitonsBicepInputFiles { <# 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) { + if ($varSlzPolicySet.Count -gt 0) { + $varPolicyParamVarName = Get-PolicySetParamVariableName $varSlzPolicySet + [void]$varSlzPolicyParams.Add($varPolicyParamVarName) + [void]$varSlzPolicySetList.Add($varSlzPolicySet) + $varSlzPolicySet = @() + } + else { + $varPolicyParamVarName = Get-PolicySetParamVariableName $varAlzPolicySet + [void]$varAlzPolicyParams.Add($varPolicyParamVarName) + [void]$varAlzPolicySetList.Add($varAlzPolicySet) + $varAlzPolicySet = @() + } #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" } @@ -282,15 +270,9 @@ function New-SLZPolicySetDefinitonsBicepInputFiles { <# 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 - } + if ($_ -ne $null -and $varLine -match $_) { + Add-Content $parSlzPolicySetDefinitonTxtFile $varLine } } $varAlzPolicyParams | ForEach-Object { @@ -385,9 +367,16 @@ Checks whether to add an end bracket to the policy set definition file function Confirm-AddEndBracket { param ($parPolicySetfilePath) $varPolicySetFileContent = Get-Content $parPolicySetfilePath - + #for the sceanario where there are no slz custom policies $varIterationCounter = $varPolicySetFileContent.Count - + if ($varIterationCounter -eq 1) { + if ($varPolicySetFileContent[$varIterationCounter][-1] -eq "]") { + return $false + } + else { + return $true + } + } do { if ($varPolicySetFileContent[$varIterationCounter] -match '}') { return $true @@ -407,95 +396,20 @@ 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 - } + $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 { +function New-CustomSlzPolicySetDefinitionBicepFile { [CmdletBinding(SupportsShouldProcess)] param() @@ -510,13 +424,13 @@ function New-DefaultandCustomSlzPolicySetDefinitionBicepFile { } $varSlzPolicyDefinitionsSetBicepInput = "$parSlzPolicySetDefinitonTxtFile" - $varDefaultandCustomSLZPolicyDefinitionsBicepFile = "$parDestRootPath/definitions/slz-defaultandCustomPolicySetDefinitions.bicep" + $varCustomSLZPolicyDefinitionsBicepFile = "$parDestRootPath/definitions/slz-CustomPolicySetDefinitions.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 '') { + Get-Content $varCustomSLZPolicyDefinitionsBicepFile | ForEach-Object { + if ($_ -match '') { if ($_ -match '.+([Ss]tart)\s*-->') { $varKeepCopying = $false @@ -555,7 +469,7 @@ function New-DefaultandCustomSlzPolicySetDefinitionBicepFile { } #replace $varDefaultandCustomSLZPolicyDefinitionsBicepFile with $parTempSLZPolicySetDefinitionOutput - Copy-Item $parTempSLZPolicySetDefinitionOutput -Destination $varDefaultandCustomSLZPolicyDefinitionsBicepFile -force + Copy-Item $parTempSLZPolicySetDefinitionOutput -Destination $varCustomSLZPolicyDefinitionsBicepFile -force } <# @@ -587,7 +501,7 @@ function New-AlzPolicySetDefinitionBicepFile { if ($_ -match '.+([Ss]tart)\s*-->') { $varKeepCopying = $false - Add-Content -Path $parTempSLZPolicySetDefinitionOutput -Value "// start" + Add-Content -Path $parTempALZPolicySetDefinitionOutput -Value "// start" # copy $alzPolicyDefinitionsSetBicepInput Get-Content $alzPolicyDefinitionsSetBicepInput | Add-Content -Path $parTempALZPolicySetDefinitionOutput Add-Content -Path $parTempALZPolicySetDefinitionOutput -Value "// end" @@ -634,12 +548,11 @@ 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 + Write-Information "Removing tempCustomPolicyDefinitions.bicep and slzTempCustomPolicySetDefinitions.bicep files" -InformationAction Continue + Get-Item -Path ".\tempCustomPolicyDefinitions.bicep" | Remove-Item + Get-Item -Path ".\slzTempCustomPolicySetDefinitions.bicep" | Remove-Item Get-Item -Path ".\alzTempPolicySetDefinitions.bicep" | Remove-Item - Write-Information "Removed tempDefaultandCustomPolicyDefinitions.bicep, slzTempGlobalDefaultandCustomPolicySetDefinitions.bicep and slzTempDefaultandCustomPolicySetDefinitions.bicep files" -InformationAction Continue + Write-Information "Removed tempCustomPolicyDefinitions.bicep and slzTempCustomPolicySetDefinitions.bicep files" -InformationAction Continue } <# @@ -668,25 +581,19 @@ function Flush_Output { } 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 #> +Copy-SlzCustomPolicyDefinitionsBicep +<# For slz 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-AlzPolicyDefinitionsBicepFile +<# The function will create a file containing 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 +New-CustomSlzPolicySetDefinitionBicepFile <# The function will create ALZ policy set definition bicep file #> New-AlzPolicySetDefinitionBicepFile Remove-TempFile diff --git a/orchestration/scripts/New-Compliance.ps1 b/orchestration/scripts/New-Compliance.ps1 index 8673f7b..4d3093b 100644 --- a/orchestration/scripts/New-Compliance.ps1 +++ b/orchestration/scripts/New-Compliance.ps1 @@ -44,7 +44,12 @@ function Get-PolicyAssignmentsandExemptions { 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 + if (Confirm-AzResourceVersion) { + $varPolicySetDefinitions = Get-AzPolicySetDefinition -ManagementGroupName $varManagementGroupId -BackwardCompatible -WarningAction Ignore + } + else { + $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 @@ -231,11 +236,22 @@ function New-CustomCompliance { $varManagementGroupId = "$parDeploymentPrefix$parDeploymentSuffix" $parDeploymentLocation = $parParameters.parDeploymentLocation.value $varCustomerPolicySets = Convert-ToArray($parParameters.parCustomerPolicySets.value) + + $varCustomerPolicySets.foreach({ + if ($null -ne $_.policyParameterFilePath -and $_.policyParameterFilePath -ne "") { + $_.policyAssignmentParameters = (Get-Content -Path $_.policyParameterFilePath -Raw) -replace '\r?\n', '' + } + else { + $_.policyAssignmentParameters = '{}' + } + }) + $varParams = @{ - parDeploymentPrefix = $parDeploymentPrefix - parDeploymentSuffix = $parDeploymentSuffix - parRequireOwnerRolePermission = $parParameters.parRequireOwnerRolePermission.value - parCustomerPolicySets = $varCustomerPolicySets + parDeploymentPrefix = $parDeploymentPrefix + parDeploymentSuffix = $parDeploymentSuffix + parRequireOwnerRolePermission = $parParameters.parRequireOwnerRolePermission.value + parCustomerPolicySets = $varCustomerPolicySets + parPolicyAssignmentEnforcementMode = $parParameters.parPolicyAssignmentEnforcementMode.value } $varDeploymentName = "deploy-customcompliance-$vartimeStamp" @@ -337,63 +353,61 @@ function New-DefaultCompliance { parLogAnalyticsWorkspaceLogRetentionInDays = ($parParameters.parLogRetentionInDays.value).ToString() parMsDefenderForCloudEmailSecurityContact = $parParameters.parMsDefenderForCloudEmailSecurityContact.value parPolicyEffect = $parParameters.parPolicyEffect.value + parPolicyAssignmentEnforcementMode = $parParameters.parPolicyAssignmentEnforcementMode.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 + $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 + $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) { + $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 - } + if ($modDeployDefaultCompliance.ProvisioningState -eq "Failed") { + Write-Error "Error occurred during default compliance deployment." -ErrorAction Stop + } - Write-Information ">>> Default compliance completed" -InformationAction Continue - return $modDeployDefaultCompliance + 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 } - 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 + 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 { - $varDeploymentErrorCodes = Get-FailedDeploymentErrorCodes $varManagementGroupId $varDeploymentName $varManagementGroupDeployment - if ($null -eq $varDeploymentErrorCodes) { - $varRetry = $false + $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 { - $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 - } + $varRetry = $false + Write-Error ">>> Error occurred in default compliance deployment. Please try after addressing the above error." -ErrorAction Stop } } } @@ -494,8 +508,8 @@ function Invoke-PolicyGeneration { Write-Information ">>> Initiating Policy generation script" -InformationAction Continue - $varInvokeSLZDefaultandCustomPolicy = '.\Invoke-SlzDefaultandCustomPolicyToBicep.ps1' - & $varInvokeSLZDefaultandCustomPolicy -parAttendedLogin $parAttendedLogin -ErrorAction Stop + $varInvokeSLZCustomPolicy = '.\Invoke-SlzCustomPolicyToBicep.ps1' + & $varInvokeSLZCustomPolicy -parAttendedLogin $parAttendedLogin -ErrorAction Stop Write-Information ">>> Policy generation complete" -InformationAction Continue return @@ -511,7 +525,7 @@ function Invoke-PolicyGeneration { Gets the default and custom policy set definition name and versions. #> function Get-PolicySetDefinitionVersion { - $varTargetDirectories = "../../modules/compliance/policySetDefinitions", "../../custom/policies/definitions" + $varTargetDirectories = "../../custom/policies/definitions" $varPolicySetDefinitionDict = @{} foreach ($varDirectory in $varTargetDirectories) { $varSlzPolicySetDefinitionFiles = Get-ChildItem -Path "$varDirectory/*.json" diff --git a/orchestration/scripts/New-Platform.ps1 b/orchestration/scripts/New-Platform.ps1 index d1ac5df..df0b4c2 100644 --- a/orchestration/scripts/New-Platform.ps1 +++ b/orchestration/scripts/New-Platform.ps1 @@ -126,7 +126,7 @@ function New-Platform { Write-Error "`n Error while executing platform deployment" -ErrorAction Stop } - Write-Information ">>> Platform deployment completed" -InformationAction Continue + Write-Information ">>> Platform deployment completed`n" -InformationAction Continue # update parameters Out-DeploymentParameters "platform" $modDeploySovereignPlatform $varManagementGroupId $parParameters return $modDeploySovereignPlatform diff --git a/orchestration/scripts/parameters/policyParameters/policySetParameterSampleFile.json b/orchestration/scripts/parameters/policyParameters/policySetParameterSampleFile.json new file mode 100644 index 0000000..c1309bc --- /dev/null +++ b/orchestration/scripts/parameters/policyParameters/policySetParameterSampleFile.json @@ -0,0 +1,11 @@ +{ + "stringParameterName": { + "value": "value" + }, + "objectParameterName": { + "value": {} + }, + "arrayParameterName": { + "value": [] + } +} diff --git a/orchestration/scripts/parameters/sovereignLandingZone.parameters.json b/orchestration/scripts/parameters/sovereignLandingZone.parameters.json index b5daefe..4faedf3 100644 --- a/orchestration/scripts/parameters/sovereignLandingZone.parameters.json +++ b/orchestration/scripts/parameters/sovereignLandingZone.parameters.json @@ -494,13 +494,17 @@ "usedBy": "all and compliance", "defaultValue": "Deny", "value": null, - "allowedValues": [ - "Audit", - "Deny", - "Disabled" - ], + "allowedValues": ["Audit", "Deny", "Disabled"], "description": "The policy effect used in all assignments for the Sovereignty Baseline policy initiatives." }, + "parPolicyAssignmentEnforcementMode": { + "type": "string", + "usedBy": "all and compliance", + "defaultValue": "Default", + "value": null, + "allowedValues": ["Default", "DoNotEnforce"], + "description": "The enforcement mode used in all policy and initiative assignments." + }, "parDeployLogAnalyticsWorkspace": { "type": "bool", "usedBy": "all, platform", @@ -517,11 +521,13 @@ "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" + "policySetAssignmentDescription": "NIST 800-53 Initiative", + "policySetManagementGroupAssignmentScope": "/providers/Microsoft.Management/managementGroups/REPLACE_WITH_MANAGEMENT_GROUP_ID", + "policyParameterFilePath": "./parameters/policyParameters/nist800Parameter.json" } ], "value": [], - "description": "Optional array of customer specified policy assignments to the top-level management group." + "description": "Optional array of customer specified policy assignments to the mentioned scope with the optional input parameter file. If scope is empty assigned at root." }, "parTags": { "type": "object",