diff --git a/infra-as-code/bicep/modules/hubNetworking/generateddocs/hubNetworking.bicep.md b/infra-as-code/bicep/modules/hubNetworking/generateddocs/hubNetworking.bicep.md index ae2720185..b19ca61f2 100644 --- a/infra-as-code/bicep/modules/hubNetworking/generateddocs/hubNetworking.bicep.md +++ b/infra-as-code/bicep/modules/hubNetworking/generateddocs/hubNetworking.bicep.md @@ -28,6 +28,7 @@ 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. +parAzFirewallPoliciesEnabled | No | Switch to enable/disable Azure Firewall Policies deployment. parAzFirewallPoliciesName | No | Azure Firewall Policies Name. 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. @@ -252,6 +253,14 @@ Azure Firewall Name. - Default value: `[format('{0}-azfw-{1}', parameters('parCompanyPrefix'), parameters('parLocation'))]` +### parAzFirewallPoliciesEnabled + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Switch to enable/disable Azure Firewall Policies deployment. + +- Default value: `True` + ### parAzFirewallPoliciesName ![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) @@ -495,6 +504,10 @@ outPrivateDnsZonesNames | array | outDdosPlanResourceId | string | outHubVirtualNetworkName | string | outHubVirtualNetworkId | string | +outHubRouteTableId | string | +outHubRouteTableName | string | +outBastionNsgId | string | +outBastionNsgName | string | ## Snippets @@ -611,6 +624,9 @@ outHubVirtualNetworkId | string | "parAzFirewallName": { "value": "[format('{0}-azfw-{1}', parameters('parCompanyPrefix'), parameters('parLocation'))]" }, + "parAzFirewallPoliciesEnabled": { + "value": true + }, "parAzFirewallPoliciesName": { "value": "[format('{0}-azfwpolicy-{1}', parameters('parCompanyPrefix'), parameters('parLocation'))]" }, diff --git a/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep b/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep index 4b3590fe4..ec7177f6c 100644 --- a/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep +++ b/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep @@ -160,6 +160,9 @@ param parAzFirewallEnabled bool = true @sys.description('Azure Firewall Name.') param parAzFirewallName string = '${parCompanyPrefix}-azfw-${parLocation}' +@sys.description('Switch to enable/disable Azure Firewall Policies deployment.') +param parAzFirewallPoliciesEnabled bool = true + @sys.description('Azure Firewall Policies Name.') param parAzFirewallPoliciesName string = '${parCompanyPrefix}-azfwpolicy-${parLocation}' @@ -853,7 +856,7 @@ module modAzureFirewallMgmtPublicIp '../publicIp/publicIp.bicep' = if (parAzFire } } -resource resFirewallPolicies 'Microsoft.Network/firewallPolicies@2023-02-01' = if (parAzFirewallEnabled) { +resource resFirewallPolicies 'Microsoft.Network/firewallPolicies@2023-02-01' = if (parAzFirewallEnabled && parAzFirewallPoliciesEnabled) { name: parAzFirewallPoliciesName location: parLocation tags: parTags @@ -1068,3 +1071,7 @@ output outPrivateDnsZonesNames array = (parPrivateDnsZonesEnabled ? modPrivateDn output outDdosPlanResourceId string = resDdosProtectionPlan.id output outHubVirtualNetworkName string = resHubVnet.name output outHubVirtualNetworkId string = resHubVnet.id +output outHubRouteTableId string = parAzFirewallEnabled ? resHubRouteTable.id : '' +output outHubRouteTableName string = parAzFirewallEnabled ? resHubRouteTable.name : '' +output outBastionNsgId string = parAzBastionEnabled ? resBastionNsg.id : '' +output outBastionNsgName string = parAzBastionEnabled ? resBastionNsg.name : '' diff --git a/infra-as-code/bicep/modules/policy/assignments/alzDefaults/alzDefaultPolicyAssignments.bicep b/infra-as-code/bicep/modules/policy/assignments/alzDefaults/alzDefaultPolicyAssignments.bicep index 7246d0610..382517bdb 100644 --- a/infra-as-code/bicep/modules/policy/assignments/alzDefaults/alzDefaultPolicyAssignments.bicep +++ b/infra-as-code/bicep/modules/policy/assignments/alzDefaults/alzDefaultPolicyAssignments.bicep @@ -1655,3 +1655,31 @@ module modPolicyAssignmentSandboxEnforceAlz '../../../policy/assignments/policyA parTelemetryOptOut: parTelemetryOptOut } } + +// The following module is used to deploy the policy exemptions +module modPolicyExemptionsConfidentialOnline '../../exemptions/policyExemptions.bicep' = if (parLandingZoneMgConfidentialEnable) { + scope: managementGroup(varManagementGroupIds.landingZonesConfidentialOnline) + name: take('${parTopLevelManagementGroupPrefix}-deploy-policy-exemptions${parTopLevelManagementGroupSuffix}', 64) + params: { + parPolicyAssignmentId: modPolicyAssignmentIntRootEnforceSovereigntyGlobal.outputs.outPolicyAssignmentId + parPolicyDefinitionReferenceIds: ['AllowedLocationsForResourceGroups', 'AllowedLocations'] + parExemptionName: 'Confidential-Online-Location-Exemption' + parExemptionDisplayName: 'Confidential Online Location Exemption' + parDescription: 'Exempt the confidential online management group from the SLZ Global location policies. The confidential management groups have their own location restrictions and this may result in a conflict if both sets are included.' + } + dependsOn: [modPolicyAssignmentLzsConfidentialOnlineEnforceSovereigntyConf] +} + +// The following module is used to deploy the policy exemptions +module modPolicyExemptionsConfidentialCorp '../../exemptions/policyExemptions.bicep' = if (parLandingZoneMgConfidentialEnable) { + scope: managementGroup(varManagementGroupIds.landingZonesConfidentialCorp) + name: take('${parTopLevelManagementGroupPrefix}-deploy-policy-exemptions${parTopLevelManagementGroupSuffix}', 64) + params: { + parPolicyAssignmentId: modPolicyAssignmentIntRootEnforceSovereigntyGlobal.outputs.outPolicyAssignmentId + parPolicyDefinitionReferenceIds: ['AllowedLocationsForResourceGroups', 'AllowedLocations'] + 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: [modPolicyAssignmentLzsConfidentialCorpEnforceSovereigntyConf] +} diff --git a/infra-as-code/bicep/modules/policy/assignments/generateddocs/policyAssignmentManagementGroup.bicep.md b/infra-as-code/bicep/modules/policy/assignments/generateddocs/policyAssignmentManagementGroup.bicep.md index 92036d22f..99af732b2 100644 --- a/infra-as-code/bicep/modules/policy/assignments/generateddocs/policyAssignmentManagementGroup.bicep.md +++ b/infra-as-code/bicep/modules/policy/assignments/generateddocs/policyAssignmentManagementGroup.bicep.md @@ -136,6 +136,12 @@ Set Parameter to true to Opt-out of deployment telemetry - Default value: `False` +## Outputs + +Name | Type | Description +---- | ---- | ----------- +outPolicyAssignmentId | string | + ## Snippets ### Parameter file diff --git a/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep b/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep index b62e8127d..b9ac25532 100644 --- a/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep +++ b/infra-as-code/bicep/modules/policy/assignments/policyAssignmentManagementGroup.bicep @@ -143,3 +143,5 @@ module modCustomerUsageAttribution '../../../CRML/customerUsageAttribution/cuaId name: 'pid-${varCuaid}-${uniqueString(deployment().location, parPolicyAssignmentName)}' params: {} } + +output outPolicyAssignmentId string = resPolicyAssignment.id diff --git a/infra-as-code/bicep/modules/policy/exemptions/README.md b/infra-as-code/bicep/modules/policy/exemptions/README.md new file mode 100644 index 000000000..3b7014660 --- /dev/null +++ b/infra-as-code/bicep/modules/policy/exemptions/README.md @@ -0,0 +1,23 @@ +# Module: Policy Exemptions + +This module defines a Policy Exemptions. + +Module deploys the following resources: + +- Policy Exemptions + +## Parameters + +- [Link to Parameters](generateddocs/policyExemptions.bicep.md) + +## Outputs + +None + +## Deployment + +Module is intended to be called from other modules as a reusable resource. + +## Bicep Visualizer + +![Bicep Visualizer](media/bicepVisualizer.png "Bicep Visualizer") diff --git a/infra-as-code/bicep/modules/policy/exemptions/generateddocs/policyExemptions.bicep.md b/infra-as-code/bicep/modules/policy/exemptions/generateddocs/policyExemptions.bicep.md new file mode 100644 index 000000000..7478c978f --- /dev/null +++ b/infra-as-code/bicep/modules/policy/exemptions/generateddocs/policyExemptions.bicep.md @@ -0,0 +1,102 @@ +# ALZ Bicep - Management Group Policy Exemptions + +Module used to create a policy exemption for a policy assignment in a management group + +## Parameters + +Parameter name | Required | Description +-------------- | -------- | ----------- +parPolicyAssignmentId | Yes | The ID of the policy set assignment for which the exemption will be established. +parExemptionCategory | No | The exemption category to be used. +parDescription | Yes | The description which provides context for the policy exemption. +parAssignmentScopeValidation | No | Sets the scope to permit an exemption to bypass this validation and be created beyond the assignment scope. +parPolicyDefinitionReferenceIds | Yes | List used to specify which policy definition(s) in the initiative the subject resource has an exemption to. +parExemptionName | Yes | The resource name of the policy exemption. +parExemptionDisplayName | Yes | The display name of the exemption. + +### parPolicyAssignmentId + +![Parameter Setting](https://img.shields.io/badge/parameter-required-orange?style=flat-square) + +The ID of the policy set assignment for which the exemption will be established. + +### parExemptionCategory + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +The exemption category to be used. + +- Default value: `Waiver` + +- Allowed values: `Waiver`, `Mitigated` + +### parDescription + +![Parameter Setting](https://img.shields.io/badge/parameter-required-orange?style=flat-square) + +The description which provides context for the policy exemption. + +### parAssignmentScopeValidation + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Sets the scope to permit an exemption to bypass this validation and be created beyond the assignment scope. + +- Default value: `Default` + +- Allowed values: `Default`, `DoNotValidate` + +### parPolicyDefinitionReferenceIds + +![Parameter Setting](https://img.shields.io/badge/parameter-required-orange?style=flat-square) + +List used to specify which policy definition(s) in the initiative the subject resource has an exemption to. + +### parExemptionName + +![Parameter Setting](https://img.shields.io/badge/parameter-required-orange?style=flat-square) + +The resource name of the policy exemption. + +### parExemptionDisplayName + +![Parameter Setting](https://img.shields.io/badge/parameter-required-orange?style=flat-square) + +The display name of the exemption. + +## 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/policy/exemptions/policyExemptions.json" + }, + "parameters": { + "parPolicyAssignmentId": { + "value": "" + }, + "parExemptionCategory": { + "value": "Waiver" + }, + "parDescription": { + "value": "" + }, + "parAssignmentScopeValidation": { + "value": "Default" + }, + "parPolicyDefinitionReferenceIds": { + "value": [] + }, + "parExemptionName": { + "value": "" + }, + "parExemptionDisplayName": { + "value": "" + } + } +} +``` diff --git a/infra-as-code/bicep/modules/policy/exemptions/media/bicepVisualizer.png b/infra-as-code/bicep/modules/policy/exemptions/media/bicepVisualizer.png new file mode 100644 index 000000000..03dde588a Binary files /dev/null and b/infra-as-code/bicep/modules/policy/exemptions/media/bicepVisualizer.png differ diff --git a/infra-as-code/bicep/modules/policy/exemptions/parameters/policyExemptions.parameters.all.json b/infra-as-code/bicep/modules/policy/exemptions/parameters/policyExemptions.parameters.all.json new file mode 100644 index 000000000..c1b6c34e5 --- /dev/null +++ b/infra-as-code/bicep/modules/policy/exemptions/parameters/policyExemptions.parameters.all.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "parPolicyAssignmentId": { + "value": "/providers/microsoft.management/managementgroups/policyAssignmentScopeName/providers/microsoft.authorization/policyassignments/policyAssignmentName" + }, + "parExemptionCategory": { + "value": "Waiver" + }, + "parDescription": { + "value": "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." + }, + "parAssignmentScopeValidation": { + "value": "Default" + }, + "parPolicyDefinitionReferenceIds": { + "value": ["AllowedLocationsForResourceGroups", "AllowedLocations"] + }, + "parExemptionName": { + "value": "Confidential-Corp-Location-Exemption" + }, + "parExemptionDisplayName": { + "value": "Confidential Corp Location Exemption" + } + } +} diff --git a/infra-as-code/bicep/modules/policy/exemptions/parameters/policyExemptions.parameters.min.json b/infra-as-code/bicep/modules/policy/exemptions/parameters/policyExemptions.parameters.min.json new file mode 100644 index 000000000..fd31fe468 --- /dev/null +++ b/infra-as-code/bicep/modules/policy/exemptions/parameters/policyExemptions.parameters.min.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "parPolicyAssignmentId": { + "value": "/providers/microsoft.management/managementgroups/policyAssignmentScopeName/providers/microsoft.authorization/policyassignments/policyAssignmentName" + }, + "parDescription": { + "value": "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." + }, + "parPolicyDefinitionReferenceIds": { + "value": ["AllowedLocationsForResourceGroups", "AllowedLocations"] + }, + "parExemptionName": { + "value": "Confidential-Corp-Location-Exemption" + }, + "parExemptionDisplayName": { + "value": "Confidential Corp Location Exemption" + } + } +} diff --git a/infra-as-code/bicep/modules/policy/exemptions/policyExemptions.bicep b/infra-as-code/bicep/modules/policy/exemptions/policyExemptions.bicep new file mode 100644 index 000000000..276d46dd5 --- /dev/null +++ b/infra-as-code/bicep/modules/policy/exemptions/policyExemptions.bicep @@ -0,0 +1,46 @@ +targetScope = 'managementGroup' + +metadata name = 'ALZ Bicep - Management Group Policy Exemptions' +metadata description = 'Module used to create a policy exemption for a policy assignment in a management group' + +@sys.description('The ID of the policy set assignment for which the exemption will be established.') +param parPolicyAssignmentId string + +@allowed([ + 'Waiver' + 'Mitigated' +]) +@sys.description('The exemption category to be used.') +param parExemptionCategory string = 'Waiver' + +@sys.description('The description which provides context for the policy exemption.') +param parDescription string + +@allowed([ + 'Default' + 'DoNotValidate' +]) +@sys.description('Sets the scope to permit an exemption to bypass this validation and be created beyond the assignment scope.') +param parAssignmentScopeValidation string = 'Default' + +@sys.description('List used to specify which policy definition(s) in the initiative the subject resource has an exemption to.') +param parPolicyDefinitionReferenceIds array + +@sys.description('The resource name of the policy exemption.') +param parExemptionName string + +@sys.description('The display name of the exemption.') +param parExemptionDisplayName string + +// Create Policy Exemption +resource resPolicyExemption 'Microsoft.Authorization/policyExemptions@2022-07-01-preview' = { + name: parExemptionName + properties: { + assignmentScopeValidation: parAssignmentScopeValidation + description: parDescription + displayName: parExemptionDisplayName + exemptionCategory: parExemptionCategory + policyAssignmentId: parPolicyAssignmentId + policyDefinitionReferenceIds: parPolicyDefinitionReferenceIds + } +}