This guide covers how to develop the system locally. Note that the configuration options described in this page are optimized for local development and may not represent best practices.
-
Install gcloud.
-
Create a Google Cloud project using the Cloud Console. Set your Project ID as an environment variable:
export PROJECT_ID="..."
Note this is the project ID, not name or number.
-
Configure gcloud:
gcloud auth login && \ gcloud auth application-default login && \ gcloud auth application-default set-quota-project "${PROJECT_ID}"
-
Install the Firebase CLI.
-
Configure the Firebase CLI:
firebase login
Use the same Google credentials as you used in the previous steps.
-
Change directory into this repository:
cd /path/to/exposure-notifications-verification-server
-
Bootstrap the local key management system:
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.
-
Create a
.env
file with your configuration. This will aid future development since you cansource
this file instead of trying to find all these values again.# Google project configuration. export PROJECT_ID="TODO" export GOOGLE_CLOUD_PROJECT="${PROJECT_ID}" # Get these values from the firebase console. export FIREBASE_API_KEY="TODO" export FIREBASE_PROJECT_ID="${PROJECT_ID}" export FIREBASE_MESSAGE_SENDER_ID="TODO" export FIREBASE_APP_ID="TODO" export FIREBASE_MEASUREMENT_ID="TODO" export FIREBASE_AUTH_DOMAIN="${PROJECT_ID}.firebaseapp.com" export FIREBASE_DATABASE_URL="https://${PROJECT_ID}.firebaseio.com" export FIREBASE_STORAGE_BUCKET="${PROJECT_ID}.appspot.com" # Disable local observability. export OBSERVABILITY_EXPORTER="NOOP" # 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 values with: # # openssl rand -base64 NUM # # where NUM is 32 or 64, respectively. export COOKIE_KEYS="ARLaFwAqBGIkm5pLjAveJuahtCnX2NLoAUz2kCZKrScUaUkEaxHSvJLVYb5yAPCc441Cho5n5yp8jdEmy6hyig==,RLjcRZeqc07s6dh3OK4CM1POjHDZHC+usNU1w/XNTjM=" # Configure cache and cache HMAC. Create your own values with: # # openssl rand -base64 128 # export CACHE_TYPE="IN_MEMORY" export CACHE_HMAC_KEY="/wC2dki5Z+To9iFwUamINtHIMOH/dME7e5Gy+9h3WTDBhqeeSYkqduZRjcZWwG3kPMdiWAdBxxop5wB+BHTBnSlfVVmy8qKVNv+Wf5ywgxV7SbB8bjNQBHSpn7aC5RxR6nkEsZ2w2fUhTJwD9q+MDo6TQvf+8OXEPrV1SXWNHrs=" # Configure rate limiter. Create your own values with: # # openssl rand -base64 128 # export RATE_LIMIT_TYPE="MEMORY" export RATE_LIMIT_HMAC_KEY="/wC2dki5Z+To9iFwUamINtHIMOH/dME7e5Gy+9h3WTDBhqeeSYkqduZRjcZWwG3kPMdiWAdBxxop5wB+BHTBnSlfVVmy8qKVNv+Wf5ywgxV7SbB8bjNQBHSpn7aC5RxR6nkEsZ2w2fUhTJwD9q+MDo6TQvf+8OXEPrV1SXWNHrs=" # 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 # 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=" # Configure database pooling. export DB_POOL_MIN_CONNS="2" export DB_POOL_MAX_CONNS="10" # Enable dev mode. Do not enable dev mode or database dev mode in production # environments. export DEV_MODE="true" export DB_DEBUG="true"
-
Source the
.env
file. Do this each time before you start the server:source .env
-
Start the database:
eval $(./scripts/dev init) ./scripts/dev dbstart
-
Run any migrations:
./scripts/dev dbmigrate
-
(Optional) Seed the database with fake data:
./scripts/dev dbseed
This will create some default users like
[email protected]
and[email protected]
for local development. Check the seed file for more details on what is created. -
Start the server:
go run ./cmd/server
Open your browser to http://localhost:8080.
Register a test-phone-number for your account by visiting:
https://console.cloud.google.com/customer-identity/mfa?project=${PROJECT_ID}
This will skip the actual sending of SMS codes for 2-factor auth and allow you to instead set a static challenge response code. Do not do this in production.