Merge PR#54: Friendly loop indexes when setting adduser options
[noc.git] / doc / ACME / LAN.md
1 [[!meta title="Certificates for services on our LAN"]]
2
3 # Let's Encrypt certs for services on our LAN
4
5 We use [Let's Encrypt] to acquire and renew certificates for basically
6 all services.  However, some services are only exposed on the LAN, and
7 so certificate acquisition becomes a bit trickier.
8
9 [ACME], the protocol for interacting with [Let's Encrypt],
10 supports [DNS-01] authorization, so we can use that to acquire certs
11 without exposing services to the Internet.
12
13 [Let's Encrypt]: https://letsencrypt.org/
14 [DNS-01]: https://tools.ietf.org/html/draft-ietf-acme-acme-07#section-8.5
15 [ACME]:   https://tools.ietf.org/html/draft-ietf-acme-acme-07
16
17
18 ## Overview
19
20 Let's say we need certificates for `metrics.mgmt.realraum.at`
21
22 `metrics.mgmt` will send DNS updates to `gw`.  It only needs TXT records for
23  `_acme-challenge.metrics.mgmt.realraum.at` and they will be authenticated using
24  HMAC-SHA256.
25
26
27 ## Bind9
28
29 ### Generating a TSIG key
30
31 On the system running the services:
32
33 - Install `bind9utils` to have the not-so-aptly named `dnssec-keygen` tool.
34 - As `root`, generate an HMAC-SHA256 key and make it readable by `acme`:
35
36         # dnssec-keygen -K /etc/acme -a HMAC-SHA256 -b 256 \
37                         -n USER metrics.mgmt.realraum.at.
38         Kmetrics.mgmt.realraum.at.+163+06888
39
40         # chown root:acme /etc/acme/K*
41         # chmod 0440 /etc/acme/K*
42
43 - Lookup the key, as we will need to put it in the NS' configuration
44
45         # cat /etc/acme/Kmetrics.mgmt.realraum.at.+163+06888.private
46         Private-key-format: v1.3
47         Algorithm: 163 (HMAC_SHA256)
48         Key: FG4v6Eya7utyJ1GxXm019kYBawN+jvfEWCC/7lIgraQ=
49         Bits: AAA=
50         Created: 20171022235329
51         Publish: 20171022235329
52         Activate: 20171022235329
53
54
55 _Note:_ I selected HMAC-SHA256 because `gw.realraum.at` is running an
56         obsolete version of Bind9 that only supports HMAC or RSA.
57         In principle, the setup should be similar for asymetric signatures.
58
59
60 ### Adding the keys
61
62 On `gw.realraum.at`:
63
64 - `/etc/bind/keys.conf` should exist and be accessible to `root` and `bind`:
65
66         # touch           /etc/bind/keys.conf
67         # chown root:bind /etc/bind/keys.conf
68         # chmod 0640      /etc/bind/keys.conf
69
70 - Check that `keys.conf` is included from `named.conf.local`:
71
72         # head /etc/bind/named.conf.local
73         include "/etc/bind/zones.rfc1918";
74         include "/etc/bind/keys.conf";
75         [...]
76
77 - Add the key descriptor to `keys.conf`:
78
79         # cat >> /etc/bind/keys.conf
80         key metrics.mgmt.realraum.at. {
81             algorithm HMAC-SHA256;
82             secret "4QZWZsLagxXaoBCAxDqbSZmoSjN5qJvZviadrPXkmvU=";
83         }
84
85
86 ### Setting up DNS updates
87
88 - Edit the zone description in `named.conf.local` to allow updates:
89
90         zone "realraum.at" {
91             type master;
92             file "/etc/bind/db.realraum.at";
93             [...]
94
95             update-policy {
96                 grant metrics.mgmt.realraum.at. name _acme-challenge.metrics.mgmt.realraum.at. TXT;
97             };
98         };
99
100 - The update journal for the zone should be writeable by `bind`:
101
102         # touch           /etc/bind/db.realraum.at.jnl
103         # chown root:bind /etc/bind/db.realraum.at.jnl
104         # chmod 0660      /etc/bind/db.realraum.at.jnl
105
106 - Restart `bind`
107
108
109 ## [acmetool]
110
111 ### Installation
112
113 - `acmetool` is available from the official repos starting with Stretch.
114 - For earlier releases, Christian [has a package](https://build.spreadspace.org/)
115
116 Start with a working, [rootless acmetool setup].
117
118 _Note:_ On Debian, _hooks_ are located in `/etc/acme/hooks`, instead of
119         `/usr/lib/acme/hooks` or `/usr/libexec/acme/hooks`.
120
121 [acmetool]: https://hlandau.github.io/acme/
122 [rootless acmetool setup]: https://hlandau.github.io/acme/userguide#annex-root-configured-non-root-operation
123
124
125 ### Setting up the hook
126
127 An example hook using `nsupdate`
128 [already ships](https://github.com/hlandau/acme/blob/master/_doc/dns.hook)
129 with acmetool.
130
131 - Install `dnsutils` (contains `nsupdate`)
132 - Link the hook from the documentation:
133
134         # ln -s ../../../usr/share/doc/acmetool/examples/dns.hook /etc/acme/
135
136 - Write the configuration for it:
137
138         # cat > /etc/default/acme-dns
139         NSUPDATE_ARGS="-k /etc/acme/Kmetrics.mgmt.realraum.at.+163+06888.key"
140
141         nsupdate_cmds() {
142             echo server 192.168.33.1
143         }
144
145 - Test
146
147         # sudo -u acme /etc/acme/hooks/dns.hook challenge-dns-start \
148           foo.example.com "" "foobar"
149         # sudo -u acme /etc/acme/hooks/dns.hook challenge-dns-start \
150           foo.example.com "" "foobar"
151
152   If either of those commands fail with an error,
153   check the DNS traffic (`tcpdump -vvv port 53`)
154
155
156 ### Certificate acquisition
157
158 Once everything is setup, getting a certificate from Let's Encrypt
159 is quite easy:
160
161         # sudo -u acme acmetool want metrics.mgmt.realraum.at
162
163
164 ### Testing automated removal
165
166 Last thing, you should check that automatic renewal is setup and works:
167
168 - Is the cron job in place?
169
170         # crontab -u acme -l
171         
172         37 13 * * * /usr/bin/acmetool --batch reconcile
173
174 - Is the default hook for reloading services in place?
175   If you delete the certificate and key, then run `acmetool`,
176   do your services use the new certificate?
177
178         # [check the service's certificate fingerprint, with openssl s_client]
179         # rm -rf /var/lib/acme/keys/*
180         # sudo -u acme acmetool --batch reconcile
181         # [check the service's certificate fingerprint, they should differ]