I am trying to deploy a V2 Storage Account along with Private Endpoint and Private link using ARM Template. I already have a Resource Group, VNET and Subnet existing in my Subscription and i would like to leverage them to provision a new Storage Account with a Private Endpoint and Private Link.
When i run the command from powershell to deploy the ARM Template it throws me the error though i am able to see Private Endpoint and Storage Account being created. What i don't see is the Private Link
New-AzResourceGroupDeployment : 11:02:18 PM - The deployment 'Storacc_PvtEndpoint'
failed with error(s). Showing 1 out of 1 error(s).
Status Message: Cannot parse the request. (Code: InvalidRequestFormat)
- Error converting value "blob" to type
'System.Collections.Generic.ICollection`1[System.String]'. Path
'properties.privateLinkServiceConnections[0].properties.groupIds', line 1, position
336. (Code:InvalidJson)
CorrelationId: 9606ab6b-35d6-49c0-a811-fa5154ff83e6
At line:1 char:1
+ New-AzResourceGroupDeployment -ResourceGroupName dops-pipeline -Templ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [New-AzResourceGroupDeployment], Exc
eption
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.ResourceManager.Cmdlets.Imple
mentation.NewAzureResourceGroupDeploymentCmdlet
DeploymentName : Storacc_PvtEndpoint
ResourceGroupName : dops-pipeline
ProvisioningState : Failed
Timestamp : 5/26/2021 2:02:13 AM
Mode : Incremental
TemplateLink :
Parameters :
Name Type
Value
=======================================
========================= ==========
storageAccountType String
Standard_LRS
location String
canadacentral
containerPrefix String
canadacentral
vnetName String
pvt-endpoint-vnet
subnetName String
blob-pvt-endpoint-sub
resourceGroupName String
dops-pipeline
blobStorageAccountPrivateEndpointName String
endpointsht5gcoc5cztq
Outputs :
DeploymentDebugLogLevel :
Please find below my ARM Template
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storageAccountType": {
"type": "string",
"defaultValue": "Standard_LRS",
"allowedValues": [
"Standard_LRS",
"Standard_GRS",
"Standard_ZRS",
"Premium_LRS"
],
"metadata": {
"description": "Storage Account type"
}
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "Storage Account Location"
}
},
"containerPrefix" : {
"type" : "string",
"defaultValue" : "[resourceGroup().location]"
},
"vnetName" : {
"type" : "string",
"defaultValue" : "pvt-endpoint-vnet"
},
"subnetName" : {
"type" : "string",
"defaultValue" : "blob-pvt-endpoint-sub"
},
"resourceGroupName" : {
"type" : "string",
"defaultValue" : "dops-pipeline"
},
"blobStorageAccountPrivateEndpointName" : {
"type" : "string",
"defaultValue" : "[toLower(concat('endpoint',uniqueString(resourceGroup().id)))]"
}
},
"variables": {
"blobstorageAccountName" : "[tolower(concat('stor', uniquestring(subscription().id,resourceGroup().id)))]",
"blobStorageAccountId" : "[resourceId('Microsoft.Storage/storageAccounts', variables('blobStorageAccountName'))]",
"blobPublicDNSZoneForwarder" : "[concat('.blob.', environment().suffixes.storage)]",
"blobPrivateDNSZoneName" : "[concat('privatelink', variables('blobPublicDNSZoneForwarder'))]",
"blobPrivateDnsZoneId" : "[resourceId('Microsoft.Network/privateDnsZones', variables('blobPrivateDnsZoneName'))]",
"blobPrivateDnsZoneGroup" : "[concat(parameters('blobStorageAccountPrivateEndpointName'),'/', variables('blobStorageAccountPrivateEndpointGroupName'), 'PrivateDnsZoneGroup')]",
"blobStorageAccountPrivateEndpointGroupName" : "blob",
"vnetId" : "[concat('/subscriptions/',subscription().subscriptionId,'/resourceGroups/',parameters('resourceGroupName'),'/providers/','Microsoft.Network/virtualNetworks/',parameters('vnetName'))]",
"subnetId" : "[concat('/subscriptions/',subscription().subscriptionId,'/resourceGroups/',parameters('resourceGroupName'),'/providers/','Microsoft.Network/virtualNetworks/',parameters('vnetName'),'/subnets/',parameters('subnetName'))]"
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2021-01-01",
"name": "[variables('blobstorageAccountName')]",
"location": "[parameters('location')]",
"sku": {
"name": "[parameters('storageAccountType')]"
},
"kind": "StorageV2",
"properties": {
"minimumTlsVersion" : "TLS1_2",
"allowBlobPublicAccess" : false,
"networkAcls": {
"bypass" : "AzureServices",
"defaultAction" : "Deny",
"virtualNetworkRules" : [
{
"id" : "[variables('subnetId')]",
"action" : "Allow"
}
]
}
}
},
{
"type" : "Microsoft.Network/privateDnsZones/virtualNetworkLinks",
"apiVersion": "2018-09-01",
"name" : "[concat(variables('blobPrivateDNSZoneName'), '/link_to_', toLower(parameters('vnetName')))]",
"location" : "global",
"dependsOn" : [
"[variables('blobPrivateDnsZoneId')]"
],
"properties" : {
"registrationEnabled" : false,
"virtualNetwork" : {
"id" : "[variables('vnetId')]"
}
}
},
{
"type" : "Microsoft.Network/privateEndpoints",
"apiVersion" : "2020-04-01",
"name" : "[parameters('blobStorageAccountPrivateEndpointName')]",
"location" : "[resourceGroup().location]",
"dependsOn" : [
"[variables('blobStorageAccountId')]"
],
"properties" : {
"privateLinkServiceConnections" : [
{
"name" : "parameters('blobStorageAccountPrivateEndpointName')",
"properties" : {
"privateLinkServiceId" : "[variables('blobStorageAccountId')]",
"groupIds" : "[variables('blobStorageAccountPrivateEndpointGroupName')]"
}
}
],
"subnet" :{
"id" : "[variables('subnetId')]"
},
"customDnsConfigs" : [
{
"fqdn" : "[concat(variables('blobStorageAccountName'),variables('blobPublicDNSZoneForwarder'))]"
}
]
}
},
{
"type" : "Microsoft.Network/privateDnsZones",
"apiVersion" : "2018-09-01",
"name" : "[variables('blobPrivateDNSZoneName')]",
"location" : "global",
"properties" : {
"maxNumberOfRecordSets" : 25000,
"maxNumberOfVirtualNetworkLinks" : 1000,
"maxNumberOfVirtualNetworkLinksWithRegistration" : 100
}
},
{
"type" : "Microsoft.Network/privateEndpoints/privateDnsZoneGroups",
"apiVersion" : "2020-03-01",
"name" : "[variables('blobPrivateDnsZoneGroup')]",
"location" : "[resourceGroup().location]",
"dependsOn" : [
"[variables('blobPrivateDnsZoneId')]",
"[parameters('blobStorageAccountPrivateEndpointName')]"
],
"properties" : {
"privateDnsZoneConfigs" :[
{
"name" : "dnsConfig",
"properties" : {
"privateDnsZoneId" : "[variables('blobPrivateDnsZoneId')]"
}
}
]
}
},
{
"type": "Microsoft.Storage/storageAccounts/blobServices",
"apiVersion": "2021-01-01",
"name" :"[tolower(concat(variables('blobstorageaccountname'), '/default'))]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', variables('blobstorageAccountName'))]"
],
"properties": {
"isVersioningEnabled" : true,
"deleteRetentionPolicy" : {
"enabled" : true,
"days" : 30
},
"changeFeed" : {
"enabled" : true
},
"containerDeleteRetentionPolicy" :{
"enabled" : true,
"days" : 30
}
}
},
{
"type": "Microsoft.Storage/storageAccounts/blobServices/containers",
"apiVersion": "2021-01-01",
"name": "[concat(variables('blobstorageAccountName'), '/default/', parameters('containerPrefix'), copyIndex())]",
"copy": {
"name": "containercopy",
"count": 2
},
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', variables('blobstorageAccountName'))]"
]
}
],
"outputs": {
"storageAccountName": {
"type": "string",
"value": "[variables('blobstorageAccountName')]"
}
}
}
This issue was solved by @Thomas's comments, just add them as an answer to close the question.
You need to remove
"[variables('vnetId')]"
fromdependsOn
, if a resource is not defined in the template it shouldn't be used independson
, and the propertygroupIds
is an array so should be :"groupIds": [ "[variables('blobStorageAccountPrivateEndpointGroupName')]"]
.
Reference - https://learn.microsoft.com/en-us/azure/templates/microsoft.network/privateendpoints?tabs=json