From 0629a063bc105492d9756a73758a81bb83215025 Mon Sep 17 00:00:00 2001 From: "Dustin C. Hatch" Date: Tue, 20 Feb 2018 16:00:55 -0600 Subject: [PATCH] roles/named: Support managing zones The *named* role now supports generating configuration for authoritative DNS zones and DNSSEC keys. Zones are defined by populating the `named_zones` variable with a list of objects describing the zone. Zone properties can include: * `name`: The DNS domain name * `type`: The zone type, defaults to `master` * `allow_update`: A list of hosts/networks or DNSSEC key names (which must be specified as an object with a `key` property) * `update_policy`: A list of BIND update policy statements * `ttl`: The default (minimum) TTL for the zone * `origin`: The authoritative name server for the zone * `refresh`, `retry`, `expire`: Record cache timeout values * `default_records`: A list of default records, defined as objects with the following properties: * `name`: The RR name * `type`: The RR type (default: `A`) * `value`: The RR value Zone files will be created in `/var/named/dynamic`. Existing zone files will **not** be overwritten; management of zone records is done using `nsupdate` or similar. --- roles/named/defaults/main.yml | 5 +++++ roles/named/tasks/main.yml | 20 ++++++++++++++++++++ roles/named/templates/named.conf.j2 | 1 + roles/named/templates/named.zones.j2 | 26 ++++++++++++++++++++++++++ roles/named/templates/zone.j2 | 15 +++++++++++++++ 5 files changed, 67 insertions(+) create mode 100644 roles/named/templates/named.zones.j2 create mode 100644 roles/named/templates/zone.j2 diff --git a/roles/named/defaults/main.yml b/roles/named/defaults/main.yml index 05774f8..12bcd82 100644 --- a/roles/named/defaults/main.yml +++ b/roles/named/defaults/main.yml @@ -14,3 +14,8 @@ named_dnssec: true named_dnssec_validation: true named_global_include: [] named_options_include: '{{ named_default_options_include }}' +named_zones: [] +named_default_ttl: 3600 +named_default_refresh: 900 +named_default_retry: 600 +named_default_expire: 86400 diff --git a/roles/named/tasks/main.yml b/roles/named/tasks/main.yml index dfdb11d..f515541 100644 --- a/roles/named/tasks/main.yml +++ b/roles/named/tasks/main.yml @@ -13,6 +13,26 @@ tags: - install +- name: ensure zones are configured + template: + src: named.zones.j2 + dest: /etc/named.zones + mode: '0640' + owner: root + group: named + validate: named-checkconf %s + notify: reload named +- name: ensure zone files exist + template: + src: zone.j2 + dest: /var/named/dynamic/{{ item.zone }}.zone + mode: '0640' + owner: root + group: named + force: no + with_items: '{{ named_zones }}' + notify: reload named + - name: ensure named is configured template: src: named.conf.j2 diff --git a/roles/named/templates/named.conf.j2 b/roles/named/templates/named.conf.j2 index f7a9fc8..0e21e1f 100644 --- a/roles/named/templates/named.conf.j2 +++ b/roles/named/templates/named.conf.j2 @@ -65,6 +65,7 @@ zone "." IN { include "/etc/named.rfc1912.zones"; include "/etc/named.root.key"; +include "/etc/named.zones"; {% for path in named_global_include %} include "{{ path }}"; {% endfor %} diff --git a/roles/named/templates/named.zones.j2 b/roles/named/templates/named.zones.j2 new file mode 100644 index 0000000..5fe4755 --- /dev/null +++ b/roles/named/templates/named.zones.j2 @@ -0,0 +1,26 @@ +// Zone configuration for ISC BIND +{% for zone in named_zones %} + +zone "{{ zone.zone }}" { + type {{ zone.type|d('master') }}; + file "dynamic/{{ zone.zone }}.zone"; +{% if zone.allow_update|d %} + allow-update { +{% for auth in zone.allow_update %} +{% if auth.key is defined %} + key {{ auth.key }}; +{% else %} + {{ auth }}; +{% endif %} +{% endfor %} + }; +{% endif %} +{% if zone.update_policy|d %} + update-policy { +{% for auth in zone.update_policy %} + {{ auth }}; +{% endfor %} + }; +{% endif %} +}; +{% endfor %} diff --git a/roles/named/templates/zone.j2 b/roles/named/templates/zone.j2 new file mode 100644 index 0000000..0361cdd --- /dev/null +++ b/roles/named/templates/zone.j2 @@ -0,0 +1,15 @@ +$TTL {{ item.ttl|d(named_default_ttl) }} +@ IN SOA {{ item.origin|d(ansible_fqdn + '.') }} {{ item.contact|d('hostmaster.{}.'.format(item.zone)) }} ( + {{ ansible_date_time.year }}{{ ansible_date_time.month }}{{ ansible_date_time.day }}00 + {{ item.refresh|d(named_default_refresh) }} + {{ item.retry|d(named_default_retry) }} + {{ item.expire|d(named_default_expire) }} + {{ item.ttl|d(named_default_ttl) }} +) + + IN NS {{ item.origin|d(ansible_fqdn + '.') }} +{% if item.default_records is defined %} +{% for rr in item.default_records %} +{{ rr.name }} IN {{ rr.type|d('A') }} {{ rr.value }} +{% endfor %} +{% endif %}