From 7b752ce49225eec704202079303bcc80cb032b27 Mon Sep 17 00:00:00 2001 From: Frederic Alix <9548962+fredericalix@users.noreply.github.com> Date: Fri, 3 Sep 2021 14:37:19 +0200 Subject: [PATCH] :sparkles: MQTT node: Add SSL/TLS support (#1828) * MQTT node: Add SSL/TLS support * Add import IDisplayOptions * Remove as NodePropertyTypes --- .../credentials/Mqtt.credentials.ts | 95 +++++++++++++++++++ packages/nodes-base/nodes/MQTT/Mqtt.node.ts | 45 +++++++-- .../nodes-base/nodes/MQTT/MqttTrigger.node.ts | 44 +++++++-- 3 files changed, 166 insertions(+), 18 deletions(-) diff --git a/packages/nodes-base/credentials/Mqtt.credentials.ts b/packages/nodes-base/credentials/Mqtt.credentials.ts index dda740b9a5..f841d37500 100644 --- a/packages/nodes-base/credentials/Mqtt.credentials.ts +++ b/packages/nodes-base/credentials/Mqtt.credentials.ts @@ -1,5 +1,6 @@ import { ICredentialType, + IDisplayOptions, INodeProperties, } from 'n8n-workflow'; @@ -69,5 +70,99 @@ export class Mqtt implements ICredentialType { default: '', description: 'Client ID. If left empty, one is autogenrated for you', }, + { + displayName: 'SSL', + name: 'ssl', + type: 'boolean', + default: false, + }, + { + displayName: 'Passwordless', + name: 'passwordless', + type: 'boolean', + displayOptions: { + show: { + ssl: [ + true, + ], + }, + }, + default: true, + description: 'Passwordless connection with certificates (SASL mechanism EXTERNAL)', + }, + { + displayName: 'CA Certificates', + name: 'ca', + type: 'string', + typeOptions: { + password: true, + }, + displayOptions: { + show: { + ssl: [ + true, + ], + }, + }, + default: '', + description: 'SSL CA Certificates to use.', + }, + { + displayName: 'Reject Unauthorized Certificate', + name: 'rejectUnauthorized', + type: 'boolean', + displayOptions: { + show: { + ssl: [ + true, + ], + passwordless: [ + true, + ], + }, + } as IDisplayOptions, + default: '', + description: 'Validate Certificate.', + }, + { + displayName: 'Client Certificate', + name: 'cert', + type: 'string', + typeOptions: { + password: true, + }, + displayOptions: { + show: { + ssl: [ + true, + ], + passwordless: [ + true, + ], + }, + } as IDisplayOptions, + default: '', + description: 'SSL Client Certificate to use.', + }, + { + displayName: 'Client Key', + name: 'key', + type: 'string', + typeOptions: { + password: true, + }, + displayOptions: { + show: { + ssl: [ + true, + ], + passwordless: [ + true, + ], + }, + }, + default: '', + description: 'SSL Client Key to use.', + }, ]; } diff --git a/packages/nodes-base/nodes/MQTT/Mqtt.node.ts b/packages/nodes-base/nodes/MQTT/Mqtt.node.ts index 8b0cc76e4e..6a73fa0277 100644 --- a/packages/nodes-base/nodes/MQTT/Mqtt.node.ts +++ b/packages/nodes-base/nodes/MQTT/Mqtt.node.ts @@ -119,19 +119,46 @@ export class Mqtt implements INodeType { const port = credentials.port as number || 1883; const clientId = credentials.clientId as string || `mqttjs_${Math.random().toString(16).substr(2, 8)}`; const clean = credentials.clean as boolean; + const ssl = credentials.ssl as boolean; + const ca = credentials.ca as string; + const cert = credentials.cert as string; + const key = credentials.key as string; + const rejectUnauthorized = credentials.rejectUnauthorized as boolean; - const clientOptions: IClientOptions = { - port, - clean, - clientId, - }; + let client: mqtt.MqttClient; - if (credentials.username && credentials.password) { - clientOptions.username = credentials.username as string; - clientOptions.password = credentials.password as string; + if (ssl === false) { + const clientOptions: IClientOptions = { + port, + clean, + clientId, + }; + + if (credentials.username && credentials.password) { + clientOptions.username = credentials.username as string; + clientOptions.password = credentials.password as string; + } + + client = mqtt.connect(brokerUrl, clientOptions); } + else { + const clientOptions: IClientOptions = { + port, + clean, + clientId, + ca, + cert, + key, + rejectUnauthorized, + }; + if (credentials.username && credentials.password) { + clientOptions.username = credentials.username as string; + clientOptions.password = credentials.password as string; + } - const client = mqtt.connect(brokerUrl, clientOptions); + client = mqtt.connect(brokerUrl, clientOptions); + } + const sendInputData = this.getNodeParameter('sendInputData', 0) as boolean; // tslint:disable-next-line: no-any diff --git a/packages/nodes-base/nodes/MQTT/MqttTrigger.node.ts b/packages/nodes-base/nodes/MQTT/MqttTrigger.node.ts index a6a3056145..d0a719e156 100644 --- a/packages/nodes-base/nodes/MQTT/MqttTrigger.node.ts +++ b/packages/nodes-base/nodes/MQTT/MqttTrigger.node.ts @@ -102,19 +102,45 @@ export class MqttTrigger implements INodeType { const port = credentials.port as number || 1883; const clientId = credentials.clientId as string || `mqttjs_${Math.random().toString(16).substr(2, 8)}`; const clean = credentials.clean as boolean; + const ssl = credentials.ssl as boolean; + const ca = credentials.ca as string; + const cert = credentials.cert as string; + const key = credentials.key as string; + const rejectUnauthorized = credentials.rejectUnauthorized as boolean; - const clientOptions: IClientOptions = { - port, - clean, - clientId, - }; + let client: mqtt.MqttClient; - if (credentials.username && credentials.password) { - clientOptions.username = credentials.username as string; - clientOptions.password = credentials.password as string; + if (ssl === false) { + const clientOptions: IClientOptions = { + port, + clean, + clientId, + }; + + if (credentials.username && credentials.password) { + clientOptions.username = credentials.username as string; + clientOptions.password = credentials.password as string; + } + + client = mqtt.connect(brokerUrl, clientOptions); } + else { + const clientOptions: IClientOptions = { + port, + clean, + clientId, + ca, + cert, + key, + rejectUnauthorized, + }; + if (credentials.username && credentials.password) { + clientOptions.username = credentials.username as string; + clientOptions.password = credentials.password as string; + } - const client = mqtt.connect(brokerUrl, clientOptions); + client = mqtt.connect(brokerUrl, clientOptions); + } const self = this;