diff --git a/bundles/bind-acme/metadata.py b/bundles/bind-acme/metadata.py new file mode 100644 index 0000000..c133fe3 --- /dev/null +++ b/bundles/bind-acme/metadata.py @@ -0,0 +1,63 @@ +h = repo.libs.hashable.hashable + + +@metadata_reactor.provides( + 'bind/acme_hostname', +) +def acme_hostname(metadata): + return { + 'bind': { + 'acme_hostname': 'acme.'+ metadata.get('bind/hostname'), + }, + } + + +@metadata_reactor.provides( + 'bind/zones', +) +def acme_records(metadata): + if metadata.get('bind/type') == 'slave': + return {} + + return { + 'bind': { + 'zones': { + zone: { + 'records': { + # FIXME: bw currently cant handle lists of dicts :( + h({ + 'name': f"_acme-challenge{'.' if name else ''}{name}", + 'type': 'CNAME', + 'value': metadata.get('bind/acme_hostname'), + }) + for name in { + record['name'] if record['name'] != '@' else '' + for record in conf['records'] + if '._domainkey' not in record['name'] + } + } + } + for zone, conf in metadata.get('bind/zones').items() + }, + }, + } + + + +@metadata_reactor.provides( + 'bind/zones', +) +def acme_zone(metadata): + if metadata.get('bind/type') == 'slave': + return {} + + return { + 'bind': { + 'zones': { + metadata.get('bind/hostname'): { + 'keys': ['acme'], + 'records': set(), + }, + }, + }, + } diff --git a/bundles/bind/files/db.acme b/bundles/bind/files/db.acme deleted file mode 100644 index 33526bf..0000000 --- a/bundles/bind/files/db.acme +++ /dev/null @@ -1,13 +0,0 @@ -$TTL 600 -@ IN SOA acme.${hostname}. admin.acme.${hostname}. ( - 2021070821 ;Serial - 3600 ;Refresh - 200 ;Retry - 1209600 ;Expire - 900 ;Negative response caching TTL -) - -@ IN A 162.55.188.157 -@ IN AAAA 2a01:4f8:1c1c:4121::2 -@ IN NS resolver.name. -@ IN NS second.resolver.name. diff --git a/bundles/bind/files/named.conf.local b/bundles/bind/files/named.conf.local index 5c429fe..8295ac1 100644 --- a/bundles/bind/files/named.conf.local +++ b/bundles/bind/files/named.conf.local @@ -4,10 +4,12 @@ acl "${view['name']}" { }; % endfor -key "acme" { +% for name, token in keys.items(): +key "${name}" { algorithm hmac-sha512; - secret "${acme_key}"; + secret "${token}"; }; +% endfor % for view in views: view "${view['name']}" { @@ -30,23 +32,19 @@ view "${view['name']}" { 8.8.8.8; }; - % for zone in zones: + % for zone, conf in sorted(zones.items()): zone "${zone}" { type ${type}; -% if type == 'slave': + % if type == 'slave': masters { ${master_ip}; }; -% endif + % endif + % for key in conf.get('keys', []): + allow-update { key "${key}"; }; + % endfor file "/var/lib/bind/${view['name']}/db.${zone}"; }; % endfor - zone "acme.${hostname}" { - type master; - file "/var/lib/bind/${view['name']}/db.acme.${hostname}"; - masterfile-format text; - allow-update { key "acme"; }; - }; - include "/etc/bind/named.conf.default-zones"; include "/etc/bind/zones.rfc1918"; }; diff --git a/bundles/bind/items.py b/bundles/bind/items.py index 8fabddd..4ef1f26 100644 --- a/bundles/bind/items.py +++ b/bundles/bind/items.py @@ -92,9 +92,9 @@ files['/etc/bind/named.conf.local'] = { 'type': node.metadata.get('bind/type'), 'master_ip': master_ip, 'views': views, - 'zones': sorted(zones), + 'zones': zones, 'hostname': node.metadata.get('bind/hostname'), - 'acme_key': node.metadata.get('bind/acme_key'), + 'keys': node.metadata.get('bind/keys'), }, 'owner': 'root', 'group': 'bind', @@ -137,26 +137,9 @@ for view in views: 'svc_systemd:bind9:restart', ], } - files[f"/var/lib/bind/{view['name']}/db.acme.{node.metadata.get('bind/hostname')}"] = { - 'source': 'db.acme', - 'content_type': 'mako', - 'context': { - 'hostname': node.metadata.get('bind/hostname'), - }, - 'owner': 'root', - 'group': 'bind', - 'needs': [ - 'pkg_apt:bind9', - ], - 'needed_by': [ - 'svc_systemd:bind9', - ], - 'triggers': [ - 'svc_systemd:bind9:restart', - ], - } - for zone, records in zones.items(): + for zone, conf in zones.items(): + records = conf['records'] unique_records = [ dict(record_tuple) for record_tuple in set( diff --git a/bundles/bind/metadata.py b/bundles/bind/metadata.py index 75c2d7a..f13d837 100644 --- a/bundles/bind/metadata.py +++ b/bundles/bind/metadata.py @@ -11,6 +11,7 @@ defaults = { 'bind': { 'zones': {}, 'slaves': {}, + 'keys': {}, }, 'telegraf': { 'config': { @@ -26,23 +27,6 @@ defaults = { } -@metadata_reactor.provides( - 'bind/acme_key', -) -def acme_key(metadata): - return { - 'bind': { - 'acme_key': repo.libs.hmac.hmac_sha512( - 'acme', - str(repo.vault.random_bytes_as_base64_for( - f"{metadata.get('id')} bind key acme", - length=32, - )), - ), - } - } - - @metadata_reactor.provides( 'bind/type', ) @@ -93,7 +77,8 @@ def collect_records(metadata): for type, values in records.items(): for value in values: zones\ - .setdefault(zone, set())\ + .setdefault(zone, {})\ + .setdefault('records', set())\ .add( h({'name': name, 'type': type, 'value': value}) ) @@ -123,10 +108,13 @@ def ns_records(metadata): 'bind': { 'zones': { zone: { - # FIXME: bw currently cant handle lists of dicts :( - h({'name': '@', 'type': 'NS', 'value': f"{nameserver}."}) - for nameserver in nameservers - } for zone in metadata.get('bind/zones').keys() + 'records': { + # FIXME: bw currently cant handle lists of dicts :( + h({'name': '@', 'type': 'NS', 'value': f"{nameserver}."}) + for nameserver in nameservers + } + } + for zone in metadata.get('bind/zones').keys() }, }, } @@ -148,3 +136,24 @@ def slaves(metadata): ], }, } + + +@metadata_reactor.provides( + 'bind/keys', +) +def generate_keys(metadata): + return { + 'bind': { + 'keys': { + key: repo.libs.hmac.hmac_sha512( + 'acme', + str(repo.vault.random_bytes_as_base64_for( + f"{metadata.get('id')} bind key {key}", + length=32, + )), + ) + for zone, conf in metadata.get('bind/zones').items() + for key in set(conf.get('keys', [])) + }, + }, + } diff --git a/nodes/htz.mails.py b/nodes/htz.mails.py index b14b07b..942b81f 100644 --- a/nodes/htz.mails.py +++ b/nodes/htz.mails.py @@ -10,6 +10,7 @@ 'dnsserver', ], 'bundles': [ + 'bind-acme', 'islamicstate.eu', 'wireguard', 'zfs',