Blame docs/security/tls.md

12bb45
# TLS certificates in Infra 
12bb45
12bb45
## Common naming convention.
12bb45
Ansible roles are using the following logic to distribute .key/.cert files
12bb45
12bb45
```
12bb45
  * {{ public_name }}.key : TLS private key
12bb45
  * {{ public_name }}.crt : signed TLS certificate
12bb45
  * {{ public_name }}-CAchain.crt : Trusted chain from CA (usually a symlink in pkistore is enough as we have a very few)
12bb45
12bb45
```
12bb45
 
12bb45
## Public certificates
12bb45
12bb45
### DigiCert
12bb45
We have some long-term certificates that we use for www/lists/ci/etc .centos.org
12bb45
Those need to be required through DigiCert Web ui and through internal RH ticket.
12bb45
Once we have the signed cert back, we can upload it in pkistore and deploy
12bb45
12bb45
12bb45
### Letsencrypt
12bb45
12bb45
!!! warning
12bb45
    This is now the prefered way to retrieve and use TLS certs in the CentOS infra for all public services.
12bb45
12bb45
12bb45
We use one dedicated node to obtain/renew certs for the acme http challenges, and also the same for dns challenges (for internal openshift setup). 
12bb45
Actually that node is `certbot.rdu2.centos.org`.
12bb45
12bb45
#### How to obtain new cert (DNS challenge is the preferred way)
12bb45
12bb45
##### For dns challenge
12bb45
We have automated the delegated dynamic zone needed for acme-challenge update with acme.sh
12bb45
We just have once to add in our zone (main one, so centos.org)  a CNAME pointing to the delegated zone acme.centos.org
12bb45
Example (simple) for forums.centos.org : 
12bb45
12bb45
```
12bb45
_acme-challenge.forums IN  CNAME _acme-challenge.forums.acme.centos.org.
12bb45
```
12bb45
Now on certbot node, we can just ask acme.sh to dynamically update acme.centos.org with our ddns.key file (already present) that is permitted to update the acme.centos.org and instruct acme.sh that while asking for a record in centos.org, it has to update other TXT record for the 'acme-challenge' record
12bb45
12bb45
```
12bb45
acme.sh --issue --dns dns_nsupdate -d forums.centos.org --challenge-alias forums.acme.centos.org
12bb45
```
12bb45
12bb45
Let's see what this produces on our DNS node, basically updating TXT record:
12bb45
12bb45
```
12bb45
Dec 10 10:35:57 ns1 named[28134]: client @0x7fe6240e93a0 8.43.84.3#59340/key ddns: signer "ddns" approved
12bb45
Dec 10 10:35:57 ns1 named[28134]: client @0x7fe6240e93a0 8.43.84.3#59340/key ddns: updating zone 'acme.centos.org/IN': adding an RR at '_acme-challenge.forums.acme.centos.org' TXT "mKq4hBQnYsbWEmTYEkZu6OjVsQJBGQsXWS0c8Zdu9hQ"
12bb45
```
12bb45
12bb45
And back on the certbot node, where it just updates, then waits and finalizes the acme validation with letsencrypt servers:
12bb45
12bb45
```
12bb45
[Tue 10 Dec 10:35:56 UTC 2019] Single domain='forums.centos.org'
12bb45
[Tue 10 Dec 10:35:56 UTC 2019] Getting domain auth token for each domain
12bb45
[Tue 10 Dec 10:35:57 UTC 2019] Getting webroot for domain='forums.centos.org'
12bb45
[Tue 10 Dec 10:35:57 UTC 2019] Adding txt value: mKq4hBQnYsbWEmTYEkZu6OjVsQJBGQsXWS0c8Zdu9hQ for domain:  _acme-challenge.forums.acme.centos.org
12bb45
[Tue 10 Dec 10:35:57 UTC 2019] adding _acme-challenge.forums.acme.centos.org. 60 in txt "mKq4hBQnYsbWEmTYEkZu6OjVsQJBGQsXWS0c8Zdu9hQ"
12bb45
[Tue 10 Dec 10:35:57 UTC 2019] The txt record is added: Success.
12bb45
[Tue 10 Dec 10:35:57 UTC 2019] Let's check each dns records now. Sleep 20 seconds first.
12bb45
[Tue 10 Dec 10:36:19 UTC 2019] Checking forums.centos.org for _acme-challenge.forums.acme.centos.org
12bb45
[Tue 10 Dec 10:36:19 UTC 2019] Domain forums.centos.org '_acme-challenge.forums.acme.centos.org' success.
12bb45
[Tue 10 Dec 10:36:19 UTC 2019] All success, let's return
12bb45
[Tue 10 Dec 10:36:19 UTC 2019] Verifying: forums.centos.org
12bb45
[Tue 10 Dec 10:36:22 UTC 2019] Success
12bb45
[Tue 10 Dec 10:36:22 UTC 2019] Removing DNS records.
12bb45
[Tue 10 Dec 10:36:22 UTC 2019] Removing txt: mKq4hBQnYsbWEmTYEkZu6OjVsQJBGQsXWS0c8Zdu9hQ for domain: _acme-challenge.forums.acme.centos.org
12bb45
[Tue 10 Dec 10:36:22 UTC 2019] removing _acme-challenge.forums.acme.centos.org. txt
12bb45
[Tue 10 Dec 10:36:22 UTC 2019] Removed: Success
12bb45
[Tue 10 Dec 10:36:22 UTC 2019] Verify finished, start to sign.
12bb45
[Tue 10 Dec 10:36:22 UTC 2019] Lets finalize the order, Le_OrderFinalize: https://acme-v02.api.letsencrypt.org/acme/finalize/52322595/1718928579
12bb45
[Tue 10 Dec 10:36:23 UTC 2019] Download cert, Le_LinkCert: https://acme-v02.api.letsencrypt.org/acme/cert/04cd1bdeeef194461a56d1323b11691aeccd
12bb45
[Tue 10 Dec 10:36:24 UTC 2019] Cert success.
12bb45
12bb45
```
12bb45
12bb45
PS : for a wildcard, just add multiple -d and '*.domain'
12bb45
```
12bb45
acme.sh --issue --dns dns_nsupdate -d stg.centos.org -d '*.stg.centos.org' --challenge-alias stg.acme.centos.org
12bb45
```
12bb45
All certs/keys obtained through acme are under /root/.acme.sh/{hostname}/ so you'll then have to import those into this pkistore dir
12bb45
12bb45
##### For http challenge 
12bb45
Normally we prefer DNS challenge, but there are corner cases like delegated records for which that would be problematic. That's the case for {buildlogs,cloud,vault}.centos.org nodes (delegated records to pdns/geoip)
12bb45
 
12bb45
You can add multiple SANs in the same certs. Here is one example with mon.centos.org and SAN mon.j7.centos.org, status.centos.org :
12bb45
12bb45
```
12bb45
certbot certonly --webroot --webroot-path /var/www/html --manual-public-ip-logging-ok --agree-tos --email sysadmin@centos.org -d mon.centos.org -d mon.j7.centos.org -d status.centos.org
12bb45
12bb45
```
12bb45
All files (certs/keys) are then available under /etc/letsencrypt/live/ (you'll have to import those into this pkistore dir)
12bb45
12bb45
12bb45
12bb45
#### How to renew existing certs
12bb45
##### For DNS challenges (existing records)
12bb45
For each cert/dns record, we have to ask for a renewal
12bb45
```
12bb45
acme.sh --renew-all 
12bb45
```
12bb45
12bb45
##### For HTTP challange
12bb45
For http challenge it's better to run first with --dry-run, then fix eventual issue and then launch it again for real operations
12bb45
```
12bb45
time certbot renew --webroot --webroot-path /var/www/html --manual-public-ip-logging-ok --agree-tos --email sysadmin@centos.org --dry-run ; echo return code $?
12bb45
12bb45
certbot renew --force-renew --webroot --webroot-path /var/www/html --manual-public-ip-logging-ok --agree-tos --email sysadmin@centos.org
12bb45
12bb45
```
12bb45
12bb45
### Deploying through ansible
12bb45
Don't forget to have pushed the new/renewed certs/keys into this pkistore directory first.
12bb45
Important too : Please validate that the -CAChain.crt is linked to correct CA chain. As LetsEncrypt is rotating also their CA, please validate that your .crt is correctly being validated with correct CAchain with simple provided tool in this repository : 
12bb45
12bb45
```
12bb45
./validate_public_chain koji.mbox.centos.org.crt 
12bb45
Validating cert [koji.mbox.centos.org.crt] with CAChain [koji.mbox.centos.org-CAChain.crt] and default trusted ca-bundle
12bb45
koji.mbox.centos.org.crt: OK
12bb45
12bb45
```
12bb45
Once it's committed/pushed to pkistore git repo, tobisna (ansible bot) will deploy the renewed TLS certs automatically
12bb45
12bb45
12bb45