Skip to content

Commit aeeafc3

Browse files
Merge pull request #97 from nadvornik/reverse
Autogenerate reverse zones
2 parents e3bf427 + 4495972 commit aeeafc3

File tree

3 files changed

+55
-0
lines changed

3 files changed

+55
-0
lines changed

bind/config.sls

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{% from "bind/map.jinja" import map with context %}
2+
{% from "bind/reverse_zone.jinja" import generate_reverse %}
23
34
include:
45
- bind
@@ -175,6 +176,9 @@ bind_rndc_client_config:
175176
{% for zone, zone_data in view_data.get('configured_zones', {}).items() -%}
176177
{%- set file = salt['pillar.get']("bind:available_zones:" + zone + ":file", false) %}
177178
{%- set zone_records = salt['pillar.get']('bind:available_zones:' + zone + ':records', {}) %}
179+
{%- if salt['pillar.get']('bind:available_zones:' + zone + ':generate_reverse') %}
180+
{%- 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', {})) %}
181+
{%- endif %}
178182
{# If we define RRs in pillar, we use the internal template to generate the zone file
179183
otherwise, we fallback to the old behaviour and use the declared file
180184
#}

bind/reverse_zone.jinja

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{%- macro generate_reverse(zone_records, net, for_zones, available_zones) %}
2+
{%- set res = {} %}
3+
{%- set net = salt['network.calc_net'](net) %}
4+
{% set for_zones = [ for_zones ] if for_zones is string else for_zones %}
5+
{% set for_zones = available_zones.keys() if for_zones|length == 1 and for_zones[0] == 'any' else for_zones %}
6+
{%- for zone in for_zones %}
7+
{%- set A_records = available_zones.get(zone, {}).get('records', {}).get('A', {}) %}
8+
{%- for name, addr_list in A_records|dictsort %}
9+
{%- set addr_list = [ addr_list ] if addr_list is string or addr_list is number else addr_list %}
10+
{%- for addr in addr_list %}
11+
{%- if salt['network.ip_in_subnet'](addr, net) %}
12+
{%- if name.endswith('.') %}
13+
{%- set full_name = name %}
14+
{%- else %}
15+
{%- set full_name = name + '.' + zone + '.' %}
16+
{%- endif %}
17+
{%- set rev_ip = '.'.join(addr.split('.')[::-1]) %}
18+
{%- do res.update({rev_ip + '.in-addr.arpa.': full_name}) %}
19+
{%- endif %}
20+
{%- endfor %}
21+
{%- endfor %}
22+
{%- endfor %}
23+
{%- do zone_records.update({'PTR': res }) %}
24+
{%- endmacro %}

pillar.example

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,33 @@ bind:
308308
- '"v=spf1 mx a ip4:1.2.3.4 ~all"'
309309
_dmarc: '"v=DMARC1; p=quarantine; rua=mailto:[email protected]; fo=1:d:s; adkim=r; aspf=r; pct=100; ri=86400"'
310310

311+
312+
313+
314+
3.2.1.in-addr.arpa: # auto-generated reverse zone
315+
file: example.com.rev.txt
316+
soa: # Declare the SOA RRs for the zone
317+
ns: ns1.example.com # Required
318+
contact: hostmaster.example.com # Required
319+
serial: auto # autoupdate serial on each change
320+
class: IN # Optional. Default: IN
321+
refresh: 8600 # Optional. Default: 12h
322+
retry: 900 # Optional. Default: 15m
323+
expiry: 86000 # Optional. Default: 2w
324+
nxdomain: 500 # Optional. Default: 1m
325+
ttl: 8600 # Optional. Not set by default
326+
records: # Records for the zone, grouped by type
327+
NS:
328+
'@':
329+
ns1.example.com.
330+
generate_reverse: # take all A records from example.com that are in 1.2.3.0/24 subnet
331+
net: 1.2.3.0/24 # and generate reverse records for them
332+
for_zones:
333+
- example.com # example.com is a zone defined in pillar, see above
334+
335+
# for_zones:
336+
# - any # generate reverse record for any zone
337+
311338
### Externally defined Zones ###
312339
bind:
313340
available_zones:

0 commit comments

Comments
 (0)