Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

doc: add certificate update notes #2932

Merged
merged 1 commit into from
Apr 28, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 151 additions & 0 deletions doc/update-certificates.md
Original file line number Diff line number Diff line change
@@ -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