-
anarcat authored
That scenario is more complex and has more implications than just renewing the key. It *also* includes cert revocation so it's implicit as well.
anarcat authoredThat scenario is more complex and has more implications than just renewing the key. It *also* includes cert revocation so it's implicit as well.
letsencrypt.mdwn 5.24 KiB
[[!toc levels=3]]
# How to get an X.509 certificate for your new name
## The letsencrypt-domains git repository
If not already done, clone git repos letsencrypt-domains and
backup-keys.
git clone ssh://git@git-rw.torproject.org/admin/letsencrypt-domains
cd letsencrypt-domains
git clone pauli.torproject.org:/srv/puppet.torproject.org/git/tor-backup-keys.git backup-keys
## Add your new name
Add your domain name and optional alternative names (`SAN`) to the
`domains` file:
$EDIT domains
## Public key pinning
If you do not want to use HPKP, skip this section.
Generate backup [HPKP][]:
[HPKP]: https://en.wikipedia.org/wiki/HTTP_Public_Key_Pinning
./bin/manage-backup-keys create
See `tor-passwords/000-backup-keys` for the passphrase when prompted.
The private key is a backup RSA certificate that can be used to rotate
HTTPS certificates in case of a compromise, while respecting the pins
sent as `Public-Key-Pins` headers.
Push the new key to the backup-keys repo:
cd backup-keys
git status
git add $yourfiles
git commit
git push
cd ..
## Push the updated domain list to the letsencrypt-domains repo
git diff domains
git add domains
git commit
git push
The last command will produce output from the `dehydrated` command
which talks with the DNS primary (currently `nevii`) to fetch new keys
and update old ones.
The new keys and certs are being copied to the LDAP host
(currently `pauli`) under
`/srv/puppet.torproject.org/from-letsencrypt/`. Then [[Puppet]] pick
those up in the `ssl` module. Use the `ssl::service` resource to
deploy them.
See the "Design" section below for more information on how that works.
See also [[static-component]] for an example of how to deploy an
encrypted virtual host and onion service.
# Disabling HPKP
To disable key pinning ([HPKP][]) on a given domain, just remove the
backup key from the repository:
cd backup-keys
git rm example.torproject.org*
git commit
git push
Then run Puppet on all affected hosts, for example the static mirrors:
cumin 'C:roles::static_mirror_web' 'puppet agent -t'
# Renewing a certificate before its expiry date
If a certificate has been revoked, it should be renewed before its
expiry date. To do so, you can drop a special file in the
`per-domain-config` directory to change the expiry date range and run
the script by hand.
Create a file matching the primary domain name of the certificate on
the DNS master:
cat <<EOF > /srv/letsencrypt.torproject.org/repositories/letsencrypt-domains/per-domain-config/example.torproject.org
RENEW_DAYS="85"
EOF
Here we tell the ACME client (dehydrated) to renew the cert if it is
85 days or older (instead of the 30 days period).
Then run the script by hand (or wait for cron to do its thing):
letsencrypt@nevii:~$ dehydrated-wrap --cron
[...]
Processing example.torproject.org with alternative names: example.torproject.org
+ Using certificate specific config file!
+ RENEW_DAYS = 85
+ Checking domain name(s) of existing cert... unchanged.
+ Checking expire date of existing cert...
+ Valid till May 18 20:40:45 2020 GMT Certificate will expire
(Less than 85 days). Renewing!
+ Signing domains...
[..]
Then remove the file.
# Design
How is this built anyways?
When you push to the git repository on the `git-rw.torproject.org`
server (currently `cupani`):
1. a per-repository hook gets called in
`/srv/git.torproject.org/git-helpers/post-receive-per-repo.d/admin\%letsencrypt-domains/trigger-letsencrypt-server`
2. this hooks hits the DNS master over SSH (`letsencrypt@nevii`) and
there the `authorized_keys` file hardcodes the command to
`/srv/letsencrypt.torproject.org/bin/from-githost`
3. ... which in turns just calls `bin/update` in the same directory
(`/srv/letsencrypt.torproject.org`)
4. ... which in turns pulls the `letsencrypt-domains` repository and
runs `dehydrated-wrap --cron` with a special `BASE` variable that
points dehydrated at our configuration, in
`etc/dehydrated-config`, again in the same directory
5. Through that special configuration, the dehydrated command is
configured to call a custom hook (`bin/le-hook`) which implements
logic around the DNS-01 authentication challenge, notably adding
challenges, bumping serial numbers in the primary nameserver, and
waiting for secondaries to sync. Note that there's a configuration
file for that hook in `/etc/dsa/le-hook.conf`.
6. The `le-hook` also pushes the changes around. The hook calls the
`bin/deploy` file which installs the certificates files in
`var/result`.
7. It also generates a Public Key Pin (PKP) hash with the
`bin/get-pin` command and appends Diffie-Hellman paramets
(`dh-$size.pem`) to the certificate chain.
8. It finally calls the `bin/push` command which runs `rsync` to the
Puppet server, which in turns hardcodes the place where those
files are dumped (in
`pauli:/srv/puppet.torproject.org/from-letsencrypt`) through its
`authorized_keys` file.
9. Finally, those certificates are collected by Puppet through the
`ssl` module. Pay close attention to how the
`tor-puppet/modules/apache2/templates/ssl-key-pins.erb` template
works: it will not deploy key pinning if the backup `.pin` file is
missing.