From a6a98a8b4bbff017baec81c3728cf11305fc9be7 Mon Sep 17 00:00:00 2001 From: David Galloway Date: Thu, 8 Dec 2016 16:10:14 -0500 Subject: [PATCH] nameserver: Support dynamic DNS in named config Signed-off-by: David Galloway --- roles/nameserver/README.rst | 56 +++++++++++++++++++++++- roles/nameserver/defaults/main.yml | 2 + roles/nameserver/tasks/config.yml | 1 - roles/nameserver/tasks/main.yml | 6 +++ roles/nameserver/templates/named.conf.j2 | 17 +++++++ 5 files changed, 80 insertions(+), 2 deletions(-) diff --git a/roles/nameserver/README.rst b/roles/nameserver/README.rst index 3c403eac..63f1b539 100644 --- a/roles/nameserver/README.rst +++ b/roles/nameserver/README.rst @@ -71,6 +71,9 @@ Most variables are defined in ``roles/nameserver/defaults/main.yml`` and values | | | | |**NOTE:** Setting to "yes" will add ``allow-recursion { any; }``. See To-Do. | +--------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ +|``ddns_keys: {}`` |A dictionary defining each Dynamic DNS zone's authorized key. See **Dynamic DNS** below. Defined in an encrypted file in | +| |the secrets repo | ++--------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+ **named_domains: []** @@ -129,6 +132,7 @@ The ``named_domains`` dictionary is the bread and butter of creating zone files. ddns.example.com: ipvar: NULL dynamic: true + forward: ddns.example.com Inventory +++++++++ @@ -146,6 +150,54 @@ Using the ``named_domains`` example above and inventory below, forward *and reve **Note:** Hosts in inventory with no IP address defined will not have records created and should be added to ``miscrecords`` in ``named_domains``. +Dynamic DNS ++++++++++++ +If you wish to use the Dynamic DNS feature of this role, you should generate an HMAC-MD5 keypair using dnssec-keygen_ for each zone you want to be able to dynamically update. The key generated should be pasted in the ``secret`` value of the ``ddns_keys`` dictionary for the corresponding domain. + +**Example**:: + + $ dnssec-keygen -a HMAC-MD5 -b 512 -n USER ddns.example.com + Kddns.example.com.+157+57501 + $ cat Kddns.example.com.+157+57501.key + ddns.example.com. IN KEY 0 3 157 LxFSAiBgKYtsTTV/hjaK7LNdsbk19xQv0ZY9xLtrpdIWhf2S4gurD5GJ JjP9N8bnlCPKc7zVy+JcBYbSMSsm2A== + + # In {{ secrets_path }}/nameserver.yml + --- + ddns_keys: + ddns.example.com: + secret: "LxFSAiBgKYtsTTV/hjaK7LNdsbk19xQv0ZY9xLtrpdIWhf2S4gurD5GJ JjP9N8bnlCPKc7zVy+JcBYbSMSsm2A==" + +``roles/nameserver/templates/named.conf.j2`` loops through each domain in ``named_domains``, checks whether ``dynamic: true`` and if so, then loops through ``ddns_keys`` and matches the secret key to the domain. + +These instructions assume you'll either have one host updating DNS records or you'll be sharing the resulting key. Clients can use nsupdate_ to update the nameserver. Configuring that is outside the scope of this role. + +You can have two types of Dynamic DNS zones: + + 1. A pure dynamic DNS zone with no static A records + 2. A mixed zone consisting of both dynamic and static records + +For a mixed zone, you must specify ``ddns_hostname_prefixes`` under the domain in ``named_domains`` else your dynamic records will be overwritten each time the records task is run. **Example**:: + + named_domains: + private.example.com: + forward: private.example.com + ipvar: ip + dynamic: true + ddns_hostname_prefixes: + - foo + ddns.example.com: + forward: ddns.example.com + ipvar: NULL + dynamic: true + +In the example above, a dynamic hostname of ``foo001.private.example.com`` will be saved and restored at the end of the records task. If you *dynamically* added a hostname of ``bar001.private.example.com`` however, the records task will remove it. Do not create static hostnames in your ansible inventory using any of the prefixes in ``ddns_hostname_prefixes`` or you'll end up with duplicates in the zone file. + +The records task will not modify the ddns.example.com zone file. + +For our upstream test lab's purposes, this allows us to combine static and dynamic records in our ``front.sepia.ceph.com`` domain so teuthology_'s ``lab_domain`` variable can remain unchanged. + +**NOTE:** Reverse zone Dynamic DNS is not supported at this time. + Tags ++++ @@ -177,7 +229,9 @@ To-Do - Allow additional user-defined firewall rules - DNSSEC -- Dynamic DNS - Add support for specifying networks to allow recursion from .. _Sepia: https://ceph.github.io/sepia/ +.. _dnssec-keygen: https://ftp.isc.org/isc/bind9/cur/9.9/doc/arm/man.dnssec-keygen.html +.. _nsupdate: https://linux.die.net/man/8/nsupdate +.. _teuthology: http://docs.ceph.com/teuthology/docs/siteconfig.html?highlight=lab_domain diff --git a/roles/nameserver/defaults/main.yml b/roles/nameserver/defaults/main.yml index 64f797e7..c4dc0a5f 100644 --- a/roles/nameserver/defaults/main.yml +++ b/roles/nameserver/defaults/main.yml @@ -23,3 +23,5 @@ named_conf_soa_ttl: 3600 named_conf_soa_refresh: 3600 named_conf_soa_retry: 3600 named_conf_soa_expire: 604800 + +ddns_keys: {} diff --git a/roles/nameserver/tasks/config.yml b/roles/nameserver/tasks/config.yml index 8de15301..b3171fc8 100644 --- a/roles/nameserver/tasks/config.yml +++ b/roles/nameserver/tasks/config.yml @@ -10,7 +10,6 @@ dest: "{{ named_conf_file }}" validate: named-checkconf %s notify: restart named - with_dict: "{{ named_domains }}" - name: Apply named daemon options lineinfile: diff --git a/roles/nameserver/tasks/main.yml b/roles/nameserver/tasks/main.yml index 5a59d54b..87fbdb89 100644 --- a/roles/nameserver/tasks/main.yml +++ b/roles/nameserver/tasks/main.yml @@ -1,4 +1,10 @@ --- +- name: Include secrets + include_vars: "{{ secrets_path | mandatory }}/nameserver.yml" + no_log: true + tags: + - always + # Install and update system packages - include: packages.yml tags: diff --git a/roles/nameserver/templates/named.conf.j2 b/roles/nameserver/templates/named.conf.j2 index cd7ac2d1..5b17d815 100644 --- a/roles/nameserver/templates/named.conf.j2 +++ b/roles/nameserver/templates/named.conf.j2 @@ -24,11 +24,28 @@ logging { }; }; +# Dynamic DNS +{% for key, zone in named_domains.iteritems() %} +{% if zone.dynamic == true %} +{% for domain, values in ddns_keys.iteritems() %} +{% if key == domain %} +key "{{ key }}" { + algorithm hmac-md5; + secret "{{ values.secret }}"; +}; +{% endif %} +{% endfor %} +{% endif %} +{% endfor %} + # Forward zones {% for key, zone in named_domains.iteritems() %} zone "{{ key }}" { type master; file "{{ named_conf_zones_path }}/{{ key }}"; +{% if zone.dynamic == true %} + allow-update { key "{{ key }}"; }; +{% endif %} }; {% endfor %} -- 2.47.3