Add certificate management via Mythic Beasts DNSAPI.

This commit is contained in:
Jim Hague 2023-02-20 15:50:20 +00:00
parent 0ee6d4a45b
commit 061cf5bc6c
15 changed files with 221 additions and 0 deletions

View File

@ -0,0 +1,3 @@
dnsapi:
keyid: 'xyzzy'
secret: 'plugh'

4
pillar/top.sls Normal file
View File

@ -0,0 +1,4 @@
base:
'scabbers.lunch.org.uk':
- secrets/dnsapi

View File

@ -0,0 +1,3 @@
HOOK=/etc/dehydrated/dehydrated-mythic-dns01/dehydrated-mythic-dns01.sh
CHALLENGETYPE=dns-01
HOOK_CHAIN=yes

View File

@ -0,0 +1 @@
CONTEXT_EMAIL=jim@lunch.org.uk

View File

@ -0,0 +1,2 @@
#!/bin/sh
exec /usr/bin/dehydrated --cron >> /var/log/dehydrated.log 2>&1

View File

@ -0,0 +1,2 @@
CHALLENGETYPE=dns-01
HOOK_CHAIN=yes

View File

@ -0,0 +1,10 @@
#!/usr/bin/env bash
# Copyright (C) 2018 Mythic Beasts Ltd
. "$(dirname "$0")"/../common/mythic-dns01
echo -ne "$ARGS" | while read domain filename token; do
echo " ++ cleaning DNS for $domain"
call_api DELETE _acme-challenge.$domain $token
done

View File

@ -0,0 +1,73 @@
# Copyright (C) Mythic Beasts Ltd 2018
CONFIG=${MYTHIC_DNS_CONFIG:-/etc/dehydrated/dnsapi.config.txt}
# configure the busy wait loop; max time is $SLEEP * $MAXTRIES
SLEEP=5
MAXTRIES=60
# all our public authoritative servers
SERVERS="ns1.mythic-beasts.com ns2.mythic-beasts.com"
# dig options
DIGOPT='+time=1 +tries=1 +short'
wait_for_dns() {
local key val i s
key="$1" val="$2"
for i in $(seq $MAXTRIES); do
for s in $SERVERS; do
if ! dig $DIGOPT @$s $key txt | grep -q -e $val; then
sleep $SLEEP
continue 2
fi
done
break
done
if [ "$i" -eq "$MAXTRIES" ]; then
echo challenge record not found in DNS >&2
exit 1
fi
}
call_api() {
local action key val dns_domain dns_api_pass rr_part dns_api_secret
action="$1" key="$2" val="$3"
while read dns_domain dns_api_pass dns_api_secret; do
case $key in
*$dns_domain)
rr_part=$(basename $key .$dns_domain)
# If we have a third component in the config file then use the v2 API.
if [ -z "${dns_api_secret}" ]; then
# use DNS API v1
echo -n "$dns_api_pass" |
curl --data-urlencode "domain=$dns_domain" --data-urlencode "password@-" --data-urlencode "command=$action $rr_part 30 TXT $val" https://dnsapi.mythic-beasts.com/
else
# use DNS API v2
case $action in
ADD)
# Use POST here rather than PUT as we may handle multiple challenges in a single run - for example both '*' and bare domain.
echo -n "user = ${dns_api_pass}:${dns_api_secret}" |
curl -f -K - -X POST "https://api.mythic-beasts.com/dns/v2/zones/${dns_domain}/records/${rr_part}/TXT" -d data="${val}"
if [ $? -ne 0 ]; then
echo "Error adding DNS records"
exit 2
fi
;;
DELETE)
echo -n "user = ${dns_api_pass}:${dns_api_secret}" |
curl -f -K - -X DELETE "https://api.mythic-beasts.com/dns/v2/zones/${dns_domain}/records/${rr_part}/TXT"
if [ $? -ne 0 ]; then
echo "Error cleaning up DNS records"
exit 3
fi
;;
esac
fi
break
;;
esac
done < $CONFIG
}

View File

@ -0,0 +1,20 @@
#!/usr/bin/env bash
# Copyright (c) 2018 Mythic Beasts Ltd
group_args() {
local nl=$'\n'
ARGS=''
while [ "$1" ]; do ARGS="$ARGS$1 $2 $3$nl"; shift 3; done
export ARGS
}
action=$1
shift
case $action in
deploy_challenge|clean_challenge)
group_args "$@"
"$(dirname "$0")"/${action/_/-}/mythic-dns01
;;
esac

View File

@ -0,0 +1,14 @@
#!/usr/bin/env bash
# Copyright (C) 2018 Mythic Beasts Ltd
. "$(dirname "$0")"/../common/mythic-dns01
echo -ne "$ARGS" | while read domain filename token; do
echo " ++ setting DNS for $domain"
call_api ADD _acme-challenge.$domain $token
done
echo -ne "$ARGS" | while read domain filename token; do
echo " ++ waiting DNS for $domain"
wait_for_dns _acme-challenge.$domain $token
done

View File

@ -0,0 +1,23 @@
{%- set keyid = pillar['dnsapi']['keyid'] -%}
{%- set secret = pillar['dnsapi']['secret'] -%}
{#- -#}
{#- bear-cave.org.uk domains -#}
{#- -#}
bear-cave.org.uk {{ keyid }} {{ secret }}
www.bear-cave.org.uk {{ keyid }} {{ secret }}
{# -#}
{#- lunch.org.uk domains -#}
{#- -#}
lunch.org.uk {{ keyid }} {{ secret }}
www.lunch.org.uk {{ keyid }} {{ secret }}
hg.lunch.org.uk {{ keyid }} {{ secret }}
jenkins.lunch.org.uk {{ keyid }} {{ secret }}
lists.lunch.org.uk {{ keyid }} {{ secret }}
mail.lunch.org.uk {{ keyid }} {{ secret }}
{# -#}
{#- cryhavoc.org.uk domains -#}
{#- -#}
cryhavoc.org.uk {{ keyid }} {{ secret }}
www.cryhavoc.org.uk {{ keyid }} {{ secret }}
dottes.cryhavoc.org.uk {{ keyid }} {{ secret }}
lists.cryhavoc.org.uk {{ keyid }} {{ secret }}

View File

@ -0,0 +1,8 @@
bear-cave.org.uk www.bear-cave.org.uk
lunch.org.uk www.lunch.org.uk
hg.lunch.org.uk
jenkins.lunch.org.uk
mail.lunch.org.uk
lists.lunch.org.uk lists.cryhavoc.org.uk
cryhavoc.org.uk www.cryhavoc.org.uk
dottes.cryhavoc.org.uk

View File

@ -0,0 +1,9 @@
/var/log/dehydrated.log
{
rotate 12
monthly
missingok
notifempty
delaycompress
compress
}

View File

@ -0,0 +1,48 @@
dehydrated:
pkg.installed:
- pkgs:
- dehydrated
- dnsutils
dehydrated_domains:
file.managed:
- name: /etc/dehydrated/domains.txt
- source: salt://certificates/dehydrated/domains.txt
- mode: '0644'
dehydrated_dnsapi:
file.managed:
- name: /etc/dehydrated/dnsapi.config.txt
- source: salt://certificates/dehydrated/dnsapi.config.txt
- mode: '0600'
- template: jinja
dehydrated_mythic_dns01:
file.recurse:
- name: /etc/dehydrated/dehydrated-mythic-dns01
- source: salt://certificates/dehydrated/dehydrated-mythic-dns01
- dir_mode: '0755'
- file_mode: '0755'
- exclude_pat:
- "debian*"
- README.md
dehydrated_hooks:
file.recurse:
- name: /etc/dehydrated/conf.d
- source: salt://certificates/dehydrated/conf.d
- dir_mode: '0755'
- file_mode: '0644'
dehydrated_cron:
file.managed:
- name: /etc/cron.daily/dehydrated
- source: salt://certificates/dehydrated/cron.daily
- mode: '0755'
dehydrated_logrotate:
file.managed:
- name: /etc/logrotate.d/dehydrated
- source: salt://certificates/dehydrated/logrotate
- mode: '0644'

View File

@ -7,3 +7,4 @@ base:
'scabbers.lunch.org.uk':
- debian
- certificates