NSX ALB LetsEncrypt with DNS-01 challenge - BIND example

    In some of my previous posts, mentioned here LetsEncrypt script integration and Script parameter usage, I explained how useful it can be for NSX advanced load balancing solutions to utilise this kind of approach for free and automatic certificate manipulation, especially in environments with large number of web services inside. This approach utilises HTTP-01 based challenge with LetsEncrypt systems and L7 HTTP/S virtual services on NSX ALB side.

    Now, from some time ago there is enhancement in this area, developed by official Avi Networks devops page, in terms of using DNS-01 challenge also. I tried on-prem option using Bind DNS as server which works very well.

    Steps are pretty much similar to HTTP-01 option, which can be summarised as following:

    - Create L7 virtual service with publicly available FQDN - certificates resolved can be in both options RSA or ECDSA, as configured during creation;

      - Download required DNS-01 challenge script HERE

    - Useful help on rest of steps in terms of configuration around certificate management service used for certificates creation can be observed on official link HERE

    There are 2 functions inside script (add_dns_text_record(key_digest_64, txt_record_name, kwargs) and remove_dns_text_record(key_digest_64, txt_record_name, kwargs)) which needs to be created for this custom implementation - because I tested DNS system based on Bind something like this should be modified inside script:

- import of required libraries - uncomment boto3 as script example is based for AWS environment:

#import boto3

import dns.query

import dns.tsigkeyring

import dns.update

import dns.rdatatype

- change functions accordingly - useful dynamic DNS manipulation using python at DNSpython, for Bind DNS add/remove steps:

def add_dns_text_record(key_digest_64, txt_record_name, kwargs):

        # Add your custom code here to add dns txt record under your domain name with name

        # txt_record_name and value key_digest_64

        keyring = dns.tsigkeyring.from_text({

            'host-example.' : 'XXXXXXXXXXXXXXXXXXXXXX=='

        })

        update = dns.update.UpdateMessage('dyn.test.example', keyring=keyring)

        update.add('host', 300, 'a', sys.argv[1])

        response = dns.query.tcp(update, '<DNS-server-IP>')


    def remove_dns_text_record(key_digest_64, txt_record_name, kwargs):

        # Add your custom code here to remove dns txt record under your domain name with name

        # txt_record_name and value key_digest_64

        keyring = dns.tsigkeyring.from_text({

            'host-example.' : 'XXXXXXXXXXXXXXXXXXXXXX=='

        })

        update = dns.update.UpdateMessage('dyn.test.example', keyring=keyring)

        update.remove('host', 300, 'a', sys.argv[1])

        response = dns.query.tcp(update, '<DNS-server-IP>')

    Useful setup for this type of certificates is extremely important and valuable if someone wants to work with wildcard certs (ie *.example.org), because they can be generated using DNS-01 challenge. You should be cautious around rate limiting stuff on LetsEncrypt like before.    

    Like before, after successful certificate generation - you just need it to assign it to appropriate virtual service (created at beginning or existing one) and after that renewal process will be automated per default NSX ALB (Avi) policy on 30, 7 and 1 day before expiration.

Comments

Popular posts from this blog

VMware SD WAN - multiple locations - LAN IP address space overlapping with NAT

NSX-T Layer 2 bridging - scenarios & use cases