diff --git a/avm/res/batch/batch-account/README.md b/avm/res/batch/batch-account/README.md index 5c5f32c55f..b59fde3e2d 100644 --- a/avm/res/batch/batch-account/README.md +++ b/avm/res/batch/batch-account/README.md @@ -226,6 +226,24 @@ module batchAccount 'br/public:avm/res/batch/batch-account:' = { poolAllocationMode: 'BatchService' privateEndpoints: [ { + customDnsConfigs: [ + { + fqdn: 'abc.batch.com' + ipAddresses: [ + '10.0.0.10' + ] + } + ] + ipConfigurations: [ + { + name: 'myIPconfig' + properties: { + groupId: 'batchAccount' + memberName: 'batchAccount' + privateIPAddress: '10.0.0.10' + } + } + ] privateDnsZoneResourceIds: [ '' ] @@ -343,6 +361,24 @@ module batchAccount 'br/public:avm/res/batch/batch-account:' = { "privateEndpoints": { "value": [ { + "customDnsConfigs": [ + { + "fqdn": "abc.batch.com", + "ipAddresses": [ + "10.0.0.10" + ] + } + ], + "ipConfigurations": [ + { + "name": "myIPconfig", + "properties": { + "groupId": "batchAccount", + "memberName": "batchAccount", + "privateIPAddress": "10.0.0.10" + } + } + ], "privateDnsZoneResourceIds": [ "" ], @@ -895,14 +931,20 @@ Optional. Custom DNS configurations. | Name | Required | Type | Description | | :-- | :-- | :--| :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | No | string | | -| [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | Yes | array | | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | No | string | Required. Fqdn that resolves to private endpoint IP address. | +| [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | Yes | array | Required. A list of private IP addresses of the private endpoint. | ### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +Required. Fqdn that resolves to private endpoint IP address. + - Required: No - Type: string ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` + +Required. A list of private IP addresses of the private endpoint. + - Required: Yes - Type: array @@ -930,28 +972,52 @@ Optional. A list of IP configurations of the private endpoint. This will be used | Name | Required | Type | Description | | :-- | :-- | :--| :-- | -| [`groupId`](#parameter-privateendpointsipconfigurationsgroupid) | Yes | string | | -| [`memberName`](#parameter-privateendpointsipconfigurationsmembername) | Yes | string | | -| [`name`](#parameter-privateendpointsipconfigurationsname) | Yes | string | | -| [`privateIpAddress`](#parameter-privateendpointsipconfigurationsprivateipaddress) | Yes | string | | +| [`name`](#parameter-privateendpointsipconfigurationsname) | Yes | string | Required. The name of the resource that is unique within a resource group. | +| [`properties`](#parameter-privateendpointsipconfigurationsproperties) | Yes | object | Required. Properties of private endpoint IP configurations. | + +### Parameter: `privateEndpoints.ipConfigurations.name` + +Required. The name of the resource that is unique within a resource group. -### Parameter: `privateEndpoints.ipConfigurations.groupId` - Required: Yes - Type: string -### Parameter: `privateEndpoints.ipConfigurations.memberName` +### Parameter: `privateEndpoints.ipConfigurations.properties` + +Required. Properties of private endpoint IP configurations. + +- Required: Yes +- Type: object + +| Name | Required | Type | Description | +| :-- | :-- | :--| :-- | +| [`groupId`](#parameter-privateendpointsipconfigurationspropertiesgroupid) | Yes | string | Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. | +| [`memberName`](#parameter-privateendpointsipconfigurationspropertiesmembername) | Yes | string | Required. The member name of a group obtained from the remote resource that this private endpoint should connect to. | +| [`privateIPAddress`](#parameter-privateendpointsipconfigurationspropertiesprivateipaddress) | Yes | string | Required. A private IP address obtained from the private endpoint's subnet. | + +### Parameter: `privateEndpoints.ipConfigurations.properties.groupId` + +Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. + - Required: Yes - Type: string -### Parameter: `privateEndpoints.ipConfigurations.name` +### Parameter: `privateEndpoints.ipConfigurations.properties.memberName` + +Required. The member name of a group obtained from the remote resource that this private endpoint should connect to. + - Required: Yes - Type: string -### Parameter: `privateEndpoints.ipConfigurations.privateIpAddress` +### Parameter: `privateEndpoints.ipConfigurations.properties.privateIPAddress` + +Required. A private IP address obtained from the private endpoint's subnet. + - Required: Yes - Type: string + ### Parameter: `privateEndpoints.location` Optional. The location to deploy the private endpoint to. @@ -1154,4 +1220,4 @@ 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.2.0` | Remote reference | +| `br/public:avm/res/network/private-endpoint:0.3.1` | Remote reference | diff --git a/avm/res/batch/batch-account/main.bicep b/avm/res/batch/batch-account/main.bicep index 147b04221a..10378fe471 100644 --- a/avm/res/batch/batch-account/main.bicep +++ b/avm/res/batch/batch-account/main.bicep @@ -204,14 +204,21 @@ resource batchAccount_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@ scope: batchAccount }] -module batchAccount_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.2.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { +module batchAccount_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.3.1' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { name: '${uniqueString(deployment().name, location)}-BatchAccount-PrivateEndpoint-${index}' params: { - groupIds: [ - privateEndpoint.?service ?? 'batchAccount' + privateLinkServiceConnections: [ + { + name: name + properties: { + privateLinkServiceId: batchAccount.id + groupIds: [ + privateEndpoint.?service ?? 'batchAccount' + ] + } + } ] name: privateEndpoint.?name ?? 'pep-${last(split(batchAccount.id, '/'))}-${privateEndpoint.?service ?? 'batchAccount'}-${index}' - serviceResourceId: batchAccount.id subnetResourceId: privateEndpoint.subnetResourceId enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location @@ -343,16 +350,29 @@ type privateEndpointType = { @description('Optional. Custom DNS configurations.') customDnsConfigs: { + @description('Required. Fqdn that resolves to private endpoint IP address.') fqdn: string? + + @description('Required. A list of private IP addresses of the private endpoint.') ipAddresses: string[] }[]? @description('Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints.') ipConfigurations: { + @description('Required. The name of the resource that is unique within a resource group.') name: string - groupId: string - memberName: string - privateIpAddress: string + + @description('Required. Properties of private endpoint IP configurations.') + properties: { + @description('Required. The ID of a group obtained from the remote resource that this private endpoint should connect to.') + groupId: string + + @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.') + privateIPAddress: string + } }[]? @description('Optional. Application security groups in which the private endpoint IP configuration is included.') diff --git a/avm/res/batch/batch-account/main.json b/avm/res/batch/batch-account/main.json index 8ba5f23677..1e54643441 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.23.1.45101", - "templateHash": "16960327826957585535" + "templateHash": "2440542999931048241" }, "name": "Batch Accounts", "description": "This module deploys a Batch Account.", @@ -241,12 +241,18 @@ "properties": { "fqdn": { "type": "string", - "nullable": true + "nullable": true, + "metadata": { + "description": "Required. Fqdn that resolves to private endpoint IP address." + } }, "ipAddresses": { "type": "array", "items": { "type": "string" + }, + "metadata": { + "description": "Required. A list of private IP addresses of the private endpoint." } } } @@ -262,16 +268,36 @@ "type": "object", "properties": { "name": { - "type": "string" - }, - "groupId": { - "type": "string" - }, - "memberName": { - "type": "string" + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } }, - "privateIpAddress": { - "type": "string" + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private IP address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } } } }, @@ -768,17 +794,22 @@ }, "mode": "Incremental", "parameters": { - "groupIds": { + "privateLinkServiceConnections": { "value": [ - "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'batchAccount')]" + { + "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()))]" }, - "serviceResourceId": { - "value": "[resourceId('Microsoft.Batch/batchAccounts', parameters('name'))]" - }, "subnetResourceId": { "value": "[coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId]" }, @@ -827,7 +858,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "2788827530274342759" + "templateHash": "2821141217598568122" }, "name": "Private Endpoints", "description": "This module deploys a Private Endpoint.", @@ -842,7 +873,7 @@ "roleDefinitionIdOrName": { "type": "string", "metadata": { - "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead." + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." } }, "principalId": { @@ -924,6 +955,154 @@ } }, "nullable": true + }, + "ipConfigurationsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private ip address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + } + }, + "nullable": true + }, + "manualPrivateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, + "privateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, + "customDnsConfigType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "metadata": { + "description": "Required. Fqdn that resolves to private endpoint ip address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. A list of private ip addresses of the private endpoint." + } + } + } + }, + "nullable": true } }, "parameters": { @@ -939,12 +1118,6 @@ "description": "Required. Resource ID of the subnet where the endpoint needs to be created." } }, - "serviceResourceId": { - "type": "string", - "metadata": { - "description": "Required. Resource ID of the resource that needs to be connected to the network." - } - }, "applicationSecurityGroupResourceIds": { "type": "array", "nullable": true, @@ -960,18 +1133,11 @@ } }, "ipConfigurations": { - "type": "array", - "nullable": true, + "$ref": "#/definitions/ipConfigurationsType", "metadata": { "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." } }, - "groupIds": { - "type": "array", - "metadata": { - "description": "Required. Subtype(s) of the connection to be created. The allowed values depend on the type serviceResourceId refers to." - } - }, "privateDnsZoneGroupName": { "type": "string", "nullable": true, @@ -1002,7 +1168,7 @@ "roleAssignments": { "$ref": "#/definitions/roleAssignmentType", "metadata": { - "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + "description": "Optional. Array of role assignments to create." } }, "tags": { @@ -1013,17 +1179,21 @@ } }, "customDnsConfigs": { - "type": "array", - "nullable": true, + "$ref": "#/definitions/customDnsConfigType", "metadata": { "description": "Optional. Custom DNS configurations." } }, "manualPrivateLinkServiceConnections": { - "type": "array", - "nullable": true, + "$ref": "#/definitions/manualPrivateLinkServiceConnectionsType", "metadata": { - "description": "Optional. Manual PrivateLink Service Connections." + "description": "Optional. A grouping of information about the connection to the remote resource. Used when the network admin does not have access to approve connections to the remote resource." + } + }, + "privateLinkServiceConnections": { + "$ref": "#/definitions/privateLinkServiceConnectionsType", + "metadata": { + "description": "Optional. A grouping of information about the connection to the remote resource." } }, "enableTelemetry": { @@ -1053,7 +1223,7 @@ "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2023-07-01", - "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.2.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.3.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -1089,15 +1259,7 @@ "customNetworkInterfaceName": "[coalesce(parameters('customNetworkInterfaceName'), '')]", "ipConfigurations": "[coalesce(parameters('ipConfigurations'), createArray())]", "manualPrivateLinkServiceConnections": "[coalesce(parameters('manualPrivateLinkServiceConnections'), createArray())]", - "privateLinkServiceConnections": [ - { - "name": "[parameters('name')]", - "properties": { - "privateLinkServiceId": "[parameters('serviceResourceId')]", - "groupIds": "[parameters('groupIds')]" - } - } - ], + "privateLinkServiceConnections": "[coalesce(parameters('privateLinkServiceConnections'), createArray())]", "subnet": { "id": "[parameters('subnetResourceId')]" } @@ -1127,7 +1289,7 @@ "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", "name": "[guid(resourceId('Microsoft.Network/privateEndpoints', parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", "properties": { - "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", 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 4ec2feaf2e..a9ff31f549 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 @@ -105,6 +105,24 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' principalType: 'ServicePrincipal' } ] + ipConfigurations: [ + { + name: 'myIPconfig' + properties: { + groupId: 'batchAccount' + memberName: 'batchAccount' + privateIPAddress: '10.0.0.10' + } + } + ] + customDnsConfigs: [ + { + fqdn: 'abc.batch.com' + ipAddresses: [ + '10.0.0.10' + ] + } + ] } ] networkProfile: { diff --git a/avm/res/cognitive-services/account/README.md b/avm/res/cognitive-services/account/README.md index b63f01ca87..665b62d9e9 100644 --- a/avm/res/cognitive-services/account/README.md +++ b/avm/res/cognitive-services/account/README.md @@ -161,6 +161,24 @@ module account 'br/public:avm/res/cognitive-services/account:' = { } privateEndpoints: [ { + customDnsConfigs: [ + { + fqdn: 'abc.account.com' + ipAddresses: [ + '10.0.0.10' + ] + } + ] + ipConfigurations: [ + { + name: 'myIPconfig' + properties: { + groupId: 'account' + memberName: 'default' + privateIPAddress: '10.0.0.10' + } + } + ] privateDnsZoneResourceIds: [ '' ] @@ -289,6 +307,24 @@ module account 'br/public:avm/res/cognitive-services/account:' = { "privateEndpoints": { "value": [ { + "customDnsConfigs": [ + { + "fqdn": "abc.account.com", + "ipAddresses": [ + "10.0.0.10" + ] + } + ], + "ipConfigurations": [ + { + "name": "myIPconfig", + "properties": { + "groupId": "account", + "memberName": "default", + "privateIPAddress": "10.0.0.10" + } + } + ], "privateDnsZoneResourceIds": [ "" ], @@ -1149,14 +1185,20 @@ Optional. Custom DNS configurations. | Name | Required | Type | Description | | :-- | :-- | :--| :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | No | string | | -| [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | Yes | array | | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | No | string | Required. Fqdn that resolves to private endpoint IP address. | +| [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | Yes | array | Required. A list of private IP addresses of the private endpoint. | ### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +Required. Fqdn that resolves to private endpoint IP address. + - Required: No - Type: string ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` + +Required. A list of private IP addresses of the private endpoint. + - Required: Yes - Type: array @@ -1184,28 +1226,52 @@ Optional. A list of IP configurations of the private endpoint. This will be used | Name | Required | Type | Description | | :-- | :-- | :--| :-- | -| [`groupId`](#parameter-privateendpointsipconfigurationsgroupid) | Yes | string | | -| [`memberName`](#parameter-privateendpointsipconfigurationsmembername) | Yes | string | | -| [`name`](#parameter-privateendpointsipconfigurationsname) | Yes | string | | -| [`privateIpAddress`](#parameter-privateendpointsipconfigurationsprivateipaddress) | Yes | string | | +| [`name`](#parameter-privateendpointsipconfigurationsname) | Yes | string | Required. The name of the resource that is unique within a resource group. | +| [`properties`](#parameter-privateendpointsipconfigurationsproperties) | Yes | object | Required. Properties of private endpoint IP configurations. | + +### Parameter: `privateEndpoints.ipConfigurations.name` + +Required. The name of the resource that is unique within a resource group. -### Parameter: `privateEndpoints.ipConfigurations.groupId` - Required: Yes - Type: string -### Parameter: `privateEndpoints.ipConfigurations.memberName` +### Parameter: `privateEndpoints.ipConfigurations.properties` + +Required. Properties of private endpoint IP configurations. + +- Required: Yes +- Type: object + +| Name | Required | Type | Description | +| :-- | :-- | :--| :-- | +| [`groupId`](#parameter-privateendpointsipconfigurationspropertiesgroupid) | Yes | string | Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. | +| [`memberName`](#parameter-privateendpointsipconfigurationspropertiesmembername) | Yes | string | Required. The member name of a group obtained from the remote resource that this private endpoint should connect to. | +| [`privateIPAddress`](#parameter-privateendpointsipconfigurationspropertiesprivateipaddress) | Yes | string | Required. A private IP address obtained from the private endpoint's subnet. | + +### Parameter: `privateEndpoints.ipConfigurations.properties.groupId` + +Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. + - Required: Yes - Type: string -### Parameter: `privateEndpoints.ipConfigurations.name` +### Parameter: `privateEndpoints.ipConfigurations.properties.memberName` + +Required. The member name of a group obtained from the remote resource that this private endpoint should connect to. + - Required: Yes - Type: string -### Parameter: `privateEndpoints.ipConfigurations.privateIpAddress` +### Parameter: `privateEndpoints.ipConfigurations.properties.privateIPAddress` + +Required. A private IP address obtained from the private endpoint's subnet. + - Required: Yes - Type: string + ### Parameter: `privateEndpoints.location` Optional. The location to deploy the private endpoint to. @@ -1432,4 +1498,4 @@ 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.2.0` | Remote reference | +| `br/public:avm/res/network/private-endpoint:0.3.1` | Remote reference | diff --git a/avm/res/cognitive-services/account/main.bicep b/avm/res/cognitive-services/account/main.bicep index 62ac4428ef..4e416c77dc 100644 --- a/avm/res/cognitive-services/account/main.bicep +++ b/avm/res/cognitive-services/account/main.bicep @@ -261,14 +261,21 @@ resource cognitiveService_diagnosticSettings 'Microsoft.Insights/diagnosticSetti scope: cognitiveService }] -module cognitiveService_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.2.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { +module cognitiveService_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.3.1' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { name: '${uniqueString(deployment().name, location)}-CognitiveService-PrivateEndpoint-${index}' params: { - groupIds: [ - privateEndpoint.?service ?? 'account' + privateLinkServiceConnections: [ + { + name: name + properties: { + privateLinkServiceId: cognitiveService.id + groupIds: [ + privateEndpoint.?service ?? 'account' + ] + } + } ] name: privateEndpoint.?name ?? 'pep-${last(split(cognitiveService.id, '/'))}-${privateEndpoint.?service ?? 'account'}-${index}' - serviceResourceId: cognitiveService.id subnetResourceId: privateEndpoint.subnetResourceId enableTelemetry: privateEndpoint.?enableTelemetry ?? enableTelemetry location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location @@ -403,16 +410,29 @@ type privateEndpointType = { @description('Optional. Custom DNS configurations.') customDnsConfigs: { + @description('Required. Fqdn that resolves to private endpoint IP address.') fqdn: string? + + @description('Required. A list of private IP addresses of the private endpoint.') ipAddresses: string[] }[]? @description('Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints.') ipConfigurations: { + @description('Required. The name of the resource that is unique within a resource group.') name: string - groupId: string - memberName: string - privateIpAddress: string + + @description('Required. Properties of private endpoint IP configurations.') + properties: { + @description('Required. The ID of a group obtained from the remote resource that this private endpoint should connect to.') + groupId: string + + @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.') + privateIPAddress: string + } }[]? @description('Optional. Application security groups in which the private endpoint IP configuration is included.') diff --git a/avm/res/cognitive-services/account/main.json b/avm/res/cognitive-services/account/main.json index 5966902ed5..37b334dccb 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.23.1.45101", - "templateHash": "7267850394264518578" + "templateHash": "8113334263625418936" }, "name": "Cognitive Services", "description": "This module deploys a Cognitive Service.", @@ -241,12 +241,18 @@ "properties": { "fqdn": { "type": "string", - "nullable": true + "nullable": true, + "metadata": { + "description": "Required. Fqdn that resolves to private endpoint IP address." + } }, "ipAddresses": { "type": "array", "items": { "type": "string" + }, + "metadata": { + "description": "Required. A list of private IP addresses of the private endpoint." } } } @@ -262,16 +268,36 @@ "type": "object", "properties": { "name": { - "type": "string" - }, - "groupId": { - "type": "string" - }, - "memberName": { - "type": "string" + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } }, - "privateIpAddress": { - "type": "string" + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private IP address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } } } }, @@ -808,17 +834,22 @@ }, "mode": "Incremental", "parameters": { - "groupIds": { + "privateLinkServiceConnections": { "value": [ - "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'account')]" + { + "name": "[parameters('name')]", + "properties": { + "privateLinkServiceId": "[resourceId('Microsoft.CognitiveServices/accounts', parameters('name'))]", + "groupIds": [ + "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'account')]" + ] + } + } ] }, "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()))]" }, - "serviceResourceId": { - "value": "[resourceId('Microsoft.CognitiveServices/accounts', parameters('name'))]" - }, "subnetResourceId": { "value": "[coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId]" }, @@ -867,7 +898,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "2788827530274342759" + "templateHash": "2821141217598568122" }, "name": "Private Endpoints", "description": "This module deploys a Private Endpoint.", @@ -882,7 +913,7 @@ "roleDefinitionIdOrName": { "type": "string", "metadata": { - "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead." + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." } }, "principalId": { @@ -964,6 +995,154 @@ } }, "nullable": true + }, + "ipConfigurationsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private ip address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + } + }, + "nullable": true + }, + "manualPrivateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, + "privateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, + "customDnsConfigType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "metadata": { + "description": "Required. Fqdn that resolves to private endpoint ip address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. A list of private ip addresses of the private endpoint." + } + } + } + }, + "nullable": true } }, "parameters": { @@ -979,12 +1158,6 @@ "description": "Required. Resource ID of the subnet where the endpoint needs to be created." } }, - "serviceResourceId": { - "type": "string", - "metadata": { - "description": "Required. Resource ID of the resource that needs to be connected to the network." - } - }, "applicationSecurityGroupResourceIds": { "type": "array", "nullable": true, @@ -1000,18 +1173,11 @@ } }, "ipConfigurations": { - "type": "array", - "nullable": true, + "$ref": "#/definitions/ipConfigurationsType", "metadata": { "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." } }, - "groupIds": { - "type": "array", - "metadata": { - "description": "Required. Subtype(s) of the connection to be created. The allowed values depend on the type serviceResourceId refers to." - } - }, "privateDnsZoneGroupName": { "type": "string", "nullable": true, @@ -1042,7 +1208,7 @@ "roleAssignments": { "$ref": "#/definitions/roleAssignmentType", "metadata": { - "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + "description": "Optional. Array of role assignments to create." } }, "tags": { @@ -1053,17 +1219,21 @@ } }, "customDnsConfigs": { - "type": "array", - "nullable": true, + "$ref": "#/definitions/customDnsConfigType", "metadata": { "description": "Optional. Custom DNS configurations." } }, "manualPrivateLinkServiceConnections": { - "type": "array", - "nullable": true, + "$ref": "#/definitions/manualPrivateLinkServiceConnectionsType", "metadata": { - "description": "Optional. Manual PrivateLink Service Connections." + "description": "Optional. A grouping of information about the connection to the remote resource. Used when the network admin does not have access to approve connections to the remote resource." + } + }, + "privateLinkServiceConnections": { + "$ref": "#/definitions/privateLinkServiceConnectionsType", + "metadata": { + "description": "Optional. A grouping of information about the connection to the remote resource." } }, "enableTelemetry": { @@ -1093,7 +1263,7 @@ "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2023-07-01", - "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.2.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.3.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -1129,15 +1299,7 @@ "customNetworkInterfaceName": "[coalesce(parameters('customNetworkInterfaceName'), '')]", "ipConfigurations": "[coalesce(parameters('ipConfigurations'), createArray())]", "manualPrivateLinkServiceConnections": "[coalesce(parameters('manualPrivateLinkServiceConnections'), createArray())]", - "privateLinkServiceConnections": [ - { - "name": "[parameters('name')]", - "properties": { - "privateLinkServiceId": "[parameters('serviceResourceId')]", - "groupIds": "[parameters('groupIds')]" - } - } - ], + "privateLinkServiceConnections": "[coalesce(parameters('privateLinkServiceConnections'), createArray())]", "subnet": { "id": "[parameters('subnetResourceId')]" } @@ -1167,7 +1329,7 @@ "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", "name": "[guid(resourceId('Microsoft.Network/privateEndpoints', parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", "properties": { - "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", 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 5ee0cd261b..ac011a2766 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 @@ -149,6 +149,24 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' Environment: 'Non-Prod' Role: 'DeploymentValidation' } + ipConfigurations: [ + { + name: 'myIPconfig' + properties: { + groupId: 'account' + memberName: 'default' + privateIPAddress: '10.0.0.10' + } + } + ] + customDnsConfigs: [ + { + fqdn: 'abc.account.com' + ipAddresses: [ + '10.0.0.10' + ] + } + ] } ] tags: { diff --git a/avm/res/key-vault/vault/README.md b/avm/res/key-vault/vault/README.md index 8a77180d71..15daab9c4a 100644 --- a/avm/res/key-vault/vault/README.md +++ b/avm/res/key-vault/vault/README.md @@ -235,6 +235,24 @@ module vault 'br/public:avm/res/key-vault/vault:' = { } privateEndpoints: [ { + customDnsConfigs: [ + { + fqdn: 'abc.keyvault.com' + ipAddresses: [ + '10.0.0.10' + ] + } + ] + ipConfigurations: [ + { + name: 'myIPconfig' + properties: { + groupId: 'vault' + memberName: 'default' + privateIPAddress: '10.0.0.10' + } + } + ] privateDnsZoneResourceIds: [ '' ] @@ -474,6 +492,24 @@ module vault 'br/public:avm/res/key-vault/vault:' = { "privateEndpoints": { "value": [ { + "customDnsConfigs": [ + { + "fqdn": "abc.keyvault.com", + "ipAddresses": [ + "10.0.0.10" + ] + } + ], + "ipConfigurations": [ + { + "name": "myIPconfig", + "properties": { + "groupId": "vault", + "memberName": "default", + "privateIPAddress": "10.0.0.10" + } + } + ], "privateDnsZoneResourceIds": [ "" ], @@ -585,9 +621,34 @@ module vault 'br/public:avm/res/key-vault/vault:' = { location: '' privateEndpoints: [ { + customDnsConfigs: [ + { + fqdn: 'abc.keyvault.com' + ipAddresses: [ + '10.0.0.10' + ] + } + ] + ipConfigurations: [ + { + name: 'myIPconfig' + properties: { + groupId: 'vault' + memberName: 'default' + privateIPAddress: '10.0.0.10' + } + } + ] privateDnsZoneResourceIds: [ '' ] + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Reader' + } + ] subnetResourceId: '' tags: { Environment: 'Non-Prod' @@ -631,9 +692,34 @@ module vault 'br/public:avm/res/key-vault/vault:' = { "privateEndpoints": { "value": [ { + "customDnsConfigs": [ + { + "fqdn": "abc.keyvault.com", + "ipAddresses": [ + "10.0.0.10" + ] + } + ], + "ipConfigurations": [ + { + "name": "myIPconfig", + "properties": { + "groupId": "vault", + "memberName": "default", + "privateIPAddress": "10.0.0.10" + } + } + ], "privateDnsZoneResourceIds": [ "" ], + "roleAssignments": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ], "subnetResourceId": "", "tags": { "Environment": "Non-Prod", @@ -1251,14 +1337,20 @@ Optional. Custom DNS configurations. | Name | Required | Type | Description | | :-- | :-- | :--| :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | No | string | | -| [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | Yes | array | | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | No | string | Required. Fqdn that resolves to private endpoint IP address. | +| [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | Yes | array | Required. A list of private IP addresses of the private endpoint. | ### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +Required. Fqdn that resolves to private endpoint IP address. + - Required: No - Type: string ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` + +Required. A list of private IP addresses of the private endpoint. + - Required: Yes - Type: array @@ -1286,28 +1378,52 @@ Optional. A list of IP configurations of the private endpoint. This will be used | Name | Required | Type | Description | | :-- | :-- | :--| :-- | -| [`groupId`](#parameter-privateendpointsipconfigurationsgroupid) | Yes | string | | -| [`memberName`](#parameter-privateendpointsipconfigurationsmembername) | Yes | string | | -| [`name`](#parameter-privateendpointsipconfigurationsname) | Yes | string | | -| [`privateIpAddress`](#parameter-privateendpointsipconfigurationsprivateipaddress) | Yes | string | | +| [`name`](#parameter-privateendpointsipconfigurationsname) | Yes | string | Required. The name of the resource that is unique within a resource group. | +| [`properties`](#parameter-privateendpointsipconfigurationsproperties) | Yes | object | Required. Properties of private endpoint IP configurations. | + +### Parameter: `privateEndpoints.ipConfigurations.name` + +Required. The name of the resource that is unique within a resource group. -### Parameter: `privateEndpoints.ipConfigurations.groupId` - Required: Yes - Type: string -### Parameter: `privateEndpoints.ipConfigurations.memberName` +### Parameter: `privateEndpoints.ipConfigurations.properties` + +Required. Properties of private endpoint IP configurations. + +- Required: Yes +- Type: object + +| Name | Required | Type | Description | +| :-- | :-- | :--| :-- | +| [`groupId`](#parameter-privateendpointsipconfigurationspropertiesgroupid) | Yes | string | Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. | +| [`memberName`](#parameter-privateendpointsipconfigurationspropertiesmembername) | Yes | string | Required. The member name of a group obtained from the remote resource that this private endpoint should connect to. | +| [`privateIPAddress`](#parameter-privateendpointsipconfigurationspropertiesprivateipaddress) | Yes | string | Required. A private IP address obtained from the private endpoint's subnet. | + +### Parameter: `privateEndpoints.ipConfigurations.properties.groupId` + +Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. + - Required: Yes - Type: string -### Parameter: `privateEndpoints.ipConfigurations.name` +### Parameter: `privateEndpoints.ipConfigurations.properties.memberName` + +Required. The member name of a group obtained from the remote resource that this private endpoint should connect to. + - Required: Yes - Type: string -### Parameter: `privateEndpoints.ipConfigurations.privateIpAddress` +### Parameter: `privateEndpoints.ipConfigurations.properties.privateIPAddress` + +Required. A private IP address obtained from the private endpoint's subnet. + - Required: Yes - Type: string + ### Parameter: `privateEndpoints.location` Optional. The location to deploy the private endpoint to. @@ -1511,4 +1627,4 @@ 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.2.0` | Remote reference | +| `br/public:avm/res/network/private-endpoint:0.3.1` | Remote reference | diff --git a/avm/res/key-vault/vault/main.bicep b/avm/res/key-vault/vault/main.bicep index c07ffa48ba..28b0553884 100644 --- a/avm/res/key-vault/vault/main.bicep +++ b/avm/res/key-vault/vault/main.bicep @@ -239,14 +239,21 @@ module keyVault_keys 'key/main.bicep' = [for (key, index) in (keys ?? []): { } }] -module keyVault_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.2.0' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { +module keyVault_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.3.1' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { name: '${uniqueString(deployment().name, location)}-KeyVault-PrivateEndpoint-${index}' params: { - groupIds: [ - privateEndpoint.?service ?? 'vault' + privateLinkServiceConnections: [ + { + name: name + properties: { + privateLinkServiceId: keyVault.id + groupIds: [ + privateEndpoint.?service ?? 'vault' + ] + } + } ] name: privateEndpoint.?name ?? 'pep-${last(split(keyVault.id, '/'))}-${privateEndpoint.?service ?? 'vault'}-${index}' - serviceResourceId: keyVault.id subnetResourceId: privateEndpoint.subnetResourceId enableTelemetry: enableTelemetry location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location @@ -382,16 +389,29 @@ type privateEndpointType = { @description('Optional. Custom DNS configurations.') customDnsConfigs: { + @description('Required. Fqdn that resolves to private endpoint IP address.') fqdn: string? + + @description('Required. A list of private IP addresses of the private endpoint.') ipAddresses: string[] }[]? @description('Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints.') ipConfigurations: { + @description('Required. The name of the resource that is unique within a resource group.') name: string - groupId: string - memberName: string - privateIpAddress: string + + @description('Required. Properties of private endpoint IP configurations.') + properties: { + @description('Required. The ID of a group obtained from the remote resource that this private endpoint should connect to.') + groupId: string + + @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.') + privateIPAddress: string + } }[]? @description('Optional. Application security groups in which the private endpoint IP configuration is included.') diff --git a/avm/res/key-vault/vault/main.json b/avm/res/key-vault/vault/main.json index b9a9f93646..c3bc831762 100644 --- a/avm/res/key-vault/vault/main.json +++ b/avm/res/key-vault/vault/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "665865372091259296" + "templateHash": "1282169260807050154" }, "name": "Key Vaults", "description": "This module deploys a Key Vault.", @@ -241,12 +241,18 @@ "properties": { "fqdn": { "type": "string", - "nullable": true + "nullable": true, + "metadata": { + "description": "Required. Fqdn that resolves to private endpoint IP address." + } }, "ipAddresses": { "type": "array", "items": { "type": "string" + }, + "metadata": { + "description": "Required. A list of private IP addresses of the private endpoint." } } } @@ -262,16 +268,36 @@ "type": "object", "properties": { "name": { - "type": "string" - }, - "groupId": { - "type": "string" - }, - "memberName": { - "type": "string" + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } }, - "privateIpAddress": { - "type": "string" + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private IP address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } } } }, @@ -1659,17 +1685,22 @@ }, "mode": "Incremental", "parameters": { - "groupIds": { + "privateLinkServiceConnections": { "value": [ - "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'vault')]" + { + "name": "[parameters('name')]", + "properties": { + "privateLinkServiceId": "[resourceId('Microsoft.KeyVault/vaults', parameters('name'))]", + "groupIds": [ + "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'vault')]" + ] + } + } ] }, "name": { "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'name'), format('pep-{0}-{1}-{2}', last(split(resourceId('Microsoft.KeyVault/vaults', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'vault'), copyIndex()))]" }, - "serviceResourceId": { - "value": "[resourceId('Microsoft.KeyVault/vaults', parameters('name'))]" - }, "subnetResourceId": { "value": "[coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId]" }, @@ -1718,7 +1749,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "2788827530274342759" + "templateHash": "2821141217598568122" }, "name": "Private Endpoints", "description": "This module deploys a Private Endpoint.", @@ -1733,7 +1764,7 @@ "roleDefinitionIdOrName": { "type": "string", "metadata": { - "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead." + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." } }, "principalId": { @@ -1815,6 +1846,154 @@ } }, "nullable": true + }, + "ipConfigurationsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private ip address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + } + }, + "nullable": true + }, + "manualPrivateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, + "privateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, + "customDnsConfigType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "metadata": { + "description": "Required. Fqdn that resolves to private endpoint ip address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. A list of private ip addresses of the private endpoint." + } + } + } + }, + "nullable": true } }, "parameters": { @@ -1830,12 +2009,6 @@ "description": "Required. Resource ID of the subnet where the endpoint needs to be created." } }, - "serviceResourceId": { - "type": "string", - "metadata": { - "description": "Required. Resource ID of the resource that needs to be connected to the network." - } - }, "applicationSecurityGroupResourceIds": { "type": "array", "nullable": true, @@ -1851,18 +2024,11 @@ } }, "ipConfigurations": { - "type": "array", - "nullable": true, + "$ref": "#/definitions/ipConfigurationsType", "metadata": { "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." } }, - "groupIds": { - "type": "array", - "metadata": { - "description": "Required. Subtype(s) of the connection to be created. The allowed values depend on the type serviceResourceId refers to." - } - }, "privateDnsZoneGroupName": { "type": "string", "nullable": true, @@ -1893,7 +2059,7 @@ "roleAssignments": { "$ref": "#/definitions/roleAssignmentType", "metadata": { - "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + "description": "Optional. Array of role assignments to create." } }, "tags": { @@ -1904,17 +2070,21 @@ } }, "customDnsConfigs": { - "type": "array", - "nullable": true, + "$ref": "#/definitions/customDnsConfigType", "metadata": { "description": "Optional. Custom DNS configurations." } }, "manualPrivateLinkServiceConnections": { - "type": "array", - "nullable": true, + "$ref": "#/definitions/manualPrivateLinkServiceConnectionsType", "metadata": { - "description": "Optional. Manual PrivateLink Service Connections." + "description": "Optional. A grouping of information about the connection to the remote resource. Used when the network admin does not have access to approve connections to the remote resource." + } + }, + "privateLinkServiceConnections": { + "$ref": "#/definitions/privateLinkServiceConnectionsType", + "metadata": { + "description": "Optional. A grouping of information about the connection to the remote resource." } }, "enableTelemetry": { @@ -1944,7 +2114,7 @@ "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2023-07-01", - "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.2.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.3.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -1980,15 +2150,7 @@ "customNetworkInterfaceName": "[coalesce(parameters('customNetworkInterfaceName'), '')]", "ipConfigurations": "[coalesce(parameters('ipConfigurations'), createArray())]", "manualPrivateLinkServiceConnections": "[coalesce(parameters('manualPrivateLinkServiceConnections'), createArray())]", - "privateLinkServiceConnections": [ - { - "name": "[parameters('name')]", - "properties": { - "privateLinkServiceId": "[parameters('serviceResourceId')]", - "groupIds": "[parameters('groupIds')]" - } - } - ], + "privateLinkServiceConnections": "[coalesce(parameters('privateLinkServiceConnections'), createArray())]", "subnet": { "id": "[parameters('subnetResourceId')]" } @@ -2018,7 +2180,7 @@ "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", "name": "[guid(resourceId('Microsoft.Network/privateEndpoints', parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", "properties": { - "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", diff --git a/avm/res/key-vault/vault/tests/e2e/max/main.test.bicep b/avm/res/key-vault/vault/tests/e2e/max/main.test.bicep index 5827070e98..6710a71e32 100644 --- a/avm/res/key-vault/vault/tests/e2e/max/main.test.bicep +++ b/avm/res/key-vault/vault/tests/e2e/max/main.test.bicep @@ -216,6 +216,24 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' principalType: 'ServicePrincipal' } ] + ipConfigurations: [ + { + name: 'myIPconfig' + properties: { + groupId: 'vault' + memberName: 'default' + privateIPAddress: '10.0.0.10' + } + } + ] + customDnsConfigs: [ + { + fqdn: 'abc.keyvault.com' + ipAddresses: [ + '10.0.0.10' + ] + } + ] } ] roleAssignments: [ diff --git a/avm/res/key-vault/vault/tests/e2e/private-endpoint/dependencies.bicep b/avm/res/key-vault/vault/tests/e2e/private-endpoint/dependencies.bicep index b9eb57d972..a9999dcb53 100644 --- a/avm/res/key-vault/vault/tests/e2e/private-endpoint/dependencies.bicep +++ b/avm/res/key-vault/vault/tests/e2e/private-endpoint/dependencies.bicep @@ -4,6 +4,9 @@ param location string = resourceGroup().location @description('Required. The name of the Virtual Network to create.') param virtualNetworkName string +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + var addressPrefix = '10.0.0.0/16' resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { @@ -47,8 +50,16 @@ resource privateDNSZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { } } +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + 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 Private DNS Zone.') output privateDNSResourceId string = privateDNSZone.id + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId diff --git a/avm/res/key-vault/vault/tests/e2e/private-endpoint/main.test.bicep b/avm/res/key-vault/vault/tests/e2e/private-endpoint/main.test.bicep index ad4258b82f..c391bdf550 100644 --- a/avm/res/key-vault/vault/tests/e2e/private-endpoint/main.test.bicep +++ b/avm/res/key-vault/vault/tests/e2e/private-endpoint/main.test.bicep @@ -36,6 +36,7 @@ module nestedDependencies 'dependencies.bicep' = { name: '${uniqueString(deployment().name, location)}-nestedDependencies' params: { virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' location: location } } @@ -62,6 +63,31 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' Environment: 'Non-Prod' Role: 'DeploymentValidation' } + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + ipConfigurations: [ + { + name: 'myIPconfig' + properties: { + groupId: 'vault' + memberName: 'default' + privateIPAddress: '10.0.0.10' + } + } + ] + customDnsConfigs: [ + { + fqdn: 'abc.keyvault.com' + ipAddresses: [ + '10.0.0.10' + ] + } + ] } ] tags: { diff --git a/avm/res/network/private-endpoint/README.md b/avm/res/network/private-endpoint/README.md index 0015b935b3..6fb235bb50 100644 --- a/avm/res/network/private-endpoint/README.md +++ b/avm/res/network/private-endpoint/README.md @@ -548,19 +548,19 @@ Custom DNS configurations. | Name | Required | Type | Description | | :-- | :-- | :--| :-- | -| [`fqdn`](#parameter-customdnsconfigsfqdn) | Yes | string | Required. Fqdn that resolves to private endpoint ip address. | -| [`ipAddresses`](#parameter-customdnsconfigsipaddresses) | Yes | array | Required. A list of private ip addresses of the private endpoint. | +| [`fqdn`](#parameter-customdnsconfigsfqdn) | Yes | string | Required. Fqdn that resolves to private endpoint IP address. | +| [`ipAddresses`](#parameter-customdnsconfigsipaddresses) | Yes | array | Required. A list of private IP addresses of the private endpoint. | ### Parameter: `customDnsConfigs.fqdn` -Required. Fqdn that resolves to private endpoint ip address. +Required. Fqdn that resolves to private endpoint IP address. - Required: Yes - Type: string ### Parameter: `customDnsConfigs.ipAddresses` -Required. A list of private ip addresses of the private endpoint. +Required. A list of private IP addresses of the private endpoint. - Required: Yes - Type: array @@ -608,7 +608,7 @@ Required. Properties of private endpoint IP configurations. | :-- | :-- | :--| :-- | | [`groupId`](#parameter-ipconfigurationspropertiesgroupid) | Yes | string | Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. | | [`memberName`](#parameter-ipconfigurationspropertiesmembername) | Yes | string | Required. The member name of a group obtained from the remote resource that this private endpoint should connect to. | -| [`privateIPAddress`](#parameter-ipconfigurationspropertiesprivateipaddress) | Yes | string | Required. A private ip address obtained from the private endpoint's subnet. | +| [`privateIPAddress`](#parameter-ipconfigurationspropertiesprivateipaddress) | Yes | string | Required. A private IP address obtained from the private endpoint's subnet. | ### Parameter: `ipConfigurations.properties.groupId` @@ -626,7 +626,7 @@ Required. The member name of a group obtained from the remote resource that this ### Parameter: `ipConfigurations.properties.privateIPAddress` -Required. A private ip address obtained from the private endpoint's subnet. +Required. A private IP address obtained from the private endpoint's subnet. - Required: Yes - Type: string diff --git a/avm/res/network/private-endpoint/main.bicep b/avm/res/network/private-endpoint/main.bicep index 08399b166f..8ff37d7dbc 100644 --- a/avm/res/network/private-endpoint/main.bicep +++ b/avm/res/network/private-endpoint/main.bicep @@ -188,7 +188,7 @@ type ipConfigurationsType = { @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 } }[]? @@ -228,9 +228,9 @@ type privateLinkServiceConnectionsType = { }[]? type customDnsConfigType = { - @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[] }[]? diff --git a/avm/res/network/private-endpoint/main.json b/avm/res/network/private-endpoint/main.json index 7caa529b5d..0227bf8f8e 100644 --- a/avm/res/network/private-endpoint/main.json +++ b/avm/res/network/private-endpoint/main.json @@ -133,7 +133,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." } } }, @@ -236,7 +236,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": { @@ -245,7 +245,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." } } } diff --git a/avm/res/search/search-service/README.md b/avm/res/search/search-service/README.md index f5382fe232..096f5cd277 100644 --- a/avm/res/search/search-service/README.md +++ b/avm/res/search/search-service/README.md @@ -1180,4 +1180,4 @@ 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.2.1` | Remote reference | +| `br/public:avm/res/network/private-endpoint:0.3.1` | Remote reference | diff --git a/avm/res/search/search-service/main.bicep b/avm/res/search/search-service/main.bicep index 42a3bb2afc..54b20f22a4 100644 --- a/avm/res/search/search-service/main.bicep +++ b/avm/res/search/search-service/main.bicep @@ -201,14 +201,21 @@ resource searchService_roleAssignments 'Microsoft.Authorization/roleAssignments@ scope: searchService }] -module searchService_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.2.1' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { +module searchService_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.3.1' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { name: '${uniqueString(deployment().name, location)}-searchService-PrivateEndpoint-${index}' params: { - groupIds: [ - privateEndpoint.?service ?? 'searchService' + privateLinkServiceConnections: [ + { + name: name + properties: { + privateLinkServiceId: searchService.id + groupIds: [ + privateEndpoint.?service ?? 'searchService' + ] + } + } ] name: privateEndpoint.?name ?? 'pep-${last(split(searchService.id, '/'))}-${privateEndpoint.?service ?? 'searchService'}-${index}' - serviceResourceId: searchService.id subnetResourceId: privateEndpoint.subnetResourceId location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location lock: privateEndpoint.?lock ?? lock diff --git a/avm/res/search/search-service/main.json b/avm/res/search/search-service/main.json index 4a7b90621d..456a5fa77a 100644 --- a/avm/res/search/search-service/main.json +++ b/avm/res/search/search-service/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "7881856021577467097" + "templateHash": "6391154387448662965" }, "name": "Search Services", "description": "This module deploys a Search Service.", @@ -684,17 +684,22 @@ }, "mode": "Incremental", "parameters": { - "groupIds": { + "privateLinkServiceConnections": { "value": [ - "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'searchService')]" + { + "name": "[parameters('name')]", + "properties": { + "privateLinkServiceId": "[resourceId('Microsoft.Search/searchServices', parameters('name'))]", + "groupIds": [ + "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'searchService')]" + ] + } + } ] }, "name": { "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'name'), format('pep-{0}-{1}-{2}', last(split(resourceId('Microsoft.Search/searchServices', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'searchService'), copyIndex()))]" }, - "serviceResourceId": { - "value": "[resourceId('Microsoft.Search/searchServices', parameters('name'))]" - }, "subnetResourceId": { "value": "[coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId]" }, @@ -743,7 +748,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "13477311172998188302" + "templateHash": "2821141217598568122" }, "name": "Private Endpoints", "description": "This module deploys a Private Endpoint.", @@ -758,7 +763,7 @@ "roleDefinitionIdOrName": { "type": "string", "metadata": { - "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead." + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." } }, "principalId": { @@ -882,6 +887,89 @@ }, "nullable": true }, + "manualPrivateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, + "privateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, "customDnsConfigType": { "type": "array", "items": { @@ -920,12 +1008,6 @@ "description": "Required. Resource ID of the subnet where the endpoint needs to be created." } }, - "serviceResourceId": { - "type": "string", - "metadata": { - "description": "Required. Resource ID of the resource that needs to be connected to the network." - } - }, "applicationSecurityGroupResourceIds": { "type": "array", "nullable": true, @@ -946,12 +1028,6 @@ "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." } }, - "groupIds": { - "type": "array", - "metadata": { - "description": "Required. Subtype(s) of the connection to be created. The allowed values depend on the type serviceResourceId refers to." - } - }, "privateDnsZoneGroupName": { "type": "string", "nullable": true, @@ -982,7 +1058,7 @@ "roleAssignments": { "$ref": "#/definitions/roleAssignmentType", "metadata": { - "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + "description": "Optional. Array of role assignments to create." } }, "tags": { @@ -999,10 +1075,15 @@ } }, "manualPrivateLinkServiceConnections": { - "type": "array", - "nullable": true, + "$ref": "#/definitions/manualPrivateLinkServiceConnectionsType", + "metadata": { + "description": "Optional. A grouping of information about the connection to the remote resource. Used when the network admin does not have access to approve connections to the remote resource." + } + }, + "privateLinkServiceConnections": { + "$ref": "#/definitions/privateLinkServiceConnectionsType", "metadata": { - "description": "Optional. Manual PrivateLink Service Connections." + "description": "Optional. A grouping of information about the connection to the remote resource." } }, "enableTelemetry": { @@ -1032,7 +1113,7 @@ "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2023-07-01", - "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.2.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.3.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -1068,15 +1149,7 @@ "customNetworkInterfaceName": "[coalesce(parameters('customNetworkInterfaceName'), '')]", "ipConfigurations": "[coalesce(parameters('ipConfigurations'), createArray())]", "manualPrivateLinkServiceConnections": "[coalesce(parameters('manualPrivateLinkServiceConnections'), createArray())]", - "privateLinkServiceConnections": [ - { - "name": "[parameters('name')]", - "properties": { - "privateLinkServiceId": "[parameters('serviceResourceId')]", - "groupIds": "[parameters('groupIds')]" - } - } - ], + "privateLinkServiceConnections": "[coalesce(parameters('privateLinkServiceConnections'), createArray())]", "subnet": { "id": "[parameters('subnetResourceId')]" } @@ -1106,7 +1179,7 @@ "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", "name": "[guid(resourceId('Microsoft.Network/privateEndpoints', parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", "properties": { - "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", diff --git a/avm/res/sql/server/README.md b/avm/res/sql/server/README.md index 6136d9ae44..a13ba10626 100644 --- a/avm/res/sql/server/README.md +++ b/avm/res/sql/server/README.md @@ -526,6 +526,24 @@ module server 'br/public:avm/res/sql/server:' = { location: '' privateEndpoints: [ { + customDnsConfigs: [ + { + fqdn: 'abc.sqlServer.com' + ipAddresses: [ + '10.0.0.10' + ] + } + ] + ipConfigurations: [ + { + name: 'myIPconfig' + properties: { + groupId: 'sqlServer' + memberName: 'sqlServer' + privateIPAddress: '10.0.0.10' + } + } + ] privateDnsZoneResourceIds: [ '' ] @@ -575,6 +593,24 @@ module server 'br/public:avm/res/sql/server:' = { "privateEndpoints": { "value": [ { + "customDnsConfigs": [ + { + "fqdn": "abc.sqlServer.com", + "ipAddresses": [ + "10.0.0.10" + ] + } + ], + "ipConfigurations": [ + { + "name": "myIPconfig", + "properties": { + "groupId": "sqlServer", + "memberName": "sqlServer", + "privateIPAddress": "10.0.0.10" + } + } + ], "privateDnsZoneResourceIds": [ "" ], @@ -1307,7 +1343,7 @@ Configuration details for private endpoints. For security reasons, it is recomme | [`lock`](#parameter-privateendpointslock) | No | object | Optional. Specify the type of lock. | | [`manualPrivateLinkServiceConnections`](#parameter-privateendpointsmanualprivatelinkserviceconnections) | No | array | Optional. Manual PrivateLink Service Connections. | | [`name`](#parameter-privateendpointsname) | No | string | Optional. The name of the private endpoint. | -| [`privateDnsZoneGroupName`](#parameter-privateendpointsprivatednszonegroupname) | No | string | Optional. The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided. | +| [`privateDnsZoneGroupName`](#parameter-privateendpointsprivatednszonegroupname) | No | string | Optional. The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided. | | [`privateDnsZoneResourceIds`](#parameter-privateendpointsprivatednszoneresourceids) | No | array | Optional. 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) | No | array | Optional. Array of role assignments to create. | | [`service`](#parameter-privateendpointsservice) | No | string | Optional. The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob". | @@ -1330,19 +1366,19 @@ Optional. Custom DNS configurations. | Name | Required | Type | Description | | :-- | :-- | :--| :-- | -| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | No | string | Required. Fqdn that resolves to private endpoint ip address. | -| [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | Yes | array | Required. A list of private ip addresses of the private endpoint. | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | No | string | Required. Fqdn that resolves to private endpoint IP address. | +| [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | Yes | array | Required. A list of private IP addresses of the private endpoint. | ### Parameter: `privateEndpoints.customDnsConfigs.fqdn` -Required. Fqdn that resolves to private endpoint ip address. +Required. Fqdn that resolves to private endpoint IP address. - Required: No - Type: string ### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` -Required. A list of private ip addresses of the private endpoint. +Required. A list of private IP addresses of the private endpoint. - Required: Yes - Type: array @@ -1392,7 +1428,7 @@ Required. Properties of private endpoint IP configurations. | :-- | :-- | :--| :-- | | [`groupId`](#parameter-privateendpointsipconfigurationspropertiesgroupid) | Yes | string | Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. | | [`memberName`](#parameter-privateendpointsipconfigurationspropertiesmembername) | Yes | string | Required. The member name of a group obtained from the remote resource that this private endpoint should connect to. | -| [`privateIPAddress`](#parameter-privateendpointsipconfigurationspropertiesprivateipaddress) | Yes | string | Required. A private ip address obtained from the private endpoint's subnet. | +| [`privateIPAddress`](#parameter-privateendpointsipconfigurationspropertiesprivateipaddress) | Yes | string | Required. A private IP address obtained from the private endpoint's subnet. | ### Parameter: `privateEndpoints.ipConfigurations.properties.groupId` @@ -1410,7 +1446,7 @@ Required. The member name of a group obtained from the remote resource that this ### Parameter: `privateEndpoints.ipConfigurations.properties.privateIPAddress` -Required. A private ip address obtained from the private endpoint's subnet. +Required. A private IP address obtained from the private endpoint's subnet. - Required: Yes - Type: string @@ -1447,7 +1483,7 @@ Optional. The name of the private endpoint. ### Parameter: `privateEndpoints.privateDnsZoneGroupName` -Optional. The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided. +Optional. The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided. - Required: No - Type: string @@ -1629,7 +1665,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.2.1` | Remote reference | +| `br/public:avm/res/network/private-endpoint:0.3.1` | Remote reference | ## Notes diff --git a/avm/res/sql/server/main.bicep b/avm/res/sql/server/main.bicep index ed6d64e517..32be5e38be 100644 --- a/avm/res/sql/server/main.bicep +++ b/avm/res/sql/server/main.bicep @@ -234,14 +234,21 @@ module server_elasticPools 'elastic-pool/main.bicep' = [for (elasticPool, index) } }] -module server_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.2.1' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { +module server_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.3.1' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { name: '${uniqueString(deployment().name, location)}-server-PrivateEndpoint-${index}' params: { - groupIds: [ - privateEndpoint.?service ?? 'sqlServer' + privateLinkServiceConnections: [ + { + name: name + properties: { + privateLinkServiceId: server.id + groupIds: [ + privateEndpoint.?service ?? 'sqlServer' + ] + } + } ] name: privateEndpoint.?name ?? 'pep-${last(split(server.id, '/'))}-${privateEndpoint.?service ?? 'sqlServer'}-${index}' - serviceResourceId: server.id subnetResourceId: privateEndpoint.subnetResourceId location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location lock: privateEndpoint.?lock ?? lock @@ -392,6 +399,7 @@ type roleAssignmentType = { }[]? type privateEndpointType = { + @description('Optional. The name of the private endpoint.') name: string? @@ -404,7 +412,7 @@ type privateEndpointType = { @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.') @@ -412,10 +420,10 @@ type privateEndpointType = { @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[] }[]? @@ -432,7 +440,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 } }[]? diff --git a/avm/res/sql/server/main.json b/avm/res/sql/server/main.json index 4ae2fd096c..2e5b06fdd3 100644 --- a/avm/res/sql/server/main.json +++ b/avm/res/sql/server/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "11876144653623707899" + "templateHash": "14112506919364586281" }, "name": "Azure SQL Servers", "description": "This module deploys an Azure SQL Server.", @@ -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": { @@ -185,7 +185,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 +194,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 +233,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." } } }, @@ -1560,17 +1560,22 @@ }, "mode": "Incremental", "parameters": { - "groupIds": { + "privateLinkServiceConnections": { "value": [ - "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'sqlServer')]" + { + "name": "[parameters('name')]", + "properties": { + "privateLinkServiceId": "[resourceId('Microsoft.Sql/servers', parameters('name'))]", + "groupIds": [ + "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'sqlServer')]" + ] + } + } ] }, "name": { "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'name'), format('pep-{0}-{1}-{2}', last(split(resourceId('Microsoft.Sql/servers', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'sqlServer'), copyIndex()))]" }, - "serviceResourceId": { - "value": "[resourceId('Microsoft.Sql/servers', parameters('name'))]" - }, "subnetResourceId": { "value": "[coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId]" }, @@ -1619,7 +1624,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "13477311172998188302" + "templateHash": "2821141217598568122" }, "name": "Private Endpoints", "description": "This module deploys a Private Endpoint.", @@ -1634,7 +1639,7 @@ "roleDefinitionIdOrName": { "type": "string", "metadata": { - "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead." + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." } }, "principalId": { @@ -1758,6 +1763,89 @@ }, "nullable": true }, + "manualPrivateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, + "privateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, "customDnsConfigType": { "type": "array", "items": { @@ -1796,12 +1884,6 @@ "description": "Required. Resource ID of the subnet where the endpoint needs to be created." } }, - "serviceResourceId": { - "type": "string", - "metadata": { - "description": "Required. Resource ID of the resource that needs to be connected to the network." - } - }, "applicationSecurityGroupResourceIds": { "type": "array", "nullable": true, @@ -1822,12 +1904,6 @@ "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." } }, - "groupIds": { - "type": "array", - "metadata": { - "description": "Required. Subtype(s) of the connection to be created. The allowed values depend on the type serviceResourceId refers to." - } - }, "privateDnsZoneGroupName": { "type": "string", "nullable": true, @@ -1858,7 +1934,7 @@ "roleAssignments": { "$ref": "#/definitions/roleAssignmentType", "metadata": { - "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + "description": "Optional. Array of role assignments to create." } }, "tags": { @@ -1875,10 +1951,15 @@ } }, "manualPrivateLinkServiceConnections": { - "type": "array", - "nullable": true, + "$ref": "#/definitions/manualPrivateLinkServiceConnectionsType", + "metadata": { + "description": "Optional. A grouping of information about the connection to the remote resource. Used when the network admin does not have access to approve connections to the remote resource." + } + }, + "privateLinkServiceConnections": { + "$ref": "#/definitions/privateLinkServiceConnectionsType", "metadata": { - "description": "Optional. Manual PrivateLink Service Connections." + "description": "Optional. A grouping of information about the connection to the remote resource." } }, "enableTelemetry": { @@ -1908,7 +1989,7 @@ "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2023-07-01", - "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.2.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.3.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -1944,15 +2025,7 @@ "customNetworkInterfaceName": "[coalesce(parameters('customNetworkInterfaceName'), '')]", "ipConfigurations": "[coalesce(parameters('ipConfigurations'), createArray())]", "manualPrivateLinkServiceConnections": "[coalesce(parameters('manualPrivateLinkServiceConnections'), createArray())]", - "privateLinkServiceConnections": [ - { - "name": "[parameters('name')]", - "properties": { - "privateLinkServiceId": "[parameters('serviceResourceId')]", - "groupIds": "[parameters('groupIds')]" - } - } - ], + "privateLinkServiceConnections": "[coalesce(parameters('privateLinkServiceConnections'), createArray())]", "subnet": { "id": "[parameters('subnetResourceId')]" } @@ -1982,7 +2055,7 @@ "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", "name": "[guid(resourceId('Microsoft.Network/privateEndpoints', parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", "properties": { - "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", diff --git a/avm/res/sql/server/tests/e2e/pe/main.test.bicep b/avm/res/sql/server/tests/e2e/pe/main.test.bicep index cf2f89b0ac..c407701e97 100644 --- a/avm/res/sql/server/tests/e2e/pe/main.test.bicep +++ b/avm/res/sql/server/tests/e2e/pe/main.test.bicep @@ -67,6 +67,24 @@ module testDeployment '../../../main.bicep' = { Environment: 'Non-Prod' Role: 'DeploymentValidation' } + ipConfigurations: [ + { + name: 'myIPconfig' + properties: { + groupId: 'sqlServer' + memberName: 'sqlServer' + privateIPAddress: '10.0.0.10' + } + } + ] + customDnsConfigs: [ + { + fqdn: 'abc.sqlServer.com' + ipAddresses: [ + '10.0.0.10' + ] + } + ] } ] tags: {