diff --git a/LICENSE b/LICENSE index 52ec1c1..d919c41 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ - Copyright (c) 2013 Salt Stack Formulas + Copyright (c) 2013-2015 Salt Stack Formulas Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -11,4 +11,3 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - diff --git a/README.rst b/README.rst index 322b3a6..c88ae43 100644 --- a/README.rst +++ b/README.rst @@ -31,9 +31,23 @@ Example Pillar .. code:: yaml bind: - config: - name: /etc/named.conf - source: salt://bind/files/named.conf - user: root - group: named - mode: 640 + configured_zones: + sub.domain.com: + type: master + notify: False + configured_views: + myview1: + match_clients: + - client1 + - client2 + configured_zones: + my.zone: + type: master + notify: False + +See *bind/pillar.example*. + +Notes +===== + +* When using views all zones must be configured in views! diff --git a/bind/config.sls b/bind/config.sls index 1dc68c1..740559e 100644 --- a/bind/config.sls +++ b/bind/config.sls @@ -3,6 +3,29 @@ include: - bind +{{ map.log_dir }}: + file.directory: + - user: root + - group: {{ salt['pillar.get']('bind:config:group', map.group) }} + - mode: 775 + - require: + - pkg: bind + +bind_restart: + service.running: + - name: {{ map.service }} + - reload: False + - watch: + - file: {{ map.log_dir }}/query.log + +{{ map.log_dir }}/query.log: + file.managed: + - user: bind + - group: {{ salt['pillar.get']('bind:config:group', map.group) }} + - mode: 644 + - require: + - file: {{ map.log_dir }} + named_directory: file.directory: - name: {{ map.named_directory }} @@ -13,70 +36,42 @@ named_directory: - require: - pkg: bind -{% if grains['os_family'] == 'RedHat' %} bind_config: - file: - - managed + file.managed: - name: {{ map.config }} - - source: 'salt://bind/files/redhat/named.conf' + - source: 'salt://{{ map.config_source_dir }}/named.conf' - template: jinja - 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', '640') }} + - mode: {{ salt['pillar.get']('bind:config:mode', map.mode) }} + - context: + map: {{ map }} - require: - pkg: bind - watch_in: - service: bind bind_local_config: - file: - - managed + file.managed: - name: {{ map.local_config }} - - source: 'salt://bind/files/redhat/named.conf.local' + - source: 'salt://{{ map.config_source_dir }}/named.conf.local' - template: jinja - 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: + map: {{ map }} - require: - pkg: bind + - file: {{ map.log_dir }}/query.log - watch_in: - - service: named -{% endif %} + - service: bind {% if grains['os_family'] == 'Debian' %} -bind_config: - file: - - managed - - name: {{ map.config }} - - source: 'salt://bind/files/debian/named.conf' - - template: jinja - - 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') }} - - require: - - pkg: bind - - watch_in: - - service: bind - bind_key_config: - file: - - managed + file.managed: - name: {{ map.key_config }} - - source: 'salt://bind/files/debian/named.conf.key' - - template: jinja - - 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') }} - - require: - - pkg: bind - - watch_in: - - service: bind - -bind_local_config: - file: - - managed - - name: {{ map.local_config }} - - source: 'salt://bind/files/debian/named.conf.local' + - source: 'salt://{{ map.config_source_dir }}/named.conf.key' - template: jinja - user: {{ salt['pillar.get']('bind:config:user', map.user) }} - group: {{ salt['pillar.get']('bind:config:group', map.group) }} @@ -87,10 +82,9 @@ bind_local_config: - service: bind bind_options_config: - file: - - managed + file.managed: - name: {{ map.options_config }} - - source: 'salt://bind/files/debian/named.conf.options' + - source: 'salt://{{ map.config_source_dir }}/named.conf.options' - template: jinja - user: {{ salt['pillar.get']('bind:config:user', map.user) }} - group: {{ salt['pillar.get']('bind:config:group', map.group) }} @@ -101,10 +95,9 @@ bind_options_config: - service: bind bind_default_zones: - file: - - managed + file.managed: - name: {{ map.default_zones_config }} - - source: 'salt://bind/files/debian/named.conf.default-zones' + - source: 'salt://{{ map.config_source_dir }}/named.conf.default-zones' - template: jinja - user: {{ salt['pillar.get']('bind:config:user', map.user) }} - group: {{ salt['pillar.get']('bind:config:group', map.group) }} @@ -114,30 +107,21 @@ bind_default_zones: - watch_in: - service: bind -/var/log/bind9: - file: - - directory - - user: root - - group: bind - - mode: 775 +/etc/logrotate.d/{{ map.service }}: + file.managed: + - source: salt://{{ map.config_source_dir }}/logrotate_bind - template: jinja - - -/etc/logrotate.d/bind9: - file: - - managed - - source: salt://bind/files/debian/logrotate_bind - user: root - group: root - + - context: + map: {{ map }} {% endif %} -{% for key,args in salt['pillar.get']('bind:configured_zones', {}).iteritems() -%} -{%- set file = salt['pillar.get']("available_zones:" + key + ":file") %} +{% for key, args in salt['pillar.get']('bind:configured_zones', {}).iteritems() -%} +{%- set file = salt['pillar.get']("bind:available_zones:" + key + ":file") %} {% if args['type'] == "master" -%} zones-{{ file }}: - file: - - managed + file.managed: - name: {{ map.named_directory }}/{{ file }} - source: 'salt://bind/zones/{{ file }}' - user: {{ salt['pillar.get']('bind:config:user', map.user) }} @@ -146,10 +130,10 @@ zones-{{ file }}: - watch_in: - service: bind - require: - - file: {{ map.named_directory }} + - file: named_directory {% if args['dnssec'] is defined and args['dnssec'] -%} -signed-{{file}}: +signed-{{ file }}: cmd.run: - cwd: {{ map.named_directory }} - name: zonesigner -zone {{ key }} {{ file }} @@ -159,3 +143,32 @@ signed-{{file}}: {% endif %} {% endfor %} + +{%- for view, view_data in salt['pillar.get']('bind:configured_views', {}).iteritems() %} +{% for key,args in view_data.get('configured_zones', {}).iteritems() -%} +{%- set file = salt['pillar.get']("bind:available_zones:" + key + ":file") %} +{% if args['type'] == "master" -%} +zones-{{ file }}: + file.managed: + - name: {{ map.named_directory }}/{{ file }} + - source: 'salt://bind/zones/{{ file }}' + - 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') }} + - watch_in: + - service: bind + - require: + - file: named_directory + +{% if args['dnssec'] is defined and args['dnssec'] -%} +signed-{{ file }}: + cmd.run: + - cwd: {{ map.named_directory }} + - name: zonesigner -zone {{ key }} {{ file }} + - prereq: + - file: zones-{{ file }} +{% endif %} + +{% endif %} +{% endfor %} +{% endfor %} diff --git a/bind/files/debian/logrotate_bind b/bind/files/debian/logrotate_bind index 9677a5a..cbc1417 100644 --- a/bind/files/debian/logrotate_bind +++ b/bind/files/debian/logrotate_bind @@ -1,4 +1,4 @@ -/var/log/bind9/query.log { +{{ map.log_dir }}/query.log { rotate 7 daily missingok @@ -7,5 +7,7 @@ copytruncate compress create 0664 bind root + {% if not salt['pkg.version']('logrotate').startswith('3.7')-%} su + {% endif %} } diff --git a/bind/files/debian/named.conf b/bind/files/debian/named.conf index 80f3eb5..aa8432a 100644 --- a/bind/files/debian/named.conf +++ b/bind/files/debian/named.conf @@ -6,7 +6,8 @@ // // If you are just adding zones, please do that in /etc/bind/named.conf.local -include "/etc/bind/named.conf.key"; -include "/etc/bind/named.conf.options"; -include "/etc/bind/named.conf.local"; -include "/etc/bind/named.conf.default-zones"; +include "{{ map.options_config }}"; +include "{{ map.local_config }}"; +{%- if salt['pillar.get']('bind:keys', {}) is defined %} +include "{{ map.key_config }}"; +{% endif %} diff --git a/bind/files/debian/named.conf.local b/bind/files/debian/named.conf.local index 322a56b..bdc3cee 100644 --- a/bind/files/debian/named.conf.local +++ b/bind/files/debian/named.conf.local @@ -7,15 +7,29 @@ // organization //include "/etc/bind/zones.rfc1918"; -{% for key,args in salt['pillar.get']('bind:configured_zones', {}).iteritems() -%} -{%- set file = salt['pillar.get']("available_zones:" + key + ":file") %} -{%- set masters = salt['pillar.get']("available_zones:" + key + ":masters") %} +{%- macro zone(key, args, file, masters) %} zone "{{ key }}" { type {{ args['type'] }}; + {% if args['dnssec'] is defined and args['dnssec'] -%} + file "zones/{{ file }}.signed"; + {% else -%} file "zones/{{ file }}"; - {% if args['allow-update'] is defined -%} + {%- endif %} + {% if args['allow-update'] is defined -%} allow-update { {{args['allow-update']}}; }; {%- endif %} + {%- if args.update_policy is defined %} + update-policy { + {%- for policy in args.update_policy %} + {{ policy }}; + {%- endfor %} + }; + {%- endif %} + allow-transfer { + {% for remote in args.get('allow-transfer', {}) %} + {{ remote }}; + {% endfor %} + }; {% if args['type'] == "master" -%} {% if args['notify'] -%} notify yes; @@ -27,9 +41,43 @@ zone "{{ key }}" { masters { {{ masters }} }; {%- endif %} }; +{%- endmacro %} + +{%- if salt['pillar.get']('bind:configured_views', {}) is not defined %} +include "{{ map.default_zones_config }}"; +{%- endif %} + +{% for key, args in salt['pillar.get']('bind:configured_zones', {}).iteritems() -%} +{%- set file = salt['pillar.get']("bind:available_zones:" + key + ":file") %} +{%- set masters = salt['pillar.get']("bind:available_zones:" + key + ":masters") %} +{{ zone(key, args, file, masters) }} {% endfor %} +{% for view, view_data in salt['pillar.get']('bind:configured_views', {}).iteritems() %} + +view {{ view }} { +{%- if view == 'default' %} + include "{{ map.default_zones_config }}"; +{%- endif %} + +match-clients { +{%- for acl in view_data.get('match_clients', {}) %} + {{ acl }}; +{%- endfor %} +}; + +{% for key, args in view_data.get('configured_zones', {}).iteritems() -%} +{%- set file = salt['pillar.get']("bind:available_zones:" + key + ":file") %} +{%- set masters = salt['pillar.get']("bind:available_zones:" + key + ":masters") %} + {{ zone(key, args, file, masters) }} +{%- endfor %} +}; +{%- endfor %} + logging { - channel "querylog" { file "/var/log/bind9/query.log"; print-time yes; }; + channel "querylog" { + file "{{ map.log_dir }}/query.log"; + print-time yes; + }; category queries { querylog; }; }; diff --git a/bind/files/debian/named.conf.options b/bind/files/debian/named.conf.options index 7661808..39c7c56 100644 --- a/bind/files/debian/named.conf.options +++ b/bind/files/debian/named.conf.options @@ -15,7 +15,21 @@ options { // }; auth-nxdomain no; # conform to RFC1035 - {% if salt['pillar.get']('bind:config:ipv6', 'False') %} + +{%- if salt['pillar.get']('bind:config:ipv6', False) %} listen-on-v6 { {{ salt['pillar.get']('bind:config:ipv6_listen', 'any') }}; }; - {% endif %} +{%- endif -%} + +{#- Allow inclusion of arbitrary statements #} +{%- for statement, value in salt['pillar.get']('bind:config:options', {}).iteritems() -%} + {%- if value is iterable and value is not string %} + {{ statement }} { + {%- for item in value %} + {{ item }}; + {%- endfor %} + }; + {%- else %} + {{ statement }} {{ value }}; + {%- endif %} +{%- endfor %} }; diff --git a/bind/files/redhat/named.conf b/bind/files/redhat/named.conf index 710c37a..946f91f 100644 --- a/bind/files/redhat/named.conf +++ b/bind/files/redhat/named.conf @@ -41,5 +41,5 @@ zone "." IN { }; include "/etc/named.rfc1912.zones"; -include "/etc/named.conf.local"; +include "{{ map.local_config }}"; include "/etc/named.root.key"; diff --git a/bind/files/redhat/named.conf.local b/bind/files/redhat/named.conf.local index 569e6d9..03a053d 100644 --- a/bind/files/redhat/named.conf.local +++ b/bind/files/redhat/named.conf.local @@ -7,8 +7,8 @@ //include "/etc/bind/zones.rfc1918"; {% for key,args in salt['pillar.get']('bind:configured_zones', {}).iteritems() -%} -{%- set file = salt['pillar.get']("available_zones:" + key + ":file") %} -{%- set masters = salt['pillar.get']("available_zones:" + key + ":masters") %} +{%- set file = salt['pillar.get']("bind:available_zones:" + key + ":file") %} +{%- set masters = salt['pillar.get']("bind:available_zones:" + key + ":masters") %} zone "{{ key }}" { type {{ args['type'] }}; file "data/{{ file }}"; diff --git a/bind/init.sls b/bind/init.sls index c24af2b..feb6609 100644 --- a/bind/init.sls +++ b/bind/init.sls @@ -1,11 +1,9 @@ {% from "bind/map.jinja" import map with context %} bind: - pkg: - - installed + pkg.installed: - pkgs: {{ map.pkgs|json }} - service: - - running + service.running: - name: {{ map.service }} - enable: True - reload: True diff --git a/bind/map.jinja b/bind/map.jinja index 1be4d25..b26c44e 100644 --- a/bind/map.jinja +++ b/bind/map.jinja @@ -1,23 +1,33 @@ {% set map = salt['grains.filter_by']({ 'Debian': { - 'pkgs': ['bind9', 'bind9utils'], + 'pkgs': ['bind9', 'bind9utils', 'dnssec-tools'], 'service': 'bind9', + 'config_source_dir': 'bind/files/debian', 'config': '/etc/bind/named.conf', 'local_config': '/etc/bind/named.conf.local', 'key_config': '/etc/bind/named.conf.key', 'options_config': '/etc/bind/named.conf.options', 'default_zones_config': '/etc/bind/named.conf.default-zones', 'named_directory': '/var/cache/bind/zones', + 'log_dir': '/var/log/bind9', 'user': 'root', - 'group': 'bind' + 'group': 'bind', + 'mode': '644' }, 'RedHat': { 'pkgs': ['bind'], 'service': 'named', + 'config_source_dir': 'bind/files/redhat', 'config': '/etc/named.conf', 'local_config': '/etc/named.conf.local', 'named_directory': '/var/named/data', + 'log_dir': '/var/log/named', 'user': 'root', - 'group': 'named' + 'group': 'named', + 'mode': '640' }, -}, merge=salt['pillar.get']('bind:lookup')) %} +}, merge=salt['grains.filter_by']({ + 'Ubuntu': { + 'log_dir': '/var/log/named' + }, +}, grain='os', merge=salt['pillar.get']('bind:lookup'))) %} diff --git a/pillar.example b/pillar.example index cbda55f..0e7e7b6 100644 --- a/pillar.example +++ b/pillar.example @@ -11,6 +11,8 @@ bind: user: root group: named mode: 640 + options: + allow-recursion: '{ any; };' # Never include this on a public resolver bind: keys: @@ -23,12 +25,27 @@ bind: 1.168.192.in-addr.arpa: type: master notify: False + allow-transfer: + - 1.1.1.1 + - 2.2.2.2 dynamic.domain.com: type: master allow-update: "key core_dhcp" notify: True + configured_views: + myview1: + match_clients: + - client1 + - client2 + configured_zones: + my.zone: + type: master + notify: False + update_policy: + - "grant core_dhcp name dns_entry_allowed_to_update. ANY" -available_zones: - sub.domain.org: - file: db.sub.domain.org - masters: "192.168.0.1;" +bind: + available_zones: + sub.domain.org: + file: db.sub.domain.org + masters: "192.168.0.1;"