wip
This commit is contained in:
parent
28a2b53a9d
commit
d2ea2ccd9c
11 changed files with 99 additions and 53 deletions
|
@ -13,34 +13,19 @@ def acme_hostname(metadata):
|
||||||
|
|
||||||
|
|
||||||
@metadata_reactor.provides(
|
@metadata_reactor.provides(
|
||||||
'bind/zones',
|
'dns',
|
||||||
)
|
)
|
||||||
def acme_records(metadata):
|
def acme_records(metadata):
|
||||||
if metadata.get('bind/type') == 'slave':
|
if metadata.get('bind/type') == 'slave':
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'bind': {
|
'dns': {
|
||||||
'zones': {
|
f'_acme-challenge.{domain}': {
|
||||||
zone: {
|
'CNAME': {f"{domain}.{metadata.get('bind/acme_hostname')}."},
|
||||||
'records': {
|
}
|
||||||
# FIXME: bw currently cant handle lists of dicts :(
|
for domain in node.metadata.get('letsencrypt/domains')
|
||||||
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')
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -38,9 +38,11 @@ view "${view['name']}" {
|
||||||
% if type == 'slave':
|
% if type == 'slave':
|
||||||
masters { ${master_ip}; };
|
masters { ${master_ip}; };
|
||||||
% endif
|
% endif
|
||||||
|
% if type == 'master':
|
||||||
% for key in conf.get('keys', []):
|
% for key in conf.get('keys', []):
|
||||||
allow-update { key "${key}"; };
|
allow-update { key "${key}"; };
|
||||||
% endfor
|
% endfor
|
||||||
|
% endif
|
||||||
file "/var/lib/bind/${view['name']}/db.${zone}";
|
file "/var/lib/bind/${view['name']}/db.${zone}";
|
||||||
};
|
};
|
||||||
% endfor
|
% endfor
|
||||||
|
|
|
@ -3,7 +3,7 @@ options {
|
||||||
dnssec-validation auto;
|
dnssec-validation auto;
|
||||||
|
|
||||||
listen-on-v6 { any; };
|
listen-on-v6 { any; };
|
||||||
allow-query { any; };
|
allow-query { any; };
|
||||||
|
|
||||||
max-cache-size 30%;
|
max-cache-size 30%;
|
||||||
querylog yes;
|
querylog yes;
|
||||||
|
|
|
@ -53,6 +53,7 @@ files['/etc/bind/named.conf.options'] = {
|
||||||
'context': {
|
'context': {
|
||||||
'type': node.metadata.get('bind/type'),
|
'type': node.metadata.get('bind/type'),
|
||||||
'slave_ips': sorted(slave_ips),
|
'slave_ips': sorted(slave_ips),
|
||||||
|
'master_ip': master_ip,
|
||||||
},
|
},
|
||||||
'owner': 'root',
|
'owner': 'root',
|
||||||
'group': 'bind',
|
'group': 'bind',
|
||||||
|
@ -165,6 +166,7 @@ for view in views:
|
||||||
unique_records
|
unique_records
|
||||||
)),
|
)),
|
||||||
'hostname': node.metadata.get('bind/hostname'),
|
'hostname': node.metadata.get('bind/hostname'),
|
||||||
|
'type': node.metadata.get('bind/type'),
|
||||||
},
|
},
|
||||||
'needs': [
|
'needs': [
|
||||||
f"directory:/var/lib/bind/{view['name']}",
|
f"directory:/var/lib/bind/{view['name']}",
|
||||||
|
|
|
@ -3,3 +3,4 @@ BASEDIR=/var/lib/dehydrated
|
||||||
WELLKNOWN="${BASEDIR}/acme-challenges"
|
WELLKNOWN="${BASEDIR}/acme-challenges"
|
||||||
DOMAINS_TXT="/etc/dehydrated/domains.txt"
|
DOMAINS_TXT="/etc/dehydrated/domains.txt"
|
||||||
HOOK="/etc/dehydrated/hook.sh"
|
HOOK="/etc/dehydrated/hook.sh"
|
||||||
|
CA="https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||||
|
|
|
@ -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
|
|
41
bundles/letsencrypt/files/dns_challenge_hook.sh
Normal file
41
bundles/letsencrypt/files/dns_challenge_hook.sh
Normal 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
|
|
@ -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>
|
deploy_cert() {<%text>
|
||||||
local DOMAIN="${1}" KEYFILE="${2}" CERTFILE="${3}" FULLCHAINFILE="${4}" CHAINFILE="${5}" TIMESTAMP="${6}"</%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():
|
% for service, config in node.metadata.get('letsencrypt/concat_and_deploy', {}).items():
|
||||||
|
@ -32,6 +65,6 @@ exit_hook() {<%text>
|
||||||
|
|
||||||
<%text>
|
<%text>
|
||||||
HANDLER="$1"; shift
|
HANDLER="$1"; shift
|
||||||
if [[ "${HANDLER}" =~ ^(deploy_cert|exit_hook)$ ]]; then
|
if [[ "${HANDLER}" =~ ^(deploy_cert|exit_hook|deploy_challenge)$ ]]; then
|
||||||
"$HANDLER" "$@"
|
"$HANDLER" "$@"
|
||||||
fi</%text>
|
fi</%text>
|
||||||
|
|
|
@ -21,6 +21,14 @@ files = {
|
||||||
},
|
},
|
||||||
'/etc/dehydrated/hook.sh': {
|
'/etc/dehydrated/hook.sh': {
|
||||||
'content_type': 'mako',
|
'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',
|
'mode': '0755',
|
||||||
},
|
},
|
||||||
'/etc/dehydrated/letsencrypt-ensure-some-certificate': {
|
'/etc/dehydrated/letsencrypt-ensure-some-certificate': {
|
||||||
|
|
|
@ -40,7 +40,7 @@ def renew(metadata):
|
||||||
return {
|
return {
|
||||||
'systemd-timers': {
|
'systemd-timers': {
|
||||||
'letsencrypt': {
|
'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',
|
'when': 'daily',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
},
|
},
|
||||||
'bind': {
|
'bind': {
|
||||||
'hostname': 'resolver.name',
|
'hostname': 'resolver.name',
|
||||||
|
'acme_hostname': 'acme.sublimity.de',
|
||||||
'zones': {
|
'zones': {
|
||||||
'sublimity.de': {},
|
'sublimity.de': {},
|
||||||
'freibrief.net': {},
|
'freibrief.net': {},
|
||||||
|
@ -63,6 +64,7 @@
|
||||||
'letsencrypt': {
|
'letsencrypt': {
|
||||||
'domains': {
|
'domains': {
|
||||||
'ckn.li': set(),
|
'ckn.li': set(),
|
||||||
|
'test1.ckn.li': set(),
|
||||||
'sublimity.de': set(),
|
'sublimity.de': set(),
|
||||||
'freibrief.net': set(),
|
'freibrief.net': set(),
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue