Skip to content
This repository has been archived by the owner on Jul 12, 2023. It is now read-only.

Commit

Permalink
Use new filesystem key manager (#488)
Browse files Browse the repository at this point in the history
* Use new filesystem key manager

* Update
  • Loading branch information
sethvargo authored Sep 8, 2020
1 parent 752cbb7 commit e013f21
Show file tree
Hide file tree
Showing 7 changed files with 316 additions and 68 deletions.
94 changes: 53 additions & 41 deletions docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,47 +33,36 @@ represent best practices.

Use the same Google credentials as you used in the previous steps.

1. Create a Google Cloud KMS key ring and two signing keys:
1. Change directory into this repository:

```sh
gcloud kms keyrings create "signing" \
--location "us"
gcloud kms keys create "token-signing" \
--location "us" \
--keyring "signing" \
--purpose "asymmetric-signing" \
--default-algorithm "ec-sign-p256-sha256"
gcloud kms keys create "certificate-signing" \
--location "us" \
--keyring "signing" \
--purpose "asymmetric-signing" \
--default-algorithm "ec-sign-p256-sha256" \
```text
cd /path/to/exposure-notifications-verification-server
```

To get the resource names to the keys (for use below):

```sh
gcloud kms keys describe "token-signing" \
--location "us" \
--keyring "signing"
1. Bootstrap the local key management system:

gcloud kms keys describe "certificate-signing" \
--location "us" \
--keyring "signing"
```text
go run ./tools/gen-keys
```

This will output some environment variables. **Save these environment
variables for the next step!**

The default development setup uses a local, on-disk key manager to persist
across server restarts. The production installation recommends a hosted key
management service like Google Cloud KMS. It is possible to use Google Cloud
KMS locally by following the instructions in the production setup guide.

1. Create a `.env` file with your configuration. This will aid future
development since you can `source` this file instead of trying to find all
these values again.

```sh
# Create a file named .env with these contents
export PROJECT_ID="YOUR_PROJECT_ID" # TODO: replace
# Google project configuration.
export PROJECT_ID="TODO"
export GOOGLE_CLOUD_PROJECT="${PROJECT_ID}"
# Get these values from the firebase console
# Get these values from the firebase console.
export FIREBASE_API_KEY="TODO"
export FIREBASE_PROJECT_ID="${PROJECT_ID}"
export FIREBASE_MESSAGE_SENDER_ID="TODO"
Expand All @@ -85,35 +74,58 @@ represent best practices.
export FIREBASE_PRIVACY_POLICY_URL="TODO"
export FIREBASE_TERMS_OF_SERVICE_URL="TODO"
# Populate these with the resource IDs from above. These values will be of
# the format:
#
# projects/ID/locations/us/keyRings/signing/cryptoKeys/token-signing/cryptoKeyVersions/1Z
export TOKEN_SIGNING_KEY="TODO"
export CERTIFICATE_SIGNING_KEY="TODO"
# Disable local observability
# Disable local observability.
export OBSERVABILITY_EXPORTER="NOOP"
# Configure a CSRF auth key. Create your own with `openssl rand -base64 32`.
# Configure CSRF for preventing request forgery. Create your own with:
#
# openssl rand -base64 32
#
export CSRF_AUTH_KEY="RcCNhTkS9tSDMSGcl4UCa1FUg9GmctkJpdI+eqZ+3v4="
# Configure cookie encryption, the first is 64 bytes, the second is 32.
# Create your own with `openssl rand -base64 NUM` where NUM is 32 or 64
# Create your own values with:
#
# openssl rand -base64 NUM
#
# where NUM is 32 or 64, respectively.
export COOKIE_KEYS="ARLaFwAqBGIkm5pLjAveJuahtCnX2NLoAUz2kCZKrScUaUkEaxHSvJLVYb5yAPCc441Cho5n5yp8jdEmy6hyig==,RLjcRZeqc07s6dh3OK4CM1POjHDZHC+usNU1w/XNTjM="
# Configure certificate key management. The CERTIFICATE_SIGNING_KEY should
# be the value output in the previous step.
export CERTIFICATE_KEY_MANAGER="FILESYSTEM"
export CERTIFICATE_KEY_FILESYSTEM_ROOT="$(pwd)/local"
export CERTIFICATE_SIGNING_KEY="TODO" # (e.g. "/system/certificate-signing/1122334455")
# Configure token key management. The TOKEN_SIGNING_KEY should be the value
# output in the previous step.
export TOKEN_KEY_MANAGER="FILESYSTEM"
export TOKEN_KEY_FILESYSTEM_ROOT="$(pwd)/local"
export TOKEN_SIGNING_KEY="TODO" # (e.g. "/system/token-signing/1122334455")
# Configure the database key manager. The CERTIFICATE_SIGNING_KEYRING and
# DB_ENCRYPTION_KEY should be the values output in the previous step.
export DB_KEY_MANAGER="FILESYSTEM"
export DB_KEY_FILESYSTEM_ROOT="$(pwd)/local"
export CERTIFICATE_SIGNING_KEYRING="TODO" # (e.g. "/realm")
export DB_ENCRYPTION_KEY="TODO" # (e.g. "/system/database-encryption")
# Use an in-memory key manager for encrypting values in the database. Create
# your own encryption key with `openssl rand -base64 64`.
export KEY_MANAGER="IN_MEMORY"
export DB_ENCRYPTION_KEY="O04ZjG4WuoceRd0k2pTqDN0r8omr6sbFL0U3T5b12Lo="
# Database HMAC keys - these should be at least 64 bytes, preferably 128
# Create your own with `openssl rand -base64 128`.
# Database HMAC keys - these should be at least 64 bytes, preferably 128.
# Create your own with:
#
# openssl rand -base64 128
#
export DB_APIKEY_DATABASE_KEY="RlV/RBEt0lDeK54r8U9Zi7EDFZid3fiKM2HFgjR9sZGMb+duuQomjGdNKYnzrNyKgeTBcc1V4qVs6fBrN6IFTLbgkp/u52MGhSooAQI4EuZ6JFuyxQBeu54Ia3mihF111BMcCWpHDg2MAh8k8f669plEQaqoQFg3GThP/Lx1OY0="
export DB_APIKEY_SIGNATURE_KEY="HFeglmupbtv/I2X04OQRl1V7mcvfAXuv8XtmIFYV6aYsPuwQVFtXDlfFrjouYT2Z6kYln7B90RcutHJNjpPDRkyBQ28HtWmid3dr0tpJ1KiiK5NGG7JS9mU8fCvEYklw5RV+1f8qN13nWzHpW8/RQw9rR/vQGy90yL5/aydBuVA="
export DB_VERIFICATION_CODE_DATABASE_KEY="YEN4+tnuf1DzQPryRzrPVilqT0Q2TO8IIg3C8prvXWGAaoABOWACl79hS40OneuaU8GsQHwhJ13wM2A5ooyOq+uqxCjrqVJZZXPU5xzl/6USEYAp4z2b0ZYrfkx2SRk1o9HfFi1RMqpaBf1TRIbsNOK9hNRG3nS2It49y6mR1ho="
# Enable dev mode
# Enable dev mode. Do not enable dev mode or database dev mode in production
# environments.
export DEV_MODE=1
export DB_DEBUG=1
```
Expand Down
77 changes: 77 additions & 0 deletions docs/production.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,81 @@

This page includes helpful tips for configuring things in production:

## Key management

The default production key management solution is [Google Cloud KMS][gcp-kms].
If you are using the Terraform configurations, the system will automatically
bootstrap and create the key rings and keys in Cloud KMS. If you are not using
the Terraform configurations, follow this guide to create the keys manually:

1. Create a Google Cloud KMS key ring

```sh
gcloud kms keyrings create "en-verification" \
--location "us"
```

Note that the "us" location is configurable. If you choose a different
location, substitute it in all future commands.

1. Create two signing keys - one for tokens and one for certificates:

```sh
gcloud kms keys create "token-signing" \
--location "us" \
--keyring "en-verification" \
--purpose "asymmetric-signing" \
--default-algorithm "ec-sign-p256-sha256" \
--protection-level "hsm"
```

```sh
gcloud kms keys create "certificate-signing" \
--location "us" \
--keyring "en-verification" \
--purpose "asymmetric-signing" \
--default-algorithm "ec-sign-p256-sha256" \
--protection-level "hsm"
```

Note the "us" location is configurable, but the key purpose and algorithm
must be the same as above.

1. Create an encryption key for encrypting values in the database:

```sh
gcloud kms keys create "database-encrypter" \
--location "us" \
--keyring "en-verification" \
--purpose "encryption" \
--rotation-period "30d" \
--protection-level "hsm"
```

1. Get the resource names to the keys:

```sh
gcloud kms keys describe "token-signing" \
--location "us" \
--keyring "en-verification"
```

```sh
gcloud kms keys describe "certificate-signing" \
--location "us" \
--keyring "en-verification"
```

```sh
gcloud kms keys describe "database-encrypter" \
--location "us" \
--keyring "en-verification"
```

1. Provide these values as the `TOKEN_SIGNING_KEY`, `CERTIFICATE_SIGNING_KEY`,
and `DB_ENCRYPTION_KEY` respectively in the environment where the services
will run. You also need to grant the service permission to use the keys.


## Observability (tracing and metrics)

Expand Down Expand Up @@ -220,3 +295,5 @@ lifetime is short, it is probably safe to remove the key beyond 30 days.
If you are using system keys, the system administrator will handle rotation. If
you are using realm keys, you can generate new keys in the UI.
[gcp-kms]: https://cloud.google.com/kms
10 changes: 7 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,18 @@ require (
firebase.google.com/go v3.13.0+incompatible
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5 // indirect
github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496 // indirect
github.com/aws/aws-sdk-go v1.34.18 // indirect
github.com/client9/misspell v0.3.4
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/frankban/quicktest v1.8.1 // indirect
github.com/google/exposure-notifications-server v0.6.2-0.20200901223640-ce4572602269
github.com/google/exposure-notifications-server v0.7.0
github.com/google/go-cmp v0.5.2
github.com/gorilla/csrf v1.7.0
github.com/gorilla/handlers v1.5.0
github.com/gorilla/mux v1.8.0
github.com/gorilla/schema v1.2.0
github.com/gorilla/sessions v1.2.1
github.com/grpc-ecosystem/grpc-gateway v1.14.8 // indirect
github.com/jinzhu/gorm v1.9.16
github.com/jinzhu/now v1.1.1 // indirect
github.com/kelseyhightower/envconfig v1.4.0 // indirect
Expand All @@ -39,9 +41,11 @@ require (
github.com/unrolled/secure v1.0.8
go.opencensus.io v0.22.4
go.uber.org/zap v1.16.0
golang.org/x/net v0.0.0-20200904194848-62affa334b73 // indirect
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 // indirect
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e
golang.org/x/tools v0.0.0-20200901201813-cf97e2b30f39
google.golang.org/genproto v0.0.0-20200901141002-b3bf27a9dbd1
golang.org/x/tools v0.0.0-20200908163505-ea3a2cdbfbeb
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d
gopkg.in/gormigrate.v1 v1.6.0
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect
honnef.co/go/tools v0.0.1-2020.1.5
Expand Down
Loading

0 comments on commit e013f21

Please sign in to comment.