From adc9f0b18eb0c769075bdc2c98610993ed52a929 Mon Sep 17 00:00:00 2001 From: Baptiste Jonglez Date: Sat, 26 Mar 2016 17:54:31 +0100 Subject: [PATCH] NSD: first playbook, still rough around the edges (no TSIG support) --- README | 32 +++++++++++++++ handlers/main.yml | 7 ++++ tasks/main.yml | 65 ++++++++++++++++++++++++++++++ templates/config.j2 | 30 ++++++++++++++ templates/primary_zone_config.j2 | 9 +++++ templates/secondary_zone_config.j2 | 9 +++++ 6 files changed, 152 insertions(+) create mode 100644 README create mode 100644 handlers/main.yml create mode 100644 tasks/main.yml create mode 100644 templates/config.j2 create mode 100644 templates/primary_zone_config.j2 create mode 100644 templates/secondary_zone_config.j2 diff --git a/README b/README new file mode 100644 index 0000000..437b08a --- /dev/null +++ b/README @@ -0,0 +1,32 @@ +NSD role + +It is assumed that all machines host the exact same zones in the same way +(i.e. for each zone, they are either all masters, or all slaves). +This greatly simplifies configuration, and there is generally no need +to have masters and slaves for the same zone handled by Ansible, since +Ansible can just push the zone to all machines (so, they can all be masters). + +There are cases where having multiple masters whose zone is pushed by Ansible +is not desirable: + +- dynamic DNS records (which isn't supported by NSD anyway) +- DNSSEC (you could always generate DNSSEC signatures in ansible, but it's awkward) + + +You can put key-value pairs in group_vars, under the key "nsd_common_config", +they will be used for the NSD configuration on all hosts. +A few common configuration entries are in the playbook itself, because they are +needed to properly create relevant directories. + +Some machine-specific configuration is also possible, e.g. for the bind IP. +Put key-value pairs in host_vars, under the key "nsd_local_config". + +If you want to pass multiple values for a key (e.g. ip-address), just use +a list as value, it will automatically be expanded. + + +The playbook is currently only tested with Debian wheezy. + +When a master zone is updated, the slaves are notified. Obviously, the slaves +need to be configured to accept notification from at least one master and pull +zones accordingly. diff --git a/handlers/main.yml b/handlers/main.yml new file mode 100644 index 0000000..a8113f3 --- /dev/null +++ b/handlers/main.yml @@ -0,0 +1,7 @@ +--- + +- name: restart nsd3 + service: name=nsd3 state=restarted + +- name: rebuild nsd3 database + command: /usr/sbin/nsdc rebuild diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100644 index 0000000..cc758c6 --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,65 @@ +--- + +- name: Install nsd3 + apt: pkg=nsd3 state=present + +- name: Configure nsd3 + template: src=config.j2 dest={{ nsd_config_dir }}/nsd.conf owner=root group=root mode=0644 + notify: + - restart nsd3 + + +- name: Create zone configuration directory + file: path={{ zones_config_dir }} state=directory owner=root group=root mode=0755 + +- name: Create primary zone directory + file: path={{ primary_zones_dir }} state=directory owner=root group=root mode=0755 + +- name: Create secondary zone directory + file: path={{ secondary_zones_dir }} state=directory owner=nsd group=nsd mode=0755 + + +# Unfortunately, nsd doesn't allow to say "include all files in this directory". +# The following implements the inclusion logic: the main config file includes +# a secondary file, in which we add include statements for each zone. +- name: Wipe include file + copy: dest={{ zones_include_file }} content="# Generated automatically by Ansible, do not edit by hand.\n" + +- name: Configure primary nsd3 zones + template: src=primary_zone_config.j2 dest="{{ zones_config_dir }}/{{ item.zone_name }}.primary.conf" owner=root group=root mode=0644 + notify: + - restart nsd3 + with_items: "{{ nsd_primary_zones }}" + +- name: Add include lines for primary zones to the include file + lineinfile: + state: present + dest: "{{ zones_include_file }}" + regexp: "^include: {{ zones_config_dir }}/{{ item.zone_name }}.primary.conf" + line: "include: {{ zones_config_dir }}/{{ item.zone_name }}.primary.conf" + with_items: "{{ nsd_primary_zones }}" + notify: + - restart nsd3 + +- name: Copy primary nsd3 zones + copy: src="files/nsd/{{ item.zone_filename }}" dest="{{ primary_zones_dir }}/{{ item.zone_filename }}" owner=root group=root mode=0644 + with_items: "{{ nsd_primary_zones }}" + notify: + - rebuild nsd3 database + + +- name: Configure secondary nsd3 zones + template: src=secondary_zone_config.j2 dest="{{ zones_config_dir }}/{{ item.zone_name }}.secondary.conf" owner=root group=root mode=0644 + notify: + - restart nsd3 + with_items: "{{ nsd_secondary_zones }}" + +- name: Add include lines for secondary zones to the include file + lineinfile: + state: present + dest: "{{ zones_include_file }}" + regexp: "^include: {{ zones_config_dir }}/{{ item.zone_name }}.secondary.conf" + line: "include: {{ zones_config_dir }}/{{ item.zone_name }}.secondary.conf" + with_items: "{{ nsd_secondary_zones }}" + notify: + - restart nsd3 diff --git a/templates/config.j2 b/templates/config.j2 new file mode 100644 index 0000000..0717c95 --- /dev/null +++ b/templates/config.j2 @@ -0,0 +1,30 @@ +# NSD configuration, automatically generated by Ansible. +# Do not edit by hand! + +server: + # Common configuration +{% for key, value in nsd_common_config.iteritems() %} +{% if value is string or value is number %} + {{ key }}: "{{ value }}" +{% else %} +{% for subvalue in value %} + {{ key }}: "{{ subvalue }}" +{% endfor %} +{% endif %} +{% endfor %} + + # Local configuration +{% for key, value in nsd_local_config.iteritems() %} +{% if value is string or value is number %} + {{ key }}: "{{ value }}" +{% else %} +{% for subvalue in value %} + {{ key }}: "{{ subvalue }}" +{% endfor %} +{% endif %} +{% endfor %} + + +# Include zone definitions +include: "{{ zones_include_file }}" + diff --git a/templates/primary_zone_config.j2 b/templates/primary_zone_config.j2 new file mode 100644 index 0000000..acceab7 --- /dev/null +++ b/templates/primary_zone_config.j2 @@ -0,0 +1,9 @@ +# Primary zone definition for {{ item.zone_name }} +zone: + name: "{{ item.zone_name }}" + zonefile: "{{ primary_zones_dir }}/{{ item.zone_filename }}" +{% for slave in item.slaves %} + notify: {{ slave.ip }} NOKEY + provide-xfr: {{ slave.ip }} NOKEY +{% endfor %} + diff --git a/templates/secondary_zone_config.j2 b/templates/secondary_zone_config.j2 new file mode 100644 index 0000000..9544e97 --- /dev/null +++ b/templates/secondary_zone_config.j2 @@ -0,0 +1,9 @@ +# Secondary zone definition for {{ item.zone_name }} +zone: + name: "{{ item.zone_name }}" + zonefile: "{{ secondary_zones_dir }}/{{ item.zone_name }}" +{% for master in item.masters %} + allow-notify: {{ master.ip }} NOKEY + request-xfr: AXFR {{ master.ip }} NOKEY +{% endfor %} +