Merge pull request #118 from crux-capacitor/master

Add support for multiple views serving the same zone but different record sets.
This commit is contained in:
Niels Abspoel 2018-11-16 23:09:22 +01:00 committed by GitHub
commit df046903ce
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 162 additions and 38 deletions

View file

@ -86,6 +86,13 @@ declared.
`bind:available_zones:<zone>:file` should point to an existing zone file
that will be **sourced** by the formula.
Using Views
-----------
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.
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.
External zone files
-------------------

View file

@ -204,8 +204,13 @@ bind_rndc_client_config:
{%- do views.update(salt['pillar.get']('bind:configured_views', {})) %}
{%- for view, view_data in views|dictsort %}
{%- set dash_view = '-' + view if view else '' %}
{% for zone, zone_data in view_data.get('configured_zones', {})|dictsort -%}
{%- for zone, zone_data in view_data.get('configured_zones', {})|dictsort -%}
{%- if 'file' in zone_data %}
{%- set file = zone_data.file %}
{%- set zone = file|replace(".txt", "") %}
{%- else %}
{%- set file = salt['pillar.get']("bind:available_zones:" + zone + ":file", false) %}
{%- endif %}
{%- 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', {})) %}

View file

@ -7,6 +7,22 @@
// organization
//include "/etc/bind/zones.rfc1918";
{% for name, data in salt['pillar.get']('bind:configured_acls', {})|dictsort %}
acl {{ name }} {
{%- for d in data %}
{{ d }};
{%- endfor %}
};
{%- endfor %}
{%- for name, data in salt['pillar.get']('bind:configured_masters', {})|dictsort %}
masters {{ name }} {
{%- for d in data %}
{{ d }};
{%- endfor %}
};
{%- endfor %}
{%- macro zone(key, args, file, masters) %}
zone "{{ key }}" {
type {{ args['type'] }};
@ -92,21 +108,24 @@ include "{{ map.default_zones_config }}";
{{ zone(key, args, file, masters) }}
{% endfor %}
{% for view, view_data in salt['pillar.get']('bind:configured_views', {})|dictsort %}
{%- for view, view_data in salt['pillar.get']('bind:configured_views', {})|dictsort %}
view {{ view }} {
{%- if view == 'default' %}
include "{{ map.default_zones_config }}";
{%- endif %}
match-clients {
match-clients {
{%- for acl in view_data.get('match_clients', {}) %}
{{ acl }};
{%- endfor %}
};
};
{% for key, args in view_data.get('configured_zones', {})|dictsort -%}
{%- for key, args in view_data.get('configured_zones', {})|dictsort -%}
{%- if 'file' in args %}
{%- set file = args.file %}
{%- else %}
{%- set file = salt['pillar.get']("bind:available_zones:" + key + ":file") %}
{%- endif %}
{%- set masters = salt['pillar.get']("bind:available_zones:" + key + ":masters") %}
{{ zone(key, args, file, masters) }}
{%- endfor %}
@ -163,20 +182,3 @@ statistics-channels {
{%- endfor %}
};
{%- endif %}
{%- for name, data in salt['pillar.get']('bind:configured_acls', {})|dictsort %}
acl {{ name }} {
{%- for d in data %}
{{ d }};
{%- endfor %}
};
{%- endfor %}
{%- for name, data in salt['pillar.get']('bind:configured_masters', {})|dictsort %}
masters {{ name }} {
{%- for d in data %}
{{ d }};
{%- endfor %}
};
{%- endfor %}

97
pillar-with-views.example Normal file
View file

@ -0,0 +1,97 @@
bind:
configured_acls: # We have an internal ACL restricted to our
internal: # private IP range.
- 10.0.0.0/8 # In this case, an ACL for external isn't needed
# as that view will be matched by 'any'.
# Notice that there is no 'configured_zones' at this indentation level.
# That is because when you are using views, the bind service forces all zones to be served via a view.
#
# Also note - any other zones defined in any other conf files will either need to be commented out, or
# also served via a view using a file include. If you have other zones being served outside of a view, bind will
# fail to start and give you an error message indicating this. You will likely find these externally-defined zones
# in /etc/named.conf and /etc/named.conf.local
configured_views:
external: # A view called 'external' to match anything except the 'internal' ACL.
match_clients:
- any # This will match anything, including the public internet.
configured_zones:
mydomain.com: # Notice that this value matches on both views.
type: master
file: external.mydomain.com.txt # Specify the file to be used, which must match the file
recursion: yes # name of the zone below under available_zones.
# This filename also must match the corresponding zone name
# without the .txt extension (and be sure to use .txt as the extension).
notify: False
dnssec: False
internal: # The 'internal' view that is restricted to the 'internal' ACL.
match_clients:
- internal # This will match only our ACL named 'internal'.
configured_zones:
mydomain.com: # Same as above - both views will serve the same zone.
type: master
file: internal.mydomain.com.txt # Different file - matches the internal zone below.
# Again, this filename must match the corresponding zone name
# without the .txt extension (and be sure to use .txt as the extension).
recursion: yes
notify: False
dnssec: False
available_zones:
external.mydomain.com: # Beginning of the 'external' zone definition.
file: external.mydomain.com.txt # The file in which to save this zone's record set - matches the file
# specified in the 'external' view.
soa: # Declare the SOA RRs for the zone
ns: ns1.external.mydomain.com # Required
contact: hostmaster@mydomain.com # Required
serial: auto # Alternatively, 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
A:
portal: 50.60.70.80
gateway: 50.60.70.81
directory: 50.60.70.82
ns1: 50.60.70.83
www: 50.60.70.84
NS:
'@':
- ns1
CNAME:
login: portal.mydomain.com.
dashboard: www.mydomain.com.
internal.mydomain.com: # Beginning of the 'internal' zone definition.
file: internal.mydomain.com.txt # The file in which to save this zone's record set - matches the file
# specified in the 'internal' view.
soa: # Declare the SOA RRs for the zone
ns: ns1.mydomain.com # Required
contact: hostmaster@mydomain.com # Required
serial: auto # Alternatively, 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
A:
portal: 10.0.0.10 # Here we serve all private IPs as opposed to the public IPs
gateway: 10.0.0.11 # in the external zone.
directory: 10.0.0.12
ns1: 10.0.0.13
www: 10.0.0.14
NS:
'@':
- ns1
CNAME:
login: portal.mydomain.com.
dashboard: www.mydomain.com.

View file

@ -231,7 +231,9 @@ bind:
notify: False # Don't notify any NS RRs of any changes to zone
also-notify: # Do notify these IP addresses (pointless as
- 1.1.1.1 # notify has been set to no)
- 2.2.2.2
- 2.2.2.2 # If using views, do not define configured_zones
# at this indentation level - define it using the sub-key
# of your view under configured_views.
sub.domain2.com: # Domain zone with DNSSEC
type: master # We're the master of this zone
@ -279,6 +281,15 @@ bind:
configured_zones: # Zones that our view is applicable to
my.zone: # We've defined a new zone in here
type: master
file: example.com.txt # Optional: specify the zone file to be used for this view,
# otherwise it will default to the file matching the name of the zone that you
# specify here (which must match a zone under 'available_zones'.
# The file name must match what you have entered for 'file' in the zone under
# 'available_zones'.
# This allows you to define multiple views that serve the same zone, but
# serve a different record set in each.
# If doing this, you need to configure the zones and their record sets
# underneath the 'available_zones' section.
notify: False
update_policy: # A given update policy
- "grant core_dhcp name dns_entry_allowed_to_update. ANY"
@ -286,7 +297,9 @@ bind:
configured_acls: # And now for some ACLs
my_net: # Our ACL's name
- 127.0.0.0/8 # And the applicable IP addresses
- 10.20.0.0/16
- 10.20.0.0/16 # If using views, you need to create an ACL per view to differentiate
# who accesses the view, and then specify the appropriate ACL name under
# the 'match_clients' sub-key of your view.
### Define zone records in pillar ###
bind: