diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 07dc4dad77..45e53dbfc7 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -129,6 +129,7 @@ /avm/res/network/network-manager/ @Azure/avm-res-network-networkmanager-module-owners-bicep @Azure/avm-module-reviewers-bicep /avm/res/network/network-security-group/ @Azure/avm-res-network-networksecuritygroup-module-owners-bicep @Azure/avm-module-reviewers-bicep /avm/res/network/network-watcher/ @Azure/avm-res-network-networkwatcher-module-owners-bicep @Azure/avm-module-reviewers-bicep +/avm/res/network/p2s-vpn-gateway/ @Azure/avm-res-network-p2svpngateway-module-owners-bicep @Azure/avm-module-reviewers-bicep /avm/res/network/private-dns-zone/ @Azure/avm-res-network-privatednszone-module-owners-bicep @Azure/avm-module-reviewers-bicep /avm/res/network/private-endpoint/ @Azure/avm-res-network-privateendpoint-module-owners-bicep @Azure/avm-module-reviewers-bicep /avm/res/network/private-link-service/ @Azure/avm-res-network-privatelinkservice-module-owners-bicep @Azure/avm-module-reviewers-bicep diff --git a/.github/ISSUE_TEMPLATE/avm_module_issue.yml b/.github/ISSUE_TEMPLATE/avm_module_issue.yml index 7ff72be0e8..87181132dc 100644 --- a/.github/ISSUE_TEMPLATE/avm_module_issue.yml +++ b/.github/ISSUE_TEMPLATE/avm_module_issue.yml @@ -164,6 +164,7 @@ body: - "avm/res/network/network-manager" - "avm/res/network/network-security-group" - "avm/res/network/network-watcher" + - "avm/res/network/p2s-vpn-gateway" - "avm/res/network/private-dns-zone" - "avm/res/network/private-endpoint" - "avm/res/network/private-link-service" diff --git a/.github/workflows/avm.res.network.p2s-vpn-gateway.yml b/.github/workflows/avm.res.network.p2s-vpn-gateway.yml new file mode 100644 index 0000000000..0c828516c1 --- /dev/null +++ b/.github/workflows/avm.res.network.p2s-vpn-gateway.yml @@ -0,0 +1,88 @@ +name: "avm.res.network.p2s-vpn-gateway" + +on: + 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 + customLocation: + type: string + description: "Default location overwrite (e.g., eastus)" + required: false + push: + branches: + - main + paths: + - ".github/actions/templates/avm-**" + - ".github/workflows/avm.template.module.yml" + - ".github/workflows/avm.res.network.p2s-vpn-gateway.yml" + - "avm/res/network/p2s-vpn-gateway/**" + - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/network/p2s-vpn-gateway" + workflowPath: ".github/workflows/avm.res.network.p2s-vpn-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" + permissions: + id-token: write # For OIDC + contents: write # For release tags + 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/p2s-vpn-gateway/README.md b/avm/res/network/p2s-vpn-gateway/README.md new file mode 100644 index 0000000000..8034b210a5 --- /dev/null +++ b/avm/res/network/p2s-vpn-gateway/README.md @@ -0,0 +1,627 @@ +# P2S VPN Gateway `[Microsoft.Network/p2svpnGateways]` + +This module deploys a Virtual Hub P2S Gateway. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Usage examples](#Usage-examples) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [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.Network/p2svpnGateways` | [2024-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2024-01-01/p2svpnGateways) | + +## 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/p2s-vpn-gateway:`. + +- [Using only defaults](#example-1-using-only-defaults) +- [Using only defaults](#example-2-using-only-defaults) +- [WAF-aligned](#example-3-waf-aligned) + +### Example 1: _Using only defaults_ + +This instance deploys the module with the minimum set of required parameters. + + +
+ +via Bicep module + +```bicep +module p2sVpnGateway 'br/public:avm/res/network/p2s-vpn-gateway:' = { + name: 'p2sVpnGatewayDeployment' + params: { + // Required parameters + name: 'vscminp2sVpnGw' + virtualHubId: '' + vpnServerConfigurationId: '' + // Non-required parameters + associatedRouteTableName: 'defaultRouteTable' + location: '' + p2SConnectionConfigurationsName: 'p2sConnectionConfig1' + vpnClientAddressPoolAddressPrefixes: [ + '10.0.2.0/24' + ] + } +} +``` + +
+

+ +

+ +via JSON parameters file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "vscminp2sVpnGw" + }, + "virtualHubId": { + "value": "" + }, + "vpnServerConfigurationId": { + "value": "" + }, + // Non-required parameters + "associatedRouteTableName": { + "value": "defaultRouteTable" + }, + "location": { + "value": "" + }, + "p2SConnectionConfigurationsName": { + "value": "p2sConnectionConfig1" + }, + "vpnClientAddressPoolAddressPrefixes": { + "value": [ + "10.0.2.0/24" + ] + } + } +} +``` + +
+

+ +

+ +via Bicep parameters file + +```bicep-params +using 'br/public:avm/res/network/p2s-vpn-gateway:' + +// Required parameters +param name = 'vscminp2sVpnGw' +param virtualHubId = '' +param vpnServerConfigurationId = '' +// Non-required parameters +param associatedRouteTableName = 'defaultRouteTable' +param location = '' +p2SConnectionConfigurationsName: 'p2sConnectionConfig1' +param vpnClientAddressPoolAddressPrefixes = [ + '10.0.2.0/24' +] +``` + +
+

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

+ +via Bicep module + +```bicep +module p2sVpnGateway 'br/public:avm/res/network/p2s-vpn-gateway:' = { + name: 'p2sVpnGatewayDeployment' + params: { + // Required parameters + name: 'vscmaxp2sVpnGw' + virtualHubId: '' + vpnServerConfigurationId: '' + // Non-required parameters + associatedRouteTableName: 'noneRouteTable' + customDnsServers: [ + '10.50.10.50' + '10.50.50.50' + ] + enableInternetSecurity: false + inboundRouteMapResourceId: '' + isRoutingPreferenceInternet: false + location: '' + outboundRouteMapResourceId: '' + p2SConnectionConfigurationsName: 'p2sConnectionConfig1' + propagatedLabelNames: '' + propagatedRouteTableNames: [ + '' + ] + vpnClientAddressPoolAddressPrefixes: [ + '10.0.2.0/24' + '10.0.3.0/24' + ] + vpnGatewayScaleUnit: 5 + } +} +``` + +
+

+ +

+ +via JSON parameters file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "vscmaxp2sVpnGw" + }, + "virtualHubId": { + "value": "" + }, + "vpnServerConfigurationId": { + "value": "" + }, + // Non-required parameters + "associatedRouteTableName": { + "value": "noneRouteTable" + }, + "customDnsServers": { + "value": [ + "10.50.10.50", + "10.50.50.50" + ] + }, + "enableInternetSecurity": { + "value": false + }, + "inboundRouteMapResourceId": { + "value": "" + }, + "isRoutingPreferenceInternet": { + "value": false + }, + "location": { + "value": "" + }, + "outboundRouteMapResourceId": { + "value": "" + }, + "p2SConnectionConfigurationsName": { + "value": "p2sConnectionConfig1" + }, + "propagatedLabelNames": { + "value": "" + }, + "propagatedRouteTableNames": { + "value": [ + "" + ] + }, + "vpnClientAddressPoolAddressPrefixes": { + "value": [ + "10.0.2.0/24", + "10.0.3.0/24" + ] + }, + "vpnGatewayScaleUnit": { + "value": 5 + } + } +} +``` + +
+

+ +

+ +via Bicep parameters file + +```bicep-params +using 'br/public:avm/res/network/p2s-vpn-gateway:' + +// Required parameters +param name = 'vscmaxp2sVpnGw' +param virtualHubId = '' +param vpnServerConfigurationId = '' +// Non-required parameters +param associatedRouteTableName = 'noneRouteTable' +param customDnsServers = [ + '10.50.10.50' + '10.50.50.50' +] +param enableInternetSecurity = false +param inboundRouteMapResourceId = '' +param isRoutingPreferenceInternet = false +param location = '' +param outboundRouteMapResourceId = '' +p2SConnectionConfigurationsName: 'p2sConnectionConfig1' +param propagatedLabelNames = '' +param propagatedRouteTableNames = [ + '' +] +param vpnClientAddressPoolAddressPrefixes = [ + '10.0.2.0/24' + '10.0.3.0/24' +] +param vpnGatewayScaleUnit = 5 +``` + +
+

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

+ +via Bicep module + +```bicep +module p2sVpnGateway 'br/public:avm/res/network/p2s-vpn-gateway:' = { + name: 'p2sVpnGatewayDeployment' + params: { + // Required parameters + name: 'vscwafp2sVpnGw' + virtualHubId: '' + vpnServerConfigurationId: '' + // Non-required parameters + associatedRouteTableName: 'defaultRouteTable' + enableInternetSecurity: true + isRoutingPreferenceInternet: false + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + p2SConnectionConfigurationsName: 'p2sConnectionConfig1' + tags: { + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + vpnClientAddressPoolAddressPrefixes: [ + '10.0.2.0/24' + ] + } +} +``` + +
+

+ +

+ +via JSON parameters file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "vscwafp2sVpnGw" + }, + "virtualHubId": { + "value": "" + }, + "vpnServerConfigurationId": { + "value": "" + }, + // Non-required parameters + "associatedRouteTableName": { + "value": "defaultRouteTable" + }, + "enableInternetSecurity": { + "value": true + }, + "isRoutingPreferenceInternet": { + "value": false + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "p2SConnectionConfigurationsName": { + "value": "p2sConnectionConfig1" + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "Role": "DeploymentValidation" + } + }, + "vpnClientAddressPoolAddressPrefixes": { + "value": [ + "10.0.2.0/24" + ] + } + } +} +``` + +
+

+ +

+ +via Bicep parameters file + +```bicep-params +using 'br/public:avm/res/network/p2s-vpn-gateway:' + +// Required parameters +param name = 'vscwafp2sVpnGw' +param virtualHubId = '' +param vpnServerConfigurationId = '' +// Non-required parameters +param associatedRouteTableName = 'defaultRouteTable' +param enableInternetSecurity = true +param isRoutingPreferenceInternet = false +param location = '' +param lock = { + kind: 'CanNotDelete' + name: 'myCustomLockName' +} +p2SConnectionConfigurationsName: 'p2sConnectionConfig1' +param tags = { + Environment: 'Non-Prod' + Role: 'DeploymentValidation' +} +param vpnClientAddressPoolAddressPrefixes = [ + '10.0.2.0/24' +] +``` + +
+

+ +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`location`](#parameter-location) | string | Location where all resources will be created. | +| [`name`](#parameter-name) | string | The name of the P2S VPN Gateway. | +| [`p2SConnectionConfigurationsName`](#parameter-p2sconnectionconfigurationsname) | string | The name of the P2S Connection Configuration. | +| [`virtualHubId`](#parameter-virtualhubid) | string | The resource ID of the gateways virtual hub. | +| [`vpnClientAddressPoolAddressPrefixes`](#parameter-vpnclientaddresspooladdressprefixes) | array | The address prefixes for the VPN Client Address Pool. | +| [`vpnServerConfigurationId`](#parameter-vpnserverconfigurationid) | string | The resource ID of the VPN Server Configuration. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`associatedRouteTableName`](#parameter-associatedroutetablename) | string | The name of the associated route table. Required if deploying in a Secure Virtual Hub; cannot be a custom route table. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`customDnsServers`](#parameter-customdnsservers) | array | The custom DNS servers for the P2S VPN Gateway. | +| [`enableInternetSecurity`](#parameter-enableinternetsecurity) | bool | Enable/Disable Internet Security; "Propagate Default Route". | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | +| [`inboundRouteMapResourceId`](#parameter-inboundroutemapresourceid) | string | The Resource ID of the inbound route map. | +| [`isRoutingPreferenceInternet`](#parameter-isroutingpreferenceinternet) | bool | The routing preference for the P2S VPN Gateway, Internet or Microsoft network. | +| [`lock`](#parameter-lock) | object | The lock settings of the service. | +| [`outboundRouteMapResourceId`](#parameter-outboundroutemapresourceid) | string | The Resource ID of the outbound route map. | +| [`propagatedLabelNames`](#parameter-propagatedlabelnames) | array | The Labels to propagate routes to. | +| [`propagatedRouteTableNames`](#parameter-propagatedroutetablenames) | array | The names of the route tables to propagate to the P2S VPN Gateway. | +| [`tags`](#parameter-tags) | object | Tags of the resource. | +| [`vpnGatewayScaleUnit`](#parameter-vpngatewayscaleunit) | int | The scale unit of the VPN Gateway. | + +### Parameter: `location` + +Location where all resources will be created. + +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + +### Parameter: `name` + +The name of the P2S VPN Gateway. + +- Required: Yes +- Type: string + +### Parameter: `p2SConnectionConfigurationsName` + +The name of the P2S Connection Configuration. + +- Required: No +- Type: string + +### Parameter: `virtualHubId` + +The resource ID of the gateways virtual hub. + +- Required: Yes +- Type: string + +### Parameter: `vpnClientAddressPoolAddressPrefixes` + +The address prefixes for the VPN Client Address Pool. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `vpnServerConfigurationId` + +The resource ID of the VPN Server Configuration. + +- Required: Yes +- Type: string + +### Parameter: `associatedRouteTableName` + +The name of the associated route table. Required if deploying in a Secure Virtual Hub; cannot be a custom route table. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'defaultRouteTable' + 'noneRouteTable' + ] + ``` + +### Parameter: `customDnsServers` + +The custom DNS servers for the P2S VPN Gateway. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `enableInternetSecurity` + +Enable/Disable Internet Security; "Propagate Default Route". + +- Required: No +- Type: bool + +### Parameter: `enableTelemetry` + +Enable/Disable usage telemetry for module. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `inboundRouteMapResourceId` + +The Resource ID of the inbound route map. + +- Required: No +- Type: string + +### Parameter: `isRoutingPreferenceInternet` + +The routing preference for the P2S VPN Gateway, Internet or Microsoft network. + +- Required: No +- Type: bool + +### 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: `outboundRouteMapResourceId` + +The Resource ID of the outbound route map. + +- Required: No +- Type: string + +### Parameter: `propagatedLabelNames` + +The Labels to propagate routes to. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `propagatedRouteTableNames` + +The names of the route tables to propagate to the P2S VPN Gateway. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `tags` + +Tags of the resource. + +- Required: No +- Type: object + +### Parameter: `vpnGatewayScaleUnit` + +The scale unit of the VPN Gateway. + +- Required: No +- Type: int + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the user VPN configuration. | +| `resourceGroupName` | string | The name of the resource group the user VPN configuration was deployed into. | +| `resourceId` | string | The resource ID of the user VPN configuration. | + +## 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/p2s-vpn-gateway/main.bicep b/avm/res/network/p2s-vpn-gateway/main.bicep new file mode 100644 index 0000000000..2fe5686ba1 --- /dev/null +++ b/avm/res/network/p2s-vpn-gateway/main.bicep @@ -0,0 +1,192 @@ +metadata name = 'P2S VPN Gateway' +metadata description = 'This module deploys a Virtual Hub P2S Gateway.' +metadata owner = 'Azure/module-maintainers' + +@description('Required. The name of the P2S VPN Gateway.') +param name string + +@description('Required. Location where all resources will be created.') +param location string = resourceGroup().location + +@allowed([ + 'noneRouteTable' + 'defaultRouteTable' +]) +@description('Conditional. The name of the associated route table. Required if deploying in a Secure Virtual Hub; cannot be a custom route table.') +param associatedRouteTableName string? + +@description('Optional. The names of the route tables to propagate to the P2S VPN Gateway.') +param propagatedRouteTableNames array = [] + +@description('Optional. The custom DNS servers for the P2S VPN Gateway.') +param customDnsServers array = [] + +@description('Optional. The routing preference for the P2S VPN Gateway, Internet or Microsoft network.') +param isRoutingPreferenceInternet bool? + +@description('Required. The name of the P2S Connection Configuration.') +param p2SConnectionConfigurationsName string? + +@description('Optional. Enable/Disable Internet Security; "Propagate Default Route".') +param enableInternetSecurity bool? + +@description('Optional. The Resource ID of the inbound route map.') +param inboundRouteMapResourceId string? + +@description('Optional. The Resource ID of the outbound route map.') +param outboundRouteMapResourceId string? + +@description('Optional. The Labels to propagate routes to.') +param propagatedLabelNames array = [] + +@description('Required. The address prefixes for the VPN Client Address Pool.') +param vpnClientAddressPoolAddressPrefixes array = [] + +@description('Required. The resource ID of the gateways virtual hub.') +param virtualHubId string + +@description('Optional. The scale unit of the VPN Gateway.') +param vpnGatewayScaleUnit int? + +@description('Required. The resource ID of the VPN Server Configuration.') +param vpnServerConfigurationId string + +@description('Optional. Tags of the resource.') +param tags object? + +@description('Optional. The lock settings of the service.') +param lock lockType + +@description('Optional. Enable/Disable usage telemetry for module.') +param enableTelemetry bool = true + +// =============== // + +@description('Extract the virtual hub name from the virtual hub ID.') +var virtualHubName = split(virtualHubId, '/')[8] + +// ============== // + +#disable-next-line no-deployments-resources +resource avmTelemetry 'Microsoft.Resources/deployments@2024-03-01' = if (enableTelemetry) { + name: take( + '46d3xbcp.res.network-p2svpngateway.${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' + } + } + } + } +} + +resource p2sVpnGateway 'Microsoft.Network/p2svpnGateways@2024-01-01' = { + name: name + location: location + tags: tags + properties: { + customDnsServers: customDnsServers + isRoutingPreferenceInternet: isRoutingPreferenceInternet + p2SConnectionConfigurations: [ + { + name: p2SConnectionConfigurationsName + properties: { + enableInternetSecurity: enableInternetSecurity + routingConfiguration: { + associatedRouteTable: { + id: resourceId('Microsoft.Network/virtualHubs/hubRouteTables','${virtualHubName}','${associatedRouteTableName}') + } + inboundRouteMap: (!empty(inboundRouteMapResourceId)) ? { + id: inboundRouteMapResourceId + } : null + outboundRouteMap: (!empty(outboundRouteMapResourceId)) ? { + id: outboundRouteMapResourceId + } : null + propagatedRouteTables: { + ids: [ + for table in (propagatedRouteTableNames): { + id: resourceId('Microsoft.Network/virtualHubs/hubRouteTables','${virtualHubName}','${table}') + } + ] + labels: propagatedLabelNames + } + } + vpnClientAddressPool: { + addressPrefixes: vpnClientAddressPoolAddressPrefixes + } + } + } + ] + virtualHub: { + id: virtualHubId + } + vpnGatewayScaleUnit: vpnGatewayScaleUnit + vpnServerConfiguration: { + id: vpnServerConfigurationId + } + } +} + +resource vpnGateway_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: p2sVpnGateway +} + +@description('The name of the user VPN configuration.') +output name string = p2sVpnGateway.name + +@description('The resource ID of the user VPN configuration.') +output resourceId string = p2sVpnGateway.id + +@description('The name of the resource group the user VPN configuration was deployed into.') +output resourceGroupName string = resourceGroup().name + +@description('The location the resource was deployed into.') +output location string = p2sVpnGateway.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 vnetRoutesStaticRoutesType = { + staticRoutes: [ + { + @description('Optional. The address prefixes of the static route.') + addressPrefixes: array? + + @description('Optional. The name of the static route.') + name: string? + + @description('Optional. The next hop IP of the static route.') + nextHopIpAddress: string? + } + ] + staticRoutesConfig: { + @description('Optional. ') + vnetLocalRouteOverrideCriteria: string? + } +} + diff --git a/avm/res/network/p2s-vpn-gateway/main.json b/avm/res/network/p2s-vpn-gateway/main.json new file mode 100644 index 0000000000..96af81c65a --- /dev/null +++ b/avm/res/network/p2s-vpn-gateway/main.json @@ -0,0 +1,336 @@ +{ + "$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.31.34.60546", + "templateHash": "91504486809439588" + }, + "name": "P2S VPN Gateway", + "description": "This module deploys a Virtual Hub P2S 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 + }, + "vnetRoutesStaticRoutesType": { + "type": "object", + "properties": { + "staticRoutes": { + "type": "array", + "prefixItems": [ + { + "type": "object", + "properties": { + "addressPrefixes": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The address prefixes of the static route." + } + }, + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the static route." + } + }, + "nextHopIpAddress": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The next hop IP of the static route." + } + } + } + } + ], + "items": false + }, + "staticRoutesConfig": { + "type": "object", + "properties": { + "vnetLocalRouteOverrideCriteria": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. " + } + } + } + } + } + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the P2S VPN Gateway." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Required. Location where all resources will be created." + } + }, + "associatedRouteTableName": { + "type": "string", + "nullable": true, + "allowedValues": [ + "noneRouteTable", + "defaultRouteTable" + ], + "metadata": { + "description": "Conditional. The name of the associated route table. Required if deploying in a Secure Virtual Hub; cannot be a custom route table." + } + }, + "propagatedRouteTableNames": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The names of the route tables to propagate to the P2S VPN Gateway." + } + }, + "customDnsServers": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The custom DNS servers for the P2S VPN Gateway." + } + }, + "isRoutingPreferenceInternet": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. The routing preference for the P2S VPN Gateway, Internet or Microsoft network." + } + }, + "p2SConnectionConfigurationsName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Required. The name of the P2S Connection Configuration." + } + }, + "enableInternetSecurity": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable/Disable Internet Security; \"Propagate Default Route\"." + } + }, + "inboundRouteMapResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource ID of the inbound route map." + } + }, + "outboundRouteMapResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource ID of the outbound route map." + } + }, + "propagatedLabelNames": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The Labels to propagate routes to." + } + }, + "vpnClientAddressPoolAddressPrefixes": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Required. The address prefixes for the VPN Client Address Pool." + } + }, + "virtualHubId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the gateways virtual hub." + } + }, + "vpnGatewayScaleUnit": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The scale unit of the VPN Gateway." + } + }, + "vpnServerConfigurationId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the VPN Server Configuration." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "virtualHubName": "[split(parameters('virtualHubId'), '/')[8]]" + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[take(format('46d3xbcp.res.network-p2svpngateway.{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" + } + } + } + } + }, + "p2sVpnGateway": { + "type": "Microsoft.Network/p2svpnGateways", + "apiVersion": "2024-01-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "customDnsServers": "[parameters('customDnsServers')]", + "isRoutingPreferenceInternet": "[parameters('isRoutingPreferenceInternet')]", + "p2SConnectionConfigurations": [ + { + "name": "[parameters('p2SConnectionConfigurationsName')]", + "properties": { + "enableInternetSecurity": "[parameters('enableInternetSecurity')]", + "routingConfiguration": { + "associatedRouteTable": { + "id": "[resourceId('Microsoft.Network/virtualHubs/hubRouteTables', format('{0}', variables('virtualHubName')), format('{0}', parameters('associatedRouteTableName')))]" + }, + "inboundRouteMap": "[if(not(empty(parameters('inboundRouteMapResourceId'))), createObject('id', parameters('inboundRouteMapResourceId')), null())]", + "outboundRouteMap": "[if(not(empty(parameters('outboundRouteMapResourceId'))), createObject('id', parameters('outboundRouteMapResourceId')), null())]", + "propagatedRouteTables": { + "copy": [ + { + "name": "ids", + "count": "[length(parameters('propagatedRouteTableNames'))]", + "input": { + "id": "[resourceId('Microsoft.Network/virtualHubs/hubRouteTables', format('{0}', variables('virtualHubName')), format('{0}', parameters('propagatedRouteTableNames')[copyIndex('ids')]))]" + } + } + ], + "labels": "[parameters('propagatedLabelNames')]" + } + }, + "vpnClientAddressPool": { + "addressPrefixes": "[parameters('vpnClientAddressPoolAddressPrefixes')]" + } + } + } + ], + "virtualHub": { + "id": "[parameters('virtualHubId')]" + }, + "vpnGatewayScaleUnit": "[parameters('vpnGatewayScaleUnit')]", + "vpnServerConfiguration": { + "id": "[parameters('vpnServerConfigurationId')]" + } + } + }, + "vpnGateway_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/p2svpnGateways/{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": [ + "p2sVpnGateway" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the user VPN configuration." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the user VPN configuration." + }, + "value": "[resourceId('Microsoft.Network/p2svpnGateways', parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the user VPN configuration was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('p2sVpnGateway', '2024-01-01', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/network/p2s-vpn-gateway/tests/e2e/defaults/dependencies.bicep b/avm/res/network/p2s-vpn-gateway/tests/e2e/defaults/dependencies.bicep new file mode 100644 index 0000000000..dfc78768e5 --- /dev/null +++ b/avm/res/network/p2s-vpn-gateway/tests/e2e/defaults/dependencies.bicep @@ -0,0 +1,57 @@ +@description('Required. The name of the virtual WAN to create.') +param virtualWANName string + +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +resource virtualWan 'Microsoft.Network/virtualWans@2024-01-01' = { + name: virtualWANName + location: location +} + +resource vpnServerConfiguration 'Microsoft.Network/vpnServerConfigurations@2024-01-01' = { + name: '${virtualWANName}-${location}-vpnServerConfiguration' + location: location + properties: { + aadAuthenticationParameters: { + aadAudience: '11111111-1234-4321-1234-111111111111' + aadIssuer: 'https://sts.windows.net/11111111-1111-1111-1111-111111111111/' + aadTenant: 'https://login.microsoftonline.com/11111111-1111-1111-1111-111111111111' + } + vpnAuthenticationTypes: [ + 'AAD' + ] + vpnProtocols: [ + 'OpenVPN' + ] + } +} + +resource virtualHub 'Microsoft.Network/virtualHubs@2024-01-01' = { + name: '${virtualWANName}-${location}-hub' + location: location + properties: { + addressPrefix: '10.0.0.0/23' + virtualWan: { + id: virtualWan.id + } + } +} + +@description('The resource ID of the created Virtual WAN.') +output virtualWANResourceId string = virtualWan.id + +@description('The name of the created Virtual WAN.') +output virtualWANName string = virtualWan.name + +@description('The resource ID of the created Virtual Hub.') +output virtualHubResourceId string = virtualHub.id + +@description('The name of the created Virtual Hub.') +output virtualHubName string = virtualHub.name + +@description('The resource ID of the created VPN Server Configuration.') +output vpnServerConfigurationResourceId string = vpnServerConfiguration.id + +@description('The name of the created VPN Server Configuration.') +output vpnServerConfigurationName string = vpnServerConfiguration.name diff --git a/avm/res/network/p2s-vpn-gateway/tests/e2e/defaults/main.test.bicep b/avm/res/network/p2s-vpn-gateway/tests/e2e/defaults/main.test.bicep new file mode 100644 index 0000000000..7a0d7ba6cd --- /dev/null +++ b/avm/res/network/p2s-vpn-gateway/tests/e2e/defaults/main.test.bicep @@ -0,0 +1,66 @@ +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.p2svpngateway-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param resourceLocation 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 = 'vscmin' + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + + + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + virtualWANName: 'dep-${namePrefix}-vw-${serviceShort}' + location: resourceLocation + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}p2sVpnGw' + location: resourceLocation + p2SConnectionConfigurationsName: 'p2sConnectionConfig1' + vpnClientAddressPoolAddressPrefixes: [ + '10.0.2.0/24' + ] + associatedRouteTableName: 'defaultRouteTable' + virtualHubId: nestedDependencies.outputs.virtualHubResourceId + vpnServerConfigurationId: nestedDependencies.outputs.vpnServerConfigurationResourceId + } + } +] diff --git a/avm/res/network/p2s-vpn-gateway/tests/e2e/max/dependencies.bicep b/avm/res/network/p2s-vpn-gateway/tests/e2e/max/dependencies.bicep new file mode 100644 index 0000000000..aa1bb60c57 --- /dev/null +++ b/avm/res/network/p2s-vpn-gateway/tests/e2e/max/dependencies.bicep @@ -0,0 +1,150 @@ +@description('Required. The name of the virtual WAN to create.') +param virtualWANName string + +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +resource virtualWan 'Microsoft.Network/virtualWans@2024-01-01' = { + name: virtualWANName + location: location +} + +resource vpnServerConfiguration 'Microsoft.Network/vpnServerConfigurations@2024-01-01' = { + name: '${virtualWANName}-${location}-vpnServerConfiguration' + location: location + properties: { + aadAuthenticationParameters: { + aadAudience: '11111111-1234-4321-1234-111111111111' + aadIssuer: 'https://sts.windows.net/11111111-1111-1111-1111-111111111111/' + aadTenant: 'https://login.microsoftonline.com/11111111-1111-1111-1111-111111111111' + } + vpnAuthenticationTypes: [ + 'AAD' + ] + vpnProtocols: [ + 'OpenVPN' + ] + } +} + +resource virtualHub 'Microsoft.Network/virtualHubs@2024-01-01' = { + name: '${virtualWANName}-${location}-hub' + location: location + properties: { + addressPrefix: '10.0.0.0/23' + virtualWan: { + id: virtualWan.id + } + } +} + +resource hubRouteTable 'Microsoft.Network/virtualHubs/hubRouteTables@2024-01-01' = { + name: 'VPNRouteTable' + parent: virtualHub + properties: { + labels: [ + 'VPNRoutes' + ] + routes: [ + { + name: 'DefaultVPNRoute' + destinations: [ + '10.1.100.0/24' + ] + destinationType: 'CIDR' + nextHop: azureFirewall.id + nextHopType: 'ResourceId' + } + ] + } +} + +resource hubRouteMap 'Microsoft.Network/virtualHubs/routeMaps@2024-01-01' = { + name: 'VPNRouteMap' + parent: virtualHub + properties: { + rules: [ + { + actions: [ + { + parameters: [ + { + asPath: [ + '65051' + ] + } + ] + type: 'Add' + } + ] + matchCriteria: [ + { + asPath: [ + '65050' + ] + matchCondition: 'Equals' + } + ] + name: 'TestVPNRouteMap' + nextStepIfMatched: 'Continue' + } + ] + } +} +resource azureFirewall 'Microsoft.Network/azureFirewalls@2024-01-01' = { + name: '${virtualWANName}-${location}-hub' + location: location + properties: { + sku: { + name: 'AZFW_Hub' + tier: 'Premium' + } + virtualHub: { + id: virtualHub.id + } + hubIPAddresses: { + publicIPs: { + count: 1 + } + } + } +} + +@description('The resource ID of the created Virtual WAN.') +output virtualWANResourceId string = virtualWan.id + +@description('The name of the created Virtual WAN.') +output virtualWANName string = virtualWan.name + +@description('The resource ID of the created Virtual Hub.') +output virtualHubResourceId string = virtualHub.id + +@description('The name of the created Virtual Hub.') +output virtualHubName string = virtualHub.name + +@description('The resource ID of the created VPN Server Configuration.') +output vpnServerConfigurationResourceId string = vpnServerConfiguration.id + +@description('The name of the created VPN Server Configuration.') +output vpnServerConfigurationName string = vpnServerConfiguration.name + +@description('The resource ID of the created hub Azure Firewall') +output azureFirewallResourceId string = azureFirewall.id + +@description('The name of the created hub Azure Firewall') +output azureFirewallName string = azureFirewall.name + +@description('The resource ID of the created hub route table') +output hubRouteTableName string = hubRouteTable.name + +@description('The name of the created hub route table') +output hubRouteTableResourceId string = hubRouteTable.id + +@description('The labels for the created hub route table') +output hubRouteTableLabels string[] = hubRouteTable.properties.labels + +@description('The resource ID of the created hub route map') +output hubRouteMapResourceId string = hubRouteMap.id + +@description('The name of the created hub route map') +output hubRouteMapName string = hubRouteMap.name diff --git a/avm/res/network/p2s-vpn-gateway/tests/e2e/max/main.test.bicep b/avm/res/network/p2s-vpn-gateway/tests/e2e/max/main.test.bicep new file mode 100644 index 0000000000..5acc25f822 --- /dev/null +++ b/avm/res/network/p2s-vpn-gateway/tests/e2e/max/main.test.bicep @@ -0,0 +1,80 @@ +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.p2svpngateway-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param resourceLocation 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 = 'vscmax' + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + + + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + virtualWANName: 'dep-${namePrefix}-vw-${serviceShort}' + location: resourceLocation + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + location: resourceLocation + name: '${namePrefix}${serviceShort}p2sVpnGw' + customDnsServers: [ + '10.50.10.50' + '10.50.50.50' + ] + isRoutingPreferenceInternet: false + enableInternetSecurity: false + associatedRouteTableName: 'noneRouteTable' + inboundRouteMapResourceId: nestedDependencies.outputs.hubRouteMapResourceId + outboundRouteMapResourceId: nestedDependencies.outputs.hubRouteMapResourceId + propagatedRouteTableNames: [ + nestedDependencies.outputs.hubRouteTableName + ] + propagatedLabelNames: nestedDependencies.outputs.hubRouteTableLabels + vpnClientAddressPoolAddressPrefixes: [ + '10.0.2.0/24' + '10.0.3.0/24' + ] + virtualHubId: nestedDependencies.outputs.virtualHubResourceId + vpnGatewayScaleUnit: 5 + vpnServerConfigurationId: nestedDependencies.outputs.vpnServerConfigurationResourceId + p2SConnectionConfigurationsName: 'p2sConnectionConfig1' + } + } +] diff --git a/avm/res/network/p2s-vpn-gateway/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/network/p2s-vpn-gateway/tests/e2e/waf-aligned/dependencies.bicep new file mode 100644 index 0000000000..c28dbefb5c --- /dev/null +++ b/avm/res/network/p2s-vpn-gateway/tests/e2e/waf-aligned/dependencies.bicep @@ -0,0 +1,82 @@ +@description('Required. The name of the virtual WAN to create.') +param virtualWANName string + +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +resource virtualWan 'Microsoft.Network/virtualWans@2024-01-01' = { + name: virtualWANName + location: location +} + +resource vpnServerConfiguration 'Microsoft.Network/vpnServerConfigurations@2024-01-01' = { + name: '${virtualWANName}-${location}-vpnServerConfiguration' + location: location + properties: { + aadAuthenticationParameters: { + aadAudience: '11111111-1234-4321-1234-111111111111' + aadIssuer: 'https://sts.windows.net/11111111-1111-1111-1111-111111111111/' + aadTenant: 'https://login.microsoftonline.com/11111111-1111-1111-1111-111111111111' + } + vpnAuthenticationTypes: [ + 'AAD' + ] + vpnProtocols: [ + 'OpenVPN' + ] + } +} + +resource virtualHub 'Microsoft.Network/virtualHubs@2024-01-01' = { + name: '${virtualWANName}-${location}-hub' + location: location + properties: { + addressPrefix: '10.0.0.0/23' + virtualWan: { + id: virtualWan.id + } + } +} + +resource azureFirewall 'Microsoft.Network/azureFirewalls@2024-01-01' = { + name: '${virtualWANName}-${location}-hub' + location: location + properties: { + sku: { + name: 'AZFW_Hub' + tier: 'Premium' + } + virtualHub: { + id: virtualHub.id + } + hubIPAddresses: { + publicIPs: { + count: 1 + } + } + } +} + +@description('The resource ID of the created Virtual WAN.') +output virtualWANResourceId string = virtualWan.id + +@description('The name of the created Virtual WAN.') +output virtualWANName string = virtualWan.name + +@description('The resource ID of the created Virtual Hub.') +output virtualHubResourceId string = virtualHub.id + +@description('The name of the created Virtual Hub.') +output virtualHubName string = virtualHub.name + +@description('The resource ID of the created VPN Server Configuration.') +output vpnServerConfigurationResourceId string = vpnServerConfiguration.id + +@description('The name of the created VPN Server Configuration.') +output vpnServerConfigurationName string = vpnServerConfiguration.name + +@description('The resource ID of the created hub Azure Firewall') +output azureFirewallResourceId string = azureFirewall.id + +@description('The name of the created hub Azure Firewall') +output azureFirewallName string = azureFirewall.name diff --git a/avm/res/network/p2s-vpn-gateway/tests/e2e/waf-aligned/main.test.bicep b/avm/res/network/p2s-vpn-gateway/tests/e2e/waf-aligned/main.test.bicep new file mode 100644 index 0000000000..f855bc1486 --- /dev/null +++ b/avm/res/network/p2s-vpn-gateway/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,76 @@ +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.p2svpngateway-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param resourceLocation 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 = 'vscwaf' + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + + + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + virtualWANName: 'dep-${namePrefix}-vw-${serviceShort}' + location: resourceLocation + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}p2sVpnGw' + location: resourceLocation + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + tags: { + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + p2SConnectionConfigurationsName: 'p2sConnectionConfig1' + isRoutingPreferenceInternet: false + enableInternetSecurity: true + associatedRouteTableName: 'defaultRouteTable' + vpnClientAddressPoolAddressPrefixes: [ + '10.0.2.0/24' + ] + virtualHubId: nestedDependencies.outputs.virtualHubResourceId + vpnServerConfigurationId: nestedDependencies.outputs.vpnServerConfigurationResourceId + } + } +] diff --git a/avm/res/network/p2s-vpn-gateway/version.json b/avm/res/network/p2s-vpn-gateway/version.json new file mode 100644 index 0000000000..7245f14872 --- /dev/null +++ b/avm/res/network/p2s-vpn-gateway/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.1", + "pathFilters": [ + "./main.json" + ] + } \ No newline at end of file