Application Gateway mTLS with LetsEncrypt
Background
mTLS with the Application Gateway Frontend is a new preview feature. https://docs.microsoft.com/en-us/azure/application-gateway/mutual-authentication-overview
I had the opportunity to get a little more familiar with the configuration, and am simply sharing some scripts and the browser UX.
mTLS Certificate for Application Gateway
Application Gateway is a little picky in the fact it wants the certificate chain used for mTLS to be complete in a single file. LetsEncrypt certs don’t include the root CA, so I need to download and bundle it ready for AppGw.
If you don’t bundle them correctly, you’ll get a message like this
Error: Certificate contains 0 root CAs. TrustedClientCertificate must contain only one root CA.
Certificate script snippets
I’ve created the certificates in Ubuntu WSL using Certbot and OpenSSL.
Generate a certificate
domain='mtls.azdemo.co.uk'
sudo certbot certonly --manual --preferred-challenges dns -d $domain
Generate the pfx
sudo openssl pkcs12 -inkey /etc/letsencrypt/live/$domain/privkey.pem -in /etc/letsencrypt/live/$domain/cert.pem -export -out /etc/letsencrypt/live/$domain/pkcs12.pfx
Download the root CA
curl -O https://letsencrypt.org/certs/isrgrootx1.pem
Combine the public key with the LetsEncrypt root CA, ready for AppGw.
cat /etc/letsencrypt/live/$domain/cert.pem isrgrootx1.pem > AppGwMtlsBundle.pem
Application Gateway script snippets
Using PowerShell and the AZ CLI to create a new HTTPS listener on an existing Application Gateway.
$appgwname = 'myAppGw'
$appgwrg = 'myRg'
$certpassword = 'myPfxPassword'
$certfile='C:\Temp\mtlsazdemocouk\pkcs12.pfx'
$sslname='mtlsazdemo'
$domain='mtls.azdemo.co.uk'
$frontendPortName='PublicSSL'
az network application-gateway ssl-cert create --gateway-name $appgwname -n $sslname -g $appgwrg --cert-file $certfile --cert-password $certpassword
az network application-gateway frontend-port create -g $appgwrg --gateway-name $appgwname -n $frontendPortName --port 443
$frontendIp=az network application-gateway show -n $appgwname -g $appgwrg --query "frontendIpConfigurations[?privateIpAddress==null].{name:name}" -o tsv
az network application-gateway http-listener create -g $appgwrg --gateway-name $appgwname --frontend-port $frontendPortName -n $domain.Replace('.','') --frontend-ip $frontendIp --ssl-cert $sslname --host-name $domain
User Experience
Accessing the site with HTTPS frontend listener, but no mTLS SSL Profile associated.
Accessing the site after enabling mTLS SSL Profile.
Behaviour when a valid certificate is not provided