diff --git a/include/Configuration.h b/include/Configuration.h index 2bdc950..0620503 100644 --- a/include/Configuration.h +++ b/include/Configuration.h @@ -90,6 +90,9 @@ struct CONFIG_T { bool Mqtt_Hass_IndividualPanels; bool Mqtt_Tls; char Mqtt_RootCaCert[MQTT_MAX_ROOT_CA_CERT_STRLEN + 1]; + bool Mqtt_TlsCertLogin; + char Mqtt_ClientCert[MQTT_MAX_ROOT_CA_CERT_STRLEN + 1]; + char Mqtt_ClientKey[MQTT_MAX_ROOT_CA_CERT_STRLEN + 1]; char Mqtt_Hostname[MQTT_MAX_HOSTNAME_STRLEN + 1]; diff --git a/include/WebApi_mqtt.h b/include/WebApi_mqtt.h index 99a494f..5eecc5b 100644 --- a/include/WebApi_mqtt.h +++ b/include/WebApi_mqtt.h @@ -3,7 +3,7 @@ #include -#define MQTT_JSON_DOC_SIZE 3072 +#define MQTT_JSON_DOC_SIZE 10240 class WebApiMqttClass { public: diff --git a/include/defaults.h b/include/defaults.h index a2ba316..8c37166 100644 --- a/include/defaults.h +++ b/include/defaults.h @@ -66,6 +66,9 @@ "mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d\n" \ "emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=\n" \ "-----END CERTIFICATE-----\n" +#define MQTT_TLSCERTLOGIN false +#define MQTT_TLSCLIENTCERT "" +#define MQTT_TLSCLIENTKEY "" #define MQTT_LWT_TOPIC "dtu/status" #define MQTT_LWT_ONLINE "online" #define MQTT_LWT_OFFLINE "offline" diff --git a/src/Configuration.cpp b/src/Configuration.cpp index 12b184a..593d6df 100644 --- a/src/Configuration.cpp +++ b/src/Configuration.cpp @@ -65,6 +65,9 @@ bool ConfigurationClass::write() JsonObject mqtt_tls = mqtt.createNestedObject("tls"); mqtt_tls["enabled"] = config.Mqtt_Tls; mqtt_tls["root_ca_cert"] = config.Mqtt_RootCaCert; + mqtt_tls["certlogin"] = config.Mqtt_TlsCertLogin; + mqtt_tls["client_cert"] = config.Mqtt_ClientCert; + mqtt_tls["client_key"] = config.Mqtt_ClientKey; JsonObject mqtt_hass = mqtt.createNestedObject("hass"); mqtt_hass["enabled"] = config.Mqtt_Hass_Enabled; @@ -202,6 +205,9 @@ bool ConfigurationClass::read() JsonObject mqtt_tls = mqtt["tls"]; config.Mqtt_Tls = mqtt_tls["enabled"] | MQTT_TLS; strlcpy(config.Mqtt_RootCaCert, mqtt_tls["root_ca_cert"] | MQTT_ROOT_CA_CERT, sizeof(config.Mqtt_RootCaCert)); + config.Mqtt_TlsCertLogin = mqtt_tls["certlogin"] | MQTT_TLSCERTLOGIN; + strlcpy(config.Mqtt_ClientCert, mqtt_tls["client_cert"] | MQTT_TLSCLIENTCERT, sizeof(config.Mqtt_ClientCert)); + strlcpy(config.Mqtt_ClientKey, mqtt_tls["client_key"] | MQTT_TLSCLIENTKEY, sizeof(config.Mqtt_ClientKey)); JsonObject mqtt_hass = mqtt["hass"]; config.Mqtt_Hass_Enabled = mqtt_hass["enabled"] | MQTT_HASS_ENABLED; diff --git a/src/MqttSettings.cpp b/src/MqttSettings.cpp index 9548fba..da0363d 100644 --- a/src/MqttSettings.cpp +++ b/src/MqttSettings.cpp @@ -104,7 +104,12 @@ void MqttSettingsClass::performConnect() if (config.Mqtt_Tls) { static_cast(mqttClient)->setCACert(config.Mqtt_RootCaCert); static_cast(mqttClient)->setServer(config.Mqtt_Hostname, config.Mqtt_Port); - static_cast(mqttClient)->setCredentials(config.Mqtt_Username, config.Mqtt_Password); + if (config.Mqtt_TlsCertLogin) { + static_cast(mqttClient)->setCertificate(config.Mqtt_ClientCert); + static_cast(mqttClient)->setPrivateKey(config.Mqtt_ClientKey); + } else { + static_cast(mqttClient)->setCredentials(config.Mqtt_Username, config.Mqtt_Password); + } static_cast(mqttClient)->setWill(willTopic.c_str(), 2, config.Mqtt_Retain, config.Mqtt_LwtValue_Offline); static_cast(mqttClient)->setClientId(clientId.c_str()); static_cast(mqttClient)->onConnect(std::bind(&MqttSettingsClass::onMqttConnect, this, _1)); diff --git a/src/WebApi_mqtt.cpp b/src/WebApi_mqtt.cpp index 05fe2d1..ff40dad 100644 --- a/src/WebApi_mqtt.cpp +++ b/src/WebApi_mqtt.cpp @@ -45,6 +45,8 @@ void WebApiMqttClass::onMqttStatus(AsyncWebServerRequest* request) root["mqtt_retain"] = config.Mqtt_Retain; root["mqtt_tls"] = config.Mqtt_Tls; root["mqtt_root_ca_cert_info"] = getRootCaCertInfo(config.Mqtt_RootCaCert); + root["mqtt_tls_cert_login"] = config.Mqtt_TlsCertLogin; + root["mqtt_client_cert_info"] = getRootCaCertInfo(config.Mqtt_ClientCert); root["mqtt_lwt_topic"] = String(config.Mqtt_Topic) + config.Mqtt_LwtTopic; root["mqtt_publish_interval"] = config.Mqtt_PublishInterval; root["mqtt_hass_enabled"] = config.Mqtt_Hass_Enabled; @@ -76,6 +78,9 @@ void WebApiMqttClass::onMqttAdminGet(AsyncWebServerRequest* request) root["mqtt_retain"] = config.Mqtt_Retain; root["mqtt_tls"] = config.Mqtt_Tls; root["mqtt_root_ca_cert"] = config.Mqtt_RootCaCert; + root["mqtt_tls_cert_login"] = config.Mqtt_TlsCertLogin; + root["mqtt_client_cert"] = config.Mqtt_ClientCert; + root["mqtt_client_key"] = config.Mqtt_ClientKey; root["mqtt_lwt_topic"] = config.Mqtt_LwtTopic; root["mqtt_lwt_online"] = config.Mqtt_LwtValue_Online; root["mqtt_lwt_offline"] = config.Mqtt_LwtValue_Offline; @@ -137,6 +142,9 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request) && root.containsKey("mqtt_topic") && root.containsKey("mqtt_retain") && root.containsKey("mqtt_tls") + && root.containsKey("mqtt_tls_cert_login") + && root.containsKey("mqtt_client_cert") + && root.containsKey("mqtt_client_key") && root.containsKey("mqtt_lwt_topic") && root.containsKey("mqtt_lwt_online") && root.containsKey("mqtt_lwt_offline") @@ -212,8 +220,10 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request) return; } - if (root["mqtt_root_ca_cert"].as().length() > MQTT_MAX_ROOT_CA_CERT_STRLEN) { - retMsg["message"] = "Certificate must not longer then " STR(MQTT_MAX_ROOT_CA_CERT_STRLEN) " characters!"; + if (root["mqtt_root_ca_cert"].as().length() > MQTT_MAX_ROOT_CA_CERT_STRLEN + || root["mqtt_client_cert"].as().length() > MQTT_MAX_ROOT_CA_CERT_STRLEN + || root["mqtt_client_key"].as().length() > MQTT_MAX_ROOT_CA_CERT_STRLEN) { + retMsg["message"] = "Certificates must not be longer than " STR(MQTT_MAX_ROOT_CA_CERT_STRLEN) " characters!"; retMsg["code"] = WebApiError::MqttCertificateLength; retMsg["param"]["max"] = MQTT_MAX_ROOT_CA_CERT_STRLEN; response->setLength(); @@ -291,6 +301,9 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request) config.Mqtt_Retain = root["mqtt_retain"].as(); config.Mqtt_Tls = root["mqtt_tls"].as(); strlcpy(config.Mqtt_RootCaCert, root["mqtt_root_ca_cert"].as().c_str(), sizeof(config.Mqtt_RootCaCert)); + config.Mqtt_TlsCertLogin = root["mqtt_tls_cert_login"].as(); + strlcpy(config.Mqtt_ClientCert, root["mqtt_client_cert"].as().c_str(), sizeof(config.Mqtt_ClientCert)); + strlcpy(config.Mqtt_ClientKey, root["mqtt_client_key"].as().c_str(), sizeof(config.Mqtt_ClientKey)); config.Mqtt_Port = root["mqtt_port"].as(); strlcpy(config.Mqtt_Hostname, root["mqtt_hostname"].as().c_str(), sizeof(config.Mqtt_Hostname)); strlcpy(config.Mqtt_Username, root["mqtt_username"].as().c_str(), sizeof(config.Mqtt_Username)); diff --git a/webapp/src/locales/de.json b/webapp/src/locales/de.json index 0cc300e..699f774 100644 --- a/webapp/src/locales/de.json +++ b/webapp/src/locales/de.json @@ -259,6 +259,8 @@ "Retain": "Retain", "Tls": "TLS", "RootCertifcateInfo": "Root CA-Zertifikat-Informationen", + "TlsCertLogin": "Anmeldung mit TLS Zertifikat", + "ClientCertifcateInfo": "Client Zertifikat-Informationen", "HassSummary": "Home Assistant MQTT-Auto-Discovery Konfigurationszusammenfassung", "Expire": "Ablaufen", "IndividualPanels": "Einzelne Paneele", @@ -387,6 +389,9 @@ "EnableRetain": "Retain Flag aktivieren", "EnableTls": "TLS aktivieren", "RootCa": "CA-Root-Zertifikat (Standard Letsencrypt):", + "TlsCertLoginEnable": "TLS Zertifikat Login", + "ClientCert": "TLS Client-Zertifikat:", + "ClientKey": "TLS Client-Key:", "LwtParameters": "LWT-Parameter", "LwtTopic": "LWT-Topic:", "LwtTopicHint": "LWT-Topic, wird der Basis Topic angehängt", diff --git a/webapp/src/locales/en.json b/webapp/src/locales/en.json index 8cbd609..527bcaf 100644 --- a/webapp/src/locales/en.json +++ b/webapp/src/locales/en.json @@ -259,6 +259,8 @@ "Retain": "Retain", "Tls": "TLS", "RootCertifcateInfo": "Root CA Certifcate Info", + "TlsCertLogin": "Login with TLS Certificate", + "ClientCertifcateInfo": "Client Certifcate Info", "HassSummary": "Home Assistant MQTT Auto Discovery Configuration Summary", "Expire": "Expire", "IndividualPanels": "Individual Panels", @@ -387,6 +389,9 @@ "EnableRetain": "Enable Retain Flag", "EnableTls": "Enable TLS", "RootCa": "CA-Root-Certificate (default Letsencrypt):", + "TlsCertLoginEnable": "Enable TLS Certificate Login", + "ClientCert": "TLS Client-Certificate:", + "ClientKey": "TLS Client-Key:", "LwtParameters": "LWT Parameters", "LwtTopic": "LWT Topic:", "LwtTopicHint": "LWT topic, will be append base topic", diff --git a/webapp/src/locales/fr.json b/webapp/src/locales/fr.json index bbf79d8..d45ecaa 100644 --- a/webapp/src/locales/fr.json +++ b/webapp/src/locales/fr.json @@ -259,6 +259,8 @@ "Retain": "Conserver", "Tls": "TLS", "RootCertifcateInfo": "Informations sur le certificat de l'autorité de certification racine", + "TlsCertLogin": "Connexion avec un certificat TLS", + "ClientCertifcateInfo": "Informations sur le certificat du client", "HassSummary": "Résumé de la configuration de la découverte automatique du MQTT de Home Assistant", "Expire": "Expiration", "IndividualPanels": "Panneaux individuels", @@ -387,6 +389,9 @@ "EnableRetain": "Activation du maintien", "EnableTls": "Activer le TLS", "RootCa": "Certificat CA-Root (par défaut Letsencrypt)", + "TlsCertLoginEnable": "Activer la connexion par certificat TLS", + "ClientCert": "Certificat client TLS:", + "ClientKey": "Clé client TLS:", "LwtParameters": "Paramètres LWT", "LwtTopic": "Sujet LWT", "LwtTopicHint": "Sujet LWT, sera ajouté comme sujet de base", diff --git a/webapp/src/types/MqttConfig.ts b/webapp/src/types/MqttConfig.ts index 8077ae7..dc6280e 100644 --- a/webapp/src/types/MqttConfig.ts +++ b/webapp/src/types/MqttConfig.ts @@ -9,6 +9,9 @@ export interface MqttConfig { mqtt_retain: boolean; mqtt_tls: boolean; mqtt_root_ca_cert: string; + mqtt_tls_cert_login: boolean; + mqtt_client_cert: string; + mqtt_client_key: string; mqtt_lwt_topic: string; mqtt_lwt_online: string; mqtt_lwt_offline: string; diff --git a/webapp/src/types/MqttStatus.ts b/webapp/src/types/MqttStatus.ts index fe046ed..839d485 100644 --- a/webapp/src/types/MqttStatus.ts +++ b/webapp/src/types/MqttStatus.ts @@ -8,6 +8,8 @@ export interface MqttStatus { mqtt_retain: boolean; mqtt_tls: boolean; mqtt_root_ca_cert_info: string; + mqtt_tls_cert_login: boolean; + mqtt_client_cert_info: string; mqtt_connected: boolean; mqtt_hass_enabled: boolean; mqtt_hass_expire: boolean; diff --git a/webapp/src/views/MqttAdminView.vue b/webapp/src/views/MqttAdminView.vue index 1c6cde9..6cd5ef2 100644 --- a/webapp/src/views/MqttAdminView.vue +++ b/webapp/src/views/MqttAdminView.vue @@ -60,6 +60,21 @@ :label="$t('mqttadmin.RootCa')" v-model="mqttConfigList.mqtt_root_ca_cert" type="textarea" maxlength="2560" rows="10"/> + + + + + + {{ $t('mqttinfo.RootCertifcateInfo') }} {{ mqttDataList.mqtt_root_ca_cert_info }} + + {{ $t('mqttinfo.TlsCertLogin') }} + + + + + + {{ $t('mqttinfo.ClientCertifcateInfo') }} + {{ mqttDataList.mqtt_client_cert_info }} +