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

Include certmgr in fmt-frontend. #947

Merged
merged 1 commit into from
Jan 25, 2021
Merged
Show file tree
Hide file tree
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
97 changes: 40 additions & 57 deletions certmgr/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@

## Certificate storage

The certificates are stored in a docker volume. The volume is named letsencrypt
and is mounted by the `frontend` and the `certmgr` containers. Both containers mount
the volume at `/etc/cert_store`.
The certificates are stored in a docker volume. The volume is named letsencrypt and is mounted by the `frontend` and the
`certmgr` containers. Both containers mount the volume at `/etc/cert_store`.

At the top level, there are 2 directories in `/etc/cert_store`:

Expand All @@ -13,20 +12,18 @@ At the top level, there are 2 directories in `/etc/cert_store`:
- SSL Certificate: `/etc/cert_store/nginx/<server_name>/fullchain.pem`
- SSL Private Key: `/etc/cert_store/nginx/<server_name>/privkey.pem`

This is implemented by setting up `/etc/cert_store/nginx/<server_name>` as a
symbolic link to the self-signed or letsencrypt certificates.
This is implemented by setting up `/etc/cert_store/nginx/<server_name>` as a symbolic link to the self-signed or
letsencrypt certificates.

- `selfsigned` - stores a self-signed certificate for the server in
`/etc/letsencrypt/selfsigned/<server_name>`
- `selfsigned` - stores a self-signed certificate for the server in `/etc/letsencrypt/selfsigned/<server_name>`

Certificates issued by letsencrypt are stored in `/etc/letsencrypt/live/<server_name>`.

## Entrypoint scripts for the certmgr container for TheCombine

### Environment Variables

The following environment variables are used by the certmgr to control its
behavior:
The following environment variables are used by the certmgr to control its behavior:

| Variable Name | Description |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
Expand All @@ -44,16 +41,13 @@ behavior:

### Modes of Operation

The `CERT_MODE` environment variable specifies the mode in which the `certmgr`
container should run:
The `CERT_MODE` environment variable specifies the mode in which the `certmgr` container should run:

- `self-signed`: Issue a self-signed certificate. This mode is useful for servers/machines
that are not accessible from the internet, such as QA servers or development
machines.
- `self-signed`: Issue a self-signed certificate. This mode is useful for servers/machines that are not accessible from
the internet, such as QA servers or development machines.
- `letsencrypt`: Use `certbot` to obtain an SSL certificate from _Let's Encrypt_.
- `cert-server`: `cert-server` extends the `letsencrypt` mode. In addition to
obtaining its own certificate from _Let's Encrypt_, the `certmgr` will also
obtain certificates for each server/domain listed in `CERT_PROXY_DOMAINS`.
- `cert-server`: `cert-server` extends the `letsencrypt` mode. In addition to obtaining its own certificate from _Let's
Encrypt_, the `certmgr` will also obtain certificates for each server/domain listed in `CERT_PROXY_DOMAINS`.

### Script Descriptions

Expand All @@ -62,78 +56,69 @@ container should run:
`entrypoint.py` does the following:

- sets up the sub-directories for volume for storing the certificates
- instantiates the certificate class specified by the `CERT_MODE` environment
variable.
- instantiates the certificate class specified by the `CERT_MODE` environment variable.
- calls the certificate's `create` method to create the required certificate
- enters a loop to call the certificate's `renew` method every 12 hours. `renew`
will `renew` all certificates that are close to expiring.
- enters a loop to call the certificate's `renew` method every 12 hours. `renew` will `renew` all certificates that are
close to expiring.

#### base_cert.py

`base_cert.py` defines an abstract base class for SSL Certificate types.

#### self_signed_cert.py

`self_signed_cert.py` implements the certmgr behavior when `CERT_MODE` is set to
`self-signed`. It creates a self-signed certificate to be used by the nginx web
server and enters a loop to periodically check to see if the certificate needs
to be renewed/recreated. The certificate is valid for 10 years and will be
renewed when there are less than 10 days until is expires.
`self_signed_cert.py` implements the certmgr behavior when `CERT_MODE` is set to `self-signed`. It creates a self-signed
certificate to be used by the nginx web server and enters a loop to periodically check to see if the certificate needs
to be renewed/recreated. The certificate is valid for 10 years and will be renewed when there are less than 10 days
until is expires.

#### letsencrypt_cert.py

`letsencrypt_cert.py` implements the certmgr behavior when `CERT_MODE` is set to
`letsencrypt`. If there is no certificate or if it was issued by `localhost`,
then `letsencrypt_cert.py` will:
`letsencrypt_cert.py` implements the certmgr behavior when `CERT_MODE` is set to `letsencrypt`. If there is no
certificate or if it was issued by `localhost`, then `letsencrypt_cert.py` will:

- create a self-signed certificate
- wait for the webserver to come up
- use `certbot` to request a certificate from `letsencrypt` using the webroot
authentication method
- redirect the webserver configuration to point to the new certificate
Once there is a letsencrypt certificate, `letsencrypt_cert.py` enters a loop to check
every 12 hours if the certificate should be renewed.
- use `certbot` to request a certificate from `letsencrypt` using the webroot authentication method
- redirect the webserver configuration to point to the new certificate Once there is a letsencrypt certificate,
`letsencrypt_cert.py` enters a loop to check every 12 hours if the certificate should be renewed.

#### cert_proxy_server.py

`cert_proxy_server.py` implements the certmgr behavior when `CERT_MODE` is set to
`cert-server`. It uses the LetsEncryptCert base class (in `letsencrypt_cert.py)
to obtain its own certificate. It then creates certificates for each specified
proxy and uploads the certificates to an AWS S3 bucket
`cert_proxy_server.py` implements the certmgr behavior when `CERT_MODE` is set to `cert-server`. It uses the
LetsEncryptCert base class (in `letsencrypt_cert.py) to obtain its own certificate. It then creates certificates for
each specified proxy and uploads the certificates to an AWS S3 bucket

#### cert_client.py

_Not Implemented Yet_

`cert_client.py` will implement the certmgr behavior when `CERT_MODE` is set to
`cert-client`. It will fetch an SSL certificate from the AWS S3 bucket (when an
internet connection is available).
`cert_client.py` will implement the certmgr behavior when `CERT_MODE` is set to `cert-client`. It will fetch an SSL
certificate from the AWS S3 bucket (when an internet connection is available).

#### aws.py

`aws.py` is a collection of utility routines for uploading certificates to an S3 bucket
or downloading objects from the bucket.
`aws.py` is a collection of utility routines for uploading certificates to an S3 bucket or downloading objects from the
bucket.

#### cert_renewal_hook.py

When in `cert-server` mode, `cert_renewal_hook.py` is called each time letsencrypt
renews any of the certificates managed by the server. The hook pushes all the proxy
certs to the S3 bucket.
When in `cert-server` mode, `cert_renewal_hook.py` is called each time letsencrypt renews any of the certificates
managed by the server. The hook pushes all the proxy certs to the S3 bucket.

#### utils.py

`utils.py` is a collection of utility functions used by the different certmgr modes.

## Installation Requirements

The following scenarios list the various requirements for the Ansible playbook
that is used to setup the various targets, `playbook_target_setup.yml` and the
Python script that is used to setup the development environment,
`docker_setup.py`. `docker_setup.py` is only used for setting up a development
environment that uses a self-signed certificate.
The following scenarios list the various requirements for the Ansible playbook that is used to setup the various
targets, `playbook_target_setup.yml` and the Python script that is used to setup the development environment,
`docker_setup.py`. `docker_setup.py` is only used for setting up a development environment that uses a self-signed
certificate.

When installing TheCombine for using self-signed certificates, e.g. for the QA
server or for development use, the following steps are required:
When installing TheCombine for using self-signed certificates, e.g. for the QA server or for development use, the
following steps are required:

1. Build each container:
- frontend
Expand All @@ -151,10 +136,8 @@ server or for development use, the following steps are required:
- run `docker-compose build`
- run `docker-compose up --detach`

Note that the machines that are configured to get their certificates from
_Let's Encrypt_ need to have the frontend webserver reloaded in order to switch
from the self-signed certificate to the one from _Let's Encrypt_. To do this,
run:
Note that the machines that are configured to get their certificates from _Let's Encrypt_ need to have the frontend
webserver reloaded in order to switch from the self-signed certificate to the one from _Let's Encrypt_. To do this, run:

```
docker-compose exec frontend nginx -s reload
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
"eject": "react-scripts eject",
"fmt-backend": "dotnet-format",
"fmt-backend-check": "dotnet-format --check",
"fmt-frontend": "prettier --write \"./{.github,.vscode,docker_deploy,docs,public,scripts,src,user_guide/docs}/**/*.{js,jsx,ts,tsx,json,md,yml}\"",
"fmt-frontend-check": "prettier --check \"./{.github,.vscode,docker_deploy,docs,public,scripts,src,user_guide/docs}/**/*.{js,jsx,ts,tsx,json,md,yml}\"",
"fmt-frontend": "prettier --write \"./{.github,.vscode,certmgr,docker_deploy,docs,public,scripts,src,user_guide/docs}/**/*.{js,jsx,ts,tsx,json,md,yml}\"",
"fmt-frontend-check": "prettier --check \"./{.github,.vscode,certmgr,docker_deploy,docs,public,scripts,src,user_guide/docs}/**/*.{js,jsx,ts,tsx,json,md,yml}\"",
"frontend": "react-scripts start",
"gen-backend-coverage-report": "tsc scripts/genBackendCoverageReport.ts && node scripts/genBackendCoverageReport.js",
"import-sem-doms": "tsc scripts/importSemanticDomains.ts && node scripts/importSemanticDomains.js",
Expand Down