diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 26d7a976d6..b0279a864d 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -108,7 +108,7 @@ /avm/res/network/trafficmanagerprofile/ @Azure/avm-res-network-trafficmanagerprofile-module-owners-bicep @Azure/avm-core-team-technical-bicep #/avm/res/network/virtual-hub/ @Azure/avm-res-network-virtualhub-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/network/virtual-network/ @Azure/avm-res-network-virtualnetwork-module-owners-bicep @Azure/avm-core-team-technical-bicep -#/avm/res/network/virtual-network-gateway/ @Azure/avm-res-network-virtualnetworkgateway-module-owners-bicep @Azure/avm-core-team-technical-bicep +/avm/res/network/virtual-network-gateway/ @Azure/avm-res-network-virtualnetworkgateway-module-owners-bicep @Azure/avm-core-team-technical-bicep #/avm/res/network/virtual-wan/ @Azure/avm-res-network-virtualwan-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/network/vpn-gateway/ @Azure/avm-res-network-vpngateway-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/network/vpn-site/ @Azure/avm-res-network-vpnsite-module-owners-bicep @Azure/avm-core-team-technical-bicep diff --git a/.github/workflows/avm.res.network.virtual-network-gateway.yml b/.github/workflows/avm.res.network.virtual-network-gateway.yml new file mode 100644 index 0000000000..6090d0ccce --- /dev/null +++ b/.github/workflows/avm.res.network.virtual-network-gateway.yml @@ -0,0 +1,83 @@ +name: "avm.res.network.virtual-network-gateway" + +on: + schedule: + - cron: "0 12 1/15 * *" # Bi-Weekly Test (on 1st & 15th of month) + workflow_dispatch: + inputs: + staticValidation: + type: boolean + description: "Execute static validation" + required: false + default: true + deploymentValidation: + type: boolean + description: "Execute deployment validation" + required: false + default: true + removeDeployment: + type: boolean + description: "Remove deployed module" + required: false + default: true + + push: + branches: + - main + paths: + - ".github/actions/templates/avm-**" + - ".github/workflows/avm.template.module.yml" + - ".github/workflows/avm.res.network.virtual-network-gateway.yml" + - "avm/res/network/virtual-network-gateway/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/network/virtual-network-gateway" + workflowPath: ".github/workflows/avm.res.network.virtual-network-gateway.yml" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-latest + name: "Initialize pipeline" + steps: + - name: "Checkout" + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: "Set input parameters to output variables" + id: get-workflow-param + uses: ./.github/actions/templates/avm-getWorkflowInput + with: + workflowPath: "${{ env.workflowPath}}" + - name: "Get module test file paths" + id: get-module-test-file-paths + uses: ./.github/actions/templates/avm-getModuleTestFiles + with: + modulePath: "${{ env.modulePath }}" + outputs: + workflowInput: ${{ steps.get-workflow-param.outputs.workflowInput }} + moduleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.moduleTestFilePaths }} + psRuleModuleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.psRuleModuleTestFilePaths }} + modulePath: "${{ env.modulePath }}" + + ############################## + # Call reusable workflow # + ############################## + call-workflow-passing-data: + name: "Run" + needs: + - job_initialize_pipeline + uses: ./.github/workflows/avm.template.module.yml + with: + workflowInput: "${{ needs.job_initialize_pipeline.outputs.workflowInput }}" + moduleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.moduleTestFilePaths }}" + psRuleModuleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.psRuleModuleTestFilePaths }}" + modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" + secrets: inherit diff --git a/avm/res/network/virtual-network-gateway/README.md b/avm/res/network/virtual-network-gateway/README.md new file mode 100644 index 0000000000..91b7147342 --- /dev/null +++ b/avm/res/network/virtual-network-gateway/README.md @@ -0,0 +1,1569 @@ +# Virtual Network Gateways `[Microsoft.Network/virtualNetworkGateways]` + +This module deploys a Virtual Network Gateway. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Usage examples](#Usage-examples) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | [2020-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-05-01/locks) | +| `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | +| `Microsoft.Insights/diagnosticSettings` | [2021-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) | +| `Microsoft.Network/publicIPAddresses` | [2023-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-04-01/publicIPAddresses) | +| `Microsoft.Network/virtualNetworkGateways` | [2023-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-04-01/virtualNetworkGateways) | +| `Microsoft.Network/virtualNetworkGateways/natRules` | [2023-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-04-01/virtualNetworkGateways/natRules) | + +## Usage examples + +The following section provides usage examples for the module, which were used to validate and deploy the module successfully. For a full reference, please review the module's test folder in its repository. + +>**Note**: Each example lists all the required parameters first, followed by the rest - each in alphabetical order. + +>**Note**: To reference the module, please use the following syntax `br/public:avm/res/network/virtual-network-gateway:`. + +- [AAD-VPN](#example-1-aad-vpn) +- [Using only defaults](#example-2-using-only-defaults) +- [ExpressRoute](#example-3-expressroute) +- [Using large parameter set](#example-4-using-large-parameter-set) +- [VPN](#example-5-vpn) +- [WAF-aligned](#example-6-waf-aligned) + +### Example 1: _AAD-VPN_ + +This instance deploys the module with the AAD set of required parameters. + + +
+ +via Bicep module + +```bicep +module virtualNetworkGateway 'br/public:avm/res/network/virtual-network-gateway:' = { + name: '${uniqueString(deployment().name, location)}-test-nvngavpn' + params: { + // Required parameters + gatewayType: 'Vpn' + name: 'nvngavpn001' + skuName: 'VpnGw2AZ' + vNetResourceId: '' + // Non-required parameters + activeActive: false + domainNameLabel: [ + 'dm-nvngavpn' + ] + location: '' + publicIpZones: [ + '1' + '2' + '3' + ] + vpnClientAadConfiguration: { + aadAudience: '41b23e61-6c1e-4545-b367-cd054e0ed4b4' + aadIssuer: '' + aadTenant: '' + vpnAuthenticationTypes: [ + 'AAD' + ] + vpnClientProtocols: [ + 'OpenVPN' + ] + } + vpnType: 'RouteBased' + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "gatewayType": { + "value": "Vpn" + }, + "name": { + "value": "nvngavpn001" + }, + "skuName": { + "value": "VpnGw2AZ" + }, + "vNetResourceId": { + "value": "" + }, + // Non-required parameters + "activeActive": { + "value": false + }, + "domainNameLabel": { + "value": [ + "dm-nvngavpn" + ] + }, + "location": { + "value": "" + }, + "publicIpZones": { + "value": [ + "1", + "2", + "3" + ] + }, + "vpnClientAadConfiguration": { + "value": { + "aadAudience": "41b23e61-6c1e-4545-b367-cd054e0ed4b4", + "aadIssuer": "", + "aadTenant": "", + "vpnAuthenticationTypes": [ + "AAD" + ], + "vpnClientProtocols": [ + "OpenVPN" + ] + } + }, + "vpnType": { + "value": "RouteBased" + } + } +} +``` + +
+

+ +### Example 2: _Using only defaults_ + +This instance deploys the module with the minimum set of required parameters. + + +

+ +via Bicep module + +```bicep +module virtualNetworkGateway 'br/public:avm/res/network/virtual-network-gateway:' = { + name: '${uniqueString(deployment().name, location)}-test-nvgmin' + params: { + // Required parameters + gatewayType: 'Vpn' + name: 'nvgmin001' + skuName: 'VpnGw2AZ' + vNetResourceId: '' + // Non-required parameters + location: '' + publicIpZones: [ + '1' + '2' + '3' + ] + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "gatewayType": { + "value": "Vpn" + }, + "name": { + "value": "nvgmin001" + }, + "skuName": { + "value": "VpnGw2AZ" + }, + "vNetResourceId": { + "value": "" + }, + // Non-required parameters + "location": { + "value": "" + }, + "publicIpZones": { + "value": [ + "1", + "2", + "3" + ] + } + } +} +``` + +
+

+ +### Example 3: _ExpressRoute_ + +This instance deploys the module with the ExpressRoute set of required parameters. + + +

+ +via Bicep module + +```bicep +module virtualNetworkGateway 'br/public:avm/res/network/virtual-network-gateway:' = { + name: '${uniqueString(deployment().name, location)}-test-nvger' + params: { + // Required parameters + gatewayType: 'ExpressRoute' + name: 'nvger001' + skuName: 'ErGw1AZ' + vNetResourceId: '' + // Non-required parameters + domainNameLabel: [ + 'dm-nvger' + ] + gatewayPipName: 'pip-nvger' + location: '' + publicIpZones: [ + '1' + '2' + '3' + ] + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "gatewayType": { + "value": "ExpressRoute" + }, + "name": { + "value": "nvger001" + }, + "skuName": { + "value": "ErGw1AZ" + }, + "vNetResourceId": { + "value": "" + }, + // Non-required parameters + "domainNameLabel": { + "value": [ + "dm-nvger" + ] + }, + "gatewayPipName": { + "value": "pip-nvger" + }, + "location": { + "value": "" + }, + "publicIpZones": { + "value": [ + "1", + "2", + "3" + ] + } + } +} +``` + +
+

+ +### Example 4: _Using large parameter set_ + +This instance deploys the module with most of its features enabled. + + +

+ +via Bicep module + +```bicep +module virtualNetworkGateway 'br/public:avm/res/network/virtual-network-gateway:' = { + name: '${uniqueString(deployment().name, location)}-test-nvgmax' + params: { + // Required parameters + gatewayType: 'Vpn' + name: 'nvgmax001' + skuName: 'VpnGw2AZ' + vNetResourceId: '' + // Non-required parameters + activeActive: true + allowRemoteVnetTraffic: true + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + name: 'customSetting' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + disableIPSecReplayProtection: true + domainNameLabel: [ + 'dm-nvgmax' + ] + enableBgpRouteTranslationForNat: true + enablePrivateIpAddress: true + gatewayDefaultSiteLocalNetworkGatewayId: '' + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + natRules: [ + { + externalMappings: [ + { + addressSpace: '192.168.0.0/24' + portRange: '100' + } + ] + internalMappings: [ + { + addressSpace: '10.100.0.0/24' + portRange: '100' + } + ] + mode: 'IngressSnat' + name: 'nat-rule-1-static-IngressSnat' + type: 'Static' + } + { + externalMappings: [ + { + addressSpace: '10.200.0.0/26' + } + ] + internalMappings: [ + { + addressSpace: '172.16.0.0/26' + } + ] + mode: 'EgressSnat' + name: 'nat-rule-2-dynamic-EgressSnat' + type: 'Dynamic' + } + ] + publicIpZones: [ + '1' + '2' + '3' + ] + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + vpnGatewayGeneration: 'Generation2' + vpnType: 'RouteBased' + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "gatewayType": { + "value": "Vpn" + }, + "name": { + "value": "nvgmax001" + }, + "skuName": { + "value": "VpnGw2AZ" + }, + "vNetResourceId": { + "value": "" + }, + // Non-required parameters + "activeActive": { + "value": true + }, + "allowRemoteVnetTraffic": { + "value": true + }, + "diagnosticSettings": { + "value": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "metricCategories": [ + { + "category": "AllMetrics" + } + ], + "name": "customSetting", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ] + }, + "disableIPSecReplayProtection": { + "value": true + }, + "domainNameLabel": { + "value": [ + "dm-nvgmax" + ] + }, + "enableBgpRouteTranslationForNat": { + "value": true + }, + "enablePrivateIpAddress": { + "value": true + }, + "gatewayDefaultSiteLocalNetworkGatewayId": { + "value": "" + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "natRules": { + "value": [ + { + "externalMappings": [ + { + "addressSpace": "192.168.0.0/24", + "portRange": "100" + } + ], + "internalMappings": [ + { + "addressSpace": "10.100.0.0/24", + "portRange": "100" + } + ], + "mode": "IngressSnat", + "name": "nat-rule-1-static-IngressSnat", + "type": "Static" + }, + { + "externalMappings": [ + { + "addressSpace": "10.200.0.0/26" + } + ], + "internalMappings": [ + { + "addressSpace": "172.16.0.0/26" + } + ], + "mode": "EgressSnat", + "name": "nat-rule-2-dynamic-EgressSnat", + "type": "Dynamic" + } + ] + }, + "publicIpZones": { + "value": [ + "1", + "2", + "3" + ] + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + }, + "vpnGatewayGeneration": { + "value": "Generation2" + }, + "vpnType": { + "value": "RouteBased" + } + } +} +``` + +
+

+ +### Example 5: _VPN_ + +This instance deploys the module with the VPN set of required parameters. + + +

+ +via Bicep module + +```bicep +module virtualNetworkGateway 'br/public:avm/res/network/virtual-network-gateway:' = { + name: '${uniqueString(deployment().name, location)}-test-nvgvpn' + params: { + // Required parameters + gatewayType: 'Vpn' + name: 'nvgvpn001' + skuName: 'VpnGw2AZ' + vNetResourceId: '' + // Non-required parameters + activeActive: true + allowRemoteVnetTraffic: true + disableIPSecReplayProtection: true + domainNameLabel: [ + 'dm-nvgvpn' + ] + enableBgpRouteTranslationForNat: true + enablePrivateIpAddress: true + gatewayDefaultSiteLocalNetworkGatewayId: '' + location: '' + publicIpZones: [ + '1' + '2' + '3' + ] + vpnGatewayGeneration: 'Generation2' + vpnType: 'RouteBased' + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "gatewayType": { + "value": "Vpn" + }, + "name": { + "value": "nvgvpn001" + }, + "skuName": { + "value": "VpnGw2AZ" + }, + "vNetResourceId": { + "value": "" + }, + // Non-required parameters + "activeActive": { + "value": true + }, + "allowRemoteVnetTraffic": { + "value": true + }, + "disableIPSecReplayProtection": { + "value": true + }, + "domainNameLabel": { + "value": [ + "dm-nvgvpn" + ] + }, + "enableBgpRouteTranslationForNat": { + "value": true + }, + "enablePrivateIpAddress": { + "value": true + }, + "gatewayDefaultSiteLocalNetworkGatewayId": { + "value": "" + }, + "location": { + "value": "" + }, + "publicIpZones": { + "value": [ + "1", + "2", + "3" + ] + }, + "vpnGatewayGeneration": { + "value": "Generation2" + }, + "vpnType": { + "value": "RouteBased" + } + } +} +``` + +
+

+ +### Example 6: _WAF-aligned_ + +This instance deploys the module in alignment with the best-practices of the Azure Well-Architected Framework. + + +

+ +via Bicep module + +```bicep +module virtualNetworkGateway 'br/public:avm/res/network/virtual-network-gateway:' = { + name: '${uniqueString(deployment().name, location)}-test-nvgmwaf' + params: { + // Required parameters + gatewayType: 'Vpn' + name: 'nvgmwaf001' + skuName: 'VpnGw2AZ' + vNetResourceId: '' + // Non-required parameters + activeActive: true + allowRemoteVnetTraffic: true + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + name: 'customSetting' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + disableIPSecReplayProtection: true + domainNameLabel: [ + 'dm-nvgmwaf' + ] + enableBgpRouteTranslationForNat: true + enablePrivateIpAddress: true + gatewayDefaultSiteLocalNetworkGatewayId: '' + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + natRules: [ + { + externalMappings: [ + { + addressSpace: '192.168.0.0/24' + portRange: '100' + } + ] + internalMappings: [ + { + addressSpace: '10.100.0.0/24' + portRange: '100' + } + ] + mode: 'IngressSnat' + name: 'nat-rule-1-static-IngressSnat' + type: 'Static' + } + { + externalMappings: [ + { + addressSpace: '10.200.0.0/26' + } + ] + internalMappings: [ + { + addressSpace: '172.16.0.0/26' + } + ] + mode: 'EgressSnat' + name: 'nat-rule-2-dynamic-EgressSnat' + type: 'Dynamic' + } + ] + publicIpZones: [ + '1' + '2' + '3' + ] + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + vpnGatewayGeneration: 'Generation2' + vpnType: 'RouteBased' + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "gatewayType": { + "value": "Vpn" + }, + "name": { + "value": "nvgmwaf001" + }, + "skuName": { + "value": "VpnGw2AZ" + }, + "vNetResourceId": { + "value": "" + }, + // Non-required parameters + "activeActive": { + "value": true + }, + "allowRemoteVnetTraffic": { + "value": true + }, + "diagnosticSettings": { + "value": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "metricCategories": [ + { + "category": "AllMetrics" + } + ], + "name": "customSetting", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ] + }, + "disableIPSecReplayProtection": { + "value": true + }, + "domainNameLabel": { + "value": [ + "dm-nvgmwaf" + ] + }, + "enableBgpRouteTranslationForNat": { + "value": true + }, + "enablePrivateIpAddress": { + "value": true + }, + "gatewayDefaultSiteLocalNetworkGatewayId": { + "value": "" + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "natRules": { + "value": [ + { + "externalMappings": [ + { + "addressSpace": "192.168.0.0/24", + "portRange": "100" + } + ], + "internalMappings": [ + { + "addressSpace": "10.100.0.0/24", + "portRange": "100" + } + ], + "mode": "IngressSnat", + "name": "nat-rule-1-static-IngressSnat", + "type": "Static" + }, + { + "externalMappings": [ + { + "addressSpace": "10.200.0.0/26" + } + ], + "internalMappings": [ + { + "addressSpace": "172.16.0.0/26" + } + ], + "mode": "EgressSnat", + "name": "nat-rule-2-dynamic-EgressSnat", + "type": "Dynamic" + } + ] + }, + "publicIpZones": { + "value": [ + "1", + "2", + "3" + ] + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + }, + "vpnGatewayGeneration": { + "value": "Generation2" + }, + "vpnType": { + "value": "RouteBased" + } + } +} +``` + +
+

+ + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`gatewayType`](#parameter-gatewaytype) | string | Specifies the gateway type. E.g. VPN, ExpressRoute. | +| [`name`](#parameter-name) | string | Specifies the Virtual Network Gateway name. | +| [`skuName`](#parameter-skuname) | string | The SKU of the Gateway. | +| [`vNetResourceId`](#parameter-vnetresourceid) | string | Virtual Network resource ID. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`activeActive`](#parameter-activeactive) | bool | Value to specify if the Gateway should be deployed in active-active or active-passive configuration. | +| [`activeGatewayPipName`](#parameter-activegatewaypipname) | string | Specifies the name of the Public IP used by the Virtual Network Gateway when active-active configuration is required. If it's not provided, a '-pip' suffix will be appended to the gateway's name. | +| [`allowRemoteVnetTraffic`](#parameter-allowremotevnettraffic) | bool | Configure this gateway to accept traffic from other Azure Virtual Networks. This configuration does not support connectivity to Azure Virtual WAN. | +| [`allowVirtualWanTraffic`](#parameter-allowvirtualwantraffic) | bool | Configures this gateway to accept traffic from remote Virtual WAN networks. | +| [`asn`](#parameter-asn) | int | ASN value. | +| [`clientRevokedCertThumbprint`](#parameter-clientrevokedcertthumbprint) | string | Thumbprint of the revoked certificate. This would revoke VPN client certificates matching this thumbprint from connecting to the VNet. | +| [`clientRootCertData`](#parameter-clientrootcertdata) | string | Client root certificate data used to authenticate VPN clients. Cannot be configured if vpnClientAadConfiguration is provided. | +| [`diagnosticSettings`](#parameter-diagnosticsettings) | array | The diagnostic settings of the service. | +| [`disableIPSecReplayProtection`](#parameter-disableipsecreplayprotection) | bool | disableIPSecReplayProtection flag. Used for VPN Gateways. | +| [`domainNameLabel`](#parameter-domainnamelabel) | array | DNS name(s) of the Public IP resource(s). If you enabled active-active configuration, you need to provide 2 DNS names, if you want to use this feature. A region specific suffix will be appended to it, e.g.: your-DNS-name.westeurope.cloudapp.azure.com. | +| [`enableBgp`](#parameter-enablebgp) | bool | Value to specify if BGP is enabled or not. | +| [`enableBgpRouteTranslationForNat`](#parameter-enablebgproutetranslationfornat) | bool | EnableBgpRouteTranslationForNat flag. Can only be used when "natRules" are enabled on the Virtual Network Gateway. | +| [`enableDnsForwarding`](#parameter-enablednsforwarding) | bool | Whether DNS forwarding is enabled or not and is only supported for Express Route Gateways. The DNS forwarding feature flag must be enabled on the current subscription. | +| [`enablePrivateIpAddress`](#parameter-enableprivateipaddress) | bool | Whether private IP needs to be enabled on this gateway for connections or not. Used for configuring a Site-to-Site VPN connection over ExpressRoute private peering. | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | +| [`gatewayDefaultSiteLocalNetworkGatewayId`](#parameter-gatewaydefaultsitelocalnetworkgatewayid) | string | The reference to the LocalNetworkGateway resource which represents local network site having default routes. Assign Null value in case of removing existing default site setting. | +| [`gatewayPipName`](#parameter-gatewaypipname) | string | Specifies the name of the Public IP used by the Virtual Network Gateway. If it's not provided, a '-pip' suffix will be appended to the gateway's name. | +| [`location`](#parameter-location) | string | Location for all resources. | +| [`lock`](#parameter-lock) | object | The lock settings of the service. | +| [`natRules`](#parameter-natrules) | array | NatRules for virtual network gateway. NAT is supported on the the following SKUs: VpnGw2~5, VpnGw2AZ~5AZ and is supported for IPsec/IKE cross-premises connections only. | +| [`publicIpDiagnosticSettings`](#parameter-publicipdiagnosticsettings) | array | The diagnostic settings of the Public IP. | +| [`publicIPPrefixResourceId`](#parameter-publicipprefixresourceid) | string | Resource ID of the Public IP Prefix object. This is only needed if you want your Public IPs created in a PIP Prefix. | +| [`publicIpZones`](#parameter-publicipzones) | array | Specifies the zones of the Public IP address. Basic IP SKU does not support Availability Zones. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | +| [`tags`](#parameter-tags) | object | Tags of the resource. | +| [`vpnClientAadConfiguration`](#parameter-vpnclientaadconfiguration) | object | Configuration for AAD Authentication for P2S Tunnel Type, Cannot be configured if clientRootCertData is provided. | +| [`vpnClientAddressPoolPrefix`](#parameter-vpnclientaddresspoolprefix) | string | The IP address range from which VPN clients will receive an IP address when connected. Range specified must not overlap with on-premise network. | +| [`vpnGatewayGeneration`](#parameter-vpngatewaygeneration) | string | The generation for this VirtualNetworkGateway. Must be None if virtualNetworkGatewayType is not VPN. | +| [`vpnType`](#parameter-vpntype) | string | Specifies the VPN type. | + +### Parameter: `gatewayType` + +Specifies the gateway type. E.g. VPN, ExpressRoute. + +- Required: Yes +- Type: string +- Allowed: + ```Bicep + [ + 'ExpressRoute' + 'Vpn' + ] + ``` + +### Parameter: `name` + +Specifies the Virtual Network Gateway name. + +- Required: Yes +- Type: string + +### Parameter: `skuName` + +The SKU of the Gateway. + +- Required: Yes +- Type: string +- Allowed: + ```Bicep + [ + 'Basic' + 'ErGw1AZ' + 'ErGw2AZ' + 'ErGw3AZ' + 'HighPerformance' + 'Standard' + 'UltraPerformance' + 'VpnGw1' + 'VpnGw1AZ' + 'VpnGw2' + 'VpnGw2AZ' + 'VpnGw3' + 'VpnGw3AZ' + 'VpnGw4' + 'VpnGw4AZ' + 'VpnGw5' + 'VpnGw5AZ' + ] + ``` + +### Parameter: `vNetResourceId` + +Virtual Network resource ID. + +- Required: Yes +- Type: string + +### Parameter: `activeActive` + +Value to specify if the Gateway should be deployed in active-active or active-passive configuration. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `activeGatewayPipName` + +Specifies the name of the Public IP used by the Virtual Network Gateway when active-active configuration is required. If it's not provided, a '-pip' suffix will be appended to the gateway's name. + +- Required: No +- Type: string +- Default: `[format('{0}-pip2', parameters('name'))]` + +### Parameter: `allowRemoteVnetTraffic` + +Configure this gateway to accept traffic from other Azure Virtual Networks. This configuration does not support connectivity to Azure Virtual WAN. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `allowVirtualWanTraffic` + +Configures this gateway to accept traffic from remote Virtual WAN networks. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `asn` + +ASN value. + +- Required: No +- Type: int +- Default: `65815` + +### Parameter: `clientRevokedCertThumbprint` + +Thumbprint of the revoked certificate. This would revoke VPN client certificates matching this thumbprint from connecting to the VNet. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `clientRootCertData` + +Client root certificate data used to authenticate VPN clients. Cannot be configured if vpnClientAadConfiguration is provided. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `diagnosticSettings` + +The diagnostic settings of the service. + +- Required: No +- Type: array + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`eventHubAuthorizationRuleResourceId`](#parameter-diagnosticsettingseventhubauthorizationruleresourceid) | string | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| [`eventHubName`](#parameter-diagnosticsettingseventhubname) | string | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub. | +| [`logAnalyticsDestinationType`](#parameter-diagnosticsettingsloganalyticsdestinationtype) | string | A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type. | +| [`logCategoriesAndGroups`](#parameter-diagnosticsettingslogcategoriesandgroups) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to '' to disable log collection. | +| [`marketplacePartnerResourceId`](#parameter-diagnosticsettingsmarketplacepartnerresourceid) | string | The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs. | +| [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | array | The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to '' to disable metric collection. | +| [`name`](#parameter-diagnosticsettingsname) | string | The name of diagnostic setting. | +| [`storageAccountResourceId`](#parameter-diagnosticsettingsstorageaccountresourceid) | string | Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub. | +| [`workspaceResourceId`](#parameter-diagnosticsettingsworkspaceresourceid) | string | Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub. | + +### Parameter: `diagnosticSettings.eventHubAuthorizationRuleResourceId` + +Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. + +- Required: No +- Type: string + +### Parameter: `diagnosticSettings.eventHubName` + +Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub. + +- Required: No +- Type: string + +### Parameter: `diagnosticSettings.logAnalyticsDestinationType` + +A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'AzureDiagnostics' + 'Dedicated' + ] + ``` + +### Parameter: `diagnosticSettings.logCategoriesAndGroups` + +The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to '' to disable log collection. + +- Required: No +- Type: array + +### Parameter: `diagnosticSettings.marketplacePartnerResourceId` + +The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs. + +- Required: No +- Type: string + +### Parameter: `diagnosticSettings.metricCategories` + +The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to '' to disable metric collection. + +- Required: No +- Type: array + +### Parameter: `diagnosticSettings.name` + +The name of diagnostic setting. + +- Required: No +- Type: string + +### Parameter: `diagnosticSettings.storageAccountResourceId` + +Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub. + +- Required: No +- Type: string + +### Parameter: `diagnosticSettings.workspaceResourceId` + +Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub. + +- Required: No +- Type: string + +### Parameter: `disableIPSecReplayProtection` + +disableIPSecReplayProtection flag. Used for VPN Gateways. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `domainNameLabel` + +DNS name(s) of the Public IP resource(s). If you enabled active-active configuration, you need to provide 2 DNS names, if you want to use this feature. A region specific suffix will be appended to it, e.g.: your-DNS-name.westeurope.cloudapp.azure.com. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `enableBgp` + +Value to specify if BGP is enabled or not. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `enableBgpRouteTranslationForNat` + +EnableBgpRouteTranslationForNat flag. Can only be used when "natRules" are enabled on the Virtual Network Gateway. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `enableDnsForwarding` + +Whether DNS forwarding is enabled or not and is only supported for Express Route Gateways. The DNS forwarding feature flag must be enabled on the current subscription. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `enablePrivateIpAddress` + +Whether private IP needs to be enabled on this gateway for connections or not. Used for configuring a Site-to-Site VPN connection over ExpressRoute private peering. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `enableTelemetry` + +Enable/Disable usage telemetry for module. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `gatewayDefaultSiteLocalNetworkGatewayId` + +The reference to the LocalNetworkGateway resource which represents local network site having default routes. Assign Null value in case of removing existing default site setting. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `gatewayPipName` + +Specifies the name of the Public IP used by the Virtual Network Gateway. If it's not provided, a '-pip' suffix will be appended to the gateway's name. + +- Required: No +- Type: string +- Default: `[format('{0}-pip1', parameters('name'))]` + +### Parameter: `location` + +Location for all resources. + +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + +### Parameter: `lock` + +The lock settings of the service. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`kind`](#parameter-lockkind) | string | Specify the type of lock. | +| [`name`](#parameter-lockname) | string | Specify the name of lock. | + +### Parameter: `lock.kind` + +Specify the type of lock. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'CanNotDelete' + 'None' + 'ReadOnly' + ] + ``` + +### Parameter: `lock.name` + +Specify the name of lock. + +- Required: No +- Type: string + +### Parameter: `natRules` + +NatRules for virtual network gateway. NAT is supported on the the following SKUs: VpnGw2~5, VpnGw2AZ~5AZ and is supported for IPsec/IKE cross-premises connections only. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `publicIpDiagnosticSettings` + +The diagnostic settings of the Public IP. + +- Required: No +- Type: array + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`eventHubAuthorizationRuleResourceId`](#parameter-publicipdiagnosticsettingseventhubauthorizationruleresourceid) | string | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| [`eventHubName`](#parameter-publicipdiagnosticsettingseventhubname) | string | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub. | +| [`logAnalyticsDestinationType`](#parameter-publicipdiagnosticsettingsloganalyticsdestinationtype) | string | A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type. | +| [`logCategoriesAndGroups`](#parameter-publicipdiagnosticsettingslogcategoriesandgroups) | array | The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to '' to disable log collection. | +| [`marketplacePartnerResourceId`](#parameter-publicipdiagnosticsettingsmarketplacepartnerresourceid) | string | The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs. | +| [`metricCategories`](#parameter-publicipdiagnosticsettingsmetriccategories) | array | The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to '' to disable metric collection. | +| [`name`](#parameter-publicipdiagnosticsettingsname) | string | The name of diagnostic setting. | +| [`storageAccountResourceId`](#parameter-publicipdiagnosticsettingsstorageaccountresourceid) | string | Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub. | +| [`workspaceResourceId`](#parameter-publicipdiagnosticsettingsworkspaceresourceid) | string | Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub. | + +### Parameter: `publicIpDiagnosticSettings.eventHubAuthorizationRuleResourceId` + +Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. + +- Required: No +- Type: string + +### Parameter: `publicIpDiagnosticSettings.eventHubName` + +Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub. + +- Required: No +- Type: string + +### Parameter: `publicIpDiagnosticSettings.logAnalyticsDestinationType` + +A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'AzureDiagnostics' + 'Dedicated' + ] + ``` + +### Parameter: `publicIpDiagnosticSettings.logCategoriesAndGroups` + +The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to '' to disable log collection. + +- Required: No +- Type: array + +### Parameter: `publicIpDiagnosticSettings.marketplacePartnerResourceId` + +The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs. + +- Required: No +- Type: string + +### Parameter: `publicIpDiagnosticSettings.metricCategories` + +The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to '' to disable metric collection. + +- Required: No +- Type: array + +### Parameter: `publicIpDiagnosticSettings.name` + +The name of diagnostic setting. + +- Required: No +- Type: string + +### Parameter: `publicIpDiagnosticSettings.storageAccountResourceId` + +Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub. + +- Required: No +- Type: string + +### Parameter: `publicIpDiagnosticSettings.workspaceResourceId` + +Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub. + +- Required: No +- Type: string + +### Parameter: `publicIPPrefixResourceId` + +Resource ID of the Public IP Prefix object. This is only needed if you want your Public IPs created in a PIP Prefix. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `publicIpZones` + +Specifies the zones of the Public IP address. Basic IP SKU does not support Availability Zones. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `roleAssignments` + +Array of role assignments to create. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`principalId`](#parameter-roleassignmentsprincipalid) | string | The principal ID of the principal (user/group/identity) to assign the role to. | +| [`roleDefinitionIdOrName`](#parameter-roleassignmentsroledefinitionidorname) | string | The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`condition`](#parameter-roleassignmentscondition) | string | The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container". | +| [`conditionVersion`](#parameter-roleassignmentsconditionversion) | string | Version of the condition. | +| [`delegatedManagedIdentityResourceId`](#parameter-roleassignmentsdelegatedmanagedidentityresourceid) | string | The Resource Id of the delegated managed identity resource. | +| [`description`](#parameter-roleassignmentsdescription) | string | The description of the role assignment. | +| [`principalType`](#parameter-roleassignmentsprincipaltype) | string | The principal type of the assigned principal ID. | + +### Parameter: `roleAssignments.principalId` + +The principal ID of the principal (user/group/identity) to assign the role to. + +- Required: Yes +- Type: string + +### Parameter: `roleAssignments.roleDefinitionIdOrName` + +The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. + +- Required: Yes +- Type: string + +### Parameter: `roleAssignments.condition` + +The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container". + +- Required: No +- Type: string + +### Parameter: `roleAssignments.conditionVersion` + +Version of the condition. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + '2.0' + ] + ``` + +### Parameter: `roleAssignments.delegatedManagedIdentityResourceId` + +The Resource Id of the delegated managed identity resource. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.description` + +The description of the role assignment. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + +### Parameter: `tags` + +Tags of the resource. + +- Required: No +- Type: object + +### Parameter: `vpnClientAadConfiguration` + +Configuration for AAD Authentication for P2S Tunnel Type, Cannot be configured if clientRootCertData is provided. + +- Required: No +- Type: object +- Default: `{}` + +### Parameter: `vpnClientAddressPoolPrefix` + +The IP address range from which VPN clients will receive an IP address when connected. Range specified must not overlap with on-premise network. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `vpnGatewayGeneration` + +The generation for this VirtualNetworkGateway. Must be None if virtualNetworkGatewayType is not VPN. + +- Required: No +- Type: string +- Default: `'None'` +- Allowed: + ```Bicep + [ + 'Generation1' + 'Generation2' + 'None' + ] + ``` + +### Parameter: `vpnType` + +Specifies the VPN type. + +- Required: No +- Type: string +- Default: `'RouteBased'` +- Allowed: + ```Bicep + [ + 'PolicyBased' + 'RouteBased' + ] + ``` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `activeActive` | bool | Shows if the virtual network gateway is configured in active-active mode. | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the virtual network gateway. | +| `resourceGroupName` | string | The resource group the virtual network gateway was deployed. | +| `resourceId` | string | The resource ID of the virtual network gateway. | + +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other CARML modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `br/public:avm/res/network/public-ip-address:0.2.0` | Remote reference | + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/network/virtual-network-gateway/main.bicep b/avm/res/network/virtual-network-gateway/main.bicep new file mode 100644 index 0000000000..f05fb532d2 --- /dev/null +++ b/avm/res/network/virtual-network-gateway/main.bicep @@ -0,0 +1,484 @@ +metadata name = 'Virtual Network Gateways' +metadata description = 'This module deploys a Virtual Network Gateway.' +metadata owner = 'Azure/module-maintainers' + +@description('Required. Specifies the Virtual Network Gateway name.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Specifies the name of the Public IP used by the Virtual Network Gateway. If it\'s not provided, a \'-pip\' suffix will be appended to the gateway\'s name.') +param gatewayPipName string = '${name}-pip1' + +@description('Optional. Specifies the name of the Public IP used by the Virtual Network Gateway when active-active configuration is required. If it\'s not provided, a \'-pip\' suffix will be appended to the gateway\'s name.') +param activeGatewayPipName string = '${name}-pip2' + +@description('Optional. Resource ID of the Public IP Prefix object. This is only needed if you want your Public IPs created in a PIP Prefix.') +param publicIPPrefixResourceId string = '' + +@description('Optional. Specifies the zones of the Public IP address. Basic IP SKU does not support Availability Zones.') +param publicIpZones array = [] + +@description('Optional. DNS name(s) of the Public IP resource(s). If you enabled active-active configuration, you need to provide 2 DNS names, if you want to use this feature. A region specific suffix will be appended to it, e.g.: your-DNS-name.westeurope.cloudapp.azure.com.') +param domainNameLabel array = [] + +@description('Required. Specifies the gateway type. E.g. VPN, ExpressRoute.') +@allowed([ + 'Vpn' + 'ExpressRoute' +]) +param gatewayType string + +@description('Optional. The generation for this VirtualNetworkGateway. Must be None if virtualNetworkGatewayType is not VPN.') +@allowed([ + 'Generation1' + 'Generation2' + 'None' +]) +param vpnGatewayGeneration string = 'None' + +@description('Required. The SKU of the Gateway.') +@allowed([ + 'Basic' + 'VpnGw1' + 'VpnGw2' + 'VpnGw3' + 'VpnGw4' + 'VpnGw5' + 'VpnGw1AZ' + 'VpnGw2AZ' + 'VpnGw3AZ' + 'VpnGw4AZ' + 'VpnGw5AZ' + 'Standard' + 'HighPerformance' + 'UltraPerformance' + 'ErGw1AZ' + 'ErGw2AZ' + 'ErGw3AZ' +]) +param skuName string + +@description('Optional. Specifies the VPN type.') +@allowed([ + 'PolicyBased' + 'RouteBased' +]) +param vpnType string = 'RouteBased' + +@description('Required. Virtual Network resource ID.') +param vNetResourceId string + +@description('Optional. Value to specify if the Gateway should be deployed in active-active or active-passive configuration.') +param activeActive bool = true + +@description('Optional. Value to specify if BGP is enabled or not.') +param enableBgp bool = true + +@description('Optional. ASN value.') +param asn int = 65815 + +@description('Optional. The IP address range from which VPN clients will receive an IP address when connected. Range specified must not overlap with on-premise network.') +param vpnClientAddressPoolPrefix string = '' + +@description('Optional. Configures this gateway to accept traffic from remote Virtual WAN networks.') +param allowVirtualWanTraffic bool = false + +@description('Optional. Configure this gateway to accept traffic from other Azure Virtual Networks. This configuration does not support connectivity to Azure Virtual WAN.') +param allowRemoteVnetTraffic bool = false + +@description('Optional. disableIPSecReplayProtection flag. Used for VPN Gateways.') +param disableIPSecReplayProtection bool = false + +@description('Optional. Whether DNS forwarding is enabled or not and is only supported for Express Route Gateways. The DNS forwarding feature flag must be enabled on the current subscription.') +param enableDnsForwarding bool = false + +@description('Optional. Whether private IP needs to be enabled on this gateway for connections or not. Used for configuring a Site-to-Site VPN connection over ExpressRoute private peering.') +param enablePrivateIpAddress bool = false + +@description('Optional. The reference to the LocalNetworkGateway resource which represents local network site having default routes. Assign Null value in case of removing existing default site setting.') +param gatewayDefaultSiteLocalNetworkGatewayId string = '' + +@description('Optional. NatRules for virtual network gateway. NAT is supported on the the following SKUs: VpnGw2~5, VpnGw2AZ~5AZ and is supported for IPsec/IKE cross-premises connections only.') +param natRules array = [] + +@description('Optional. EnableBgpRouteTranslationForNat flag. Can only be used when "natRules" are enabled on the Virtual Network Gateway.') +param enableBgpRouteTranslationForNat bool = false + +@description('Optional. Client root certificate data used to authenticate VPN clients. Cannot be configured if vpnClientAadConfiguration is provided.') +param clientRootCertData string = '' + +@description('Optional. Thumbprint of the revoked certificate. This would revoke VPN client certificates matching this thumbprint from connecting to the VNet.') +param clientRevokedCertThumbprint string = '' + +@description('Optional. The diagnostic settings of the Public IP.') +param publicIpDiagnosticSettings diagnosticSettingType + +@description('Optional. The diagnostic settings of the service.') +param diagnosticSettings diagnosticSettingType + +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType + +@description('Optional. The lock settings of the service.') +param lock lockType + +@description('Optional. Tags of the resource.') +param tags object? + +@description('Optional. Enable/Disable usage telemetry for module.') +param enableTelemetry bool = true + +@description('Optional. Configuration for AAD Authentication for P2S Tunnel Type, Cannot be configured if clientRootCertData is provided.') +param vpnClientAadConfiguration object = {} + +// ================// +// Variables // +// ================// + +// Other Variables +var zoneRedundantSkus = [ + 'VpnGw1AZ' + 'VpnGw2AZ' + 'VpnGw3AZ' + 'VpnGw4AZ' + 'VpnGw5AZ' + 'ErGw1AZ' + 'ErGw2AZ' + 'ErGw3AZ' +] +var gatewayPipSku = contains(zoneRedundantSkus, skuName) ? 'Standard' : 'Basic' +var gatewayPipAllocationMethod = contains(zoneRedundantSkus, skuName) ? 'Static' : 'Dynamic' + +var isActiveActiveValid = gatewayType != 'ExpressRoute' ? activeActive : false +var virtualGatewayPipNameVar = isActiveActiveValid ? [ + gatewayPipName + activeGatewayPipName +] : [ + gatewayPipName +] + +var vpnTypeVar = gatewayType != 'ExpressRoute' ? vpnType : 'PolicyBased' + +var isBgpValid = gatewayType != 'ExpressRoute' ? enableBgp : false +var bgpSettings = { + asn: asn +} + +// Potential configurations (active-active vs active-passive) +var ipConfiguration = isActiveActiveValid ? [ + { + properties: { + privateIPAllocationMethod: 'Dynamic' + subnet: { + id: '${vNetResourceId}/subnets/GatewaySubnet' + } + publicIPAddress: { + id: az.resourceId('Microsoft.Network/publicIPAddresses', gatewayPipName) + } + } + name: 'vNetGatewayConfig1' + } + { + properties: { + privateIPAllocationMethod: 'Dynamic' + subnet: { + id: '${vNetResourceId}/subnets/GatewaySubnet' + } + publicIPAddress: { + id: isActiveActiveValid ? az.resourceId('Microsoft.Network/publicIPAddresses', activeGatewayPipName) : az.resourceId('Microsoft.Network/publicIPAddresses', gatewayPipName) + } + } + name: 'vNetGatewayConfig2' + } +] : [ + { + properties: { + privateIPAllocationMethod: 'Dynamic' + subnet: { + id: '${vNetResourceId}/subnets/GatewaySubnet' + } + publicIPAddress: { + id: az.resourceId('Microsoft.Network/publicIPAddresses', gatewayPipName) + } + } + name: 'vNetGatewayConfig1' + } +] + +var vpnClientConfiguration = !empty(clientRootCertData) ? { + vpnClientAddressPool: { + addressPrefixes: [ + vpnClientAddressPoolPrefix + ] + } + vpnClientRootCertificates: [ + { + name: 'RootCert1' + properties: { + PublicCertData: clientRootCertData + } + } + ] + vpnClientRevokedCertificates: !empty(clientRevokedCertThumbprint) ? [ + { + name: 'RevokedCert1' + properties: { + Thumbprint: clientRevokedCertThumbprint + } + } + ] : null +} : !empty(vpnClientAadConfiguration) ? { + vpnClientAddressPool: { + addressPrefixes: [ + vpnClientAddressPoolPrefix + ] + } + aadTenant: vpnClientAadConfiguration.aadTenant + aadAudience: vpnClientAadConfiguration.aadAudience + aadIssuer: vpnClientAadConfiguration.aadIssuer + vpnAuthenticationTypes: vpnClientAadConfiguration.vpnAuthenticationTypes + vpnClientProtocols: vpnClientAadConfiguration.vpnClientProtocols +} : null + +var builtInRoleNames = { + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Network Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7') + Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Role Based Access Control Administrator (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +// ================// +// Deployments // +// ================// + +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { + name: take('46d3xbcp.res.network-virtualnetworkgateway.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}', 64) + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } + } + } + } +} + + +// Public IPs +@batchSize(1) +module publicIPAddress 'br/public:avm/res/network/public-ip-address:0.2.0' = [for (virtualGatewayPublicIpName, index) in virtualGatewayPipNameVar: { + name: virtualGatewayPublicIpName + params: { + name: virtualGatewayPublicIpName + diagnosticSettings: publicIpDiagnosticSettings + location: location + lock: lock + publicIPAllocationMethod: gatewayPipAllocationMethod + publicIpPrefixResourceId: !empty(publicIPPrefixResourceId) ? publicIPPrefixResourceId : '' + tags: tags + skuName: gatewayPipSku + zones: contains(zoneRedundantSkus, skuName) ? publicIpZones : [] + dnsSettings: { + domainNameLabel: length(virtualGatewayPipNameVar) == length(domainNameLabel) ? domainNameLabel[index] : virtualGatewayPublicIpName + domainNameLabelScope:'' + } + } +}] + + +// VNET Gateway +// ============ +resource virtualNetworkGateway 'Microsoft.Network/virtualNetworkGateways@2023-04-01' = { + name: name + location: location + tags: tags + properties: { + ipConfigurations: ipConfiguration + activeActive: isActiveActiveValid + allowRemoteVnetTraffic: allowRemoteVnetTraffic + allowVirtualWanTraffic: allowVirtualWanTraffic + enableBgp: isBgpValid + bgpSettings: isBgpValid ? bgpSettings : null + disableIPSecReplayProtection: disableIPSecReplayProtection + enableDnsForwarding: gatewayType == 'ExpressRoute' ? enableDnsForwarding : null + enablePrivateIpAddress: enablePrivateIpAddress + enableBgpRouteTranslationForNat: enableBgpRouteTranslationForNat + gatewayType: gatewayType + gatewayDefaultSite: !empty(gatewayDefaultSiteLocalNetworkGatewayId) ? { + id: gatewayDefaultSiteLocalNetworkGatewayId + } : null + sku: { + name: skuName + tier: skuName + } + vpnType: vpnTypeVar + vpnClientConfiguration: !empty(vpnClientAddressPoolPrefix) ? vpnClientConfiguration : null + vpnGatewayGeneration: gatewayType == 'Vpn' ? vpnGatewayGeneration : 'None' + } + dependsOn: [ + publicIPAddress + ] +} + +module virtualNetworkGateway_natRules 'nat-rule/main.bicep' = [for (natRule, index) in natRules: { + name: '${deployment().name}-NATRule-${index}' + params: { + name: natRule.name + virtualNetworkGatewayName: virtualNetworkGateway.name + externalMappings: contains(natRule, 'externalMappings') ? natRule.externalMappings : [] + internalMappings: contains(natRule, 'internalMappings') ? natRule.internalMappings : [] + ipConfigurationId: contains(natRule, 'ipConfigurationId') ? natRule.ipConfigurationId : '' + mode: contains(natRule, 'mode') ? natRule.mode : '' + type: contains(natRule, 'type') ? natRule.type : '' + } +}] + +resource virtualNetworkGateway_lock 'Microsoft.Authorization/locks@2020-05-01' = if (!empty(lock ?? {}) && lock.?kind != 'None') { + name: lock.?name ?? 'lock-${name}' + properties: { + level: lock.?kind ?? '' + notes: lock.?kind == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot delete or modify the resource or child resources.' + } + scope: virtualNetworkGateway +} + +resource virtualNetworkGateway_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: diagnosticSetting.?metricCategories ?? [ + { + category: 'AllMetrics' + timeGrain: null + enabled: true + } + ] + logs: diagnosticSetting.?logCategoriesAndGroups ?? [ + { + categoryGroup: 'AllLogs' + enabled: true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: virtualNetworkGateway +}] + +resource virtualNetworkGateway_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(virtualNetworkGateway.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + principalId: roleAssignment.principalId + description: roleAssignment.?description + principalType: roleAssignment.?principalType + condition: roleAssignment.?condition + conditionVersion: !empty(roleAssignment.?condition) ? (roleAssignment.?conditionVersion ?? '2.0') : null // Must only be set if condtion is set + delegatedManagedIdentityResourceId: roleAssignment.?delegatedManagedIdentityResourceId + } + scope: virtualNetworkGateway +}] + +// ================// +// Outputs // +// ================// +@description('The resource group the virtual network gateway was deployed.') +output resourceGroupName string = resourceGroup().name + +@description('The name of the virtual network gateway.') +output name string = virtualNetworkGateway.name + +@description('The resource ID of the virtual network gateway.') +output resourceId string = virtualNetworkGateway.id + +@description('Shows if the virtual network gateway is configured in active-active mode.') +output activeActive bool = virtualNetworkGateway.properties.activeActive + +@description('The location the resource was deployed into.') +output location string = virtualNetworkGateway.location + +// =============== // +// Definitions // +// =============== // + +type lockType = { + @description('Optional. Specify the name of lock.') + name: string? + + @description('Optional. Specify the type of lock.') + kind: ('CanNotDelete' | 'ReadOnly' | 'None')? +}? + +type roleAssignmentType = { + @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') + roleDefinitionIdOrName: string + + @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') + principalId: string + + @description('Optional. The principal type of the assigned principal ID.') + principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? + + @description('Optional. The description of the role assignment.') + description: string? + + @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') + condition: string? + + @description('Optional. Version of the condition.') + conditionVersion: '2.0'? + + @description('Optional. The Resource Id of the delegated managed identity resource.') + delegatedManagedIdentityResourceId: string? +}[]? + +type diagnosticSettingType = { + @description('Optional. The name of diagnostic setting.') + name: string? + + @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to \'\' to disable log collection.') + logCategoriesAndGroups: { + @description('Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here.') + category: string? + + @description('Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to \'AllLogs\' to collect all logs.') + categoryGroup: string? + }[]? + + @description('Optional. The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to \'\' to disable metric collection.') + metricCategories: { + @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to \'AllMetrics\' to collect all metrics.') + category: string + }[]? + + @description('Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type.') + logAnalyticsDestinationType: ('Dedicated' | 'AzureDiagnostics')? + + @description('Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.') + workspaceResourceId: string? + + @description('Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.') + storageAccountResourceId: string? + + @description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') + eventHubAuthorizationRuleResourceId: string? + + @description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.') + eventHubName: string? + + @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') + marketplacePartnerResourceId: string? +}[]? diff --git a/avm/res/network/virtual-network-gateway/main.json b/avm/res/network/virtual-network-gateway/main.json new file mode 100644 index 0000000000..06543e2543 --- /dev/null +++ b/avm/res/network/virtual-network-gateway/main.json @@ -0,0 +1,1396 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "13396048573854621912" + }, + "name": "Virtual Network Gateways", + "description": "This module deploys a Virtual Network Gateway.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "diagnosticSettingType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to 'AllLogs' to collect all logs." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to '' to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to 'AllMetrics' to collect all metrics." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to '' to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Specifies the Virtual Network Gateway name." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "gatewayPipName": { + "type": "string", + "defaultValue": "[format('{0}-pip1', parameters('name'))]", + "metadata": { + "description": "Optional. Specifies the name of the Public IP used by the Virtual Network Gateway. If it's not provided, a '-pip' suffix will be appended to the gateway's name." + } + }, + "activeGatewayPipName": { + "type": "string", + "defaultValue": "[format('{0}-pip2', parameters('name'))]", + "metadata": { + "description": "Optional. Specifies the name of the Public IP used by the Virtual Network Gateway when active-active configuration is required. If it's not provided, a '-pip' suffix will be appended to the gateway's name." + } + }, + "publicIPPrefixResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of the Public IP Prefix object. This is only needed if you want your Public IPs created in a PIP Prefix." + } + }, + "publicIpZones": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Specifies the zones of the Public IP address. Basic IP SKU does not support Availability Zones." + } + }, + "domainNameLabel": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. DNS name(s) of the Public IP resource(s). If you enabled active-active configuration, you need to provide 2 DNS names, if you want to use this feature. A region specific suffix will be appended to it, e.g.: your-DNS-name.westeurope.cloudapp.azure.com." + } + }, + "gatewayType": { + "type": "string", + "allowedValues": [ + "Vpn", + "ExpressRoute" + ], + "metadata": { + "description": "Required. Specifies the gateway type. E.g. VPN, ExpressRoute." + } + }, + "vpnGatewayGeneration": { + "type": "string", + "defaultValue": "None", + "allowedValues": [ + "Generation1", + "Generation2", + "None" + ], + "metadata": { + "description": "Optional. The generation for this VirtualNetworkGateway. Must be None if virtualNetworkGatewayType is not VPN." + } + }, + "skuName": { + "type": "string", + "allowedValues": [ + "Basic", + "VpnGw1", + "VpnGw2", + "VpnGw3", + "VpnGw4", + "VpnGw5", + "VpnGw1AZ", + "VpnGw2AZ", + "VpnGw3AZ", + "VpnGw4AZ", + "VpnGw5AZ", + "Standard", + "HighPerformance", + "UltraPerformance", + "ErGw1AZ", + "ErGw2AZ", + "ErGw3AZ" + ], + "metadata": { + "description": "Required. The SKU of the Gateway." + } + }, + "vpnType": { + "type": "string", + "defaultValue": "RouteBased", + "allowedValues": [ + "PolicyBased", + "RouteBased" + ], + "metadata": { + "description": "Optional. Specifies the VPN type." + } + }, + "vNetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Virtual Network resource ID." + } + }, + "activeActive": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Value to specify if the Gateway should be deployed in active-active or active-passive configuration." + } + }, + "enableBgp": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Value to specify if BGP is enabled or not." + } + }, + "asn": { + "type": "int", + "defaultValue": 65815, + "metadata": { + "description": "Optional. ASN value." + } + }, + "vpnClientAddressPoolPrefix": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The IP address range from which VPN clients will receive an IP address when connected. Range specified must not overlap with on-premise network." + } + }, + "allowVirtualWanTraffic": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Configures this gateway to accept traffic from remote Virtual WAN networks." + } + }, + "allowRemoteVnetTraffic": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Configure this gateway to accept traffic from other Azure Virtual Networks. This configuration does not support connectivity to Azure Virtual WAN." + } + }, + "disableIPSecReplayProtection": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. disableIPSecReplayProtection flag. Used for VPN Gateways." + } + }, + "enableDnsForwarding": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Whether DNS forwarding is enabled or not and is only supported for Express Route Gateways. The DNS forwarding feature flag must be enabled on the current subscription." + } + }, + "enablePrivateIpAddress": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Whether private IP needs to be enabled on this gateway for connections or not. Used for configuring a Site-to-Site VPN connection over ExpressRoute private peering." + } + }, + "gatewayDefaultSiteLocalNetworkGatewayId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The reference to the LocalNetworkGateway resource which represents local network site having default routes. Assign Null value in case of removing existing default site setting." + } + }, + "natRules": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. NatRules for virtual network gateway. NAT is supported on the the following SKUs: VpnGw2~5, VpnGw2AZ~5AZ and is supported for IPsec/IKE cross-premises connections only." + } + }, + "enableBgpRouteTranslationForNat": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. EnableBgpRouteTranslationForNat flag. Can only be used when \"natRules\" are enabled on the Virtual Network Gateway." + } + }, + "clientRootCertData": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Client root certificate data used to authenticate VPN clients. Cannot be configured if vpnClientAadConfiguration is provided." + } + }, + "clientRevokedCertThumbprint": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Thumbprint of the revoked certificate. This would revoke VPN client certificates matching this thumbprint from connecting to the VNet." + } + }, + "publicIpDiagnosticSettings": { + "$ref": "#/definitions/diagnosticSettingType", + "metadata": { + "description": "Optional. The diagnostic settings of the Public IP." + } + }, + "diagnosticSettings": { + "$ref": "#/definitions/diagnosticSettingType", + "metadata": { + "description": "Optional. The diagnostic settings of the service." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." + } + }, + "vpnClientAadConfiguration": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Configuration for AAD Authentication for P2S Tunnel Type, Cannot be configured if clientRootCertData is provided." + } + } + }, + "variables": { + "zoneRedundantSkus": [ + "VpnGw1AZ", + "VpnGw2AZ", + "VpnGw3AZ", + "VpnGw4AZ", + "VpnGw5AZ", + "ErGw1AZ", + "ErGw2AZ", + "ErGw3AZ" + ], + "gatewayPipSku": "[if(contains(variables('zoneRedundantSkus'), parameters('skuName')), 'Standard', 'Basic')]", + "gatewayPipAllocationMethod": "[if(contains(variables('zoneRedundantSkus'), parameters('skuName')), 'Static', 'Dynamic')]", + "isActiveActiveValid": "[if(not(equals(parameters('gatewayType'), 'ExpressRoute')), parameters('activeActive'), false())]", + "virtualGatewayPipNameVar": "[if(variables('isActiveActiveValid'), createArray(parameters('gatewayPipName'), parameters('activeGatewayPipName')), createArray(parameters('gatewayPipName')))]", + "vpnTypeVar": "[if(not(equals(parameters('gatewayType'), 'ExpressRoute')), parameters('vpnType'), 'PolicyBased')]", + "isBgpValid": "[if(not(equals(parameters('gatewayType'), 'ExpressRoute')), parameters('enableBgp'), false())]", + "bgpSettings": { + "asn": "[parameters('asn')]" + }, + "ipConfiguration": "[if(variables('isActiveActiveValid'), createArray(createObject('properties', createObject('privateIPAllocationMethod', 'Dynamic', 'subnet', createObject('id', format('{0}/subnets/GatewaySubnet', parameters('vNetResourceId'))), 'publicIPAddress', createObject('id', resourceId('Microsoft.Network/publicIPAddresses', parameters('gatewayPipName')))), 'name', 'vNetGatewayConfig1'), createObject('properties', createObject('privateIPAllocationMethod', 'Dynamic', 'subnet', createObject('id', format('{0}/subnets/GatewaySubnet', parameters('vNetResourceId'))), 'publicIPAddress', createObject('id', if(variables('isActiveActiveValid'), resourceId('Microsoft.Network/publicIPAddresses', parameters('activeGatewayPipName')), resourceId('Microsoft.Network/publicIPAddresses', parameters('gatewayPipName'))))), 'name', 'vNetGatewayConfig2')), createArray(createObject('properties', createObject('privateIPAllocationMethod', 'Dynamic', 'subnet', createObject('id', format('{0}/subnets/GatewaySubnet', parameters('vNetResourceId'))), 'publicIPAddress', createObject('id', resourceId('Microsoft.Network/publicIPAddresses', parameters('gatewayPipName')))), 'name', 'vNetGatewayConfig1')))]", + "vpnClientConfiguration": "[if(not(empty(parameters('clientRootCertData'))), createObject('vpnClientAddressPool', createObject('addressPrefixes', createArray(parameters('vpnClientAddressPoolPrefix'))), 'vpnClientRootCertificates', createArray(createObject('name', 'RootCert1', 'properties', createObject('PublicCertData', parameters('clientRootCertData')))), 'vpnClientRevokedCertificates', if(not(empty(parameters('clientRevokedCertThumbprint'))), createArray(createObject('name', 'RevokedCert1', 'properties', createObject('Thumbprint', parameters('clientRevokedCertThumbprint')))), null())), if(not(empty(parameters('vpnClientAadConfiguration'))), createObject('vpnClientAddressPool', createObject('addressPrefixes', createArray(parameters('vpnClientAddressPoolPrefix'))), 'aadTenant', parameters('vpnClientAadConfiguration').aadTenant, 'aadAudience', parameters('vpnClientAadConfiguration').aadAudience, 'aadIssuer', parameters('vpnClientAadConfiguration').aadIssuer, 'vpnAuthenticationTypes', parameters('vpnClientAadConfiguration').vpnAuthenticationTypes, 'vpnClientProtocols', parameters('vpnClientAadConfiguration').vpnClientProtocols), null()))]", + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2023-07-01", + "name": "[take(format('46d3xbcp.res.network-virtualnetworkgateway.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4)), 64)]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "virtualNetworkGateway": { + "type": "Microsoft.Network/virtualNetworkGateways", + "apiVersion": "2023-04-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "ipConfigurations": "[variables('ipConfiguration')]", + "activeActive": "[variables('isActiveActiveValid')]", + "allowRemoteVnetTraffic": "[parameters('allowRemoteVnetTraffic')]", + "allowVirtualWanTraffic": "[parameters('allowVirtualWanTraffic')]", + "enableBgp": "[variables('isBgpValid')]", + "bgpSettings": "[if(variables('isBgpValid'), variables('bgpSettings'), null())]", + "disableIPSecReplayProtection": "[parameters('disableIPSecReplayProtection')]", + "enableDnsForwarding": "[if(equals(parameters('gatewayType'), 'ExpressRoute'), parameters('enableDnsForwarding'), null())]", + "enablePrivateIpAddress": "[parameters('enablePrivateIpAddress')]", + "enableBgpRouteTranslationForNat": "[parameters('enableBgpRouteTranslationForNat')]", + "gatewayType": "[parameters('gatewayType')]", + "gatewayDefaultSite": "[if(not(empty(parameters('gatewayDefaultSiteLocalNetworkGatewayId'))), createObject('id', parameters('gatewayDefaultSiteLocalNetworkGatewayId')), null())]", + "sku": { + "name": "[parameters('skuName')]", + "tier": "[parameters('skuName')]" + }, + "vpnType": "[variables('vpnTypeVar')]", + "vpnClientConfiguration": "[if(not(empty(parameters('vpnClientAddressPoolPrefix'))), variables('vpnClientConfiguration'), null())]", + "vpnGatewayGeneration": "[if(equals(parameters('gatewayType'), 'Vpn'), parameters('vpnGatewayGeneration'), 'None')]" + }, + "dependsOn": [ + "publicIPAddress" + ] + }, + "virtualNetworkGateway_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.Network/virtualNetworkGateways/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "virtualNetworkGateway" + ] + }, + "virtualNetworkGateway_diagnosticSettings": { + "copy": { + "name": "virtualNetworkGateway_diagnosticSettings", + "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" + }, + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Network/virtualNetworkGateways/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'name'), format('{0}-diagnosticSettings', parameters('name')))]", + "properties": { + "storageAccountId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'storageAccountResourceId')]", + "workspaceId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'workspaceResourceId')]", + "eventHubAuthorizationRuleId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubAuthorizationRuleResourceId')]", + "eventHubName": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubName')]", + "metrics": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics', 'timeGrain', null(), 'enabled', true())))]", + "logs": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'AllLogs', 'enabled', true())))]", + "marketplacePartnerId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'marketplacePartnerResourceId')]", + "logAnalyticsDestinationType": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logAnalyticsDestinationType')]" + }, + "dependsOn": [ + "virtualNetworkGateway" + ] + }, + "virtualNetworkGateway_roleAssignments": { + "copy": { + "name": "virtualNetworkGateway_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/virtualNetworkGateways/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.Network/virtualNetworkGateways', parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", + "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "virtualNetworkGateway" + ] + }, + "publicIPAddress": { + "copy": { + "name": "publicIPAddress", + "count": "[length(variables('virtualGatewayPipNameVar'))]", + "mode": "serial", + "batchSize": 1 + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[variables('virtualGatewayPipNameVar')[copyIndex()]]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[variables('virtualGatewayPipNameVar')[copyIndex()]]" + }, + "diagnosticSettings": { + "value": "[parameters('publicIpDiagnosticSettings')]" + }, + "location": { + "value": "[parameters('location')]" + }, + "lock": { + "value": "[parameters('lock')]" + }, + "publicIPAllocationMethod": { + "value": "[variables('gatewayPipAllocationMethod')]" + }, + "publicIpPrefixResourceId": "[if(not(empty(parameters('publicIPPrefixResourceId'))), createObject('value', parameters('publicIPPrefixResourceId')), createObject('value', ''))]", + "tags": { + "value": "[parameters('tags')]" + }, + "skuName": { + "value": "[variables('gatewayPipSku')]" + }, + "zones": "[if(contains(variables('zoneRedundantSkus'), parameters('skuName')), createObject('value', parameters('publicIpZones')), createObject('value', createArray()))]", + "dnsSettings": { + "value": { + "domainNameLabel": "[if(equals(length(variables('virtualGatewayPipNameVar')), length(parameters('domainNameLabel'))), parameters('domainNameLabel')[copyIndex()], variables('virtualGatewayPipNameVar')[copyIndex()])]", + "domainNameLabelScope": "" + } + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "11486686724612026983" + }, + "name": "Public IP Addresses", + "description": "This module deploys a Public IP Address.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"" + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "dnsSettingsType": { + "type": "object", + "properties": { + "domainNameLabel": { + "type": "string", + "metadata": { + "description": "Required. The domain name label. The concatenation of the domain name label and the regionalized DNS zone make up the fully qualified domain name associated with the public IP address. If a domain name label is specified, an A DNS record is created for the public IP in the Microsoft Azure DNS system." + } + }, + "domainNameLabelScope": { + "type": "string", + "allowedValues": [ + "", + "NoReuse", + "ResourceGroupReuse", + "SubscriptionReuse", + "TenantReuse" + ], + "metadata": { + "description": "Required. The domain name label scope. If a domain name label and a domain name label scope are specified, an A DNS record is created for the public IP in the Microsoft Azure DNS system with a hashed value includes in FQDN." + } + }, + "fqdn": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Fully Qualified Domain Name of the A DNS record associated with the public IP. This is the concatenation of the domainNameLabel and the regionalized DNS zone." + } + }, + "reverseFqdn": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The reverse FQDN. A user-visible, fully qualified domain name that resolves to this public IP address. If the reverseFqdn is specified, then a PTR DNS record is created pointing from the IP address in the in-addr.arpa domain to the reverse FQDN." + } + } + } + }, + "ddosSettingsType": { + "type": "object", + "properties": { + "ddosProtectionPlan": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + }, + "metadata": { + "description": "Required. The DDoS protection plan ID associated with the public IP address." + } + }, + "protectionMode": { + "type": "string", + "allowedValues": [ + "Enabled" + ], + "metadata": { + "description": "Required. The DDoS protection policy customizations." + } + } + } + }, + "diagnosticSettingType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to '' to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to '' to disable log collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the Public IP Address." + } + }, + "publicIpPrefixResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the Public IP Prefix object. This is only needed if you want your Public IPs created in a PIP Prefix." + } + }, + "publicIPAllocationMethod": { + "type": "string", + "defaultValue": "Static", + "allowedValues": [ + "Dynamic", + "Static" + ], + "metadata": { + "description": "Optional. The public IP address allocation method." + } + }, + "zones": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. A list of availability zones denoting the IP allocated for the resource needs to come from." + } + }, + "publicIPAddressVersion": { + "type": "string", + "defaultValue": "IPv4", + "allowedValues": [ + "IPv4", + "IPv6" + ], + "metadata": { + "description": "Optional. IP address version." + } + }, + "dnsSettings": { + "$ref": "#/definitions/dnsSettingsType", + "nullable": true, + "metadata": { + "description": "Optional. The DNS settings of the public IP address." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "skuName": { + "type": "string", + "defaultValue": "Standard", + "allowedValues": [ + "Basic", + "Standard" + ], + "metadata": { + "description": "Optional. Name of a public IP address SKU." + } + }, + "skuTier": { + "type": "string", + "defaultValue": "Regional", + "allowedValues": [ + "Global", + "Regional" + ], + "metadata": { + "description": "Optional. Tier of a public IP address SKU." + } + }, + "ddosSettings": { + "$ref": "#/definitions/ddosSettingsType", + "nullable": true, + "metadata": { + "description": "Optional. The DDoS protection plan configuration associated with the public IP address." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "idleTimeoutInMinutes": { + "type": "int", + "defaultValue": 4, + "metadata": { + "description": "Optional. The idle timeout of the public IP address." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "diagnosticSettings": { + "$ref": "#/definitions/diagnosticSettingType", + "metadata": { + "description": "Optional. The diagnostic settings of the service." + } + } + }, + "variables": { + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "DNS Resolver Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0f2ebee7-ffd4-4fc0-b3b7-664099fdad5d')]", + "DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314')]", + "Domain Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'eeaeda52-9324-47f6-8069-5d5bade478b2')]", + "Domain Services Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '361898ef-9ed1-48c2-849c-a832951106bb')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2023-07-01", + "name": "[format('46d3xbcp.res.network-publicipaddress.{0}.{1}', replace('0.2.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "publicIpAddress": { + "type": "Microsoft.Network/publicIPAddresses", + "apiVersion": "2023-04-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "sku": { + "name": "[parameters('skuName')]", + "tier": "[parameters('skuTier')]" + }, + "zones": "[parameters('zones')]", + "properties": { + "ddosSettings": "[parameters('ddosSettings')]", + "dnsSettings": "[parameters('dnsSettings')]", + "publicIPAddressVersion": "[parameters('publicIPAddressVersion')]", + "publicIPAllocationMethod": "[parameters('publicIPAllocationMethod')]", + "publicIPPrefix": "[if(not(empty(parameters('publicIpPrefixResourceId'))), createObject('id', parameters('publicIpPrefixResourceId')), null())]", + "idleTimeoutInMinutes": "[parameters('idleTimeoutInMinutes')]", + "ipTags": [] + } + }, + "publicIpAddress_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.Network/publicIPAddresses/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "publicIpAddress" + ] + }, + "publicIpAddress_roleAssignments": { + "copy": { + "name": "publicIpAddress_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/publicIPAddresses/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.Network/publicIPAddresses', parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "publicIpAddress" + ] + }, + "publicIpAddress_diagnosticSettings": { + "copy": { + "name": "publicIpAddress_diagnosticSettings", + "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" + }, + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Network/publicIPAddresses/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'name'), format('{0}-diagnosticSettings', parameters('name')))]", + "properties": { + "storageAccountId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'storageAccountResourceId')]", + "workspaceId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'workspaceResourceId')]", + "eventHubAuthorizationRuleId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubAuthorizationRuleResourceId')]", + "eventHubName": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubName')]", + "metrics": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics', 'timeGrain', null(), 'enabled', true())))]", + "logs": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs', 'enabled', true())))]", + "marketplacePartnerId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'marketplacePartnerResourceId')]", + "logAnalyticsDestinationType": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logAnalyticsDestinationType')]" + }, + "dependsOn": [ + "publicIpAddress" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the public IP address was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the public IP address." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the public IP address." + }, + "value": "[resourceId('Microsoft.Network/publicIPAddresses', parameters('name'))]" + }, + "ipAddress": { + "type": "string", + "metadata": { + "description": "The public IP address of the public IP address resource." + }, + "value": "[if(contains(reference('publicIpAddress'), 'ipAddress'), reference('publicIpAddress').ipAddress, '')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('publicIpAddress', '2023-04-01', 'full').location]" + } + } + } + } + }, + "virtualNetworkGateway_natRules": { + "copy": { + "name": "virtualNetworkGateway_natRules", + "count": "[length(parameters('natRules'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-NATRule-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('natRules')[copyIndex()].name]" + }, + "virtualNetworkGatewayName": { + "value": "[parameters('name')]" + }, + "externalMappings": "[if(contains(parameters('natRules')[copyIndex()], 'externalMappings'), createObject('value', parameters('natRules')[copyIndex()].externalMappings), createObject('value', createArray()))]", + "internalMappings": "[if(contains(parameters('natRules')[copyIndex()], 'internalMappings'), createObject('value', parameters('natRules')[copyIndex()].internalMappings), createObject('value', createArray()))]", + "ipConfigurationId": "[if(contains(parameters('natRules')[copyIndex()], 'ipConfigurationId'), createObject('value', parameters('natRules')[copyIndex()].ipConfigurationId), createObject('value', ''))]", + "mode": "[if(contains(parameters('natRules')[copyIndex()], 'mode'), createObject('value', parameters('natRules')[copyIndex()].mode), createObject('value', ''))]", + "type": "[if(contains(parameters('natRules')[copyIndex()], 'type'), createObject('value', parameters('natRules')[copyIndex()].type), createObject('value', ''))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "3164103777824557279" + }, + "name": "VPN Gateway NAT Rules", + "description": "This module deploys a Virtual Network Gateway NAT Rule.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the NAT rule." + } + }, + "virtualNetworkGatewayName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Virtual Network Gateway this NAT rule is associated with. Required if the template is used in a standalone deployment." + } + }, + "externalMappings": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. An address prefix range of destination IPs on the outside network that source IPs will be mapped to. In other words, your post-NAT address prefix range." + } + }, + "internalMappings": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. An address prefix range of source IPs on the inside network that will be mapped to a set of external IPs. In other words, your pre-NAT address prefix range." + } + }, + "ipConfigurationId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. A NAT rule must be configured to a specific Virtual Network Gateway instance. This is applicable to Dynamic NAT only. Static NAT rules are automatically applied to both Virtual Network Gateway instances." + } + }, + "mode": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "", + "EgressSnat", + "IngressSnat" + ], + "metadata": { + "description": "Optional. The type of NAT rule for Virtual Network NAT. IngressSnat mode (also known as Ingress Source NAT) is applicable to traffic entering the Azure hub's site-to-site Virtual Network gateway. EgressSnat mode (also known as Egress Source NAT) is applicable to traffic leaving the Azure hub's Site-to-site Virtual Network gateway." + } + }, + "type": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "", + "Dynamic", + "Static" + ], + "metadata": { + "description": "Optional. The type of NAT rule for Virtual Network NAT. Static one-to-one NAT establishes a one-to-one relationship between an internal address and an external address while Dynamic NAT assigns an IP and port based on availability." + } + } + }, + "resources": [ + { + "type": "Microsoft.Network/virtualNetworkGateways/natRules", + "apiVersion": "2023-04-01", + "name": "[format('{0}/{1}', parameters('virtualNetworkGatewayName'), parameters('name'))]", + "properties": { + "externalMappings": "[parameters('externalMappings')]", + "internalMappings": "[parameters('internalMappings')]", + "ipConfigurationId": "[if(not(empty(parameters('ipConfigurationId'))), parameters('ipConfigurationId'), null())]", + "mode": "[if(not(empty(parameters('mode'))), parameters('mode'), null())]", + "type": "[if(not(empty(parameters('type'))), parameters('type'), null())]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the NAT rule." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the NAT rule." + }, + "value": "[resourceId('Microsoft.Network/virtualNetworkGateways/natRules', parameters('virtualNetworkGatewayName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the NAT rule was deployed into." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "virtualNetworkGateway" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the virtual network gateway was deployed." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the virtual network gateway." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the virtual network gateway." + }, + "value": "[resourceId('Microsoft.Network/virtualNetworkGateways', parameters('name'))]" + }, + "activeActive": { + "type": "bool", + "metadata": { + "description": "Shows if the virtual network gateway is configured in active-active mode." + }, + "value": "[reference('virtualNetworkGateway').activeActive]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('virtualNetworkGateway', '2023-04-01', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/network/virtual-network-gateway/nat-rule/README.md b/avm/res/network/virtual-network-gateway/nat-rule/README.md new file mode 100644 index 0000000000..fd02b15daf --- /dev/null +++ b/avm/res/network/virtual-network-gateway/nat-rule/README.md @@ -0,0 +1,128 @@ +# VPN Gateway NAT Rules `[Microsoft.Network/virtualNetworkGateways/natRules]` + +This module deploys a Virtual Network Gateway NAT Rule. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Network/virtualNetworkGateways/natRules` | [2023-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-04-01/virtualNetworkGateways/natRules) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | The name of the NAT rule. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`virtualNetworkGatewayName`](#parameter-virtualnetworkgatewayname) | string | The name of the parent Virtual Network Gateway this NAT rule is associated with. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`externalMappings`](#parameter-externalmappings) | array | An address prefix range of destination IPs on the outside network that source IPs will be mapped to. In other words, your post-NAT address prefix range. | +| [`internalMappings`](#parameter-internalmappings) | array | An address prefix range of source IPs on the inside network that will be mapped to a set of external IPs. In other words, your pre-NAT address prefix range. | +| [`ipConfigurationId`](#parameter-ipconfigurationid) | string | A NAT rule must be configured to a specific Virtual Network Gateway instance. This is applicable to Dynamic NAT only. Static NAT rules are automatically applied to both Virtual Network Gateway instances. | +| [`mode`](#parameter-mode) | string | The type of NAT rule for Virtual Network NAT. IngressSnat mode (also known as Ingress Source NAT) is applicable to traffic entering the Azure hub's site-to-site Virtual Network gateway. EgressSnat mode (also known as Egress Source NAT) is applicable to traffic leaving the Azure hub's Site-to-site Virtual Network gateway. | +| [`type`](#parameter-type) | string | The type of NAT rule for Virtual Network NAT. Static one-to-one NAT establishes a one-to-one relationship between an internal address and an external address while Dynamic NAT assigns an IP and port based on availability. | + +### Parameter: `name` + +The name of the NAT rule. + +- Required: Yes +- Type: string + +### Parameter: `virtualNetworkGatewayName` + +The name of the parent Virtual Network Gateway this NAT rule is associated with. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `externalMappings` + +An address prefix range of destination IPs on the outside network that source IPs will be mapped to. In other words, your post-NAT address prefix range. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `internalMappings` + +An address prefix range of source IPs on the inside network that will be mapped to a set of external IPs. In other words, your pre-NAT address prefix range. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `ipConfigurationId` + +A NAT rule must be configured to a specific Virtual Network Gateway instance. This is applicable to Dynamic NAT only. Static NAT rules are automatically applied to both Virtual Network Gateway instances. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `mode` + +The type of NAT rule for Virtual Network NAT. IngressSnat mode (also known as Ingress Source NAT) is applicable to traffic entering the Azure hub's site-to-site Virtual Network gateway. EgressSnat mode (also known as Egress Source NAT) is applicable to traffic leaving the Azure hub's Site-to-site Virtual Network gateway. + +- Required: No +- Type: string +- Default: `''` +- Allowed: + ```Bicep + [ + '' + 'EgressSnat' + 'IngressSnat' + ] + ``` + +### Parameter: `type` + +The type of NAT rule for Virtual Network NAT. Static one-to-one NAT establishes a one-to-one relationship between an internal address and an external address while Dynamic NAT assigns an IP and port based on availability. + +- Required: No +- Type: string +- Default: `''` +- Allowed: + ```Bicep + [ + '' + 'Dynamic' + 'Static' + ] + ``` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the NAT rule. | +| `resourceGroupName` | string | The name of the resource group the NAT rule was deployed into. | +| `resourceId` | string | The resource ID of the NAT rule. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/network/virtual-network-gateway/nat-rule/main.bicep b/avm/res/network/virtual-network-gateway/nat-rule/main.bicep new file mode 100644 index 0000000000..5134050345 --- /dev/null +++ b/avm/res/network/virtual-network-gateway/nat-rule/main.bicep @@ -0,0 +1,59 @@ +metadata name = 'VPN Gateway NAT Rules' +metadata description = 'This module deploys a Virtual Network Gateway NAT Rule.' +metadata owner = 'Azure/module-maintainers' + +@description('Required. The name of the NAT rule.') +param name string + +@description('Conditional. The name of the parent Virtual Network Gateway this NAT rule is associated with. Required if the template is used in a standalone deployment.') +param virtualNetworkGatewayName string + +@description('Optional. An address prefix range of destination IPs on the outside network that source IPs will be mapped to. In other words, your post-NAT address prefix range.') +param externalMappings array = [] + +@description('Optional. An address prefix range of source IPs on the inside network that will be mapped to a set of external IPs. In other words, your pre-NAT address prefix range.') +param internalMappings array = [] + +@description('Optional. A NAT rule must be configured to a specific Virtual Network Gateway instance. This is applicable to Dynamic NAT only. Static NAT rules are automatically applied to both Virtual Network Gateway instances.') +param ipConfigurationId string = '' + +@description('Optional. The type of NAT rule for Virtual Network NAT. IngressSnat mode (also known as Ingress Source NAT) is applicable to traffic entering the Azure hub\'s site-to-site Virtual Network gateway. EgressSnat mode (also known as Egress Source NAT) is applicable to traffic leaving the Azure hub\'s Site-to-site Virtual Network gateway.') +@allowed([ + '' + 'EgressSnat' + 'IngressSnat' +]) +param mode string = '' + +@description('Optional. The type of NAT rule for Virtual Network NAT. Static one-to-one NAT establishes a one-to-one relationship between an internal address and an external address while Dynamic NAT assigns an IP and port based on availability.') +@allowed([ + '' + 'Dynamic' + 'Static' +]) +param type string = '' + +resource virtualNetworkGateway 'Microsoft.Network/virtualNetworkGateways@2023-04-01' existing = { + name: virtualNetworkGatewayName +} + +resource natRule 'Microsoft.Network/virtualNetworkGateways/natRules@2023-04-01' = { + name: name + parent: virtualNetworkGateway + properties: { + externalMappings: externalMappings + internalMappings: internalMappings + ipConfigurationId: !empty(ipConfigurationId) ? ipConfigurationId : null + mode: !empty(mode) ? any(mode) : null + type: !empty(type) ? any(type) : null + } +} + +@description('The name of the NAT rule.') +output name string = natRule.name + +@description('The resource ID of the NAT rule.') +output resourceId string = natRule.id + +@description('The name of the resource group the NAT rule was deployed into.') +output resourceGroupName string = resourceGroup().name diff --git a/avm/res/network/virtual-network-gateway/nat-rule/main.json b/avm/res/network/virtual-network-gateway/nat-rule/main.json new file mode 100644 index 0000000000..e0b660bbef --- /dev/null +++ b/avm/res/network/virtual-network-gateway/nat-rule/main.json @@ -0,0 +1,110 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "3164103777824557279" + }, + "name": "VPN Gateway NAT Rules", + "description": "This module deploys a Virtual Network Gateway NAT Rule.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the NAT rule." + } + }, + "virtualNetworkGatewayName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Virtual Network Gateway this NAT rule is associated with. Required if the template is used in a standalone deployment." + } + }, + "externalMappings": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. An address prefix range of destination IPs on the outside network that source IPs will be mapped to. In other words, your post-NAT address prefix range." + } + }, + "internalMappings": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. An address prefix range of source IPs on the inside network that will be mapped to a set of external IPs. In other words, your pre-NAT address prefix range." + } + }, + "ipConfigurationId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. A NAT rule must be configured to a specific Virtual Network Gateway instance. This is applicable to Dynamic NAT only. Static NAT rules are automatically applied to both Virtual Network Gateway instances." + } + }, + "mode": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "", + "EgressSnat", + "IngressSnat" + ], + "metadata": { + "description": "Optional. The type of NAT rule for Virtual Network NAT. IngressSnat mode (also known as Ingress Source NAT) is applicable to traffic entering the Azure hub's site-to-site Virtual Network gateway. EgressSnat mode (also known as Egress Source NAT) is applicable to traffic leaving the Azure hub's Site-to-site Virtual Network gateway." + } + }, + "type": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "", + "Dynamic", + "Static" + ], + "metadata": { + "description": "Optional. The type of NAT rule for Virtual Network NAT. Static one-to-one NAT establishes a one-to-one relationship between an internal address and an external address while Dynamic NAT assigns an IP and port based on availability." + } + } + }, + "resources": [ + { + "type": "Microsoft.Network/virtualNetworkGateways/natRules", + "apiVersion": "2023-04-01", + "name": "[format('{0}/{1}', parameters('virtualNetworkGatewayName'), parameters('name'))]", + "properties": { + "externalMappings": "[parameters('externalMappings')]", + "internalMappings": "[parameters('internalMappings')]", + "ipConfigurationId": "[if(not(empty(parameters('ipConfigurationId'))), parameters('ipConfigurationId'), null())]", + "mode": "[if(not(empty(parameters('mode'))), parameters('mode'), null())]", + "type": "[if(not(empty(parameters('type'))), parameters('type'), null())]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the NAT rule." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the NAT rule." + }, + "value": "[resourceId('Microsoft.Network/virtualNetworkGateways/natRules', parameters('virtualNetworkGatewayName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the NAT rule was deployed into." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/network/virtual-network-gateway/tests/e2e/aadvpn/dependencies.bicep b/avm/res/network/virtual-network-gateway/tests/e2e/aadvpn/dependencies.bicep new file mode 100644 index 0000000000..b801da63fd --- /dev/null +++ b/avm/res/network/virtual-network-gateway/tests/e2e/aadvpn/dependencies.bicep @@ -0,0 +1,31 @@ +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +var addressPrefix = '10.0.0.0/16' + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + addressPrefix + ] + } + subnets: [ + { + name: 'GatewaySubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 16, 0) + } + } + ] + } +} + +@description('The resource ID of the created Virtual Network.') +output vnetResourceId string = virtualNetwork.id + diff --git a/avm/res/network/virtual-network-gateway/tests/e2e/aadvpn/main.test.bicep b/avm/res/network/virtual-network-gateway/tests/e2e/aadvpn/main.test.bicep new file mode 100644 index 0000000000..9fdee33d7e --- /dev/null +++ b/avm/res/network/virtual-network-gateway/tests/e2e/aadvpn/main.test.bicep @@ -0,0 +1,85 @@ +targetScope = 'subscription' + +metadata name = 'AAD-VPN' +metadata description = 'This instance deploys the module with the AAD set of required parameters.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-network.virtualnetworkgateways-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'nvngavpn' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +#disable-next-line no-hardcoded-location // Just a value to avoid ongoing capacity challenges +var tempLocation = 'francecentral' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + location: tempLocation + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + } +} + + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + location: tempLocation + name: '${namePrefix}${serviceShort}001' + skuName: 'VpnGw2AZ' + gatewayType: 'Vpn' + vNetResourceId: nestedDependencies.outputs.vnetResourceId + activeActive: false + domainNameLabel: [ + '${namePrefix}-dm-${serviceShort}' + ] + publicIpZones: [ + '1' + '2' + '3' + ] + vpnClientAadConfiguration: { + // The Application ID of the "Azure VPN" Azure AD Enterprise App for Azure Public + aadAudience: '41b23e61-6c1e-4545-b367-cd054e0ed4b4' + aadIssuer: 'https://sts.windows.net/${tenant().tenantId}/' + aadTenant: '${environment().authentication.loginEndpoint}/${tenant().tenantId}/' + vpnAuthenticationTypes: [ + 'AAD' + ] + vpnClientProtocols: [ + 'OpenVPN' + ] + } + vpnType: 'RouteBased' + } +}] + diff --git a/avm/res/network/virtual-network-gateway/tests/e2e/defaults/dependencies.bicep b/avm/res/network/virtual-network-gateway/tests/e2e/defaults/dependencies.bicep new file mode 100644 index 0000000000..c3aebf111c --- /dev/null +++ b/avm/res/network/virtual-network-gateway/tests/e2e/defaults/dependencies.bicep @@ -0,0 +1,49 @@ +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Required. The name of the Local Network Gateway to create.') +param localNetworkGatewayName string + +var addressPrefix = '10.0.0.0/16' + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + addressPrefix + ] + } + subnets: [ + { + name: 'GatewaySubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 16, 0) + } + } + ] + } +} + +resource localNetworkGateway 'Microsoft.Network/localNetworkGateways@2023-04-01' = { + name: localNetworkGatewayName + location: location + properties: { + gatewayIpAddress: '100.100.100.100' + localNetworkAddressSpace: { + addressPrefixes: [ + '192.168.0.0/24' + ] + } + } +} + +@description('The resource ID of the created Virtual Network.') +output vnetResourceId string = virtualNetwork.id + +@description('The resource ID of the created Local Network Gateway.') +output localNetworkGatewayResourceId string = localNetworkGateway.id diff --git a/avm/res/network/virtual-network-gateway/tests/e2e/defaults/main.test.bicep b/avm/res/network/virtual-network-gateway/tests/e2e/defaults/main.test.bicep new file mode 100644 index 0000000000..2233ca8739 --- /dev/null +++ b/avm/res/network/virtual-network-gateway/tests/e2e/defaults/main.test.bicep @@ -0,0 +1,68 @@ +targetScope = 'subscription' + +metadata name = 'Using only defaults' +metadata description = 'This instance deploys the module with the minimum set of required parameters.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-network.virtualnetworkgateways-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'nvgmin' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +#disable-next-line no-hardcoded-location // Just a value to avoid ongoing capacity challenges +var tempLocation = 'francecentral' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= + +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + location: tempLocation + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + localNetworkGatewayName: 'dep-${namePrefix}-lng-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + location: tempLocation + name: '${namePrefix}${serviceShort}001' + skuName: 'VpnGw2AZ' + gatewayType: 'Vpn' + vNetResourceId: nestedDependencies.outputs.vnetResourceId + publicIpZones: [ + '1' + '2' + '3' + ] + } +}] diff --git a/avm/res/network/virtual-network-gateway/tests/e2e/expressRoute/dependencies.bicep b/avm/res/network/virtual-network-gateway/tests/e2e/expressRoute/dependencies.bicep new file mode 100644 index 0000000000..223faddfbd --- /dev/null +++ b/avm/res/network/virtual-network-gateway/tests/e2e/expressRoute/dependencies.bicep @@ -0,0 +1,30 @@ +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +var addressPrefix = '10.0.0.0/16' + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + addressPrefix + ] + } + subnets: [ + { + name: 'GatewaySubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 16, 0) + } + } + ] + } +} + +@description('The resource ID of the created Virtual Network.') +output vnetResourceId string = virtualNetwork.id diff --git a/avm/res/network/virtual-network-gateway/tests/e2e/expressRoute/main.test.bicep b/avm/res/network/virtual-network-gateway/tests/e2e/expressRoute/main.test.bicep new file mode 100644 index 0000000000..d65c528f1f --- /dev/null +++ b/avm/res/network/virtual-network-gateway/tests/e2e/expressRoute/main.test.bicep @@ -0,0 +1,70 @@ +targetScope = 'subscription' + +metadata name = 'ExpressRoute' +metadata description = 'This instance deploys the module with the ExpressRoute set of required parameters.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-network.virtualnetworkgateways-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'nvger' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +#disable-next-line no-hardcoded-location // Just a value to avoid ongoing capacity challenges +var tempLocation = 'francecentral' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + location: tempLocation + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + location: tempLocation + name: '${namePrefix}${serviceShort}001' + skuName: 'ErGw1AZ' + gatewayType: 'ExpressRoute' + vNetResourceId: nestedDependencies.outputs.vnetResourceId + domainNameLabel: [ + '${namePrefix}-dm-${serviceShort}' + ] + gatewayPipName: '${namePrefix}-pip-${serviceShort}' + publicIpZones: [ + '1' + '2' + '3' + ] + } +}] diff --git a/avm/res/network/virtual-network-gateway/tests/e2e/max/dependencies.bicep b/avm/res/network/virtual-network-gateway/tests/e2e/max/dependencies.bicep new file mode 100644 index 0000000000..ab4fdf887a --- /dev/null +++ b/avm/res/network/virtual-network-gateway/tests/e2e/max/dependencies.bicep @@ -0,0 +1,60 @@ +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +@description('Required. The name of the Local Network Gateway to create.') +param localNetworkGatewayName string + +var addressPrefix = '10.0.0.0/16' + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + addressPrefix + ] + } + subnets: [ + { + name: 'GatewaySubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 16, 0) + } + } + ] + } +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +resource localNetworkGateway 'Microsoft.Network/localNetworkGateways@2023-04-01' = { + name: localNetworkGatewayName + location: location + properties: { + gatewayIpAddress: '100.100.100.100' + localNetworkAddressSpace: { + addressPrefixes: [ + '192.168.0.0/24' + ] + } + } +} + +@description('The resource ID of the created Virtual Network.') +output vnetResourceId string = virtualNetwork.id + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId + +@description('The resource ID of the created Local Network Gateway.') +output localNetworkGatewayResourceId string = localNetworkGateway.id diff --git a/avm/res/network/virtual-network-gateway/tests/e2e/max/main.test.bicep b/avm/res/network/virtual-network-gateway/tests/e2e/max/main.test.bicep new file mode 100644 index 0000000000..a89a82fc36 --- /dev/null +++ b/avm/res/network/virtual-network-gateway/tests/e2e/max/main.test.bicep @@ -0,0 +1,168 @@ +targetScope = 'subscription' + +metadata name = 'Using large parameter set' +metadata description = 'This instance deploys the module with most of its features enabled.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-network.virtualnetworkgateways-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'nvgmax' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +#disable-next-line no-hardcoded-location // Just a value to avoid ongoing capacity challenges +var tempLocation = 'francecentral' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + location: tempLocation + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + localNetworkGatewayName: 'dep-${namePrefix}-lng-${serviceShort}' + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-diagnosticDependencies' + params: { + storageAccountName: 'dep${namePrefix}diasa${serviceShort}01' + logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' + eventHubNamespaceEventHubName: 'dep-${namePrefix}-evh-${serviceShort}' + eventHubNamespaceName: 'dep-${namePrefix}-evhns-${serviceShort}' + location: tempLocation + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + location: tempLocation + name: '${namePrefix}${serviceShort}001' + vpnGatewayGeneration: 'Generation2' + skuName: 'VpnGw2AZ' + gatewayType: 'Vpn' + vNetResourceId: nestedDependencies.outputs.vnetResourceId + activeActive: true + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + domainNameLabel: [ + '${namePrefix}-dm-${serviceShort}' + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + publicIpZones: [ + '1' + '2' + '3' + ] + roleAssignments: [ + { + roleDefinitionIdOrName: 'Owner' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + { + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + { + roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + vpnType: 'RouteBased' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + enablePrivateIpAddress: true + gatewayDefaultSiteLocalNetworkGatewayId: nestedDependencies.outputs.localNetworkGatewayResourceId + disableIPSecReplayProtection: true + allowRemoteVnetTraffic: true + natRules: [ + { + name: 'nat-rule-1-static-IngressSnat' + type: 'Static' + mode: 'IngressSnat' + internalMappings: [ + { + addressSpace: '10.100.0.0/24' + portRange: '100' + } + ] + externalMappings: [ + { + addressSpace: '192.168.0.0/24' + portRange: '100' + } + ] + } + { + name: 'nat-rule-2-dynamic-EgressSnat' + type: 'Dynamic' + mode: 'EgressSnat' + internalMappings: [ + { + addressSpace: '172.16.0.0/26' + } + ] + externalMappings: [ + { + addressSpace: '10.200.0.0/26' + } + ] + } + ] + enableBgpRouteTranslationForNat: true + } +}] + diff --git a/avm/res/network/virtual-network-gateway/tests/e2e/vpn/dependencies.bicep b/avm/res/network/virtual-network-gateway/tests/e2e/vpn/dependencies.bicep new file mode 100644 index 0000000000..c3aebf111c --- /dev/null +++ b/avm/res/network/virtual-network-gateway/tests/e2e/vpn/dependencies.bicep @@ -0,0 +1,49 @@ +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Required. The name of the Local Network Gateway to create.') +param localNetworkGatewayName string + +var addressPrefix = '10.0.0.0/16' + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + addressPrefix + ] + } + subnets: [ + { + name: 'GatewaySubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 16, 0) + } + } + ] + } +} + +resource localNetworkGateway 'Microsoft.Network/localNetworkGateways@2023-04-01' = { + name: localNetworkGatewayName + location: location + properties: { + gatewayIpAddress: '100.100.100.100' + localNetworkAddressSpace: { + addressPrefixes: [ + '192.168.0.0/24' + ] + } + } +} + +@description('The resource ID of the created Virtual Network.') +output vnetResourceId string = virtualNetwork.id + +@description('The resource ID of the created Local Network Gateway.') +output localNetworkGatewayResourceId string = localNetworkGateway.id diff --git a/avm/res/network/virtual-network-gateway/tests/e2e/vpn/main.test.bicep b/avm/res/network/virtual-network-gateway/tests/e2e/vpn/main.test.bicep new file mode 100644 index 0000000000..f99d5256e2 --- /dev/null +++ b/avm/res/network/virtual-network-gateway/tests/e2e/vpn/main.test.bicep @@ -0,0 +1,79 @@ +targetScope = 'subscription' + +metadata name = 'VPN' +metadata description = 'This instance deploys the module with the VPN set of required parameters.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-network.virtualnetworkgateways-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'nvgvpn' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +#disable-next-line no-hardcoded-location // Just a value to avoid ongoing capacity challenges +var tempLocation = 'francecentral' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + location: tempLocation + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + localNetworkGatewayName: 'dep-${namePrefix}-lng-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + location: tempLocation + name: '${namePrefix}${serviceShort}001' + vpnGatewayGeneration: 'Generation2' + skuName: 'VpnGw2AZ' + gatewayType: 'Vpn' + vNetResourceId: nestedDependencies.outputs.vnetResourceId + activeActive: true + domainNameLabel: [ + '${namePrefix}-dm-${serviceShort}' + ] + publicIpZones: [ + '1' + '2' + '3' + ] + vpnType: 'RouteBased' + enablePrivateIpAddress: true + gatewayDefaultSiteLocalNetworkGatewayId: nestedDependencies.outputs.localNetworkGatewayResourceId + disableIPSecReplayProtection: true + allowRemoteVnetTraffic: true + enableBgpRouteTranslationForNat: true + } +}] + diff --git a/avm/res/network/virtual-network-gateway/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/network/virtual-network-gateway/tests/e2e/waf-aligned/dependencies.bicep new file mode 100644 index 0000000000..c3aebf111c --- /dev/null +++ b/avm/res/network/virtual-network-gateway/tests/e2e/waf-aligned/dependencies.bicep @@ -0,0 +1,49 @@ +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Required. The name of the Local Network Gateway to create.') +param localNetworkGatewayName string + +var addressPrefix = '10.0.0.0/16' + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + addressPrefix + ] + } + subnets: [ + { + name: 'GatewaySubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 16, 0) + } + } + ] + } +} + +resource localNetworkGateway 'Microsoft.Network/localNetworkGateways@2023-04-01' = { + name: localNetworkGatewayName + location: location + properties: { + gatewayIpAddress: '100.100.100.100' + localNetworkAddressSpace: { + addressPrefixes: [ + '192.168.0.0/24' + ] + } + } +} + +@description('The resource ID of the created Virtual Network.') +output vnetResourceId string = virtualNetwork.id + +@description('The resource ID of the created Local Network Gateway.') +output localNetworkGatewayResourceId string = localNetworkGateway.id diff --git a/avm/res/network/virtual-network-gateway/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/virtual-network-gateway/tests/e2e/waf-aligned/main.test.bicep new file mode 100644 index 0000000000..a79b6d0a5e --- /dev/null +++ b/avm/res/network/virtual-network-gateway/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,149 @@ +targetScope = 'subscription' + +metadata name = 'WAF-aligned' +metadata description = 'This instance deploys the module in alignment with the best-practices of the Azure Well-Architected Framework.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-network.virtualnetworkgateways-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'nvgmwaf' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +#disable-next-line no-hardcoded-location // Just a value to avoid ongoing capacity challenges +var tempLocation = 'francecentral' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + location: tempLocation + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + localNetworkGatewayName: 'dep-${namePrefix}-lng-${serviceShort}' + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-diagnosticDependencies' + params: { + storageAccountName: 'dep${namePrefix}diasa${serviceShort}01' + logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' + eventHubNamespaceEventHubName: 'dep-${namePrefix}-evh-${serviceShort}' + eventHubNamespaceName: 'dep-${namePrefix}-evhns-${serviceShort}' + location: tempLocation + } +} +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + location: tempLocation + name: '${namePrefix}${serviceShort}001' + vpnGatewayGeneration: 'Generation2' + skuName: 'VpnGw2AZ' + gatewayType: 'Vpn' + vNetResourceId: nestedDependencies.outputs.vnetResourceId + activeActive: true + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + domainNameLabel: [ + '${namePrefix}-dm-${serviceShort}' + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + publicIpZones: [ + '1' + '2' + '3' + ] + vpnType: 'RouteBased' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + enablePrivateIpAddress: true + gatewayDefaultSiteLocalNetworkGatewayId: nestedDependencies.outputs.localNetworkGatewayResourceId + disableIPSecReplayProtection: true + allowRemoteVnetTraffic: true + natRules: [ + { + name: 'nat-rule-1-static-IngressSnat' + type: 'Static' + mode: 'IngressSnat' + internalMappings: [ + { + addressSpace: '10.100.0.0/24' + portRange: '100' + } + ] + externalMappings: [ + { + addressSpace: '192.168.0.0/24' + portRange: '100' + } + ] + } + { + name: 'nat-rule-2-dynamic-EgressSnat' + type: 'Dynamic' + mode: 'EgressSnat' + internalMappings: [ + { + addressSpace: '172.16.0.0/26' + } + ] + externalMappings: [ + { + addressSpace: '10.200.0.0/26' + } + ] + } + ] + enableBgpRouteTranslationForNat: true + } +}] + diff --git a/avm/res/network/virtual-network-gateway/version.json b/avm/res/network/virtual-network-gateway/version.json new file mode 100644 index 0000000000..8def869ede --- /dev/null +++ b/avm/res/network/virtual-network-gateway/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.1", + "pathFilters": [ + "./main.json" + ] +}