# Advice neededa; Editing / Keeping multiple secrets

**URL:** <https://discourse.nodered.org/t/advice-neededa-editing-keeping-multiple-secrets/83981>\
**Category:** Developing Nodes\
**Created:** [23 December 2023 13:27 UTC](https://discourse.nodered.org/t/advice-neededa-editing-keeping-multiple-secrets/83981 "2023-12-23T13:27:53Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Stwissel](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/stwissel/32/126_2.png) [@Stwissel](https://discourse.nodered.org/u/Stwissel)\
**Post date:** [23 December 2023 13:27 UTC](https://discourse.nodered.org/t/advice-neededa-editing-keeping-multiple-secrets/83981/1 "2023-12-23T13:27:53Z")

</div>

I just published my latest update to my DDNS node for Cloudflare.

> **[@insectos/node-red-cloudflare-ddns](https://www.npmjs.com/package/@insectos/node-red-cloudflare-ddns)**
>
> A DDNS client for Cloudflare with optional distributed operation. Latest version: 0.2.0, last published: 11 minutes ago. Start using @insectos/node-red-cloudflare-ddns in your project by running \`npm i @insectos/node-red-cloudflare-ddns\`. There are...

In it I split IP acquisition and DNS update into (optional) two nodes to fit my use case.  
To ensure that a spoke only can update its own DNS entry it needs to submit a password.  
The hub checks it.  
On the spoke it is a simple credential, on the Hub I currently have a JSON object with keys for host and values as passwords. It's an ugly hack and can't stay like that.

I was thinking of an editable list to capture host/password pairs and then create 2 arrays (later stringify): one for the hosts a property and one for the passwords aas credentials.

Now the questions:

- is that a sensible approach or is there a better way?
- how can I access credentials in oneditprepare to build the editable list?

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [23 December 2023 15:41 UTC](https://discourse.nodered.org/t/advice-neededa-editing-keeping-multiple-secrets/83981/2 "2023-12-23T15:41:54Z")

</div>

> [@Stwissel](#):
>
> is that a sensible approach or is there a better way?

Anything that stores passwords is not secure and can never be. I don't think storing as a credential really isn't any better as they only hide stuff really I think. I don't believe they actually make it secure (unless you have a way to prevent people with editor access from accessing the settings.js file but then Node-RED itself probably couldn't either).

The "problem" with Node-RED is that, being a general-purpose dev platform, it has a lot of access. So I think that the only possibility is to have an external service that Node-RED cannot directly access, only via an API. Captured passwords must be pre-hashed (maybe at the client), and then sent to the external service where they probably need to be re-hashed.

But inventing such a service is fraught with issues - use a proper key-store instead.

Sorry, have to rush. Catch up later.

---

<div class="post-metadata">

**Author:** ![Stwissel](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/stwissel/32/126_2.png) [@Stwissel](https://discourse.nodered.org/u/Stwissel)\
**Post date:** [23 December 2023 18:56 UTC](https://discourse.nodered.org/t/advice-neededa-editing-keeping-multiple-secrets/83981/3 "2023-12-23T18:56:24Z")

</div>

Thx for the rant. AFAIK credentials are stored encrypted, so access to settings.js won’t provide you access.  
  
Anyone who has access to OS level of a running application can wreck it. Point is case: common practice in containers (unrelated to NodeRED) is to use env variables for credentials. So messing with the KeyValue store is easy Even Docker secrets are just a `cat` away from disclosure. Once you have access to kubectl all bets are off.

I don’t see NodeRED being worse. I’d appreciate constructive discussion.

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [23 December 2023 19:50 UTC](https://discourse.nodered.org/t/advice-neededa-editing-keeping-multiple-secrets/83981/4 "2023-12-23T19:50:17Z")

</div>

> [@Stwissel](#):
>
> Thx for the rant. AFAIK credentials are stored encrypted, so access to settings.js won’t provide you access.

Correct

You could use the [editableList widget](https://nodered.org/docs/api/ui/editableList/) and store the array in a credentials setting.

Or if you want the host names not encrypted, you could split out the hostnames and passwords into separate arrays but then you need some way to key them together (or always ensure the entries are synced)

---

<div class="post-metadata">

**Author:** ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)\
**Post date:** [23 December 2023 20:20 UTC](https://discourse.nodered.org/t/advice-neededa-editing-keeping-multiple-secrets/83981/5 "2023-12-23T20:20:02Z")

</div>

> [@Stwissel](#):
>
> access credentials in oneditprepare

as onedtprepare runs client side it has to request/get things from the server side - but you should not pass actual credentials to the client side. What we normally do is pass " **password**" instead - so that if it is editied/changed we can then send back the new value - but do not expose the original.

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [23 December 2023 20:54 UTC](https://discourse.nodered.org/t/advice-neededa-editing-keeping-multiple-secrets/83981/6 "2023-12-23T20:54:48Z")

</div>

> [@Stwissel](#):
>
> for the rant. AFAIK credentials are stored encrypted, so access to settings.js won’t provide you access.

Had to rush the post as headed out with the family. Now have only mobile.

Needs more thought. You can't get the original password text but you DO get access to the hash in settings. This is not good I don't think. Enough for casual protection but not for anything really valuable I'm fairly sure. A node-red instance with write access to settings could also change the hash to something known maybe?

This is why keystores exist. Rule 1: don't use the same system for security and general processing.

PS: You will know when I'm ranting. This is certainly not that. Do whatever you want, just don't pass things off as Secure unless prosperity tested. You asked, I responded.

---

<div class="post-metadata">

**Author:** ![Stwissel](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/stwissel/32/126_2.png) [@Stwissel](https://discourse.nodered.org/u/Stwissel)\
**Post date:** [24 December 2023 10:51 UTC](https://discourse.nodered.org/t/advice-neededa-editing-keeping-multiple-secrets/83981/7 "2023-12-24T10:51:26Z")

</div>

Is there an annotated example for editable list? All the "usual" input fields get bound to `input` while the list (unsurprisingly) gets bound to `ol`. How to populate / collect the values?

---

<div class="post-metadata">

**Author:** ![Stwissel](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/stwissel/32/126_2.png) [@Stwissel](https://discourse.nodered.org/u/Stwissel)\
**Post date:** [24 December 2023 10:53 UTC](https://discourse.nodered.org/t/advice-neededa-editing-keeping-multiple-secrets/83981/8 "2023-12-24T10:53:38Z")

</div>

Slightly tricky. I would need to alter each password isn't it. The value is just a string even if you could parse it into a JS Object.

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [24 December 2023 11:19 UTC](https://discourse.nodered.org/t/advice-neededa-editing-keeping-multiple-secrets/83981/9 "2023-12-24T11:19:46Z")

</div>

> [@Stwissel](#):
>
> Is there an annotated example for editable list

It's fairly well documented (in the link I wrote above). You don't need anything bound - you can populate your array in oneditprepare and then grab the user input in oneditsave and set your array.

There are also a fair few nodes you can look at for additional clues. Like the inject node:

- Here is where the props are added to the list: [node-red/packages/node\_modules/@node-red/nodes/core/common/20-inject.html at 0e8d3127944a91f39fb49bcb4b388b184ce11edd · node-red/node-red · GitHub](https://github.com/node-red/node-red/blob/0e8d3127944a91f39fb49bcb4b388b184ce11edd/packages/node_modules/%40node-red/nodes/core/common/20-inject.html#L600)

- Here is where the props are gathered and stored: [node-red/packages/node\_modules/@node-red/nodes/core/common/20-inject.html at 0e8d3127944a91f39fb49bcb4b388b184ce11edd · node-red/node-red · GitHub](https://github.com/node-red/node-red/blob/0e8d3127944a91f39fb49bcb4b388b184ce11edd/packages/node_modules/%40node-red/nodes/core/common/20-inject.html#L698)

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [24 December 2023 11:24 UTC](https://discourse.nodered.org/t/advice-neededa-editing-keeping-multiple-secrets/83981/10 "2023-12-24T11:24:08Z")

</div>

Hi @Stwissel

The editable list is a little daunting at first, but once you get it - it picks up quickly  
Here is a minimal guide

1. Define your config value for the list

```js
defaults: {
    filters: { value: [] }, /* this will be an array of objects) /*
    ...
},

```

1. Define your control (don't bind it to config value name)

```auto
<div>
    <ol id="myFilters"> </ol>
</div>

```

1. on `oneditprepare`, set it up + restore previous values.

```js
$('#myFilters').editableList({
   removable: true,
   addButton: 'Add New Item',
   addItem: AddItem
});

/* Restore items - this calls the addItem assignment for each object in your array */
this.filters.forEach((Item) => {$('#myFilters').editableList('addItem', Item)});

```

1. Create the `addItem` callback

```auto
function AddItem(container, index, data) {
 /* data : Will be the element in the array, its empty when the button is clicked to add 
  * Construct an object of your choosing 
  * container : Is the Dom element that is added to the list                                  
  * you can bind values to your html elements as per normal javascript
                You are responsible for adding html content to it
  * index : Is the item index in the list     
  */

   // Add the item data to the container
   $(container).data('data', data);
}

```

1. on `oneditsave` write the list data to your config

```auto
const Items = $('#myFilters').editableList('items')
this.filters = [];
for (let i = 0; i < Items.length; i++) {
    const ItemData = Items[i].data('data');
    this.filters.push(ItemData)
}

```

I think I have that right - check my example here.

> <https://github.com/zwave-js/node-red-contrib-zwave-js/blob/main/zwave-js/event-filter.html>

You beat me to it @Steve-Mcl 😄

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [7 January 2024 11:24 UTC](https://discourse.nodered.org/t/advice-neededa-editing-keeping-multiple-secrets/83981/11 "2024-01-07T11:24:11Z")

</div>

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.
