mirror of
https://github.com/saltstack-formulas/bind-formula.git
synced 2025-04-15 17:20:21 +00:00
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.
This commit is contained in:
parent
522b369cab
commit
7e47c7658f
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
|
||||
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
|
||||
-------------------
|
||||
|
||||
|
|
|
@ -203,19 +203,24 @@ bind_rndc_client_config:
|
|||
{%- set views = {False: salt['pillar.get']('bind', {})} %}{# process non-view zones in the same loop #}
|
||||
{%- 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 -%}
|
||||
{%- set file = salt['pillar.get']("bind:available_zones:" + zone + ":file", false) %}
|
||||
{%- 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 %}
|
||||
{%- set dash_view = '-' + view if view else '' %}
|
||||
{%- 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', {})) %}
|
||||
{%- endif %}
|
||||
{# 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
|
||||
#}
|
||||
{%- 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' %}
|
||||
{% if file and zone_data['type'] == 'master' -%}
|
||||
{%- 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' %}
|
||||
{% if file and zone_data['type'] == 'master' -%}
|
||||
zones{{ dash_view }}-{{ zone }}{{ '.include' if serial_auto else ''}}:
|
||||
file.managed:
|
||||
- name: {{ zones_directory }}/{{ file }}{{ '.include' if serial_auto else ''}}
|
||||
|
|
|
@ -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,23 +108,26 @@ 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 }};
|
||||
{{ acl }};
|
||||
{%- endfor %}
|
||||
};
|
||||
};
|
||||
|
||||
{% for key, args in view_data.get('configured_zones', {})|dictsort -%}
|
||||
{%- set file = salt['pillar.get']("bind:available_zones:" + key + ":file") %}
|
||||
{%- 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) }}
|
||||
{{ zone(key, args, file, masters) }}
|
||||
{%- endfor %}
|
||||
};
|
||||
{%- 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
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
|
||||
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,14 +281,25 @@ bind:
|
|||
configured_zones: # Zones that our view is applicable to
|
||||
my.zone: # We've defined a new zone in here
|
||||
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
|
||||
- "grant core_dhcp name dns_entry_allowed_to_update. ANY"
|
||||
|
||||
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:
|
||||
|
|
Loading…
Add table
Reference in a new issue