Hitting the Apex: Onboard a root or apex domain and add a self-managed SSL certificate
In this article, we’ll cover how you onboard a root or apex domain to your CDN endpoint, and add a self-managed SSL certificate. We’ll also cover how to enforce HTTPS traffic on your CDN endpoint.
If you are reading this, chances are you want to create your own static website, want to know more about static site generators, how to host your static website using Azure services, or how you can automate the full integration of your web code and the deployment of your site build. Either way, the series of blog posts below might be something for you!
This article is written as a successor to a series that includes:
- The only guide you need for a static website in Azure - Part 1: Create a static website. In this article, I cover what a static website is, what there is to choose from, and how to create a (local) static website.
- The only guide you need for a static website in Azure - Part 2: Host your site using Azure Blob Storage. In this article, I cover how you can host your static website in Azure Blob Storage, what there is to choose from, and some basics around Content Delivery Network (CDN).
- The only guide you need for a static website in Azure - Part 3: Automate using Azure DevOps Pipelines. In this article, I cover what the Azure DevOps services are, and how to automate the build and deployment for your static website to Azure storage.
Let’s get started.
What is Azure DNS?
Azure DNS is a hosting service for DNS domains that provides name resolution by using Microsoft Azure infrastructure. By hosting your domains in Azure, you can manage your DNS records by using the same credentials, APIs, tools, and billing as your other Azure services. You can’t use Azure DNS to buy a domain name.
If you want to learn more about Azure DNS, check out the official documentation from Microsoft.
What is Azure Key Vault?
Azure Key Vault is a cloud service for securely storing and accessing secrets, API keys, passwords, certificates, and cryptographic keys, so you can keep them private.
If you want to learn more about Azure Key Vault, check out the official documentation from Microsoft.
Prerequisites
To start onboarding your apex or root domain to your CDN endpoint and add a self-managed SSL certificate, make sure you have met the following prerequisites.
Azure subscription
For this guide you need an Azure subscription, with a native user account that has the rights to create and edit an Azure Storage Account, and upload the static website build to this account.
Azure-hosted website
For this guide you need an Azure hosted website. This guide takes a static website from Azure Blob storage as the starting point. You also need a CDN profile with an endpoint to this static website. If you don’t have these things ready yet, create your static website build by following the first and second part of my “The only guide you need for a static website in Azure” blog series.
Self-managed SSL certificate
You will need an SSL certificate for this guide if you plan to follow the full guide and bring in your own SSL certificate. It is not possible to choose for an Azure-managed certificate for an apex or root domain. You can purchase an SSL certificate from the most common domain providers, such as Cloudflare, Namecheap, or local providers like TransIP from the Netherlands.
Azure CLI
In this guide you’ll use the Azure Cloud Shell for Azure CLI. However, if you prefer to work from your local workstation you can install the Azure CLI locally.
Onboarding your root or apex domain
An apex is the “root” level of your domain, for example schutten.cloud. The domain apex is the “root” of the domain name hierarchy. Each subdomain of this (eg. www.schutten.cloud) is not a domain apex, but a subdomain of schutten.cloud.
Let’s onboard the apex domain to an Azure CDN endpoint.
Create DNS zone
Open the Azure Cloud Shell, either by using the link or by clicking on its icon once you are logged in to the Azure Portal.
If you are using the Azure CLI locally, you’ll first need to sign in using the az login
command to using any CLI commands.
Now create a resource group that will contain the DNS zone. In the example below, I create a resource group named rg-p-weu-schuttencloud in the west-europe region. Use the example to create your own resource group by replacing the values with your own:
az group create \
--name rg-p-weu-schuttencloud \
--location westeurope
Now create a DNS zone. In the example below, I create a DNS zone named schutten.cloud in the resource group rg-p-weu-schuttencloud. Use the example to create your own DNS zone by replacing the values with your own:
az network dns zone create \
--name schutten.cloud \
--resource-group rg-p-weu-schuttencloud
Create an alias record for zone apex
Now create a recordset in the apex of the zone. In the example below I create a recordset in the apex of the schutten.cloud zone, with a TTL (time-to-live) of 60 seconds and my CDN endpoint as the target resource. Use the example to create your own DNS zone by replacing the values with your own:
az network dns record-set a create \
--name "@" \
--resource-group rg-p-weu-schuttencloud \
--zone-name schutten.cloud \
--target-resource YourCDNEndpoint \
--ttl 60
This will create a zone apex record pointing to your CDN resource, which uses a CNAME record-mapping cdnverify for onboarding the domain on your CDN profile. In my case cdnverify.schuttencloud.com.
Delegate the domain
The next thing to do is to update the NS (name server) records for your domain with your domain registrar.
Before you can delegate your DNS zone to Azure DNS, you need to know the name servers for your zone. In the example below I retrieve the required information for the earlier DNS zone schutten.cloud. Use the example to retrieve your own DNS zone information by replacing the values with your own:
az network dns zone show \
--resource-group rg-p-weu-schuttencloud \
--name schutten.cloud
The answer returned should look like the image below, where the four lines after “nameServers” are the ones we’ll need in the next step. Write these down.
As each registrar has its own DNS management tools to change the name server records for a domain, it is not possible to include this in this manual. Your domain registrar probably has documentation available for updating the NS records. If not, please contact your domain registrar.
To verify that the NS records are updated correctly, you can use the nslookup
command. Use the example below and replace the values with your own:
nslookup -type=SOA schutten.cloud
Your response should look similar to the following nslookup
output:
Onboard the custom domain on your CDN
Now that we have registered our apex domain, we can add it to the CDN endpoint. In the example below I add the domain schutten.cloud to my CDN endpoint ep-cdn-schuttencloud, which is part of the CDN profile cdn-schuttencloud. Use the example to add your own custom domain to your CDN endpoint by replacing the values with your own:
az cdn custom-domain create \
--name schuttenclouddomain \
--resource-group rg-p-weu-schuttencloud \
--hostname schutten.cloud \
--endpoint-name ep-cdn-schuttencloud \
--profile-name cdn-schuttencloud
Azure verifies that the CNAME record exists for the custom domain name you entered. If the CNAME is correct, your custom domain will be validated. Now enable HTTPS on the custom domain for Azure CDN, by using the example below and replacing the values with your own:
az cdn custom-domain enable-https \
--name schuttenclouddomain \
--resource-group rg-p-weu-schuttencloud \
--endpoint-name ep-cdn-schuttencloud \
--profile-name cdn-schuttencloud \
--min-tls-version 1.2
You have now added your apex/root domain to your CDN endpoint and should be able to reach your static website hosted in your Azure (Blob) storage account on this domain in your web browser.
Using a self-managed SSL certificate
In this blog we’ve created a CDN endpoint with a CDN managed certificate for the www.schutten.cloud subdomain. Unfortunately, it is not possible to use CDN managed certificates for apex/root domains. You are therefore obliged to submit your own certificate. Azure Key Vault is the obvious choice to store the certificate. Let’s get started.
Create an Azure Key Vault
Now create an Azure Key Vault that will store your certificate. In the example below I am creating an Azure Key Vault within the same resource group as the Azure DNS Zone, which is rg-p-weu-schuttencloud, again in the west-europe region. Use the example below to create your key vault by replacing the values with your own.
az keyvault create \
--name "kv-p-weu-schuttencloud" \
--resource-group "rg-p-weu-schuttencloud" \
--location westeurope
Register the service principal for CDN/Front Door
To enable the CDN endpoint to access the certificate in the key vault, we register a service principal. In the example below, I register a service principal in Azure Active Directory as an app. Execute this command:
az ad sp create --id 205478c0-bd83-4e1b-a9d6-db63a3e1e1c8
After this we have to give the service principal access to be able to request the certificate. In the example below I give ‘get’ permissions to the service principal on the secrets and certificates in the key vault. Use the example below and replace the values with your own:
az keyvault set-policy \
--name "kv-p-weu-schuttencloud" \
--certificate-permissions get \
--secret-permissions get \
--application-id 205478c0-bd83-4e1b-a9d6-db63a3e1e1c8
The service principal can now access this key vault and the certificates it contains.
Prepare your certificate (optional)
Azure Key Vault only accepts PKCS12 and PEM certificates, but sometimes SSL certificate vendors provide the certificate in a different format. In my case, my supplier provided the certificates in CRT format. With openssl
we can solve this problem and create a supported PFX certificate from the CRT certificates.
You can download OpenSSL from their website, or by executing the choco install openssl
command, if you’re using Chocolatey like myself.
Run the following command in the folder of your downloaded certificates, where the key file should be just a text file with your private in it, which you received from your SSL certificate provider:
openssl pkcs12 -export -out schutten.cloud.pfx -inkey certificate.key -in certificate.crt -in rootca.crt
You now have a certificate which is ready to be imported in the Azure Key Vault.
Import certificate to Azure Key Vault
Now import your certificate to the Azure Key Vault. In the example below I’m naming the certificate SchuttenCloud and importing the certificate.pfx PKCS12-file to the earlier created key vault. Use the example below to import your own certificate to your key vault by replacing the values with your own.
az keyvault certificate import \
--name "SchuttenCloud" \
--file "certificate.pfx" \
--vault-name "kv-p-weu-schuttencloud"
Enable HTTPS on CDN endpoint
Now enable HTTPS on the custom domain for Azure CDN, by using the example below and replacing the values with your own:
az cdn custom-domain enable-https \
--name schuttenclouddomain \
--resource-group rg-p-weu-schuttencloud \
--endpoint-name ep-cdn-schuttencloud \
--profile-name cdn-schuttencloud \
--min-tls-version 1.2 \
--user-cert-grou-name rg-p-weu-schuttencloud \
--user-cert-secret-name SchuttenCloud \
--user-cert-vault-name kv-p-weu-schuttencloud
You have now enabled HTTPS on your your CDN endpoint and should be able to reach your static website hosted in your Azure (Blob) storage account on this domain in your web browser trough HTTPS.
Redirecting HTTP requests to https
Obviously we want to redirect all HTTP requests to HTTPS. If you don’t know why this is important, I suggest you read this blog article.
In the example below, a CDN engine rule is added to forward all traffic coming in via HTTP to the HTTPS protocol. More information about the parameters and fields within a CDN engine rule can be found on Microsoft’s official documentation site. Use the example below to create the rule yourself, by replacing the values with your own:
az cdn endpoint rule add \
--name ep-cdn-schuttencloud \
--resource-group group rg-p-weu-schuttencloud \
--profile-name cdn-schuttencloud \
--order 1 \
--rule-name "EnforceHTTPS" \
--match-variable RequestScheme \
--operator Equal \
--match-values HTTP \
--action-name "UrlRedirect" \
--redirect-protocol Https \
--redirect-type Moved
All traffic coming in via an HTTP request is now redirected to HTTPS.
Conclusion
In this article, you have read what Azure DNS is, what Azure Key Vault is, how you onboard your apex or root domain to your CDN endpoint, how to use a self-managed SSL certificate being stored in an Azure Key Vault, and how to enforce HTTPS traffic on your CDN endpoint. Don’t forget that it is important to monitor your SSL certificate. Azure won’t notify you out-of-the-box when the certificate expires, neither will they automatically renew it, as they do for you with an Azure-managed certificate. In this blog article I explain how you can monitor an SSL certificate, using Azure Application Insights.
Author: Rolf Schutten
Posted on: July 15, 2022