Static Website With HTTPS Running on Azure Blob Storage Using Azure CDN

In this post I will setup Azure Blob Storage, Azure KeyVault and Azure CDN to host a static website using HTTPS

Required Software

Ensure you have an Azure subscription you can use. If you have an MSDN subscription don’t forget to activate your monthly Azure Subscription you get with that MSDN.

You will also need the following software installed

  1. Azure CLI
  2. Access to your DNS Provider

I develop on a windows machine and use the Windows PowerShell ISE for development. I am sure there are more funkier IDEs, but this does the job for me! For ease of simplicity, I will create one large PowerShell script that can be executed line by line so you can see what is going on.

This script can be found here - again step through it line by line to execute the script.

Variables

Let’s start with declaring the variables we will use and that can be customised based on your needs.

Open the scrip in the PowerShell ISE and review

## Set Variables
############
# Set Variables
##############
$AZ_SUBSCRIPTION="" #Your subscription id
$AZ_RESOURCE_GROUP="" #Your resource group
$AZ_LOCATION="" #What location you want your resources created in
$AZ_StorageAccountName="" #Storage Account to create
$AZ_EndpointName="" #CDN Endpoint Name
$AZ_ProfileName="" #CDN Profile Name
$AZ_HostName="" #Custom Domain Name
$AZ_DomainName="" #Domain Name
$AZ_KeyVault_Name="" #Keyvault Name
$AZ_IPAdrressAllow="" #Your IP Address to access the Keyvault
$AZ_CertName="" #Name of your cert

Login to Azure - for the subscription you are using make sure you have owner rights

az login
az account set -s $AZ_SUBSCRIPTION

#Create Resource Group
az group create --resource-group $AZ_RESOURCE_GROUP --location $AZ_LOCATION

#Create the storage account 
az storage account create -n $AZ_StorageAccountName -g $AZ_RESOURCE_GROUP --sku Standard_LRS --min-tls-version TLS1_2

#Enable static website hosting
az storage blob service-properties update --account-name $AZ_StorageAccountName --static-website --404-document 404.html --index-document index.html

If you have checked out this repo then you should have the following directory present. Make sure you change into that directory in the PowerShell ISE console window

#Upload the contents of this directory to the web container
az storage blob upload-batch -s .\web -d '$web' --account-name $AZ_StorageAccountName --content-type 'text/html; charset=utf-8'

Now we are going to create a CDN profile

# Create the CDN profile
az cdn profile create --name $AZ_ProfileName -g $AZ_RESOURCE_GROUP -l $AZ_LOCATION --sku Standard_Microsoft

Once that CDN profile has been created you need to update your DNS Provider to have a CNAME reference this endpoint. I use Cloudflare as my DNS Provider and I created the following CNAME entries in the DNS Settings for my domain.

  • Type = CNAME

  • name = your domain name

  • content = yourendpointname.azureedge.net

  • Type = CNAME

  • name = cdnverify

  • content = cdnverify.yourendpointname.azureedge.net

This may take some time to propagate so wait 10 mins to try the next commands

#Get the primary web url for use later
$AZ_PrimaryWebOrigin=$(az storage account show -n $AZ_StorageAccountName -g $AZ_RESOURCE_GROUP --query "primaryEndpoints.web" --output tsv)

#Remove the staring https and trailing /
$OriginHostheader=$AZ_PrimaryWebOrigin.Substring(8,($AZ_PrimaryWebOrigin.Length - 9))

#Add the endpoint to the CDN 
az cdn endpoint create --name $AZ_EndpointName -g $AZ_RESOURCE_GROUP --profile-name $AZ_ProfileName --origin $OriginHostheader 80 443 --origin-host-header $OriginHostheader

Now we are going to create a Key Vault to host our Certificate for HTTPS.

#Create Keyvault
az keyvault create -l $AZ_LOCATION -g $AZ_RESOURCE_GROUP -n $AZ_KeyVault_Name --sku Standard --default-action Deny

#Grant access to your IP Address
az keyvault network-rule add -n $AZ_KeyVault_Name -g $AZ_RESOURCE_GROUP --ip-address $AZ_IPAdrressAllow

Now we need a certificate! I use Lets Encrypt and Certbot.

I use WSL2 + Ubuntu on my windows machine and have installed Certbot I use manual mode to request a certificate from Lets Encrypt. This requires adding another txt record to your DNS Provider.

Once you have certbot installed run the following command in a terminal window. The cert needs to be in RSA format in order to work with the Azure CDN

Remember to change your domain

sudo certbot certonly --cert-name "certname" --manual -d "your domain" --key-type rsa --preferred-challenges dns

This will then prompt you to add the txt record with a certain name and value. When added then press continue. If all went well you should have a new certificate locally on your machine

Once the cert is created run the following command to convert the cert to PFX format - change paths and domains to match yours.

sudo openssl pkcs12 -export -inkey /etc/letsencrypt/live/yourdomain/privkey.pem -in /etc/letsencrypt/live/yourdomain/fullchain.pem -name yourdoamin -out yourcertname.pfx

Once the PFX has been created you now need to import it into your Keyvault. Go back to the Powershell ISE and pick up where you left off

#Now import that certificate into your keyvault - change the path to where your pfx was created
az keyvault certificate import --file yourcertname.pfx -n $AZ_CertName --vault-name $AZ_KeyVault_Name

Now we are going to create a custom domain and map it to our CDN

#Map Azure CDN to your domain.
az cdn custom-domain create -g $AZ_RESOURCE_GROUP --endpoint-name $AZ_EndpointName --profile-name $AZ_ProfileName -n $AZ_DomainName  --hostname $AZ_HostName

In order to enable HTTPS on your custom domain you need to Register Azure CDN as an app in your Azure Active Directory. See Here for more information

The Service Principal ID for Microsoft.AzureFrontDoor-Cdn is - 205478c0-bd83-4e1b-a9d6-db63a3e1e1c8.

Run the following command.

az ad sp create --id 205478c0-bd83-4e1b-a9d6-db63a3e1e1c8

Then need to get the object id of Microsoft.AzureFrontDoor-Cdn = 3a4b744e-41e7-4d4b-9084-cd40129ba9ee and create an access policy on the key vault to allow Azure CDN get the Certificate


#Create an access policy to allow the Azure CDN access your key vault
az keyvault set-policy --name $AZ_KeyVault_Name -g $AZ_RESOURCE_GROUP `
    --object-id 3a4b744e-41e7-4d4b-9084-cd40129ba9ee `
    --certificate-permissions get  `
    --secret-permissions get 

Once that policy has been created you can run the following command to enable HTTPS on your custom domain

#Then enable https with keyvault - check the fu required for name!
$AZ_HostName = $AZ_HostName -replace '\.','-'
az cdn custom-domain enable-https -g $AZ_RESOURCE_GROUP `
--endpoint-name $AZ_EndpointName `
--profile-name $AZ_ProfileName `
--name $AZ_HostName `
--user-cert-group-name $AZ_RESOURCE_GROUP `
--user-cert-secret-name $AZ_CertName `
--user-cert-vault-name $AZ_KeyVault_Name `
--user-cert-protocol-type sni `

That will take a couple of minutes to propagate but when done your site will be ready with HTTPS using your own certificate.