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.
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
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.
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.
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)
- 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
---
The credentials passed over the Storage API will be the encrypted set. An unencrypted credential object looks like this:
{
"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.