Skip to content

Commit 7e47c76

Browse files
crux-capacitorevan.gramens
authored andcommitted
Squash commits
Update named.conf.local.jinja Some reorganization of the format. In the for-loop that handles configured_views: - Add if-block on lines 124-128 to allow specifying a file for your view, rather than defaulting to the name of the specified zone. This allows multiple views to serve the same zone, but use a different file. Update pillar.example Add documentation and an example on specifying the file to be used for a view, as well as documented that you should not define the top-level 'configured_zones' key when using views. Small comment update. Add comment about using ACLs and views. Create pillar-with-views.example An example of the bind pillar that defines multiple views for internal and external record sets. This doesn't include the other portion of the pillar the defines the bind config - this is zones, views and ACLs only. The config portion is not affected by this. Add more comment clarification. Add comment explaining file name requirements. The filename must match the corresponding zone name (without the .txt extension) because the config.sls jinja logic uses the filename to match to the zone when setting zone_records. It also is hardcoded to replace ".txt" with "" in order to make this match work, and so .txt extension is required for the logic to work. Update config.sls Add logic to detect a file specified in a view, and match it to a zone under available_zones to enable creating that zone file. Revert back Made a bad commit. Update with the required logic. Added an if-block to test for the file argument in the zone_data, and if found, use that view and update the zone variable to match the zone defined under available_zones. Fix variable set. Set zone based on file with the .txt extension removed. Update README.rst Add paragraph about using views. Update pillar-with-views.example Add some more comments for explanation.
1 parent 522b369 commit 7e47c76

File tree

5 files changed

+162
-38
lines changed

5 files changed

+162
-38
lines changed

README.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,13 @@ declared.
8686
`bind:available_zones:<zone>:file` should point to an existing zone file
8787
that will be **sourced** by the formula.
8888

89+
Using Views
90+
-----------
91+
92+
Using views introduces some restrictions by the BIND server in that once you have views defined, ALL of your zones have to be served via a view. You cannot have any zones defined outside of a view.
93+
94+
If you want multiple views to serve the same zone but with different record sets, follow the example in pillar-with-views.example to set this up. The key to this is the 'file' argument in the view configuration that allows you to set the view's configured_zone to a zone that you define underneath 'available_zones'. Without specifying this 'file' argument, your views cannot serve the same zone; they will instead serve a zone that matches the name of the view.
95+
8996
External zone files
9097
-------------------
9198

bind/config.sls

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -203,19 +203,24 @@ bind_rndc_client_config:
203203
{%- set views = {False: salt['pillar.get']('bind', {})} %}{# process non-view zones in the same loop #}
204204
{%- do views.update(salt['pillar.get']('bind:configured_views', {})) %}
205205
{%- for view, view_data in views|dictsort %}
206-
{%- set dash_view = '-' + view if view else '' %}
207-
{% for zone, zone_data in view_data.get('configured_zones', {})|dictsort -%}
208-
{%- set file = salt['pillar.get']("bind:available_zones:" + zone + ":file", false) %}
209-
{%- set zone_records = salt['pillar.get']('bind:available_zones:' + zone + ':records', {}) %}
210-
{%- if salt['pillar.get']('bind:available_zones:' + zone + ':generate_reverse') %}
211-
{%- 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', {})) %}
212-
{%- endif %}
206+
{%- set dash_view = '-' + view if view else '' %}
207+
{%- for zone, zone_data in view_data.get('configured_zones', {})|dictsort -%}
208+
{%- if 'file' in zone_data %}
209+
{%- set file = zone_data.file %}
210+
{%- set zone = file|replace(".txt", "") %}
211+
{%- else %}
212+
{%- set file = salt['pillar.get']("bind:available_zones:" + zone + ":file", false) %}
213+
{%- endif %}
214+
{%- set zone_records = salt['pillar.get']('bind:available_zones:' + zone + ':records', {}) %}
215+
{%- if salt['pillar.get']('bind:available_zones:' + zone + ':generate_reverse') %}
216+
{%- 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', {})) %}
217+
{%- endif %}
213218
{# If we define RRs in pillar, we use the internal template to generate the zone file
214219
otherwise, we fallback to the old behaviour and use the declared file
215220
#}
216-
{%- set zone_source = 'salt://bind/files/zone.jinja' if zone_records != {} else 'salt://' ~ map.zones_source_dir ~ '/' ~ file %}
217-
{%- set serial_auto = salt['pillar.get']('bind:available_zones:' + zone + ':soa:serial', '') == 'auto' %}
218-
{% if file and zone_data['type'] == 'master' -%}
221+
{%- set zone_source = 'salt://bind/files/zone.jinja' if zone_records != {} else 'salt://' ~ map.zones_source_dir ~ '/' ~ file %}
222+
{%- set serial_auto = salt['pillar.get']('bind:available_zones:' + zone + ':soa:serial', '') == 'auto' %}
223+
{% if file and zone_data['type'] == 'master' -%}
219224
zones{{ dash_view }}-{{ zone }}{{ '.include' if serial_auto else ''}}:
220225
file.managed:
221226
- name: {{ zones_directory }}/{{ file }}{{ '.include' if serial_auto else ''}}

bind/files/named.conf.local.jinja

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,22 @@
77
// organization
88
//include "/etc/bind/zones.rfc1918";
99

10+
{% for name, data in salt['pillar.get']('bind:configured_acls', {})|dictsort %}
11+
acl {{ name }} {
12+
{%- for d in data %}
13+
{{ d }};
14+
{%- endfor %}
15+
};
16+
{%- endfor %}
17+
18+
{%- for name, data in salt['pillar.get']('bind:configured_masters', {})|dictsort %}
19+
masters {{ name }} {
20+
{%- for d in data %}
21+
{{ d }};
22+
{%- endfor %}
23+
};
24+
{%- endfor %}
25+
1026
{%- macro zone(key, args, file, masters) %}
1127
zone "{{ key }}" {
1228
type {{ args['type'] }};
@@ -92,23 +108,26 @@ include "{{ map.default_zones_config }}";
92108
{{ zone(key, args, file, masters) }}
93109
{% endfor %}
94110

95-
{% for view, view_data in salt['pillar.get']('bind:configured_views', {})|dictsort %}
111+
{%- for view, view_data in salt['pillar.get']('bind:configured_views', {})|dictsort %}
96112

97113
view {{ view }} {
98114
{%- if view == 'default' %}
99115
include "{{ map.default_zones_config }}";
100116
{%- endif %}
101-
102-
match-clients {
117+
match-clients {
103118
{%- for acl in view_data.get('match_clients', {}) %}
104-
{{ acl }};
119+
{{ acl }};
105120
{%- endfor %}
106-
};
121+
};
107122

108-
{% for key, args in view_data.get('configured_zones', {})|dictsort -%}
109-
{%- set file = salt['pillar.get']("bind:available_zones:" + key + ":file") %}
123+
{%- for key, args in view_data.get('configured_zones', {})|dictsort -%}
124+
{%- if 'file' in args %}
125+
{%- set file = args.file %}
126+
{%- else %}
127+
{%- set file = salt['pillar.get']("bind:available_zones:" + key + ":file") %}
128+
{%- endif %}
110129
{%- set masters = salt['pillar.get']("bind:available_zones:" + key + ":masters") %}
111-
{{ zone(key, args, file, masters) }}
130+
{{ zone(key, args, file, masters) }}
112131
{%- endfor %}
113132
};
114133
{%- endfor %}
@@ -163,20 +182,3 @@ statistics-channels {
163182
{%- endfor %}
164183
};
165184
{%- endif %}
166-
167-
168-
{%- for name, data in salt['pillar.get']('bind:configured_acls', {})|dictsort %}
169-
acl {{ name }} {
170-
{%- for d in data %}
171-
{{ d }};
172-
{%- endfor %}
173-
};
174-
{%- endfor %}
175-
176-
{%- for name, data in salt['pillar.get']('bind:configured_masters', {})|dictsort %}
177-
masters {{ name }} {
178-
{%- for d in data %}
179-
{{ d }};
180-
{%- endfor %}
181-
};
182-
{%- endfor %}

pillar-with-views.example

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
bind:
2+
configured_acls: # We have an internal ACL restricted to our
3+
internal: # private IP range.
4+
- 10.0.0.0/8 # In this case, an ACL for external isn't needed
5+
# as that view will be matched by 'any'.
6+
7+
# Notice that there is no 'configured_zones' at this indentation level.
8+
# That is because when you are using views, the bind service forces all zones to be served via a view.
9+
#
10+
# Also note - any other zones defined in any other conf files will either need to be commented out, or
11+
# also served via a view using a file include. If you have other zones being served outside of a view, bind will
12+
# fail to start and give you an error message indicating this. You will likely find these externally-defined zones
13+
# in /etc/named.conf and /etc/named.conf.local
14+
15+
configured_views:
16+
external: # A view called 'external' to match anything except the 'internal' ACL.
17+
match_clients:
18+
- any # This will match anything, including the public internet.
19+
configured_zones:
20+
mydomain.com: # Notice that this value matches on both views.
21+
type: master
22+
file: external.mydomain.com.txt # Specify the file to be used, which must match the file
23+
recursion: yes # name of the zone below under available_zones.
24+
# This filename also must match the corresponding zone name
25+
# without the .txt extension (and be sure to use .txt as the extension).
26+
notify: False
27+
dnssec: False
28+
29+
internal: # The 'internal' view that is restricted to the 'internal' ACL.
30+
match_clients:
31+
- internal # This will match only our ACL named 'internal'.
32+
configured_zones:
33+
mydomain.com: # Same as above - both views will serve the same zone.
34+
type: master
35+
file: internal.mydomain.com.txt # Different file - matches the internal zone below.
36+
# Again, this filename must match the corresponding zone name
37+
# without the .txt extension (and be sure to use .txt as the extension).
38+
recursion: yes
39+
notify: False
40+
dnssec: False
41+
42+
available_zones:
43+
external.mydomain.com: # Beginning of the 'external' zone definition.
44+
file: external.mydomain.com.txt # The file in which to save this zone's record set - matches the file
45+
# specified in the 'external' view.
46+
47+
soa: # Declare the SOA RRs for the zone
48+
ns: ns1.external.mydomain.com # Required
49+
contact: [email protected] # Required
50+
serial: auto # Alternatively, autoupdate serial on each change
51+
class: IN # Optional. Default: IN
52+
refresh: 8600 # Optional. Default: 12h
53+
retry: 900 # Optional. Default: 15m
54+
expiry: 86000 # Optional. Default: 2w
55+
nxdomain: 500 # Optional. Default: 1m
56+
ttl: 8600 # Optional. Not set by default
57+
records: # Records for the zone, grouped by type
58+
A:
59+
portal: 50.60.70.80
60+
gateway: 50.60.70.81
61+
directory: 50.60.70.82
62+
ns1: 50.60.70.83
63+
www: 50.60.70.84
64+
NS:
65+
'@':
66+
- ns1
67+
CNAME:
68+
login: portal.mydomain.com.
69+
dashboard: www.mydomain.com.
70+
71+
internal.mydomain.com: # Beginning of the 'internal' zone definition.
72+
file: internal.mydomain.com.txt # The file in which to save this zone's record set - matches the file
73+
# specified in the 'internal' view.
74+
75+
soa: # Declare the SOA RRs for the zone
76+
ns: ns1.mydomain.com # Required
77+
contact: [email protected] # Required
78+
serial: auto # Alternatively, autoupdate serial on each change
79+
class: IN # Optional. Default: IN
80+
refresh: 8600 # Optional. Default: 12h
81+
retry: 900 # Optional. Default: 15m
82+
expiry: 86000 # Optional. Default: 2w
83+
nxdomain: 500 # Optional. Default: 1m
84+
ttl: 8600 # Optional. Not set by default
85+
records: # Records for the zone, grouped by type
86+
A:
87+
portal: 10.0.0.10 # Here we serve all private IPs as opposed to the public IPs
88+
gateway: 10.0.0.11 # in the external zone.
89+
directory: 10.0.0.12
90+
ns1: 10.0.0.13
91+
www: 10.0.0.14
92+
NS:
93+
'@':
94+
- ns1
95+
CNAME:
96+
login: portal.mydomain.com.
97+
dashboard: www.mydomain.com.

pillar.example

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,9 @@ bind:
231231
notify: False # Don't notify any NS RRs of any changes to zone
232232
also-notify: # Do notify these IP addresses (pointless as
233233
- 1.1.1.1 # notify has been set to no)
234-
- 2.2.2.2
234+
- 2.2.2.2 # If using views, do not define configured_zones
235+
# at this indentation level - define it using the sub-key
236+
# of your view under configured_views.
235237

236238
sub.domain2.com: # Domain zone with DNSSEC
237239
type: master # We're the master of this zone
@@ -279,14 +281,25 @@ bind:
279281
configured_zones: # Zones that our view is applicable to
280282
my.zone: # We've defined a new zone in here
281283
type: master
282-
notify: False
284+
file: example.com.txt # Optional: specify the zone file to be used for this view,
285+
# otherwise it will default to the file matching the name of the zone that you
286+
# specify here (which must match a zone under 'available_zones'.
287+
# The file name must match what you have entered for 'file' in the zone under
288+
# 'available_zones'.
289+
# This allows you to define multiple views that serve the same zone, but
290+
# serve a different record set in each.
291+
# If doing this, you need to configure the zones and their record sets
292+
# underneath the 'available_zones' section.
293+
notify: False
283294
update_policy: # A given update policy
284295
- "grant core_dhcp name dns_entry_allowed_to_update. ANY"
285296

286297
configured_acls: # And now for some ACLs
287298
my_net: # Our ACL's name
288299
- 127.0.0.0/8 # And the applicable IP addresses
289-
- 10.20.0.0/16
300+
- 10.20.0.0/16 # If using views, you need to create an ACL per view to differentiate
301+
# who accesses the view, and then specify the appropriate ACL name under
302+
# the 'match_clients' sub-key of your view.
290303

291304
### Define zone records in pillar ###
292305
bind:

0 commit comments

Comments
 (0)