Certificates for other hosts: jarl cert get
jarld obtains and renews a certificate for another host; the host asks
for it with one command, waits, downloads it when it is newer than its
copy and runs a hook with the paths in JARL_CERT_* variables.
- Certificates have an owner user; another user can't take the name.
An existing one is obtained again only when a name is added or
removed. A new certificates grant (names=) says which names a user
may have; it is never part of "*". Users may own
certificates.max_per_user certificates (10) or their own cert_limit.
- POST /certificates/{name}/request; owners may list, show, export and
delete theirs; keys only over HTTPS, the socket or loopback; every
download is recorded and shown as "Pulled by".
- CLI: jarl cert get (saved settings, all saved when no name), cert
saved, cert forget, cert schedule (daily systemd timer, Linux, root).
- Migration 14. Tests: server, auth, and e2e against Pebble.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b4bb99b482
commit
9db76a113c
29 files changed
+1568
-40
No files matched your search
+75
-5
@@ -231,13 +231,83 @@ jarl cert export mail --part bundle > /etc/haproxy/mail.pem
|
||||
|
||||
The parts are `fullchain` (the certificate and its chain), `cert` (the
|
||||
certificate alone), `key` and `bundle` (the key, then the chain, in one
|
||||
file, as HAProxy wants). Only administrators can export, and every export
|
||||
of the key is in the audit log (`certificate.export_key`).
|
||||
file, as HAProxy wants). Administrators can export any certificate, and
|
||||
the owner of a certificate for another host (below) their own. Every
|
||||
export of the key is in the audit log (`certificate.export_key`), and a key
|
||||
only goes over HTTPS, the local socket, or to this server itself.
|
||||
|
||||
Jarl renews the certificate, not your copy: export it again after each
|
||||
renewal (`jarl cert show` says when that is), for example from a daily
|
||||
cron job. A program on this server can instead read the files Jarl writes
|
||||
for named (use `dns`), which Jarl keeps current.
|
||||
renewal (`jarl cert show` says when that is). For another host, `jarl
|
||||
cert get` (below) does that for you. A program on this server can instead
|
||||
read the files Jarl writes for named (use `dns`), which Jarl keeps current.
|
||||
|
||||
## Certificates for other hosts
|
||||
|
||||
`jarl cert get` gets a certificate onto another host (a mail server, a
|
||||
reverse proxy) with one command: jarld obtains it from the CA and renews
|
||||
it, answering the challenges in its own zones as for its own certificates;
|
||||
the host asks for it, waits until it is there, downloads it and runs a
|
||||
hook. The host needs only a token, not an ACME client or access to DNS.
|
||||
|
||||
**On Jarl**, as an administrator, give the hosts a user and a token each:
|
||||
|
||||
```sh
|
||||
jarl user create hosts --no-password --grant "certificates:write names=*.adbraun.lol"
|
||||
jarl token create mx --user hosts # one token per host
|
||||
```
|
||||
|
||||
The `certificates` grant says which names the user may have certificates
|
||||
for. It is never part of `*`, so `operator` and `readonly` users can't
|
||||
get certificates (or download keys) unless you add one. A certificate
|
||||
belongs to the user that asked for it: its tokens can download it, other
|
||||
users can't take its name or see it, and the certificates Jarl uses
|
||||
itself are the administrators'. Hosts that should share certificates use
|
||||
the same user (each with its own token, so you can revoke one host
|
||||
alone); hosts that shouldn't, use different users. A user may own
|
||||
`certificates.max_per_user` certificates (10 by default), or what `jarl
|
||||
user update NAME --cert-limit N` (or the user's form) sets.
|
||||
|
||||
**On the host:**
|
||||
|
||||
```sh
|
||||
export JARL_SERVER=https://jarl.adbraun.lol:8053 JARL_TOKEN=@/root/jarl.token
|
||||
jarl cert get mail -d mail.adbraun.lol -d smtp.adbraun.lol --hook 'systemctl reload postfix dovecot'
|
||||
sudo jarl cert schedule # a daily systemd timer runs 'jarl cert get'
|
||||
jarl cert saved # what this host has, and when it expires
|
||||
```
|
||||
|
||||
* **Asking again** with the same names returns the certificate jarld has:
|
||||
nothing is obtained, nothing is downloaded until jarld renews it.
|
||||
**Adding or removing a name** gets a new certificate. A different
|
||||
`--key-type` alone doesn't; delete the certificate for that.
|
||||
* **Files**, in `--dir` (default `/etc/jarl/certs/NAME` as root, `./NAME`
|
||||
otherwise): `cert.pem`, `chain.pem` (the intermediates),
|
||||
`fullchain.pem`, `privkey.pem` (mode 600) and `jarl-cert.json` (serial,
|
||||
expiry, when it was fetched). Each file is replaced at once, never
|
||||
half written. The key is checked against the certificate before
|
||||
anything is written.
|
||||
* **Saved settings**: the names, `--dir`, `--hook`, the server and the
|
||||
token are saved in `/etc/jarl/cert-get/NAME.json` (as root;
|
||||
`~/.config/jarl/cert-get` otherwise), readable only by their owner.
|
||||
`jarl cert get` without a name does every saved certificate. A token
|
||||
given as `@FILE` is saved as that reference, not copied. `jarl cert
|
||||
forget NAME` stops getting one (`--delete` deletes it on jarld too).
|
||||
* **The hook** runs with `sh` after new files are written, with
|
||||
`JARL_CERT_NAME`, `JARL_CERT_DIR`, `JARL_CERT_CERT`, `JARL_CERT_CHAIN`,
|
||||
`JARL_CERT_FULLCHAIN`, `JARL_CERT_KEY`, `JARL_CERT_DOMAINS`,
|
||||
`JARL_CERT_SERIAL`, `JARL_CERT_NOT_AFTER` and `JARL_CERT_RENEWED` (1 when
|
||||
it replaced an older certificate). If it fails, `jarl cert get` exits
|
||||
non-zero and runs it again next time. It has 5 minutes.
|
||||
* **`jarl cert schedule`** (Linux with systemd, as root) writes
|
||||
`/etc/systemd/system/jarl-cert-get.service` and `.timer`, which run
|
||||
`jarl cert get` daily at a random time within the hour after midnight,
|
||||
and catch up after the host was off. `--remove` takes them away. On
|
||||
other systems, run `jarl cert get` daily with their scheduler.
|
||||
|
||||
**On the Certificates page**, the administrators see each certificate's
|
||||
owner and who downloaded it: the token, from where, when, and whether
|
||||
that host has the current certificate or hasn't fetched the renewed one
|
||||
yet. `jarl cert show NAME` says the same.
|
||||
|
||||
## Security notes
|
||||
|
||||
|
||||
Reference in new issue
Block a user