Add support X.509 client certificates for MQTT. (#5778)

Co-authored-by: h2zero <powellperalata@gmail.com>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
h2zero 2024-01-17 16:26:56 -07:00 committed by GitHub
parent b606e976e1
commit e731a2ffaa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 29 additions and 0 deletions

View file

@ -10,6 +10,8 @@ from esphome.const import (
CONF_BIRTH_MESSAGE, CONF_BIRTH_MESSAGE,
CONF_BROKER, CONF_BROKER,
CONF_CERTIFICATE_AUTHORITY, CONF_CERTIFICATE_AUTHORITY,
CONF_CLIENT_CERTIFICATE,
CONF_CLIENT_CERTIFICATE_KEY,
CONF_CLIENT_ID, CONF_CLIENT_ID,
CONF_COMMAND_TOPIC, CONF_COMMAND_TOPIC,
CONF_COMMAND_RETAIN, CONF_COMMAND_RETAIN,
@ -199,6 +201,12 @@ CONFIG_SCHEMA = cv.All(
cv.Optional(CONF_CERTIFICATE_AUTHORITY): cv.All( cv.Optional(CONF_CERTIFICATE_AUTHORITY): cv.All(
cv.string, cv.only_with_esp_idf cv.string, cv.only_with_esp_idf
), ),
cv.Inclusive(CONF_CLIENT_CERTIFICATE, "cert-key-pair"): cv.All(
cv.string, cv.only_on_esp32
),
cv.Inclusive(CONF_CLIENT_CERTIFICATE_KEY, "cert-key-pair"): cv.All(
cv.string, cv.only_on_esp32
),
cv.SplitDefault(CONF_SKIP_CERT_CN_CHECK, esp32_idf=False): cv.All( cv.SplitDefault(CONF_SKIP_CERT_CN_CHECK, esp32_idf=False): cv.All(
cv.boolean, cv.only_with_esp_idf cv.boolean, cv.only_with_esp_idf
), ),
@ -378,6 +386,9 @@ async def to_code(config):
if CONF_CERTIFICATE_AUTHORITY in config: if CONF_CERTIFICATE_AUTHORITY in config:
cg.add(var.set_ca_certificate(config[CONF_CERTIFICATE_AUTHORITY])) cg.add(var.set_ca_certificate(config[CONF_CERTIFICATE_AUTHORITY]))
cg.add(var.set_skip_cert_cn_check(config[CONF_SKIP_CERT_CN_CHECK])) cg.add(var.set_skip_cert_cn_check(config[CONF_SKIP_CERT_CN_CHECK]))
if CONF_CLIENT_CERTIFICATE in config:
cg.add(var.set_cl_certificate(config[CONF_CLIENT_CERTIFICATE]))
cg.add(var.set_cl_key(config[CONF_CLIENT_CERTIFICATE_KEY]))
# prevent error -0x428e # prevent error -0x428e
# See https://github.com/espressif/esp-idf/issues/139 # See https://github.com/espressif/esp-idf/issues/139

View file

@ -45,6 +45,11 @@ bool MQTTBackendESP32::initialize_() {
mqtt_cfg_.cert_pem = ca_certificate_.value().c_str(); mqtt_cfg_.cert_pem = ca_certificate_.value().c_str();
mqtt_cfg_.skip_cert_common_name_check = skip_cert_cn_check_; mqtt_cfg_.skip_cert_common_name_check = skip_cert_cn_check_;
mqtt_cfg_.transport = MQTT_TRANSPORT_OVER_SSL; mqtt_cfg_.transport = MQTT_TRANSPORT_OVER_SSL;
if (this->cl_certificate_.has_value() && this->cl_key_.has_value()) {
mqtt_cfg_.client_cert_pem = this->cl_certificate_.value().c_str();
mqtt_cfg_.client_key_pem = this->cl_key_.value().c_str();
}
} else { } else {
mqtt_cfg_.transport = MQTT_TRANSPORT_OVER_TCP; mqtt_cfg_.transport = MQTT_TRANSPORT_OVER_TCP;
} }
@ -79,6 +84,11 @@ bool MQTTBackendESP32::initialize_() {
mqtt_cfg_.broker.verification.certificate = ca_certificate_.value().c_str(); mqtt_cfg_.broker.verification.certificate = ca_certificate_.value().c_str();
mqtt_cfg_.broker.verification.skip_cert_common_name_check = skip_cert_cn_check_; mqtt_cfg_.broker.verification.skip_cert_common_name_check = skip_cert_cn_check_;
mqtt_cfg_.broker.address.transport = MQTT_TRANSPORT_OVER_SSL; mqtt_cfg_.broker.address.transport = MQTT_TRANSPORT_OVER_SSL;
if (this->cl_certificate_.has_value() && this->cl_key_.has_value()) {
mqtt_cfg_.credentials.authentication.certificate = this->cl_certificate_.value().c_str();
mqtt_cfg_.credentials.authentication.key = this->cl_key_.value().c_str();
}
} else { } else {
mqtt_cfg_.broker.address.transport = MQTT_TRANSPORT_OVER_TCP; mqtt_cfg_.broker.address.transport = MQTT_TRANSPORT_OVER_TCP;
} }

View file

@ -124,6 +124,8 @@ class MQTTBackendESP32 final : public MQTTBackend {
void loop() final; void loop() final;
void set_ca_certificate(const std::string &cert) { ca_certificate_ = cert; } void set_ca_certificate(const std::string &cert) { ca_certificate_ = cert; }
void set_cl_certificate(const std::string &cert) { cl_certificate_ = cert; }
void set_cl_key(const std::string &key) { cl_key_ = key; }
void set_skip_cert_cn_check(bool skip_check) { skip_cert_cn_check_ = skip_check; } void set_skip_cert_cn_check(bool skip_check) { skip_cert_cn_check_ = skip_check; }
protected: protected:
@ -154,6 +156,8 @@ class MQTTBackendESP32 final : public MQTTBackend {
uint16_t keep_alive_; uint16_t keep_alive_;
bool clean_session_; bool clean_session_;
optional<std::string> ca_certificate_; optional<std::string> ca_certificate_;
optional<std::string> cl_certificate_;
optional<std::string> cl_key_;
bool skip_cert_cn_check_{false}; bool skip_cert_cn_check_{false};
// callbacks // callbacks

View file

@ -146,6 +146,8 @@ class MQTTClientComponent : public Component {
#endif #endif
#ifdef USE_ESP32 #ifdef USE_ESP32
void set_ca_certificate(const char *cert) { this->mqtt_backend_.set_ca_certificate(cert); } void set_ca_certificate(const char *cert) { this->mqtt_backend_.set_ca_certificate(cert); }
void set_cl_certificate(const char *cert) { this->mqtt_backend_.set_cl_certificate(cert); }
void set_cl_key(const char *key) { this->mqtt_backend_.set_cl_key(key); }
void set_skip_cert_cn_check(bool skip_check) { this->mqtt_backend_.set_skip_cert_cn_check(skip_check); } void set_skip_cert_cn_check(bool skip_check) { this->mqtt_backend_.set_skip_cert_cn_check(skip_check); }
#endif #endif
const Availability &get_availability(); const Availability &get_availability();

View file

@ -112,6 +112,8 @@ CONF_CHANNELS = "channels"
CONF_CHARACTERISTIC_UUID = "characteristic_uuid" CONF_CHARACTERISTIC_UUID = "characteristic_uuid"
CONF_CHIPSET = "chipset" CONF_CHIPSET = "chipset"
CONF_CLEAR_IMPEDANCE = "clear_impedance" CONF_CLEAR_IMPEDANCE = "clear_impedance"
CONF_CLIENT_CERTIFICATE = "client_certificate"
CONF_CLIENT_CERTIFICATE_KEY = "client_certificate_key"
CONF_CLIENT_ID = "client_id" CONF_CLIENT_ID = "client_id"
CONF_CLK_PIN = "clk_pin" CONF_CLK_PIN = "clk_pin"
CONF_CLOCK_PIN = "clock_pin" CONF_CLOCK_PIN = "clock_pin"