Categories
App Service Azure Microsoft

Create SSL binding to an app custom domain in Azure App Service with ARM template

In the series of articles about ARM template, we will learn to create a template to secure a custom domain with SSL.

Via the Azure portal you can create an SSL binding with Azure App Service. When selecting SSL certificates in an App Service then Add binding, you can bind a custom domain with a certificate.

Today we will discover how to manage this operation via an Azure Resource Manager template. Our ARM template will be created in a new Azure Resource Group deployment project in Visual Studio.

 

Creation

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "websiteName": {
      "type": "string"
    },
    "websiteCustomDomainName": {
      "type": "string"
    },
    "certificateThumbprint": {
      "type": "string"
    }
  }
  ...
}
  • websiteName: the name of the azure app service such as myappname.azurewebsites.net.
  • websiteCustomDomainName: the name of the custom domain such as mycustomdomain.com.
  • certificateThumbprint: the thumbprint of the certificate to bind such as 22XXBE10XXE5D2DBAD29DXXXX7.

 

Now we will declare the resources of the ARM template:

{
  ...
  "resources": [
    {
      "apiVersion": "2015-08-01",
      "name": "[parameters('websiteName')]",
      "type": "Microsoft.Web/sites",
      "location": "[resourceGroup().location]",
      "properties": {
        "hostNameSslStates": [
          {
            "name": "[parameters('websiteCustomDomainName')]",
            "sslState": "SniEnabled",
            "thumbprint": "[parameters('certificateThumbprint')]",
            "toUpdate": true
          }
        ]
      }
    }
  ]
  ...
}

We can pay attention to several things here:

  • The SSL binding is made via a property of the website named: hostNameSslStates.
  • One or multiple hostNameSslStates can be declared.
  • Each hostNameSslState have name property corresponding to the custom domain name and thumbprint property corresponding to the certificate thumbprint that will be binded.

 

Example of use

The ARM template is now ready, let’s open a Windows PowerShell and try it:

.\Deploy-AzureResourceGroup.ps1 -ResourceGroupName 'MyResourceGroupName' -ResourceGroupLocation 'canadaeast' -TemplateFile '.\azuredeploy.json'

...

Resource Microsoft.Web/sites 'myappname' provisioning status is succeeded

If everything goes well, you should see the same kind of message as above.

 

To go further

To be able to perform the binding operation you first need to add the custom domain name to the app as seen in a previous article. If the custom domain is not added first you’ll get the following error message:

Resource Microsoft.Web/sites ‘myappname’ failed with message ‘Hostname ‘mycustomdomain.com’ does not exist’.

 

Summary

We have seen how to create an ARM template that will create an SSL binding to an app custom domain in Azure App Service.

 

You can download the example solution here:

Download full sources

Or

Browse the GitHub repository

 

Please feel free to comment or contact me if you have any question about this article.

Categories
Azure Microsoft Web certificates

Deploying a web certificate with ARM template to an Azure resource group and retrieving certificate thumbprint

In this article we will create an ARM template that will deploy a web certificate to an Azure resource group and output the certificate thumbprint.

Adding an SSL certificate to an app with Azure App Service can be achieved via the Azure portal. When selecting SSL certificates in an App Service then Upload Certificate, you can upload a PFX Certificate File with the associated Certificate password. The certificate will then be added to the resource group and will be available to create a binding with the application.

In today’s article we will discover how to manage this operation via an Azure Resource Manager template. Our ARM template will be created in a new Azure Resource Group deployment project in Visual Studio.

 

Creation

Let’s declare the parameters of the ARM template:

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "certificatePrefixName": {
      "type": "string"
    },
    "certificatePfxBase64": {
      "type": "securestring"
    },
    "certificatePfxPassword": {
      "type": "securestring"
    }
  }
  ...
}
  • certificatePrefixName: a prefix for the certificate name such as the domain name associated to the certificate.
  • certificatePfxBase64: the certificate PFX file bytes converted to a base64 string.
  • certificatePfxPassword: the password associated with the certificate.

 

Now we will declare the resources of the ARM template:

{
  ...
  "variables": {
    "certificateName": "[concat(parameters('certificatePrefixName'), uniqueString(resourceGroup().id))]"
  },
  "resources": [
    {
      "apiVersion": "2015-08-01",
      "name": "[variables('certificateName')]",
      "type": "Microsoft.Web/certificates",
      "location": "[resourceGroup().location]",
      "properties": {
        "pfxBlob": "[parameters('certificatePfxBase64')]",
        "password": "[parameters('certificatePfxPassword')]"
      },
      "tags": {
        "displayName": "Certificate"
      }
    }
  ]
  ...
}

We can pay attention to two things here:

  • The certificate name is the concatenation of the prefix name and a unique string based on the resource group id. Depending on your needs you can adapt it.
  • The certificate is declared with the following type: Microsoft.Web/certificates.

  

And to finish we will output the certificate thumbprint:

{
  ...
  "outputs": {
    "certificateThumbprint": {
      "type": "string",
      "value": "[reference(resourceId('Microsoft.Web/certificates', variables('certificateName')), providers('Microsoft.Web', 'certificates').apiVersions[0]).thumbprint]"
    }
  }
}

As you can notice, we take advantage of the ARM template function providers. This function is useful to get the latest API version for a specific namespace.

 

Example of use

The ARM template is now ready, let’s open a Windows PowerShell and try it:

.\Deploy-AzureResourceGroup.ps1 -ResourceGroupName 'MyResourceGroupName' -ResourceGroupLocation 'canadaeast' -TemplateFile '.\azuredeploy.json'

...

OutputsString      :
                     Name                   Type                       Value
                     ===============        =========================  ==========
                     certificateThumbprint  String                     22XXBE10XXE5D2DBAD29DXXXX75510583XXXXXE2

If everything goes well, you should see the same kind of message as above.

 

To go further

In the template you need the certificate PFX file bytes converted to a base 64 string. Here is a simple PowerShell script that will take the file path of a PFX file and output it as base64 string in a file:

Param([string] $pfxFilePath)

$pfxFileBytes = get-content $pfxFilePath -Encoding Byte

[System.Convert]::ToBase64String($pfxFileBytes) | Out-File 'PfxFileBytes-Base64.txt'

 

Summary

We have seen how to create an ARM template that will deploy a web certificate to an Azure resource group and output the certificate thumbprint.

 

You can download the example solution here:

Download full sources

Or

Browse the GitHub repository

 

Please feel free to comment or contact me if you have any question about this article.

Categories
App Service Azure Microsoft

Adding a custom domain name to an app with ARM template in Azure App Service

In this article we will create an ARM template that will allow to add a custom domain to a web app, mobile app, or API app in Azure App Service.

With Azure App Service it’s easy to add a custom domain via the portal. Everything is well described in the Azure documentation on the Map a custom domain name to an Azure app page.

Today we will focus on creating an Azure Resource Manager template to easily add a custom domain to an app. For our ARM template to work properly, it is first required to create the DNS record and the website.

 

Creation

Let’s declare the parameters of the ARM template:

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "websiteName": {
      "type": "string"
    },
    "websiteCustomDomainName": {
      "type": "string"
    }
  }
  ...
}
  • websiteName: the name of the azure app service such as myappname.azurewebsites.net.
  • websiteCustomDomainName: the name of the custom domain such as mycustomdomain.com.

 

Now we will declare the resources of the ARM template:

{
  ...
  "resources": [
    {
      "apiVersion": "2015-08-01",
      "name": "[concat(parameters('websiteName'),'/',parameters('websiteCustomDomainName'))]",
      "type": "Microsoft.Web/sites/hostNameBindings",
      "location": "[resourceGroup().location]",
      "properties": {
        "domainId": null,
        "hostNameType": "Verified",
        "siteName": "parameters('websiteName')"
      }
    }
  ]
  ...
}
  • The custom domain is declared with the following type: Microsoft.Web/sites/hostNameBindings.
  • The name of the resource is a concatenation of the website name and the custom domain name.

 

Example of use

The ARM template is now ready, let’s open a Windows PowerShell and try it:

.\Deploy-AzureResourceGroup.ps1 -ResourceGroupName 'MyResourceGroupName' -ResourceGroupLocation 'canadaeast' -TemplateFile '.\azuredeploy.json'

...

Resource Microsoft.Web/sites/hostNameBindings 'myappname/mycustomdomain.com' provisioning status is succeeded

If everything goes well, you should see the same kind of message as above.

 

To go further

If the DNS record is not created when deploying the template you’ll get the following error message:

A CNAME record pointing from mycustomdomain.com to myappname.azurewebsites.net was not found. Alternative record awverify.mycustomdomain.com to awverify.myappname.azurewebsites.net was not found either.

 

Summary

We have seen how to create an ARM template that will add a custom domain in Azure App Service.

 

You can download the example solution here:

Download full sources

Or

Browse the GitHub repository

 

Please feel free to comment or contact me if you have any question about this article.

Categories
Azure Microsoft Notification Hubs

Deploying Azure Notification Hub with ARM template and retrieving primary connection string

In this article we will create an ARM template that will deploy a Notification Hub and output the primary connection string.

Sending push notifications to your mobile application can require a lot of development and maintenance. Fortunately in all the Azure products, one will help you to send push notifications cross-platform with minimum efforts: Azure Notification Hubs.

Today we will focus on creating an Azure Resource Manager template to easily setup and deploy a Notification Hub to a resource group. Our ARM template will be created in a new Azure Resource Group deployment project in Visual Studio.

 

Creation

Let’s declare the parameters of the ARM template:

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "notificationHubNamespaceName": {
      "type": "string",
      "defaultValue": "[concat('myNotifHubNs', uniqueString(resourceGroup().id))]"
    },
    "notificationHubName": {
      "type": "string",
      "defaultValue": "[concat('myNotifHub', uniqueString(resourceGroup().id))]"
    },
    "notificationHubSkuName": {
      "type": "string",
      "defaultValue": "free",
      "allowedValues": [
        "free",
        "basic",
        "standard"
      ]
    }
  }
  ...
}
  • notificationHubNamespaceName: the name of the Notification Hub namespace. If no parameter is provided a default name such as myNotifHubNsesf262thj4rr6 is generated.
  • notificationHubName: the name of the Notification Hub. If no parameter is provided a default name such as myNotifHubesf262thj4rr6 is generated.
  • notificationHubSkuName: the pricing tier of the Notification Hub. If no parameter is provided the pricing tier will be free.

 

Now we will declare the resources composed by the Notification Hub namespace and the Notification Hub:

{
  ...
  "resources": [
    {
      "apiVersion": "2014-09-01",
      "name": "[parameters('notificationHubNamespaceName')]",
      "type": "Microsoft.NotificationHubs/namespaces",
      "location": "[resourceGroup().location]",
      "sku": {
        "name": "[parameters('notificationHubSkuName')]"
      },
      "properties": {
        "name": "[parameters('notificationHubNamespaceName')]",
        "namespaceType": "NotificationHub"
      },
      "resources": [
        {
          "apiVersion": "2014-09-01",
          "name": "[concat(parameters('notificationHubNamespaceName'),'/',parameters('notificationHubName'))]",
          "type": "Microsoft.NotificationHubs/namespaces/notificationHubs",
          "location": "[resourceGroup().location]",
          "dependsOn": [
            "[concat('Microsoft.NotificationHubs/namespaces/', parameters('notificationHubNamespaceName'))]"
          ],
          "properties": {
            "name": "[parameters('notificationHubName')]"
          },
          "tags": {
            "displayName": "NotificationHub"
          }
        }
      ],
      "tags": {
        "displayName": "NotificationHubNamespace"
      }
    }
  ]
  ...
}

We can pay attention to several things here:

  • The namespace is declared with the following type: Microsoft.NotificationHubs/namespaces.
  • The hub is declared with the following type: Microsoft.NotificationHubs/namespaces/notificationHubs.
  • The hub depends on the namespace as hubs are always declared under a namespace.

 

And to finish, we will output the primary connection string of the hub: 

{
  ...
  "outputs": {
    "NotificationHubNamespaceConnectionString": {
      "type": "string",
      "value": "[listKeys(resourceId('Microsoft.NotificationHubs/namespaces/notificationHubs/authorizationRules', parameters('notificationHubNamespaceName'), parameters('notificationHubName'), 'DefaultFullSharedAccessSignature'), providers('Microsoft.NotificationHubs', 'namespaces/notificationHubs').apiVersions[0]).primaryConnectionString]"
    }
  }
}

As you can notice, we take advantage of the ARM template function listKeys and the ARM template function providers.

The function providers is useful to get the latest API version for a specific namespace, whereas listkeys is the function that will allow us to get the properties for a specific key name.

By default when a new hub is created, two access keys are created: DefaultListenSharedAccessSignature and DefaultFullSharedAccessSignature. In our template we retrieve the primary connection string for the second one.

 

Example of use

The ARM template is now ready, let’s open a Windows PowerShell and try it:

.\Deploy-AzureResourceGroup.ps1 -ResourceGroupName 'MyResourceGroupName' -ResourceGroupLocation 'canadaeast' -TemplateFile '.\azuredeploy.json'

...

OutputsString      :
                     Name                                      Type                       Value
                     ===============                           =========================  ==========
                     notificationHubNamespaceConnectionString  String                     Endpoint=sb://mynotifhubnsjibxupcseloca.servicebus.windows.net/;SharedAccessKeyName=DefaultFullSharedAccessSignature;SharedAccessKey=b0zOZuqc/mvrcLq8M49mfLomHBw4PH56uazMM/8r22Q=

If everything goes well, you should see the same kind of message as above.

 

To go further

In the template we are outputting the connection string as an example. But in a more advance scenario with a Website you could directly set the application setting that require the connection string like the following:

{
  ...
  "resources": [
    {
      ...
      "resources": [
        {
          "apiVersion": "2015-08-01",
          "name": "appsettings",
          "type": "config",
          "dependsOn": [
            "[resourceId('Microsoft.NotificationHubs/namespaces/notificationHubs', parameters('notificationHubNamespaceName'), parameters('notificationHubName'))]",
            "[resourceId('Microsoft.Web/sites', parameters('myWebsiteName'))]"
          ],
          "properties": {
            "NotificationHubConnectionString": "[listKeys(resourceId('Microsoft.NotificationHubs/namespaces/notificationHubs/authorizationRules', parameters('notificationHubNamespaceName'), parameters('notificationHubName'), 'DefaultFullSharedAccessSignature'), providers('Microsoft.NotificationHubs', 'namespaces/notificationHubs').apiVersions[0]).primaryConnectionString]",
            "NotificationHubPath": "[parameters('notificationHubName')]"
          }
        }
      ]
      ...
    }
  ]
  ...
}

 

Summary

We have seen how to create an ARM template that will deploy an Azure Notification Hub and output the primary connection string.

 

You can download the example solution here:

Download full sources

Or

Browse the GitHub repository

 

Please feel free to comment or contact me if you have any question about this article.