Forum Discussion

John_Heyer_1508's avatar
John_Heyer_1508
Icon for Cirrostratus rankCirrostratus
Dec 09, 2015

Accessing GTM / Bigip-DNS zones via CLI or API

We're using the BigIP-DNS (aka GTM) module to manage our internal DNS. The BigIP stores this in the BIND backend. As part of a migration, I need to move about 1000 entries from one zone to another.

 

Deleting the old ones is easy via GUI, but manually creating new ones in the GUI is quite cumbersome and prone to human error. Is there a CLI way to do this, or perhaps leverage the API?

 

I do understand the BIND backend is officially unsupported so am not optimistic such a method exists, but thought I'd ask. Worst case, I could manually edit the zone file and restart named, but am hoping there's a nice n' pretty way.

 

3 Replies

  • Are you moving them to a new zone or an existing zone? What you can do is to download the zone file of the existing zone, edit it, then import it into a new zone. If it is an existing zone, there is a process to freeze the zone in ZoneRunner and manually edit the zone file. Check out this SOL if that's the case, https://support.f5.com/kb/en-us/solutions/public/7000/000/sol7032.html.

     

    Also, since you are using ZoneRunner, are you also using DnsExpress for the actual resolution to the internet?

     

  • They're being migrated to existing zones, but re-creating those is not a problem. Basically we previously had 1,000+ hosts under mydomain.com; we're now breaking those off in to subdomain1.mydomain.com, subdomain1.mydomain.com, etc

     

    The whole freeze process is a bit of a pain and I think I'll just create a new BIND server and do all my editing there, then set the GTMS as slaves. Once all the changes are done I'll flip them back to masters.

     

    We do use DNS Express to respond to authoritative queries from the the Internet. For security reasons, BIND is disabled on any internet-facing listeners but we do use it internally (in other words, inside the firewall).

     

  • Well, yes, and no. 😉

    First of all, this is (probably) sort of kind of mostly officially not supported, so use at your own risk, don't blame me if you screw something up, etc.

     

    Notwithstanding the above, if you're still interested ...

    So, yes - at least for the version(s) I've been dealing with, BIG-IP GTM (now called BIG-IP DNS apparently), does in fact use BIND on the back-end.

    But as with most things f5, can't just blindly use/change (though generally read but don't touch is safe) on the back-end.

    However, we have some very useful, uh, "hints"(/documentation, ...):

    K7032: Freezing zone files to allow manual update to ZoneRunner-managed zone files

    But/if we dig deeper, we find not only that it's using BIND, but we can also determine what version, and that it has dynamic DNS enabled for the zones.

    Hints:

    ss(8)

    (also be aware that many customary linux commands may be functions in the shell - probably to help keep folks from shooting themselves in the foot - you've been warned; the shell built-in command type can be quite useful too)

    /bin/ps ps(1)

    named(8)

    named -v

    rndc(8)

    nsupdate(1)

    So, now the bits to (try to) keep from shooting oneself in the foot (or worse).

    First of all, if you make DNS changes to/via BIND, ZoneRunner generally has no clue you changed something, so that could break things ... potentially badly.

    But taken from K7032 above,

    and relevant BIND information/documentation (your version may vary) BIND 9.11 Administrator Reference Manual (ARM)

    we should be able to carefully and with correct procedures, make changes in DNS via BIND in a manner that's compatible with / doesn't conflict with ZoneRunner.

    So, taking the above, "we"(/I) have implemented a specific CLI interface ... in our case, purpose specific for automating submission of DNS changes for DNS verification by letsencrypt.org CA ("of course", if one did the code differently, it might be a more general interface to make DNS changes via CLI-->nsupdate(1)).

    Also, in our case, we're calling it via ssh using key and forced command. Relevant part in ~root/.ssh/authorized_keys we have:

    command="/usr/local/sbin/_acme-challenge_helper" 

    That then forces the command and sets SSH_ORIGINAL_COMMAND - I then use SSH_ORIGINAL_COMMAND and validate its fields, and then use that to set positional arguments and then use those (consequently, likewise, and with the other bits of logic I put in it, it can also be directly called from the f5 shell as a CLI command with arguments - if it is given arguments, it ignores SSH_ORIGINAL_COMMAND, otherwise it uses SSH_ORIGINAL_COMMAND). So, I won't show all those validation checks and argument and SSH_ORIGINAL_COMMAND processing and such here.

    But what I will show here, are the parts that do most of the "heavy lifting" - notably stopping ZoneRunner (again, see also K7032 and the other bits referenced further above),

    safely making (submitting) the DNS changes, going through steps to make and validate safe to restart ZoneRunner, and restarting ZoneRunner - and if errors occur along the way, handling things as reasonably appropriate as feasible - and keeping in mind this is to be callable non-interactively.

    So, most relevant bits (and not showing all the code! - most notably not shown is most all of the validation checks and argument and SSH_ORIGINAL_COMMAND processing):

     

    #!/bin/sh
     
    set -e
     
    my_prog=/usr/local/sbin/_acme-challenge_helper
    my_prog_basename="$(basename "$my_prog")"
     
    ########################################################################
    # LOTS of processing/validation of arguments, SSH_ORIGINAL_COMMAND,
    # etc. NOT shown
    ########################################################################
     
    # have to deal with ZoneRunner first
    cd /var/named/config/namedb/
    rc=0 # exit/return code - track for deferred non-zero exits
    bigstart stop zrd
    # if we've made it to here, we've stopped ZoneRunner,
    # we handle our logic such that we'll restart it, even if we hit other errors
     
    # submit our DNS change
    nsupdate -l -k /var/named/var/run/named/session.key << __EOT__ ||
    update $add_or_del _acme-challenge.$CERTBOT_DOMAIN. 300 IN TXT${CERTBOT_VALIDATION:+ $CERTBOT_VALIDATION}
    send
    __EOT__
    rc="$?" # track on error but don't set -e exit
     
    if rndc sync -clean "$domain"; then
        # only freeze if sync was successful
        if rndc freeze "$domain" in external; then
            named-checkzone "$domain" db.external."$domain". || rc=1
            rndc thaw "$domain" in external || {
                # Unfortunately in this particular (but unlikely) case, we
                # need to exit here, and manual invention will be needed to
                # correct!  Why?  Because we were able to successfully
                # freeze, but the thaw failed!  So it's not safe to take
                # further system actions, we need to bail with failure:
                cat <<- __EOT__ 2>&1
                    $my_prog_basename: THAW FAILED AFTER FREEZE!
                    MANUAL CORRECTION WILL BE NEEDED!
                    ON HOST $(/bin/hostname) PLEASE CORRECT / RERUN FAILED COMMAND:
                    # cd /var/named/config/namedb/ && rndc thaw $domain in external
                    $my_prog_basename: aborting!
                __EOT__
                exit 1
            }
        else
            rc=1 # track error but don't set -e exit
        fi
    else
        rc=1 # track error but don't set -e exit
    fi
     
    # restart ZoneRunner
    bigstart start zrd
     
    # exit non-zero on any deferrerd errors of interest, otherwise exit 0:
    exit "$rc"

    Some additional notes - this stops and starts ZoneRunner, so might not interact nicely with anyone/anything else using ZoneRunner at/through that time (but otherwise shouldn't hurt).

    DNS continues to be served the whole time - so that is not interrupted/disrupted.

    dynamic DNS updates are stopped (disabled) and restarted (reenabled),

    and for that and many other reasons, this should be regarded as "single threaded" (it would be prudent to add a locking mechanism, so same program couldn't be called while it was already being run).

    /usr is nominally mounted ro (there's the remount option to mount - remember to remount it ro when done with changes),

    some other filesystems are noexec, and /usr/local/sbin is conveniently on root's path (need root to stop and restart ZoneRunner anyway)

    no guarantees these locations (of program and changes to ~root/.ssh/authorized_keys) are covered in UCS or other backups (I've not checked that yet).

    Oh, and "of course" the code could be better commented too.

     

    Good luck! (and be careful!) Anyway, thought others might find the information useful.