Moving node-RED - Failed to decrypt credentials

Maybe the auto-generated credentialSecret is stored in there. That would explain it.

I just checked... it is indeed in the .config.json as key _credentialSecret

So once you set credentialSecret in your settings.js with your own secret, it will be removed from there at the next launch and the existing credentials will be re-encrypted with your own key.

For reference, these are the files I commit to source control. Everything to run the instance is in there. I just need to run npm install after checkout. So backups of your workspace are not really an issue if you follow that setup.

.
├── .gitignore
├── flows_cred.json
├── flows.json
├── package.json
├── package-lock.json
└── settings.js

NOTE:
These settings are important for this:

flowFile: 'flows.json',
flowFilePretty: true,
credentialSecret: "your key here...",

Thanks for testing Paul.
I think that the issue maybe in the last few lines of the .config.json file;

"projects": {
  "projects": {
   "Master_flow": {
    "credentialSecret": "mysecret"
   },
   "Store": {
    "credentialSecret": "mysecret"
   }
  },
  "activeProject": "Master_flow"
 }
}

Where it's still referring to 'projects' & "activeProject": "Master_flow"
What are the last entries in your .config.json file Paul?

You can try to use the credentialSecret from the "Master_flow" section. That is the actual secret that was used to encrypt the credentials.

Just set it as credentialSecret in the settings.js on the new machine.

And, on the new machine, look out for the _credentialSecret in .config.json. I think it should be removed beforehand (or delete the .config.json, it will be regenerated)

I think by now it would be best to start the migration again with a fresh Node-RED workspace on the target machine. I have some steps in mind that you could follow. I can write them down, if you want.

Thanks, but first I'd be interested to know what I asked in my last post, as that could be the issue.

None of that is in the json since there were no projects involved. Try taking it out.

That's what I thought. The .config.json keeps different settings per project. And the key "activeProject": "Master_flow" determines the project that is launched at start-up.

So to migrate from a projects to non-projects workspace, we need to piece all this data together into the right place.

Still the same with that section taken out unfortunately.

It seems strange that the "mysecret" in .config.json, isn't a hash, it's a single word password

"credentialSecret": "mysecret"

Strange, but it should not matter. As soon as it is set to any string, it will be used as encryption key.

Just to let you know. i reproduced this
pi with projects -> macOS no projects

13 Nov 07:04:33 - [warn] Error loading credentials: SyntaxError: Unexpected token e in JSON at position 0
13 Nov 07:04:33 - [warn] Error loading flows: Error: Failed to decrypt credentials

That's good, perhaps @knolleary has thoughts on this.

What steps did you take exactly? What files did you copy? Did you copy and properties from one file to another?

Let me try to explain all the different bits.

Without Projects

  • if credentialSecret is not set in your settings.js file, then NR will generate a key and store it in .config.json at the top level of the object under the name _credentialSecret. This is a long randomly generated string.
  • if credentialSecret is set in your settings.js file, then NR will use that instead.
  • if it finds _credentialSecret in .config.json and credentialSecret in settings.js then we assume this is the first time you've run since setting credentialSecret and the runtime will re-encrypt the credential file using credentialSecret and then delete _credentialSecret as it is no longer needed. (Technically it does this migration the first time you hit Deploy after starting it up in this state).

With Projects

  • if projects are enabled then it ignores credentialSecret in your settings file and _credentialSecret in .config.json.
  • Instead it uses the project-specific credential secret that is also stored in the .config.json file under the projects.[name-of-project].credentialSecret property.

Migrating from Projects on Device A to Not-Projects on Device B

To do this you need to:

  1. copy the flow and credential files from the projects subdirectory on Device A onto Device B
  2. copy the value of projects.[name-of-project].credentialSecret from .config.json on Device A to credentialSecret in the settings.js file on Device B

I know this works cause I've just run a workshop with a room full of developers who were doing pretty much exactly this (albeit Device B is actually an instance running in a Cloud environment).

5 Likes

The value of .credentialSecret from.config.json on Device A is a plain text password, whilst the credentialSecret in the settings.js file is curently a hash. Is that expected?

It may look like a hash but it isn't - it's just a string of characters.

And yes, .config.json contains the project's credentialSecret value in plain text because:

  1. that is not a file you put in version control
  2. if we did encrypt it somehow, where would we store the key to decrypt it? We'd have to encrypt that key. But where would we store the key to decrypt that key? And so on.

Well the good news is that it works!!
All my credentials are now accessible.

Thanks everyone.

2 Likes

@knolleary Worked for me too! Thanks Nick!

1 Like

In my case credentials contains of plaintext characters and were absolutely identical in both cases, but decryption had not worked until I removed manually _credentialSecret from .config on the site where projects were disabled.

@knolleary I would like to draw your attention to the fact that the _credentialSecret is not automatically deleted without hit "Deploy" button even if the credentialSecret present in settings.js. Please consider, that sometimes users can't hit "Deploy" button manually to change .config.json because they have only "read" rigths. Sometimes prepared flows.json files just copied to production environment where disableEditor:true setting is activated; On my opinion the behaviour like this is a bug. You shouldn't wait when "Deploy" button will be hit. I believe that _credentialSecret from .config.json have to removed immediately when credentialSecret will appear in settings.js
I've checked Node-RED 1.0.4 and latest from the official docker containers. I think you can simply reproduce this bug - the behaviour is exactly the same as the scenario you had described in your Nov 19th post. Please think to change algorithm and exclude "Deploy" hit from the scenario.

@eitijupaenoithoowohd we can only remove _credentialSecret from .config.json when we know that the credentials file has been re-encrypted according to the credentialSecret value from the settings file. That means rewriting the credentials file, and we only do that when the user hits the Deploy button.

If you are copying flows files onto a system then you need to make sure its settings.js file have the right credentialSecret in it before you run the flows.

If you have previously run Node-RED on that system without a credentialSecret in its settings file, then it will have generated _credentialSecret in the .config.json file and you'll need to either remove the value yourself from the file, or delete the .config.json file.

@knolleary Thank you for your detailed answer.

I have understood that simple solution is not exists and impossible to do re-encryption without "Deploy" hit. And this is the basic problem.

I want to explain. In my case the copied flows files got from a site where projects was enabled and credentialSecret being in .config.json but not in settings.js

I would like to leave my post in this topic to someone, who will have the same problem like me. I hope my experience will be useful.