Search code examples
azureazure-bicepazure-appserviceazure-front-doorazure-private-link

How do I automatically approve a private endpoint request from front door?


I am using Infrastructure-As-Code to create an app service, and a front door endpoint using a private endpoint. I do this with bicep templates.

Once created, I have to approve the private endpoint link in the UI.

How can I automatically approve this private endpoint request? Is there a way to do this with a bicep deployment?

I use this bicep to create the origin, with the endpoint.

resource appService 'Microsoft.Web/sites@2022-09-01' existing = {
  name: applicationName
  scope: resourceGroup(resourceGroup)
}

resource fdOrigin 'Microsoft.Cdn/profiles/originGroups/origins@2021-06-01' = {
  name: 'fd-origin'
  parent: fdOriginGroup
  properties: {
    hostName: '${applicationName}.azurewebsites.net'
    httpPort: 80
    httpsPort: 443
    originHostHeader: '${applicationName}.azurewebsites.net'
    priority: 1
    weight: 1000
    sharedPrivateLinkResource: {
      groupId: 'sites'
      privateLinkLocation: 'EastUS2'
      requestMessage: 'Created by Deployment Pipeline'
      status: 'Approved'
      privateLink: {
        id: appService.id
      }
    }
  }
}

I've tried setting the status to approved in the sharedPrivateLinkResource section, but it doesn't approve it. It's doesn't throw an error, but the link is still in Pending status.

I can approve it with the bicep below, but I have to hardcode the private link name. I can't find a way to get the private link name from the bicep above.

resource privateEndpointConnection 'Microsoft.Web/sites/privateEndpointConnections@2022-09-01' = {
  name: 'MyAppService/ecc50509-75b1-xxxx-92c9-62bebcececf3-13f6a331-6472-4497-bf94-67adda467e22'
  properties: {
      privateLinkServiceConnectionState: {
          status: 'Approved' 
          description: 'Approved by pipeline'
      }
  }
}

Solution

  • Once front-door deployment is completed, the private endpoint connections information are available on the webapp properties itself. You can verify that by running:

    az rest --method get --uri <webapp-resource-id>?api-version=2022-09-01
    

    You will see this section:

    "privateEndpointConnections": [
      {
        "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx/resourceGroups/front-door-test/providers/Microsoft.Web/sites/myapp-bckwiz6zgci7k/privateEndpointConnections/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        ...
      }
    ]
    

    you can create a module to fetch the endpoint name:

    // fetch-private-endpoint.bicep
    param appName string
    resource app 'Microsoft.Web/sites@2020-06-01' existing = {
      name: appName
    }
    output name string = last(split(first(app.properties.privateEndpointConnections).id,'/'))
    

    Then having a second module to approve the connection:

    // approve-private-endpoint.bicep
    param appName string
    param endPointName string
    
    resource app 'Microsoft.Web/sites@2022-09-01' existing = {
      name: appName
    }
    
    resource privateEndpointConnection 'Microsoft.Web/sites/privateEndpointConnections@2022-09-01' = {
      parent: app
      name: endPointName
      properties: {
        privateLinkServiceConnectionState: {
          status: 'Approved'
          description: 'Approved by pipeline'
        }
      }
    }
    

    Then in your main template you can add that:

    // Need to wait for front door deployment to be completed
    module fetchPrivateEdnpointName 'modules/fetch-private-endpoint.bicep' = {
      name: 'fetch-private-endpoint'
      dependsOn: [
        fdOrigin
      ]
      params: {
        appName: appName
      }
    }
    
    module approvePrivateEndpoint 'modules/approve-private-endpoint.bicep' = {
      name: 'approve-private-endpoint'
      params: {
        appName: appName
        endPointName: fetchPrivateEdnpointName.outputs.name
      }
    }