FR: Manipulate credentials from runtime

Hi Team,
I propose the following scenario:

Add the following methods to the node object when calling RED.nodes.createNode:

  • addCredentialSet(name, cred)
  • deleteCredentialSet(name)
  • updateCredentialSet(name, cred)

Being attached to the node, we cannot define the id when calling credentials methods

To avoid modifying the credential from another node:

// Do not return these new methods when calling RED.nodes.getNode(id)
function getNode(id) {
    var node;
    if (activeNodesToFlow[id] && activeFlows[activeNodesToFlow[id]]) {
        node = activeFlows[activeNodesToFlow[id]].getNode(id,true);
        const { addCredentialSet, deleteCredentialSet, updateCredentialSet, ...safeNode } = node;
        return safeNode;
    }
    ...
    return null;
}

So, a node can only modify its credentials

Next, we need to discuss how we update the creds file and the cache
Hoping I haven't forgotten anything :thinking:

Sorry if I don't get it. :thinking:
There's an existing credentials API. Why would there be a demand for that additional logic?

I think this is about self updating creds - i.e you store a time limited session token in a node, and have it updated, i.e for a refresh token as an example, but only when the node that is updating it - owns those creds - else that could be a MASSIVE SECURITY ISSUE

Creds can only be updated from the UI at this stage, at least without getting hackerish.

1 Like

The goal as Marcus says is to allow a node to update its credentials which is currently not possible because it is a clone.

It has been a long standing principle that the flow/credentials can only be updated via the /flows endpoint - ie doing a redeploy from the editor. And that nodes shouldn't be able to rewrite their own configuration.

This has posed some challenges around self-renewing credentials, but we'd need to think through the consequences (and unintended side-effects) of allowing nodes to modify things like this.

2 Likes

What are the possible consequences?

Currently all developers who update their credentials do so with an external file which involves a lot of external files and if they are not deleted when uninstalling the module a security risk but I digress... why does a node not shouldn't be able to update your credentials?

I don't have a quick answer. This has been one of the long standing principles we've stuck to - and I haven't had to think about how/why we came to this conclusion for quite some time.

Certainly one of the issues is around version control and the Projects feature. If nodes can modify the credentials file, then it will have uncommitted changes. If the user reverts the project or deploys to another machine, the credentials will be out of sync.

1 Like

Damn, well... since this is not a user action, the version control should not change.
I don't use the project so I don't know the consequences. Should the credentials be in the versioning?

Let's imagine that it is functional, all good, a user who reverts will in any case have a problem with these outdated credentials

I believe that updating nodes should not perform version control, even if it did there would be problems. By the way how do external files work since they have this problem?

Agree strongly with Nick here. Changes to the credentials handling should not be rushed and the consequences need to be well understood.

There are plenty of advantages of forcing people to use external files for this and plenty of ways to manage those files, potentially even from Node-RED flows (something else that people need to think about when offloading security processing - you may need to put files where they are read-only to Node-RED itself).

This is a subject that is hard to get right and easy to get wrong.

So for you, if a node needs to update its credentials it must do so with an external file?

Can't we just ignore the change? I mean it's not done by the user.

Or we create downright a separate file which is only used for the credentials which must be updated, this will help developers not to use crypto?

Not what I said at all.

Not helpful rhetoric. And not accurate.

:sweat_smile:

I mean, we create a second creds file which will only be used by the new methods (allowing updating from runtime), this allows us not to break version control and it allows centralization of these particular creds

But allowing your Node-RED runtime to update its own credentials - even via some new process - poses risks that need to be thought through. I certainly don't know what those risks are, I only know that such a design pattern should not be undertaken lightly or be rushed. Security is an area that, I'm afraid, needs to be taken at a steady pace, not rushed into.

If it were me, I would do my best to avoid having any credentials at all stored in Node-RED but this is a topic all of its own and probably not for this thread. It is a complex area & I am certainly not the best expert on the matter.

Sorry, my logic may be stupid and for what it's worth...

If a node wants to dynamically store credentials, it will use a file or a database using a file. The potential risk being that the file is not encrypted (or badly) or not deleted when the node is uninstalled.

Since many nodes do it, why not create built-in logic to do it? This reduces these risks. If a developper wants something custom, why not? As credentials are dynamic we can ignore them in versioning and ignore them during the future flows export.

API: currently credentials are not accessible (at least those like passwords)
Local access: Unfortunately we can't do much, even if the credentials are stored elsewhere, we can access them by looking for the keys in the node configuration

The main risk is the API and a malicious node. The local risk depends on the client and nothing can be done about that (I think)

Please I am not an expert and I just want to evolve this subject which has not really had an answer; if this is not possible then we note it so that we know why

Indeed, why not? This is not really about why not, more about whether there is a safe way to do it. It takes time and resources to do it correctly. Doing it in a hurry and making a mistake would be the worst possible outcome.

Sometimes your enthusiasm comes across a little forcefully :grinning: That is great for some things but there are subject areas where a more measured approach is required. Given that likely everyone with any knowledge in this area is extremely busy already, it comes down to resources and priorities.

My input to this is based on my experiences in Cyber Security and Enterprise Architecture so I know that this can be a minefield area. However, I don't have the detailed knowledge to say exactly what issues there might be and how they might be mitigated. Unfortunately, I also don't have the time to do the research required.

One of the reasons we've held back from this is the fact the storage layer of Node-RED is pluggable with a well defined api. It was designed so that any actions that Node-RED needed to do to store data was done via the API, which could result in files on disk, or entries in a database.

Then 3rd party nodes started taking it upon themselves to start writing their own files to disk - without consideration of the storage API and the fact that Node-RED could be running in an environment without a persistent file system. I don't recall (but it has been some time), any specific proposal or request to extend the storage API to support more node-specific storage tasks.

We could certainly look at extending the storage api to support additional functions. There will be a migration issue to consider - nodes that want to start using the new apis would either just not work in older versions of NR, or need to be written to handle both cases.

I assure you that this is not intentional :slightly_smiling_face:

This would indeed be a good idea, it would (ideally) eliminate writing other files to disk.

A sort of adminStorage for encrypted data

Interesting discussions here... we too have struggled with managing "transient" data like bearer tokens and session cookies over the years.

It seems safe to say that whatever solution is found should NOT update the file system, as this impacts the project versioning and the storage apis. So perhaps calling this a problem of "updating credentials" is not helpful -- I think we just need some in-memory temporary storage that can be treated like other context variables (albeit with limited access).

Stored credentials could then continue to operate as-is, initializing the config nodes. Any "updates" from the node itself would override them in the config node's memory, and remain in effect until the server is restarted (or they expire, if that could be handled, too).

I'm not suggesting that I have a way to implement any of this, just thinking out loud. Nick and the team will just need time to figure out the best way forward without breaking changes.

You are right, a sort of context specific to each node which writes to disk (the idea is to have persistence - needs to be discussed) and which is not accessible from the editor.

Do we create two, one encrypted by default and the other not?

With this way the credentials are static and if we want dynamic credentials (or something else) we use this new context store.

By rereading the Storage API description, it just allows you to define where the data is written - here we should create a new storage

This may be the best approach

except in a cloud environment where disk isn't available - so must support database and/or other as well.