diff --git a/README.rst b/README.rst index a042460..6074579 100644 --- a/README.rst +++ b/README.rst @@ -93,6 +93,61 @@ To use an external tool to manage the file, simply declare the location of the zone file in `bind:configured_zones::file` and **don't** add any entry for the in `bind:available_zones` +DNSSEC +====== + +The `bind` formula currently support two ways to enable DNSSEC: + +* Using the `zonesigner` binary provided by `dnssec-tools` (legacy) ; +* Using internal features of `bind`. + +Here is sample pillar entries to use the latter. + +On the master server : + +.. code:: yaml + +bind: + lookup: + key_directory: '/etc/bind/keys' + config: + options: + dnssec-enable: 'yes' + dnssec-validation: 'yes' + configured_acls: + slave_server: + - 192.168.1.2 + configured_zones: + domain.tld: + file: "db.domain.tld" + type: master + notify: True + allow-transfer: + - localnets + - localhost + - slave_server + allow-update: 'none' + auto-dnssec: 'maintain' + +On the slave server : + +.. code:: yaml + +bind: + config: + options: + dnssec-enable: 'yes' + dnssec-validation: 'yes' + configured_zones: + domain.tld: + file: "db.domain.tld.signed" + type: slave + masters: + - master_server + configured_masters: + master_server: + - 192.168.1.1 + Notes ===== diff --git a/bind/config.sls b/bind/config.sls index 1e8be69..8a81478 100644 --- a/bind/config.sls +++ b/bind/config.sls @@ -1,5 +1,11 @@ {% from "bind/map.jinja" import map with context %} +{%- set key_directory = salt['pillar.get']('bind:lookup:key_directory', map.key_directory) %} +{%- set key_algorithm = salt['pillar.get']('bind:lookup:key_algorithm', map.key_algorithm) %} +{%- set key_algorithm_field = salt['pillar.get']('bind:lookup:key_algorithm_field', map.key_algorithm_field) %} +{%- set key_size = salt['pillar.get']('bind:lookup:key_size', map.key_size) %} +{%- set key_flags = {'zsk': 256, 'ksk': 257} %} + include: - bind @@ -17,6 +23,7 @@ bind_restart: - reload: False - watch: - file: {{ map.chroot_dir }}{{ map.log_dir }}/query.log + - file: bind_key_directory {{ map.chroot_dir }}{{ map.log_dir }}/query.log: file.managed: @@ -109,6 +116,8 @@ bind_options_config: - user: {{ salt['pillar.get']('bind:config:user', map.user) }} - group: {{ salt['pillar.get']('bind:config:group', map.group) }} - mode: {{ salt['pillar.get']('bind:config:mode', '644') }} + - context: + key_directory: {{ map.key_directory }} - require: - pkg: bind - watch_in: @@ -201,6 +210,15 @@ zones{{ dash_view }}-{{ zone }}{{ '.include' if serial_auto else ''}}: - require: - file: named_directory +{% if zone_data['dnssec'] is defined and zone_data['dnssec'] -%} +signed-{{ zone }}: + cmd.run: + - cwd: {{ map.named_directory }} + - name: zonesigner -zone {{ zone }} {{ file }} + - prereq: + - file: zones-{{ zone }} +{% endif %} + {% if serial_auto %} zones{{ dash_view }}-{{ zone }}: module.wait: @@ -237,7 +255,27 @@ signed{{ dash_view }}-{{ zone }}: - prereq: - file: zones{{ dash_view }}-{{ zone }} {% endif %} - {% endif %} + +{% if zone_data['auto-dnssec'] is defined -%} +zsk-{{ zone }}: + cmd.run: + - cwd: {{ key_directory }} + - name: dnssec-keygen -a {{ key_algorithm }} -b {{ key_size }} -n ZONE {{ zone }} + - runas: {{ map.user }} + - unless: "grep {{ key_flags.zsk }} {{ key_directory }}/K{{zone}}.+{{ key_algorithm_field }}+*.key" + - require: + - file: bind_key_directory + +ksk-{{ zone }}: + cmd.run: + - cwd: {{ key_directory }} + - name: dnssec-keygen -f KSK -a {{ key_algorithm }} -b {{ key_size }} -n ZONE {{ zone }} + - runas: {{ map.user }} + - unless: "grep {{ key_flags.ksk }} {{ key_directory }}/K{{zone}}.+{{ key_algorithm_field }}+*.key" + - require: + - file: bind_key_directory +{% endif %} + {% endfor %} {% endfor %} diff --git a/bind/files/debian/named.conf.options b/bind/files/debian/named.conf.options index e1987f5..860eeeb 100644 --- a/bind/files/debian/named.conf.options +++ b/bind/files/debian/named.conf.options @@ -1,3 +1,5 @@ +{%- set key_directory = salt['pillar.get']('bind:lookup:key_directory', key_directory) %} + options { directory "/var/cache/bind"; @@ -20,6 +22,10 @@ options { listen-on-v6 { {{ salt['pillar.get']('bind:config:ipv6_listen', 'any') }}; }; {%- endif -%} +{%- if key_directory %} + key-directory "{{ key_directory }}"; +{%- endif -%} + {#- Allow inclusion of arbitrary statements #} {%- for statement, value in salt['pillar.get']('bind:config:options', {}).items() -%} {%- if value is iterable and value is not string %} diff --git a/bind/files/named.conf.local.jinja b/bind/files/named.conf.local.jinja index 0189407..66cee69 100644 --- a/bind/files/named.conf.local.jinja +++ b/bind/files/named.conf.local.jinja @@ -25,6 +25,10 @@ zone "{{ key }}" { {% else -%} file "{{ map.named_directory }}/{{ file }}"; {%- endif %} + {% if args['auto-dnssec'] is defined -%} + auto-dnssec {{ args['auto-dnssec'] }}; + inline-signing yes; + {%- endif %} {%- if args['allow-update'] is defined %} allow-update { {{args['allow-update']}}; }; {%- endif %} diff --git a/bind/init.sls b/bind/init.sls index feb6609..dd55b6a 100644 --- a/bind/init.sls +++ b/bind/init.sls @@ -1,5 +1,7 @@ {% from "bind/map.jinja" import map with context %} +{%- set key_directory = salt['pillar.get']('bind:config:key_directory', map.key_directory) %} + bind: pkg.installed: - pkgs: {{ map.pkgs|json }} @@ -7,3 +9,9 @@ bind: - name: {{ map.service }} - enable: True - reload: True + +bind_key_directory: + file.directory: + - name: {{ key_directory }} + - require: + - pkg: bind diff --git a/bind/map.jinja b/bind/map.jinja index 237dbee..03dac36 100644 --- a/bind/map.jinja +++ b/bind/map.jinja @@ -19,6 +19,10 @@ 'user': 'bind', 'group': 'bind', 'mode': '644', + 'key_directory': '/etc/bind/keys', + 'key_algorithm': 'RSASHA256', + 'key_algorithm_field': '008', + 'key_size': '4096', 'options': { 'querylog': 'no' } @@ -38,13 +42,17 @@ 'user': 'named', 'group': 'named', 'mode': '640', + 'key_directory': '/etc/named.keys', + 'key_algorithm': 'RSASHA256', + 'key_algorithm_field': '008', + 'key_size': '4096', 'options': { 'listen-on': 'port 53 { 127.0.0.1; }', 'listen-on-v6': 'port 53 { ::1; }', 'allow-query': '{ localhost; }', 'recursion': 'yes', 'dnssec-enable': 'yes', - 'dnssec-validation': 'yes' + 'dnssec-validation': 'yes', } }, 'Arch': { @@ -60,7 +68,11 @@ 'log_mode': '640', 'user': 'root', 'group': 'named', - 'mode': '640' + 'mode': '640', + 'key_directory': '/etc/named.keys', + 'key_algorithm': 'RSASHA256', + 'key_algorithm_field': '008', + 'key_size': '4096', }, 'FreeBSD': { 'pkgs': ['bind911'], @@ -75,7 +87,11 @@ 'log_mode': '660', 'user': 'root', 'group': 'bind', - 'mode': '640' + 'mode': '640', + 'key_directory': '/usr/local/etc/namedb/keys', + 'key_algorithm': 'RSASHA256', + 'key_algorithm_field': '008', + 'key_size': '4096', }, 'Suse': { 'pkgs': ['bind'], @@ -92,7 +108,11 @@ 'user': 'root', 'group': 'named', 'mode': '640', - }, + 'key_directory': '/etc/named.keys', + 'key_algorithm': 'RSASHA256', + 'key_algorithm_field': '008', + 'key_size': '4096', + } }, merge=salt['grains.filter_by']({ }, grain='oscodename', merge=salt['grains.filter_by']({ 'Ubuntu': { diff --git a/pillar.example b/pillar.example index 7e47245..ce745b0 100644 --- a/pillar.example +++ b/pillar.example @@ -17,6 +17,12 @@ bind: ### General config options ### bind: + lookup: + key_directory: '/etc/bind/keys' # Key directory (needed to use auto-dnssec) + key_algorithm: RSASHA256 # Algorithm when using auto-dnssec + key_algorithm_field: 008 # See http://www.bind9.net/dns-sec-algorithm-numbers + key_size: 4096 # Key size + config: tmpl: salt://bind/files/debian/named.conf # Template we'd like to use (not implemented?) user: root # File & Directory user @@ -221,6 +227,19 @@ bind: - 1.1.1.1 # notify has been set to no) - 2.2.2.2 + sub.domain2.com: # Domain zone with DNSSEC + type: master # We're the master of this zone + notify: False # Don't notify any NS RRs of any changes to zone + dnssec: True # Create and manage signed zonefile with zonesigner + # You will have to install dnssec-tools by hand + # on many distributions + + sub.domain3.com: # Domain zone with DNSSEC + type: master # We're the master of this zone + notify: False # Don't notify any NS RRs of any changes to zone + auto-dnssec: 'maintain' # Bind will create and manage the signed zonefile + # itself, we only have to provide the clear zone + 1.168.192.in-addr.arpa: # Reverse lookup for local IPs type: master # As above notify: False # As above