Updated Design: Encryption of credentials (markdown)

Nick O'Leary 2016-09-23 11:30:13 +01:00
parent adcb746bce
commit 9c1bf217bf
1 changed files with 23 additions and 16 deletions

@ -6,32 +6,39 @@ With a move to add version control backing to node-red, the very real prospect e
We cannot escape the fact that we need to store credential information in a retrievable way; hashing is not an option. We cannot escape the fact that we need to store credential information in a retrievable way; hashing is not an option.
What we can do is look at options to encrypt the credentials by default. This feature is to enable encryption of credentials *by default* - a user has to explicitly disable encryption if they do not want it to apply.
--- ---
Any encryption scheme will require a key to encrypt/decrypt the content. This needs to be provided by the user to ensure uniqueness. If we were to default to a 'well-known' key by default, then we're no more secure than we are today. The encryption scheme requires a key to encrypt/decrypt the content.
There are some cases to consider: A user is able to provide their own key via the `credentialSecret` property in the settings file. But most users will not do that the first time they run node-red after upgrading to this release. In which case, the runtime will auto-generate a key and store it in runtime settings. The credentials will then get encrypted with that key the next time flows are deployed.
1. a user provides a `credentialSecret` property in the `settings.js` file - in which case use that to encrypt/decrypt credentials If a user then provides their own `credentialSecret` property in the `settings.js` file, the runtime will migrate from the generated key to the user provided key the next time flows are deployed.
2. no such property is provided - the runtime must generate a random key and store it in the runtime settings object (see `Storage.setSettings`). If settings are not available, no encryption can be used.
Considerations If a user changes `credentialSecret` at any point, the runtime will no longer be able to decrypt the credentials and they will be lost.
1. a user runs without `credentialSecret` set and deploys some credentials. They get encrypted with the generated key that is stored in runtime settings. *Note*: the user doesn't know what that key is unless they go digging in the underlying storage mechanism for runtime settings (default: `.config.json` file) ---
2. a user then sets `credentialSecret` to a non-null string value:
- we will migrate the encryption key from the generated one to their preferred one (and delete the generated key from runtime settings) The credentials passed over the Storage API will be the encrypted set. An unencrypted credential object looks like this:
- if they then change `credentialSecret` - we can no longer decrypt credentials so they get wiped
3. alternative, if a user sets `credentialSecret` to `null`, we disable encryption of credentials, migrating from the auto generated key. {
- if they then change `credentialSecret` to a non-null string value, we enable encryption "nodeId": {
"credentialA": "value",
"credentialB": "value"
}
}
After encryption, it looks like this:
{
"$": "b89d8209b5158a3c313675561b1a5b5phN1gDBe81Z"
}
By keeping it a valid JSON object underlying storage implementations should not be affected by the change.
All of this behaviour occurs in the runtime - the credentials passed over the Storage API will be the encrypted set, assuming:
- the storage plugin being used is the [new one](https://github.com/node-red/node-red/wiki/Design:-Version-Control).
- they have not set `credentialSecret` to `null`
If the storage plugin implements the v1 storage api (ie the existing one), the encryption scheme will be disabled.