In this article, I will show you how to configure Azure Application Gateway in front of Azure Blob Storage, so you can expose and secure access to a storage container with custom domains.
Azure Application Gateway manages the requests that client applications can send to a web app. Application Gateway routes traffic to a pool of web servers based on the URL of a request. This is known as application-layer routing. The pool of web servers can be Azure virtual machines, Azure virtual machine scale sets, Azure App Service, and even on-premises servers.
I have recently come across a use case where I need to publish my data in Azure blob storage with a custom domain to expose the content publicly. All worked as planned except for HTTPS secure access. Once you browse the custom domain, you receive the warning message that says “Your connection to this site is not secure“.
To address this issue, Microsoft noted clearly in their documentation here that if you need to enable HTTPS for custom domains on Azure storage, then you’ll have to use Azure Content Delivery Network (CDN) because Azure Storage does not yet natively support HTTPS.
What if you have a data sovereignty requirements and you don’t want to use Azure CDN?
The good news is, if you are already using Azure Application Gateway (Standard or WAF SKU), you can leverage it to enable HTTPS access to Azure blob storage with custom domains and without using Azure CDN.
To follow this article, you need to have the following:
- Azure subscription – If you don’t have an Azure subscription, you can create a free one here.
- Azure storage account – To create a general-purpose storage account, you can follow the instructions described here.
- You need one or more containers – You can follow the instructions here to create a container.
- Map a custom domain for accessing blob data in your Azure storage account – You can follow the instructions here to map a custom domain with the only HTTP enabled. To map a custom domain with HTTPS, please follow the steps described in this article instead of using the Azure CDN service.
- You need a static public IP address with Standard SKU – you can create a new public IP by running the following Azure CLI command: az network public-ip create -n pip-agw-v2 -g resourceGroupName –allocation-method Static –sku Standard
- You need a virtual network and dedicated subnet for the Application Gateway. For more information, please follow the instructions described here.
- Application Gateway v2 SKU up and running (Standard or WAF) – If you don’t have an Application Gateway, you can follow the step by step guide and create one here.
- You need a private (.pfx) certificate for your custom domain so you can upload it to the Application Gateway listener.
Below you can find the architecture diagram used for this solution:
Please note that if you are using Application Gateway V1 SKU, the VIP can change if you stop and start the application gateway. But the DNS name associated with the application gateway doesn’t change over the lifetime of the gateway. Because the DNS name doesn’t change, you should use a CNAME alias and point it to the DNS address of the application gateway. In Application Gateway V2 SKU, you can set the IP address as static, so IP and DNS name will not change over the lifetime of the application gateway.
So make sure you set and create a CNAME alias or A record to point the custom domain to the Application Gateway public IP.
Configure Storage account
First, you need to make sure that your storage account is configured correctly. When you deploy a storage account in Azure, by default secure transfer is Enabled and TLS Version is set to a minimum 1.2. So nothing to change here.
Next, you want to configure your storage account to allow access only from the virtual network and the subnet (e.g. AppGW-Subnet) where Application Gateway is deployed.
Within the same storage account, browse to Firewalls and virtual networks as shown in the figure below, choose selected networks, and add your existing virtual network. Additionally, it’s very important to add your public IP address or your on-premises networks under Firewall (Address range) so you would be able to manage and access the storage container in the Azure Portal.
This means that TLS is enforced with Application Gateway for public access, and then securely forward requests to storage account with encryption as well, so this is end-to-end TLS encryption. And by enabling firewall rules for the selected virtual networks, we take additional security measures to allow requests only from the application gateway subnet.
You can find more details about Azure Storage firewalls and virtual networks in the documentation here.
Configure Application Gateway
Assuming you have all the prerequisites in place, take now the following steps to configure the Application Gateway to access the storage container securely.
First, you need to add a new backend pool with the blob storage as a target. The target is the FQDN of the Azure storage blob service as shown in the figure below.
Next, you need to add a new listener using the ‘Frontend IP‘ as Public, listening on port 443 (HTTPS). Then you need to upload your custom domain (.pfx) private certificate.
Then you need to make sure to select the ‘Listener type‘ as Multisite and specify your custom domain since you will be hosting more than one site behind this Application Gateway.
Next, you need to add HTTP settings with the following details:
- Backend protocol: HTTPS
- Backend protocol: 443
- Trusted root certificate
- Use well known CA certificate: Yes – This option is only available for Application Gateway v2 SKU and not in the v1 SKU. This means that we trust the wildcard certificate issued by Microsoft to (*.blob.core.windows.net). This allows us to securely forward the requests from the Application Gateway to the blob storage over HTTPS (end-to-end encryption).
- Additional settings:
- Cookie-based affinity: Disable
- Connection draining: Disable
- Request time-out: 20 seconds
- Override backend path: /
- Override with new hostname: Yes
- Override with the specific domain name: Enter your storageaccountname.blob.core.windows.net
- Use a custom probe: No – We will select the health probe in the next step.
Custom Health probe
Next, you need to create a custom health probe with the following details:
- Protocol: HTTPS
- Pick hostname from backend HTTP settings: Yes
- Pick port from backend HTTP settings: Yes
- Path: /
- Use probe matching conditions: Yes
- HTTP response status code match: 400
- HTTP settings: Choose the HTTP settings (443) that you created in the previous step
This step is very important because custom probes allow you to have more granular control over health monitoring. When using custom probes, you can configure a custom Hostname, URL path, probe interval, and how many failed responses to accept before marking the back-end pool instance as unhealthy, etc.
In this case, since we are using Azure blob container as the backend which is not a static or dynamic website you will receive an unhealthy status. Thus, you need to specify the HTTP response status code match as 400. The status code 400 is expected here since accessing the blob storage without specifying the full URL, you will receive the error message ‘Value for one of the query parameters specified in the request URI is invalid‘ which translates to code 400.
The final step is to create a new routing rule which will send traffic from a given frontend public IP address to your backend targets (Azure blob storage account). A routing rule must contain a listener and at least one backend target.
Click add + Request routing rule with the following details:
- Rule name: Choose a descriptive name.
- Listener: Choose the listener that you created in the previous step.
Select Backend targets and choose the following settings:
- Target Type: Backend pool
- Backend target: Select the backed target that you create in the first step.
- HTTP settings: Select HTTP settings (port 443) that you created in the previous step.
Once you applied all the configuration noted above, as well as the creation of CNAME alias in DNS pointing to the public IP address of Application Gateway. Then go to Azure Portal, navigate to the resource group, application gateway, and check the Backend Health blade to ensure that your server (backend pool) which is the FQDN of your storage account is healthy as shown in the figure below.
Once the Application Gateway is configured and the backend pool is in a healthy state, you can browse your custom domain via HTTPS and access securely your storage container.
Now it works! You can enjoy your web page, requested from Azure blob storage account with a custom domain and SSL support.
That’s it there you have it!
In this guide, I showed you how to configure Azure Application Gateway in front of Azure Blob Storage, so you can expose and enable HTTPS access to Azure storage container with custom domains without using Azure Content Delivery Network (CDN).
Please note that the same steps described above will also apply to host your website in Azure Storage. For more information about static website, please check how to host a static website on Azure Blob Storage.
Azure Application Gateway provides an application delivery controller (ADC) as a service. It offers various layer 7 load-balancing capabilities for your applications. This service is highly available, scalable, and fully managed by Azure.
To learn more about Application Gateway, see What is Azure Application Gateway.
Thank you for reading my blog.
If you have any questions or feedback, please leave a comment.