Skip to content
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
11 changes: 11 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
## [Unreleased]
### Added
- The ```rekey``` command, to re-encrypt the project settings and encrypted submission data of a database with a new DB_SECRET.

### Fixed
- The clone command did not re-encrypt encrypted fields within the rows of a datagrid or an editgrid.
- The clone command named custom submission collections after the unsanitized project and collection names, where
the server never reads them, and cloned their revisions from and to the default revisions collection. It now
uses the server's names (```myproject_records``` and ```myproject_records_revisions```), and warns when the
destination still has submissions in a collection an earlier clone misnamed.

## 2.3.2
### Changed
- Fixing the cloner to not skip if the destination item does not exist
Expand Down
31 changes: 31 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,37 @@ yarn test:cloner
They cover every clone flag, the dry run output, resuming an interrupted clone, and cloning from an API source
(served by a stub API), against a real Mongo database.

### Rekey

formio rekey <mongo_db> --new-db-secret=[NEW_SECRET] --old-db-secret=[OLD_SECRET] [--old-db-secret=[ANOTHER_OLD_SECRET]]

Re-encrypts the project settings and the encrypted submission data of a database with a new ```DB_SECRET```, for
example after a clone was run with the wrong ```--dst-db-secret```.

The project settings are encrypted with the ```DB_SECRET```. Encrypted submission data is encrypted with the
```secret``` of its project settings or, when the project has none, with the ```DB_SECRET```. Every value is
first tried with the secret it should be encrypted with, and left alone when it already is. Otherwise each of
the old secrets is tried, and the value is re-encrypted and read back before it is written. Give every secret
the data may be encrypted with: after a clone that is both the wrong destination secret and the source secret.

| Option | What it does |
| --- | --- |
| ```--new-db-secret <secret>``` | The ```DB_SECRET``` the database should be encrypted with (required). |
| ```--old-db-secret <secret>``` | A secret the data may currently be encrypted with. Give it more than once to try several. |
| ```-p, --project <ids>``` | Only re-key these projects (comma separated). All projects by default. |
| ```--dry-run``` | Change nothing. Report how much would be re-keyed, and what cannot be decrypted. |
| ```--no-submission-revisions``` | Leave the submission revisions alone. |
| ```--batch-size <size>``` | The number of documents written at a time (default 1000). |
| ```--ca <file>```, ```--cert <file>``` | The TLS certificate authority and certificate key file for the connection. |

Back up the database, and stop the servers that use it, before re-keying: a server running with the wrong
secret keeps writing data encrypted with it. Start with a ```--dry-run```.

Values none of the secrets can decrypt are listed and left as they are, and the command exits with an error.
A project whose settings cannot be decrypted is skipped entirely, because the secret of its data is in those
settings. A document that changes while it is being re-keyed is never overwritten. Values that are already
encrypted with the new secret are skipped, so the command can be stopped and run again as often as needed.

### Deploy

```
Expand Down
1 change: 1 addition & 0 deletions commands/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module.exports = function(program, next) {
deploy: require('./deploy.js')(program, next),
copy: require('./copy.js')(program, next),
migrate: require('./migrate.js')(program, next),
rekey: require('./rekey.js')(program, next),
submissions: require('./submissions.js')(program, next)
};
};
26 changes: 26 additions & 0 deletions commands/rekey.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/* eslint-disable max-len */
'use strict';

/**
* Collect an option that can be given more than once.
* @param {string} value - This value.
* @param {string[]} previous - The values given before it.
*/
function collect(value, previous) {
return previous.concat([value]);
}

module.exports = function(program, next) {
program
.command('rekey <mongo_url>')
.description('Re-encrypt the project settings and encrypted submission data of a database with a new DB_SECRET.')
.requiredOption('--new-db-secret <secret>', 'The DB_SECRET the database should be encrypted with.')
.option('--old-db-secret <secret>', 'A secret the data may currently be encrypted with. Give it more than once to try several.', collect, [])
.option('-p, --project <project_id,...>', 'Only re-key these projects (comma separated). All projects by default.')
.option('--dry-run', 'Change nothing. Report how much would be re-keyed, and what cannot be decrypted.', false)
.option('--no-submission-revisions', 'Leave the submission revisions alone.')
.option('--batch-size <size>', 'The number of documents written at a time (default - 1000).')
.option('--ca <ca>', 'The TLS certificate authority for the mongo url.')
.option('--cert <cert>', 'The TLS certificate key file for the mongo connection.')
.action((mongoUrl, options) => require('../src/rekey')(mongoUrl, options));
};
Loading
Loading