This commit is contained in:
mwiegand 2021-11-06 11:44:46 +01:00
parent 28a2b53a9d
commit d2ea2ccd9c
11 changed files with 99 additions and 53 deletions

View file

@ -13,34 +13,19 @@ def acme_hostname(metadata):
@metadata_reactor.provides(
'bind/zones',
'dns',
)
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': f"{name}.{zone}.{metadata.get('bind/acme_hostname')}.",
})
for name in {
record['name'] if record['name'] != '@' else ''
for record in conf['records']
if f"{record['name']}.{zone}" in metadata.get('letsencrypt/domains')
}
}
}
for zone, conf in metadata.get('bind/zones').items()
if zone != metadata.get('bind/acme_hostname')
},
},
'dns': {
f'_acme-challenge.{domain}': {
'CNAME': {f"{domain}.{metadata.get('bind/acme_hostname')}."},
}
for domain in node.metadata.get('letsencrypt/domains')
}
}

View file

@ -38,9 +38,11 @@ view "${view['name']}" {
% if type == 'slave':
masters { ${master_ip}; };
% endif
% if type == 'master':
% for key in conf.get('keys', []):
allow-update { key "${key}"; };
% endfor
% endif
file "/var/lib/bind/${view['name']}/db.${zone}";
};
% endfor

View file

@ -3,7 +3,7 @@ options {
dnssec-validation auto;
listen-on-v6 { any; };
allow-query { any; };
allow-query { any; };
max-cache-size 30%;
querylog yes;

View file

@ -53,6 +53,7 @@ files['/etc/bind/named.conf.options'] = {
'context': {
'type': node.metadata.get('bind/type'),
'slave_ips': sorted(slave_ips),
'master_ip': master_ip,
},
'owner': 'root',
'group': 'bind',
@ -165,6 +166,7 @@ for view in views:
unique_records
)),
'hostname': node.metadata.get('bind/hostname'),
'type': node.metadata.get('bind/type'),
},
'needs': [
f"directory:/var/lib/bind/{view['name']}",

View file

@ -3,3 +3,4 @@ BASEDIR=/var/lib/dehydrated
WELLKNOWN="${BASEDIR}/acme-challenges"
DOMAINS_TXT="/etc/dehydrated/domains.txt"
HOOK="/etc/dehydrated/hook.sh"
CA="https://acme-staging-v02.api.letsencrypt.org/directory"

View file

@ -1,28 +0,0 @@
#!/usr/bin/env bash
set -e
set -u
set -o pipefail
OPERATION=$1
DOMAIN=$2
TOKEN=$4
TTL=300
case "$1" in
"deploy_challenge")
;;
"clean_challenge")
;;
"deploy_cert")
;;
"unchanged_cert")
;;
"startup_hook")
;;
"exit_hook")
;;
esac
exit 0

View file

@ -0,0 +1,41 @@
#!/usr/bin/env bash
set -e
set -u
set -o pipefail
ACME_ZONE=${acme_hostname}
SERVER=${bind_hostname}
OPERATION=$1
DOMAIN=$2
TOKEN=$4
TTL=300
case "$1" in
"deploy_challenge")
printf "
server 127.0.0.1
zone $ACME_ZONE.
update add $DOMAIN.$ACME_ZONE. 600 IN TXT \"$TOKEN\"
send
" | nsupdate -y $TOKEN
;;
"clean_challenge")
printf "
server 127.0.0.1
zone $ACME_ZONE.
update delete $DOMAIN.$ACME_ZONE. TXT
send
" | nsupdate -y $TOKEN
;;
"deploy_cert")
;;
"unchanged_cert")
;;
"startup_hook")
;;
"exit_hook")
;;
esac
exit 0

View file

@ -1,3 +1,36 @@
deploy_challenge() {
set -e
set -u
set -o pipefail
ACME_ZONE=${zone}
SERVER=${server}
DOMAIN=$1
CHALLENGE=$3
KEY=hmac-sha512:acme:${acme_key}
cmd="
server 127.0.0.1
zone $ACME_ZONE.
update delete $DOMAIN.$ACME_ZONE. TXT
update add $DOMAIN.$ACME_ZONE. 60 IN TXT \"$CHALLENGE\"
send
"
echo "$cmd"
echo "$cmd" | nsupdate -y $KEY
cmd="
server $SERVER
local $SERVER
zone $ACME_ZONE.
update delete $DOMAIN.$ACME_ZONE. TXT
update add $DOMAIN.$ACME_ZONE. 60 IN TXT \"$CHALLENGE\"
send
"
echo "$cmd"
echo "$cmd" | nsupdate -y $KEY
sleep 10
}
deploy_cert() {<%text>
local DOMAIN="${1}" KEYFILE="${2}" CERTFILE="${3}" FULLCHAINFILE="${4}" CHAINFILE="${5}" TIMESTAMP="${6}"</%text>
% for service, config in node.metadata.get('letsencrypt/concat_and_deploy', {}).items():
@ -32,6 +65,6 @@ exit_hook() {<%text>
<%text>
HANDLER="$1"; shift
if [[ "${HANDLER}" =~ ^(deploy_cert|exit_hook)$ ]]; then
if [[ "${HANDLER}" =~ ^(deploy_cert|exit_hook|deploy_challenge)$ ]]; then
"$HANDLER" "$@"
fi</%text>

View file

@ -21,6 +21,14 @@ files = {
},
'/etc/dehydrated/hook.sh': {
'content_type': 'mako',
'context': {
'server': node.metadata.get('network/external/ipv4').split('/')[0],
'zone': node.metadata.get('bind/acme_hostname'),
'acme_key': node.metadata.get('bind/keys/acme'),
},
'mode': '0755',
},
'/etc/dehydrated/letsencrypt-ensure-some-certificate': {
'mode': '0755',
},
'/etc/dehydrated/letsencrypt-ensure-some-certificate': {

View file

@ -40,7 +40,7 @@ def renew(metadata):
return {
'systemd-timers': {
'letsencrypt': {
'command': '/bin/bash -c "/usr/bin/dehydrated --cron --accept-terms --challenge http-01 && /usr/bin/dehydrated --cleanup"',
'command': '/bin/bash -c "/usr/bin/dehydrated --cron --accept-terms --challenge dns-01 && /usr/bin/dehydrated --cleanup"',
'when': 'daily',
},
},

View file

@ -32,6 +32,7 @@
},
'bind': {
'hostname': 'resolver.name',
'acme_hostname': 'acme.sublimity.de',
'zones': {
'sublimity.de': {},
'freibrief.net': {},
@ -63,6 +64,7 @@
'letsencrypt': {
'domains': {
'ckn.li': set(),
'test1.ckn.li': set(),
'sublimity.de': set(),
'freibrief.net': set(),
},