From da9f5726ce28607342dbfc902a0fb1a48e6044de Mon Sep 17 00:00:00 2001 From: Arek Sredzki Date: Wed, 21 Dec 2022 00:46:35 -0800 Subject: [PATCH] Improve configuration documentation, especially for data encryption keys With these changes, it should be clear that users must generate a unique DATA_ENCRYPTION_KEY. Additionally, the Dockerfile is updated for Node 19 as that is the recommended version (latest stable release at this time). --- Dockerfile | 2 +- config/docker.js | 8 +++++++- config/local.template | 24 ++++++++++++++++++++++++ config/models.js | 35 ++++------------------------------- docker-compose.yml | 7 +++++++ docs/database.md | 2 +- docs/docker.md | 13 ++++++++++--- 7 files changed, 54 insertions(+), 37 deletions(-) diff --git a/Dockerfile b/Dockerfile index ab725b0cd..bb2e7ddfc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:10 +FROM node:19 # Create app directory WORKDIR /usr/src/electron-release-server diff --git a/config/docker.js b/config/docker.js index bcfffcbff..af181eacf 100644 --- a/config/docker.js +++ b/config/docker.js @@ -6,7 +6,13 @@ module.exports = { models: { datastore: 'postgresql', - migrate: 'alter' + migrate: 'alter', + dataEncryptionKeys: { + // DEKs should be 32 bytes long, and cryptographically random. + // You can generate such a key by running the following: + // require('crypto').randomBytes(32).toString('base64') + default: process.env['DATA_ENCRYPTION_KEY'], + } }, port: 80, diff --git a/config/local.template b/config/local.template index 9d1c665b8..423b69ce3 100644 --- a/config/local.template +++ b/config/local.template @@ -59,6 +59,30 @@ module.exports = { token_secret: 'INSERT_RANDOM_TOKEN_KEY' }, + models: { + datastore: 'postgresql', + + /****************************************************************************** + * * + * The set of DEKs (data encryption keys) for at-rest encryption. * + * i.e. when encrypting/decrypting data for attributes with `encrypt: true`. * + * * + * > The `default` DEK is used for all new encryptions, but multiple DEKs * + * > can be configured to allow for key rotation. In production, be sure to * + * > manage these keys like you would any other sensitive credential. * + * * + * > For more info, see: * + * > https://sailsjs.com/docs/concepts/orm/model-settings#?dataEncryptionKeys * + * * + ******************************************************************************/ + dataEncryptionKeys: { + // DEKs should be 32 bytes long, and cryptographically random. + // You can generate such a key by running the following: + // require('crypto').randomBytes(32).toString('base64') + default: 'DATA_ENCRYPTION_KEY' + }, + }, + datastores: { postgresql: { adapter: 'sails-postgresql', diff --git a/config/models.js b/config/models.js index f115c24d3..b1f4e5dbb 100644 --- a/config/models.js +++ b/config/models.js @@ -11,13 +11,10 @@ module.exports.models = { - /*************************************************************************** - * * - * Your app's default connection. i.e. the name of one of your app's * - * datastores (see `config/datastores.js`) * - * * - ***************************************************************************/ - // datastore: 'localDiskDb', + // Your app's default datastore. i.e. the name of one of your app's datastores (see `config/datastores.js`) + // The former `connection` model setting is now `datastore`. This sets the datastore + // that models will use, unless overridden directly in the model file in `api/models`. + datastore: 'postgresql', /*************************************************************************** * * @@ -44,12 +41,6 @@ module.exports.models = { // uncomment the next line. // fetchRecordsOnDestroy: true, - // The former `connection` model setting is now `datastore`. This sets the datastore - // that models will use, unless overridden directly in the model file in `api/models`. - // It defaults to a datastore called `default`, which (unless otherwise configured in - // the `config/datastores.js` file) uses the built-in `sails-disk` adapter. - datastore: 'default', - // Because you can't have the old `connection` setting at the same time as the new // `datastore` setting, we'll set it to `null` here. When you merge this file into your // existing `config/models.js` file, just remove any reference to `connection`. @@ -66,22 +57,4 @@ module.exports.models = { createdAt: { type: 'string', autoCreatedAt: true, }, updatedAt: { type: 'string', autoUpdatedAt: true, }, }, - - /****************************************************************************** - * * - * The set of DEKs (data encryption keys) for at-rest encryption. * - * i.e. when encrypting/decrypting data for attributes with `encrypt: true`. * - * * - * > The `default` DEK is used for all new encryptions, but multiple DEKs * - * > can be configured to allow for key rotation. In production, be sure to * - * > manage these keys like you would any other sensitive credential. * - * * - * > For more info, see: * - * > https://sailsjs.com/docs/concepts/orm/model-settings#?dataEncryptionKeys * - * * - ******************************************************************************/ - dataEncryptionKeys: { - default: 'DXWjEVS/hpdunftnkrxSMDBBrgTxYG5mV5+D7zUBcWs=' - }, - }; diff --git a/docker-compose.yml b/docker-compose.yml index 205f6bed1..be0cc1439 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -14,6 +14,13 @@ services: DB_USERNAME: releaseserver DB_NAME: releaseserver DB_PASSWORD: secret + # DEKs should be 32 bytes long, and cryptographically random. + # You can generate such a key by running the following: + # require('crypto').randomBytes(32).toString('base64') + # PLEASE ENSURE THAT YOU CHANGE THIS VALUE IN PRODUCTION + DATA_ENCRYPTION_KEY: oIh0YgyxQbShuMjw4/laYcZnGKzvC3UniWFsqL0t4Zs= + # Recommended: 63 random alpha-numeric characters + # Generate using: https://www.grc.com/passwords.htm TOKEN_SECRET: change_me_in_production APP_URL: 'localhost:5000' ASSETS_PATH: '/usr/src/electron-release-server/releases' diff --git a/docs/database.md b/docs/database.md index 0dca2d6b4..3234d5108 100644 --- a/docs/database.md +++ b/docs/database.md @@ -49,7 +49,7 @@ After completing this section, you should now have > Hint: You now need to ensure that these settings are reflected in the `config/local.js` file. ``` - connections: { + datastores: { postgresql: { adapter: 'sails-postgresql', host: 'localhost', diff --git a/docs/docker.md b/docs/docker.md index 119a38786..c5a8bd8aa 100644 --- a/docs/docker.md +++ b/docs/docker.md @@ -26,6 +26,11 @@ To run the single container provide the next environment variables: - `DB_PORT` – port of postgres - `DB_USERNAME`, `DB_PASSWORD` – credentials to access postgres - `DB_NAME` – Database name +- `DATA_ENCRYPTION_KEY` - DEKs should be 32 bytes long, and cryptographically random. + You can generate such a key by running the following: + ``` + require('crypto').randomBytes(32).toString('base64') + ``` - `TOKEN_SECRET` – Recommended: 63 random alpha-numeric characters - `APP_URL` - base url for the app - [ref](http://sailsjs.org/documentation/reference/application/sails-get-base-url) @@ -33,10 +38,12 @@ To use `production.js` set `NODE_ENV` to `"production"` – so you should not se `APP_USERNAME`, `APP_PASSWORD`, `DB_HOST`, `DB_PORT`, `DB_USERNAME`, `DB_PASSWORD`, `DB_NAME`, `TOKEN_SECRET`. -**Warning**: You can insert the `TOKEN_SECRET`, `APP_PASSWORD`, `DB_PASSWORD` directly into the `docker-compose.yml`, but keep your secrets and private information in private. The production secrets must not be committed publicly! +**Warning**: You can insert the `APP_PASSWORD`, `DB_PASSWORD`, `TOKEN_SECRET`, and `DATA_ENCRYPTION_KEY` directly into +the `docker-compose.yml`, but this is not advised since it makes it easy to accidentally publish your secretms. +The production secrets must not be committed publicly! ## How to run -Firstly you should start with development setting to run database migration. +For your first run, you should start with development settings (which are the default) since this will perform database initialization/migration. -After it you should `always` run in production mode – set `NODE_ENV` to `"production"`. +For all subsequent executions, you should run in production mode by setting `NODE_ENV` to `"production"`.