diff --git a/bundles/bind-acme/metadata.py b/bundles/bind-acme/metadata.py index 4f464ce..25b4401 100644 --- a/bundles/bind-acme/metadata.py +++ b/bundles/bind-acme/metadata.py @@ -20,16 +20,18 @@ def acme_records(metadata): @metadata_reactor.provides( - 'bind/zones', + 'bind/views/external/zones', ) def acme_zone(metadata): return { 'bind': { - 'zones': { - metadata.get('bind/acme_zone'): { - 'dynamic': True, - 'views': ['external'], - 'records': set(), + 'views': { + 'external': { + 'zones': { + metadata.get('bind/acme_zone'): { + 'dynamic': True, + }, + }, }, }, }, diff --git a/bundles/bind/items.py b/bundles/bind/items.py index 96ef842..af83e05 100644 --- a/bundles/bind/items.py +++ b/bundles/bind/items.py @@ -1,18 +1,6 @@ from ipaddress import ip_address, ip_interface from datetime import datetime -if node.metadata.get('bind/type') == 'master': - zones = node.metadata.get('bind/zones') - master_ip = None - slave_ips = [ - ip_interface(repo.get_node(slave).metadata.get('network/external/ipv4')).ip - for slave in node.metadata.get('bind/slaves') - ] -else: - zones = repo.get_node(node.metadata.get('bind/master_node')).metadata.get('bind/zones') - master_ip = ip_interface(repo.get_node(node.metadata.get('bind/master_node')).metadata.get('network/external/ipv4')).ip - slave_ips = [] - directories[f'/var/lib/bind'] = { 'owner': 'bind', 'group': 'bind', @@ -48,6 +36,19 @@ files['/etc/bind/named.conf'] = { 'svc_systemd:bind9:restart', ], } + +if node.metadata.get('bind/type') == 'master': + master_node = node + master_ip = None + slave_ips = [ + ip_interface(repo.get_node(slave).metadata.get('network/external/ipv4')).ip + for slave in node.metadata.get('bind/slaves') + ] +else: + master_node = repo.get_node(node.metadata.get('bind/master_node')) + master_ip = ip_interface(repo.get_node(node.metadata.get('bind/master_node')).metadata.get('network/external/ipv4')).ip + slave_ips = [] + files['/etc/bind/named.conf.options'] = { 'content_type': 'mako', 'context': { @@ -74,12 +75,11 @@ files['/etc/bind/named.conf.local'] = { 'type': node.metadata.get('bind/type'), 'master_ip': master_ip, 'views': dict(sorted( - node.metadata.get('bind/views').items(), + master_node.metadata.get('bind/hostname'), key=lambda e: (e[1].get('default', False), e[0]), )), 'zones': zones, 'hostname': node.metadata.get('bind/hostname'), - 'keys': node.metadata.get('bind/keys'), }, 'owner': 'root', 'group': 'bind', @@ -94,24 +94,6 @@ files['/etc/bind/named.conf.local'] = { ], } -def record_matches_view(record, records, view): - if record['type'] in ['A', 'AAAA']: - if view == 'external': - # no internal addresses in external view - if ip_address(record['value']).is_private: - return False - elif view == 'internal': - # external addresses in internal view only, if no internal exists - if ip_address(record['value']).is_global: - for other_record in records: - if ( - record['name'] == other_record['name'] and - record['type'] == other_record['type'] and - ip_address(other_record['value']).is_private - ): - return False - return True - for view_name, view_conf in node.metadata.get('bind/views').items(): directories[f"/var/lib/bind/{view_name}"] = { 'owner': 'bind', @@ -125,18 +107,7 @@ for view_name, view_conf in node.metadata.get('bind/views').items(): ], } - for zone, conf in zones.items(): - if view_name not in conf.get('views', ['internal', 'external']): - continue - - records = conf['records'] - unique_records = [ - dict(record_tuple) - for record_tuple in set( - tuple(record.items()) for record in records - ) - ] - + for zone, conf in view_conf['zones'].items(): files[f"/var/lib/bind/{view_name}/db.{zone}"] = { 'owner': 'bind', 'group': 'bind', @@ -150,23 +121,22 @@ for view_name, view_conf in node.metadata.get('bind/views').items(): 'svc_systemd:bind9:restart', ], } - if True or node.metadata.get('bind/type') == 'master': #FIXME: slave doesnt get updated if db doesnt get rewritten on each apply - files[f"/var/lib/bind/{view_name}/db.{zone}"].update({ - 'source': 'db', - 'content_type': 'mako', - 'unless': f"test -f /var/lib/bind/{view_name}/db.{zone}" if conf.get('dynamic', False) else 'false', - 'context': { - 'view': view_name, - 'serial': datetime.now().strftime('%Y%m%d%H'), - 'records': list(filter( - lambda record: record_matches_view(record, records, view_name), - unique_records - )), - 'hostname': node.metadata.get('bind/hostname'), - 'type': node.metadata.get('bind/type'), - 'keys': node.metadata.get('bind/keys'), - }, - }) + #FIXME: slave doesnt get updated if db doesnt get rewritten on each apply + files[f"/var/lib/bind/{view_name}/db.{zone}"].update({ + 'source': 'db', + 'content_type': 'mako', + 'unless': f"test -f /var/lib/bind/{view_name}/db.{zone}" if conf.get('dynamic', False) else 'false', + 'context': { + 'serial': datetime.now().strftime('%Y%m%d%H'), + 'records': list(filter( + lambda record: record_matches_view(record, records, view_name), + unique_records + )), + 'hostname': node.metadata.get('bind/hostname'), + 'type': node.metadata.get('bind/type'), + 'keys': node.metadata.get('bind/keys'), + }, + }) svc_systemd['bind9'] = {} diff --git a/bundles/bind/metadata.py b/bundles/bind/metadata.py index 194c602..4fa6e8f 100644 --- a/bundles/bind/metadata.py +++ b/bundles/bind/metadata.py @@ -21,24 +21,18 @@ defaults = { '172.16.0.0/12', '192.168.0.0/16', }, - 'keys': {}, 'zones': {}, }, 'external': { 'default': True, - 'name': 'external', 'is_internal': False, 'acl': { 'any', }, - 'keys': {}, 'zones': {}, }, }, - 'keys': { - 'internal': {}, - 'external': {}, - }, + 'zones': {}, }, 'telegraf': { 'config': { @@ -77,7 +71,7 @@ def dns(metadata): @metadata_reactor.provides( - 'bind/zones', + 'bind/views', ) def collect_records(metadata): if metadata.get('bind/type') == 'slave': @@ -137,15 +131,20 @@ def ns_records(metadata): ] return { 'bind': { - 'zones': { - zone: { - 'records': { - # FIXME: bw currently cant handle lists of dicts :( - h({'name': '@', 'type': 'NS', 'value': f"{nameserver}."}) - for nameserver in nameservers - } + 'views': { + view_name: { + 'zones': { + zone_name: { + 'records': { + # FIXME: bw currently cant handle lists of dicts :( + h({'name': '@', 'type': 'NS', 'value': f"{nameserver}."}) + for nameserver in nameservers + } + } + for zone_name, zone_conf in view_conf['zones'].items() + } } - for zone in metadata.get('bind/zones').keys() + for view_name, view_conf in metadata.get('bind/views').items() }, }, } @@ -176,21 +175,22 @@ def generate_keys(metadata): return { 'bind': { 'views': { - view: { - 'keys': { - f'{view}.{zone}': repo.libs.hmac.hmac_sha512( - zone, - str(repo.vault.random_bytes_as_base64_for( - f"{metadata.get('id')} bind {view} key {zone}", - length=32, - )), - ) - for zone, conf in metadata.get('bind/zones').items() - if conf.get('dynamic', False) - and view in conf.get('views', metadata.get('bind/views').keys()) + view_name: { + 'zones': { + zone_name: { + 'key': repo.libs.hmac.hmac_sha512( + f'{view_name}.{zone_name}', + str(repo.vault.random_bytes_as_base64_for( + f"{metadata.get('id')} bind {view_name} key {zone_name}", + length=32, + )), + ) + } + for zone_name, zone_conf in view_conf['zones'].items() + if zone_conf.get('dynamic', False) } } - for view in metadata.get('bind/views') + for view_name, view_conf in metadata.get('bind/views').items() } }, } @@ -199,39 +199,28 @@ def generate_keys(metadata): @metadata_reactor.provides( 'bind/views', ) -def allow_keys_in_acl(metadata): +def generate_acl_entries_for_keys(metadata): return { 'bind': { 'views': { - view: { + view_name: { 'acl': { - f'key {key}' - for key in conf['keys'] + *{ + f'key {view_name}.{zone_name}' + for zone_name, zone_conf in view_conf['zones'].items() + if zone_conf.get('key', False) + }, + *{ + f'! key {other_view_name}.{zone_name}' + for other_view_name, other_view_conf in metadata.get('bind/views').items() + if other_view_name != view_name + for zone_name, zone_conf in other_view_conf['zones'].items() + if zone_conf.get('key', False) + } } } - for view, conf in metadata.get('bind/views').items() - } - }, - } - - -@metadata_reactor.provides( - 'bind/views', -) -def reject_keys_from_other_views(metadata): - return { - 'bind': { - 'views': { - view: { - 'acl': { - f'! key {key}' - for other_view, other_conf in metadata.get('bind/views').items() - if other_view != view - for key in other_conf['keys'] - } - } - for view, conf in metadata.get('bind/views').items() - if not conf.get('default') - } + for view_name, view_conf in metadata.get('bind/views').items() + if not view_conf.get('default') + }, }, }