diff --git a/src/bin/agent/tests/ca_controller_unittests.cc b/src/bin/agent/tests/ca_controller_unittests.cc index df7c747087..c5b800d5cc 100644 --- a/src/bin/agent/tests/ca_controller_unittests.cc +++ b/src/bin/agent/tests/ca_controller_unittests.cc @@ -866,6 +866,54 @@ TEST_F(CtrlAgentControllerTest, configWrite) { ctrl->deregisterCommands(); } +// Tests that config-write fails with a bad path. +TEST_F(CtrlAgentControllerTest, badConfigWrite) { + ASSERT_NO_THROW(initProcess()); + EXPECT_TRUE(checkProcess()); + + // The framework available makes it very difficult to test the actual + // code as CtrlAgentController is not initialized the same way it is + // in production code. In particular, the way CtrlAgentController + // is initialized in tests does not call registerCommands(). + // This is a crude workaround for this problem. Proper solution should + // be developed sooner rather than later. + const DControllerBasePtr& base = getController(); + const CtrlAgentControllerPtr& ctrl + = boost::dynamic_pointer_cast(base); + ASSERT_TRUE(ctrl); + // Now clean up after ourselves. + ctrl->registerCommands(); + + // Add a config file. + ctrl->setConfigFile(string(TEST_DATA_BUILDDIR) + string("/config.json")); + + // First, build the command: + string file("/tmp/config-write.json"); + string cmd_txt = "{ \"command\": \"config-write\" }"; + ConstElementPtr cmd = Element::fromJSON(cmd_txt); + ConstElementPtr params = Element::fromJSON("{\"filename\": \"" + file + "\" }"); + CtrlAgentCommandMgr& mgr_ = CtrlAgentCommandMgr::instance(); + + // Send the command + ConstElementPtr answer = mgr_.handleCommand("config-write", params, cmd); + + // Check that the command failed. + string expected = "not allowed to write config into "; + expected += file; + expected += ": file "; + expected += file; + expected += " must be in the same directory as the config file ("; + expected += string(TEST_DATA_BUILDDIR) + string("/config.json"); + expected += ")"; + checkAnswer(answer, isc::config::CONTROL_RESULT_ERROR, expected); + + // Remove the file. + ::remove(file.c_str()); + + // Now clean up after ourselves. + ctrl->deregisterCommands(); +} + // Tests if config-reload attempts to reload a file and reports that the // file is missing. TEST_F(CtrlAgentControllerTest, configReloadMissingFile) { diff --git a/src/bin/d2/tests/d2_command_unittest.cc b/src/bin/d2/tests/d2_command_unittest.cc index 1b35867733..f83f5cd88b 100644 --- a/src/bin/d2/tests/d2_command_unittest.cc +++ b/src/bin/d2/tests/d2_command_unittest.cc @@ -1012,6 +1012,9 @@ TEST_F(CtrlChannelD2Test, writeConfigFilename) { EXPECT_NO_THROW(createUnixChannelServer()); string response; + // This is normally set by the command line -c parameter. + server_->setConfigFile("test1.json"); + sendUnixCommand("{ \"command\": \"config-write\", " "\"arguments\": { \"filename\": \"test2.json\" } }", response); @@ -1020,6 +1023,60 @@ TEST_F(CtrlChannelD2Test, writeConfigFilename) { ::remove("test2.json"); } +// Tests if config-write can be called with a valid full path as parameter. +TEST_F(CtrlChannelD2Test, configWriteFullPath) { + createUnixChannelServer(); + std::string response; + + // This is normally set by the command line -c parameter. + server_->setConfigFile("/tmp/test1.json"); + + sendUnixCommand("{ \"command\": \"config-write\", " + "\"arguments\": { \"filename\": \"/tmp/test2.json\" } }", + response); + + checkConfigWrite(response, CONTROL_RESULT_SUCCESS, "/tmp/test2.json"); + ::remove("/tmp/test2.json"); +} + +// Tests if config-write raises an error with invalid path as parameter. +TEST_F(CtrlChannelD2Test, configWriteBadPath) { + createUnixChannelServer(); + std::string response; + + // This is normally set by the command line -c parameter. + server_->setConfigFile("test1.json"); + + sendUnixCommand("{ \"command\": \"config-write\", " + "\"arguments\": { \"filename\": \"/tmp/test2.json\" } }", + response); + + string expected = "not allowed to write config into /tmp/test2.json: "; + expected += "file /tmp/test2.json must be in the same directory "; + expected += "as the config file (test1.json)"; + checkConfigWrite(response, CONTROL_RESULT_ERROR, expected); + ::remove("/tmp/test2.json"); +} + +// Tests if config-write raises an error with invalid full path as parameter. +TEST_F(CtrlChannelD2Test, configWriteBadFullPath) { + createUnixChannelServer(); + std::string response; + + // This is normally set by the command line -c parameter. + server_->setConfigFile("/tmp/kea1/test.json"); + + sendUnixCommand("{ \"command\": \"config-write\", " + "\"arguments\": { \"filename\": \"/tmp/kea2/test.json\" } }", + response); + + string expected = "not allowed to write config into /tmp/kea2/test.json: "; + expected += "file /tmp/kea2/test.json must be in the same directory "; + expected += "as the config file (/tmp/kea1/test.json)"; + checkConfigWrite(response, CONTROL_RESULT_ERROR, expected); + ::remove("/tmp/kea2/test.json"); +} + // Tests if config-reload attempts to reload a file and reports that the // file is missing. TEST_F(CtrlChannelD2Test, configReloadMissingFile) { diff --git a/src/bin/d2/tests/d2_http_command_unittest.cc b/src/bin/d2/tests/d2_http_command_unittest.cc index 0f48e61f76..ed243b15db 100644 --- a/src/bin/d2/tests/d2_http_command_unittest.cc +++ b/src/bin/d2/tests/d2_http_command_unittest.cc @@ -368,6 +368,12 @@ public: ASSERT_TRUE(from_file); } else if (exp_status == CONTROL_RESULT_ERROR) { + // Errors can be in a list. + if (rsp->getType() == Element::list) { + ASSERT_EQ(1, rsp->size()); + rsp = rsp->get(0); + } + // Let's check if the reason for failure was given. ConstElementPtr text = rsp->get("text"); ASSERT_TRUE(text); @@ -450,10 +456,19 @@ public: void testConfigHashGet(); // Tests if config-write can be called without any parameters. - void testWriteConfigNoFilename(); + void testConfigWriteNoFilename(); // Tests if config-write can be called with a valid filename as parameter. - void testWriteConfigFilename(); + void testConfigWriteFilename(); + + // Tests if config-write can be called with a valid full path as parameter. + void testConfigWriteFullPath(); + + // Tests if config-write raises an error with invalid path as parameter. + void testConfigWriteBadPath(); + + // Tests if config-write raises an error with invalid full path as parameter. + void testConfigWriteBadFullPath(); // Tests if config-reload attempts to reload a file and reports that the // file is missing. @@ -1437,7 +1452,7 @@ TEST_F(HttpsCtrlChannelD2Test, configSet) { // Tests if config-write can be called without any parameters. void -BaseCtrlChannelD2Test::testWriteConfigNoFilename() { +BaseCtrlChannelD2Test::testConfigWriteNoFilename() { EXPECT_NO_THROW(createHttpChannelServer()); string response; @@ -1452,17 +1467,17 @@ BaseCtrlChannelD2Test::testWriteConfigNoFilename() { ::remove("test1.json"); } -TEST_F(HttpCtrlChannelD2Test, writeConfigNoFilename) { - testWriteConfigNoFilename(); +TEST_F(HttpCtrlChannelD2Test, configWriteNoFilename) { + testConfigWriteNoFilename(); } -TEST_F(HttpsCtrlChannelD2Test, writeConfigNoFilename) { - testWriteConfigNoFilename(); +TEST_F(HttpsCtrlChannelD2Test, configWriteNoFilename) { + testConfigWriteNoFilename(); } // Tests if config-write can be called with a valid filename as parameter. void -BaseCtrlChannelD2Test::testWriteConfigFilename() { +BaseCtrlChannelD2Test::testConfigWriteFilename() { EXPECT_NO_THROW(createHttpChannelServer()); string response; @@ -1474,12 +1489,93 @@ BaseCtrlChannelD2Test::testWriteConfigFilename() { ::remove("test2.json"); } -TEST_F(HttpCtrlChannelD2Test, writeConfigFilename) { - testWriteConfigFilename(); +TEST_F(HttpCtrlChannelD2Test, configWriteFilename) { + testConfigWriteFilename(); } -TEST_F(HttpsCtrlChannelD2Test, writeConfigFilename) { - testWriteConfigFilename(); +TEST_F(HttpsCtrlChannelD2Test, configWriteFilename) { + testConfigWriteFilename(); +} + +// Tests if config-write can be called with a valid full path as parameter. +void +BaseCtrlChannelD2Test::testConfigWriteFullPath() { + createHttpChannelServer(); + std::string response; + + // This is normally set by the command line -c parameter. + server_->setConfigFile("/tmp/test1.json"); + + sendHttpCommand("{ \"command\": \"config-write\", " + "\"arguments\": { \"filename\": \"/tmp/test2.json\" } }", + response); + + checkConfigWrite(response, CONTROL_RESULT_SUCCESS, "/tmp/test2.json"); + ::remove("/tmp/test2.json"); +} + +TEST_F(HttpCtrlChannelD2Test, configWriteFullPath) { + testConfigWriteFullPath(); +} + +TEST_F(HttpsCtrlChannelD2Test, configWriteFullPath) { + testConfigWriteFullPath(); +} + +// Tests if config-write raises an error with invalid path as parameter. +void +BaseCtrlChannelD2Test::testConfigWriteBadPath() { + createHttpChannelServer(); + std::string response; + + // This is normally set by the command line -c parameter. + server_->setConfigFile("test1.json"); + + sendHttpCommand("{ \"command\": \"config-write\", " + "\"arguments\": { \"filename\": \"/tmp/test2.json\" } }", + response); + + string expected = "not allowed to write config into /tmp/test2.json: "; + expected += "file /tmp/test2.json must be in the same directory "; + expected += "as the config file (test1.json)"; + checkConfigWrite(response, CONTROL_RESULT_ERROR, expected); + ::remove("/tmp/test2.json"); +} + +TEST_F(HttpCtrlChannelD2Test, configWriteBadPath) { + testConfigWriteBadPath(); +} + +TEST_F(HttpsCtrlChannelD2Test, configWriteBadPath) { + testConfigWriteBadPath(); +} + +// Tests if config-write raises an error with invalid full path as parameter. +void +BaseCtrlChannelD2Test::testConfigWriteBadFullPath() { + createHttpChannelServer(); + std::string response; + + // This is normally set by the command line -c parameter. + server_->setConfigFile("/tmp/kea1/test.json"); + + sendHttpCommand("{ \"command\": \"config-write\", " + "\"arguments\": { \"filename\": \"/tmp/kea2/test.json\" } }", + response); + + string expected = "not allowed to write config into /tmp/kea2/test.json: "; + expected += "file /tmp/kea2/test.json must be in the same directory "; + expected += "as the config file (/tmp/kea1/test.json)"; + checkConfigWrite(response, CONTROL_RESULT_ERROR, expected); + ::remove("/tmp/kea2/test.json"); +} + +TEST_F(HttpCtrlChannelD2Test, configWriteBadFullPath) { + testConfigWriteBadFullPath(); +} + +TEST_F(HttpsCtrlChannelD2Test, configWriteBadFullPath) { + testConfigWriteBadFullPath(); } // Tests if config-reload attempts to reload a file and reports that the diff --git a/src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc b/src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc index d23cc2399c..699deb7632 100644 --- a/src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc +++ b/src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc @@ -1544,11 +1544,9 @@ TEST_F(CtrlChannelDhcpv4SrvTest, configWriteFullPath) { createUnixChannelServer(); std::string response; - // This is normally set by the command line -c parameter. server_->setConfigFile("/tmp/test1.json"); - sendUnixCommand("{ \"command\": \"config-write\", " "\"arguments\": { \"filename\": \"/tmp/test2.json\" } }", response); diff --git a/src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc b/src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc index be1d1fa9e8..28c0075089 100644 --- a/src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc +++ b/src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc @@ -1538,6 +1538,9 @@ TEST_F(CtrlChannelDhcpv6SrvTest, configWriteFilename) { createUnixChannelServer(); std::string response; + // This is normally set by the command line -c parameter. + server_->setConfigFile("test1.json"); + sendUnixCommand("{ \"command\": \"config-write\", " "\"arguments\": { \"filename\": \"test2.json\" } }", response); @@ -1545,6 +1548,57 @@ TEST_F(CtrlChannelDhcpv6SrvTest, configWriteFilename) { ::remove("test2.json"); } +// Tests if config-write can be called with a valid full path as parameter. +TEST_F(CtrlChannelDhcpv6SrvTest, configWriteFullPath) { + createUnixChannelServer(); + std::string response; + + // This is normally set by the command line -c parameter. + server_->setConfigFile("/tmp/test1.json"); + + sendUnixCommand("{ \"command\": \"config-write\", " + "\"arguments\": { \"filename\": \"/tmp/test2.json\" } }", response); + + checkConfigWrite(response, CONTROL_RESULT_SUCCESS, "/tmp/test2.json"); + ::remove("/tmp/test2.json"); +} + +// Tests if config-write raises an error with invalid path as parameter. +TEST_F(CtrlChannelDhcpv6SrvTest, configWriteBadPath) { + createUnixChannelServer(); + std::string response; + + // This is normally set by the command line -c parameter. + server_->setConfigFile("test1.json"); + + sendUnixCommand("{ \"command\": \"config-write\", " + "\"arguments\": { \"filename\": \"/tmp/test2.json\" } }", response); + + string expected = "not allowed to write config into /tmp/test2.json: "; + expected += "file /tmp/test2.json must be in the same directory "; + expected += "as the config file (test1.json)"; + checkConfigWrite(response, CONTROL_RESULT_ERROR, expected); + ::remove("/tmp/test2.json"); +} + +// Tests if config-write raises an error with invalid full path as parameter. +TEST_F(CtrlChannelDhcpv6SrvTest, configWriteBadFullPath) { + createUnixChannelServer(); + std::string response; + + // This is normally set by the command line -c parameter. + server_->setConfigFile("/tmp/kea1/test.json"); + + sendUnixCommand("{ \"command\": \"config-write\", " + "\"arguments\": { \"filename\": \"/tmp/kea2/test.json\" } }", response); + + string expected = "not allowed to write config into /tmp/kea2/test.json: "; + expected += "file /tmp/kea2/test.json must be in the same directory "; + expected += "as the config file (/tmp/kea1/test.json)"; + checkConfigWrite(response, CONTROL_RESULT_ERROR, expected); + ::remove("/tmp/kea2/test.json"); +} + // Tests if config-reload attempts to reload a file and reports that the // file is missing. TEST_F(CtrlChannelDhcpv6SrvTest, configReloadMissingFile) { diff --git a/src/bin/dhcp6/tests/http_control_socket_unittest.cc b/src/bin/dhcp6/tests/http_control_socket_unittest.cc index cf1552b40b..31dc697dfd 100644 --- a/src/bin/dhcp6/tests/http_control_socket_unittest.cc +++ b/src/bin/dhcp6/tests/http_control_socket_unittest.cc @@ -401,6 +401,12 @@ public: ASSERT_TRUE(from_file); } else if (exp_status == CONTROL_RESULT_ERROR) { + // Errors can be in a list. + if (rsp->getType() == Element::list) { + ASSERT_EQ(1, rsp->size()); + rsp = rsp->get(0); + } + // Let's check if the reason for failure was given. ConstElementPtr text = rsp->get("text"); ASSERT_TRUE(text); @@ -515,6 +521,15 @@ public: // Tests if config-write can be called with a valid filename as parameter. void testConfigWriteFilename(); + // Tests if config-write can be called with a valid full path as parameter. + void testConfigWriteFullPath(); + + // Tests if config-write raises an error with invalid path as parameter. + void testConfigWriteBadPath(); + + // Tests if config-write raises an error with invalid full path as parameter. + void testConfigWriteBadFullPath(); + // Tests if config-reload attempts to reload a file and reports that the // file is missing. void testConfigReloadMissingFile(); @@ -2322,6 +2337,9 @@ BaseCtrlChannelDhcpv6Test::testConfigWriteFilename() { createHttpChannelServer(); std::string response; + // This is normally set by the command line -c parameter. + server_->setConfigFile("test1.json"); + sendHttpCommand("{ \"command\": \"config-write\", " "\"arguments\": { \"filename\": \"test2.json\" } }", response); @@ -2338,6 +2356,87 @@ TEST_F(HttpsCtrlChannelDhcpv6Test, configWriteFilename) { testConfigWriteFilename(); } +// Tests if config-write can be called with a valid full path as parameter. +void +BaseCtrlChannelDhcpv6Test::testConfigWriteFullPath() { + createHttpChannelServer(); + std::string response; + + // This is normally set by the command line -c parameter. + server_->setConfigFile("/tmp/test1.json"); + + sendHttpCommand("{ \"command\": \"config-write\", " + "\"arguments\": { \"filename\": \"/tmp/test2.json\" } }", + response); + + checkConfigWrite(response, CONTROL_RESULT_SUCCESS, "/tmp/test2.json"); + ::remove("/tmp/test2.json"); +} + +TEST_F(HttpCtrlChannelDhcpv6Test, configWriteFullPath) { + testConfigWriteFullPath(); +} + +TEST_F(HttpsCtrlChannelDhcpv6Test, configWriteFullPath) { + testConfigWriteFullPath(); +} + +// Tests if config-write raises an error with invalid path as parameter. +void +BaseCtrlChannelDhcpv6Test::testConfigWriteBadPath() { + createHttpChannelServer(); + std::string response; + + // This is normally set by the command line -c parameter. + server_->setConfigFile("test1.json"); + + sendHttpCommand("{ \"command\": \"config-write\", " + "\"arguments\": { \"filename\": \"/tmp/test2.json\" } }", + response); + + string expected = "not allowed to write config into /tmp/test2.json: "; + expected += "file /tmp/test2.json must be in the same directory "; + expected += "as the config file (test1.json)"; + checkConfigWrite(response, CONTROL_RESULT_ERROR, expected); + ::remove("/tmp/test2.json"); +} + +TEST_F(HttpCtrlChannelDhcpv6Test, configWriteBadPath) { + testConfigWriteBadPath(); +} + +TEST_F(HttpsCtrlChannelDhcpv6Test, configWriteBadPath) { + testConfigWriteBadPath(); +} + +// Tests if config-write raises an error with invalid full path as parameter. +void +BaseCtrlChannelDhcpv6Test::testConfigWriteBadFullPath() { + createHttpChannelServer(); + std::string response; + + // This is normally set by the command line -c parameter. + server_->setConfigFile("/tmp/kea1/test.json"); + + sendHttpCommand("{ \"command\": \"config-write\", " + "\"arguments\": { \"filename\": \"/tmp/kea2/test.json\" } }", + response); + + string expected = "not allowed to write config into /tmp/kea2/test.json: "; + expected += "file /tmp/kea2/test.json must be in the same directory "; + expected += "as the config file (/tmp/kea1/test.json)"; + checkConfigWrite(response, CONTROL_RESULT_ERROR, expected); + ::remove("/tmp/kea2/test.json"); +} + +TEST_F(HttpCtrlChannelDhcpv6Test, configWriteBadFullPath) { + testConfigWriteBadFullPath(); +} + +TEST_F(HttpsCtrlChannelDhcpv6Test, configWriteBadFullPath) { + testConfigWriteBadFullPath(); +} + // Tests if config-reload attempts to reload a file and reports that the // file is missing. void