VivekAnandChakravarthy
VivekAnandChakravarthy

Reputation: 719

Unable to deploy private endpoint for flex consumption function app in azure using bicep

resource storageAccount 'Microsoft.Storage/storageAccounts@2021-04-01' = {
  name: 'vvkstaccforflexfuncapp'  
  location: 'uksouth'
  kind: 'StorageV2'
  sku: {
    name: 'Standard_LRS'
  }
  properties: {
    accessTier: 'Hot'
    minimumTlsVersion: 'TLS1_2'
  }
}


resource appInsights 'Microsoft.Insights/components@2020-02-02' = {
  name: 'name'
  location: 'uksouth'
  kind: 'web'
  properties: {
    Application_Type: 'web'
  }
}

resource virtualNetwork 'Microsoft.Network/virtualNetworks@2019-11-01' = {
  name: 'vnetforflexfuncapp'
  location: 'uksouth'
  properties: {
    addressSpace: {
      addressPrefixes: [
        '10.0.0.0/16'
      ]
    }
    subnets: [
      {
        name: 'InboundSubnet'
        properties: {
          addressPrefix: '10.0.0.0/24'
        }
      }
      {
        name: 'OutboundSubnet'
        properties: {
          addressPrefix: '10.0.1.0/24'
          delegations: [
            {
              name: 'delegation'
              properties: {
                serviceName: 'Microsoft.App/environments'
              }
            }
          ]
        }
      }
    ]
  }
}


resource flexappserviceplan 'Microsoft.Web/serverfarms@2024-04-01' = {
  name: 'vscodeflexappserviceplan'
  location:  'uksouth'
  sku: {
    name: 'FC1'
    tier: 'FlexConsumption'
    family: 'FC'
    capacity: 0
  }
  kind: 'functionapp'
  properties: {
    perSiteScaling: false
    elasticScaleEnabled: false
    maximumElasticWorkerCount: 1
    isSpot: false
    reserved: true
    isXenon: false
    hyperV: false
    targetWorkerCount: 1
    targetWorkerSizeId: 0
    zoneRedundant: false
  }
}

resource flexfunapp 'Microsoft.Web/sites@2024-04-01' = {
  name: 'vscodeflexfunapp02'
  location: 'uksouth'
  kind: 'functionapp,linux'
  properties: {
    serverFarmId: flexappserviceplan.id
    clientAffinityEnabled: false
    siteConfig: {
      appSettings: [
        {
          name: 'AzureWebJobsStorage'
          value: storageAccount.properties.primaryEndpoints.blob
        }
        {
          name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
          value: appInsights.properties.ConnectionString
        }
      ]
      numberOfWorkers: 1
    }
    functionAppConfig: {
      deployment: {
        storage: {
          type: 'blobcontainer'
          value: '${storageAccount.properties.primaryEndpoints.blob}container'
          authentication: {
            type: 'SystemAssignedIdentity'
          }
          
        }
      }
      scaleAndConcurrency: {
        maximumInstanceCount: 100
        instanceMemoryMB: 4096
      }
      runtime: {
        name: 'python'
        version: '3.11'
      }
    }
    httpsOnly: true
    publicNetworkAccess: 'Disabled'
    virtualNetworkSubnetId: virtualNetwork.properties.subnets[1].id
  }
}

resource networkSecurityGroup 'Microsoft.Network/networkSecurityGroups@2019-11-01' = {
  name: 'privateEndpointNSG'
  location: 'uksouth'
  properties: {
    securityRules: [
      {
        name: 'AllowAzurePrivateLink'
        properties: {
          priority: 100
          access: 'Allow'
          direction: 'Inbound'
          protocol: '*'
          sourceAddressPrefix: 'AzureActiveDirectory'  // Required for Azure Private Link
          sourcePortRange: '*'
          destinationAddressPrefix: '*'
          destinationPortRange: '*'
        }
      }
      {
        name: 'AllowAppTraffic'
        properties: {
          priority: 200
          access: 'Allow'
          direction: 'Inbound'
          protocol: 'Tcp'
          sourceAddressPrefix: '10.0.0.0/16'
          sourcePortRange: '*'
          destinationAddressPrefix: '*'
          destinationPortRange: '*'
        }
      }
    ]
  }
}


resource subnetAssociation 'Microsoft.Network/virtualNetworks/subnets@2021-02-01' = {
  parent: virtualNetwork
  name: 'InboundSubnet'
  properties: {
    networkSecurityGroup: {
      id: networkSecurityGroup.id
    }
  }
}

resource dnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = {
  name: 'privatelink.azurewebsites.net' // For Function Apps
  location: 'global'
}

resource dnsZoneLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = {
  parent: dnsZone
  name: 'vnetlink'
  properties: {
    virtualNetwork: {
      id: virtualNetwork.id
    }
    registrationEnabled: true
  }
}

resource privateEndpoint 'Microsoft.Network/privateEndpoints@2024-05-01' = {
  name: '${flexfunapp.name}-private-endpoint'
  location: 'uksouth'
  properties: {
    subnet: {
      id: virtualNetwork.properties.subnets[0].id // Use the InboundSubnet for the private endpoint
    }
    privateLinkServiceConnections: [
      {
        name: 'functionAppPrivateLink'
        properties: {
          privateLinkServiceId: flexfunapp.id
          groupIds: [
             'web'
          ]
        }
      }
    ]
  }
}

PS C:\Windows\System32> New-AzResourceGroupDeployment -Name 'FlexFuncAppDeployment' -TemplateFile 'D:\LearnBicep\PracticeBicep\flexfunctionapp.bicep' -ResourceGroupName 'vivekchak-rg' -Mode Incremental

New-AzResourceGroupDeployment: 1:41:20 PM - The deployment 'FlexFuncAppDeployment' failed with error(s). Showing 3 out of 3 error(s). Status Message: Call to Microsoft.Web/sites failed. Error message: GroupId is invalid. (Code: BadRequest)

Status Message: Address prefix and ipam pool reference are both empty/null in request payload of resource /subscriptions//resourceGroups/vivekchak-rg/providers/Microsoft.Network/virtualNetworks/vnetforflexfuncapp/subnets/InboundSubnet. Please provide either address prefix or ipam pool reference. (Code: NoAddressPrefixOrPoolProvided)

Status Message: The location property is required for this definition. (Code:LocationRequired)

I'm able to deploy all the resources as given in the bicep except the private endpoint, getting error as shown above.

Unable to figure out the error. please help

Upvotes: 1

Views: 146

Answers (1)

Thomas
Thomas

Reputation: 29736

Few things:

  • The location property is required for this definition. (Code:LocationRequired): The dnsZoneLink resource is missing the location property.
resource dnsZoneLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = {
  parent: dnsZone
  location: 'global'
  name: 'vnetlink'
  properties: {
    virtualNetwork: {
      id: virtualNetwork.id
    }
    registrationEnabled: true
  }
}
  • Call to Microsoft.Web/sites failed. Error message: GroupId is invalid. (Code: BadRequest): The groupIds property on the privateEndpoint resource has a wrong value. It should be sites.
resource privateEndpoint 'Microsoft.Network/privateEndpoints@2024-05-01' = {
  name: '${flexfunapp.name}-private-endpoint'
  location: 'uksouth'
  properties: {
    subnet: {
      id: virtualNetwork.properties.subnets[0].id // Use the InboundSubnet for the private endpoint
    }
    privateLinkServiceConnections: [
      {
        name: 'functionAppPrivateLink'
        properties: {
          privateLinkServiceId: flexfunapp.id
          groupIds: [
             'sites'
          ]
        }
      }
    ]
  }
}
  • Address prefix and ipam pool reference are both empty/null in request payload of resource ...: You should NOT be updating the subnet using the subnetAssociation resource. It will drop existing properties. Instead, you can specify the NSG when creating the vnet:
resource virtualNetwork 'Microsoft.Network/virtualNetworks@2019-11-01' = {
  name: 'thomastest-001-uks-vnet'
  location: 'uksouth'
  properties: {
    addressSpace: {
      addressPrefixes: [
        '10.0.0.0/16'
      ]
    }
    subnets: [
      {
        name: 'InboundSubnet'
        properties: {
          addressPrefix: '10.0.0.0/24'
          networkSecurityGroup: {
            id: networkSecurityGroup.id
          }
        }
      }
      ...
    ]
  }
}
  • You are creating a classic app insight resource which was retired last year (see documentation). You should create a workspace-based app insights:

enter image description here

resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' = {
  name: 'thomastest-001-uks-log'
  location: 'uksouth'
  properties: {
    sku: {
      name: 'PerGB2018'
    }
  }
}

resource appInsights 'Microsoft.Insights/components@2020-02-02' = {
  name: 'thomastest-001-uks-appi'
  location: 'uksouth'
  kind: 'web'
  properties: {
    Application_Type: 'web'
    WorkspaceResourceId: logAnalyticsWorkspace.id
  }
}

Full bicep sample:

resource storageAccount 'Microsoft.Storage/storageAccounts@2021-04-01' = {
  name: 'thomastest001uksst'  
  location: 'uksouth'
  kind: 'StorageV2'
  sku: {
    name: 'Standard_LRS'
  }
  properties: {
    accessTier: 'Hot'
    minimumTlsVersion: 'TLS1_2'
  }
}

resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' = {
  name: 'thomastest-001-uks-log'
  location: 'uksouth'
  properties: {
    sku: {
      name: 'PerGB2018'
    }
  }
}

resource appInsights 'Microsoft.Insights/components@2020-02-02' = {
  name: 'thomastest-001-uks-appi'
  location: 'uksouth'
  kind: 'web'
  properties: {
    Application_Type: 'web'
    WorkspaceResourceId: logAnalyticsWorkspace.id
  }
}

resource networkSecurityGroup 'Microsoft.Network/networkSecurityGroups@2019-11-01' = {
  name: 'thomastest-001-uks-nsg'
  location: 'uksouth'
  properties: {
    securityRules: [
      {
        name: 'AllowAzurePrivateLink'
        properties: {
          priority: 100
          access: 'Allow'
          direction: 'Inbound'
          protocol: '*'
          sourceAddressPrefix: 'AzureActiveDirectory'  // Required for Azure Private Link
          sourcePortRange: '*'
          destinationAddressPrefix: '*'
          destinationPortRange: '*'
        }
      }
      {
        name: 'AllowAppTraffic'
        properties: {
          priority: 200
          access: 'Allow'
          direction: 'Inbound'
          protocol: 'Tcp'
          sourceAddressPrefix: '10.0.0.0/16'
          sourcePortRange: '*'
          destinationAddressPrefix: '*'
          destinationPortRange: '*'
        }
      }
    ]
  }
}

resource virtualNetwork 'Microsoft.Network/virtualNetworks@2019-11-01' = {
  name: 'thomastest-001-uks-vnet'
  location: 'uksouth'
  properties: {
    addressSpace: {
      addressPrefixes: [
        '10.0.0.0/16'
      ]
    }
    subnets: [
      {
        name: 'InboundSubnet'
        properties: {
          addressPrefix: '10.0.0.0/24'
          networkSecurityGroup: {
            id: networkSecurityGroup.id
          }
        }
      }
      {
        name: 'OutboundSubnet'
        properties: {
          addressPrefix: '10.0.1.0/24'
          delegations: [
            {
              name: 'delegation'
              properties: {
                serviceName: 'Microsoft.App/environments'
              }
            }
          ]
        }
      }
    ]
  }
}


resource flexappserviceplan 'Microsoft.Web/serverfarms@2024-04-01' = {
  name: 'thomastest-001-uks-asp'
  location:  'uksouth'
  sku: {
    name: 'FC1'
    tier: 'FlexConsumption'
    family: 'FC'
    capacity: 0
  }
  kind: 'functionapp'
  properties: {
    reserved: true // linux
  }
}

resource flexfunapp 'Microsoft.Web/sites@2024-04-01' = {
  name: 'thomastest-001-uks-flex'
  location: 'uksouth'
  kind: 'functionapp,linux'
  properties: {
    serverFarmId: flexappserviceplan.id
    clientAffinityEnabled: false
    siteConfig: {
      appSettings: [
        {
          name: 'AzureWebJobsStorage'
          value: storageAccount.properties.primaryEndpoints.blob
        }
        {
          name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
          value: appInsights.properties.ConnectionString
        }
      ]
      numberOfWorkers: 1
    }
    functionAppConfig: {
      deployment: {
        storage: {
          type: 'blobcontainer'
          value: '${storageAccount.properties.primaryEndpoints.blob}container'
          authentication: {
            type: 'SystemAssignedIdentity'
          }
          
        }
      }
      scaleAndConcurrency: {
        maximumInstanceCount: 100
        instanceMemoryMB: 4096
      }
      runtime: {
        name: 'python'
        version: '3.11'
      }
    }
    httpsOnly: true
    publicNetworkAccess: 'Disabled'
    virtualNetworkSubnetId: virtualNetwork.properties.subnets[1].id
  }
}

resource dnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = {
  name: 'privatelink.azurewebsites.net' // For Function Apps
  location: 'global'
}

resource dnsZoneLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = {
  parent: dnsZone
  location: 'global'
  name: 'vnetlink'
  properties: {
    virtualNetwork: {
      id: virtualNetwork.id
    }
    registrationEnabled: true
  }
}

resource privateEndpoint 'Microsoft.Network/privateEndpoints@2024-05-01' = {
  name: '${flexfunapp.name}-private-endpoint'
  location: 'uksouth'
  properties: {
    subnet: {
      id: virtualNetwork.properties.subnets[0].id // Use the InboundSubnet for the private endpoint
    }
    privateLinkServiceConnections: [
      {
        name: 'functionAppPrivateLink'
        properties: {
          privateLinkServiceId: flexfunapp.id
          groupIds: [
             'sites'
          ]
        }
      }
    ]
  }
}

Upvotes: 2

Related Questions