From e92988d5a5762e46c979716c06ff543c880a31d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoine=20Beaupr=C3=A9?= Date: Wed, 15 Apr 2020 10:53:45 -0400 Subject: [PATCH] move the letsencrypt documentation in a broader tls page TLS covers more than just letsencrypt: there we could document our custom CAs and the other signing mechanisms also in operation in Tor that we might get into contact with. This is specifically in preperation for the documentation of the contacts we had with digicert. --- tsa/howto/letsencrypt.mdwn | 163 +-------------------------- tsa/howto/tls.mdwn | 220 +++++++++++++++++++++++++++++++++++++ 2 files changed, 222 insertions(+), 161 deletions(-) create mode 100644 tsa/howto/tls.mdwn diff --git a/tsa/howto/letsencrypt.mdwn b/tsa/howto/letsencrypt.mdwn index 46b43024..2b568bea 100644 --- a/tsa/howto/letsencrypt.mdwn +++ b/tsa/howto/letsencrypt.mdwn @@ -1,162 +1,3 @@ -[[!toc levels=3]] +[[!meta redir="tls"]] -# 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 < /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. +moved to [[tls]]. diff --git a/tsa/howto/tls.mdwn b/tsa/howto/tls.mdwn new file mode 100644 index 00000000..7917cc43 --- /dev/null +++ b/tsa/howto/tls.mdwn @@ -0,0 +1,220 @@ +TLS is the [Transport Layer Security](https://en.wikipedia.org/wiki/Transport_Layer_Security) protocol, previously known as +SSL and also known as [HTTPS](https://en.wikipedia.org/wiki/HTTPS) on the web. This page documents how +TLS is used across the TPA infrastructure and specifically how we +manage the related [X.509](https://en.wikipedia.org/wiki/X.509) certificates that make this work. + +[[!toc levels=3]] + +# Tutorial + +## 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. + + +## 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 < /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. + +# How-to + +## 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' + +## Pager playbook +## Disaster recovery + +# Reference + +## Installation + + +## SLA + + +## Design + +### Let's encrypt workflow + +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. + +## Issues + + + + +## Monitoring and testing + + + + +# Discussion + +## Overview + + + + +## Goals + + +### Must have + +### Nice to have + +### Non-Goals + +## Approvals required + + +## Proposed Solution + +## Cost + +## Alternatives considered + + -- GitLab