are required and verified, i.e. like ``cert-required``. It defaults
to true and is a HA config (vs peer config) parameter.
+Kea 2.2.0 adds to a new security feature with the ``restrict-commands``
+HA config parameter: when it is configured to ``true`` (default is
+``false``) commands which are not used by the hook are rejected.
+
Following is an example of HA server pair and Control Agent
configuration for Hot-Standby with TLS.
-// Copyright (C) 2018-2021 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2018-2022 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
using namespace isc::data;
using namespace isc::dhcp;
+using namespace std;
namespace isc {
namespace ha {
+unordered_set<string> CommandCreator::ha_commands4_ = {
+ "list-commands", "status-get",
+ "dhcp-disable", "dhcp-enable", "ha-reset", "ha-heartbeat",
+ "lease4-update", "lease4-del", "lease4-get-all", "lease4-get-page",
+ "ha-maintenance-notify", "ha-sync-complete-notify"
+};
+
+unordered_set<string> CommandCreator::ha_commands6_ = {
+ "list-commands", "status-get",
+ "dhcp-disable", "dhcp-enable", "ha-reset", "ha-heartbeat",
+ "lease6-bulk-apply", "lease6-update", "lease6-del", "lease6-get-all",
+ "lease6-get-page",
+ "ha-maintenance-notify", "ha-sync-complete-notify"
+};
+
ConstElementPtr
CommandCreator::createDHCPDisable(const unsigned int max_period,
const HAServerType& server_type) {
CommandCreator::insertService(ConstElementPtr& command,
const HAServerType& server_type) {
ElementPtr service = Element::createList();
- const std::string service_name = (server_type == HAServerType::DHCPv4 ? "dhcp4" : "dhcp6");
+ const string service_name = (server_type == HAServerType::DHCPv4 ? "dhcp4" : "dhcp6");
service->add(Element::create(service_name));
// We have no better way of setting a new element here than
-// Copyright (C) 2018-2021 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2018-2022 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
#include <ha_server_type.h>
#include <cc/data.h>
#include <dhcpsrv/lease.h>
+#include <unordered_set>
#include <string>
namespace isc {
static data::ConstElementPtr
createSyncCompleteNotify(const HAServerType& server_type);
+ /// @brief List of commands used by the High Availability in v4.
+ static std::unordered_set<std::string> ha_commands4_;
+
+ /// @brief List of commands used by the High Availability in v6.
+ static std::unordered_set<std::string> ha_commands6_;
+
private:
/// @brief Replaces "cltt" with "expire" value within the lease.
enable_multi_threading_(false), http_dedicated_listener_(false),
http_listener_threads_(0), http_client_threads_(0),
trust_anchor_(), cert_file_(), key_file_(), require_client_certs_(true),
- peers_(), state_machine_(new StateMachineConfig()) {
+ restrict_commands_(false), peers_(),
+ state_machine_(new StateMachineConfig()) {
}
HAConfig::PeerConfigPtr
require_client_certs_ = flag;
}
+ /// @brief Returns restrict-commands.
+ bool getRestrictCommands() const {
+ return (restrict_commands_);
+ }
+
+ /// @brief Sets restrict-commands.
+ ///
+ /// @param flag Restrict commands to HA flag value.
+ void setRestrictCommands(bool flag) {
+ restrict_commands_ = flag;
+ }
+
/// @brief Returns configuration of the specified server.
///
/// @param name Server name.
util::Optional<std::string> cert_file_; ///< Certificate file.
util::Optional<std::string> key_file_; ///< Private key file.
bool require_client_certs_; ///< Require client certs flag.
+ bool restrict_commands_; ///< Restrict commands to HA flag.
PeerConfigMap peers_; ///< Map of peers' configurations.
StateMachineConfigPtr state_machine_; ///< State machine configuration.
};
{ "max-response-delay", Element::integer, "60000" },
{ "max-unacked-clients", Element::integer, "10" },
{ "require-client-certs", Element::boolean, "true" },
+ { "restrict-commands", Element::boolean, "false" },
{ "send-lease-updates", Element::boolean, "true" },
{ "sync-leases", Element::boolean, "true" },
{ "sync-timeout", Element::integer, "60000" },
// Get 'require-client-certs'.
config_storage->setRequireClientCerts(getBoolean(c, "require-client-certs"));
+ // Get 'restrict-commands'.
+ config_storage->setRestrictCommands(getBoolean(c, "restrict-commands"));
+
// Peers configuration parsing.
const auto& peers_vec = peers->listValue();
#include <ha_service_states.h>
#include <cc/command_interpreter.h>
#include <cc/data.h>
+#include <config/cmd_response_creator.h>
#include <config/timeouts.h>
#include <dhcp/iface_mgr.h>
#include <dhcpsrv/cfgmgr.h>
// Instantiate the listener.
listener_.reset(new CmdHttpListener(server_address, my_url.getPort(),
listener_threads, tls_context));
+ // Set the command filter when enabled.
+ if (config_->getRestrictCommands()) {
+ if (server_type == HAServerType::DHCPv4) {
+ CmdResponseCreator::command_accept_list_ =
+ CommandCreator::ha_commands4_;
+ } else {
+ CmdResponseCreator::command_accept_list_ =
+ CommandCreator::ha_commands6_;
+ }
+ }
}
}
" \"cert-file\": \"!CA!/kea-client.crt\","
" \"key-file\": \"!CA!/kea-client.key\","
" \"require-client-certs\": false,"
+ " \"restrict-commands\": true,"
" \"peers\": ["
" {"
" \"name\": \"my-server\","
expected += "/kea-client.key";
EXPECT_EQ(expected, impl->getConfig()->getKeyFile().get());
EXPECT_FALSE(impl->getConfig()->getRequireClientCerts());
+ EXPECT_TRUE(impl->getConfig()->getRestrictCommands());
// Check the first peer parameters: it inherits them from the global level.
HAConfig::PeerConfigPtr cfg = impl->getConfig()->getThisServerConfig();
#include <config.h>
#include <asiolink/asio_wrapper.h>
+#include <config/cmd_response_creator.h>
#include <ha_test.h>
#include <ha_config.h>
#include <ha_service.h>
HAMtServiceTest()
: HATest() {
MultiThreadingMgr::instance().setMode(true);
+ CmdResponseCreator::command_accept_list_.clear();
}
/// @brief Destructor.
io_service_->get_io_service().reset();
io_service_->poll();
MultiThreadingMgr::instance().setMode(false);
+ CmdResponseCreator::command_accept_list_.clear();
}
/// @brief Callback function invoke upon test timeout.
" \"this-server-name\": \"server1\","
" \"mode\": \"passive-backup\","
" \"wait-backup-ack\": true,"
+ " \"restrict-commands\": true,"
" \"peers\": ["
" {"
" \"name\": \"server1\","
// Multi-threading should be enabled.
ASSERT_TRUE(ha_config->getEnableMultiThreading());
+ // Command filtering is enabled.
+ EXPECT_FALSE(CmdResponseCreator::command_accept_list_.empty());
+
// Now we'll start, pause, resume and stop a few times.
for (int i = 0; i < 3; ++i) {
// Verify we're stopped.