Last active
May 22, 2017 02:10
-
-
Save dlangille/f55307a52733920337f248ebcc128c1d to your computer and use it in GitHub Desktop.
Description of a centralized LetsEncrypt strategy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
I'm basing this on https://blog.crashed.org/letsencrypt-in-freebsd-org/ | |
I'll create a new jail: certs.int.unixathome.org | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
get this port installed: https://reviews.freebsd.org/D10308 | |
based on https://github.com/Neilpang/acme.sh/wiki/How-to-install | |
In my testing, I saw this: | |
root@certs:/usr/local/sbin # chown acme:acme /var/db/acme | |
root@certs:/usr/local/sbin # sudo -u acme /usr/local/sbin/acme.sh --install --home /var/db/acme --config-home /var/db/acme/data --certhome /var/db/acme/mycerts --accountemail "dan@langille.org" --accountkey /var/db/acme/myaccount.key --accountconf /var/db/acme/myaccount.conf --useragent "BSD Cabal HQ" | |
[Sat May 20 01:07:08 UTC 2017] Installing to /var/db/acme | |
[Sat May 20 01:07:08 UTC 2017] Installed to /var/db/acme/acme.sh | |
[Sat May 20 01:07:08 UTC 2017] No profile is found, you will need to go into /var/db/acme to use acme.sh | |
[Sat May 20 01:07:08 UTC 2017] Installing cron job | |
2 0 * * * "/var/db/acme"/acme.sh --cron --home "/var/db/acme" --config-home "/var/db/acme/data" > /dev/null | |
[Sat May 20 01:07:08 UTC 2017] Good, bash is found, so change the shebang to use bash as preferred. | |
/usr/local/sbin/acme.sh: cannot create /var/db/acme/acme.sh: Permission denied | |
/usr/local/sbin/acme.sh: cannot create /var/db/acme/acme.sh: Permission denied | |
[Sat May 20 01:07:08 UTC 2017] OK | |
root@certs:/var/db/acme # ls -l | |
total 178 | |
-r-xr-xr-x 1 acme acme 142724 May 20 01:07 acme.sh | |
-rw-r--r-- 1 acme acme 150 May 20 01:07 acme.sh.env | |
drwx------ 2 acme acme 3 May 20 01:07 data | |
-rw-r--r-- 1 acme acme 237 May 20 01:07 myaccount.conf | |
root@certs:/var/db/acme # rm acme.sh | |
root@certs:/var/db/acme # cat acme.sh.env | |
export LE_WORKING_DIR="/var/db/acme" | |
export LE_CONFIG_HOME="/var/db/acme/data" | |
alias acme.sh="/var/db/acme/acme.sh --config-home '/var/db/acme/data'" | |
root@certs:/var/db/acme # |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
root@certs:~/tmp # acme.sh --issue --dns -d example.com -d www.example.com -d cp.example.com | |
[Sat May 20 01:13:11 UTC 2017] Registering account | |
[Sat May 20 01:13:15 UTC 2017] Registered | |
[Sat May 20 01:13:16 UTC 2017] Update success. | |
[Sat May 20 01:13:16 UTC 2017] ACCOUNT_THUMBPRINT='zCArdwbAFZW_hSVMG4UPxaVSF0wBohkDh9qlXXVm8cw' | |
[Sat May 20 01:13:16 UTC 2017] Creating domain key | |
[Sat May 20 01:13:16 UTC 2017] Multi domain='DNS:www.example.com,DNS:cp.example.com' | |
[Sat May 20 01:13:16 UTC 2017] Getting domain auth token for each domain | |
[Sat May 20 01:13:16 UTC 2017] Getting webroot for domain='example.com' | |
[Sat May 20 01:13:16 UTC 2017] Getting new-authz for domain='example.com' | |
[Sat May 20 01:13:17 UTC 2017] The new-authz request is ok. | |
[Sat May 20 01:13:17 UTC 2017] Getting webroot for domain='www.example.com' | |
[Sat May 20 01:13:17 UTC 2017] Getting new-authz for domain='www.example.com' | |
[Sat May 20 01:13:17 UTC 2017] The new-authz request is ok. | |
[Sat May 20 01:13:17 UTC 2017] Getting webroot for domain='cp.example.com' | |
[Sat May 20 01:13:17 UTC 2017] Getting new-authz for domain='cp.example.com' | |
[Sat May 20 01:13:18 UTC 2017] The new-authz request is ok. | |
[Sat May 20 01:13:18 UTC 2017] Add the following TXT record: | |
[Sat May 20 01:13:18 UTC 2017] Domain: '_acme-challenge.example.com' | |
[Sat May 20 01:13:18 UTC 2017] TXT value: 'ckfmEefyLnJHsh7QB9R__KbBHIlyqt5wUl-v9kkOEtY' | |
[Sat May 20 01:13:18 UTC 2017] Please be aware that you prepend _acme-challenge. before your domain | |
[Sat May 20 01:13:18 UTC 2017] so the resulting subdomain will be: _acme-challenge.example.com | |
[Sat May 20 01:13:18 UTC 2017] Add the following TXT record: | |
[Sat May 20 01:13:18 UTC 2017] Domain: '_acme-challenge.www.example.com' | |
[Sat May 20 01:13:18 UTC 2017] TXT value: '2ALopkCJmIZiI11_2Ut7s729U0mpVkgl8GfTtT_ZitU' | |
[Sat May 20 01:13:18 UTC 2017] Please be aware that you prepend _acme-challenge. before your domain | |
[Sat May 20 01:13:18 UTC 2017] so the resulting subdomain will be: _acme-challenge.www.example.com | |
[Sat May 20 01:13:18 UTC 2017] Add the following TXT record: | |
[Sat May 20 01:13:18 UTC 2017] Domain: '_acme-challenge.cp.example.com' | |
[Sat May 20 01:13:18 UTC 2017] TXT value: 'n4fxVLPwuis5pPHkGkhB6qPuktsSYuRqjEY0JpCh-1k' | |
[Sat May 20 01:13:18 UTC 2017] Please be aware that you prepend _acme-challenge. before your domain | |
[Sat May 20 01:13:18 UTC 2017] so the resulting subdomain will be: _acme-challenge.cp.example.com | |
[Sat May 20 01:13:18 UTC 2017] Please add the TXT records to the domains, and retry again. | |
[Sat May 20 01:13:18 UTC 2017] Please add '--debug' or '--log' to check more details. | |
[Sat May 20 01:13:18 UTC 2017] See: https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh | |
root@certs:~/tmp # |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
I deleted all files in /var/db/acme | |
cd /usr/local/sbin | |
acme.sh --install \ | |
--home /var/db/acme \ | |
--config-home /var/db/acme/data \ | |
--certhome /var/db/acme/mycerts \ | |
--accountemail "dan@langille.org" \ | |
--accountkey /var/db/acme/myaccount.key \ | |
--accountconf /var/db/acme/myaccount.conf \ | |
--useragent "BSD Cabal HQ" | |
[Sat May 20 01:29:48 UTC 2017] Installing to /var/db/acme | |
[Sat May 20 01:29:48 UTC 2017] Installed to /var/db/acme/acme.sh | |
[Sat May 20 01:29:49 UTC 2017] No profile is found, you will need to go into /var/db/acme to use acme.sh | |
[Sat May 20 01:29:49 UTC 2017] Installing cron job | |
2 0 * * * /usr/local/sbin/acme.sh --cron --home "/var/db/acme" --config-home "/var/db/acme/data" > /dev/null | |
[Sat May 20 01:29:49 UTC 2017] Good, bash is found, so change the shebang to use bash as preferred. | |
/usr/local/sbin/acme.sh: cannot create /var/db/acme/acme.sh: Permission denied | |
/usr/local/sbin/acme.sh: cannot create /var/db/acme/acme.sh: Permission denied | |
That permission denied is: | |
[acme@certs ~]$ ls -l | |
total 178 | |
-r-xr-xr-x 1 acme acme 142724 May 20 01:30 acme.sh | |
-rw-r--r-- 1 acme acme 150 May 20 01:29 acme.sh.env | |
drwx------ 2 acme acme 3 May 20 01:29 data | |
-rw-r--r-- 1 acme acme 237 May 20 01:29 myaccount.conf | |
We don't want acme.sh in there anyway | |
rm acme.sh | |
Then alter the alias in this file to point to /usr/local/sbin/acme.sh | |
$ cat acme.sh.env | |
export LE_WORKING_DIR="/var/db/acme" | |
export LE_CONFIG_HOME="/var/db/acme/data" | |
alias acme.sh="/usr/local/sbin/acme.sh --config-home '/var/db/acme/data'" | |
At this point, we have: | |
[acme@certs ~]$ find . | |
. | |
./myaccount.conf | |
./acme.sh.env | |
./data | |
./data/account.conf | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[acme@certs ~]$ acme.sh --issue --dns -d example.com -d www.example.com -d cp.example.com | |
[Sat May 20 01:36:05 UTC 2017] Registering account | |
[Sat May 20 01:36:08 UTC 2017] Registered | |
[Sat May 20 01:36:09 UTC 2017] Update success. | |
[Sat May 20 01:36:09 UTC 2017] ACCOUNT_THUMBPRINT='cKk2PPACeTh1jkpSXl5DM0SLi4UXY6sbQBkagDjat00' | |
[Sat May 20 01:36:09 UTC 2017] Creating domain key | |
[Sat May 20 01:36:09 UTC 2017] Multi domain='DNS:www.example.com,DNS:cp.example.com' | |
[Sat May 20 01:36:09 UTC 2017] Getting domain auth token for each domain | |
[Sat May 20 01:36:09 UTC 2017] Getting webroot for domain='example.com' | |
[Sat May 20 01:36:09 UTC 2017] Getting new-authz for domain='example.com' | |
[Sat May 20 01:36:10 UTC 2017] The new-authz request is ok. | |
[Sat May 20 01:36:10 UTC 2017] Getting webroot for domain='www.example.com' | |
[Sat May 20 01:36:10 UTC 2017] Getting new-authz for domain='www.example.com' | |
[Sat May 20 01:36:10 UTC 2017] The new-authz request is ok. | |
[Sat May 20 01:36:10 UTC 2017] Getting webroot for domain='cp.example.com' | |
[Sat May 20 01:36:10 UTC 2017] Getting new-authz for domain='cp.example.com' | |
[Sat May 20 01:36:11 UTC 2017] The new-authz request is ok. | |
[Sat May 20 01:36:11 UTC 2017] Add the following TXT record: | |
[Sat May 20 01:36:11 UTC 2017] Domain: '_acme-challenge.example.com' | |
[Sat May 20 01:36:11 UTC 2017] TXT value: 'R2ZzeVpVgxJP1dXrHdEhGcvglpUNFD0ZRJrlrgmLe2o' | |
[Sat May 20 01:36:11 UTC 2017] Please be aware that you prepend _acme-challenge. before your domain | |
[Sat May 20 01:36:11 UTC 2017] so the resulting subdomain will be: _acme-challenge.example.com | |
[Sat May 20 01:36:11 UTC 2017] Add the following TXT record: | |
[Sat May 20 01:36:11 UTC 2017] Domain: '_acme-challenge.www.example.com' | |
[Sat May 20 01:36:11 UTC 2017] TXT value: 'gyHQMoVzLOnOUG8GsVNOS_OGdMvPYxz43yYUuntM7_k' | |
[Sat May 20 01:36:11 UTC 2017] Please be aware that you prepend _acme-challenge. before your domain | |
[Sat May 20 01:36:11 UTC 2017] so the resulting subdomain will be: _acme-challenge.www.example.com | |
[Sat May 20 01:36:11 UTC 2017] Add the following TXT record: | |
[Sat May 20 01:36:11 UTC 2017] Domain: '_acme-challenge.cp.example.com' | |
[Sat May 20 01:36:11 UTC 2017] TXT value: 'fuoqbQhAZwSqt_4P7l3GCsqsJ1s08JNkPlBbOCjj620' | |
[Sat May 20 01:36:11 UTC 2017] Please be aware that you prepend _acme-challenge. before your domain | |
[Sat May 20 01:36:11 UTC 2017] so the resulting subdomain will be: _acme-challenge.cp.example.com | |
[Sat May 20 01:36:11 UTC 2017] Please add the TXT records to the domains, and retry again. | |
[Sat May 20 01:36:11 UTC 2017] Please add '--debug' or '--log' to check more details. | |
[Sat May 20 01:36:11 UTC 2017] See: https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh | |
Now we have: | |
[acme@certs ~]$ find . | |
. | |
./mycerts | |
./mycerts/example.com | |
./mycerts/example.com/example.com.csr | |
./mycerts/example.com/example.com.csr.conf | |
./mycerts/example.com/example.com.key | |
./mycerts/example.com/example.com.conf | |
./myaccount.key | |
./.rnd | |
./myaccount.conf | |
./acme.sh.env | |
./data | |
./data/account.conf | |
./data/http.header | |
./data/ca | |
./data/ca/acme-v01.api.letsencrypt.org | |
./data/ca/acme-v01.api.letsencrypt.org/account.json | |
./data/ca/acme-v01.api.letsencrypt.org/ca.conf |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
The hint about dns_myapi.sh came from the bottom of https://github.com/Neilpang/acme.sh/tree/master/dnsapi | |
The clue for dns_myapi_rm came when running the test without that function defined. | |
[acme@certs ~]$ cat ~/.acme.sh/dns_myapi.sh | |
#!/bin/sh | |
dns_myapi_add() { | |
fulldomain="$1" | |
txtvalue="$2" | |
_info "Adding DNS ${fulldomain} ${txtvalue}" | |
echo "${fulldomain}. 60 IN TXT \"${txtvalue}\"" > "${LE_WORKING_DIR}/dnsextra/${fulldomain}" | |
return $? | |
} | |
dns_myapi_rm() { | |
return $? | |
} | |
[acme@certs ~]$ | |
also, moved dnsextra from ~/ to ~/.~/.acme.sh | |
Now when running, I get this: | |
[acme@certs ~]$ acme.sh --issue --dns dns_myapi -d www.example.com | |
[Sat May 20 02:10:10 UTC 2017] Single domain='www.example.com' | |
[Sat May 20 02:10:10 UTC 2017] Getting domain auth token for each domain | |
[Sat May 20 02:10:10 UTC 2017] Getting webroot for domain='www.example.com' | |
[Sat May 20 02:10:10 UTC 2017] Getting new-authz for domain='www.example.com' | |
[Sat May 20 02:10:12 UTC 2017] The new-authz request is ok. | |
[Sat May 20 02:10:12 UTC 2017] Found domain api file: /var/db/acme/.acme.sh/dns_myapi.sh | |
[Sat May 20 02:10:12 UTC 2017] Adding DNS _acme-challenge.www.example.com nmz6gMTrW3nhDg1aofnI64FjSn5cMDm5VgsTvVkwtPk | |
[Sat May 20 02:10:12 UTC 2017] Sleep 120 seconds for the txt records to take effect | |
### <-- you see a countdown here | |
[Sat May 20 02:12:15 UTC 2017] Verifying:www.example.com | |
[Sat May 20 02:12:18 UTC 2017] www.example.com:Verify error:DNS problem: NXDOMAIN looking up TXT for _acme-challenge.www.example.com | |
[Sat May 20 02:12:18 UTC 2017] Please add '--debug' or '--log' to check more details. | |
[Sat May 20 02:12:18 UTC 2017] See: https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh | |
[acme@certs ~]$ | |
Note what it created by using the dns_myapi script: | |
[acme@certs ~/.acme.sh]$ cat dnsextra/_acme-challenge.www.example.com | |
_acme-challenge.www.example.com. 60 IN TXT "nmz6gMTrW3nhDg1aofnI64FjSn5cMDm5VgsTvVkwtPk" | |
[acme@certs ~/.acme.sh]$ | |
NOTE that that the string on line 46 comes from line 32 | |
OK, next step, start pushing that stuff into DNS zone files. I will most likely do this from another jail, | |
where the dnsextra diretory is nullfs mounted into it. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
I have created another jail, dns-publish, on the same host and installed svn into it. | |
Now I have to figure out how to automate the push and pull of those DNS entries. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
on the jail host: | |
sudo zfs create system/data/dnsextra | |
sudo zfs set compression=lz4 system/data/dnsextra | |
to get the permissions right, from within the jail: | |
cd /var/db/acme/.acme.sh | |
mv dnsextra dnsextra.tmp | |
mkdir dnsextra | |
on the host: | |
sudo zfs set mountpoint=/usr/jails/certs//var/db/acme/.acme.sh/dnsextra system/data/dnsextra | |
back in the jail: | |
chown acme:acme dnsextra | |
cp -a dnsextra.tmp/* dnsextra/ | |
In the dns-publish jail, I create this directory for a mount point: | |
sudo mkdir /var/db/dnsextras | |
I added this entry to /etc/fstab.dns-publish and restarted that jail: | |
/usr/jails/certs//var/db/acme/.acme.sh/dnsextra /usr/jails/dns-publish/var/db/dnsextras nullfs ro,nosuid,noexec 0 0 | |
BOOM, we have dnsextras from the certs jail magically available (READ-ONL) in the dns-publish jail. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
On a typical day, we might want to renew multiple domains. What does that look like? | |
NOTE: I realized I should be using --staging here. i.e. not real certs. I've also started using my own domains. | |
$ acme.sh --staging --issue --dns dns_myapi -d www.langille.org -d dan.langille.org -d www.freebsddiary.org | |
[acme@certs ~]$ acme.sh --staging --issue --dns dns_myapi -d www.langille.org -d dan.langille.org -d www.freebsddiary.org | |
[Sat May 20 13:02:25 UTC 2017] Using stage api:https://acme-staging.api.letsencrypt.org | |
[Sat May 20 13:02:25 UTC 2017] Multi domain='DNS:dan.langille.org,DNS:www.freebsddiary.org' | |
[Sat May 20 13:02:25 UTC 2017] Getting domain auth token for each domain | |
[Sat May 20 13:02:25 UTC 2017] Getting webroot for domain='www.langille.org' | |
[Sat May 20 13:02:25 UTC 2017] Getting new-authz for domain='www.langille.org' | |
[Sat May 20 13:02:28 UTC 2017] The new-authz request is ok. | |
[Sat May 20 13:02:28 UTC 2017] Getting webroot for domain='dan.langille.org' | |
[Sat May 20 13:02:28 UTC 2017] Getting new-authz for domain='dan.langille.org' | |
[Sat May 20 13:02:29 UTC 2017] The new-authz request is ok. | |
[Sat May 20 13:02:29 UTC 2017] Getting webroot for domain='www.freebsddiary.org' | |
[Sat May 20 13:02:29 UTC 2017] Getting new-authz for domain='www.freebsddiary.org' | |
[Sat May 20 13:02:29 UTC 2017] The new-authz request is ok. | |
[Sat May 20 13:02:29 UTC 2017] Found domain api file: /var/db/acme/.acme.sh/dns_myapi.sh | |
[Sat May 20 13:02:29 UTC 2017] Adding DNS _acme-challenge.www.langille.org [REDACTED] | |
[Sat May 20 13:02:30 UTC 2017] Found domain api file: /var/db/acme/.acme.sh/dns_myapi.sh | |
[Sat May 20 13:02:30 UTC 2017] Adding DNS _acme-challenge.dan.langille.org [REDACTED] | |
[Sat May 20 13:02:30 UTC 2017] Found domain api file: /var/db/acme/.acme.sh/dns_myapi.sh | |
[Sat May 20 13:02:30 UTC 2017] Adding DNS _acme-challenge.www.freebsddiary.org [REDACTED] | |
[Sat May 20 13:02:30 UTC 2017] Sleep 120 seconds for the txt records to take effect | |
Looking on dns-publish, I see: | |
[dan@dns-publish:~] $ ls -l /var/db/dnsextras/ | |
total 2 | |
-rw-r--r-- 1 169 169 90 May 20 13:02 _acme-challenge.dan.langille.org | |
-rw-r--r-- 1 169 169 89 May 20 02:10 _acme-challenge.www.example.com | |
-rw-r--r-- 1 169 169 94 May 20 13:02 _acme-challenge.www.freebsddiary.org | |
-rw-r--r-- 1 169 169 90 May 20 13:02 _acme-challenge.www.langille.org | |
[dan@dns-publish:~] $ | |
Good, so the domain name can be found, sort of, from that. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
How do I get a list of domain names I'm handling? I already have the zone files, so how about this. | |
Assuming the directory contains: | |
[dan@dns-publish:~/DNS] $ ls bsdcan* freebsddiary.* fresh* | |
bsdcan.ca.db bsdcan.org.db freebsddiary.org.db freshports.org.db | |
bsdcan.com.db freebsddiary.com.db freshports.net.db freshsource.org.db | |
Then this script: | |
#!/bin/sh | |
DNSDIR=${HOME}/DNS | |
ZONEFILES=`/bin/ls ${DNSDIR}/*.db` | |
ZONEFILESUFFIX=".db" | |
DOMAINS="" | |
for domain in ${ZONEFILES} | |
do | |
echo processing ${domain} | |
# remove the leading directory name | |
FILENAME=`/usr/bin/basename ${domain}` | |
echo "got filename = '${FILENAME}'" | |
# NOTE the space at the end of the string to separate the domains. | |
# The final result will have a trailing space. | |
DOMAINS="${DOMAINS}`/usr/bin/basename ${FILENAME} ${ZONEFILESUFFIX}` " | |
done | |
echo ${DOMAINS} | |
produced this: | |
[dan@dns-publish:~/DNS] $ ~/bin/list-domains | |
processing /usr/home/dan/DNS/bsdcan.ca.db | |
got filename = 'bsdcan.ca.db' | |
processing /usr/home/dan/DNS/bsdcan.com.db | |
got filename = 'bsdcan.com.db' | |
processing /usr/home/dan/DNS/bsdcan.org.db | |
got filename = 'bsdcan.org.db' | |
processing /usr/home/dan/DNS/freebsddiary.com.db | |
got filename = 'freebsddiary.com.db' | |
processing /usr/home/dan/DNS/freebsddiary.org.db | |
got filename = 'freebsddiary.org.db' | |
processing /usr/home/dan/DNS/freshports.net.db | |
got filename = 'freshports.net.db' | |
processing /usr/home/dan/DNS/freshports.org.db | |
got filename = 'freshports.org.db' | |
processing /usr/home/dan/DNS/freshsource.org.db | |
got filename = 'freshsource.org.db' | |
bsdcan.ca bsdcan.com bsdcan.org freebsddiary.com freebsddiary.org freshports.net freshports.org freshsource.org | |
From there, it's easy to then see what file name extensions to look for. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From this script: | |
[dan@dns-publish:~/DNS] $ cat ~/bin/list-waiting-requests | |
#!/bin/sh | |
DNS_DIR=${HOME}/DNS | |
CHALLENGE_DIR="/var/db/dnsextras" | |
ZONE_FILES=`/bin/ls ${DNS_DIR}/*.db` | |
# for specific testing | |
#ZONE_FILES=`/bin/ls ${DNS_DIR}/bsdcan* ${DNS_DIR}/freebsddiary.* ${DNS_DIR}/fresh*` | |
ZONE_FILE_SUFFIX=".db" | |
DOMAINS="" | |
for domain in ${ZONE_FILES} | |
do | |
# remove the leading directory name | |
FILENAME=`/usr/bin/basename ${domain}` | |
# NOTE the space at the end of the string to separate the domains. | |
# The final result will have a trailing space. | |
DOMAINS="${DOMAINS}`/usr/bin/basename ${FILENAME} ${ZONE_FILE_SUFFIX}` " | |
done | |
# echo ${DOMAINS} | |
for domain in ${DOMAINS} | |
do | |
CHALLENGES=`find ${CHALLENGE_DIR} -name _acme-challenge.*${domain}` | |
if [ ! -z "${CHALLENGES}" ] | |
then | |
for challenge in ${CHALLENGES} | |
do | |
challenge_file=`/usr/bin/basename ${challenge}` | |
echo ${challenge} is a request for domain ${domain} | |
done | |
fi | |
done | |
I get: | |
$ ~/bin/list-waiting-requests | |
/var/db/dnsextras/_acme-challenge.www.freebsddiary.org is a request for domain freebsddiary.org | |
/var/db/dnsextras/_acme-challenge.dan.langille.org is a request for domain langille.org | |
/var/db/dnsextras/_acme-challenge.www.langille.org is a request for domain langille.org |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Next step, append the data to the zone files. The amended script is: | |
$ cat ~/bin/append-to-zone-files | |
#!/bin/sh | |
DNS_DIR=${HOME}/DNS | |
CHALLENGE_DIR="/var/db/dnsextras" | |
CHALLENGE_PREFIX="_acme-challenge" | |
ZONE_FILES=`/bin/ls ${DNS_DIR}/*.db` | |
BASENAME="/usr/bin/basename" | |
FIND="/usr/bin/find" | |
GREP="/usr/bin/grep" | |
LS="/bin/ls" | |
# for specific testing | |
#ZONE_FILES=`${LS} ${DNS_DIR}/bsdcan* ${DNS_DIR}/freebsddiary.* ${DNS_DIR}/fresh*` | |
ZONE_FILE_SUFFIX=".db" | |
DOMAINS="" | |
for domain in ${ZONE_FILES} | |
do | |
# remove the leading directory name | |
FILENAME=`${BASENAME} ${domain}` | |
# NOTE the space at the end of the string to separate the domains. | |
# The final result will have a trailing space. | |
DOMAINS="${DOMAINS}`${BASENAME} ${FILENAME} ${ZONE_FILE_SUFFIX}` " | |
done | |
# echo ${DOMAINS} | |
for domain in ${DOMAINS} | |
do | |
CHALLENGES=`${FIND} ${CHALLENGE_DIR} -name ${CHALLENGE_PREFIX}.*${domain}` | |
if [ ! -z "${CHALLENGES}" ] | |
then | |
for challenge in ${CHALLENGES} | |
do | |
challenge_file=`${BASENAME} ${challenge}` | |
echo ${challenge_file} is a request for domain ${domain} | |
# append the challenge to the one file | |
# grep 'IN TXT' /var/db/dnsextras/_acme-challenge.www.freebsddiary.org | |
${GREP} 'IN TXT' ${challenge} >> ${DNS_DIR}/${domain}.db | |
done | |
fi | |
done | |
[dan@dns-publish:~/bin] $ | |
The results are: | |
[dan@dns-publish:~/bin] $ svn di ~/DNS/ | |
Index: /usr/home/dan/DNS/freebsddiary.org.db | |
=================================================================== | |
--- /usr/home/dan/DNS/freebsddiary.org.db (revision 4165) | |
+++ /usr/home/dan/DNS/freebsddiary.org.db (working copy) | |
@@ -55,3 +55,4 @@ | |
; | |
freebsddiary.org. IN TXT "v=spf1 ip4:64.90.182.103 ip4:162.208.116.77 ?all" | |
freebsddiary.org. IN SPF "v=spf1 ip4:64.90.182.103 ip4:162.208.116.77 ?all" | |
+_acme-challenge.www.freebsddiary.org. 60 IN TXT "9gfHxsSn1ajI1hAf7T8K6DMBRALYefbto0kRKQuhSbY" | |
Index: /usr/home/dan/DNS/langille.org.db | |
=================================================================== | |
--- /usr/home/dan/DNS/langille.org.db (revision 4165) | |
+++ /usr/home/dan/DNS/langille.org.db (working copy) | |
@@ -57,3 +57,5 @@ | |
; clavin1 clavin2 zuul supernew tallboy gelt | |
langille.org. IN TXT "v=spf1 ip4:162.208.116.86 ip4:199.233.228.197 ip4:162.208.116.64/26 ip4:206.127.23.226/26 ip4:199.233.228.194/29 ip4:64.90.182.98/27 include:_spf.google.com ~all" | |
langille.org. IN SPF "v=spf1 ip4:162.208.116.86 ip4:199.233.228.197 ip4:162.208.116.64/26 ip4:206.127.23.226/26 ip4:199.233.228.194/29 ip4:64.90.182.98/27 include:_spf.google.com ~all" | |
+_acme-challenge.dan.langille.org. 60 IN TXT "Yf8YKvyrrPR6j-PmXttsfLtKqmeT7nxMs8cTdrw8Axg" | |
+_acme-challenge.www.langille.org. 60 IN TXT "xa4I5BUsvkxYiIr9TRITOCt7yjlx8bftKuTwu23iHq8" | |
This looks right to me. | |
The problem is removing challenge records which are no longer required. That could be a simple sed command. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
At http://www.linuxquestions.org/questions/programming-9/shell-script-bind-related-654894-print/ I found this script: | |
$ cat ~/bin/bump_serial.sh | |
#!/bin/sh | |
/usr/bin/perl -i.bak -pe 'BEGIN {chomp ($now=qx/date +%Y%m%d/)}; | |
/(\d{8})(\d{2})/ and do { | |
$serial = ($1 eq $now ? $2+1 : 0); | |
s/\d{8}(\d{2})/sprintf "%8d%02d",$now,$serial/e; | |
}' $1 | |
Feel free to do this without perl... | |
Running it the first time, it changed the serial to today's date: | |
[dan@dns-publish:~/DNS] $ ~/bin/bump_serial.sh langille.org.db | |
[dan@dns-publish:~/DNS] $ svn di langille.org.db | |
Index: langille.org.db | |
=================================================================== | |
--- langille.org.db (revision 4165) | |
+++ langille.org.db (working copy) | |
@@ -1,7 +1,7 @@ | |
$TTL 600 | |
$ORIGIN org. | |
langille IN SOA muster.unixathome.org. soa.unixathome.org. ( | |
- 2017042100 ; Serial | |
+ 2017052000 ; Serial | |
10800 ; Refresh | |
1800 ; Retry | |
1209600 ; Expire | |
@@ -57,3 +57,5 @@ | |
; clavin1 clavin2 zuul supernew tallboy gelt | |
langille.org. IN TXT "v=spf1 ip4:162.208.116.86 ip4:199.233.228.197 ip4:162.208.116.64/26 ip4:206.127.23.226/26 ip4:199.233.228.194/29 ip4:64.90.182.98/27 include:_spf.google.com ~all" | |
langille.org. IN SPF "v=spf1 ip4:162.208.116.86 ip4:199.233.228.197 ip4:162.208.116.64/26 ip4:206.127.23.226/26 ip4:199.233.228.194/29 ip4:64.90.182.98/27 include:_spf.google.com ~all" | |
+_acme-challenge.dan.langille.org. 60 IN TXT "Yf8YKvyrrPR6j-PmXttsfLtKqmeT7nxMs8cTdrw8Axg" | |
+_acme-challenge.www.langille.org. 60 IN TXT "xa4I5BUsvkxYiIr9TRITOCt7yjlx8bftKuTwu23iHq8" | |
running it the second time, it increments by one: | |
[dan@dns-publish:~/DNS] $ ~/bin/bump_serial.sh langille.org.db | |
[dan@dns-publish:~/DNS] $ ~/bsvn dingille.org.db | |
Index: langille.org.db | |
=================================================================== | |
--- langille.org.db (revision 4165) | |
+++ langille.org.db (working copy) | |
@@ -1,7 +1,7 @@ | |
$TTL 600 | |
$ORIGIN org. | |
langille IN SOA muster.unixathome.org. soa.unixathome.org. ( | |
- 2017042100 ; Serial | |
+ 2017052001 ; Serial | |
10800 ; Refresh | |
1800 ; Retry | |
1209600 ; Expire | |
@@ -57,3 +57,5 @@ | |
; clavin1 clavin2 zuul supernew tallboy gelt | |
langille.org. IN TXT "v=spf1 ip4:162.208.116.86 ip4:199.233.228.197 ip4:162.208.116.64/26 ip4:206.127.23.226/26 ip4:199.233.228.194/29 ip4:64.90.182.98/27 include:_spf.google.com ~all" | |
langille.org. IN SPF "v=spf1 ip4:162.208.116.86 ip4:199.233.228.197 ip4:162.208.116.64/26 ip4:206.127.23.226/26 ip4:199.233.228.194/29 ip4:64.90.182.98/27 include:_spf.google.com ~all" | |
+_acme-challenge.dan.langille.org. 60 IN TXT "Yf8YKvyrrPR6j-PmXttsfLtKqmeT7nxMs8cTdrw8Axg" | |
+_acme-challenge.www.langille.org. 60 IN TXT "xa4I5BUsvkxYiIr9TRITOCt7yjlx8bftKuTwu23iHq8" | |
This seems to do what is required. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
At present, my DNS is in stand alone zone files. | |
With acme DNS challenges for LetsEncrypt, a new approach is needed. | |
Peter Wemm did this: | |
cat soa/freebsd.org primary/freebsd.org extra/freebsd.org.txt > unsigned/freebsd.org | |
I think my new approach will involve two repos. One where I do manual changes to the | |
zones. The other will be what is automatically pushed to DNS servers after assembly | |
of serial and extra bits. | |
I won't have a separate SOA file like above, but just the extra bit ... | |
This should just work. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
I have branched my main DNS into a dns-01 branch. Updates to this branch will be exported to DNS servers. | |
With this slightly modified code, I copy from main DNS, append challenges, then bump serial: | |
[dan@dns-publish:~] $ cat ~/bin/append-to-zone-files | |
#!/bin/sh | |
# where we get pure DNS files | |
DNS_SRC_DIR="${HOME}/DNS" | |
# where we put the dns stuff for the servers to svn up later | |
DNS01_DST_DIR="${HOME}/dns-01" | |
# where do we find the acme challegne files | |
CHALLENGE_DIR="/var/db/dnsextras" | |
# what do the challenge files look like? | |
CHALLENGE_PREFIX="_acme-challenge" | |
ZONE_FILE_SUFFIX=".db" | |
# list of zone files we support | |
ZONE_FILES=`/bin/ls ${DNS_SRC_DIR}/*${ZONE_FILE_SUFFIX}` | |
# various tools we use | |
BASENAME="/usr/bin/basename" | |
FIND="/usr/bin/find" | |
GREP="/usr/bin/grep" | |
LS="/bin/ls" | |
BUMP_SERIAL="${HOME}/bin/bump_serial.sh" | |
# for specific testing | |
#ZONE_FILES=`${LS} ${DNS_SRC_DIR}/bsdcan* ${DNS_SRC_DIR}/freebsddiary.* ${DNS_SRC_DIR}/fresh*` | |
DOMAINS="" | |
for domain in ${ZONE_FILES} | |
do | |
# remove the leading directory name | |
FILENAME=`${BASENAME} ${domain}` | |
# NOTE the space at the end of the string to separate the domains. | |
# The final result will have a trailing space. | |
DOMAINS="${DOMAINS}`${BASENAME} ${FILENAME} ${ZONE_FILE_SUFFIX}` " | |
done | |
# echo ${DOMAINS} | |
for domain in ${DOMAINS} | |
do | |
zone_file="${domain}${ZONE_FILE_SUFFIX}" | |
CHALLENGES=`${FIND} ${CHALLENGE_DIR} -name ${CHALLENGE_PREFIX}.*${domain}` | |
if [ ! -z "${CHALLENGES}" ] | |
then | |
for challenge in ${CHALLENGES} | |
do | |
challenge_file=`${BASENAME} ${challenge}` | |
echo ${challenge_file} is a request for domain ${domain} | |
# append the challenge to the one file | |
# grep 'IN TXT' /var/db/dnsextras/_acme-challenge.www.freebsddiary.org | |
cat ${DNS_SRC_DIR}/${zone_file} > ${DNS01_DST_DIR}/${zone_file} | |
${GREP} 'IN TXT' ${challenge} >> ${DNS01_DST_DIR}/${zone_file} | |
${BUMP_SERIAL} ${DNS01_DST_DIR}/${zone_file} | |
done | |
fi | |
done | |
See the diffs here: | |
[dan@dns-publish:~/dns-01] $ ~/bin/append-to-zone-files | |
_acme-challenge.www.freebsddiary.org is a request for domain freebsddiary.org | |
_acme-challenge.dan.langille.org is a request for domain langille.org | |
_acme-challenge.www.langille.org is a request for domain langille.org | |
[dan@dns-publish:~/dns-01] $ cd - | |
/usr/home/dan/DNS | |
[dan@dns-publish:~/DNS] $ svn di | |
[dan@dns-publish:~/DNS] $ cd - | |
/usr/home/dan/dns-01 | |
[dan@dns-publish:~/dns-01] $ svn di | |
Index: freebsddiary.org.db | |
=================================================================== | |
--- freebsddiary.org.db (revision 4166) | |
+++ freebsddiary.org.db (working copy) | |
@@ -1,7 +1,7 @@ | |
$TTL 600 | |
$ORIGIN org. | |
freebsddiary IN SOA muster.unixathome.org. soa.unixathome.org. ( | |
- 2015123800 ; Serial | |
+ 2017052000 ; Serial | |
10800 ; Refresh | |
1800 ; Retry | |
1209600 ; Expire | |
@@ -55,3 +55,4 @@ | |
; | |
freebsddiary.org. IN TXT "v=spf1 ip4:64.90.182.103 ip4:162.208.116.77 ?all" | |
freebsddiary.org. IN SPF "v=spf1 ip4:64.90.182.103 ip4:162.208.116.77 ?all" | |
+_acme-challenge.www.freebsddiary.org. 60 IN TXT "9gfHxsSn1ajI1hAf7T8K6DMBRALYefbto0kRKQuhSbY" | |
Index: langille.org.db | |
=================================================================== | |
--- langille.org.db (revision 4166) | |
+++ langille.org.db (working copy) | |
@@ -1,7 +1,7 @@ | |
$TTL 600 | |
$ORIGIN org. | |
langille IN SOA muster.unixathome.org. soa.unixathome.org. ( | |
- 2017042100 ; Serial | |
+ 2017052000 ; Serial | |
10800 ; Refresh | |
1800 ; Retry | |
1209600 ; Expire | |
@@ -57,3 +57,4 @@ | |
; clavin1 clavin2 zuul supernew tallboy gelt | |
langille.org. IN TXT "v=spf1 ip4:162.208.116.86 ip4:199.233.228.197 ip4:162.208.116.64/26 ip4:206.127.23.226/26 ip4:199.233.228.194/29 ip4:64.90.182.98/27 include:_spf.google.com ~all" | |
langille.org. IN SPF "v=spf1 ip4:162.208.116.86 ip4:199.233.228.197 ip4:162.208.116.64/26 ip4:206.127.23.226/26 ip4:199.233.228.194/29 ip4:64.90.182.98/27 include:_spf.google.com ~all" | |
+_acme-challenge.www.langille.org. 60 IN TXT "xa4I5BUsvkxYiIr9TRITOCt7yjlx8bftKuTwu23iHq8" | |
[dan@dns-publish:~/dns-01] $ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
I think I have a better idea for dns-01. | |
At present the flow is: | |
certs jail | |
- runs acme.sh script to create requests for new certs and dns-01 _acme-challenge TXT records | |
dns-publish jail | |
- has nullfs mounted directory with _acme-challenge TXT records | |
- svn up's the DNS files to make sure it has the latest | |
- adds in any _acme-challenge TXT records | |
- puts results in DSTDIR | |
dns-rsync jail | |
- has nullfs mounted directory with DNS records including _acme-challenge TXT records from previous step | |
- DNS master ryncs from this directory, notices any changes, and issues a reload/restart | |
I decided not to go with svn because it was getting awkward/difficult to secure it well enough. | |
With this solution, rsync is the only tool which can run, and the source data cannot be altered as it's nullfs mounted. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@koobs suggested this (http://twitter.com/koobs/status/866118344587358208) | |
$ mkdir test | |
$ cd test | |
$ touch a b | |
$ ls -l | |
total 0 | |
-rw-r--r-- 1 dan staff 0 May 21 10:04 a | |
-rw-r--r-- 1 dan staff 0 May 21 10:04 b | |
# point current at a | |
$ ln -s a current | |
$ ls -l | |
total 4 | |
-rw-r--r-- 1 dan staff 0 May 21 10:04 a | |
-rw-r--r-- 1 dan staff 0 May 21 10:04 b | |
lrwxr-xr-x 1 dan staff 1 May 21 10:05 current -> a | |
# When time comes to create a new set of zone files | |
# create a new directory | |
# copy zone files there | |
# update the symlink | |
$ touch c | |
$ ln -sf c current | |
$ ls -l | |
total 4 | |
-rw-r--r-- 1 dan staff 0 May 21 10:04 a | |
-rw-r--r-- 1 dan staff 0 May 21 10:04 b | |
-rw-r--r-- 1 dan staff 0 May 21 10:07 c | |
lrwxr-xr-x 1 dan staff 1 May 21 10:07 current -> c | |
# BOOM | |
# This step is atomic. Thank you koobs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
I was wondering how to detect which files are updated during an rsync. I found the solution on the man page: --out-format | |
$ rsync -a --out-format="updated: %n" -zz -e "ssh -i ~/.ssh/id_ed25519" muster@10.55.0.54: . | |
updated: bsdcan.ca.db |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment