From 2c7263b0e5c61090f8c09865e4217895c0cf114a Mon Sep 17 00:00:00 2001 From: Alexander Sehr Date: Thu, 7 Mar 2024 09:35:59 +0100 Subject: [PATCH] feat: Update PE implementation in alignment to latest schema (1) (#1087) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description Follow up to #1070 - Applied latest PE schema accross all modules - Ensured that all modules deploy at least 2 PEs to wnsure there is no concurrency issue - Removed several dedicated `private-endpoint` tests cases if already implemented in max ## Pipeline Reference | Pipeline | | - | [![avm.res.automation.automation-account](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.automation.automation-account.yml/badge.svg?branch=feat%2Fpe-adjustments-962-946-1042&event=workflow_dispatch)](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.automation.automation-account.yml) [![avm.res.batch.batch-account](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.batch.batch-account.yml/badge.svg?branch=feat%2Fpe-adjustments-962-946-1042&event=workflow_dispatch)](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.batch.batch-account.yml) [![avm.res.cache.redis](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.cache.redis.yml/badge.svg?branch=feat%2Fpe-adjustments-962-946-1042&event=workflow_dispatch)](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.cache.redis.yml) [![avm.res.cognitive-services.account](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.cognitive-services.account.yml/badge.svg?branch=feat%2Fpe-adjustments-962-946-1042&event=workflow_dispatch)](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.cognitive-services.account.yml) [![avm.res.container-registry.registry](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.container-registry.registry.yml/badge.svg?branch=feat%2Fpe-adjustments-962-946-1042&event=workflow_dispatch)](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.container-registry.registry.yml) [![avm.res.data-factory.factory](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.data-factory.factory.yml/badge.svg?branch=feat%2Fpe-adjustments-962-946-1042&event=workflow_dispatch)](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.data-factory.factory.yml) ## Type of Change - [ ] Update to CI Environment or utlities (Non-module effecting changes) - [x] Azure Verified Module updates: - [x] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [x] Update to documentation --------- Co-authored-by: Sebastian Gräf Co-authored-by: Kris Baranek Co-authored-by: ChrisSidebotham-MSFT <48600046+ChrisSidebotham@users.noreply.github.com> --- .../automation/automation-account/README.md | 46 ++++++- .../automation/automation-account/main.bicep | 39 ++++-- .../automation/automation-account/main.json | 77 +++++------ .../tests/e2e/max/dependencies.bicep | 22 ++- .../tests/e2e/max/main.test.bicep | 20 ++- .../tests/e2e/waf-aligned/main.test.bicep | 4 + .../automation-account/version.json | 2 +- avm/res/batch/batch-account/README.md | 94 ++++++++++--- avm/res/batch/batch-account/main.bicep | 39 ++++-- avm/res/batch/batch-account/main.json | 72 +++++----- .../tests/e2e/max/dependencies.bicep | 24 +++- .../tests/e2e/max/main.test.bicep | 35 ++++- .../tests/e2e/waf-aligned/main.test.bicep | 5 + avm/res/batch/batch-account/version.json | 2 +- avm/res/cache/redis/README.md | 34 ++++- avm/res/cache/redis/main.bicep | 32 +++-- avm/res/cache/redis/main.json | 63 +++++---- .../cache/redis/tests/e2e/max/main.test.bicep | 10 ++ .../tests/e2e/waf-aligned/main.test.bicep | 4 + avm/res/cache/redis/version.json | 4 +- avm/res/cognitive-services/account/README.md | 34 ++++- avm/res/cognitive-services/account/main.bicep | 33 +++-- avm/res/cognitive-services/account/main.json | 64 +++++---- .../account/tests/e2e/max/main.test.bicep | 10 ++ .../account/tests/e2e/speech/main.test.bicep | 3 + .../main.test.bicep | 3 + .../main.test.bicep | 3 + .../tests/e2e/waf-aligned/main.test.bicep | 4 + .../cognitive-services/account/version.json | 2 +- avm/res/container-registry/registry/README.md | 127 +++++------------- .../container-registry/registry/main.bicep | 39 ++++-- avm/res/container-registry/registry/main.json | 65 +++++---- .../registry/tests/e2e/encr/main.test.bicep | 3 + .../registry/tests/e2e/max/main.test.bicep | 11 +- .../registry/tests/e2e/pe/dependencies.bicep | 49 ------- .../registry/tests/e2e/pe/main.test.bicep | 64 --------- .../tests/e2e/waf-aligned/main.test.bicep | 4 + .../container-registry/registry/version.json | 2 +- avm/res/data-factory/factory/README.md | 54 +++++--- avm/res/data-factory/factory/main.bicep | 39 ++++-- avm/res/data-factory/factory/main.json | 65 +++++---- .../factory/tests/e2e/max/main.test.bicep | 8 +- avm/res/data-factory/factory/version.json | 2 +- 43 files changed, 796 insertions(+), 520 deletions(-) delete mode 100644 avm/res/container-registry/registry/tests/e2e/pe/dependencies.bicep delete mode 100644 avm/res/container-registry/registry/tests/e2e/pe/main.test.bicep diff --git a/avm/res/automation/automation-account/README.md b/avm/res/automation/automation-account/README.md index 43a4f43ccf..7453918030 100644 --- a/avm/res/automation/automation-account/README.md +++ b/avm/res/automation/automation-account/README.md @@ -233,6 +233,18 @@ module automationAccount 'br/public:avm/res/automation/automation-account:' + ] + service: 'Webhook' + subnetResourceId: '' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } { privateDnsZoneResourceIds: [ '' @@ -467,6 +479,18 @@ module automationAccount 'br/public:avm/res/automation/automation-account:" + ], + "service": "Webhook", + "subnetResourceId": "", + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + }, { "privateDnsZoneResourceIds": [ "" @@ -1420,7 +1444,7 @@ Configuration details for private endpoints. For security reasons, it is recomme | Parameter | Type | Description | | :-- | :-- | :-- | -| [`service`](#parameter-privateendpointsservice) | string | The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob". | +| [`service`](#parameter-privateendpointsservice) | string | The subresource to deploy the private endpoint for. For example "blob", "table", "queue" or "file". | | [`subnetResourceId`](#parameter-privateendpointssubnetresourceid) | string | Resource ID of the subnet where the endpoint needs to be created. | **Optional parameters** @@ -1432,9 +1456,10 @@ Configuration details for private endpoints. For security reasons, it is recomme | [`customNetworkInterfaceName`](#parameter-privateendpointscustomnetworkinterfacename) | string | The custom name of the network interface attached to the private endpoint. | | [`enableTelemetry`](#parameter-privateendpointsenabletelemetry) | bool | Enable/Disable usage telemetry for module. | | [`ipConfigurations`](#parameter-privateendpointsipconfigurations) | array | A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints. | +| [`isManualConnection`](#parameter-privateendpointsismanualconnection) | bool | If Manual Private Link Connection is required. | | [`location`](#parameter-privateendpointslocation) | string | The location to deploy the private endpoint to. | | [`lock`](#parameter-privateendpointslock) | object | Specify the type of lock. | -| [`manualPrivateLinkServiceConnections`](#parameter-privateendpointsmanualprivatelinkserviceconnections) | array | Manual PrivateLink Service Connections. | +| [`manualConnectionRequestMessage`](#parameter-privateendpointsmanualconnectionrequestmessage) | string | A message passed to the owner of the remote resource with the manual connection request. | | [`name`](#parameter-privateendpointsname) | string | The name of the private endpoint. | | [`privateDnsZoneGroupName`](#parameter-privateendpointsprivatednszonegroupname) | string | The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided. | | [`privateDnsZoneResourceIds`](#parameter-privateendpointsprivatednszoneresourceids) | array | The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones. | @@ -1443,7 +1468,7 @@ Configuration details for private endpoints. For security reasons, it is recomme ### Parameter: `privateEndpoints.service` -The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob". +The subresource to deploy the private endpoint for. For example "blob", "table", "queue" or "file". - Required: Yes - Type: string @@ -1561,6 +1586,13 @@ A private ip address obtained from the private endpoint's subnet. - Required: Yes - Type: string +### Parameter: `privateEndpoints.isManualConnection` + +If Manual Private Link Connection is required. + +- Required: No +- Type: bool + ### Parameter: `privateEndpoints.location` The location to deploy the private endpoint to. @@ -1604,12 +1636,12 @@ Specify the name of lock. - Required: No - Type: string -### Parameter: `privateEndpoints.manualPrivateLinkServiceConnections` +### Parameter: `privateEndpoints.manualConnectionRequestMessage` -Manual PrivateLink Service Connections. +A message passed to the owner of the remote resource with the manual connection request. - Required: No -- Type: array +- Type: string ### Parameter: `privateEndpoints.name` @@ -1905,7 +1937,7 @@ This section gives you an overview of all local-referenced module files (i.e., o | Reference | Type | | :-- | :-- | | `res/operational-insights/workspace/linked-service` | Local reference | -| `br/public:avm/res/network/private-endpoint:0.3.1` | Remote reference | +| `br/public:avm/res/network/private-endpoint:0.4.0` | Remote reference | | `br/public:avm/res/operations-management/solution:0.1.0` | Remote reference | ## Data Collection diff --git a/avm/res/automation/automation-account/main.bicep b/avm/res/automation/automation-account/main.bicep index 512aa2354a..9db1af88c2 100644 --- a/avm/res/automation/automation-account/main.bicep +++ b/avm/res/automation/automation-account/main.bicep @@ -328,34 +328,45 @@ resource automationAccount_diagnosticSettings 'Microsoft.Insights/diagnosticSett scope: automationAccount }] -module automationAccount_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.3.1' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { +module automationAccount_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { name: '${uniqueString(deployment().name, location)}-automationAccount-PrivateEndpoint-${index}' params: { - privateLinkServiceConnections: [ + name: privateEndpoint.?name ?? 'pep-${last(split(automationAccount.id, '/'))}-${privateEndpoint.service}-${index}' + privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true ? [ { - name: name + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(automationAccount.id, '/'))}-${privateEndpoint.service}-${index}' properties: { privateLinkServiceId: automationAccount.id groupIds: [ - privateEndpoint.?service ?? 'automationaccount' + privateEndpoint.service ] } } - ] - name: privateEndpoint.?name ?? 'pep-${last(split(automationAccount.id, '/'))}-${privateEndpoint.?service ?? privateEndpoint.service}-${index}' + ] : null + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(automationAccount.id, '/'))}-${privateEndpoint.service}-${index}' + properties: { + privateLinkServiceId: automationAccount.id + groupIds: [ + privateEndpoint.service + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } + ] : null subnetResourceId: privateEndpoint.subnetResourceId + enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location lock: privateEndpoint.?lock ?? lock privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds roleAssignments: privateEndpoint.?roleAssignments tags: privateEndpoint.?tags ?? tags - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections customDnsConfigs: privateEndpoint.?customDnsConfigs ipConfigurations: privateEndpoint.?ipConfigurations applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName - enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry } }] @@ -438,7 +449,7 @@ type privateEndpointType = { @description('Optional. The location to deploy the private endpoint to.') location: string? - @description('Required. The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob".') + @description('Required. The subresource to deploy the private endpoint for. For example "blob", "table", "queue" or "file".') service: string @description('Required. Resource ID of the subnet where the endpoint needs to be created.') @@ -450,6 +461,13 @@ type privateEndpointType = { @description('Optional. The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones.') privateDnsZoneResourceIds: string[]? + @description('Optional. If Manual Private Link Connection is required.') + isManualConnection: bool? + + @description('Optional. A message passed to the owner of the remote resource with the manual connection request.') + @maxLength(140) + manualConnectionRequestMessage: string? + @description('Optional. Custom DNS configurations.') customDnsConfigs: { @description('Required. Fqdn that resolves to private endpoint ip address.') @@ -492,9 +510,6 @@ type privateEndpointType = { @description('Optional. Tags to be applied on all resources/resource groups in this deployment.') tags: object? - @description('Optional. Manual PrivateLink Service Connections.') - manualPrivateLinkServiceConnections: array? - @description('Optional. Enable/Disable usage telemetry for module.') enableTelemetry: bool? }[]? diff --git a/avm/res/automation/automation-account/main.json b/avm/res/automation/automation-account/main.json index 0a24cab446..feb3919fc8 100644 --- a/avm/res/automation/automation-account/main.json +++ b/avm/res/automation/automation-account/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "3223894986476226816" + "templateHash": "17457652611185300575" }, "name": "Automation Accounts", "description": "This module deploys an Azure Automation Account.", @@ -149,7 +149,7 @@ "service": { "type": "string", "metadata": { - "description": "Required. The service (sub-) type to deploy the private endpoint for. For example \"vault\" or \"blob\"." + "description": "Required. The subresource to deploy the private endpoint for. For example \"blob\", \"table\", \"queue\" or \"file\"." } }, "subnetResourceId": { @@ -175,6 +175,21 @@ "description": "Optional. The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones." } }, + "isManualConnection": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. If Manual Private Link Connection is required." + } + }, + "manualConnectionRequestMessage": { + "type": "string", + "nullable": true, + "maxLength": 140, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." + } + }, "customDnsConfigs": { "type": "array", "items": { @@ -283,13 +298,6 @@ "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." } }, - "manualPrivateLinkServiceConnections": { - "type": "array", - "nullable": true, - "metadata": { - "description": "Optional. Manual PrivateLink Service Connections." - } - }, "enableTelemetry": { "type": "bool", "nullable": true, @@ -2310,25 +2318,17 @@ }, "mode": "Incremental", "parameters": { - "privateLinkServiceConnections": { - "value": [ - { - "name": "[parameters('name')]", - "properties": { - "privateLinkServiceId": "[resourceId('Microsoft.Automation/automationAccounts', parameters('name'))]", - "groupIds": [ - "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'automationaccount')]" - ] - } - } - ] - }, "name": { - "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'name'), format('pep-{0}-{1}-{2}', last(split(resourceId('Microsoft.Automation/automationAccounts', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].service), copyIndex()))]" + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'name'), format('pep-{0}-{1}-{2}', last(split(resourceId('Microsoft.Automation/automationAccounts', parameters('name')), '/')), coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].service, copyIndex()))]" }, + "privateLinkServiceConnections": "[if(not(equals(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualPrivateLinkServiceConnections'), true())), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.Automation/automationAccounts', parameters('name')), '/')), coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].service, copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId('Microsoft.Automation/automationAccounts', parameters('name')), 'groupIds', createArray(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].service))))), createObject('value', null()))]", + "manualPrivateLinkServiceConnections": "[if(equals(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualPrivateLinkServiceConnections'), true()), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.Automation/automationAccounts', parameters('name')), '/')), coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].service, copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId('Microsoft.Automation/automationAccounts', parameters('name')), 'groupIds', createArray(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].service), 'requestMessage', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualConnectionRequestMessage'), 'Manual approval required.'))))), createObject('value', null()))]", "subnetResourceId": { "value": "[coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId]" }, + "enableTelemetry": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'enableTelemetry'), parameters('enableTelemetry'))]" + }, "location": { "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'location'), reference(split(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location)]" }, @@ -2347,9 +2347,6 @@ "tags": { "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'tags'), parameters('tags'))]" }, - "manualPrivateLinkServiceConnections": { - "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualPrivateLinkServiceConnections')]" - }, "customDnsConfigs": { "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'customDnsConfigs')]" }, @@ -2361,9 +2358,6 @@ }, "customNetworkInterfaceName": { "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'customNetworkInterfaceName')]" - }, - "enableTelemetry": { - "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'enableTelemetry'), parameters('enableTelemetry'))]" } }, "template": { @@ -2373,8 +2367,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "2821141217598568122" + "version": "0.24.24.22086", + "templateHash": "2592884001616184297" }, "name": "Private Endpoints", "description": "This module deploys a Private Endpoint.", @@ -2423,7 +2417,7 @@ "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\"" + "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": { @@ -2501,7 +2495,7 @@ "privateIPAddress": { "type": "string", "metadata": { - "description": "Required. A private ip address obtained from the private endpoint's subnet." + "description": "Required. A private IP address obtained from the private endpoint's subnet." } } }, @@ -2604,7 +2598,7 @@ "fqdn": { "type": "string", "metadata": { - "description": "Required. Fqdn that resolves to private endpoint ip address." + "description": "Required. Fqdn that resolves to private endpoint IP address." } }, "ipAddresses": { @@ -2613,7 +2607,7 @@ "type": "string" }, "metadata": { - "description": "Required. A list of private ip addresses of the private endpoint." + "description": "Required. A list of private IP addresses of the private endpoint." } } } @@ -2739,7 +2733,7 @@ "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2023-07-01", - "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.3.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.4.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -2844,8 +2838,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "18168683629401652671" + "version": "0.24.24.22086", + "templateHash": "9321937464667207030" }, "name": "Private Endpoint Private DNS Zone Groups", "description": "This module deploys a Private Endpoint Private DNS Zone Group.", @@ -2956,6 +2950,13 @@ "description": "The location the resource was deployed into." }, "value": "[reference('privateEndpoint', '2023-04-01', 'full').location]" + }, + "groupId": { + "type": "string", + "metadata": { + "description": "The group Id for the private endpoint Group." + }, + "value": "[if(not(empty(reference('privateEndpoint').manualPrivateLinkServiceConnections)), reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties.groupIds[0], reference('privateEndpoint').privateLinkServiceConnections[0].properties.groupIds[0])]" } } } diff --git a/avm/res/automation/automation-account/tests/e2e/max/dependencies.bicep b/avm/res/automation/automation-account/tests/e2e/max/dependencies.bicep index 77af000af6..403211cdb7 100644 --- a/avm/res/automation/automation-account/tests/e2e/max/dependencies.bicep +++ b/avm/res/automation/automation-account/tests/e2e/max/dependencies.bicep @@ -22,7 +22,19 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { { name: 'defaultSubnet' properties: { - addressPrefix: cidrSubnet(addressPrefix, 16, 0) + addressPrefix: cidrSubnet(addressPrefix, 20, 0) + } + } + { + name: 'custom-private-subnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 20, 1) + } + } + { + name: 'custom-private-subnet-2' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 20, 2) } } ] @@ -50,9 +62,15 @@ resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018- location: location } -@description('The resource ID of the created Virtual Network Subnet.') +@description('The resource ID of the created Virtual Network Default Subnet.') output subnetResourceId string = virtualNetwork.properties.subnets[0].id +@description('The resource ID of the 2nd created Virtual Network Subnet.') +output customSubnet1ResourceId string = virtualNetwork.properties.subnets[1].id + +@description('The resource ID of the 3rd created Virtual Network Subnet.') +output customSubnet2ResourceId string = virtualNetwork.properties.subnets[2].id + @description('The principal ID of the created Managed Identity.') output managedIdentityPrincipalId string = managedIdentity.properties.principalId diff --git a/avm/res/automation/automation-account/tests/e2e/max/main.test.bicep b/avm/res/automation/automation-account/tests/e2e/max/main.test.bicep index 8067995a67..0c9b5a710d 100644 --- a/avm/res/automation/automation-account/tests/e2e/max/main.test.bicep +++ b/avm/res/automation/automation-account/tests/e2e/max/main.test.bicep @@ -102,7 +102,19 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' nestedDependencies.outputs.privateDNSZoneResourceId ] service: 'Webhook' - subnetResourceId: nestedDependencies.outputs.subnetResourceId + subnetResourceId: nestedDependencies.outputs.customSubnet1ResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + service: 'Webhook' + subnetResourceId: nestedDependencies.outputs.customSubnet2ResourceId tags: { 'hidden-title': 'This is visible in the resource name' Environment: 'Non-Prod' @@ -114,7 +126,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' nestedDependencies.outputs.privateDNSZoneResourceId ] service: 'DSCAndHybridWorker' - subnetResourceId: nestedDependencies.outputs.subnetResourceId + subnetResourceId: nestedDependencies.outputs.customSubnet1ResourceId tags: { 'hidden-title': 'This is visible in the resource name' Environment: 'Non-Prod' @@ -256,4 +268,8 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' Role: 'DeploymentValidation' } } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] }] diff --git a/avm/res/automation/automation-account/tests/e2e/waf-aligned/main.test.bicep b/avm/res/automation/automation-account/tests/e2e/waf-aligned/main.test.bicep index fbaee4ef11..d2bbfb2033 100644 --- a/avm/res/automation/automation-account/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/automation/automation-account/tests/e2e/waf-aligned/main.test.bicep @@ -242,4 +242,8 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' Role: 'DeploymentValidation' } } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] }] diff --git a/avm/res/automation/automation-account/version.json b/avm/res/automation/automation-account/version.json index 83083db694..c177b1bb58 100644 --- a/avm/res/automation/automation-account/version.json +++ b/avm/res/automation/automation-account/version.json @@ -1,6 +1,6 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.1", + "version": "0.3", "pathFilters": [ "./main.json" ] diff --git a/avm/res/batch/batch-account/README.md b/avm/res/batch/batch-account/README.md index b7a08c4390..1ea59e9346 100644 --- a/avm/res/batch/batch-account/README.md +++ b/avm/res/batch/batch-account/README.md @@ -231,7 +231,7 @@ module batchAccount 'br/public:avm/res/batch/batch-account:' = { { fqdn: 'abc.batch.com' ipAddresses: [ - '10.0.0.10' + '10.0.16.10' ] } ] @@ -241,7 +241,7 @@ module batchAccount 'br/public:avm/res/batch/batch-account:' = { properties: { groupId: 'batchAccount' memberName: 'batchAccount' - privateIPAddress: '10.0.0.10' + privateIPAddress: '10.0.16.10' } } ] @@ -260,6 +260,31 @@ module batchAccount 'br/public:avm/res/batch/batch-account:' = { roleDefinitionIdOrName: '' } ] + service: 'batchAccount' + subnetResourceId: '' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + { + privateDnsZoneResourceIds: [ + '' + ] + service: 'batchAccount' + subnetResourceId: '' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + { + privateDnsZoneResourceIds: [ + '' + ] + service: 'nodeManagement' subnetResourceId: '' tags: { Environment: 'Non-Prod' @@ -366,7 +391,7 @@ module batchAccount 'br/public:avm/res/batch/batch-account:' = { { "fqdn": "abc.batch.com", "ipAddresses": [ - "10.0.0.10" + "10.0.16.10" ] } ], @@ -376,7 +401,7 @@ module batchAccount 'br/public:avm/res/batch/batch-account:' = { "properties": { "groupId": "batchAccount", "memberName": "batchAccount", - "privateIPAddress": "10.0.0.10" + "privateIPAddress": "10.0.16.10" } } ], @@ -395,6 +420,31 @@ module batchAccount 'br/public:avm/res/batch/batch-account:' = { "roleDefinitionIdOrName": "" } ], + "service": "batchAccount", + "subnetResourceId": "", + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + }, + { + "privateDnsZoneResourceIds": [ + "" + ], + "service": "batchAccount", + "subnetResourceId": "", + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + }, + { + "privateDnsZoneResourceIds": [ + "" + ], + "service": "nodeManagement", "subnetResourceId": "", "tags": { "Environment": "Non-Prod", @@ -482,6 +532,7 @@ module batchAccount 'br/public:avm/res/batch/batch-account:' = { privateDnsZoneResourceIds: [ '' ] + service: 'batchAccount' subnetResourceId: '' } ] @@ -549,6 +600,7 @@ module batchAccount 'br/public:avm/res/batch/batch-account:' = { "privateDnsZoneResourceIds": [ "" ], + "service": "batchAccount", "subnetResourceId": "" } ] @@ -1022,6 +1074,7 @@ Configuration details for private endpoints. For security reasons, it is recomme | Parameter | Type | Description | | :-- | :-- | :-- | +| [`service`](#parameter-privateendpointsservice) | string | The subresource to deploy the private endpoint for. For example "blob", "table", "queue" or "file". | | [`subnetResourceId`](#parameter-privateendpointssubnetresourceid) | string | Resource ID of the subnet where the endpoint needs to be created. | **Optional parameters** @@ -1033,16 +1086,23 @@ Configuration details for private endpoints. For security reasons, it is recomme | [`customNetworkInterfaceName`](#parameter-privateendpointscustomnetworkinterfacename) | string | The custom name of the network interface attached to the private endpoint. | | [`enableTelemetry`](#parameter-privateendpointsenabletelemetry) | bool | Enable/Disable usage telemetry for module. | | [`ipConfigurations`](#parameter-privateendpointsipconfigurations) | array | A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints. | +| [`isManualConnection`](#parameter-privateendpointsismanualconnection) | bool | If Manual Private Link Connection is required. | | [`location`](#parameter-privateendpointslocation) | string | The location to deploy the private endpoint to. | | [`lock`](#parameter-privateendpointslock) | object | Specify the type of lock. | -| [`manualPrivateLinkServiceConnections`](#parameter-privateendpointsmanualprivatelinkserviceconnections) | array | Manual PrivateLink Service Connections. | +| [`manualConnectionRequestMessage`](#parameter-privateendpointsmanualconnectionrequestmessage) | string | A message passed to the owner of the remote resource with the manual connection request. | | [`name`](#parameter-privateendpointsname) | string | The name of the private endpoint. | | [`privateDnsZoneGroupName`](#parameter-privateendpointsprivatednszonegroupname) | string | The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided. | | [`privateDnsZoneResourceIds`](#parameter-privateendpointsprivatednszoneresourceids) | array | The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones. | | [`roleAssignments`](#parameter-privateendpointsroleassignments) | array | Array of role assignments to create. | -| [`service`](#parameter-privateendpointsservice) | string | The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob". | | [`tags`](#parameter-privateendpointstags) | object | Tags to be applied on all resources/resource groups in this deployment. | +### Parameter: `privateEndpoints.service` + +The subresource to deploy the private endpoint for. For example "blob", "table", "queue" or "file". + +- Required: Yes +- Type: string + ### Parameter: `privateEndpoints.subnetResourceId` Resource ID of the subnet where the endpoint needs to be created. @@ -1156,6 +1216,13 @@ A private IP address obtained from the private endpoint's subnet. - Required: Yes - Type: string +### Parameter: `privateEndpoints.isManualConnection` + +If Manual Private Link Connection is required. + +- Required: No +- Type: bool + ### Parameter: `privateEndpoints.location` The location to deploy the private endpoint to. @@ -1199,12 +1266,12 @@ Specify the name of lock. - Required: No - Type: string -### Parameter: `privateEndpoints.manualPrivateLinkServiceConnections` +### Parameter: `privateEndpoints.manualConnectionRequestMessage` -Manual PrivateLink Service Connections. +A message passed to the owner of the remote resource with the manual connection request. - Required: No -- Type: array +- Type: string ### Parameter: `privateEndpoints.name` @@ -1316,13 +1383,6 @@ The principal type of the assigned principal ID. ] ``` -### Parameter: `privateEndpoints.service` - -The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob". - -- Required: No -- Type: string - ### Parameter: `privateEndpoints.tags` Tags to be applied on all resources/resource groups in this deployment. @@ -1481,7 +1541,7 @@ This section gives you an overview of all local-referenced module files (i.e., o | Reference | Type | | :-- | :-- | -| `br/public:avm/res/network/private-endpoint:0.3.1` | Remote reference | +| `br/public:avm/res/network/private-endpoint:0.4.0` | Remote reference | ## Data Collection diff --git a/avm/res/batch/batch-account/main.bicep b/avm/res/batch/batch-account/main.bicep index 4326c505b0..8d7cbddb36 100644 --- a/avm/res/batch/batch-account/main.bicep +++ b/avm/res/batch/batch-account/main.bicep @@ -201,21 +201,33 @@ resource batchAccount_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@ scope: batchAccount }] -module batchAccount_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.3.1' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { +module batchAccount_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { name: '${uniqueString(deployment().name, location)}-BatchAccount-PrivateEndpoint-${index}' params: { - privateLinkServiceConnections: [ + name: privateEndpoint.?name ?? 'pep-${last(split(batchAccount.id, '/'))}-${privateEndpoint.service}-${index}' + privateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections != true ? [ { - name: name + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(batchAccount.id, '/'))}-${privateEndpoint.service}-${index}' properties: { privateLinkServiceId: batchAccount.id groupIds: [ - privateEndpoint.?service ?? 'batchAccount' + privateEndpoint.service ] } } - ] - name: privateEndpoint.?name ?? 'pep-${last(split(batchAccount.id, '/'))}-${privateEndpoint.?service ?? 'batchAccount'}-${index}' + ] : null + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(batchAccount.id, '/'))}-${privateEndpoint.service}-${index}' + properties: { + privateLinkServiceId: batchAccount.id + groupIds: [ + privateEndpoint.service + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } + ] : null subnetResourceId: privateEndpoint.subnetResourceId enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location @@ -224,7 +236,6 @@ module batchAccount_privateEndpoints 'br/public:avm/res/network/private-endpoint privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds roleAssignments: privateEndpoint.?roleAssignments tags: privateEndpoint.?tags ?? tags - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections customDnsConfigs: privateEndpoint.?customDnsConfigs ipConfigurations: privateEndpoint.?ipConfigurations applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds @@ -339,8 +350,8 @@ type privateEndpointType = { @description('Optional. The location to deploy the private endpoint to.') location: string? - @description('Optional. The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob".') - service: string? + @description('Required. The subresource to deploy the private endpoint for. For example "blob", "table", "queue" or "file".') + service: string @description('Required. Resource ID of the subnet where the endpoint needs to be created.') subnetResourceId: string @@ -351,6 +362,13 @@ type privateEndpointType = { @description('Optional. The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones.') privateDnsZoneResourceIds: string[]? + @description('Optional. If Manual Private Link Connection is required.') + isManualConnection: bool? + + @description('Optional. A message passed to the owner of the remote resource with the manual connection request.') + @maxLength(140) + manualConnectionRequestMessage: string? + @description('Optional. Custom DNS configurations.') customDnsConfigs: { @description('Required. Fqdn that resolves to private endpoint IP address.') @@ -393,9 +411,6 @@ type privateEndpointType = { @description('Optional. Tags to be applied on all resources/resource groups in this deployment.') tags: object? - @description('Optional. Manual PrivateLink Service Connections.') - manualPrivateLinkServiceConnections: array? - @description('Optional. Enable/Disable usage telemetry for module.') enableTelemetry: bool? }[]? diff --git a/avm/res/batch/batch-account/main.json b/avm/res/batch/batch-account/main.json index 3731161e53..925fe85130 100644 --- a/avm/res/batch/batch-account/main.json +++ b/avm/res/batch/batch-account/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "2397736043296643387" + "templateHash": "11102129881431176996" }, "name": "Batch Accounts", "description": "This module deploys a Batch Account.", @@ -220,9 +220,8 @@ }, "service": { "type": "string", - "nullable": true, "metadata": { - "description": "Optional. The service (sub-) type to deploy the private endpoint for. For example \"vault\" or \"blob\"." + "description": "Required. The subresource to deploy the private endpoint for. For example \"blob\", \"table\", \"queue\" or \"file\"." } }, "subnetResourceId": { @@ -248,6 +247,21 @@ "description": "Optional. The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones." } }, + "isManualConnection": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. If Manual Private Link Connection is required." + } + }, + "manualConnectionRequestMessage": { + "type": "string", + "nullable": true, + "maxLength": 140, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." + } + }, "customDnsConfigs": { "type": "array", "items": { @@ -357,13 +371,6 @@ "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." } }, - "manualPrivateLinkServiceConnections": { - "type": "array", - "nullable": true, - "metadata": { - "description": "Optional. Manual PrivateLink Service Connections." - } - }, "enableTelemetry": { "type": "bool", "nullable": true, @@ -826,22 +833,11 @@ }, "mode": "Incremental", "parameters": { - "privateLinkServiceConnections": { - "value": [ - { - "name": "[parameters('name')]", - "properties": { - "privateLinkServiceId": "[resourceId('Microsoft.Batch/batchAccounts', parameters('name'))]", - "groupIds": [ - "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'batchAccount')]" - ] - } - } - ] - }, "name": { - "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'name'), format('pep-{0}-{1}-{2}', last(split(resourceId('Microsoft.Batch/batchAccounts', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'batchAccount'), copyIndex()))]" + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'name'), format('pep-{0}-{1}-{2}', last(split(resourceId('Microsoft.Batch/batchAccounts', parameters('name')), '/')), coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].service, copyIndex()))]" }, + "privateLinkServiceConnections": "[if(not(equals(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualPrivateLinkServiceConnections'), true())), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.Batch/batchAccounts', parameters('name')), '/')), coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].service, copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId('Microsoft.Batch/batchAccounts', parameters('name')), 'groupIds', createArray(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].service))))), createObject('value', null()))]", + "manualPrivateLinkServiceConnections": "[if(equals(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualPrivateLinkServiceConnections'), true()), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.Batch/batchAccounts', parameters('name')), '/')), coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].service, copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId('Microsoft.Batch/batchAccounts', parameters('name')), 'groupIds', createArray(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].service), 'requestMessage', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualConnectionRequestMessage'), 'Manual approval required.'))))), createObject('value', null()))]", "subnetResourceId": { "value": "[coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId]" }, @@ -866,9 +862,6 @@ "tags": { "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'tags'), parameters('tags'))]" }, - "manualPrivateLinkServiceConnections": { - "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualPrivateLinkServiceConnections')]" - }, "customDnsConfigs": { "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'customDnsConfigs')]" }, @@ -889,8 +882,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "2821141217598568122" + "version": "0.24.24.22086", + "templateHash": "2592884001616184297" }, "name": "Private Endpoints", "description": "This module deploys a Private Endpoint.", @@ -939,7 +932,7 @@ "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\"" + "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": { @@ -1017,7 +1010,7 @@ "privateIPAddress": { "type": "string", "metadata": { - "description": "Required. A private ip address obtained from the private endpoint's subnet." + "description": "Required. A private IP address obtained from the private endpoint's subnet." } } }, @@ -1120,7 +1113,7 @@ "fqdn": { "type": "string", "metadata": { - "description": "Required. Fqdn that resolves to private endpoint ip address." + "description": "Required. Fqdn that resolves to private endpoint IP address." } }, "ipAddresses": { @@ -1129,7 +1122,7 @@ "type": "string" }, "metadata": { - "description": "Required. A list of private ip addresses of the private endpoint." + "description": "Required. A list of private IP addresses of the private endpoint." } } } @@ -1255,7 +1248,7 @@ "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2023-07-01", - "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.3.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.4.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -1360,8 +1353,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "18168683629401652671" + "version": "0.24.24.22086", + "templateHash": "9321937464667207030" }, "name": "Private Endpoint Private DNS Zone Groups", "description": "This module deploys a Private Endpoint Private DNS Zone Group.", @@ -1472,6 +1465,13 @@ "description": "The location the resource was deployed into." }, "value": "[reference('privateEndpoint', '2023-04-01', 'full').location]" + }, + "groupId": { + "type": "string", + "metadata": { + "description": "The group Id for the private endpoint Group." + }, + "value": "[if(not(empty(reference('privateEndpoint').manualPrivateLinkServiceConnections)), reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties.groupIds[0], reference('privateEndpoint').privateLinkServiceConnections[0].properties.groupIds[0])]" } } } diff --git a/avm/res/batch/batch-account/tests/e2e/max/dependencies.bicep b/avm/res/batch/batch-account/tests/e2e/max/dependencies.bicep index 462e8a5f27..a0acbbc302 100644 --- a/avm/res/batch/batch-account/tests/e2e/max/dependencies.bicep +++ b/avm/res/batch/batch-account/tests/e2e/max/dependencies.bicep @@ -34,7 +34,19 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { { name: 'defaultSubnet' properties: { - addressPrefix: cidrSubnet(addressPrefix, 16, 0) + addressPrefix: cidrSubnet(addressPrefix, 20, 0) + } + } + { + name: 'custom-private-subnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 20, 1) + } + } + { + name: 'custom-private-subnet-2' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 20, 2) } } ] @@ -62,8 +74,14 @@ resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018- location: location } -@description('The resource ID of the created Virtual Network Subnet.') -output subnetResourceId string = virtualNetwork.properties.subnets[0].id +@description('The resource ID of the created Virtual Network Default Subnet.') +output defaultSubnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The resource ID of the 2nd created Virtual Network Subnet.') +output customSubnet1ResourceId string = virtualNetwork.properties.subnets[1].id + +@description('The resource ID of the 3rd created Virtual Network Subnet.') +output customSubnet2ResourceId string = virtualNetwork.properties.subnets[2].id @description('The principal ID of the created Managed Identity.') output managedIdentityPrincipalId string = managedIdentity.properties.principalId diff --git a/avm/res/batch/batch-account/tests/e2e/max/main.test.bicep b/avm/res/batch/batch-account/tests/e2e/max/main.test.bicep index 1a31a13cce..85afc629ca 100644 --- a/avm/res/batch/batch-account/tests/e2e/max/main.test.bicep +++ b/avm/res/batch/batch-account/tests/e2e/max/main.test.bicep @@ -87,7 +87,8 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' privateDnsZoneResourceIds: [ nestedDependencies.outputs.privateDNSZoneResourceId ] - subnetResourceId: nestedDependencies.outputs.subnetResourceId + service: 'batchAccount' + subnetResourceId: nestedDependencies.outputs.customSubnet1ResourceId tags: { 'hidden-title': 'This is visible in the resource name' Environment: 'Non-Prod' @@ -111,7 +112,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' properties: { groupId: 'batchAccount' memberName: 'batchAccount' - privateIPAddress: '10.0.0.10' + privateIPAddress: '10.0.16.10' } } ] @@ -119,11 +120,35 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' { fqdn: 'abc.batch.com' ipAddresses: [ - '10.0.0.10' + '10.0.16.10' ] } ] } + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + service: 'batchAccount' + subnetResourceId: nestedDependencies.outputs.customSubnet2ResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + service: 'nodeManagement' + subnetResourceId: nestedDependencies.outputs.customSubnet1ResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } ] networkProfile: { accountAccess: { @@ -166,4 +191,8 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' Role: 'DeploymentValidation' } } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] }] diff --git a/avm/res/batch/batch-account/tests/e2e/waf-aligned/main.test.bicep b/avm/res/batch/batch-account/tests/e2e/waf-aligned/main.test.bicep index f66d2bac7a..b01e34b2d0 100644 --- a/avm/res/batch/batch-account/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/batch/batch-account/tests/e2e/waf-aligned/main.test.bicep @@ -86,6 +86,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' privateDnsZoneResourceIds: [ nestedDependencies.outputs.privateDNSZoneResourceId ] + service: 'batchAccount' subnetResourceId: nestedDependencies.outputs.subnetResourceId } ] @@ -100,4 +101,8 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' Role: 'DeploymentValidation' } } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] }] diff --git a/avm/res/batch/batch-account/version.json b/avm/res/batch/batch-account/version.json index c177b1bb58..a8eda31021 100644 --- a/avm/res/batch/batch-account/version.json +++ b/avm/res/batch/batch-account/version.json @@ -1,6 +1,6 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.3", + "version": "0.5", "pathFilters": [ "./main.json" ] diff --git a/avm/res/cache/redis/README.md b/avm/res/cache/redis/README.md index 1b8ef80cda..11b99c963d 100644 --- a/avm/res/cache/redis/README.md +++ b/avm/res/cache/redis/README.md @@ -156,6 +156,12 @@ module redis 'br/public:avm/res/cache/redis:' = { Role: 'DeploymentValidation' } } + { + privateDnsZoneResourceIds: [ + '' + ] + subnetResourceId: '' + } ] redisVersion: '6' roleAssignments: [ @@ -278,6 +284,12 @@ module redis 'br/public:avm/res/cache/redis:' = { "hidden-title": "This is visible in the resource name", "Role": "DeploymentValidation" } + }, + { + "privateDnsZoneResourceIds": [ + "" + ], + "subnetResourceId": "" } ] }, @@ -839,14 +851,15 @@ Configuration details for private endpoints. For security reasons, it is recomme | [`customNetworkInterfaceName`](#parameter-privateendpointscustomnetworkinterfacename) | string | The custom name of the network interface attached to the private endpoint. | | [`enableTelemetry`](#parameter-privateendpointsenabletelemetry) | bool | Enable/Disable usage telemetry for module. | | [`ipConfigurations`](#parameter-privateendpointsipconfigurations) | array | A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints. | +| [`isManualConnection`](#parameter-privateendpointsismanualconnection) | bool | If Manual Private Link Connection is required. | | [`location`](#parameter-privateendpointslocation) | string | The location to deploy the private endpoint to. | | [`lock`](#parameter-privateendpointslock) | object | Specify the type of lock. | -| [`manualPrivateLinkServiceConnections`](#parameter-privateendpointsmanualprivatelinkserviceconnections) | array | Manual PrivateLink Service Connections. | +| [`manualConnectionRequestMessage`](#parameter-privateendpointsmanualconnectionrequestmessage) | string | A message passed to the owner of the remote resource with the manual connection request. | | [`name`](#parameter-privateendpointsname) | string | The name of the private endpoint. | | [`privateDnsZoneGroupName`](#parameter-privateendpointsprivatednszonegroupname) | string | The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided. | | [`privateDnsZoneResourceIds`](#parameter-privateendpointsprivatednszoneresourceids) | array | The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones. | | [`roleAssignments`](#parameter-privateendpointsroleassignments) | array | Array of role assignments to create. | -| [`service`](#parameter-privateendpointsservice) | string | The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob". | +| [`service`](#parameter-privateendpointsservice) | string | The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory". | | [`tags`](#parameter-privateendpointstags) | object | Tags to be applied on all resources/resource groups in this deployment. | ### Parameter: `privateEndpoints.subnetResourceId` @@ -962,6 +975,13 @@ A private IP address obtained from the private endpoint's subnet. - Required: Yes - Type: string +### Parameter: `privateEndpoints.isManualConnection` + +If Manual Private Link Connection is required. + +- Required: No +- Type: bool + ### Parameter: `privateEndpoints.location` The location to deploy the private endpoint to. @@ -1005,12 +1025,12 @@ Specify the name of lock. - Required: No - Type: string -### Parameter: `privateEndpoints.manualPrivateLinkServiceConnections` +### Parameter: `privateEndpoints.manualConnectionRequestMessage` -Manual PrivateLink Service Connections. +A message passed to the owner of the remote resource with the manual connection request. - Required: No -- Type: array +- Type: string ### Parameter: `privateEndpoints.name` @@ -1124,7 +1144,7 @@ The principal type of the assigned principal ID. ### Parameter: `privateEndpoints.service` -The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob". +The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory". - Required: No - Type: string @@ -1371,7 +1391,7 @@ This section gives you an overview of all local-referenced module files (i.e., o | Reference | Type | | :-- | :-- | -| `br/public:avm/res/network/private-endpoint:0.3.1` | Remote reference | +| `br/public:avm/res/network/private-endpoint:0.4.0` | Remote reference | ## Notes diff --git a/avm/res/cache/redis/main.bicep b/avm/res/cache/redis/main.bicep index de47057248..38ffba3aab 100644 --- a/avm/res/cache/redis/main.bicep +++ b/avm/res/cache/redis/main.bicep @@ -213,12 +213,13 @@ resource redis_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04- scope: redis }] -module redis_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.3.1' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { +module redis_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { name: '${uniqueString(deployment().name, location)}-KeyVault-PrivateEndpoint-${index}' params: { + name: privateEndpoint.?name ?? 'pep-${last(split(redis.id, '/'))}-${privateEndpoint.?service ?? 'redisCache'}-${index}' privateLinkServiceConnections: [ { - name: name + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(redis.id, '/'))}-${privateEndpoint.?service ?? 'redisCache'}-${index}' properties: { privateLinkServiceId: redis.id groupIds: [ @@ -227,7 +228,18 @@ module redis_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.3.1' } } ] - name: privateEndpoint.?name ?? 'pep-${last(split(redis.id, '/'))}-${privateEndpoint.?service ?? 'redisCache'}-${index}' + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(redis.id, '/'))}-${privateEndpoint.?service ?? 'redisCache'}-${index}' + properties: { + privateLinkServiceId: redis.id + groupIds: [ + privateEndpoint.?service ?? 'redisCache' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } + ] : null subnetResourceId: privateEndpoint.subnetResourceId enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location @@ -236,7 +248,6 @@ module redis_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.3.1' privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds roleAssignments: privateEndpoint.?roleAssignments tags: privateEndpoint.?tags ?? tags - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections customDnsConfigs: privateEndpoint.?customDnsConfigs ipConfigurations: privateEndpoint.?ipConfigurations applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds @@ -289,14 +300,13 @@ type lockType = { }? type privateEndpointType = { - @description('Optional. The name of the private endpoint.') name: string? @description('Optional. The location to deploy the private endpoint to.') location: string? - @description('Optional. The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob".') + @description('Optional. The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory".') service: string? @description('Required. Resource ID of the subnet where the endpoint needs to be created.') @@ -308,6 +318,13 @@ type privateEndpointType = { @description('Optional. The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones.') privateDnsZoneResourceIds: string[]? + @description('Optional. If Manual Private Link Connection is required.') + isManualConnection: bool? + + @description('Optional. A message passed to the owner of the remote resource with the manual connection request.') + @maxLength(140) + manualConnectionRequestMessage: string? + @description('Optional. Custom DNS configurations.') customDnsConfigs: { @description('Required. Fqdn that resolves to private endpoint IP address.') @@ -350,9 +367,6 @@ type privateEndpointType = { @description('Optional. Tags to be applied on all resources/resource groups in this deployment.') tags: object? - @description('Optional. Manual PrivateLink Service Connections.') - manualPrivateLinkServiceConnections: array? - @description('Optional. Enable/Disable usage telemetry for module.') enableTelemetry: bool? }[]? diff --git a/avm/res/cache/redis/main.json b/avm/res/cache/redis/main.json index 85d840b572..9a90df4cd8 100644 --- a/avm/res/cache/redis/main.json +++ b/avm/res/cache/redis/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "16070478115038910597" + "templateHash": "798005420934456091" }, "name": "Redis Cache", "description": "This module deploys a Redis Cache.", @@ -84,7 +84,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Optional. The service (sub-) type to deploy the private endpoint for. For example \"vault\" or \"blob\"." + "description": "Optional. The subresource to deploy the private endpoint for. For example \"vault\", \"mysqlServer\" or \"dataFactory\"." } }, "subnetResourceId": { @@ -110,6 +110,21 @@ "description": "Optional. The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones." } }, + "isManualConnection": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. If Manual Private Link Connection is required." + } + }, + "manualConnectionRequestMessage": { + "type": "string", + "nullable": true, + "maxLength": 140, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." + } + }, "customDnsConfigs": { "type": "array", "items": { @@ -218,13 +233,6 @@ "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." } }, - "manualPrivateLinkServiceConnections": { - "type": "array", - "nullable": true, - "metadata": { - "description": "Optional. Manual PrivateLink Service Connections." - } - }, "enableTelemetry": { "type": "bool", "nullable": true, @@ -770,10 +778,13 @@ }, "mode": "Incremental", "parameters": { + "name": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'name'), format('pep-{0}-{1}-{2}', last(split(resourceId('Microsoft.Cache/redis', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'redisCache'), copyIndex()))]" + }, "privateLinkServiceConnections": { "value": [ { - "name": "[parameters('name')]", + "name": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.Cache/redis', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'redisCache'), copyIndex()))]", "properties": { "privateLinkServiceId": "[resourceId('Microsoft.Cache/redis', parameters('name'))]", "groupIds": [ @@ -783,9 +794,7 @@ } ] }, - "name": { - "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'name'), format('pep-{0}-{1}-{2}', last(split(resourceId('Microsoft.Cache/redis', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'redisCache'), copyIndex()))]" - }, + "manualPrivateLinkServiceConnections": "[if(equals(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualPrivateLinkServiceConnections'), true()), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.Cache/redis', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'redisCache'), copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId('Microsoft.Cache/redis', parameters('name')), 'groupIds', createArray(coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'redisCache')), 'requestMessage', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualConnectionRequestMessage'), 'Manual approval required.'))))), createObject('value', null()))]", "subnetResourceId": { "value": "[coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId]" }, @@ -810,9 +819,6 @@ "tags": { "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'tags'), parameters('tags'))]" }, - "manualPrivateLinkServiceConnections": { - "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualPrivateLinkServiceConnections')]" - }, "customDnsConfigs": { "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'customDnsConfigs')]" }, @@ -833,8 +839,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "2821141217598568122" + "version": "0.24.24.22086", + "templateHash": "2592884001616184297" }, "name": "Private Endpoints", "description": "This module deploys a Private Endpoint.", @@ -883,7 +889,7 @@ "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\"" + "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": { @@ -961,7 +967,7 @@ "privateIPAddress": { "type": "string", "metadata": { - "description": "Required. A private ip address obtained from the private endpoint's subnet." + "description": "Required. A private IP address obtained from the private endpoint's subnet." } } }, @@ -1064,7 +1070,7 @@ "fqdn": { "type": "string", "metadata": { - "description": "Required. Fqdn that resolves to private endpoint ip address." + "description": "Required. Fqdn that resolves to private endpoint IP address." } }, "ipAddresses": { @@ -1073,7 +1079,7 @@ "type": "string" }, "metadata": { - "description": "Required. A list of private ip addresses of the private endpoint." + "description": "Required. A list of private IP addresses of the private endpoint." } } } @@ -1199,7 +1205,7 @@ "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2023-07-01", - "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.3.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.4.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -1304,8 +1310,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "18168683629401652671" + "version": "0.24.24.22086", + "templateHash": "9321937464667207030" }, "name": "Private Endpoint Private DNS Zone Groups", "description": "This module deploys a Private Endpoint Private DNS Zone Group.", @@ -1416,6 +1422,13 @@ "description": "The location the resource was deployed into." }, "value": "[reference('privateEndpoint', '2023-04-01', 'full').location]" + }, + "groupId": { + "type": "string", + "metadata": { + "description": "The group Id for the private endpoint Group." + }, + "value": "[if(not(empty(reference('privateEndpoint').manualPrivateLinkServiceConnections)), reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties.groupIds[0], reference('privateEndpoint').privateLinkServiceConnections[0].properties.groupIds[0])]" } } } diff --git a/avm/res/cache/redis/tests/e2e/max/main.test.bicep b/avm/res/cache/redis/tests/e2e/max/main.test.bicep index 5ba333465d..cc8bd7dde1 100644 --- a/avm/res/cache/redis/tests/e2e/max/main.test.bicep +++ b/avm/res/cache/redis/tests/e2e/max/main.test.bicep @@ -118,6 +118,12 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' Role: 'DeploymentValidation' } } + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + } ] redisVersion: '6' shardCount: 1 @@ -150,4 +156,8 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' resourceType: 'Redis Cache' } } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] }] diff --git a/avm/res/cache/redis/tests/e2e/waf-aligned/main.test.bicep b/avm/res/cache/redis/tests/e2e/waf-aligned/main.test.bicep index 337a88e772..1a0542d4a3 100644 --- a/avm/res/cache/redis/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/cache/redis/tests/e2e/waf-aligned/main.test.bicep @@ -112,4 +112,8 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' resourceType: 'Redis Cache' } } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] }] diff --git a/avm/res/cache/redis/version.json b/avm/res/cache/redis/version.json index 7fa401bdf7..1c035df49f 100644 --- a/avm/res/cache/redis/version.json +++ b/avm/res/cache/redis/version.json @@ -1,7 +1,7 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.1", + "version": "0.2", "pathFilters": [ "./main.json" ] -} +} \ No newline at end of file diff --git a/avm/res/cognitive-services/account/README.md b/avm/res/cognitive-services/account/README.md index 2e5dc2db5d..7829d5f201 100644 --- a/avm/res/cognitive-services/account/README.md +++ b/avm/res/cognitive-services/account/README.md @@ -184,6 +184,12 @@ module account 'br/public:avm/res/cognitive-services/account:' = { Role: 'DeploymentValidation' } } + { + privateDnsZoneResourceIds: [ + '' + ] + subnetResourceId: '' + } ] publicNetworkAccess: 'Disabled' roleAssignments: [ @@ -323,6 +329,12 @@ module account 'br/public:avm/res/cognitive-services/account:' = { "hidden-title": "This is visible in the resource name", "Role": "DeploymentValidation" } + }, + { + "privateDnsZoneResourceIds": [ + "" + ], + "subnetResourceId": "" } ] }, @@ -1222,14 +1234,15 @@ Configuration details for private endpoints. For security reasons, it is recomme | [`customNetworkInterfaceName`](#parameter-privateendpointscustomnetworkinterfacename) | string | The custom name of the network interface attached to the private endpoint. | | [`enableTelemetry`](#parameter-privateendpointsenabletelemetry) | bool | Enable/Disable usage telemetry for module. | | [`ipConfigurations`](#parameter-privateendpointsipconfigurations) | array | A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints. | +| [`isManualConnection`](#parameter-privateendpointsismanualconnection) | bool | If Manual Private Link Connection is required. | | [`location`](#parameter-privateendpointslocation) | string | The location to deploy the private endpoint to. | | [`lock`](#parameter-privateendpointslock) | object | Specify the type of lock. | -| [`manualPrivateLinkServiceConnections`](#parameter-privateendpointsmanualprivatelinkserviceconnections) | array | Manual PrivateLink Service Connections. | +| [`manualConnectionRequestMessage`](#parameter-privateendpointsmanualconnectionrequestmessage) | string | A message passed to the owner of the remote resource with the manual connection request. | | [`name`](#parameter-privateendpointsname) | string | The name of the private endpoint. | | [`privateDnsZoneGroupName`](#parameter-privateendpointsprivatednszonegroupname) | string | The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided. | | [`privateDnsZoneResourceIds`](#parameter-privateendpointsprivatednszoneresourceids) | array | The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones. | | [`roleAssignments`](#parameter-privateendpointsroleassignments) | array | Array of role assignments to create. | -| [`service`](#parameter-privateendpointsservice) | string | The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob". | +| [`service`](#parameter-privateendpointsservice) | string | The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory". | | [`tags`](#parameter-privateendpointstags) | object | Tags to be applied on all resources/resource groups in this deployment. | ### Parameter: `privateEndpoints.subnetResourceId` @@ -1345,6 +1358,13 @@ A private IP address obtained from the private endpoint's subnet. - Required: Yes - Type: string +### Parameter: `privateEndpoints.isManualConnection` + +If Manual Private Link Connection is required. + +- Required: No +- Type: bool + ### Parameter: `privateEndpoints.location` The location to deploy the private endpoint to. @@ -1388,12 +1408,12 @@ Specify the name of lock. - Required: No - Type: string -### Parameter: `privateEndpoints.manualPrivateLinkServiceConnections` +### Parameter: `privateEndpoints.manualConnectionRequestMessage` -Manual PrivateLink Service Connections. +A message passed to the owner of the remote resource with the manual connection request. - Required: No -- Type: array +- Type: string ### Parameter: `privateEndpoints.name` @@ -1507,7 +1527,7 @@ The principal type of the assigned principal ID. ### Parameter: `privateEndpoints.service` -The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob". +The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory". - Required: No - Type: string @@ -1702,7 +1722,7 @@ This section gives you an overview of all local-referenced module files (i.e., o | Reference | Type | | :-- | :-- | -| `br/public:avm/res/network/private-endpoint:0.3.1` | Remote reference | +| `br/public:avm/res/network/private-endpoint:0.4.0` | Remote reference | ## Data Collection diff --git a/avm/res/cognitive-services/account/main.bicep b/avm/res/cognitive-services/account/main.bicep index 05149ac191..55a51646ae 100644 --- a/avm/res/cognitive-services/account/main.bicep +++ b/avm/res/cognitive-services/account/main.bicep @@ -265,12 +265,13 @@ resource cognitiveService_diagnosticSettings 'Microsoft.Insights/diagnosticSetti scope: cognitiveService }] -module cognitiveService_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.3.1' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { +module cognitiveService_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { name: '${uniqueString(deployment().name, location)}-CognitiveService-PrivateEndpoint-${index}' params: { + name: privateEndpoint.?name ?? 'pep-${last(split(cognitiveService.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' privateLinkServiceConnections: [ { - name: name + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(cognitiveService.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' properties: { privateLinkServiceId: cognitiveService.id groupIds: [ @@ -279,7 +280,18 @@ module cognitiveService_privateEndpoints 'br/public:avm/res/network/private-endp } } ] - name: privateEndpoint.?name ?? 'pep-${last(split(cognitiveService.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(cognitiveService.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' + properties: { + privateLinkServiceId: cognitiveService.id + groupIds: [ + privateEndpoint.?service ?? 'account' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } + ] : null subnetResourceId: privateEndpoint.subnetResourceId enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location @@ -288,7 +300,6 @@ module cognitiveService_privateEndpoints 'br/public:avm/res/network/private-endp privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds roleAssignments: privateEndpoint.?roleAssignments tags: privateEndpoint.?tags ?? tags - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections customDnsConfigs: privateEndpoint.?customDnsConfigs ipConfigurations: privateEndpoint.?ipConfigurations applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds @@ -406,7 +417,7 @@ type privateEndpointType = { @description('Optional. The location to deploy the private endpoint to.') location: string? - @description('Optional. The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob".') + @description('Optional. The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory".') service: string? @description('Required. Resource ID of the subnet where the endpoint needs to be created.') @@ -418,6 +429,13 @@ type privateEndpointType = { @description('Optional. The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones.') privateDnsZoneResourceIds: string[]? + @description('Optional. If Manual Private Link Connection is required.') + isManualConnection: bool? + + @description('Optional. A message passed to the owner of the remote resource with the manual connection request.') + @maxLength(140) + manualConnectionRequestMessage: string? + @description('Optional. Custom DNS configurations.') customDnsConfigs: { @description('Required. Fqdn that resolves to private endpoint IP address.') @@ -455,14 +473,11 @@ type privateEndpointType = { lock: lockType @description('Optional. Array of role assignments to create.') - roleAssignments: roleAssignmentType? + roleAssignments: roleAssignmentType @description('Optional. Tags to be applied on all resources/resource groups in this deployment.') tags: object? - @description('Optional. Manual PrivateLink Service Connections.') - manualPrivateLinkServiceConnections: array? - @description('Optional. Enable/Disable usage telemetry for module.') enableTelemetry: bool? }[]? diff --git a/avm/res/cognitive-services/account/main.json b/avm/res/cognitive-services/account/main.json index 97ad908e5b..a45302ba9e 100644 --- a/avm/res/cognitive-services/account/main.json +++ b/avm/res/cognitive-services/account/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "6619617132004799661" + "templateHash": "6670691272648355802" }, "name": "Cognitive Services", "description": "This module deploys a Cognitive Service.", @@ -222,7 +222,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Optional. The service (sub-) type to deploy the private endpoint for. For example \"vault\" or \"blob\"." + "description": "Optional. The subresource to deploy the private endpoint for. For example \"vault\", \"mysqlServer\" or \"dataFactory\"." } }, "subnetResourceId": { @@ -248,6 +248,21 @@ "description": "Optional. The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones." } }, + "isManualConnection": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. If Manual Private Link Connection is required." + } + }, + "manualConnectionRequestMessage": { + "type": "string", + "nullable": true, + "maxLength": 140, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." + } + }, "customDnsConfigs": { "type": "array", "items": { @@ -345,7 +360,6 @@ }, "roleAssignments": { "$ref": "#/definitions/roleAssignmentType", - "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -357,13 +371,6 @@ "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." } }, - "manualPrivateLinkServiceConnections": { - "type": "array", - "nullable": true, - "metadata": { - "description": "Optional. Manual PrivateLink Service Connections." - } - }, "enableTelemetry": { "type": "bool", "nullable": true, @@ -873,10 +880,13 @@ }, "mode": "Incremental", "parameters": { + "name": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'name'), format('pep-{0}-{1}-{2}', last(split(resourceId('Microsoft.CognitiveServices/accounts', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'account'), copyIndex()))]" + }, "privateLinkServiceConnections": { "value": [ { - "name": "[parameters('name')]", + "name": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.CognitiveServices/accounts', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'account'), copyIndex()))]", "properties": { "privateLinkServiceId": "[resourceId('Microsoft.CognitiveServices/accounts', parameters('name'))]", "groupIds": [ @@ -886,9 +896,7 @@ } ] }, - "name": { - "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'name'), format('pep-{0}-{1}-{2}', last(split(resourceId('Microsoft.CognitiveServices/accounts', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'account'), copyIndex()))]" - }, + "manualPrivateLinkServiceConnections": "[if(equals(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualPrivateLinkServiceConnections'), true()), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.CognitiveServices/accounts', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'account'), copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId('Microsoft.CognitiveServices/accounts', parameters('name')), 'groupIds', createArray(coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'account')), 'requestMessage', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualConnectionRequestMessage'), 'Manual approval required.'))))), createObject('value', null()))]", "subnetResourceId": { "value": "[coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId]" }, @@ -913,9 +921,6 @@ "tags": { "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'tags'), parameters('tags'))]" }, - "manualPrivateLinkServiceConnections": { - "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualPrivateLinkServiceConnections')]" - }, "customDnsConfigs": { "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'customDnsConfigs')]" }, @@ -936,8 +941,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "2821141217598568122" + "version": "0.24.24.22086", + "templateHash": "2592884001616184297" }, "name": "Private Endpoints", "description": "This module deploys a Private Endpoint.", @@ -986,7 +991,7 @@ "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\"" + "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": { @@ -1064,7 +1069,7 @@ "privateIPAddress": { "type": "string", "metadata": { - "description": "Required. A private ip address obtained from the private endpoint's subnet." + "description": "Required. A private IP address obtained from the private endpoint's subnet." } } }, @@ -1167,7 +1172,7 @@ "fqdn": { "type": "string", "metadata": { - "description": "Required. Fqdn that resolves to private endpoint ip address." + "description": "Required. Fqdn that resolves to private endpoint IP address." } }, "ipAddresses": { @@ -1176,7 +1181,7 @@ "type": "string" }, "metadata": { - "description": "Required. A list of private ip addresses of the private endpoint." + "description": "Required. A list of private IP addresses of the private endpoint." } } } @@ -1302,7 +1307,7 @@ "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2023-07-01", - "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.3.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.4.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -1407,8 +1412,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "18168683629401652671" + "version": "0.24.24.22086", + "templateHash": "9321937464667207030" }, "name": "Private Endpoint Private DNS Zone Groups", "description": "This module deploys a Private Endpoint Private DNS Zone Group.", @@ -1519,6 +1524,13 @@ "description": "The location the resource was deployed into." }, "value": "[reference('privateEndpoint', '2023-04-01', 'full').location]" + }, + "groupId": { + "type": "string", + "metadata": { + "description": "The group Id for the private endpoint Group." + }, + "value": "[if(not(empty(reference('privateEndpoint').manualPrivateLinkServiceConnections)), reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties.groupIds[0], reference('privateEndpoint').privateLinkServiceConnections[0].properties.groupIds[0])]" } } } diff --git a/avm/res/cognitive-services/account/tests/e2e/max/main.test.bicep b/avm/res/cognitive-services/account/tests/e2e/max/main.test.bicep index e13f8afd9f..c133cecb59 100644 --- a/avm/res/cognitive-services/account/tests/e2e/max/main.test.bicep +++ b/avm/res/cognitive-services/account/tests/e2e/max/main.test.bicep @@ -162,6 +162,12 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' } ] } + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + } ] tags: { 'hidden-title': 'This is visible in the resource name' @@ -169,4 +175,8 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' Role: 'DeploymentValidation' } } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] }] diff --git a/avm/res/cognitive-services/account/tests/e2e/speech/main.test.bicep b/avm/res/cognitive-services/account/tests/e2e/speech/main.test.bicep index e349981b03..d115398bf1 100644 --- a/avm/res/cognitive-services/account/tests/e2e/speech/main.test.bicep +++ b/avm/res/cognitive-services/account/tests/e2e/speech/main.test.bicep @@ -79,4 +79,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' Role: 'DeploymentValidation' } } + dependsOn: [ + nestedDependencies + ] }] diff --git a/avm/res/cognitive-services/account/tests/e2e/system-assigned-cmk-encryption/main.test.bicep b/avm/res/cognitive-services/account/tests/e2e/system-assigned-cmk-encryption/main.test.bicep index e657ba486b..3e79483631 100644 --- a/avm/res/cognitive-services/account/tests/e2e/system-assigned-cmk-encryption/main.test.bicep +++ b/avm/res/cognitive-services/account/tests/e2e/system-assigned-cmk-encryption/main.test.bicep @@ -68,4 +68,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' } restrictOutboundNetworkAccess: false } + dependsOn: [ + nestedDependencies + ] }] diff --git a/avm/res/cognitive-services/account/tests/e2e/user-assigned-cmk-encryption/main.test.bicep b/avm/res/cognitive-services/account/tests/e2e/user-assigned-cmk-encryption/main.test.bicep index 241ca59ae4..f161025c18 100644 --- a/avm/res/cognitive-services/account/tests/e2e/user-assigned-cmk-encryption/main.test.bicep +++ b/avm/res/cognitive-services/account/tests/e2e/user-assigned-cmk-encryption/main.test.bicep @@ -71,4 +71,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' } restrictOutboundNetworkAccess: false } + dependsOn: [ + nestedDependencies + ] }] diff --git a/avm/res/cognitive-services/account/tests/e2e/waf-aligned/main.test.bicep b/avm/res/cognitive-services/account/tests/e2e/waf-aligned/main.test.bicep index 41d53958ca..362a8ade16 100644 --- a/avm/res/cognitive-services/account/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/cognitive-services/account/tests/e2e/waf-aligned/main.test.bicep @@ -102,4 +102,8 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' systemAssigned: true } } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] }] diff --git a/avm/res/cognitive-services/account/version.json b/avm/res/cognitive-services/account/version.json index c177b1bb58..3f863a2bec 100644 --- a/avm/res/cognitive-services/account/version.json +++ b/avm/res/cognitive-services/account/version.json @@ -1,6 +1,6 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.3", + "version": "0.4", "pathFilters": [ "./main.json" ] diff --git a/avm/res/container-registry/registry/README.md b/avm/res/container-registry/registry/README.md index 9c96fdf622..12a6dca930 100644 --- a/avm/res/container-registry/registry/README.md +++ b/avm/res/container-registry/registry/README.md @@ -36,8 +36,7 @@ The following section provides usage examples for the module, which were used to - [Using only defaults](#example-1-using-only-defaults) - [Using encryption with Customer-Managed-Key](#example-2-using-encryption-with-customer-managed-key) - [Using large parameter set](#example-3-using-large-parameter-set) -- [Using private endpoint](#example-4-using-private-endpoint) -- [WAF-aligned](#example-5-waf-aligned) +- [WAF-aligned](#example-4-waf-aligned) ### Example 1: _Using only defaults_ @@ -233,7 +232,6 @@ module registry 'br/public:avm/res/container-registry/registry:' = { privateDnsZoneResourceIds: [ '' ] - service: 'registry' subnetResourceId: '' tags: { Environment: 'Non-Prod' @@ -241,6 +239,12 @@ module registry 'br/public:avm/res/container-registry/registry:' = { Role: 'DeploymentValidation' } } + { + privateDnsZoneResourceIds: [ + '' + ] + subnetResourceId: '' + } ] quarantinePolicyStatus: 'enabled' replications: [ @@ -372,13 +376,18 @@ module registry 'br/public:avm/res/container-registry/registry:' = { "privateDnsZoneResourceIds": [ "" ], - "service": "registry", "subnetResourceId": "", "tags": { "Environment": "Non-Prod", "hidden-title": "This is visible in the resource name", "Role": "DeploymentValidation" } + }, + { + "privateDnsZoneResourceIds": [ + "" + ], + "subnetResourceId": "" } ] }, @@ -443,77 +452,7 @@ module registry 'br/public:avm/res/container-registry/registry:' = {

-### Example 4: _Using private endpoint_ - -This instance deploys the module with a private endpoint. - - -

- -via Bicep module - -```bicep -module registry 'br/public:avm/res/container-registry/registry:' = { - name: '${uniqueString(deployment().name, resourceLocation)}-test-crrpe' - params: { - // Required parameters - name: 'crrpe001' - // Non-required parameters - acrSku: 'Premium' - location: '' - privateEndpoints: [ - { - privateDnsZoneResourceIds: [ - '' - ] - subnetResourceId: '' - } - ] - } -} -``` - -
-

- -

- -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 - "name": { - "value": "crrpe001" - }, - // Non-required parameters - "acrSku": { - "value": "Premium" - }, - "location": { - "value": "" - }, - "privateEndpoints": { - "value": [ - { - "privateDnsZoneResourceIds": [ - "" - ], - "subnetResourceId": "" - } - ] - } - } -} -``` - -
-

- -### Example 5: _WAF-aligned_ +### Example 4: _WAF-aligned_ This instance deploys the module in alignment with the best-practices of the Azure Well-Architected Framework. @@ -1098,14 +1037,15 @@ Configuration details for private endpoints. For security reasons, it is recomme | [`customNetworkInterfaceName`](#parameter-privateendpointscustomnetworkinterfacename) | string | The custom name of the network interface attached to the private endpoint. | | [`enableTelemetry`](#parameter-privateendpointsenabletelemetry) | bool | Enable/Disable usage telemetry for module. | | [`ipConfigurations`](#parameter-privateendpointsipconfigurations) | array | A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints. | +| [`isManualConnection`](#parameter-privateendpointsismanualconnection) | bool | If Manual Private Link Connection is required. | | [`location`](#parameter-privateendpointslocation) | string | The location to deploy the private endpoint to. | | [`lock`](#parameter-privateendpointslock) | object | Specify the type of lock. | -| [`manualPrivateLinkServiceConnections`](#parameter-privateendpointsmanualprivatelinkserviceconnections) | array | Manual PrivateLink Service Connections. | +| [`manualConnectionRequestMessage`](#parameter-privateendpointsmanualconnectionrequestmessage) | string | A message passed to the owner of the remote resource with the manual connection request. | | [`name`](#parameter-privateendpointsname) | string | The name of the private endpoint. | -| [`privateDnsZoneGroupName`](#parameter-privateendpointsprivatednszonegroupname) | string | The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided. | +| [`privateDnsZoneGroupName`](#parameter-privateendpointsprivatednszonegroupname) | string | The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided. | | [`privateDnsZoneResourceIds`](#parameter-privateendpointsprivatednszoneresourceids) | array | The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones. | | [`roleAssignments`](#parameter-privateendpointsroleassignments) | array | Array of role assignments to create. | -| [`service`](#parameter-privateendpointsservice) | string | The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob". | +| [`service`](#parameter-privateendpointsservice) | string | The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory". | | [`tags`](#parameter-privateendpointstags) | object | Tags to be applied on all resources/resource groups in this deployment. | ### Parameter: `privateEndpoints.subnetResourceId` @@ -1133,19 +1073,19 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint ip address. | -| [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private ip addresses of the private endpoint. | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | +| [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | ### Parameter: `privateEndpoints.customDnsConfigs.fqdn` -Fqdn that resolves to private endpoint ip address. +Fqdn that resolves to private endpoint IP address. - Required: No - Type: string ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` -A list of private ip addresses of the private endpoint. +A list of private IP addresses of the private endpoint. - Required: Yes - Type: array @@ -1198,7 +1138,7 @@ Properties of private endpoint IP configurations. | :-- | :-- | :-- | | [`groupId`](#parameter-privateendpointsipconfigurationspropertiesgroupid) | string | The ID of a group obtained from the remote resource that this private endpoint should connect to. | | [`memberName`](#parameter-privateendpointsipconfigurationspropertiesmembername) | string | The member name of a group obtained from the remote resource that this private endpoint should connect to. | -| [`privateIPAddress`](#parameter-privateendpointsipconfigurationspropertiesprivateipaddress) | string | A private ip address obtained from the private endpoint's subnet. | +| [`privateIPAddress`](#parameter-privateendpointsipconfigurationspropertiesprivateipaddress) | string | A private IP address obtained from the private endpoint's subnet. | ### Parameter: `privateEndpoints.ipConfigurations.properties.groupId` @@ -1216,11 +1156,18 @@ The member name of a group obtained from the remote resource that this private e ### Parameter: `privateEndpoints.ipConfigurations.properties.privateIPAddress` -A private ip address obtained from the private endpoint's subnet. +A private IP address obtained from the private endpoint's subnet. - Required: Yes - Type: string +### Parameter: `privateEndpoints.isManualConnection` + +If Manual Private Link Connection is required. + +- Required: No +- Type: bool + ### Parameter: `privateEndpoints.location` The location to deploy the private endpoint to. @@ -1264,12 +1211,12 @@ Specify the name of lock. - Required: No - Type: string -### Parameter: `privateEndpoints.manualPrivateLinkServiceConnections` +### Parameter: `privateEndpoints.manualConnectionRequestMessage` -Manual PrivateLink Service Connections. +A message passed to the owner of the remote resource with the manual connection request. - Required: No -- Type: array +- Type: string ### Parameter: `privateEndpoints.name` @@ -1280,7 +1227,7 @@ The name of the private endpoint. ### Parameter: `privateEndpoints.privateDnsZoneGroupName` -The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided. +The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided. - Required: No - Type: string @@ -1383,7 +1330,7 @@ The principal type of the assigned principal ID. ### Parameter: `privateEndpoints.service` -The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob". +The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory". - Required: No - Type: string @@ -1628,7 +1575,7 @@ This section gives you an overview of all local-referenced module files (i.e., o | Reference | Type | | :-- | :-- | -| `br/public:avm/res/network/private-endpoint:0.3.2` | Remote reference | +| `br/public:avm/res/network/private-endpoint:0.4.0` | Remote reference | ## Data Collection diff --git a/avm/res/container-registry/registry/main.bicep b/avm/res/container-registry/registry/main.bicep index 8c33bc7154..05bd6d96d4 100644 --- a/avm/res/container-registry/registry/main.bicep +++ b/avm/res/container-registry/registry/main.bicep @@ -334,12 +334,13 @@ resource registry_roleAssignments 'Microsoft.Authorization/roleAssignments@2022- scope: registry }] -module registry_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.3.2' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { +module registry_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { name: '${uniqueString(deployment().name, location)}-registry-PrivateEndpoint-${index}' params: { + name: privateEndpoint.?name ?? 'pep-${last(split(registry.id, '/'))}-${privateEndpoint.?service ?? 'registry'}-${index}' privateLinkServiceConnections: [ { - name: name + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(registry.id, '/'))}-${privateEndpoint.?service ?? 'registry'}-${index}' properties: { privateLinkServiceId: registry.id groupIds: [ @@ -348,7 +349,18 @@ module registry_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.3 } } ] - name: privateEndpoint.?name ?? 'pep-${last(split(registry.id, '/'))}-${privateEndpoint.?service ?? 'registry'}-${index}' + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(registry.id, '/'))}-${privateEndpoint.?service ?? 'registry'}-${index}' + properties: { + privateLinkServiceId: registry.id + groupIds: [ + privateEndpoint.?service ?? 'registry' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } + ] : null subnetResourceId: privateEndpoint.subnetResourceId enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location @@ -357,7 +369,6 @@ module registry_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.3 privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds roleAssignments: privateEndpoint.?roleAssignments tags: privateEndpoint.?tags ?? tags - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections customDnsConfigs: privateEndpoint.?customDnsConfigs ipConfigurations: privateEndpoint.?ipConfigurations applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds @@ -433,24 +444,31 @@ type privateEndpointType = { @description('Optional. The location to deploy the private endpoint to.') location: string? - @description('Optional. The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob".') + @description('Optional. The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory".') service: string? @description('Required. Resource ID of the subnet where the endpoint needs to be created.') subnetResourceId: string - @description('Optional. The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided.') + @description('Optional. The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided.') privateDnsZoneGroupName: string? @description('Optional. The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones.') privateDnsZoneResourceIds: string[]? + @description('Optional. If Manual Private Link Connection is required.') + isManualConnection: bool? + + @description('Optional. A message passed to the owner of the remote resource with the manual connection request.') + @maxLength(140) + manualConnectionRequestMessage: string? + @description('Optional. Custom DNS configurations.') customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint ip address.') + @description('Required. Fqdn that resolves to private endpoint IP address.') fqdn: string? - @description('Required. A list of private ip addresses of the private endpoint.') + @description('Required. A list of private IP addresses of the private endpoint.') ipAddresses: string[] }[]? @@ -467,7 +485,7 @@ type privateEndpointType = { @description('Required. The member name of a group obtained from the remote resource that this private endpoint should connect to.') memberName: string - @description('Required. A private ip address obtained from the private endpoint\'s subnet.') + @description('Required. A private IP address obtained from the private endpoint\'s subnet.') privateIPAddress: string } }[]? @@ -487,9 +505,6 @@ type privateEndpointType = { @description('Optional. Tags to be applied on all resources/resource groups in this deployment.') tags: object? - @description('Optional. Manual PrivateLink Service Connections.') - manualPrivateLinkServiceConnections: array? - @description('Optional. Enable/Disable usage telemetry for module.') enableTelemetry: bool? }[]? diff --git a/avm/res/container-registry/registry/main.json b/avm/res/container-registry/registry/main.json index fb6accc837..e08259390f 100644 --- a/avm/res/container-registry/registry/main.json +++ b/avm/res/container-registry/registry/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "3316618601179718411" + "templateHash": "9195818754355186204" }, "name": "Azure Container Registries (ACR)", "description": "This module deploys an Azure Container Registry (ACR).", @@ -150,7 +150,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Optional. The service (sub-) type to deploy the private endpoint for. For example \"vault\" or \"blob\"." + "description": "Optional. The subresource to deploy the private endpoint for. For example \"vault\", \"mysqlServer\" or \"dataFactory\"." } }, "subnetResourceId": { @@ -163,7 +163,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Optional. The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided." + "description": "Optional. The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided." } }, "privateDnsZoneResourceIds": { @@ -176,6 +176,21 @@ "description": "Optional. The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones." } }, + "isManualConnection": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. If Manual Private Link Connection is required." + } + }, + "manualConnectionRequestMessage": { + "type": "string", + "nullable": true, + "maxLength": 140, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." + } + }, "customDnsConfigs": { "type": "array", "items": { @@ -185,7 +200,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint ip address." + "description": "Required. Fqdn that resolves to private endpoint IP address." } }, "ipAddresses": { @@ -194,7 +209,7 @@ "type": "string" }, "metadata": { - "description": "Required. A list of private ip addresses of the private endpoint." + "description": "Required. A list of private IP addresses of the private endpoint." } } } @@ -233,7 +248,7 @@ "privateIPAddress": { "type": "string", "metadata": { - "description": "Required. A private ip address obtained from the private endpoint's subnet." + "description": "Required. A private IP address obtained from the private endpoint's subnet." } } }, @@ -284,13 +299,6 @@ "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." } }, - "manualPrivateLinkServiceConnections": { - "type": "array", - "nullable": true, - "metadata": { - "description": "Optional. Manual PrivateLink Service Connections." - } - }, "enableTelemetry": { "type": "bool", "nullable": true, @@ -1402,10 +1410,13 @@ }, "mode": "Incremental", "parameters": { + "name": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'name'), format('pep-{0}-{1}-{2}', last(split(resourceId('Microsoft.ContainerRegistry/registries', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'registry'), copyIndex()))]" + }, "privateLinkServiceConnections": { "value": [ { - "name": "[parameters('name')]", + "name": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.ContainerRegistry/registries', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'registry'), copyIndex()))]", "properties": { "privateLinkServiceId": "[resourceId('Microsoft.ContainerRegistry/registries', parameters('name'))]", "groupIds": [ @@ -1415,9 +1426,7 @@ } ] }, - "name": { - "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'name'), format('pep-{0}-{1}-{2}', last(split(resourceId('Microsoft.ContainerRegistry/registries', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'registry'), copyIndex()))]" - }, + "manualPrivateLinkServiceConnections": "[if(equals(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualPrivateLinkServiceConnections'), true()), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.ContainerRegistry/registries', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'registry'), copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId('Microsoft.ContainerRegistry/registries', parameters('name')), 'groupIds', createArray(coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'registry')), 'requestMessage', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualConnectionRequestMessage'), 'Manual approval required.'))))), createObject('value', null()))]", "subnetResourceId": { "value": "[coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId]" }, @@ -1442,9 +1451,6 @@ "tags": { "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'tags'), parameters('tags'))]" }, - "manualPrivateLinkServiceConnections": { - "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualPrivateLinkServiceConnections')]" - }, "customDnsConfigs": { "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'customDnsConfigs')]" }, @@ -1465,8 +1471,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "2821141217598568122" + "version": "0.24.24.22086", + "templateHash": "2592884001616184297" }, "name": "Private Endpoints", "description": "This module deploys a Private Endpoint.", @@ -1515,7 +1521,7 @@ "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\"" + "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": { @@ -1831,7 +1837,7 @@ "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2023-07-01", - "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.3.2', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.4.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -1936,8 +1942,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "18168683629401652671" + "version": "0.24.24.22086", + "templateHash": "9321937464667207030" }, "name": "Private Endpoint Private DNS Zone Groups", "description": "This module deploys a Private Endpoint Private DNS Zone Group.", @@ -2048,6 +2054,13 @@ "description": "The location the resource was deployed into." }, "value": "[reference('privateEndpoint', '2023-04-01', 'full').location]" + }, + "groupId": { + "type": "string", + "metadata": { + "description": "The group Id for the private endpoint Group." + }, + "value": "[if(not(empty(reference('privateEndpoint').manualPrivateLinkServiceConnections)), reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties.groupIds[0], reference('privateEndpoint').privateLinkServiceConnections[0].properties.groupIds[0])]" } } } diff --git a/avm/res/container-registry/registry/tests/e2e/encr/main.test.bicep b/avm/res/container-registry/registry/tests/e2e/encr/main.test.bicep index bf33665f09..740e8c19d6 100644 --- a/avm/res/container-registry/registry/tests/e2e/encr/main.test.bicep +++ b/avm/res/container-registry/registry/tests/e2e/encr/main.test.bicep @@ -70,4 +70,7 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ] } } + dependsOn: [ + nestedDependencies + ] }] diff --git a/avm/res/container-registry/registry/tests/e2e/max/main.test.bicep b/avm/res/container-registry/registry/tests/e2e/max/main.test.bicep index 38d182fd5a..6153fdefb5 100644 --- a/avm/res/container-registry/registry/tests/e2e/max/main.test.bicep +++ b/avm/res/container-registry/registry/tests/e2e/max/main.test.bicep @@ -94,7 +94,6 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' } privateEndpoints: [ { - service: 'registry' subnetResourceId: nestedDependencies.outputs.subnetResourceId privateDnsZoneResourceIds: [ nestedDependencies.outputs.privateDNSZoneResourceId @@ -105,6 +104,12 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' Role: 'DeploymentValidation' } } + { + subnetResourceId: nestedDependencies.outputs.subnetResourceId + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + } ] networkRuleSetIpRules: [ { @@ -165,4 +170,8 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' Role: 'DeploymentValidation' } } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] }] diff --git a/avm/res/container-registry/registry/tests/e2e/pe/dependencies.bicep b/avm/res/container-registry/registry/tests/e2e/pe/dependencies.bicep deleted file mode 100644 index 0422180c41..0000000000 --- a/avm/res/container-registry/registry/tests/e2e/pe/dependencies.bicep +++ /dev/null @@ -1,49 +0,0 @@ -@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: 'defaultSubnet' - properties: { - addressPrefix: cidrSubnet(addressPrefix, 16, 0) - } - } - ] - } -} - -resource privateDNSZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { - name: 'privatelink${environment().suffixes.acrLoginServer}' - location: 'global' - - resource virtualNetworkLinks 'virtualNetworkLinks@2020-06-01' = { - name: '${virtualNetwork.name}-vnetlink' - location: 'global' - properties: { - virtualNetwork: { - id: virtualNetwork.id - } - registrationEnabled: false - } - } -} - -@description('The resource ID of the created Virtual Network Subnet.') -output subnetResourceId string = virtualNetwork.properties.subnets[0].id - -@description('The resource ID of the created Private DNS Zone.') -output privateDNSZoneResourceId string = privateDNSZone.id diff --git a/avm/res/container-registry/registry/tests/e2e/pe/main.test.bicep b/avm/res/container-registry/registry/tests/e2e/pe/main.test.bicep deleted file mode 100644 index f56d0c49e3..0000000000 --- a/avm/res/container-registry/registry/tests/e2e/pe/main.test.bicep +++ /dev/null @@ -1,64 +0,0 @@ -targetScope = 'subscription' - -metadata name = 'Using private endpoint' -metadata description = 'This instance deploys the module with a private endpoint.' - -// ========== // -// Parameters // -// ========== // - -@description('Optional. The name of the resource group to deploy for testing purposes.') -@maxLength(90) -param resourceGroupName string = 'dep-${namePrefix}-containerregistry.registries-${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 = 'crrpe' - -@description('Optional. A token to inject into the name of each resource.') -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: { - virtualNetworkName: 'dep-${namePrefix}-vnet-${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}001' - location: resourceLocation - acrSku: 'Premium' - privateEndpoints: [ - { - subnetResourceId: nestedDependencies.outputs.subnetResourceId - privateDnsZoneResourceIds: [ - nestedDependencies.outputs.privateDNSZoneResourceId - ] - } - ] - } -}] diff --git a/avm/res/container-registry/registry/tests/e2e/waf-aligned/main.test.bicep b/avm/res/container-registry/registry/tests/e2e/waf-aligned/main.test.bicep index 284f517de9..c046264a97 100644 --- a/avm/res/container-registry/registry/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/container-registry/registry/tests/e2e/waf-aligned/main.test.bicep @@ -94,4 +94,8 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' Role: 'DeploymentValidation' } } + dependsOn: [ + nestedDependencies + diagnosticDependencies + ] }] diff --git a/avm/res/container-registry/registry/version.json b/avm/res/container-registry/registry/version.json index 83083db694..1c035df49f 100644 --- a/avm/res/container-registry/registry/version.json +++ b/avm/res/container-registry/registry/version.json @@ -1,6 +1,6 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.1", + "version": "0.2", "pathFilters": [ "./main.json" ] diff --git a/avm/res/data-factory/factory/README.md b/avm/res/data-factory/factory/README.md index 779fdc9c32..c66b9c79f3 100644 --- a/avm/res/data-factory/factory/README.md +++ b/avm/res/data-factory/factory/README.md @@ -173,10 +173,16 @@ module factory 'br/public:avm/res/data-factory/factory:' = { ] subnetResourceId: '' tags: { - application: 'CARML' + application: 'AVM' 'hidden-title': 'This is visible in the resource name' } } + { + privateDnsZoneResourceIds: [ + '' + ] + subnetResourceId: '' + } ] roleAssignments: [ { @@ -313,9 +319,15 @@ module factory 'br/public:avm/res/data-factory/factory:' = { ], "subnetResourceId": "", "tags": { - "application": "CARML", + "application": "AVM", "hidden-title": "This is visible in the resource name" } + }, + { + "privateDnsZoneResourceIds": [ + "" + ], + "subnetResourceId": "" } ] }, @@ -893,14 +905,15 @@ Configuration Details for private endpoints. For security reasons, it is recomme | [`customNetworkInterfaceName`](#parameter-privateendpointscustomnetworkinterfacename) | string | The custom name of the network interface attached to the private endpoint. | | [`enableTelemetry`](#parameter-privateendpointsenabletelemetry) | bool | Enable/Disable usage telemetry for module. | | [`ipConfigurations`](#parameter-privateendpointsipconfigurations) | array | A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints. | +| [`isManualConnection`](#parameter-privateendpointsismanualconnection) | bool | If Manual Private Link Connection is required. | | [`location`](#parameter-privateendpointslocation) | string | The location to deploy the private endpoint to. | | [`lock`](#parameter-privateendpointslock) | object | Specify the type of lock. | -| [`manualPrivateLinkServiceConnections`](#parameter-privateendpointsmanualprivatelinkserviceconnections) | array | Manual PrivateLink Service Connections. | +| [`manualConnectionRequestMessage`](#parameter-privateendpointsmanualconnectionrequestmessage) | string | A message passed to the owner of the remote resource with the manual connection request. | | [`name`](#parameter-privateendpointsname) | string | The name of the private endpoint. | -| [`privateDnsZoneGroupName`](#parameter-privateendpointsprivatednszonegroupname) | string | The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided. | +| [`privateDnsZoneGroupName`](#parameter-privateendpointsprivatednszonegroupname) | string | The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided. | | [`privateDnsZoneResourceIds`](#parameter-privateendpointsprivatednszoneresourceids) | array | The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones. | | [`roleAssignments`](#parameter-privateendpointsroleassignments) | array | Array of role assignments to create. | -| [`service`](#parameter-privateendpointsservice) | string | The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob". | +| [`service`](#parameter-privateendpointsservice) | string | The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory". | | [`tags`](#parameter-privateendpointstags) | object | Tags to be applied on all resources/resource groups in this deployment. | ### Parameter: `privateEndpoints.subnetResourceId` @@ -928,19 +941,19 @@ Custom DNS configurations. | Parameter | Type | Description | | :-- | :-- | :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint ip address. | -| [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private ip addresses of the private endpoint. | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | string | Fqdn that resolves to private endpoint IP address. | +| [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | array | A list of private IP addresses of the private endpoint. | ### Parameter: `privateEndpoints.customDnsConfigs.fqdn` -Fqdn that resolves to private endpoint ip address. +Fqdn that resolves to private endpoint IP address. - Required: No - Type: string ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` -A list of private ip addresses of the private endpoint. +A list of private IP addresses of the private endpoint. - Required: Yes - Type: array @@ -993,7 +1006,7 @@ Properties of private endpoint IP configurations. | :-- | :-- | :-- | | [`groupId`](#parameter-privateendpointsipconfigurationspropertiesgroupid) | string | The ID of a group obtained from the remote resource that this private endpoint should connect to. | | [`memberName`](#parameter-privateendpointsipconfigurationspropertiesmembername) | string | The member name of a group obtained from the remote resource that this private endpoint should connect to. | -| [`privateIPAddress`](#parameter-privateendpointsipconfigurationspropertiesprivateipaddress) | string | A private ip address obtained from the private endpoint's subnet. | +| [`privateIPAddress`](#parameter-privateendpointsipconfigurationspropertiesprivateipaddress) | string | A private IP address obtained from the private endpoint's subnet. | ### Parameter: `privateEndpoints.ipConfigurations.properties.groupId` @@ -1011,11 +1024,18 @@ The member name of a group obtained from the remote resource that this private e ### Parameter: `privateEndpoints.ipConfigurations.properties.privateIPAddress` -A private ip address obtained from the private endpoint's subnet. +A private IP address obtained from the private endpoint's subnet. - Required: Yes - Type: string +### Parameter: `privateEndpoints.isManualConnection` + +If Manual Private Link Connection is required. + +- Required: No +- Type: bool + ### Parameter: `privateEndpoints.location` The location to deploy the private endpoint to. @@ -1059,12 +1079,12 @@ Specify the name of lock. - Required: No - Type: string -### Parameter: `privateEndpoints.manualPrivateLinkServiceConnections` +### Parameter: `privateEndpoints.manualConnectionRequestMessage` -Manual PrivateLink Service Connections. +A message passed to the owner of the remote resource with the manual connection request. - Required: No -- Type: array +- Type: string ### Parameter: `privateEndpoints.name` @@ -1075,7 +1095,7 @@ The name of the private endpoint. ### Parameter: `privateEndpoints.privateDnsZoneGroupName` -The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided. +The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided. - Required: No - Type: string @@ -1178,7 +1198,7 @@ The principal type of the assigned principal ID. ### Parameter: `privateEndpoints.service` -The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob". +The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory". - Required: No - Type: string @@ -1319,7 +1339,7 @@ This section gives you an overview of all local-referenced module files (i.e., o | Reference | Type | | :-- | :-- | -| `br/public:avm/res/network/private-endpoint:0.3.2` | Remote reference | +| `br/public:avm/res/network/private-endpoint:0.4.0` | Remote reference | ## Notes diff --git a/avm/res/data-factory/factory/main.bicep b/avm/res/data-factory/factory/main.bicep index 77562721b6..9f692af3d6 100644 --- a/avm/res/data-factory/factory/main.bicep +++ b/avm/res/data-factory/factory/main.bicep @@ -226,12 +226,13 @@ resource dataFactory_roleAssignments 'Microsoft.Authorization/roleAssignments@20 scope: dataFactory }] -module dataFactory_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.3.2' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { +module dataFactory_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.4.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { name: '${uniqueString(deployment().name, location)}-dataFactory-PrivateEndpoint-${index}' params: { + name: privateEndpoint.?name ?? 'pep-${last(split(dataFactory.id, '/'))}-${privateEndpoint.?service ?? 'dataFactory'}-${index}' privateLinkServiceConnections: [ { - name: name + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(dataFactory.id, '/'))}-${privateEndpoint.?service ?? 'dataFactory'}-${index}' properties: { privateLinkServiceId: dataFactory.id groupIds: [ @@ -240,7 +241,18 @@ module dataFactory_privateEndpoints 'br/public:avm/res/network/private-endpoint: } } ] - name: privateEndpoint.?name ?? 'pep-${last(split(dataFactory.id, '/'))}-${privateEndpoint.?service ?? 'dataFactory'}-${index}' + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections == true ? [ + { + name: privateEndpoint.?privateLinkServiceConnectionName ?? '${last(split(dataFactory.id, '/'))}-${privateEndpoint.?service ?? 'dataFactory'}-${index}' + properties: { + privateLinkServiceId: dataFactory.id + groupIds: [ + privateEndpoint.?service ?? 'dataFactory' + ] + requestMessage: privateEndpoint.?manualConnectionRequestMessage ?? 'Manual approval required.' + } + } + ] : null subnetResourceId: privateEndpoint.subnetResourceId location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location lock: privateEndpoint.?lock ?? lock @@ -249,7 +261,6 @@ module dataFactory_privateEndpoints 'br/public:avm/res/network/private-endpoint: privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds roleAssignments: privateEndpoint.?roleAssignments tags: privateEndpoint.?tags ?? tags - manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections customDnsConfigs: privateEndpoint.?customDnsConfigs ipConfigurations: privateEndpoint.?ipConfigurations applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds @@ -322,24 +333,31 @@ type privateEndpointType = { @description('Optional. The location to deploy the private endpoint to.') location: string? - @description('Optional. The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob".') + @description('Optional. The subresource to deploy the private endpoint for. For example "vault", "mysqlServer" or "dataFactory".') service: string? @description('Required. Resource ID of the subnet where the endpoint needs to be created.') subnetResourceId: string - @description('Optional. The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided.') + @description('Optional. The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided.') privateDnsZoneGroupName: string? @description('Optional. The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones.') privateDnsZoneResourceIds: string[]? + @description('Optional. If Manual Private Link Connection is required.') + isManualConnection: bool? + + @description('Optional. A message passed to the owner of the remote resource with the manual connection request.') + @maxLength(140) + manualConnectionRequestMessage: string? + @description('Optional. Custom DNS configurations.') customDnsConfigs: { - @description('Required. Fqdn that resolves to private endpoint ip address.') + @description('Required. Fqdn that resolves to private endpoint IP address.') fqdn: string? - @description('Required. A list of private ip addresses of the private endpoint.') + @description('Required. A list of private IP addresses of the private endpoint.') ipAddresses: string[] }[]? @@ -356,7 +374,7 @@ type privateEndpointType = { @description('Required. The member name of a group obtained from the remote resource that this private endpoint should connect to.') memberName: string - @description('Required. A private ip address obtained from the private endpoint\'s subnet.') + @description('Required. A private IP address obtained from the private endpoint\'s subnet.') privateIPAddress: string } }[]? @@ -376,9 +394,6 @@ type privateEndpointType = { @description('Optional. Tags to be applied on all resources/resource groups in this deployment.') tags: object? - @description('Optional. Manual PrivateLink Service Connections.') - manualPrivateLinkServiceConnections: array? - @description('Optional. Enable/Disable usage telemetry for module.') enableTelemetry: bool? }[]? diff --git a/avm/res/data-factory/factory/main.json b/avm/res/data-factory/factory/main.json index ec293b4da5..3d71e6ca6c 100644 --- a/avm/res/data-factory/factory/main.json +++ b/avm/res/data-factory/factory/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.25.53.49325", - "templateHash": "6048154575317305583" + "templateHash": "15512301092613886840" }, "name": "Data Factories", "description": "This module deploys a Data Factory.", @@ -150,7 +150,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Optional. The service (sub-) type to deploy the private endpoint for. For example \"vault\" or \"blob\"." + "description": "Optional. The subresource to deploy the private endpoint for. For example \"vault\", \"mysqlServer\" or \"dataFactory\"." } }, "subnetResourceId": { @@ -163,7 +163,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Optional. The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided." + "description": "Optional. The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided." } }, "privateDnsZoneResourceIds": { @@ -176,6 +176,21 @@ "description": "Optional. The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones." } }, + "isManualConnection": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. If Manual Private Link Connection is required." + } + }, + "manualConnectionRequestMessage": { + "type": "string", + "nullable": true, + "maxLength": 140, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." + } + }, "customDnsConfigs": { "type": "array", "items": { @@ -185,7 +200,7 @@ "type": "string", "nullable": true, "metadata": { - "description": "Required. Fqdn that resolves to private endpoint ip address." + "description": "Required. Fqdn that resolves to private endpoint IP address." } }, "ipAddresses": { @@ -194,7 +209,7 @@ "type": "string" }, "metadata": { - "description": "Required. A list of private ip addresses of the private endpoint." + "description": "Required. A list of private IP addresses of the private endpoint." } } } @@ -233,7 +248,7 @@ "privateIPAddress": { "type": "string", "metadata": { - "description": "Required. A private ip address obtained from the private endpoint's subnet." + "description": "Required. A private IP address obtained from the private endpoint's subnet." } } }, @@ -284,13 +299,6 @@ "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." } }, - "manualPrivateLinkServiceConnections": { - "type": "array", - "nullable": true, - "metadata": { - "description": "Optional. Manual PrivateLink Service Connections." - } - }, "enableTelemetry": { "type": "bool", "nullable": true, @@ -1130,10 +1138,13 @@ }, "mode": "Incremental", "parameters": { + "name": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'name'), format('pep-{0}-{1}-{2}', last(split(resourceId('Microsoft.DataFactory/factories', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'dataFactory'), copyIndex()))]" + }, "privateLinkServiceConnections": { "value": [ { - "name": "[parameters('name')]", + "name": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.DataFactory/factories', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'dataFactory'), copyIndex()))]", "properties": { "privateLinkServiceId": "[resourceId('Microsoft.DataFactory/factories', parameters('name'))]", "groupIds": [ @@ -1143,9 +1154,7 @@ } ] }, - "name": { - "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'name'), format('pep-{0}-{1}-{2}', last(split(resourceId('Microsoft.DataFactory/factories', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'dataFactory'), copyIndex()))]" - }, + "manualPrivateLinkServiceConnections": "[if(equals(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualPrivateLinkServiceConnections'), true()), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.DataFactory/factories', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'dataFactory'), copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId('Microsoft.DataFactory/factories', parameters('name')), 'groupIds', createArray(coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'dataFactory')), 'requestMessage', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualConnectionRequestMessage'), 'Manual approval required.'))))), createObject('value', null()))]", "subnetResourceId": { "value": "[coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId]" }, @@ -1170,9 +1179,6 @@ "tags": { "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'tags'), parameters('tags'))]" }, - "manualPrivateLinkServiceConnections": { - "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualPrivateLinkServiceConnections')]" - }, "customDnsConfigs": { "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'customDnsConfigs')]" }, @@ -1193,8 +1199,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "2821141217598568122" + "version": "0.24.24.22086", + "templateHash": "2592884001616184297" }, "name": "Private Endpoints", "description": "This module deploys a Private Endpoint.", @@ -1243,7 +1249,7 @@ "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\"" + "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": { @@ -1559,7 +1565,7 @@ "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2023-07-01", - "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.3.2', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.4.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -1664,8 +1670,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "18168683629401652671" + "version": "0.24.24.22086", + "templateHash": "9321937464667207030" }, "name": "Private Endpoint Private DNS Zone Groups", "description": "This module deploys a Private Endpoint Private DNS Zone Group.", @@ -1776,6 +1782,13 @@ "description": "The location the resource was deployed into." }, "value": "[reference('privateEndpoint', '2023-04-01', 'full').location]" + }, + "groupId": { + "type": "string", + "metadata": { + "description": "The group Id for the private endpoint Group." + }, + "value": "[if(not(empty(reference('privateEndpoint').manualPrivateLinkServiceConnections)), reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties.groupIds[0], reference('privateEndpoint').privateLinkServiceConnections[0].properties.groupIds[0])]" } } } diff --git a/avm/res/data-factory/factory/tests/e2e/max/main.test.bicep b/avm/res/data-factory/factory/tests/e2e/max/main.test.bicep index 7cabaa0fc7..e825639f2e 100644 --- a/avm/res/data-factory/factory/tests/e2e/max/main.test.bicep +++ b/avm/res/data-factory/factory/tests/e2e/max/main.test.bicep @@ -134,9 +134,15 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' subnetResourceId: nestedDependencies.outputs.subnetResourceId tags: { 'hidden-title': 'This is visible in the resource name' - application: 'CARML' + application: 'AVM' } } + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + } ] roleAssignments: [ { diff --git a/avm/res/data-factory/factory/version.json b/avm/res/data-factory/factory/version.json index 83083db694..1c035df49f 100644 --- a/avm/res/data-factory/factory/version.json +++ b/avm/res/data-factory/factory/version.json @@ -1,6 +1,6 @@ { "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.1", + "version": "0.2", "pathFilters": [ "./main.json" ]