From: Francis Dupont Date: Thu, 8 Apr 2021 22:20:36 +0000 (+0200) Subject: [#1706] Checkpoint: syntax updated - need UTs? X-Git-Tag: Kea-1.9.7~43 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0d15b49c770f940f68707d9be3e757dbc68ebeb6;p=thirdparty%2Fkea.git [#1706] Checkpoint: syntax updated - need UTs? --- diff --git a/src/bin/agent/ca_cfg_mgr.h b/src/bin/agent/ca_cfg_mgr.h index df4e0f6dc7..78c722d827 100644 --- a/src/bin/agent/ca_cfg_mgr.h +++ b/src/bin/agent/ca_cfg_mgr.h @@ -119,8 +119,8 @@ public: /// @brief Sets trust-anchor parameter /// - /// @param ca Trust anchor aka Certificate Authority (can be a file or - /// with OpenSSL a directory). + /// @param ca Trust anchor aka Certificate Authority (can be a file name + /// or a directory path). void setTrustAnchor(const std::string& ca) { trust_anchor_ = ca; } @@ -225,8 +225,8 @@ private: /// TCP port the CA should listen on. uint16_t http_port_; - /// Trust anchor aka Certificate Authority (can be a file or with - /// OpenSSL a directory). + /// Trust anchor aka Certificate Authority (can be a file name or + /// a directory path). std::string trust_anchor_; /// Server certificate file name. diff --git a/src/hooks/dhcp/high_availability/ha_config.cc b/src/hooks/dhcp/high_availability/ha_config.cc index 67c2f8db06..7754f6f303 100644 --- a/src/hooks/dhcp/high_availability/ha_config.cc +++ b/src/hooks/dhcp/high_availability/ha_config.cc @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -27,8 +28,8 @@ namespace isc { namespace ha { HAConfig::PeerConfig::PeerConfig() - : name_(), url_(""), role_(STANDBY), auto_failover_(false), - basic_auth_() { + : name_(), url_(""), trust_anchor_(), cert_file_(), key_file_(), + role_(STANDBY), auto_failover_(false), basic_auth_() { } void @@ -165,6 +166,7 @@ HAConfig::HAConfig() max_ack_delay_(10000), max_unacked_clients_(10), wait_backup_ack_(false), enable_multi_threading_(false), http_dedicated_listener_(false), http_listener_threads_(0), http_client_threads_(0), + trust_anchor_(), cert_file_(), key_file_(), peers_(), state_machine_(new StateMachineConfig()) { } @@ -296,12 +298,43 @@ HAConfig::validate() { << " for server " << p->second->getName()); } - // Refuse HTTPS scheme as TLS is not (yet) supported. - if (p->second->getUrl().getScheme() == Url::HTTPS) { + // Check TLS setup. + bool use_tls = false; + Optional ca = p->second->getTrustAnchor(); + Optional cert = p->second->getCertFile(); + Optional key = p->second->getKeyFile(); + // When not configured get the value from the global level. + if (ca.unspecified()) { + ca = trust_anchor_; + } + if (cert.unspecified()) { + cert = cert_file_; + } + if (key.unspecified()) { + key = key_file_; + } + if (!ca.unspecified() || !cert.unspecified() || !key.unspecified()) { + use_tls = true; + try { + TlsContextPtr tls_context; + TlsContext::configure(tls_context, + TlsRole::CLIENT, + ca.get(), + cert.get(), + key.get()); + } catch (const isc::Exception& ex) { + isc_throw(HAConfigValidationError, "bad TLS config for server " + << p->second->getName() << ": " << ex.what()); + } + } + + // Refuse HTTPS scheme when TLS is not enabled. + if (!use_tls && (p->second->getUrl().getScheme() == Url::HTTPS)) { isc_throw(HAConfigValidationError, "bad url '" << p->second->getUrl().toText() << "': https scheme is not supported" - << " for server " << p->second->getName()); + << " for server " << p->second->getName() + << " where TLS is disabled"); } ++peers_cnt[p->second->getRole()]; diff --git a/src/hooks/dhcp/high_availability/ha_config.h b/src/hooks/dhcp/high_availability/ha_config.h index b730b80f29..359c7316e5 100644 --- a/src/hooks/dhcp/high_availability/ha_config.h +++ b/src/hooks/dhcp/high_availability/ha_config.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -98,6 +99,42 @@ public: url_ = url; } + /// @brief Return server's trust-anchor. + util::Optional getTrustAnchor() const { + return (trust_anchor_); + } + + /// @brief Sets server's trust-anchor. + /// + /// @param ca Trust anchor aka Certificate Authority. + void setTrustAnchor(const util::Optional& ca) { + trust_anchor_ = ca; + } + + /// @brief Return server's cert-file. + util::Optional getCertFile() const { + return (cert_file_); + } + + /// @brief Sets server's cert-file. + /// + /// @param cert Certificate file name. + void setCertFile(const util::Optional& cert) { + cert_file_ = cert; + } + + /// @brief Return server's key-file. + util::Optional getKeyFile() const { + return (key_file_); + } + + /// @brief Sets server's key-file. + /// + /// @param key Private key file name. + void setKeyFile(const util::Optional& key) { + key_file_ = key; + } + /// @brief Returns a string identifying a server used in logging. /// /// The label is constructed from server name and server URL. @@ -166,11 +203,14 @@ public: private: - std::string name_; ///< Server name. - http::Url url_; ///< Server URL. - Role role_; ///< Server role. - bool auto_failover_; ///< Auto failover state. - http::BasicHttpAuthPtr basic_auth_; ///< Basic HTTP authentication. + std::string name_; ///< Server name. + http::Url url_; ///< Server URL. + util::Optional trust_anchor_; ///< Server trust anchor. + util::Optional cert_file_; ///< Server cert file. + util::Optional key_file_; ///< Server key file. + Role role_; ///< Server role. + bool auto_failover_; ///< Auto failover state. + http::BasicHttpAuthPtr basic_auth_; ///< Basic HTTP authentication. }; /// @brief Pointer to the server's configuration. @@ -578,6 +618,41 @@ public: /// @param http_client_threads number of threads the client should use. void setHttpClientThreads(uint32_t http_client_threads) { http_client_threads_ = http_client_threads; + + /// @brief Return global trust-anchor. + util::Optional getTrustAnchor() const { + return (trust_anchor_); + } + + /// @brief Sets global trust-anchor. + /// + /// @param ca Trust anchor aka Certificate Authority. + void setTrustAnchor(const util::Optional& ca) { + trust_anchor_ = ca; + } + + /// @brief Return global cert-file. + util::Optional getCertFile() const { + return (cert_file_); + } + + /// @brief Sets global cert-file. + /// + /// @param cert Certificate file name. + void setCertFile(const util::Optional& cert) { + cert_file_ = cert; + } + + /// @brief Return global key-file. + util::Optional getKeyFile() const { + return (key_file_); + } + + /// @brief Sets global key-file. + /// + /// @param key Private key file name. + void setKeyFile(const util::Optional& key) { + key_file_ = key; } /// @brief Returns configuration of the specified server. @@ -641,26 +716,29 @@ public: /// @throw HAConfigValidationError if configuration is invalid. void validate(); - std::string this_server_name_; ///< This server name. - HAMode ha_mode_; ///< Mode of operation. - bool send_lease_updates_; ///< Send lease updates to partner? - bool sync_leases_; ///< Synchronize databases on startup? - uint32_t sync_timeout_; ///< Timeout for syncing lease database (ms) - uint32_t sync_page_limit_; ///< Page size limit while synchronizing - ///< leases. - uint32_t delayed_updates_limit_; ///< Maximum number of lease updates held - ///< for later send in communication-recovery. - uint32_t heartbeat_delay_; ///< Heartbeat delay in milliseconds. - uint32_t max_response_delay_; ///< Max delay in response to heartbeats. - uint32_t max_ack_delay_; ///< Maximum DHCP message ack delay. - uint32_t max_unacked_clients_; ///< Maximum number of unacked clients. - bool wait_backup_ack_; ///< Wait for lease update ack from backup? - bool enable_multi_threading_; ///< Enable multi-threading. - bool http_dedicated_listener_; ///< Enable use of own HTTP listener. - uint32_t http_listener_threads_; ///< Number of HTTP listener threads. - uint32_t http_client_threads_; ///< Number of HTTP client threads. - PeerConfigMap peers_; ///< Map of peers' configurations. - StateMachineConfigPtr state_machine_; ///< State machine configuration. + std::string this_server_name_; ///< This server name. + HAMode ha_mode_; ///< Mode of operation. + bool send_lease_updates_; ///< Send lease updates to partner? + bool sync_leases_; ///< Synchronize databases on startup? + uint32_t sync_timeout_; ///< Timeout for syncing lease database (ms) + uint32_t sync_page_limit_; ///< Page size limit while + ///< synchronizing leases. + uint32_t delayed_updates_limit_; ///< Maximum number of lease updates held + ///< for later send in communication-recovery. + uint32_t heartbeat_delay_; ///< Heartbeat delay in milliseconds. + uint32_t max_response_delay_; ///< Max delay in response to heartbeats. + uint32_t max_ack_delay_; ///< Maximum DHCP message ack delay. + uint32_t max_unacked_clients_; ///< Maximum number of unacked clients. + bool wait_backup_ack_; ///< Wait for lease update ack from backup? + bool enable_multi_threading_; ///< Enable multi-threading. + bool http_dedicated_listener_; ///< Enable use of own HTTP listener. + uint32_t http_listener_threads_; ///< Number of HTTP listener threads. + uint32_t http_client_threads_; ///< Number of HTTP client threads. + util::Optional trust_anchor_; ///< Trust anchor. + util::Optional cert_file_; ///< Certificate file. + util::Optional key_file_; ///< Private key file. + PeerConfigMap peers_; ///< Map of peers' configurations. + StateMachineConfigPtr state_machine_; ///< State machine configuration. }; /// @brief Pointer to the High Availability configuration structure. diff --git a/src/hooks/dhcp/high_availability/ha_config_parser.cc b/src/hooks/dhcp/high_availability/ha_config_parser.cc index 5b336a4f64..2d1a41033e 100644 --- a/src/hooks/dhcp/high_availability/ha_config_parser.cc +++ b/src/hooks/dhcp/high_availability/ha_config_parser.cc @@ -210,6 +210,24 @@ HAConfigParser::parseInternal(const HAConfigPtr& config_storage, threads = getAndValidateInteger(mt_config, "http-client-threads"); config_storage->setHttpClientThreads(threads); + // Get optional 'trust-anchor'. + ConstElementPtr ca = c->get("trust-anchor"); + if (ca) { + config_storage->setTrustAnchor(getString(c, ("trust-anchor"))); + } + + // Get optional 'cert-file'. + ConstElementPtr cert = c->get("cert-file"); + if (cert) { + config_storage->setCertFile(getString(c, ("cert-file"))); + } + + // Get optional 'key-file'. + ConstElementPtr key = c->get("key-file"); + if (key) { + config_storage->setKeyFile(getString(c, ("key-file"))); + } + // Peers configuration parsing. const auto& peers_vec = peers->listValue(); @@ -229,6 +247,21 @@ HAConfigParser::parseInternal(const HAConfigPtr& config_storage, // URL. cfg->setUrl(Url(getString((*p), "url"))); + // Optional trust anchor. + if ((*p)->contains("trust-anchor")) { + cfg->setTrustAnchor(getString(*p, ("trust-anchor"))); + } + + // Optional certificate file. + if ((*p)->contains("cert-file")) { + cfg->setCertFile(getString(*p, ("cert-file"))); + } + + // Optional private key file. + if ((*p)->contains("key-file")) { + cfg->setKeyFile(getString(*p, ("key-file"))); + } + // Role. cfg->setRole(getString(*p, "role")); diff --git a/src/hooks/dhcp/high_availability/tests/ha_config_unittest.cc b/src/hooks/dhcp/high_availability/tests/ha_config_unittest.cc index 16e7ad74e6..68c13eb789 100644 --- a/src/hooks/dhcp/high_availability/tests/ha_config_unittest.cc +++ b/src/hooks/dhcp/high_availability/tests/ha_config_unittest.cc @@ -676,7 +676,8 @@ TEST_F(HAConfigTest, badURLHttps) { " }" "]", "bad url 'https://127.0.0.1:8080/': " - "https scheme is not supported for server server2"); + "https scheme is not supported for server server2 " + "where TLS is disabled"); } // Only certain roles are allowed.