Credentials export / import bug?

Context

I have to move my workflows and credentials from one installation to another. I was using simple coping of the .n8n files (config and database.sqlite), but after a lot of messing around, there were strange errors that got introduced, so I decided to get a clean slate and just import the workflows data. Doing testing the offending workflows by hand it showed that the clean slate helped.

Then I used the CLI export and import commands (https://docs.n8n.io/reference/start-workflows-via-cli.html#credentials) for workflows and credentials to a fresh installed N8N setup. It went ok, successfully imported everything, but when I tried to use it I got errors on decoding the credentials.

Turns out the export:credentials command just copies the database entries as JSON, and does not export them. So when importing, as the new installation has a different secret key, they fail to decrypt them.

I was really surprised by this behavior, and it seems to be a bug. I was going to open it on Github issues but as I was told to try to do things around here, I’m posting it here.

I think it’s easy to solve this, and I was going to do it and open a PR. But first, I need to check about the design decisions about this.

TL;DR

The CLI command n8n export:credentials and n8n import:credentials just copy the database data, but doesn’t really export them, as they are saved in the exported format encrypted with the instance private key.

So they are not suitable for exporting and importing, as different instances usually have different private keys.

I think this is not what people would expect from these commands. I understand the import similar to manual import/export, like downloading the workflow as JSON and importing, or copying manually the credentials values.

I would like to fix this and open a PR, but first I want to check with the authors about it.

  • For fixing it, just decrypting on export and encrypting on import would be enough?
  • Is the current behavior desired in any way? If so, should a flag be added to the command to tell it to keep it encrypted?

By the way, to convert my credentials I made a script. It may be useful to other users so I’m posting it here.

It needs to be on a package with crypto-js (npm i crypto-js) installed.

The arguments for the command are:

  1. the config file from the original server (the one that was “exported”)
  2. the config file of the new server (the one you are “importing”)
  3. the “exported” json file with the credentials

run as:
node ./credential-converter.js in_conf out_conf creds.json
If it ok just redirect the output to a file with the converted credentials, which can be used to import in the new server.

credential-converter.js:

#!/usr/bin/env node

const fs = require('fs');

const crypto = require('crypto-js');
const AES = crypto.AES;

if (process.argv.length != 5) {
	console.error(`USAGE: ${process.argv[0]} original_config.json dest_config.json exported_credentials.json`);
	process.exit(-2);
}

[_, _, in_fn, out_fn, creds_fn ] = process.argv;

// console.log({in_fn, out_fn, creds_fn});

const in_f = fs.readFileSync(in_fn);
const in_data = JSON.parse(in_f);
const in_key = in_data.encryptionKey;

const out_f = fs.readFileSync(out_fn);
const out_data = JSON.parse(out_f);
const out_key = out_data.encryptionKey;

const creds_f = fs.readFileSync(creds_fn);
const creds_data = JSON.parse(creds_f);

// console.log(creds_data)

const new_creds = creds_data.map( (cred) => {
	// console.log(cred)
	const plain = AES.decrypt(cred.data, in_key);
	cred.data = AES.encrypt(plain, out_key).toString();
	// console.log(cred)
	return cred;
})

console.info(JSON.stringify(new_creds));

Thanks for reporting but no, that behavior is not a bug. It is done like that on purpose. Really would like to avoid having all the credentials for all services lying around in cleartext. So exporting them decrypted would never be the default and would just happen via an additional flag that people deliberately choose and so know that this is happening and know how dangerous it is.

But adding such a flag would for sure be a welcome PR.

Apart from that is it also very simple to have multiple instances with the same encryption key if credentials should be shared. It can either be changed in the file ~/.n8n/config or set via the environment variable N8N_ENCRYPTION_KEY.

1 Like
1 Like

Thanks a lot! Got released with [email protected]

1 Like