Autogenerate reverse zones

This commit is contained in:
Vladimir Nadvornik 2018-06-05 15:46:48 +02:00
parent 6e8652dcb3
commit 4623fb5e60
3 changed files with 52 additions and 0 deletions

View file

@ -1,4 +1,5 @@
{% from "bind/map.jinja" import map with context %} {% from "bind/map.jinja" import map with context %}
{% from "bind/reverse_zone.jinja" import generate_reverse %}
include: include:
- bind - bind
@ -175,6 +176,9 @@ bind_rndc_client_config:
{% for zone, zone_data in view_data.get('configured_zones', {}).items() -%} {% for zone, zone_data in view_data.get('configured_zones', {}).items() -%}
{%- set file = salt['pillar.get']("bind:available_zones:" + zone + ":file", false) %} {%- set file = salt['pillar.get']("bind:available_zones:" + zone + ":file", false) %}
{%- set zone_records = salt['pillar.get']('bind:available_zones:' + zone + ':records', {}) %} {%- set zone_records = salt['pillar.get']('bind:available_zones:' + zone + ':records', {}) %}
{%- if salt['pillar.get']('bind:available_zones:' + zone + ':generate_reverse') %}
{%- do generate_reverse(zone_records, salt['pillar.get']('bind:available_zones:' + zone + ':generate_reverse:net'), salt['pillar.get']('bind:available_zones:' + zone + ':generate_reverse:for_zones'), salt['pillar.get']('bind:available_zones', {})) %}
{%- endif %}
{# If we define RRs in pillar, we use the internal template to generate the zone file {# 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 otherwise, we fallback to the old behaviour and use the declared file
#} #}

23
bind/reverse_zone.jinja Normal file
View file

@ -0,0 +1,23 @@
{%- macro generate_reverse(zone_records, net, for_zones, available_zones) %}
{%- set res = {} %}
{%- set net = salt['network.calc_net'](net) %}
{% set for_zones = [ for_zones ] if for_zones is string else for_zones %}
{%- for zone in for_zones %}
{%- set A_records = available_zones.get(zone, {}).get('records', {}).get('A', {}) %}
{%- for name, addr_list in A_records|dictsort %}
{%- set addr_list = [ addr_list ] if addr_list is string or addr_list is number else addr_list %}
{%- for addr in addr_list %}
{%- if salt['network.ip_in_subnet'](addr, net) %}
{%- if name.endswith('.') %}
{%- set full_name = name %}
{%- else %}
{%- set full_name = name + '.' + zone + '.' %}
{%- endif %}
{%- set rev_ip = '.'.join(addr.split('.')[::-1]) %}
{%- do res.update({rev_ip + '.in-addr.arpa.': full_name}) %}
{%- endif %}
{%- endfor %}
{%- endfor %}
{%- endfor %}
{%- do zone_records.update({'PTR': res }) %}
{%- endmacro %}

View file

@ -302,6 +302,31 @@ bind:
- '"v=spf1 mx a ip4:1.2.3.4 ~all"' - '"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"' _dmarc: '"v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com; fo=1:d:s; adkim=r; aspf=r; pct=100; ri=86400"'
3.2.1.in-addr.arpa: # auto-generated reverse zone
file: example.com.rev.txt
soa: # Declare the SOA RRs for the zone
ns: ns1.example.com # Required
contact: hostmaster.example.com # Required
serial: auto # autoupdate serial on each change
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
NS:
'@':
ns1.example.com.
generate_reverse: # take all A records from example.com that are in 1.2.3.0/24 subnet
net: 1.2.3.0/24 # and generate reverse records for them
for_zones:
- example.com # example.com is a zone defined in pillar, see above
### Externally defined Zones ### ### Externally defined Zones ###
bind: bind:
available_zones: available_zones: