]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#2707] Checkpoint
authorFrancis Dupont <fdupont@isc.org>
Mon, 5 Jun 2023 15:15:59 +0000 (17:15 +0200)
committerTomek Mrugalski <tomek@isc.org>
Thu, 22 Jun 2023 14:23:38 +0000 (16:23 +0200)
14 files changed:
doc/sphinx/api-files.txt
doc/sphinx/arm/ctrl-channel.rst
doc/sphinx/arm/ddns.rst
doc/sphinx/arm/dhcp4-srv.rst
doc/sphinx/arm/dhcp6-srv.rst
src/bin/agent/ca_controller.cc
src/bin/d2/d2_controller.cc
src/bin/dhcp4/ctrl_dhcp4_srv.cc
src/bin/dhcp4/ctrl_dhcp4_srv.h
src/lib/process/d_controller.cc
src/lib/process/d_controller.h
src/lib/process/d_process.h
src/share/api/api_files.mk
src/share/api/config-hash-get.json [new file with mode: 0644]

index b4b602e3b4793257def9168ed6acf44863e8662c..6d63c15aa9fcf54df4591dda90046b5d6c5ef0be 100644 (file)
@@ -15,6 +15,7 @@ src/share/api/class-list.json
 src/share/api/class-update.json
 src/share/api/config-backend-pull.json
 src/share/api/config-get.json
+src/share/api/config-hash-get.json
 src/share/api/config-reload.json
 src/share/api/config-set.json
 src/share/api/config-test.json
index 4ede42c02d2c005fb3ec85a6a4c9d669583236ad..017fe6bf19c7a3b35d22512331e45f85f8dd1ac4 100644 (file)
@@ -369,6 +369,35 @@ An example command invocation looks like this:
        "command": "config-get"
    }
 
+.. isccmd:: config-hash-get
+.. _command-config-hash-get:
+
+The ``config-hash-get`` Command
+-------------------------------
+
+The ``config-hash-get`` command retrieves the SHA-256 hash of the current
+configuration used by the server. This command does not take any parameters.
+The returned hash can be used to detect configuration changes.
+
+An example command invocation looks like this:
+
+::
+
+   {
+       "command": "config-hash-get"
+   }
+
+And the server's response:
+
+::
+
+   {
+       "result": 0,
+       "arguments": {
+           "hash": "5C3C90EF7035249E2FF74D003C19F34EE0B83A3D329E741B52B2EF95A2C9CC5C"
+        }
+    }
+
 .. isccmd:: config-reload
 .. _command-config-reload:
 
@@ -816,6 +845,8 @@ The D2 server supports only a subset of the DHCPv4/DHCPv6 server commands:
 
 -  :isccmd:`config-get`
 
+-  :isccmd:`config-hash-get`
+
 -  :isccmd:`config-reload`
 
 -  :isccmd:`config-set`
@@ -845,6 +876,8 @@ commands are handled by the CA and they relate to the CA process itself:
 
 -  :isccmd:`config-get`
 
+-  :isccmd:`config-hash-get`
+
 -  :isccmd:`config-reload`
 
 -  :isccmd:`config-set`
index 66d436289f5d3dc6b670d93fdd2c0ec7084e689c..b559255070e23bc4bea85897c522131aa552cdbc 100644 (file)
@@ -304,6 +304,7 @@ The D2 server supports the following operational commands:
 
 - :isccmd:`build-report`
 - :isccmd:`config-get`
+- :isccmd:`config-hash-get`
 - :isccmd:`config-reload`
 - :isccmd:`config-set`
 - :isccmd:`config-test`
index fb80e1d64bbd03c0af57d3a07195147fcb1d759c..acb915a13014d666b9a9e294f0e2d685849b5e99 100644 (file)
@@ -7336,6 +7336,7 @@ The DHCPv4 server supports the following operational commands:
 
 - :isccmd:`build-report`
 - :isccmd:`config-get`
+- :isccmd:`config-hash-get`
 - :isccmd:`config-reload`
 - :isccmd:`config-set`
 - :isccmd:`config-test`
index 1af7b60297589f43f1d642f7f648b53cd4a95666..6c1ed6a726816a4585693691143e598dae3efddb 100644 (file)
@@ -5002,7 +5002,7 @@ file and in the host database backend, via :ischooklib:`libdhcp_host_cmds.so`.
 
 Setting ``ip-reservations-unique`` to ``false`` when using memfile, MySQL or PostgreSQL is supported.
 This setting is not supported when using Host Cache (see :ref:`hooks-host-cache`), and the RADIUS backend
-(see :ref:`hooks-radius`).  These reservation backends simply do not support multiple reservations for the 
+(see :ref:`hooks-radius`).  These reservation backends simply do not support multiple reservations for the
 same IP.  If either of these hooks are loaded and ``ip-reservations-unique`` is set to ``false``, then a
 configuration error will be emitted and the server will fail to start.
 
@@ -7137,6 +7137,7 @@ The DHCPv6 server supports the following operational commands:
 
 - :isccmd:`build-report`
 - :isccmd:`config-get`
+- :isccmd:`config-hash-get`
 - :isccmd:`config-reload`
 - :isccmd:`config-set`
 - :isccmd:`config-test`
index 7c4a518aafa607b6ab1ad001f930d35bd2a5800e..bc7107357884697b0cd46b74d4787fc43e717515 100644 (file)
@@ -59,6 +59,9 @@ CtrlAgentController::registerCommands() {
     CtrlAgentCommandMgr::instance().registerCommand(CONFIG_GET_COMMAND,
         std::bind(&DControllerBase::configGetHandler, this, ph::_1, ph::_2));
 
+    CtrlAgentCommandMgr::instance().registerCommand(CONFIG_HASH_GET_COMMAND,
+        std::bind(&DControllerBase::configHashGetHandler, this, ph::_1, ph::_2));
+
     CtrlAgentCommandMgr::instance().registerCommand(CONFIG_RELOAD_COMMAND,
         std::bind(&DControllerBase::configReloadHandler, this, ph::_1, ph::_2));
 
@@ -85,6 +88,7 @@ void
 CtrlAgentController::deregisterCommands() {
     CtrlAgentCommandMgr::instance().deregisterCommand(BUILD_REPORT_COMMAND);
     CtrlAgentCommandMgr::instance().deregisterCommand(CONFIG_GET_COMMAND);
+    CtrlAgentCommandMgr::instance().deregisterCommand(CONFIG_HASH_GET_COMMAND);
     CtrlAgentCommandMgr::instance().deregisterCommand(CONFIG_RELOAD_COMMAND);
     CtrlAgentCommandMgr::instance().deregisterCommand(CONFIG_SET_COMMAND);
     CtrlAgentCommandMgr::instance().deregisterCommand(CONFIG_TEST_COMMAND);
index c9799d3c2caae993f868a58c8789b3d83d1bad9a..0d0d8167915b8922929fbdf48fb52d790d6ff8af 100644 (file)
@@ -62,6 +62,9 @@ D2Controller::registerCommands() {
     CommandMgr::instance().registerCommand(CONFIG_GET_COMMAND,
         std::bind(&D2Controller::configGetHandler, this, ph::_1, ph::_2));
 
+    CommandMgr::instance().registerCommand(CONFIG_HASH_GET_COMMAND,
+        std::bind(&D2Controller::configHashGetHandler, this, ph::_1, ph::_2));
+
     CommandMgr::instance().registerCommand(CONFIG_RELOAD_COMMAND,
         std::bind(&D2Controller::configReloadHandler, this, ph::_1, ph::_2));
 
@@ -106,6 +109,7 @@ D2Controller::deregisterCommands() {
         // Deregister any registered commands (please keep in alphabetic order)
         CommandMgr::instance().deregisterCommand(BUILD_REPORT_COMMAND);
         CommandMgr::instance().deregisterCommand(CONFIG_GET_COMMAND);
+        CommandMgr::instance().deregisterCommand(CONFIG_HASH_GET_COMMAND);
         CommandMgr::instance().deregisterCommand(CONFIG_RELOAD_COMMAND);
         CommandMgr::instance().deregisterCommand(CONFIG_SET_COMMAND);
         CommandMgr::instance().deregisterCommand(CONFIG_TEST_COMMAND);
index 8dfac250d98d310de7a04f037958414216ae310f..03917c50a9f4d2575f1eadcc9b91237abf388dad 100644 (file)
@@ -9,6 +9,7 @@
 #include <cc/command_interpreter.h>
 #include <cc/data.h>
 #include <config/command_mgr.h>
+#include <cryptolink/crypto_hash.h>
 #include <dhcp/libdhcp++.h>
 #include <dhcp4/ctrl_dhcp4_srv.h>
 #include <dhcp4/dhcp4_log.h>
@@ -25,6 +26,7 @@
 #include <hooks/hooks_manager.h>
 #include <process/cfgrpt/config_report.h>
 #include <stats/stats_mgr.h>
+#include <util/encode/hex.h>
 #include <util/multi_threading_mgr.h>
 
 #include <signal.h>
@@ -289,6 +291,27 @@ ControlledDhcpv4Srv::commandConfigGetHandler(const string&,
     return (createAnswer(CONTROL_RESULT_SUCCESS, config));
 }
 
+ConstElementPtr
+ControlledDhcpv4Srv::commandConfigHashGetHandler(const string&,
+                                                 ConstElementPtr /*args*/) {
+    ConstElementPtr config = CfgMgr::instance().getCurrentCfg()->toElement();
+    // Assume that config is never null.
+    string config_txt = config->str();
+    OutputBuffer hash_data(0);
+    isc::cryptolink::digest(config_txt.c_str(),
+                            config_txt.size(),
+                            isc::cryptolink::HashAlgorithm::SHA256,
+                            hash_data);
+    vector<uint8_t> hash;
+    hash.resize(hash_data.getLength());
+    if (hash.size() > 0) {
+        memmove(&hash[0], hash_data.getData(), hash.size());
+    }
+    ElementPtr params = Element::createMap();
+    params->set("hash", Element::create(encode::encodeHex(hash)));
+    return (createAnswer(CONTROL_RESULT_SUCCESS, params));
+}
+
 ConstElementPtr
 ControlledDhcpv4Srv::commandConfigWriteHandler(const string&,
                                                ConstElementPtr args) {
@@ -839,6 +862,9 @@ ControlledDhcpv4Srv::processCommand(const string& command,
         } else if (command == "config-get") {
             return (srv->commandConfigGetHandler(command, args));
 
+        } else if (command == "config-hash-get") {
+            return (srv->commandConfigHashGetHandler(command, args));
+
         } else if (command == "config-test") {
             return (srv->commandConfigTestHandler(command, args));
 
@@ -1145,6 +1171,9 @@ ControlledDhcpv4Srv::ControlledDhcpv4Srv(uint16_t server_port /*= DHCP4_SERVER_P
     CommandMgr::instance().registerCommand("config-get",
         std::bind(&ControlledDhcpv4Srv::commandConfigGetHandler, this, ph::_1, ph::_2));
 
+    CommandMgr::instance().registerCommand("config-hash-get",
+        std::bind(&ControlledDhcpv4Srv::commandConfigHashGetHandler, this, ph::_1, ph::_2));
+
     CommandMgr::instance().registerCommand("config-reload",
         std::bind(&ControlledDhcpv4Srv::commandConfigReloadHandler, this, ph::_1, ph::_2));
 
@@ -1241,6 +1270,7 @@ ControlledDhcpv4Srv::~ControlledDhcpv4Srv() {
         CommandMgr::instance().deregisterCommand("build-report");
         CommandMgr::instance().deregisterCommand("config-backend-pull");
         CommandMgr::instance().deregisterCommand("config-get");
+        CommandMgr::instance().deregisterCommand("config-hash-get");
         CommandMgr::instance().deregisterCommand("config-reload");
         CommandMgr::instance().deregisterCommand("config-set");
         CommandMgr::instance().deregisterCommand("config-test");
index 564399cba77d0e2fe91d967af84597f496ec76cc..b18f9dd9141028ab8b760259f16ce9574319c6da 100644 (file)
@@ -193,9 +193,9 @@ private:
     commandConfigReloadHandler(const std::string& command,
                                isc::data::ConstElementPtr args);
 
-    /// @brief handler for processing 'get-config' command
+    /// @brief handler for processing 'config-get' command
     ///
-    /// This handler processes get-config command, which retrieves
+    /// This handler processes config-get command, which retrieves
     /// the current configuration and returns it in response.
     ///
     /// @param command (ignored)
@@ -205,9 +205,21 @@ private:
     commandConfigGetHandler(const std::string& command,
                             isc::data::ConstElementPtr args);
 
-    /// @brief handler for processing 'write-config' command
+    /// @brief handler for processing 'config-hash-get' command
     ///
-    /// This handle processes write-config command, which writes the
+    /// This handler processes config-hash-get command, which retrieves
+    /// the hash of the current configuration and returns it in response.
+    ///
+    /// @param command (ignored)
+    /// @param args (ignored)
+    /// @return hash of current configuration wrapped in a response
+    isc::data::ConstElementPtr
+    commandConfigHashGetHandler(const std::string& command,
+                                isc::data::ConstElementPtr args);
+
+    /// @brief handler for processing 'config-write' command
+    ///
+    /// This handle processes config-write command, which writes the
     /// current configuration to disk. This command takes one optional
     /// parameter called filename. If specified, the current configuration
     /// will be written to that file. If not specified, the file used during
index 5c115252271e14224ecdd284d875ef8350813308..077e08c0d31f847ae0eef5e713498f19caf766ee 100644 (file)
@@ -7,10 +7,12 @@
 #include <config.h>
 #include <cc/command_interpreter.h>
 #include <process/cfgrpt/config_report.h>
+#include <cryptolink/crypto_hash.h>
 #include <exceptions/exceptions.h>
 #include <hooks/hooks_manager.h>
 #include <log/logger.h>
 #include <log/logger_support.h>
+#include <util/encode/hex.h>
 #include <process/daemon.h>
 #include <process/d_log.h>
 #include <process/d_controller.h>
 #include <signal.h>
 
 using namespace isc::asiolink;
-using namespace isc::data;
 using namespace isc::config;
+using namespace isc::data;
 using namespace isc::hooks;
+using namespace isc::util;
 namespace ph = std::placeholders;
 
 namespace isc {
@@ -448,8 +451,21 @@ ConstElementPtr
 DControllerBase::configGetHandler(const std::string&,
                                   ConstElementPtr /*args*/) {
     ConstElementPtr config = process_->getCfgMgr()->getContext()->toElement();
-
-    return (createAnswer(CONTROL_RESULT_SUCCESS, config));
+    // Assume that config is never null.
+    std::string config_txt = config->str();
+    OutputBuffer hash_data(0);
+    isc::cryptolink::digest(config_txt.c_str(),
+                            config_txt.size(),
+                            isc::cryptolink::HashAlgorithm::SHA256,
+                            hash_data);
+    std::vector<uint8_t> hash;
+    hash.resize(hash_data.getLength());
+    if (hash.size() > 0) {
+        memmove(&hash[0], hash_data.getData(), hash.size());
+    }
+    ElementPtr params = Element::createMap();
+    params->set("hash", Element::create(encode::encodeHex(hash)));
+    return (createAnswer(CONTROL_RESULT_SUCCESS, params));
 }
 
 ConstElementPtr
index 53c4abb75e9a03ab22ff0fbd7f41b714e25d36df..e16253e372ecfe1dbe96c7aa2ce44bb8dde2f4f2 100644 (file)
@@ -265,6 +265,18 @@ public:
     configGetHandler(const std::string& command,
                      isc::data::ConstElementPtr args);
 
+    /// @brief handler for config-hash-get command
+    ///
+    /// This method handles the config-hash-get command, which retrieves
+    /// the current configuration and returns it in response.
+    ///
+    /// @param command (ignored)
+    /// @param args (ignored)
+    /// @return hash of current configuration wrapped in a response
+    isc::data::ConstElementPtr
+    configHashGetHandler(const std::string& command,
+                         isc::data::ConstElementPtr args);
+
     /// @brief handler for config-write command
     ///
     /// This handle processes write-config command, which writes the
index 472e708f6f9d584fa90a71e51d2ed0760d737e0b..e2b93096951c169d14ac7026bc7a33462bdbd70b 100644 (file)
@@ -36,6 +36,9 @@ static const std::string BUILD_REPORT_COMMAND("build-report");
 /// @brief String value for the config-get command.
 static const std::string CONFIG_GET_COMMAND("config-get");
 
+/// @brief String value for the config-hash-get command.
+static const std::string CONFIG_HASH_GET_COMMAND("config-hash-get");
+
 /// @brief String value for the config-write command.
 static const std::string CONFIG_WRITE_COMMAND("config-write");
 
index f10286bdb0ed0eda0233bcff1d189a31f63b201c..a9ff829f8cf9cff0d567344b2591b31a3e23b922 100644 (file)
@@ -15,6 +15,7 @@ api_files += $(top_srcdir)/src/share/api/class-list.json
 api_files += $(top_srcdir)/src/share/api/class-update.json
 api_files += $(top_srcdir)/src/share/api/config-backend-pull.json
 api_files += $(top_srcdir)/src/share/api/config-get.json
+api_files += $(top_srcdir)/src/share/api/config-hash-get.json
 api_files += $(top_srcdir)/src/share/api/config-reload.json
 api_files += $(top_srcdir)/src/share/api/config-set.json
 api_files += $(top_srcdir)/src/share/api/config-test.json
diff --git a/src/share/api/config-hash-get.json b/src/share/api/config-hash-get.json
new file mode 100644 (file)
index 0000000..d85abd1
--- /dev/null
@@ -0,0 +1,30 @@
+{
+    "access": "read",
+    "avail": "2.4.0",
+    "brief": [
+        "This command retrieves the hash of the current configuration used by the server. The configuration is essentially the same as the contents of the configuration file, but includes additional changes made by other commands and due to parameters' inheritance."
+    ],
+    "cmd-comment": [
+        "This command takes no parameters."
+    ],
+    "cmd-syntax": [
+        "{",
+        "    \"command\": \"config-hash-get\"",
+        "}"
+    ],
+    "name": "config-hash-get",
+    "resp-syntax": [
+        "{",
+        "    \"result\": <integer>,",
+        "    \"arguments\": {",
+        "        \"hash\": <SHA256 hash of the config in hexa> ",
+        "    }",
+        "}"
+    ],
+    "support": [
+        "kea-dhcp4",
+        "kea-dhcp6",
+        "kea-dhcp-ddns",
+        "kea-ctrl-agent"
+    ]
+}