Application Gateway mTLS with LetsEncrypt

Application Gateway mTLS with LetsEncrypt

2021, Sep 22    


mTLS with the Application Gateway Frontend is a new preview feature.

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

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

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'

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. TLS on the listener

Accessing the site after enabling mTLS SSL Profile. mTLS cert prompt

Behaviour when a valid certificate is not provided Access Denied 403