]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#2707] config-set in v6 now returns hash
authorTomek Mrugalski <tomek@isc.org>
Wed, 21 Jun 2023 10:22:23 +0000 (12:22 +0200)
committerTomek Mrugalski <tomek@isc.org>
Thu, 22 Jun 2023 14:23:38 +0000 (16:23 +0200)
src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc
src/bin/dhcp6/json_config_parser.cc
src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc
src/bin/dhcp6/tests/hooks_unittest.cc
src/lib/cc/command_interpreter.cc
src/lib/process/d_controller.cc

index f923901e17466ca1695564d064c63682321cbcc7..f912c17ab120caaa5b7de81e6e5faa40f64d9fdf 100644 (file)
@@ -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);
index 324b8c34f1185427890876d0302079a9e3df61bc..c8fbfc79be71a119dd2f8b9de163a4d0c454b8ec 100644 (file)
@@ -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);
 }
 
index a0cd3fce0e292cd7ff5d6f974cdffa7f4def00c0..af2ba86c7d5a048dd46aef5843f14f6cb76f48e2 100644 (file)
@@ -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-<value-changing-each-time>/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-<value-changing-each-time>/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-<value-changing-each-time>/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-<value-changing-each-time>/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 =
index 3e59b7f9f31d5de2fd5eb56af87ada7d6f858c0d..d5246d0ea231a70aa548a15f46de9fd28058eaf9 100644 (file)
@@ -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) {
index be7048e7db5752816d0433b17866f7ae7d12ef15..5cb1747105ba6ef85d5bb1ac321c55dd3bee994f 100644 (file)
@@ -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
index 363ba0115559d302aa3cc7f0f7d9b89dde5789a6..feee1b178d6fd576f2138b52de032260007d183d 100644 (file)
@@ -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<uint8_t> 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));
 }