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
"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:
- :isccmd:`config-get`
+- :isccmd:`config-hash-get`
+
- :isccmd:`config-reload`
- :isccmd:`config-set`
- :isccmd:`config-get`
+- :isccmd:`config-hash-get`
+
- :isccmd:`config-reload`
- :isccmd:`config-set`
- :isccmd:`build-report`
- :isccmd:`config-get`
+- :isccmd:`config-hash-get`
- :isccmd:`config-reload`
- :isccmd:`config-set`
- :isccmd:`config-test`
- :isccmd:`build-report`
- :isccmd:`config-get`
+- :isccmd:`config-hash-get`
- :isccmd:`config-reload`
- :isccmd:`config-set`
- :isccmd:`config-test`
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.
- :isccmd:`build-report`
- :isccmd:`config-get`
+- :isccmd:`config-hash-get`
- :isccmd:`config-reload`
- :isccmd:`config-set`
- :isccmd:`config-test`
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));
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);
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));
// 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);
#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>
#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>
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) {
} 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));
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));
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");
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)
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
#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 {
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
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
/// @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");
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
--- /dev/null
+{
+ "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"
+ ]
+}