From: Tomek Mrugalski Date: Wed, 21 Jun 2023 10:22:23 +0000 (+0200) Subject: [#2707] config-set in v6 now returns hash X-Git-Tag: Kea-2.4.0~132 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0738facc5509d559121aa12f952a094a9fa3dd2e;p=thirdparty%2Fkea.git [#2707] config-set in v6 now returns hash --- diff --git a/src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc b/src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc index f923901e17..f912c17ab1 100644 --- a/src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc +++ b/src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc @@ -933,6 +933,10 @@ TEST_F(CtrlChannelDhcpv4SrvTest, configHashGet) { int status; ConstElementPtr args = parseAnswer(status, rsp); EXPECT_EQ(CONTROL_RESULT_SUCCESS, status); + // the parseAnswer is trying to be smart with ignoring hash. + // But this time we really want to see the hash, so we'll retrieve + // the arguments manually. + args = rsp->get(CONTROL_ARGUMENTS); // Ok, now roughly check if the response seems legit. ASSERT_TRUE(args); diff --git a/src/bin/dhcp6/json_config_parser.cc b/src/bin/dhcp6/json_config_parser.cc index 324b8c34f1..c8fbfc79be 100644 --- a/src/bin/dhcp6/json_config_parser.cc +++ b/src/bin/dhcp6/json_config_parser.cc @@ -1099,8 +1099,14 @@ configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set, .arg(CfgMgr::instance().getStagingCfg()-> getConfigSummary(SrvConfig::CFGSEL_ALL6)); + // Also calculate SHA256 hash of the config that was just set and append it to the response. + ElementPtr config = CfgMgr::instance().getCurrentCfg()->toElement(); + string hash = BaseCommandMgr::getHash(config); + ElementPtr hash_map = Element::createMap(); + hash_map->set("hash", Element::create(hash)); + // Everything was fine. Configuration is successful. - answer = isc::config::createAnswer(CONTROL_RESULT_SUCCESS, "Configuration successful."); + answer = isc::config::createAnswer(CONTROL_RESULT_SUCCESS, "Configuration successful.", hash_map); return (answer); } diff --git a/src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc b/src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc index a0cd3fce0e..af2ba86c7d 100644 --- a/src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc +++ b/src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc @@ -729,9 +729,13 @@ TEST_F(CtrlChannelDhcpv6SrvTest, configSet) { std::string response; sendUnixCommand(os.str(), response); - // Verify the configuration was successful. - EXPECT_EQ("{ \"result\": 0, \"text\": \"Configuration successful.\" }", - response); + // Verify the configuration was successful. The config contains random + // socket name (/tmp/kea-/kea6.sock), so the + // hash will be different each time. As such, we can do simplified checks: + // - verify the "result": 0 is there + // - verify the "text": "Configuration successful." is there + EXPECT_NE(response.find("\"result\": 0"), std::string::npos); + EXPECT_NE(response.find("\"text\": \"Configuration successful.\""), std::string::npos); // Check that the config was indeed applied. const Subnet6Collection* subnets = @@ -793,9 +797,13 @@ TEST_F(CtrlChannelDhcpv6SrvTest, configSet) { // Verify the control channel socket no longer exists. EXPECT_FALSE(fileExists(socket_path_)); - // With no command channel, should still receive the response. - EXPECT_EQ("{ \"result\": 0, \"text\": \"Configuration successful.\" }", - response); + // Verify the configuration was successful. The config contains random + // socket name (/tmp/kea-/kea6.sock), so the + // hash will be different each time. As such, we can do simplified checks: + // - verify the "result": 0 is there + // - verify the "text": "Configuration successful." is there + EXPECT_NE(response.find("\"result\": 0"), std::string::npos); + EXPECT_NE(response.find("\"text\": \"Configuration successful.\""), std::string::npos); // Check that the config was not lost subnets = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getAll(); @@ -846,6 +854,10 @@ TEST_F(CtrlChannelDhcpv6SrvTest, configHashGet) { int status; ConstElementPtr args = parseAnswer(status, rsp); EXPECT_EQ(CONTROL_RESULT_SUCCESS, status); + // the parseAnswer is trying to be smart with ignoring hash. + // But this time we really want to see the hash, so we'll retrieve + // the arguments manually. + args = rsp->get(CONTROL_ARGUMENTS); // Ok, now roughly check if the response seems legit. ASSERT_TRUE(args); @@ -931,9 +943,13 @@ TEST_F(CtrlChannelDhcpv6SrvTest, configTest) { std::string response; sendUnixCommand(os.str(), response); - // Verify the configuration was successful. - EXPECT_EQ("{ \"result\": 0, \"text\": \"Configuration successful.\" }", - response); + // Verify the configuration was successful. The config contains random + // socket name (/tmp/kea-/kea6.sock), so the + // hash will be different each time. As such, we can do simplified checks: + // - verify the "result": 0 is there + // - verify the "text": "Configuration successful." is there + EXPECT_NE(response.find("\"result\": 0"), std::string::npos); + EXPECT_NE(response.find("\"text\": \"Configuration successful.\""), std::string::npos); // Check that the config was indeed applied. const Subnet6Collection* subnets = @@ -1603,9 +1619,14 @@ TEST_F(CtrlChannelDhcpv6SrvTest, configReloadValid) { // This command should reload test8.json config. sendUnixCommand("{ \"command\": \"config-reload\" }", response); - // Verify the configuration was successful. - EXPECT_EQ("{ \"result\": 0, \"text\": \"Configuration successful.\" }", - response); + + // Verify the configuration was successful. The config contains random + // socket name (/tmp/kea-/kea6.sock), so the + // hash will be different each time. As such, we can do simplified checks: + // - verify the "result": 0 is there + // - verify the "text": "Configuration successful." is there + EXPECT_NE(response.find("\"result\": 0"), std::string::npos); + EXPECT_NE(response.find("\"text\": \"Configuration successful.\""), std::string::npos); // Check that the config was indeed applied. const Subnet6Collection* subnets = diff --git a/src/bin/dhcp6/tests/hooks_unittest.cc b/src/bin/dhcp6/tests/hooks_unittest.cc index 3e59b7f9f3..d5246d0ea2 100644 --- a/src/bin/dhcp6/tests/hooks_unittest.cc +++ b/src/bin/dhcp6/tests/hooks_unittest.cc @@ -5648,7 +5648,10 @@ TEST_F(LoadUnloadDhcpv6SrvTest, Dhcpv6SrvConfigured) { parseAnswer(status_code, answer); if (parameters.empty()) { EXPECT_EQ(0, status_code); - EXPECT_EQ(answer->str(), R"({ "result": 0, "text": "Configuration successful." })"); + + EXPECT_EQ(answer->str(), "{ \"arguments\": { \"hash\": \"AF30DC19D03AB71CB5AB6A77C0B8D" + "2B4D8C5F5A939D7457DF723CBFB09F80744\" }, \"result\": 0, \"text\": " + "\"Configuration successful.\" }"); } else { EXPECT_EQ(1, status_code); if (parameters.find("fail-without-error") != string::npos) { diff --git a/src/lib/cc/command_interpreter.cc b/src/lib/cc/command_interpreter.cc index be7048e7db..5cb1747105 100644 --- a/src/lib/cc/command_interpreter.cc +++ b/src/lib/cc/command_interpreter.cc @@ -91,7 +91,11 @@ parseAnswer(int &rcode, const ConstElementPtr& msg) { // If there are arguments, return them. ConstElementPtr args = msg->get(CONTROL_ARGUMENTS); if (args) { - return (args); + // If the arguments contain only a hash (used in config-set/config-get), we can ignore them. + // We don't want to return arguments with just a hash. + if ( (args->getType()!=isc::data::Element::map) || (args->size() > 1) || !args->get("hash") ) { + return (args); + } } // There are no arguments, let's try to return just the text status diff --git a/src/lib/process/d_controller.cc b/src/lib/process/d_controller.cc index 363ba01155..feee1b178d 100644 --- a/src/lib/process/d_controller.cc +++ b/src/lib/process/d_controller.cc @@ -462,21 +462,10 @@ DControllerBase::configGetHandler(const std::string&, ConstElementPtr DControllerBase::configHashGetHandler(const std::string&, ConstElementPtr /*args*/) { - ConstElementPtr config = process_->getCfgMgr()->getContext()->toElement(); - // 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 hash; - hash.resize(hash_data.getLength()); - if (hash.size() > 0) { - memmove(&hash[0], hash_data.getData(), hash.size()); - } + ElementPtr config = process_->getCfgMgr()->getContext()->toElement(); + std::string hash = BaseCommandMgr::getHash(config); ElementPtr params = Element::createMap(); - params->set("hash", Element::create(encode::encodeHex(hash))); + params->set("hash", Element::create(hash)); return (createAnswer(CONTROL_RESULT_SUCCESS, params)); }