2
votes

Is there a way to add a Hybrid Connection to a Azure Web App in an automated way? (either through PowerShell or a Resource Template or even a REST call to the Azure API?)

At the moment I have an Azure Web App being deployed with a Resource Manager Template and everything is being configured correctly, however I'm unable to figure out how I can link the Web App to an existing BizTalk Hybrid Connection in the template or via PowerShell (some sort of automated way).

Azure Web App Hybrid Connection

4

4 Answers

2
votes

The Azure documentation states that linking an Azure Web App to an existing Hybrid Connection can only be done manually via the Portal:

NOTE: The Web Apps portion of the Hybrid Connections feature is available only in the Azure Portal.

2
votes

You can do this manually through the resource manager (https://resources.azure.com/) via a restful "Create" call when you drill down through your:

subscription -> resource groups -> sites -> -> hybridconnection

I have copied the call the resource manager app makes and replicated it in Powershell.

You need to:

  1. Find your subscriptions tenant id (google it)
  2. Register an application with AzureAD
    • Get that applications Id and secret
  3. Collect various constants from resource manager such as a Biztalk Uri and something called an Entity Connection String

The script uses these details to get an auth token to call the rest api from powershell. It then calls the classic rest api to add the exisitng hybrid connection to the website. Note that this will only work on a website that has previously had a hybrid connection, so you cant spin up a brand new environment without some manual work and recording details from resource manager.

Below is a copy of this script, I call it from Octopus deploy so all #{...} variables are supplied from there.

This script will keep calling an api endpoint to the external facing website that calls an internal system via the hybrid connection. It will try 5 times waiting for a 200 response.

The Hybrid.ConnectionRestUrl variable I use in the script was acquired by watching the call the resource manager makes. It is constructed like this: https://management.azure.com/subscriptions/#{SubscriptionId}/resourceGroups/#{resource-group-name}/providers/Microsoft.Web/sites/#{web-site-name}/hybridconnection/#{web-site-name}?api-version=2015-08-01

No guarantee how long this script will work as it is hardly a supported method.

    $authUri = "https://login.microsoftonline.com/#{tenant-domain}/oauth2/token"
    $authMethod = "POST"
    $authFormFields = @{resource='https://management.core.windows.net/';client_id='#{AzureAD.ApplicationId}';grant_type='client_credentials';client_secret='#{AzureAD.ApplicationSecret}'}
    $authResponse = Invoke-WebRequest -Uri $authUri -Method $authMethod -Body $authFormFields -ContentType "application/x-www-form-urlencoded" | ConvertFrom-Json

    $authorization = "Bearer " + $authResponse.access_token
    $headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
    $headers.Add("Authorization", $authorization)
    $headers.Add("Content-Type", "application/json")

    $URI = "#{Hybrid.ConnectionRestUrl}"
    $method = "PUT"
    $body = '{ "name" : "#{ExternalAzureService.WebApp}", "location" : "#{App.Location}", "type" : "Microsoft.Web/sites", "properties" : { "entityName" : "#{Hybrid.EntityName}", "entityConnectionString" : "#{Hybrid.EntityConnectionString}", "resourceType" : "", "resourceConnectionString" : "", "hostname" : "#{InternalService.Hostname.Raw}", "port" : 80, "biztalkUri" : "#{Hybrid.BiztalkUri}" } }'

    Write-Output $URI
    Write-Output $body

    Try
    {
        $result = Invoke-RestMethod -Uri $URI -Method $method -Headers $headers -Body $body
    }
    Catch
    {
        Write-Output "Error Occurred "
        $i = 1
        $pingUrl = "http://#{ExternalAzureService.WebApp.HostName}/api/callinternalsystem"
        Write-Output "Ping $i times this url: $pingUrl"
        Do
        {
             Write-Output "Starting Ping call $i"
             $response = Invoke-WebRequest $pingUrl
             If ($response.StatusCode -eq 200) {
                Write-Output "200 returned"
                Break
             }
             $i++
        } While ($i -le 5)
    }
    Write-Output " *********************************** SUCCESS ********************************** "
    Write-Output $result
2
votes

This can now be done in an Azure Resource Manager (ARM) template by using the Microsoft.Web sites/hybridConnectionNamespaces/relays template reference.

Here is an abbreviated example of what this could look like.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "resources": [
    {
      "type": "Microsoft.Web/sites",
      "apiVersion": "2018-11-01",
      "resources": [
        {
          "apiVersion": "2019-08-01",
          "dependsOn": [
            "[resourceId('Microsoft.Web/sites', variables('appName'))]"
          ],
          "name": "[concat(variables('relayName'), '/', parameters('hybridConnectionName'))]",
          "properties": {
            "hostname": "[split(json(reference(variables('hybridConnectionResourceId'), '2017-04-01').userMetadata)[0].value, ':')[0]]",
            "port": "[split(json(reference(variables('hybridConnectionResourceId'), '2017-04-01').userMetadata)[0].value, ':')[1]]",
            "relayArmUri": "[variables('hybridConnectionResourceId')]",
            "relayName": "[parameters('hybridConnectionName')]",
            "sendKeyName": "[parameters('hybridConnectionSendKeyName')]",
            "sendKeyValue": "[listkeys(concat(variables('hybridConnectionResourceId'), '/authorizationRules/defaultSender'), '2017-04-01').primaryKey]",
            "serviceBusNamespace": "[variables('relayName')]"
          },
          "tags": {
            "displayName": "hc-some-name"
          },
          "type": "hybridConnectionNamespaces/relays"
        }
      ]
    }
  ]
}
0
votes

The REST API for managing biztalk service can be found here A reference to more developer resources (including powershell) https://msdn.microsoft.com/en-us/library/azure/dn832182.aspx.

I don't have an example of an ARM template, but maybe a schema could help you https://github.com/Azure/azure-resource-manager-schemas/blob/master/schemas/2014-04-01/Microsoft.BizTalkServices.json