diff --git a/bundles/bind/files/keys.conf b/bundles/bind/files/keys.conf new file mode 100644 index 0000000..faf4ce4 --- /dev/null +++ b/bundles/bind/files/keys.conf @@ -0,0 +1,6 @@ +% for key in keys: +key ${key['name']} { + algorithm ${key['algorithm']}; + secret "${key['secret']}"; +}; +% endfor diff --git a/bundles/bind/files/named.conf.local b/bundles/bind/files/named.conf.local new file mode 100644 index 0000000..5f5e826 --- /dev/null +++ b/bundles/bind/files/named.conf.local @@ -0,0 +1,30 @@ +include "/etc/bind/keys.conf"; + +% for zone in sorted(primary_zones): +zone "${zone}" IN { + type master; + file "/var/lib/bind/primary/${zone}"; +}; +% endfor + + +zone "10.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; + +zone "16.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; +zone "17.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; +zone "18.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; +zone "19.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; +zone "20.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; +zone "21.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; +zone "22.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; +zone "23.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; +zone "24.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; +zone "25.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; +zone "26.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; +zone "27.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; +zone "28.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; +zone "29.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; +zone "30.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; +zone "31.172.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; + +zone "168.192.in-addr.arpa" { type master; file "/etc/bind/db.empty"; }; diff --git a/bundles/bind/files/named.conf.options b/bundles/bind/files/named.conf.options new file mode 100644 index 0000000..1e9db6e --- /dev/null +++ b/bundles/bind/files/named.conf.options @@ -0,0 +1,3 @@ +% for o in node.metadata.get('bind', {}).get('options', []): +<%include file="options/${o}"/> +% endfor diff --git a/bundles/bind/items.py b/bundles/bind/items.py new file mode 100644 index 0000000..bf725d4 --- /dev/null +++ b/bundles/bind/items.py @@ -0,0 +1,144 @@ +from os import listdir +from os.path import isfile, join +from datetime import datetime +from subprocess import check_output + +ZONE_HEADER = """ +; _ ____ _ _ _____ _ _ _ _ ____ +; / \\ / ___| | | |_ _| | | | \\ | |/ ___| +; / _ \\| | | |_| | | | | | | | \\| | | _ +; / ___ \\ |___| _ | | | | |_| | |\\ | |_| | +; /_/ \\_\\____|_| |_| |_| \\___/|_| \\_|\\____| +; +; --> Diese Datei wird von BundleWrap verwaltet! <-- + +$TTL 60 +@ IN SOA ns-1.kunbox.net. hostmaster.kunbox.net. ( + {serial} + 3600 + 3600 + 86400 + 300 + ) +@ IN NS ns-1.kunbox.net. + IN NS ns-2.kunbox.net. +""" + +svc_systemd = { + 'bind9': { + 'needs': { + 'pkg_apt:bind9', + }, + }, +} + +pkg_apt = { + 'bind9': {}, +} + +directories = { + "/var/lib/bind/primary": { + 'group': 'bind', + 'needs': { + 'pkg_apt:bind9', + }, + 'owner': 'bind', + 'purge': True, + }, + "/var/log/named": { + 'group': 'bind', + 'needs': { + 'pkg_apt:bind9', + }, + 'owner': 'bind', + }, +} + +files = { + "/etc/bind/keys.conf": { + 'content_type': 'mako', + 'group': 'bind', + 'mode': '0440', + 'context': { + 'keys': node.metadata.get('bind', {}).get('keys', []), + }, + 'triggers': { + 'svc_systemd:bind9:reload', + }, + 'needs': { + 'pkg_apt:bind9', + }, + }, + "/etc/bind/named.conf.options": { + 'content_type': 'mako', + 'group': 'bind', + 'mode': '0440', + 'triggers': { + 'svc_systemd:bind9:reload', + }, + 'needs': { + 'pkg_apt:bind9', + }, + }, +} + +if node.metadata.get('bind', {}).get('rndc', ''): + files['/etc/bind/rndc.conf'] = { + 'mode': '0440', + 'source': 'rndc/{}'.format(node.metadata['bind']['rndc']), + 'content_type': 'mako', + 'triggers': { + 'svc_systemd:bind9:reload', + }, + } + +# this looks for zones either directly at data/bind/zones/ or in a subdirectory if so configured +zone_path = join( + repo.path, + 'data', 'bind', 'files', 'zones', + node.metadata.get('bind', {}).get('zone_path', ""), +) + +primary_zones = set() + +for zone in listdir(zone_path): + if not isfile(join(zone_path, zone)) or zone.startswith(".") or zone.startswith("_"): + continue + + output = check_output(['git', 'log', '-1', '--pretty=%ci', join(zone_path, zone)]).decode('utf-8').strip() + serial = datetime.strptime(output, '%Y-%m-%d %H:%M:%S %z').strftime('%y%m%d%H%M') + + primary_zones.add(zone) + + files["/var/lib/bind/primary/{}".format(zone)] = { + 'content_type': 'mako', + 'context': { + 'header': ZONE_HEADER.format(serial=serial), + 'metadata_records': node.metadata.get('bind', {}).get('zones_primary', {}).get(zone, {}).get('records', []), + }, + 'mode': '0444', + 'owner': 'bind', + 'source': 'zones/{}'.format(join(node.metadata.get('bind', {}).get('zone_path', ""), zone)), + 'triggers': { + 'svc_systemd:bind9:reload', + }, + 'needs': { + 'pkg_apt:bind9' + }, + } + +primary_zones.union(set(node.metadata.get('bind', {}).get('zones_primary', {}).keys())) + +files['/etc/bind/named.conf.local'] = { + 'content_type': 'mako', + 'context': { + 'primary_zones': list(primary_zones), + }, + 'group': 'bind', + 'triggers': { + 'svc_systemd:bind9:reload', + }, + 'needs': { + 'pkg_apt:bind9', + }, +} diff --git a/bundles/bind/metadata.py b/bundles/bind/metadata.py new file mode 100644 index 0000000..f82c174 --- /dev/null +++ b/bundles/bind/metadata.py @@ -0,0 +1,52 @@ +from bundlewrap.metadata import atomic + + +@metadata_processor +def backups(metadata): + if metadata.get('bind', {}).get('zones_primary_dynamic', {}): + metadata.setdefault('backups', {}).setdefault('paths', set()).add( + '/var/lib/bind/primary.dynamic', + ) + return metadata, RUN_ME_AGAIN + + +@metadata_processor +def monitoring(metadata): + icinga2_api = metadata.setdefault('icinga2_api', {}) + node_metadata = icinga2_api.setdefault('bind', {}) + + services = node_metadata.setdefault('services', {}) + services.setdefault('BIND PROCESS', {}).update({ + 'check_command': 'nrpe', + 'vars.nrpe_command': 'check_bind_procs', + }) + for interface in metadata.get('bind', {}).get('listen', []): + services.setdefault('BIND PORT {}'.format(interface), {}).update({ + 'check_command': 'tcp', + 'vars.tcp_address': metadata['interfaces'][interface]['ip_addresses'][0], + 'vars.tcp_port': 53, + }) + + nrpe_checks = metadata.setdefault('nrpe', {}).setdefault('custom_nrpe_checks', {}) + nrpe_checks['check_bind_procs'] = '/usr/lib/nagios/plugins/check_procs -C named -c 1:1' + + return metadata, DONE + + +@metadata_processor +def sperrfix(metadata): + per_bundle = metadata.get('bind', {}).get('sperrfix', {}) + + if per_bundle.get('ignore'): + return metadata, DONE + + sources = per_bundle.get('sources', {'*'}) + + return { + 'sperrfix': { + 'bundle_rules': { + '53': atomic({'sources': sources}), + '53/udp': atomic({'sources': sources}), + }, + }, + }, OVERWRITE, RUN_ME_AGAIN diff --git a/data/bind/files/zones/franzi.business b/data/bind/files/zones/franzi.business new file mode 100644 index 0000000..d9d37d0 --- /dev/null +++ b/data/bind/files/zones/franzi.business @@ -0,0 +1,22 @@ +${header} + +$ORIGIN franzi.business + +@ IN A 94.130.52.224 + IN AAAA 2a01:4f8:10b:2a5f::2 + IN MX 10 mx0.kunbox.net. + IN TXT v=spf1 a mx ~all + +* IN A 94.130.52.224 + IN AAAA 2a01:4f8:10b:2a5f::2 + +sewfile IN A 116.203.205.248 + IN AAAA 2a01:4f8:c0c:c71b::1 + IN TXT v=spf1 a mx ~all + + +_matrix._tcp IN SRV 10.8448 matrix.franzi.business. + +2019._domainkey IN TXT v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwkg6UAcu3V98hal1UVf6yB0WT1CKDS0AK83CUlSP8bUwraPxkxK1nkQOUsmjbQs6a3FhdsKprMi32GeUaTVvZg81JIybPk3jNugfNWfSjs2TXPomYu+XD2pmmbR3cZlzC5NGR2nmBFt/P/S2ihPHj35KziiBIwK1TdvOi1M2+upCjK33Icco0ByCm0gJpD2O0cbqcBcUKqd6X440vYhNXH1ygp0e91P0iRnvS9sg6yD0xjD8kD6j/8GfxBY+9bpU3EvDoBgyJSbjw5b6PUVJbKMXzw1NIRNj0SXKs5BakjS8+7u62vR11IPCYRwy+yr0rDT0tNegM7gStIIgoTpOoQIDAQAB +_dmarc IN TXT v=DMARC1; p=none; rua=mailto:postmaster@kunsmann.eu; ruf=mailto:postmaster@kunsmann.eu; fo=0:d:s; adkim=r; aspf=r +_token._dnswl IN TXT gg3mbwjx9bbuo5osvhq7oz6bc881wcmc