mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	UI to upload certificates and keys for TLS, and send them to node red in configuration properties to store them in credentials file
by default upload buttons will be shown unless a cert or key path is already set added new settings flag called 'tlsDisableLocalFiles' to disable UI for local paths for cloud hosted NR
This commit is contained in:
		| @@ -15,17 +15,42 @@ | ||||
| --> | ||||
|  | ||||
| <script type="text/x-red" data-template-name="tls-config"> | ||||
|     <div class="form-row" class="hide" id="node-config-row-uselocalfiles"> | ||||
|         <input type="checkbox" id="node-config-input-uselocalfiles" style="display: inline-block; width: auto; vertical-align: top;"> | ||||
|         <label for="node-config-input-uselocalfiles" style="width: 70%;"><span data-i18n="tls.label.use-local-files"></label> | ||||
|     </div> | ||||
|     <div class="form-row"> | ||||
|         <label style="width: 120px;" for="node-config-input-cert"><i class="fa fa-file-text-o"></i> <span data-i18n="tls.label.cert"></span></label> | ||||
|         <input style="width: 60%;" type="text" id="node-config-input-cert" data-i18n="[placeholder]tls.placeholder.cert"> | ||||
|         <label style="width: 120px;"><i class="fa fa-file-text-o"></i> <span data-i18n="tls.label.cert"></span></label> | ||||
|         <span class="tls-config-input-data"> | ||||
|             <label class="btn ui-button" style="width: 85px; padding: 3px 0px;" for="node-config-input-certfile"><i class="fa fa-upload"></i> <span data-i18n="tls.label.upload"></span></label> | ||||
|             <input class="hide" type="file" id="node-config-input-certfile"> | ||||
|             <span id="tls-config-certname" style="width: 180px; overflow: hidden; line-height:34px; height:34px; text-overflow: ellipsis; white-space: nowrap; display: inline-block; vertical-align: middle;"> </span> | ||||
|         </span> | ||||
|         <input type="hidden" id="node-config-input-certname"> | ||||
|         <input type="hidden" id="node-config-input-certdata"> | ||||
|         <input class="hide tls-config-input-path" style="width: 60%;" type="text" id="node-config-input-cert" data-i18n="[placeholder]tls.placeholder.cert"> | ||||
|     </div> | ||||
|     <div class="form-row"> | ||||
|         <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> | ||||
|         <input style="width: 60%;" type="text" id="node-config-input-key" data-i18n="[placeholder]tls.placeholder.key"> | ||||
|         <span class="tls-config-input-data"> | ||||
|             <label class="btn" style="width: 85px; padding: 3px 0px;" for="node-config-input-keyfile"><i class="fa fa-upload"></i> <span data-i18n="tls.label.upload"></span></label> | ||||
|             <input class="hide" type="file" id="node-config-input-keyfile"> | ||||
|             <span id="tls-config-keyname" style="width: 180px; overflow: hidden; line-height:34px; height:34px; text-overflow: ellipsis; white-space: nowrap; display: inline-block; vertical-align: middle;"> </span> | ||||
|         </span> | ||||
|         <input type="hidden" id="node-config-input-keyname"> | ||||
|         <input type="hidden" id="node-config-input-keydata"> | ||||
|         <input class="hide tls-config-input-path" style="width: 60%;" type="text" id="node-config-input-key" data-i18n="[placeholder]tls.placeholder.key"> | ||||
|     </div> | ||||
|     <div class="form-row"> | ||||
|         <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> | ||||
|         <input style="width: 60%;" type="text" id="node-config-input-ca" data-i18n="[placeholder]tls.placeholder.ca"> | ||||
|         <span class="tls-config-input-data"> | ||||
|             <label class="btn" style="width: 85px; padding: 3px 0px;" for="node-config-input-cafile"><i class="fa fa-upload"></i> <span data-i18n="tls.label.upload"></span></label> | ||||
|             <input class="hide" type="file" title=" " id="node-config-input-cafile"> | ||||
|             <span id="tls-config-caname" style="width: 180px; overflow: hidden; line-height:34px; height:34px; text-overflow: ellipsis; white-space: nowrap; display: inline-block; vertical-align: middle;"> </span> | ||||
|         </span> | ||||
|         <input type="hidden" id="node-config-input-caname"> | ||||
|         <input type="hidden" id="node-config-input-cadata"> | ||||
|         <input class="hide tls-config-input-path" style="width: 60%;" type="text" id="node-config-input-ca" data-i18n="[placeholder]tls.placeholder.ca"> | ||||
|     </div> | ||||
|     <div class="form-row"> | ||||
|         <input type="checkbox" id="node-config-input-verifyservercert" style="display: inline-block; width: auto; vertical-align: top;"> | ||||
| @@ -61,13 +86,85 @@ | ||||
|                 return currentCert === '' || v != ''; | ||||
|             }}, | ||||
|             ca: {value:""}, | ||||
|             certname: {value:""}, | ||||
|             keyname: {value:""}, | ||||
|             caname: {value:""}, | ||||
|             uselocalfiles: {value:true}, | ||||
|             verifyservercert: {value: true} | ||||
|         }, | ||||
|         credentials: { | ||||
|             certdata: {type:"text"}, | ||||
|             keydata: {type:"text"}, | ||||
|             cadata: {type:"text"} | ||||
|         }, | ||||
|         label: function() { | ||||
|             return this.name || this._("tls.tls"); | ||||
|         }, | ||||
|         labelStyle: function() { | ||||
|             return this.name?"node_label_italic":""; | ||||
|         }, | ||||
|         oneditprepare: function() { | ||||
|             function updateFileUpload() { | ||||
|                 if ($("#node-config-input-uselocalfiles").is(':checked')) { | ||||
|                     $(".tls-config-input-path").show(); | ||||
|                     $(".tls-config-input-data").hide(); | ||||
|                 } else { | ||||
|                     $(".tls-config-input-data").show(); | ||||
|                     $(".tls-config-input-path").hide(); | ||||
|                 } | ||||
|             } | ||||
|             $("#node-config-input-uselocalfiles").on("click",function() { | ||||
|                 updateFileUpload(); | ||||
|             }); | ||||
|             function saveFile(property, file) { | ||||
|                 var dataInputId = "#node-config-input-"+property+"data"; | ||||
|                 var filenameInputId = "#node-config-input-"+property+"name"; | ||||
|                 var filename = file.name; | ||||
|                 var reader = new FileReader(); | ||||
|                 reader.onload = function(event) { | ||||
|                     $("#tls-config-"+property+"name").text(filename); | ||||
|                     $(filenameInputId).val(filename); | ||||
|                     $(dataInputId).val(event.target.result); | ||||
|                 } | ||||
|                 reader.readAsText(file,"UTF-8"); | ||||
|             } | ||||
|             $("#node-config-input-certfile" ).change(function() { | ||||
|                 saveFile("cert", this.files[0]); | ||||
|             }); | ||||
|             $("#node-config-input-keyfile" ).change(function() { | ||||
|                 saveFile("key", this.files[0]); | ||||
|             }); | ||||
|             $("#node-config-input-cafile" ).change(function() { | ||||
|                 saveFile("ca", this.files[0]); | ||||
|             }); | ||||
|             if (RED.settings.tlsDisableLocalFiles) { | ||||
|                 $("#node-config-row-uselocalfiles").hide(); | ||||
|             } else { | ||||
|                 $("#node-config-row-uselocalfiles").show(); | ||||
|             } | ||||
|             // in case paths were set from old TLS config | ||||
|             if(this.cert || this.key || this.ca) { | ||||
|                 this.uselocalfiles = true; | ||||
|                 $("#node-config-input-uselocalfiles").prop('checked',true); | ||||
|             } | ||||
|             $("#tls-config-certname").text(this.certname); | ||||
|             $("#tls-config-keyname").text(this.keyname); | ||||
|             $("#tls-config-caname").text(this.caname); | ||||
|             updateFileUpload(); | ||||
|         }, | ||||
|         oneditsave: function() { | ||||
|             if ($("#node-config-input-uselocalfiles").is(':checked')) { | ||||
|                 $("#node-config-input-cadata").val(""); | ||||
|                 $("#node-config-input-caname").val(""); | ||||
|                 $("#node-config-input-certdata").val(""); | ||||
|                 $("#node-config-input-certname").val(""); | ||||
|                 $("#node-config-input-keydata").val("");                | ||||
|                 $("#node-config-input-keyname").val("");   | ||||
|             } else { | ||||
|                 $("#node-config-input-ca").val(""); | ||||
|                 $("#node-config-input-cert").val(""); | ||||
|                 $("#node-config-input-key").val("");             | ||||
|             } | ||||
|         } | ||||
|     }); | ||||
| </script> | ||||
|   | ||||
| @@ -21,34 +21,65 @@ module.exports = function(RED) { | ||||
|     function TLSConfig(n) { | ||||
|         RED.nodes.createNode(this,n); | ||||
|         this.valid = true; | ||||
|         this.verifyservercert = n.verifyservercert; | ||||
|         var certPath = n.cert.trim(); | ||||
|         var keyPath = n.key.trim(); | ||||
|         var caPath = n.ca.trim(); | ||||
|  | ||||
|         if ( (certPath.length > 0) !== (keyPath.length > 0)) { | ||||
|             this.valid = false; | ||||
|             this.error(RED._("tls.error.missing-file")); | ||||
|             return; | ||||
|         } | ||||
|         this.verifyservercert = n.verifyservercert; | ||||
|         if ((certPath.length > 0) || (keyPath.length > 0)) { | ||||
|  | ||||
|         try { | ||||
|             if (certPath) { | ||||
|                 this.cert = fs.readFileSync(certPath); | ||||
|             if ( (certPath.length > 0) !== (keyPath.length > 0)) { | ||||
|                 this.valid = false; | ||||
|                 this.error(RED._("tls.error.missing-file")); | ||||
|                 return; | ||||
|             } | ||||
|             if (keyPath) { | ||||
|                 this.key = fs.readFileSync(keyPath); | ||||
|  | ||||
|             try { | ||||
|                 if (certPath) { | ||||
|                     this.cert = fs.readFileSync(certPath); | ||||
|                 } | ||||
|                 if (keyPath) { | ||||
|                     this.key = fs.readFileSync(keyPath); | ||||
|                 } | ||||
|                 if (caPath) { | ||||
|                     this.ca = fs.readFileSync(caPath); | ||||
|                 } | ||||
|             } catch(err) { | ||||
|                 this.valid = false; | ||||
|                 this.error(err.toString()); | ||||
|                 return; | ||||
|             }   | ||||
|         } else { | ||||
|             if (this.credentials) { | ||||
|                 var certData = this.credentials.certdata || ""; | ||||
|                 var keyData = this.credentials.keydata || ""; | ||||
|                 var caData = this.credentials.cadata || ""; | ||||
|                  | ||||
|                 if ((certData.length > 0) !== (keyData.length > 0)) { | ||||
|                     this.valid = false; | ||||
|                     this.error(RED._("tls.error.missing-file")); | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 if (certData) { | ||||
|                     this.cert = certData; | ||||
|                 } | ||||
|                 if (keyData) { | ||||
|                     this.key = keyData; | ||||
|                 } | ||||
|                 if (caData) { | ||||
|                     this.ca = caData; | ||||
|                 } | ||||
|             } | ||||
|             if (caPath) { | ||||
|                 this.ca = fs.readFileSync(caPath); | ||||
|             } | ||||
|         } catch(err) { | ||||
|             this.valid = false; | ||||
|             this.error(err.toString()); | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
|     RED.nodes.registerType("tls-config",TLSConfig); | ||||
|     RED.nodes.registerType("tls-config", TLSConfig, { | ||||
|         credentials: { | ||||
|             certdata: {type:"text"}, | ||||
|             keydata: {type:"text"}, | ||||
|             cadata: {type:"text"} | ||||
|         } | ||||
|     }); | ||||
|  | ||||
|     TLSConfig.prototype.addTLSOptions = function(opts) { | ||||
|         if (this.valid) { | ||||
|   | ||||
| @@ -126,6 +126,8 @@ | ||||
|     "tls": { | ||||
|         "tls": "TLS configuration", | ||||
|         "label": { | ||||
|             "use-local-files": "Use key and certificates from local files", | ||||
|             "upload": "Upload", | ||||
|             "cert": "Certificate", | ||||
|             "key": "Private Key", | ||||
|             "ca": "CA Certificate", | ||||
|   | ||||
| @@ -43,6 +43,10 @@ module.exports = { | ||||
|             safeSettings.flowFilePretty = settings.flowFilePretty; | ||||
|         } | ||||
|  | ||||
|         if (settings.tlsDisableLocalFiles) { | ||||
|             safeSettings.tlsDisableLocalFiles = settings.tlsDisableLocalFiles; | ||||
|         } | ||||
|  | ||||
|         if (!runtime.nodes.paletteEditorEnabled()) { | ||||
|             safeSettings.editorTheme = safeSettings.editorTheme || {}; | ||||
|             safeSettings.editorTheme.palette = safeSettings.editorTheme.palette || {}; | ||||
|   | ||||
| @@ -47,6 +47,10 @@ module.exports = { | ||||
|     // The maximum length, in characters, of any message sent to the debug sidebar tab | ||||
|     debugMaxLength: 1000, | ||||
|  | ||||
|     // To disable the option for using local files for storing keys and certificates in the TLS configuration | ||||
|     //  node, set this to true | ||||
|     //tlsDisableLocalFiles:true, | ||||
|  | ||||
|     // Colourise the console output of the debug node | ||||
|     //debugUseColors: true, | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user