Allow to generate zone files from pillar data

This commit is contained in:
Javier Bértoli 2017-07-12 08:38:07 -03:00
parent b3192a4d16
commit b7dc95ddbf
4 changed files with 95 additions and 7 deletions

View file

@ -24,9 +24,39 @@ Install the bind package and start the bind service.
---------------
Manage the bind configuration file.
Zone files are not generated by this state
rather than taken from `salt://zones`.
See `pillar.example` for how to overwrite
This state can generate some basic zone files if a `records` entry is found in the
`available_zones`' declaration for the zone (see `pillar.example` for how to write these)
Example Pillar
==============
.. code:: yaml
bind:
configured_zones:
example.com:
type: master
notify: False
available_zones:
example.com:
file: example.com.txt
soa:
ns: ns1.example.com # Required
contact: hostmaster.example.com # Required
serial: 2017041001 # Required
records: # Records for the zone, grouped by type
A:
mx1: # A RR with multiple values can
- 1.2.3.228 # be written as an array
- 1.2.3.229
cat: 2.3.4.188
rat: 1.2.3.231
live: 1.2.3.236
See *bind/pillar.example* for a more complete example.
On the other hand, if no `records` entry exists, the zone file is not generated by this state
rather than taken from `salt://zones`. See `pillar.example` for how to overwrite
this URL.
Example Pillar

View file

@ -134,12 +134,22 @@ bind_default_zones:
{% for zone, zone_data in salt['pillar.get']('bind:configured_zones', {}).items() -%}
{%- set file = salt['pillar.get']("bind:available_zones:" + zone + ":file", zone_data.get('file')) %}
{%- set zone_records = salt['pillar.get']('bind:available_zones:' + zone + ':records', {}) %}
{# If we define RRs in pillar, we use the internal template to generate the zone file
otherwise, we fallback to the old behaviour and use the declared file
#}
{%- set zone_source = 'salt://bind/files/zone.jinja' if zone_records != {} else 'salt://' ~ map.zones_source_dir ~ '/' ~ file %}
{% if file and zone_data['type'] == "master" -%}
zones-{{ zone }}:
file.managed:
- name: {{ map.named_directory }}/{{ file }}
- source: 'salt://{{ map.zones_source_dir }}/{{ file }}'
- source: {{ zone_source }}
- template: jinja
{% if zone_records != {} %}
- context:
soa: {{ salt['pillar.get']("bind:available_zones:" + zone + ":soa") }}
records: {{ zone_records }}
{% endif %}
- 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') }}
@ -163,12 +173,22 @@ signed-{{ zone }}:
{%- for view, view_data in salt['pillar.get']('bind:configured_views', {}).items() %}
{% for zone, zone_data in view_data.get('configured_zones', {}).items() -%}
{%- set file = salt['pillar.get']("bind:available_zones:" + zone + ":file", zone_data.get('file')) %}
{% if file and zone_data['type'] == "master" -%}
{%- set zone_records = salt['pillar.get']('bind:available_zones:' + zone + ':records', {}) %}
{# If we define RRs in pillar, we use the internal template to generate the zone file
otherwise, we fallback to the old behaviour and use the declared file
#}
{%- set zone_source = 'salt://bind/zone.jinja' if zone_records != {} else 'salt://' ~ map.zones_source_dir ~ '/' ~ file %}
{% if file and zone_data['type'] == 'master' -%}
zones-{{ view }}-{{ zone }}:
file.managed:
- name: {{ map.named_directory }}/{{ file }}
- source: 'salt://{{ map.zones_source_dir }}/{{ file }}'
- source: {{ zone_source }}
- template: jinja
{% if zone_records != {} %}
- context:
soa: {{ salt['pillar.get']("bind:available_zones:" + zone + ":soa") }}
records: {{ zone_records }}
{% endif %}
- 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') }}

View file

@ -13,7 +13,7 @@
'named_directory': '/var/cache/bind/zones',
'log_dir': '/var/log/bind9',
'log_mode': '644',
'user': 'root',
'user': 'bind',
'group': 'bind',
'mode': '644'
},

View file

@ -103,6 +103,44 @@ bind:
- 127.0.0.0/8 # And the applicable IP addresses
- 10.20.0.0/16
### Define zone records in pillar ###
bind:
available_zones:
example.com:
file: example.com.txt
soa: # Declare the SOA RRs for the zone
ns: ns1.example.com # Required
contact: hostmaster.example.com # Required
serial: 2017041001 # Required
class: IN # Optional. Default: IN
refresh: 8600 # Optional. Default: 12h
retry: 900 # Optional. Default: 15m
expiry: 86000 # Optional. Default: 2w
nxdomain: 500 # Optional. Default: 1m
ttl: 8600 # Optional. Not set by default
records: # Records for the zone, grouped by type
A:
mx1: # A RR with multiple values can
- 1.2.3.228 # be written as an array
- 1.2.3.229
cat: 2.3.4.188
rat: 1.2.3.231
live: 1.2.3.236
NS:
'@':
- rat
- cat
CNAME:
ftp: cat.example.com.
www: cat.example.com.
mail: mx1.example.com.
smtp: mx1.example.com.
TXT: # Complex records can be expressed as strings
'@':
- '"some_value"'
- '"v=spf1 mx a ip4:1.2.3.4 ~all"'
_dmarc: '"v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com; fo=1:d:s; adkim=r; aspf=r; pct=100; ri=86400"'
### Externally defined Zones ###
bind:
available_zones: