mirror of
https://github.com/saltstack-formulas/bind-formula.git
synced 2025-04-16 09:40:22 +00:00
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:
commit
df046903ce
5 changed files with 162 additions and 38 deletions
|
@ -86,6 +86,13 @@ declared.
|
||||||
`bind:available_zones:<zone>:file` should point to an existing zone file
|
`bind:available_zones:<zone>:file` should point to an existing zone file
|
||||||
that will be **sourced** by the formula.
|
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
|
External zone files
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
|
|
@ -203,19 +203,24 @@ bind_rndc_client_config:
|
||||||
{%- set views = {False: salt['pillar.get']('bind', {})} %}{# process non-view zones in the same loop #}
|
{%- set views = {False: salt['pillar.get']('bind', {})} %}{# process non-view zones in the same loop #}
|
||||||
{%- do views.update(salt['pillar.get']('bind:configured_views', {})) %}
|
{%- do views.update(salt['pillar.get']('bind:configured_views', {})) %}
|
||||||
{%- for view, view_data in views|dictsort %}
|
{%- for view, view_data in views|dictsort %}
|
||||||
{%- set dash_view = '-' + view if view else '' %}
|
{%- 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 -%}
|
||||||
{%- set file = salt['pillar.get']("bind:available_zones:" + zone + ":file", false) %}
|
{%- if 'file' in zone_data %}
|
||||||
{%- set zone_records = salt['pillar.get']('bind:available_zones:' + zone + ':records', {}) %}
|
{%- set file = zone_data.file %}
|
||||||
{%- if salt['pillar.get']('bind:available_zones:' + zone + ':generate_reverse') %}
|
{%- set zone = file|replace(".txt", "") %}
|
||||||
{%- 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', {})) %}
|
{%- else %}
|
||||||
{%- endif %}
|
{%- 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', {})) %}
|
||||||
|
{%- 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
|
||||||
#}
|
#}
|
||||||
{%- set zone_source = 'salt://bind/files/zone.jinja' if zone_records != {} else 'salt://' ~ map.zones_source_dir ~ '/' ~ file %}
|
{%- set zone_source = 'salt://bind/files/zone.jinja' if zone_records != {} else 'salt://' ~ map.zones_source_dir ~ '/' ~ file %}
|
||||||
{%- set serial_auto = salt['pillar.get']('bind:available_zones:' + zone + ':soa:serial', '') == 'auto' %}
|
{%- set serial_auto = salt['pillar.get']('bind:available_zones:' + zone + ':soa:serial', '') == 'auto' %}
|
||||||
{% if file and zone_data['type'] == 'master' -%}
|
{% if file and zone_data['type'] == 'master' -%}
|
||||||
zones{{ dash_view }}-{{ zone }}{{ '.include' if serial_auto else ''}}:
|
zones{{ dash_view }}-{{ zone }}{{ '.include' if serial_auto else ''}}:
|
||||||
file.managed:
|
file.managed:
|
||||||
- name: {{ zones_directory }}/{{ file }}{{ '.include' if serial_auto else ''}}
|
- name: {{ zones_directory }}/{{ file }}{{ '.include' if serial_auto else ''}}
|
||||||
|
|
|
@ -7,6 +7,22 @@
|
||||||
// organization
|
// organization
|
||||||
//include "/etc/bind/zones.rfc1918";
|
//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) %}
|
{%- macro zone(key, args, file, masters) %}
|
||||||
zone "{{ key }}" {
|
zone "{{ key }}" {
|
||||||
type {{ args['type'] }};
|
type {{ args['type'] }};
|
||||||
|
@ -92,23 +108,26 @@ include "{{ map.default_zones_config }}";
|
||||||
{{ zone(key, args, file, masters) }}
|
{{ zone(key, args, file, masters) }}
|
||||||
{% endfor %}
|
{% 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 }} {
|
view {{ view }} {
|
||||||
{%- if view == 'default' %}
|
{%- if view == 'default' %}
|
||||||
include "{{ map.default_zones_config }}";
|
include "{{ map.default_zones_config }}";
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
match-clients {
|
||||||
match-clients {
|
|
||||||
{%- for acl in view_data.get('match_clients', {}) %}
|
{%- for acl in view_data.get('match_clients', {}) %}
|
||||||
{{ acl }};
|
{{ acl }};
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
};
|
};
|
||||||
|
|
||||||
{% for key, args in view_data.get('configured_zones', {})|dictsort -%}
|
{%- for key, args in view_data.get('configured_zones', {})|dictsort -%}
|
||||||
{%- set file = salt['pillar.get']("bind:available_zones:" + key + ":file") %}
|
{%- 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") %}
|
{%- set masters = salt['pillar.get']("bind:available_zones:" + key + ":masters") %}
|
||||||
{{ zone(key, args, file, masters) }}
|
{{ zone(key, args, file, masters) }}
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
};
|
};
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
|
@ -163,20 +182,3 @@ statistics-channels {
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
};
|
};
|
||||||
{%- endif %}
|
{%- 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
97
pillar-with-views.example
Normal 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.
|
|
@ -231,7 +231,9 @@ bind:
|
||||||
notify: False # Don't notify any NS RRs of any changes to zone
|
notify: False # Don't notify any NS RRs of any changes to zone
|
||||||
also-notify: # Do notify these IP addresses (pointless as
|
also-notify: # Do notify these IP addresses (pointless as
|
||||||
- 1.1.1.1 # notify has been set to no)
|
- 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
|
sub.domain2.com: # Domain zone with DNSSEC
|
||||||
type: master # We're the master of this zone
|
type: master # We're the master of this zone
|
||||||
|
@ -279,14 +281,25 @@ bind:
|
||||||
configured_zones: # Zones that our view is applicable to
|
configured_zones: # Zones that our view is applicable to
|
||||||
my.zone: # We've defined a new zone in here
|
my.zone: # We've defined a new zone in here
|
||||||
type: master
|
type: master
|
||||||
notify: False
|
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
|
update_policy: # A given update policy
|
||||||
- "grant core_dhcp name dns_entry_allowed_to_update. ANY"
|
- "grant core_dhcp name dns_entry_allowed_to_update. ANY"
|
||||||
|
|
||||||
configured_acls: # And now for some ACLs
|
configured_acls: # And now for some ACLs
|
||||||
my_net: # Our ACL's name
|
my_net: # Our ACL's name
|
||||||
- 127.0.0.0/8 # And the applicable IP addresses
|
- 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 ###
|
### Define zone records in pillar ###
|
||||||
bind:
|
bind:
|
||||||
|
|
Loading…
Add table
Reference in a new issue