From 759030a390243a11dfa0f69be6fce28418396595 Mon Sep 17 00:00:00 2001 From: Robert Lightner <49571483+DaFitRobsta@users.noreply.github.com> Date: Sun, 28 Jan 2024 18:22:26 -0700 Subject: [PATCH] Feat: Add Resource Locking to ALZ Bicep Modules (#712) * Initial Commit * feat: Adding resource lock functionality * fix: Updated with custom Type definitions * feat: Added Resource Locks * feat: Added resource lock option * Feat: Added Resource Lock Option * doc: Manually generated parameter MD files * Generate Parameter Markdowns [DaFitRobsta/f019dff0] * Generate Parameter Markdowns [DaFitRobsta/f019dff0] * Standardize to camel case for DDoS * Generate Parameter Markdowns [oZakari/5e40e5ad] * Update infra-as-code/bicep/modules/privateDnsZones/privateDnsZones.bicep LGTM Co-authored-by: Zach Trocinski <30884663+oZakari@users.noreply.github.com> * Update infra-as-code/bicep/modules/privateDnsZones/privateDnsZones.bicep Thanks for finding this! Co-authored-by: Zach Trocinski <30884663+oZakari@users.noreply.github.com> * Update infra-as-code/bicep/modules/privateDnsZones/privateDnsZones.bicep LGTM Co-authored-by: Zach Trocinski <30884663+oZakari@users.noreply.github.com> * Update infra-as-code/bicep/modules/publicIp/publicIp.bicep LGTM Co-authored-by: Zach Trocinski <30884663+oZakari@users.noreply.github.com> * fix: old parameter values removed * fix: removed extra parameter. /azp run validateazcloud --------- Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Zach Trocinski Co-authored-by: Zach Trocinski <30884663+oZakari@users.noreply.github.com> --- .../generateddocs/hubNetworking.bicep.md | 120 +++++++++++++++ .../modules/hubNetworking/hubNetworking.bicep | 144 ++++++++++++++++++ .../hubNetworking.parameters.all.json | 48 ++++++ .../hubNetworking.parameters.az.all.json | 48 ++++++ .../mc-hubNetworking.parameters.all.json | 48 ++++++ .../logging/generateddocs/logging.bicep.md | 60 ++++++++ .../bicep/modules/logging/logging.bicep | 65 ++++++++ .../parameters/logging.parameters.all.json | 24 +++ .../parameters/mc-logging.parameters.all.json | 24 +++ .../privateDnsZoneLinks.bicep.md | 15 ++ .../privateDnsZoneLinks.bicep | 26 ++++ .../generateddocs/privateDnsZones.bicep.md | 15 ++ .../privateDnsZones/privateDnsZones.bicep | 44 ++++++ .../publicIp/generateddocs/publicIp.bicep.md | 16 ++ .../bicep/modules/publicIp/publicIp.bicep | 27 ++++ .../generateddocs/resourceGroup.bicep.md | 15 ++ .../generateddocs/resourceGroupLock.bicep.md | 49 ++++++ .../resourceGroup.parameters.all.json | 6 + .../modules/resourceGroup/resourceGroup.bicep | 27 ++++ .../resourceGroup/resourceGroupLock.bicep | 31 ++++ .../generateddocs/spokeNetworking.bicep.md | 45 ++++++ .../spokeNetworking.parameters.all.json | 18 +++ .../spokeNetworking/spokeNetworking.bicep | 49 ++++++ .../generateddocs/vwanConnectivity.bicep.md | 120 +++++++++++++++ .../mc-vwanConnectivity.parameters.all.json | 48 ++++++ .../vwanConnectivity.parameters.all.json | 48 ++++++ .../vwanConnectivity/vwanConnectivity.bicep | 130 ++++++++++++++++ .../generateddocs/hubPeeredSpoke.bicep.md | 75 +++++++++ .../hubPeeredSpoke/hubPeeredSpoke.bicep | 47 ++++++ .../hubPeeredSpoke.parameters.all.json | 30 ++++ .../hubPeeredSpoke.vwan.parameters.all.json | 30 ++++ 31 files changed, 1492 insertions(+) create mode 100644 infra-as-code/bicep/modules/resourceGroup/generateddocs/resourceGroupLock.bicep.md create mode 100644 infra-as-code/bicep/modules/resourceGroup/resourceGroupLock.bicep 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 3519be20e..67ddf2366 100644 --- a/infra-as-code/bicep/modules/hubNetworking/generateddocs/hubNetworking.bicep.md +++ b/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. 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. 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. parDdosEnabled | No | Switch to enable/disable DDoS Network Protection deployment. parDdosPlanName | No | DDoS Plan Name. +parDdosLock | No | Resource Lock Configuration for DDoS Plan. parAzFirewallEnabled | No | Switch to enable/disable Azure Firewall deployment. parAzFirewallName | No | Azure Firewall Name. parAzFirewallPoliciesName | No | Azure Firewall Policies Name. @@ -32,17 +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. 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. 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 +parPrivateDNSZonesLock | No | Resource Lock Configuration for Private DNS Zone(s). 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. 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. @@ -71,6 +79,14 @@ 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. + +- 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) @@ -93,6 +109,14 @@ 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. + +- 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) @@ -159,6 +183,14 @@ 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. + +- 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) @@ -175,6 +207,14 @@ 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. + +- 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) @@ -257,6 +297,14 @@ 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. + +- 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) @@ -273,6 +321,14 @@ 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. + +- 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) @@ -311,6 +367,14 @@ 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). + +- 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) @@ -343,6 +407,14 @@ 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. + +- 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) @@ -398,6 +470,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" }, @@ -432,6 +510,12 @@ outHubVirtualNetworkId | string | "parDnsServerIps": { "value": [] }, + "parVirtualNetworkLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, "parPublicIpSku": { "value": "Standard" }, @@ -456,12 +540,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 }, @@ -492,12 +588,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 }, @@ -581,6 +689,12 @@ outHubVirtualNetworkId | string | "parVirtualNetworkIdToLinkFailover": { "value": "" }, + "parPrivateDNSZonesLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, "parVpnGatewayEnabled": { "value": true }, @@ -626,6 +740,12 @@ outHubVirtualNetworkId | string | } } }, + "parVirtualNetworkGatewayLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Hub Networking Module." + } + }, "parTags": { "value": {} }, diff --git a/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep b/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep index 7d0efb12f..014fb2da1 100644 --- a/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep +++ b/infra-as-code/bicep/modules/hubNetworking/hubNetworking.bicep @@ -18,6 +18,17 @@ type subnetOptionsType = ({ 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 @@ -27,6 +38,12 @@ 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.') +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' @@ -61,6 +78,12 @@ param parSubnets subnetOptionsType = [ @sys.description('Array of DNS Server IP addresses for VNet.') param parDnsServerIps array = [] +@sys.description('Resource Lock Configuration for Virtual Network.') +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' @@ -93,12 +116,24 @@ param parAzBastionTunneling bool = false @sys.description('Name for Azure Bastion Subnet NSG.') param parAzBastionNsgName string = 'nsg-AzureBastionSubnet' +@sys.description('Resource Lock Configuration for Bastion.') +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.') +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 @@ -154,12 +189,24 @@ 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.') +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.') +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 @@ -243,6 +290,12 @@ 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).') +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 @@ -289,6 +342,12 @@ param parExpressRouteGatewayConfig object = { } } +@sys.description('Resource Lock Configuration for ExpressRoute Virtual Network Gateway.') +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 = {} @@ -355,6 +414,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 @@ -379,6 +448,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: { @@ -391,6 +470,7 @@ module modBastionPublicIp '../publicIp/publicIp.bicep' = if (parAzBastionEnabled publicIpAddressVersion: 'IPv4' publicIpAllocationMethod: 'Static' } + parResourceLockConfig: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock : parBastionLock parTags: parTags parTelemetryOptOut: parTelemetryOptOut } @@ -550,6 +630,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 @@ -579,6 +669,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' @@ -597,6 +697,7 @@ module modGatewayPublicIp '../publicIp/publicIp.bicep' = [for (gateway, i) in va parPublicIpSku: { name: parPublicIpSku } + parResourceLockConfig: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock : parVirtualNetworkGatewayLock parTags: parTags parTelemetryOptOut: parTelemetryOptOut } @@ -648,6 +749,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' @@ -671,6 +782,7 @@ module modAzureFirewallPublicIp '../publicIp/publicIp.bicep' = if (parAzFirewall parPublicIpSku: { name: parPublicIpSku } + parResourceLockConfig: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock : parAzureFirewallLock parTags: parTags parTelemetryOptOut: parTelemetryOptOut } @@ -689,6 +801,7 @@ module modAzureFirewallMgmtPublicIp '../publicIp/publicIp.bicep' = if (parAzFire parPublicIpSku: { name: 'Standard' } + parResourceLockConfig: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock : parAzureFirewallLock parTags: parTags parTelemetryOptOut: parTelemetryOptOut } @@ -715,6 +828,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) { @@ -781,6 +904,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 @@ -801,6 +934,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) @@ -811,6 +954,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/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.all.json b/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.all.json index 2ce8eb305..3776166ff 100644 --- a/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.all.json +++ b/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.all.json @@ -247,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/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.az.all.json b/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.az.all.json index 5f35c792c..b16730bac 100644 --- a/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.az.all.json +++ b/infra-as-code/bicep/modules/hubNetworking/parameters/hubNetworking.parameters.az.all.json @@ -259,6 +259,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/infra-as-code/bicep/modules/hubNetworking/parameters/mc-hubNetworking.parameters.all.json b/infra-as-code/bicep/modules/hubNetworking/parameters/mc-hubNetworking.parameters.all.json index 9794a1dda..80b17f41e 100644 --- a/infra-as-code/bicep/modules/hubNetworking/parameters/mc-hubNetworking.parameters.all.json +++ b/infra-as-code/bicep/modules/hubNetworking/parameters/mc-hubNetworking.parameters.all.json @@ -208,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/infra-as-code/bicep/modules/logging/generateddocs/logging.bicep.md b/infra-as-code/bicep/modules/logging/generateddocs/logging.bicep.md index aa14497e3..7e4b86940 100644 --- a/infra-as-code/bicep/modules/logging/generateddocs/logging.bicep.md +++ b/infra-as-code/bicep/modules/logging/generateddocs/logging.bicep.md @@ -6,17 +6,21 @@ 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. 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. parLogAnalyticsWorkspaceSolutions | No | Solutions that will be added to the Log Analytics Workspace. +parLogAnalyticsWorkspaceSolutionsLock | No | Resource Lock Configuration for Log Analytics Workspace Solutions. 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. 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. @@ -24,6 +28,14 @@ parUseSentinelClassicPricingTiers | No | Set Parameter to true to use Sent 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. + +- 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) @@ -68,6 +80,14 @@ 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. + +- 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) @@ -78,6 +98,14 @@ 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. + +- 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) @@ -118,6 +146,14 @@ 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. + +- 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) @@ -187,6 +223,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" }, @@ -202,6 +244,12 @@ outAutomationAccountId | string | "parLogAnalyticsWorkspaceLogRetentionInDays": { "value": 365 }, + "parLogAnalyticsWorkspaceLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Logging Module." + } + }, "parLogAnalyticsWorkspaceSolutions": { "value": [ "AgentHealthAssessment", @@ -216,6 +264,12 @@ outAutomationAccountId | string | "VMInsights" ] }, + "parLogAnalyticsWorkspaceSolutionsLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Logging Module." + } + }, "parLogAnalyticsWorkspaceLinkAutomationAccount": { "value": true }, @@ -231,6 +285,12 @@ outAutomationAccountId | string | "parAutomationAccountPublicNetworkAccess": { "value": true }, + "parAutomationAccountLock": { + "value": { + "kind": "None", + "notes": "This lock was created by the ALZ Bicep Logging Module." + } + }, "parTags": { "value": {} }, diff --git a/infra-as-code/bicep/modules/logging/logging.bicep b/infra-as-code/bicep/modules/logging/logging.bicep index 351259f53..92f15e72b 100644 --- a/infra-as-code/bicep/modules/logging/logging.bicep +++ b/infra-as-code/bicep/modules/logging/logging.bicep @@ -1,6 +1,23 @@ 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.') +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 +55,12 @@ 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.') +param parLogAnalyticsWorkspaceLock lockType = { + kind: 'None' + notes: 'This lock was created by the ALZ Bicep Logging Module.' +} + @allowed([ 'AgentHealthAssessment' 'AntiMalware' @@ -65,6 +88,12 @@ param parLogAnalyticsWorkspaceSolutions array = [ 'VMInsights' ] +@sys.description('Resource Lock Configuration for Log Analytics Workspace Solutions.') +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 @@ -80,6 +109,12 @@ param parAutomationAccountUseManagedIdentity bool = true @sys.description('Automation Account - Public network access.') param parAutomationAccountPublicNetworkAccess bool = true +@sys.description('Resource Lock Configuration for Automation Account.') +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 = {} @@ -119,6 +154,16 @@ resource resAutomationAccount 'Microsoft.Automation/automationAccounts@2022-08-0 } } +// 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 + } +} + resource resLogAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' = { name: parLogAnalyticsWorkspaceName location: parLogAnalyticsWorkspaceLocation @@ -132,6 +177,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 @@ -152,6 +207,16 @@ 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: parLogAnalyticsLinkedServiceAutomationAccountName diff --git a/infra-as-code/bicep/modules/logging/parameters/logging.parameters.all.json b/infra-as-code/bicep/modules/logging/parameters/logging.parameters.all.json index 711d6bc9b..73fe7eb16 100644 --- a/infra-as-code/bicep/modules/logging/parameters/logging.parameters.all.json +++ b/infra-as-code/bicep/modules/logging/parameters/logging.parameters.all.json @@ -59,6 +59,30 @@ }, "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/infra-as-code/bicep/modules/logging/parameters/mc-logging.parameters.all.json b/infra-as-code/bicep/modules/logging/parameters/mc-logging.parameters.all.json index 9eb9eee21..360454db1 100644 --- a/infra-as-code/bicep/modules/logging/parameters/mc-logging.parameters.all.json +++ b/infra-as-code/bicep/modules/logging/parameters/mc-logging.parameters.all.json @@ -53,6 +53,30 @@ }, "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/infra-as-code/bicep/modules/privateDnsZoneLinks/generateddocs/privateDnsZoneLinks.bicep.md b/infra-as-code/bicep/modules/privateDnsZoneLinks/generateddocs/privateDnsZoneLinks.bicep.md index d8e1c9999..0cb5f9b79 100644 --- a/infra-as-code/bicep/modules/privateDnsZoneLinks/generateddocs/privateDnsZoneLinks.bicep.md +++ b/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 Object ### parSpokeVirtualNetworkResourceId @@ -19,6 +20,14 @@ 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 Object + +- Default value: `@{kind=None; notes=This lock was created by the ALZ Bicep Private DNS Zone Links Module.}` + ## Snippets ### Parameter file @@ -36,6 +45,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/infra-as-code/bicep/modules/privateDnsZoneLinks/privateDnsZoneLinks.bicep b/infra-as-code/bicep/modules/privateDnsZoneLinks/privateDnsZoneLinks.bicep index b36c5e6fa..617576f25 100644 --- a/infra-as-code/bicep/modules/privateDnsZoneLinks/privateDnsZoneLinks.bicep +++ b/infra-as-code/bicep/modules/privateDnsZoneLinks/privateDnsZoneLinks.bicep @@ -1,11 +1,28 @@ 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 Object') +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 +35,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/infra-as-code/bicep/modules/privateDnsZones/generateddocs/privateDnsZones.bicep.md b/infra-as-code/bicep/modules/privateDnsZones/generateddocs/privateDnsZones.bicep.md index 19094cf95..a5b8973a9 100644 --- a/infra-as-code/bicep/modules/privateDnsZones/generateddocs/privateDnsZones.bicep.md +++ b/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 Object parTelemetryOptOut | No | Set Parameter to true to Opt-out of deployment telemetry. ### parLocation @@ -56,6 +57,14 @@ 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 Object + +- 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 +178,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/infra-as-code/bicep/modules/privateDnsZones/privateDnsZones.bicep b/infra-as-code/bicep/modules/privateDnsZones/privateDnsZones.bicep index 541cb75b5..2b3a25cb2 100644 --- a/infra-as-code/bicep/modules/privateDnsZones/privateDnsZones.bicep +++ b/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,12 @@ param parVirtualNetworkIdToLink string = '' @sys.description('Resource ID of VNet for Failover Private DNS Zone VNet Links.') param parVirtualNetworkIdToLinkFailover string = '' +@sys.description('Resource Lock Configuration Object') +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 @@ -175,6 +192,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' @@ -188,6 +214,15 @@ resource resVirtualNetworkLink 'Microsoft.Network/privateDnsZones/virtualNetwork 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)) { name: '${privateDnsZoneName}/${take('fallbacklink-${uniqueString(parVirtualNetworkIdToLinkFailover)}', 80)}' location: 'global' @@ -201,6 +236,15 @@ resource resVirtualNetworkLinkFailover 'Microsoft.Network/privateDnsZones/virtua 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) { #disable-next-line no-loc-expr-outside-params name: 'pid-${varCuaid}-${uniqueString(resourceGroup().location)}' diff --git a/infra-as-code/bicep/modules/publicIp/generateddocs/publicIp.bicep.md b/infra-as-code/bicep/modules/publicIp/generateddocs/publicIp.bicep.md index 4942e5c7b..4d239ef46 100644 --- a/infra-as-code/bicep/modules/publicIp/generateddocs/publicIp.bicep.md +++ b/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 Object 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,14 @@ 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 Object + +- 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 +76,7 @@ Set Parameter to true to Opt-out of deployment telemetry. Name | Type | Description ---- | ---- | ----------- outPublicIpId | string | +outPublicIpName | string | ## Snippets @@ -95,6 +105,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/infra-as-code/bicep/modules/publicIp/publicIp.bicep b/infra-as-code/bicep/modules/publicIp/publicIp.bicep index 2c4cc2d39..4a3741200 100644 --- a/infra-as-code/bicep/modules/publicIp/publicIp.bicep +++ b/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,12 @@ 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 Object') +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 = {} @@ -39,6 +56,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 +73,4 @@ module modCustomerUsageAttribution '../../CRML/customerUsageAttribution/cuaIdRes } output outPublicIpId string = resPublicIp.id +output outPublicIpName string = resPublicIp.name diff --git a/infra-as-code/bicep/modules/resourceGroup/generateddocs/resourceGroup.bicep.md b/infra-as-code/bicep/modules/resourceGroup/generateddocs/resourceGroup.bicep.md index 5dbeae79b..b7a39fdb7 100644 --- a/infra-as-code/bicep/modules/resourceGroup/generateddocs/resourceGroup.bicep.md +++ b/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 Object 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,14 @@ 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 Object + +- 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 +71,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/infra-as-code/bicep/modules/resourceGroup/generateddocs/resourceGroupLock.bicep.md b/infra-as-code/bicep/modules/resourceGroup/generateddocs/resourceGroupLock.bicep.md new file mode 100644 index 000000000..5dbda9713 --- /dev/null +++ b/infra-as-code/bicep/modules/resourceGroup/generateddocs/resourceGroupLock.bicep.md @@ -0,0 +1,49 @@ +# 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 Object +parResourceGroupName | Yes | Resource Group Name + +### parResourceLockConfig + +![Parameter Setting](https://img.shields.io/badge/parameter-optional-green?style=flat-square) + +Resource Lock Configuration Object + +- 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/infra-as-code/bicep/modules/resourceGroup/parameters/resourceGroup.parameters.all.json b/infra-as-code/bicep/modules/resourceGroup/parameters/resourceGroup.parameters.all.json index 6dcf98ff6..06c521245 100644 --- a/infra-as-code/bicep/modules/resourceGroup/parameters/resourceGroup.parameters.all.json +++ b/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/infra-as-code/bicep/modules/resourceGroup/resourceGroup.bicep b/infra-as-code/bicep/modules/resourceGroup/resourceGroup.bicep index a383c46b7..6ddd506ab 100644 --- a/infra-as-code/bicep/modules/resourceGroup/resourceGroup.bicep +++ b/infra-as-code/bicep/modules/resourceGroup/resourceGroup.bicep @@ -3,12 +3,29 @@ 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 Object') +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 +41,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/infra-as-code/bicep/modules/resourceGroup/resourceGroupLock.bicep b/infra-as-code/bicep/modules/resourceGroup/resourceGroupLock.bicep new file mode 100644 index 000000000..7d649d6ec --- /dev/null +++ b/infra-as-code/bicep/modules/resourceGroup/resourceGroupLock.bicep @@ -0,0 +1,31 @@ +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 Object') +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/infra-as-code/bicep/modules/spokeNetworking/generateddocs/spokeNetworking.bicep.md b/infra-as-code/bicep/modules/spokeNetworking/generateddocs/spokeNetworking.bicep.md index fa92ea911..df43b0017 100644 --- a/infra-as-code/bicep/modules/spokeNetworking/generateddocs/spokeNetworking.bicep.md +++ b/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. 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. 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. 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,14 @@ 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. + +- 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 +66,14 @@ 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. + +- 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 +94,14 @@ 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. + +- 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 +144,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 +171,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/infra-as-code/bicep/modules/spokeNetworking/parameters/spokeNetworking.parameters.all.json b/infra-as-code/bicep/modules/spokeNetworking/parameters/spokeNetworking.parameters.all.json index 112b11a08..84490f1b3 100644 --- a/infra-as-code/bicep/modules/spokeNetworking/parameters/spokeNetworking.parameters.all.json +++ b/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/infra-as-code/bicep/modules/spokeNetworking/spokeNetworking.bicep b/infra-as-code/bicep/modules/spokeNetworking/spokeNetworking.bicep index 67946db5f..a23267d61 100644 --- a/infra-as-code/bicep/modules/spokeNetworking/spokeNetworking.bicep +++ b/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,24 @@ 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.') +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.') +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 +48,12 @@ 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.') +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 +85,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 +114,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/infra-as-code/bicep/modules/vwanConnectivity/generateddocs/vwanConnectivity.bicep.md b/infra-as-code/bicep/modules/vwanConnectivity/generateddocs/vwanConnectivity.bicep.md index 43ca83794..b36b5633e 100644 --- a/infra-as-code/bicep/modules/vwanConnectivity/generateddocs/vwanConnectivity.bicep.md +++ b/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. parAzFirewallTier | No | Azure Firewall Tier associated with the Firewall to deploy. 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. parVirtualWanName | No | Prefix Used for Virtual WAN. +parVirtualWanLock | No | Resource Lock Configuration for Virtual WAN. 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`. +parVpnGatewayLock | No | Resource Lock Configuration for Virtual WAN Hub VPN Gateway. +parExpressRouteGatewayLock | No | Resource Lock Configuration for Virtual WAN Hub ExpressRoute Gateway. +parVirtualWanHubsLock | No | Resource Lock Configuration for Virtual WAN Hub. 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. 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. 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). 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,14 @@ 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. + +- 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) @@ -100,6 +116,14 @@ 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. + +- 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,6 +149,30 @@ 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. + +- 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. + +- 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. + +- 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) @@ -165,6 +213,14 @@ 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. + +- 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 +253,14 @@ 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. + +- 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 +305,14 @@ 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). + +- 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 +358,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 +382,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 +405,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 +438,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 +456,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 +548,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/infra-as-code/bicep/modules/vwanConnectivity/parameters/mc-vwanConnectivity.parameters.all.json b/infra-as-code/bicep/modules/vwanConnectivity/parameters/mc-vwanConnectivity.parameters.all.json index d61076fee..0693e34bd 100644 --- a/infra-as-code/bicep/modules/vwanConnectivity/parameters/mc-vwanConnectivity.parameters.all.json +++ b/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/infra-as-code/bicep/modules/vwanConnectivity/parameters/vwanConnectivity.parameters.all.json b/infra-as-code/bicep/modules/vwanConnectivity/parameters/vwanConnectivity.parameters.all.json index 34c82616c..a35264e0d 100644 --- a/infra-as-code/bicep/modules/vwanConnectivity/parameters/vwanConnectivity.parameters.all.json +++ b/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/infra-as-code/bicep/modules/vwanConnectivity/vwanConnectivity.bicep b/infra-as-code/bicep/modules/vwanConnectivity/vwanConnectivity.bicep index 63168a00b..152246759 100644 --- a/infra-as-code/bicep/modules/vwanConnectivity/vwanConnectivity.bicep +++ b/infra-as-code/bicep/modules/vwanConnectivity/vwanConnectivity.bicep @@ -41,12 +41,29 @@ type virtualWanOptionsType = ({ 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.') +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' @@ -75,6 +92,12 @@ param parAzFirewallDnsServers array = [] @sys.description('Prefix Used for Virtual WAN.') param parVirtualWanName string = '${parCompanyPrefix}-vwan-${parLocation}' +@sys.description('Resource Lock Configuration for Virtual WAN.') +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' @@ -102,6 +125,24 @@ param parVirtualWanHubs virtualWanOptionsType = [ { } ] +@sys.description('Resource Lock Configuration for Virtual WAN Hub VPN Gateway.') +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.') +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.') +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' @@ -122,6 +163,12 @@ param parAzFirewallAvailabilityZones array = [] @sys.description('Azure Firewall Policies Name.') param parAzFirewallPoliciesName string = '${parCompanyPrefix}-azfwpolicy-${parLocation}' +@sys.description('Resource Lock Configuration for Azure Firewall.') +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 @@ -134,6 +181,12 @@ param parDdosEnabled bool = true @sys.description('DDoS Plan Name.') param parDdosPlanName string = '${parCompanyPrefix}-ddos-plan' +@sys.description('Resource Lock Configuration for DDoS Plan.') +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 @@ -220,6 +273,12 @@ 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).') +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 = {} @@ -249,6 +308,16 @@ 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: hub.?parVirtualWanHubCustomName ?? '${parVirtualWanHubName}-${hub.parHubLocation}' location: hub.parHubLocation @@ -266,6 +335,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' @@ -319,6 +398,16 @@ 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: hub.?parExpressRouteGatewayCustomName ?? '${parExpressRouteGatewayName}-${hub.parHubLocation}' @@ -336,6 +425,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 @@ -357,6 +456,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 ((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: hub.?parAzFirewallCustomName ?? '${parAzFirewallName}-${hub.parHubLocation}' location: hub.parHubLocation @@ -381,6 +490,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 @@ -388,6 +507,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' @@ -399,6 +528,7 @@ module modPrivateDnsZones '../privateDnsZones/privateDnsZones.bicep' = if (parPr parPrivateDnsZoneAutoMergeAzureBackupZone: parPrivateDnsZoneAutoMergeAzureBackupZone parVirtualNetworkIdToLink: parVirtualNetworkIdToLink parVirtualNetworkIdToLinkFailover: parVirtualNetworkIdToLinkFailover + parResourceLockConfig: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock : parPrivateDNSZonesLock } } diff --git a/infra-as-code/bicep/orchestration/hubPeeredSpoke/generateddocs/hubPeeredSpoke.bicep.md b/infra-as-code/bicep/orchestration/hubPeeredSpoke/generateddocs/hubPeeredSpoke.bicep.md index cde35c4fc..dfb09f85f 100644 --- a/infra-as-code/bicep/orchestration/hubPeeredSpoke/generateddocs/hubPeeredSpoke.bicep.md +++ b/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. 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. +parSpokeRouteTableLock | No | Resource Lock Configuration for Spoke Network Route Table. +parPrivateDnsZoneVirtualNetworkLinkLock | No | Resource Lock Configuration for Private DNS Virtual Network Network Links. 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,14 @@ 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. + +- 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 +98,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 +162,30 @@ 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. + +- 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. + +- 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. + +- 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 +267,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 +309,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/infra-as-code/bicep/orchestration/hubPeeredSpoke/hubPeeredSpoke.bicep b/infra-as-code/bicep/orchestration/hubPeeredSpoke/hubPeeredSpoke.bicep index e59e337d3..6745b2508 100644 --- a/infra-as-code/bicep/orchestration/hubPeeredSpoke/hubPeeredSpoke.bicep +++ b/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,12 @@ 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.') +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 +51,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 +82,25 @@ 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.') +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.') +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.') +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 +188,7 @@ module modResourceGroup '../../modules/resourceGroup/resourceGroup.bicep' = { parResourceGroupName: parResourceGroupNameForSpokeNetworking parTags: parTags parTelemetryOptOut: parTelemetryOptOut + parResourceLockConfig: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock : parResourceGroupLock } } @@ -167,6 +210,9 @@ module modSpokeNetworking '../../modules/spokeNetworking/spokeNetworking.bicep' parTags: parTags parTelemetryOptOut: parTelemetryOptOut parLocation: parLocation + parGlobalResourceLock: parGlobalResourceLock + parSpokeNetworkLock: parSpokeNetworkLock + parSpokeRouteTableLock: parSpokeRouteTableLock } } @@ -177,6 +223,7 @@ module modPrivateDnsZoneLinkToSpoke '../../modules/privateDnsZoneLinks/privateDn params: { parPrivateDnsZoneResourceId: zone parSpokeVirtualNetworkResourceId: modSpokeNetworking.outputs.outSpokeVirtualNetworkId + parResourceLockConfig: (parGlobalResourceLock.kind != 'None') ? parGlobalResourceLock : parPrivateDnsZoneVirtualNetworkLinkLock } }] diff --git a/infra-as-code/bicep/orchestration/hubPeeredSpoke/parameters/hubPeeredSpoke.parameters.all.json b/infra-as-code/bicep/orchestration/hubPeeredSpoke/parameters/hubPeeredSpoke.parameters.all.json index 65328cd32..6e7acd3f4 100644 --- a/infra-as-code/bicep/orchestration/hubPeeredSpoke/parameters/hubPeeredSpoke.parameters.all.json +++ b/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/infra-as-code/bicep/orchestration/hubPeeredSpoke/parameters/hubPeeredSpoke.vwan.parameters.all.json b/infra-as-code/bicep/orchestration/hubPeeredSpoke/parameters/hubPeeredSpoke.vwan.parameters.all.json index 0b147eba3..8a3ccd8d7 100644 --- a/infra-as-code/bicep/orchestration/hubPeeredSpoke/parameters/hubPeeredSpoke.vwan.parameters.all.json +++ b/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." + } } } }