@node-red/nodes 4.1.2 → 5.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -20,6 +20,13 @@
20
20
  <label for="node-config-input-uselocalfiles" style="width: 70%;"><span data-i18n="tls.label.use-local-files"></label>
21
21
  </div>
22
22
  <div class="form-row">
23
+ <label style="width: 120px;" for="node-config-input-certType"><i class="fa fa-bars"></i> <span data-i18n="tls.label.certtype"></label>
24
+ <select id="node-config-input-certType">
25
+ <option value="files" data-i18n="tls.label.files"></option>
26
+ <option value="pfx" data-i18n="tls.label.pfx"></option>
27
+ </select>
28
+ </div>
29
+ <div class="form-row" id="node-tls-conf-cer">
23
30
  <label style="width: 120px;"><i class="fa fa-file-text-o"></i> <span data-i18n="tls.label.cert"></span></label>
24
31
  <span class="tls-config-input-data">
25
32
  <label class="red-ui-button" for="node-config-input-certfile"><i class="fa fa-upload"></i> <span data-i18n="tls.label.upload"></span></label>
@@ -31,7 +38,7 @@
31
38
  <input type="hidden" id="node-config-input-certdata">
32
39
  <input class="hide tls-config-input-path" style="width: calc(100% - 170px);" type="text" id="node-config-input-cert" data-i18n="[placeholder]tls.placeholder.cert">
33
40
  </div>
34
- <div class="form-row">
41
+ <div class="form-row" id="node-tls-conf-key">
35
42
  <label style="width: 120px;" for="node-config-input-key"><i class="fa fa-file-text-o"></i> <span data-i18n="tls.label.key"></span></label>
36
43
  <span class="tls-config-input-data">
37
44
  <label class="red-ui-button" for="node-config-input-keyfile"><i class="fa fa-upload"></i> <span data-i18n="tls.label.upload"></span></label>
@@ -43,11 +50,23 @@
43
50
  <input type="hidden" id="node-config-input-keydata">
44
51
  <input class="hide tls-config-input-path" style="width: calc(100% - 170px);" type="text" id="node-config-input-key" data-i18n="[placeholder]tls.placeholder.key">
45
52
  </div>
53
+ <div class="form-row" id="node-tls-conf-p12">
54
+ <label style="width: 120px;" for="node-config-input-p12"><i class="fa fa-file-text-o"></i> <span data-i18n="tls.label.p12"></span></label>
55
+ <span class="tls-config-input-data">
56
+ <label class="red-ui-button" for="node-config-input-p12file"><i class="fa fa-upload"></i> <span data-i18n="tls.label.upload"></span></label>
57
+ <input class="hide" type="file" id="node-config-input-p12file">
58
+ <span id="tls-config-p12name" style="width: calc(100% - 280px); overflow: hidden; line-height:34px; height:34px; text-overflow: ellipsis; white-space: nowrap; display: inline-block; vertical-align: middle;"> </span>
59
+ <button type="button" class="red-ui-button red-ui-button-small" id="tls-config-button-p12-clear" style="margin-left: 10px"><i class="fa fa-times"></i></button>
60
+ </span>
61
+ <input type="hidden" id="node-config-input-p12name">
62
+ <input type="hidden" id="node-config-input-p12data">
63
+ <input class="hide tls-config-input-path" style="width: calc(100% - 170px);" type="text" id="node-config-input-p12" data-i18n="[placeholder]tls.placeholder.p12">
64
+ </div>
46
65
  <div class="form-row">
47
- <label style="width: 100px; margin-left: 20px;" for="node-config-input-passphrase"> <span data-i18n="tls.label.passphrase"></span></label>
66
+ <label style="width: 120px;" for="node-config-input-passphrase"><i class="fa fa-key"></i> <span data-i18n="tls.label.passphrase"></span></label>
48
67
  <input type="password" style="width: calc(100% - 170px);" id="node-config-input-passphrase" data-i18n="[placeholder]tls.placeholder.passphrase">
49
68
  </div>
50
- <div class="form-row">
69
+ <div class="form-row" id="node-tls-conf-ca">
51
70
  <label style="width: 120px;" for="node-config-input-ca"><i class="fa fa-file-text-o"></i> <span data-i18n="tls.label.ca"></span></label>
52
71
  <span class="tls-config-input-data">
53
72
  <label class="red-ui-button" for="node-config-input-cafile"><i class="fa fa-upload"></i> <span data-i18n="tls.label.upload"></span></label>
@@ -83,6 +102,7 @@
83
102
  category: 'config',
84
103
  defaults: {
85
104
  name: {value:""},
105
+ certType: {value:"files"},
86
106
  cert: {value:"", validate: function(v,opt) {
87
107
  var currentKey = $("#node-config-input-key").val();
88
108
  if (currentKey === undefined) {
@@ -103,6 +123,8 @@
103
123
  }
104
124
  return RED._("node-red:tls.error.invalid-key");
105
125
  }},
126
+ p12: {value:""},
127
+ p12name: {value:""},
106
128
  ca: {value:""},
107
129
  certname: {value:""},
108
130
  keyname: {value:""},
@@ -115,6 +137,7 @@
115
137
  certdata: {type:"text"},
116
138
  keydata: {type:"text"},
117
139
  cadata: {type:"text"},
140
+ p12data: {type:"text"},
118
141
  passphrase: {type:"password"}
119
142
  },
120
143
  label: function() {
@@ -124,6 +147,21 @@
124
147
  return this.name?"node_label_italic":"";
125
148
  },
126
149
  oneditprepare: function() {
150
+ $("#node-config-input-certType").on('change',function() {
151
+ if ($("#node-config-input-certType").val() === "pfx") {
152
+ $("#node-tls-conf-cer").hide();
153
+ $("#node-tls-conf-key").hide();
154
+ $("#node-tls-conf-ca").hide();
155
+ $("#node-tls-conf-p12").show();
156
+ }
157
+ else {
158
+ $("#node-tls-conf-cer").show();
159
+ $("#node-tls-conf-key").show();
160
+ $("#node-tls-conf-ca").show();
161
+ $("#node-tls-conf-p12").hide();
162
+ }
163
+ });
164
+
127
165
  function updateFileUpload() {
128
166
  if ($("#node-config-input-uselocalfiles").is(':checked')) {
129
167
  $(".tls-config-input-path").show();
@@ -145,9 +183,19 @@
145
183
  reader.onload = function(event) {
146
184
  $("#tls-config-"+property+"name").text(filename);
147
185
  $(filenameInputId).val(filename);
148
- $(dataInputId).val(event.target.result);
186
+ if (property === "p12") {
187
+ $(dataInputId).val(btoa(String.fromCharCode(...new Uint8Array(event.target.result))))
188
+ }
189
+ else {
190
+ $(dataInputId).val(event.target.result);
191
+ }
192
+ }
193
+ if (property === "p12") {
194
+ reader.readAsArrayBuffer(file);
195
+ }
196
+ else {
197
+ reader.readAsText(file,"UTF-8");
149
198
  }
150
- reader.readAsText(file,"UTF-8");
151
199
  }
152
200
  $("#node-config-input-certfile" ).on("change", function() {
153
201
  saveFile("cert", this.files[0]);
@@ -158,6 +206,9 @@
158
206
  $("#node-config-input-cafile" ).on("change", function() {
159
207
  saveFile("ca", this.files[0]);
160
208
  });
209
+ $("#node-config-input-p12file" ).on("change", function() {
210
+ saveFile("p12", this.files[0]);
211
+ });
161
212
 
162
213
  function clearNameData(prop) {
163
214
  $("#tls-config-"+prop+"name").text("");
@@ -173,6 +224,9 @@
173
224
  $("#tls-config-button-ca-clear").on("click", function() {
174
225
  clearNameData("ca");
175
226
  });
227
+ $("#tls-config-button-p12-clear").on("click", function() {
228
+ clearNameData("p12");
229
+ });
176
230
 
177
231
  if (RED.settings.tlsConfigDisableLocalFiles) {
178
232
  $("#node-config-row-uselocalfiles").hide();
@@ -180,12 +234,13 @@
180
234
  $("#node-config-row-uselocalfiles").show();
181
235
  }
182
236
  // in case paths were set from old TLS config
183
- if(this.cert || this.key || this.ca) {
237
+ if (this.cert || this.key || this.ca || this.p12) {
184
238
  $("#node-config-input-uselocalfiles").prop('checked',true);
185
239
  }
186
240
  $("#tls-config-certname").text(this.certname);
187
241
  $("#tls-config-keyname").text(this.keyname);
188
242
  $("#tls-config-caname").text(this.caname);
243
+ $("#tls-config-p12name").text(this.p12name);
189
244
  updateFileUpload();
190
245
  },
191
246
  oneditsave: function() {
@@ -193,10 +248,13 @@
193
248
  clearNameData("ca");
194
249
  clearNameData("cert");
195
250
  clearNameData("key");
196
- } else {
251
+ clearNameData("p12");
252
+ }
253
+ else {
197
254
  $("#node-config-input-ca").val("");
198
255
  $("#node-config-input-cert").val("");
199
256
  $("#node-config-input-key").val("");
257
+ $("#node-config-input-p12").val("");
200
258
  }
201
259
  }
202
260
  });
@@ -22,15 +22,27 @@ module.exports = function(RED) {
22
22
  RED.nodes.createNode(this,n);
23
23
  this.valid = true;
24
24
  this.verifyservercert = n.verifyservercert;
25
- var certPath = n.cert.trim();
26
- var keyPath = n.key.trim();
27
- var caPath = n.ca.trim();
25
+ var certPath, keyPath, caPath, p12Path;
26
+ if (n.cert) { certPath = n.cert.trim(); }
27
+ if (n.key) { keyPath = n.key.trim(); }
28
+ if (n.ca) { caPath = n.ca.trim(); }
29
+ if (n.p12) { p12Path = n.p12.trim(); }
30
+ this.certType = n.certType || "files";
28
31
  this.servername = (n.servername||"").trim();
29
32
  this.alpnprotocol = (n.alpnprotocol||"").trim();
30
33
 
31
- if ((certPath.length > 0) || (keyPath.length > 0) || (caPath.length > 0)) {
32
-
33
- if ( (certPath.length > 0) !== (keyPath.length > 0)) {
34
+ if (this.certType === "pfx" && p12Path && p12Path.length > 0) {
35
+ try {
36
+ this.pfx = fs.readFileSync(p12Path);
37
+ }
38
+ catch(err) {
39
+ this.valid = false;
40
+ this.error(err.toString());
41
+ return;
42
+ }
43
+ }
44
+ else if ((certPath && certPath.length > 0) || (keyPath && keyPath.length > 0) || (caPath && caPath.length > 0)) {
45
+ if ( (certPath && certPath.length > 0) !== (keyPath && keyPath.length > 0)) {
34
46
  this.valid = false;
35
47
  this.error(RED._("tls.error.missing-file"));
36
48
  return;
@@ -46,18 +58,21 @@ module.exports = function(RED) {
46
58
  if (caPath) {
47
59
  this.ca = fs.readFileSync(caPath);
48
60
  }
49
- } catch(err) {
61
+ }
62
+ catch(err) {
50
63
  this.valid = false;
51
64
  this.error(err.toString());
52
65
  return;
53
66
  }
54
- } else {
67
+ }
68
+ else {
55
69
  if (this.credentials) {
56
70
  var certData = this.credentials.certdata || "";
57
71
  var keyData = this.credentials.keydata || "";
58
72
  var caData = this.credentials.cadata || "";
73
+ var p12Data = this.credentials.p12data || "";
59
74
 
60
- if ((certData.length > 0) !== (keyData.length > 0)) {
75
+ if ((certData.length > 0) !== (keyData.length > 0) && p12Data.length === 0) {
61
76
  this.valid = false;
62
77
  this.error(RED._("tls.error.missing-file"));
63
78
  return;
@@ -72,6 +87,9 @@ module.exports = function(RED) {
72
87
  if (caData) {
73
88
  this.ca = caData;
74
89
  }
90
+ if (p12Data) {
91
+ this.pfx = Buffer.from(p12Data, 'base64');
92
+ }
75
93
  }
76
94
  }
77
95
  }
@@ -80,6 +98,7 @@ module.exports = function(RED) {
80
98
  certdata: {type:"text"},
81
99
  keydata: {type:"text"},
82
100
  cadata: {type:"text"},
101
+ p12data: {type:"text"},
83
102
  passphrase: {type:"password"}
84
103
  },
85
104
  settings: {
@@ -92,14 +111,21 @@ module.exports = function(RED) {
92
111
 
93
112
  TLSConfig.prototype.addTLSOptions = function(opts) {
94
113
  if (this.valid) {
95
- if (this.key) {
96
- opts.key = this.key;
97
- }
98
- if (this.cert) {
99
- opts.cert = this.cert;
114
+ if (this.certType === "files") {
115
+ if (this.key) {
116
+ opts.key = this.key;
117
+ }
118
+ if (this.cert) {
119
+ opts.cert = this.cert;
120
+ }
121
+ if (this.ca) {
122
+ opts.ca = this.ca;
123
+ }
100
124
  }
101
- if (this.ca) {
102
- opts.ca = this.ca;
125
+ else {
126
+ if (this.pfx) {
127
+ opts.pfx = this.pfx;
128
+ }
103
129
  }
104
130
  if (this.credentials && this.credentials.passphrase) {
105
131
  opts.passphrase = this.credentials.passphrase;
@@ -204,19 +204,25 @@
204
204
  "ca": "CA Certificate",
205
205
  "verify-server-cert": "Verify server certificate",
206
206
  "servername": "Server Name",
207
- "alpnprotocol": "ALPN Protocol"
207
+ "alpnprotocol": "ALPN Protocol",
208
+ "certtype": "Cert Type",
209
+ "files": "Individual files",
210
+ "p12": "pfx or p12",
211
+ "pfx": "pfx or p12 file"
208
212
  },
209
213
  "placeholder": {
210
214
  "cert": "path to certificate (PEM format)",
211
215
  "key": "path to private key (PEM format)",
216
+ "p12": "path to .pfx or .p12 (PKCS12 format)",
212
217
  "ca": "path to CA certificate (PEM format)",
213
- "passphrase": "private key passphrase (optional)",
218
+ "passphrase": "password or passphrase (optional)",
214
219
  "servername": "for use with SNI",
215
220
  "alpnprotocol": "for use with ALPN"
216
221
  },
217
222
  "error": {
218
223
  "missing-file": "No certificate/key file provided",
219
224
  "invalid-cert": "Certificate not specified",
225
+ "invalid-p12": "pfx/p12 not specified",
220
226
  "invalid-key": "Private key not specified"
221
227
  }
222
228
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@node-red/nodes",
3
- "version": "4.1.2",
3
+ "version": "5.0.0-beta.1",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",