From 7086b189b957e9177013f486fa236f5bc7c1daca Mon Sep 17 00:00:00 2001 From: lilly Date: Thu, 30 Apr 2026 22:53:07 +0200 Subject: [PATCH] enable auth-dns role to actually configure useful zones --- roles/auth-dns/defaults/main.yaml | 3 + roles/auth-dns/handlers/main.yaml | 13 +++- roles/auth-dns/meta/argument_specs.yaml | 61 +++++++++++++++++++ roles/auth-dns/tasks/01-install.yaml | 8 ++- roles/auth-dns/tasks/02-configure.yaml | 42 +++++++++++++ roles/auth-dns/templates/knot.conf.j2 | 55 +++++++++++++---- .../templates/netplan-disable-ra.yaml | 14 +++++ roles/auth-dns/templates/zone.j2 | 4 ++ 8 files changed, 184 insertions(+), 16 deletions(-) create mode 100644 roles/auth-dns/defaults/main.yaml create mode 100644 roles/auth-dns/meta/argument_specs.yaml create mode 100644 roles/auth-dns/templates/netplan-disable-ra.yaml create mode 100644 roles/auth-dns/templates/zone.j2 diff --git a/roles/auth-dns/defaults/main.yaml b/roles/auth-dns/defaults/main.yaml new file mode 100644 index 0000000..bfc8248 --- /dev/null +++ b/roles/auth-dns/defaults/main.yaml @@ -0,0 +1,3 @@ +--- +knot__remotes: [] + diff --git a/roles/auth-dns/handlers/main.yaml b/roles/auth-dns/handlers/main.yaml index 5ee0a5d..3bce8cb 100644 --- a/roles/auth-dns/handlers/main.yaml +++ b/roles/auth-dns/handlers/main.yaml @@ -1,8 +1,17 @@ -- tags: [ 02-auth-dns ] +- tags: [ auth-dns ] name: restart knot become: true - notify: restart knot ansible.builtin.systemd: name: knot.service state: restarted +- tags: [ auth-dns ] + name: reload knot zones + become: true + ansible.builtin.command: "knotc zone-reload" + +- tags: [ auth-dns ] + name: netplan apply + become: true + ansible.builtin.command: "netplan apply" + diff --git a/roles/auth-dns/meta/argument_specs.yaml b/roles/auth-dns/meta/argument_specs.yaml new file mode 100644 index 0000000..fcf9005 --- /dev/null +++ b/roles/auth-dns/meta/argument_specs.yaml @@ -0,0 +1,61 @@ +--- +argument_specs: + main: + options: + knot__dnssec_key_id: + description: The id of the TSIG key which knot will use for zone transfer signing + type: str + required: true + knot__dnssec_key_secret: + description: The secret value of the TSIG key which knot will use for zone transfer signing + type: str + required: true + knot__remotes: + description: + - A list of definitions for remote nameservers that are used for different purposes + - See https://www.knot-dns.cz/docs/latest/html/reference.html#remote-section for details + type: list + element: dict + required: false + options: + id: + type: str + required: true + address: + type: list + required: true + element: str + knot__catalog_zones: + description: A list of catalog zones that will be served by knot + type: list + element: dict + required: true + options: + domain: + type: str + required: true + notify_targets: + type: list + element: str + required: false + knot__zones: + description: A list of user zones that will be served by knot + type: list + element: dict + required: true + options: + domain: + type: str + required: true + notify_targets: + type: list + element: str + required: false + catalog_member: + type: str + required: false + content: + type: str + required: true + + diff --git a/roles/auth-dns/tasks/01-install.yaml b/roles/auth-dns/tasks/01-install.yaml index e3a66e3..521976a 100644 --- a/roles/auth-dns/tasks/01-install.yaml +++ b/roles/auth-dns/tasks/01-install.yaml @@ -2,5 +2,9 @@ name: Install knot become: true package: - name: [ knot, knot-exporter ] - + name: + - knot + - knot-exporter + - knot-dnssecutils + - knot-dnsutils + - knot-host diff --git a/roles/auth-dns/tasks/02-configure.yaml b/roles/auth-dns/tasks/02-configure.yaml index 6577a79..a2daa0f 100644 --- a/roles/auth-dns/tasks/02-configure.yaml +++ b/roles/auth-dns/tasks/02-configure.yaml @@ -1,3 +1,14 @@ +- tags: [ auth-dns ] + name: Ensure required directories exist + become: true + loop: [ "/etc/knot", "/etc/knot/zones" ] + ansible.builtin.file: + path: "{{ item }}" + state: directory + owner: knot + group: knot + mode: u=rwx,g=rx,o= + - tags: [ auth-dns ] name: Deploy knot configuration file become: true @@ -9,3 +20,34 @@ group: knot mode: u=rw,g=r,o= +- tags: [ auth-dns ] + name: Deploy configured zones + become: true + notify: reload knot zones + loop: "{{ knot__zones }}" + loop_control: + label: "{{ item.domain }}" + vars: + zone_content: "{{ item.content }}" + template: + src: zone.j2 + dest: "/etc/knot/zones/{{ item.domain }}zone" + owner: knot + group: knot + mode: u=rw,g=r + +# this seems weird but hear me out: +# if we don't disable SLAAC, the node automatically gets an address based on IPv6 Router-Advertisements +# this results in outgoing zone transfers failing because knot will prefer to use the dynamic address over the statically configured one. +# so because we are configuring a DNS Nameserver where known IP-Addresses are actually important for ACL reasons, SLAAC is disabled +- tags: [ auth-dns ] + name: Disable IPv6 SLAAC + become: true + notify: netplan apply + ansible.builtin.template: + src: "netplan-disable-ra.yaml" + dest: "/etc/netplan/10-disable-ra.yaml" + owner: root + group: root + mode: u=rw,g=,o= + diff --git a/roles/auth-dns/templates/knot.conf.j2 b/roles/auth-dns/templates/knot.conf.j2 index d0e5a5a..243c0b7 100644 --- a/roles/auth-dns/templates/knot.conf.j2 +++ b/roles/auth-dns/templates/knot.conf.j2 @@ -15,13 +15,21 @@ database: storage: "/var/lib/knot" key: - - id: auth-dns.hamburg.ccc.de + - id: {{ knot__dnssec_key_id }} algorithm: hmac-sha512 - secret: "" + secret: "{{ knot__dnssec_key_secret }}" remote: + # static, external and public remote used for DNSSEC KSK checking - id: quad9 address: "2620:fe::fe" + {% if knot__remotes -%} + # additional remotes used in the config + {% for i_remote in knot__remotes -%} + - id: "{{ i_remote.id }}" + address: [ {% for i_addr in i_remote.address %}"{{ i_addr}}"{% if not loop.last %},{% endif %} {% endfor %} ] + {% endfor %} + {% endif %} # define how the presence of parent KSK keys is checked # in this case, we just ask quad9 which is an open resolver @@ -31,7 +39,7 @@ submission: parent-delay: 1h # define how dnssec signing is done -# in this case we don't do anything special but teach knot how to check of KSK presence +# in this case we don't do anything special but teach knot how to check for KSK presence policy: - id: default ksk-submission: default @@ -40,25 +48,48 @@ policy: # define default settings that apply to all zones template: + # template for general-purpose user zones - id: default storage: "/etc/knot/zones" file: "%s.zone" semantic-checks: on zonefile-sync: -1 zonefile-load: difference-no-serial + serial-policy: dateserial journal-content: all - default-ttl: 60 - catalog-role: member - catalog-zone: hamburg.ccc.de.catalog. + default-ttl: 7200 dnssec-signing: on dnssec-policy: default - {# notify: ["ns1.hanse.de", "ns.bsd.network."] #} - - id: minimal - {# notify: ["ns1.hanse.de", "ns.bsd.network."] #} + {# catalog-role: member #} + {# catalog-zone: hamburg.ccc.de.catalog. #} + # template for automatically created special zones + - id: catalog + catalog-role: generate + dnssec-signing: on + dnssec-policy: default + + +# define zones on this server +# See https://www.knot-dns.cz/docs/3.4/html/reference.html#zone-section zone: - {# - domain: onsite.eurofurence.catalog. #} - {# template: minimal #} - {# catalog-role: generate #} + # catalog zones + {% for i_zone in knot__catalog_zones -%} + - domain: "{{ i_zone.domain }}" + template: catalog + notify: [ {% for i_notif in i_zone.notify_targets | default([]) %}"{{ i_notif }}"{% if not loop.last %}, {% endif %}{% endfor %} ] + {% endfor %} + + # normal zones + {% for i_zone in knot__zones -%} + - domain: "{{ i_zone.domain }}" + template: default + notify: [ {% for i_notif in i_zone.notify_targets | default([]) %}"{{ i_notif }}"{% if not loop.last %}, {% endif %}{% endfor %} ] + {% if i_zone.catalog_member | default(False) -%} + catalog-role: member + catalog-zone: "{{ i_zone.catalog_member }}" + {% endif %} + {% endfor %} + {# - domain: "onsite.eurofurence.org" #} diff --git a/roles/auth-dns/templates/netplan-disable-ra.yaml b/roles/auth-dns/templates/netplan-disable-ra.yaml new file mode 100644 index 0000000..505fba2 --- /dev/null +++ b/roles/auth-dns/templates/netplan-disable-ra.yaml @@ -0,0 +1,14 @@ +# {{ ansible_managed }} +network: + ethernets: + {%- for i_iface_name in ansible_interfaces -%} + {%- if i_iface_name != "lo" -%} + {%- set i_iface = ansible_facts[i_iface_name] %} + + {{ i_iface_name }}: + match: + macaddress: "{{ i_iface.macaddress }}" + accept-ra: false + {% endif %} + {% endfor %} + diff --git a/roles/auth-dns/templates/zone.j2 b/roles/auth-dns/templates/zone.j2 new file mode 100644 index 0000000..59edf5f --- /dev/null +++ b/roles/auth-dns/templates/zone.j2 @@ -0,0 +1,4 @@ +; {{ ansible_managed }} + +{{ zone_content }} +