From 5e53a16a56400c3c0c744de586bc61dc7a4b5cba Mon Sep 17 00:00:00 2001 From: Richard Lau Date: Mon, 25 Apr 2022 13:24:37 +0100 Subject: [PATCH] doc: add certificate update notes Add notes on website certificate renewal based on what was done the last time we updated in January 2022. Refs: https://github.com/nodejs/build/issues/2811 --- doc/update-certificates.md | 151 +++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 doc/update-certificates.md diff --git a/doc/update-certificates.md b/doc/update-certificates.md new file mode 100644 index 000000000..24897b5c1 --- /dev/null +++ b/doc/update-certificates.md @@ -0,0 +1,151 @@ +# Replacing the main Node.js TLS/SSL certificate + +Node.js' public facing websites are secured by a TLS/SSL wildcard certificate. Currently this is a [multi-year subscription][] obtained via the OpenJS Foundation via [GoGetSSL][]. + +You will need build-infra level access to be able to retrieve the certificate and update the build infrastructure. Login information for Build WG accounts are in the [secrets repository][] (restricted). + +## Places that need to be updated + +* [Cloudflare](#updating-cloudflare) +* [Nginx web servers](#updating-nginx-servers) + * ci ([ci.nodejs.org][]) + * ci-release ([ci-release.nodejs.org][]) + * unencrypted ([unencrypted.nodejs.org][]) + * www ([nodejs.org][]) +* [Secrets repository](#update-copy-of-certificate-and-key-in-secrets) + +## Purchasing the new certificate + +This is done via a request to the OpenJS Foundation. GoGetSSL should send notifications to the Build WG email address from 30 days before the existing certificate expires. + +## Generating new certificate and key + +Create a new key each time you renew the certificate. + +Currently we use RSA, 4096 bits (validate on each renewal that this is still the recommended/reasonable values). + +In the `/root/tmp` directory, create the key with the following command on the www server: +``` +openssl genrsa -out star_nodejs_org.key 4096 +``` + +Generate a CSR request with the following command +``` +openssl req -new -key star_nodejs_org.key -out star_nodejs_org_chained.csr +``` +and provide the following info when prompted: + +key | value +---|--- +Country Name | US +State or Province Name | California +Locality | San Francisco +Organization Name | OpenJS Foundation +Organizational Unit Name | Node.js +Common Name | *.nodejs.org + +Go to https://my.gogetssl.com and choose `SSL Certificates` -> (The new certificate) -> `View` -> `Generate Certificate` and paste the CSR into the box provided. + +When asked to choose a validation approach, use DNS validation. This requires logging into Cloudflare and creating a CNAME entry. The process warns that this can take 10 minutes to 24 hours, although it took only a few minutes the previous time the certificate was renewed. + +Once the CNAME entry is created you will get an email with the certificate. We ran into some problems using the certificate from the email, so instead downloaded the certificate from the GoGetSSL UI via `SSL Certificates`->(The new certificate) -> `View` -> `Certificate` into `/root/tmp/star_nodejs_org_chained.csr`. + +Now you have the key and certificates that are needed to update the web servers and Cloudflare as outlined in the subsequent sections. + +## Updating Cloudflare + +Upload under `nodejs.org` -> `SSL/TLS` -> `Edge Certificates` menu, expand the entry for `*.nodejs.org, nodejs.org` and then select the wrench. This should bring up the `Replace SSL certificate and key` dialog. Copy in the certificate and key. + +Use the following options for the drop downs on the page +Option | Value +---|--- +Private Key Restrictions | Distribute to all Cloudflare data centers +Legacy Client Support | Legacy + +And then select `Upload Custom Certificate`. + +Validate that the `Expires on` for the entry now shows the updated expiry date. It make take some time for the update to propagate across the Cloudflare servers. + +## Updating nginx servers + +For each webserver, the certificate is installed into `/etc/nginx/ssl`. The following steps use `unencrypted` as an example: + +Upload the certificate and key to the server. +``` +ssh unencrypted mkdir /root/tmp +scp star_nodejs_org.key star_nodejs_org_chained.crt unencrypted:/root/tmp/ +``` + +Open an ssh session on the server, backup the existing keys and then copy over the new ones +``` +ssh unencrypted +cd /etc/nginx/ssl/ +cp nodejs_chained.crt nodejs_chained.crt.old +cp nodejs.key nodejs.key.old +cp /root/tmp/star_nodejs_org_chained.crt nodejs_chained.crt +cp /root/tmp/star_nodejs_org.key nodejs.key +``` + +Restart nginx +``` +systemctl restart nginx +``` + +Use a web browser to go to the server (e.g. https://unencrypted.nodejs.org (make sure you go to the https URL and not http)) and use the browser to view the certificate and expiry to check it matches the new expected validity dates. + +Delete `/root/tmp` on the server + +## Update copy of certificate and key in secrets + +Encrypt the key and certificate. We generally DO NOT fork projects in the nodejs-private organization. Instead we clone the [secrets repository][] directly from nodejs-private and create a new branch in that private repo. + +From where you have temporarily stored the certificates/key and assuming you have checked out the secrets repo at ~/secrets and have created a new branch. + +``` +cat star_nodejs_org_chained.crt | dotgpg create ~/secrets/build/infra/star_nodejs_org_chained.crt +``` + +``` +cat star_nodejs_org.key | dotgpg create ~/secrets/build/infra/star_nodejs_org.key +``` + +Validate that both are encrypted by looking at: + +``` +cat ~/secrets/build/infra/star_nodejs_org.key +``` + +and + +``` +cat ~/secrets/build/infra/star_nodejs_org_chained.crt +``` + +The should have similar footers/trailers to the existing content of https://github.com/nodejs-private/secrets/blob/master/build/infra/star_nodejs_org_chained.crt with the middle content being the encrypted part. + +Decrypt the new files with + +``` +dotgpg cat ~/secrets/build/infra/star_nodejs_org.key +``` + +and + +``` +dotgpg cat ~/secrets/build/infra/star_nodejs_org_chained.crt +``` + +and compare against the original files you had encrypted. + +Add the new files in git and commit. +Push your branch in nodejs-private and then create a pull request. + +Delete any local copies of the non-encrypted key/certificate files + +[ci.nodejs.org]: https://ci.nodejs.org +[ci-release.nodejs.org]: https://ci-release.nodejs.org +[GoGetSSL]: https://www.gogetssl.com/ +[multi-year subscription]: https://www.gogetssl.com/wiki/general/multi-year-subscription-ssl/ +[nodejs.org]: https://nodejs.org +[secrets repository]: https://github.com/nodejs-private/secrets +[unencrypted.nodejs.org]: https://unencrypted.nodejs.org