mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-30 21:45:37 +00:00
[#3694] apply tls settings on reload
This commit is contained in:
@@ -55,7 +55,7 @@ address and port over a TLS channel.
|
||||
|
||||
% CTRL_AGENT_HTTP_SERVICE_REUSED reused HTTP service bound to address %1:%2
|
||||
This informational message indicates that the server has reused existing
|
||||
HTTPS service on the specified address and port.
|
||||
HTTP service on the specified address and port.
|
||||
|
||||
% CTRL_AGENT_HTTP_SERVICE_STARTED HTTP service bound to address %1:%2
|
||||
This informational message indicates that the server has started HTTP service
|
||||
|
@@ -139,14 +139,31 @@ CtrlAgentProcess::configure(isc::data::ConstElementPtr config_set,
|
||||
// Search for the specific connection and reuse the existing one if found.
|
||||
auto it = sockets_.find(std::make_pair(server_address, server_port));
|
||||
if (it != sockets_.end()) {
|
||||
auto listener = getHttpListener();
|
||||
auto listener = it->second->listener_;
|
||||
if (listener) {
|
||||
// Reconfig keeping the same address and port.
|
||||
if (listener->getTlsContext()) {
|
||||
LOG_INFO(agent_logger, CTRL_AGENT_HTTPS_SERVICE_REUSED)
|
||||
.arg(server_address.toText())
|
||||
.arg(server_port);
|
||||
} else {
|
||||
if (ctx->getTrustAnchor().empty()) {
|
||||
// Can not switch from HTTPS to HTTP
|
||||
LOG_INFO(agent_logger, CTRL_AGENT_HTTPS_SERVICE_REUSED)
|
||||
.arg(server_address.toText())
|
||||
.arg(server_port);
|
||||
} else {
|
||||
// Apply TLS settings each time.
|
||||
TlsContextPtr tls_context;
|
||||
TlsContext::configure(tls_context,
|
||||
TlsRole::SERVER,
|
||||
ctx->getTrustAnchor(),
|
||||
ctx->getCertFile(),
|
||||
ctx->getKeyFile(),
|
||||
ctx->getCertRequired());
|
||||
// Overwrite the authentication setup and the http headers in the response creator config.
|
||||
it->second->config_->setAuthConfig(ctx->getAuthConfig());
|
||||
it->second->config_->setHttpHeaders(ctx->getHttpHeaders());
|
||||
getIOService()->post([listener, tls_context]() { listener->setTlsContext(tls_context); });
|
||||
}
|
||||
} else if (!ctx->getTrustAnchor().empty()) {
|
||||
// Can not switch from HTTP to HTTPS
|
||||
LOG_INFO(agent_logger, CTRL_AGENT_HTTP_SERVICE_REUSED)
|
||||
.arg(server_address.toText())
|
||||
.arg(server_port);
|
||||
|
@@ -30,6 +30,7 @@ AM_CPPFLAGS += -DTEST_DATA_BUILDDIR=\"$(abs_top_builddir)/src/bin/agent/tests\"
|
||||
AM_CPPFLAGS += -DINSTALL_PROG=\"$(abs_top_srcdir)/install-sh\"
|
||||
AM_CPPFLAGS += -DCFG_EXAMPLES=\"$(abs_top_srcdir)/doc/examples/agent\"
|
||||
AM_CPPFLAGS += -DSYNTAX_FILE=\"$(abs_srcdir)/../agent_parser.yy\"
|
||||
AM_CPPFLAGS += -DTEST_CA_DIR=\"$(abs_top_srcdir)/src/lib/asiolink/testutils/ca\"
|
||||
|
||||
AM_CXXFLAGS = $(KEA_CXXFLAGS)
|
||||
|
||||
|
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
using namespace isc::asiolink;
|
||||
using namespace isc::asiolink::test;
|
||||
using namespace isc::agent;
|
||||
using namespace isc::data;
|
||||
@@ -402,7 +403,7 @@ TEST_F(CtrlAgentControllerTest, unsuccessfulConfigUpdate) {
|
||||
// Tests that it is possible to update the configuration in such a way that the
|
||||
// listener configuration remains the same. The server should continue using the
|
||||
// listener instance it has been using prior to the reconfiguration.
|
||||
TEST_F(CtrlAgentControllerTest, noListenerChange) {
|
||||
TEST_F(CtrlAgentControllerTest, noListenerChangeHttp) {
|
||||
// This configuration should be used to override the initial configuration.
|
||||
const char* second_config =
|
||||
"{"
|
||||
@@ -420,6 +421,8 @@ TEST_F(CtrlAgentControllerTest, noListenerChange) {
|
||||
" }"
|
||||
"}";
|
||||
|
||||
const HttpListener* listener_ptr = 0;
|
||||
|
||||
// This check callback is called before the shutdown.
|
||||
auto check_callback = [&] {
|
||||
CtrlAgentProcessPtr process = getCtrlAgentProcess();
|
||||
@@ -428,6 +431,8 @@ TEST_F(CtrlAgentControllerTest, noListenerChange) {
|
||||
// Check that the HTTP listener still exists after reconfiguration.
|
||||
ConstHttpListenerPtr listener = process->getHttpListener();
|
||||
ASSERT_TRUE(listener);
|
||||
ASSERT_EQ(listener_ptr, listener.get());
|
||||
ASSERT_FALSE(listener->getTlsContext());
|
||||
EXPECT_TRUE(process->isListening());
|
||||
|
||||
EXPECT_EQ("127.0.0.1", listener->getLocalAddress().toText());
|
||||
@@ -439,6 +444,16 @@ TEST_F(CtrlAgentControllerTest, noListenerChange) {
|
||||
// Schedule SIGHUP signal to trigger reconfiguration.
|
||||
TimedSignal sighup(getIOService(), SIGHUP, 200);
|
||||
|
||||
IntervalTimer timer(getIOService());
|
||||
timer.setup([&] {
|
||||
CtrlAgentProcessPtr process = getCtrlAgentProcess();
|
||||
ASSERT_TRUE(process);
|
||||
ConstHttpListenerPtr listener = process->getHttpListener();
|
||||
ASSERT_TRUE(listener);
|
||||
listener_ptr = listener.get();
|
||||
ASSERT_FALSE(listener->getTlsContext());
|
||||
}, 50, IntervalTimer::ONE_SHOT);
|
||||
|
||||
// Start the server.
|
||||
time_duration elapsed_time;
|
||||
runWithConfig(valid_agent_config, 500,
|
||||
@@ -463,6 +478,292 @@ TEST_F(CtrlAgentControllerTest, noListenerChange) {
|
||||
EXPECT_FALSE(process->isListening());
|
||||
}
|
||||
|
||||
// Tests that it is possible to update the configuration in such a way that the
|
||||
// listener configuration remains the same. The server should continue using the
|
||||
// listener instance it has been using prior to the reconfiguration.
|
||||
TEST_F(CtrlAgentControllerTest, noListenerChangeHttps) {
|
||||
// This configuration should be used to override the initial configuration.
|
||||
string ca_dir(string(TEST_CA_DIR));
|
||||
ostringstream agent_st;
|
||||
agent_st << "{"
|
||||
<< " \"http-host\": \"127.0.0.1\","
|
||||
<< " \"http-port\": 8081,"
|
||||
<< " \"trust-anchor\": \"" << ca_dir << "/kea-ca.crt\", \n"
|
||||
<< " \"cert-file\": \"" << ca_dir << "/kea-server.crt\", \n"
|
||||
<< " \"key-file\": \"" << ca_dir << "/kea-server.key\", \n"
|
||||
<< " \"control-sockets\": {"
|
||||
<< " \"dhcp4\": {"
|
||||
<< " \"socket-type\": \"unix\","
|
||||
<< " \"socket-name\": \"/first/dhcp4/socket\""
|
||||
<< " },"
|
||||
<< " \"dhcp6\": {"
|
||||
<< " \"socket-type\": \"unix\","
|
||||
<< " \"socket-name\": \"/first/dhcp6/socket\""
|
||||
<< " }"
|
||||
<< " }"
|
||||
<< "}";
|
||||
|
||||
ostringstream second_config_st;
|
||||
second_config_st << "{"
|
||||
<< " \"http-host\": \"127.0.0.1\","
|
||||
<< " \"http-port\": 8081,"
|
||||
<< " \"trust-anchor\": \"" << ca_dir << "/kea-ca.crt\", \n"
|
||||
<< " \"cert-file\": \"" << ca_dir << "/kea-server.crt\", \n"
|
||||
<< " \"key-file\": \"" << ca_dir << "/kea-server.key\", \n"
|
||||
<< " \"control-sockets\": {"
|
||||
<< " \"dhcp4\": {"
|
||||
<< " \"socket-type\": \"unix\","
|
||||
<< " \"socket-name\": \"/second/dhcp4/socket\""
|
||||
<< " },"
|
||||
<< " \"dhcp6\": {"
|
||||
<< " \"socket-type\": \"unix\","
|
||||
<< " \"socket-name\": \"/second/dhcp6/socket\""
|
||||
<< " }"
|
||||
<< " }"
|
||||
<< "}";
|
||||
|
||||
const HttpListener* listener_ptr = 0;
|
||||
TlsContext* context = 0;
|
||||
|
||||
// This check callback is called before the shutdown.
|
||||
auto check_callback = [&] {
|
||||
CtrlAgentProcessPtr process = getCtrlAgentProcess();
|
||||
ASSERT_TRUE(process);
|
||||
|
||||
// Check that the HTTP listener still exists after reconfiguration.
|
||||
ConstHttpListenerPtr listener = process->getHttpListener();
|
||||
ASSERT_TRUE(listener);
|
||||
ASSERT_EQ(listener_ptr, listener.get());
|
||||
ASSERT_TRUE(listener->getTlsContext());
|
||||
// The TLS settings have been applied
|
||||
ASSERT_NE(context, listener->getTlsContext().get());
|
||||
EXPECT_TRUE(process->isListening());
|
||||
|
||||
EXPECT_EQ("127.0.0.1", listener->getLocalAddress().toText());
|
||||
EXPECT_EQ(8081, listener->getLocalPort());
|
||||
};
|
||||
|
||||
// Schedule reconfiguration.
|
||||
scheduleTimedWrite(second_config_st.str(), 100);
|
||||
// Schedule SIGHUP signal to trigger reconfiguration.
|
||||
TimedSignal sighup(getIOService(), SIGHUP, 200);
|
||||
|
||||
IntervalTimer timer(getIOService());
|
||||
timer.setup([&] {
|
||||
CtrlAgentProcessPtr process = getCtrlAgentProcess();
|
||||
ASSERT_TRUE(process);
|
||||
ConstHttpListenerPtr listener = process->getHttpListener();
|
||||
ASSERT_TRUE(listener);
|
||||
listener_ptr = listener.get();
|
||||
ASSERT_TRUE(listener->getTlsContext());
|
||||
context = listener->getTlsContext().get();
|
||||
}, 50, IntervalTimer::ONE_SHOT);
|
||||
|
||||
// Start the server.
|
||||
time_duration elapsed_time;
|
||||
runWithConfig(agent_st.str(), 500,
|
||||
static_cast<const TestCallback&>(check_callback),
|
||||
elapsed_time);
|
||||
|
||||
CtrlAgentCfgContextPtr ctx = getCtrlAgentCfgContext();
|
||||
ASSERT_TRUE(ctx);
|
||||
|
||||
// The server should use a correct listener configuration.
|
||||
EXPECT_EQ("127.0.0.1", ctx->getHttpHost());
|
||||
EXPECT_EQ(8081, ctx->getHttpPort());
|
||||
|
||||
// The forwarding configuration should have been updated.
|
||||
testUnixSocketInfo("dhcp4", "/second/dhcp4/socket");
|
||||
testUnixSocketInfo("dhcp6", "/second/dhcp6/socket");
|
||||
|
||||
CtrlAgentProcessPtr process = getCtrlAgentProcess();
|
||||
ASSERT_TRUE(process);
|
||||
ConstHttpListenerPtr listener = process->getHttpListener();
|
||||
ASSERT_FALSE(listener);
|
||||
EXPECT_FALSE(process->isListening());
|
||||
}
|
||||
|
||||
// Verify that the reload will reuse listener
|
||||
TEST_F(CtrlAgentControllerTest, ignoreHttpToHttpsSwitch) {
|
||||
string ca_dir(string(TEST_CA_DIR));
|
||||
|
||||
// This configuration should be used to override the initial configuration.
|
||||
ostringstream second_config_st;
|
||||
second_config_st << "{"
|
||||
<< " \"http-host\": \"127.0.0.1\","
|
||||
<< " \"http-port\": 8081,"
|
||||
<< " \"trust-anchor\": \"" << ca_dir << "/kea-ca.crt\", \n"
|
||||
<< " \"cert-file\": \"" << ca_dir << "/kea-server.crt\", \n"
|
||||
<< " \"key-file\": \"" << ca_dir << "/kea-server.key\", \n"
|
||||
<< " \"control-sockets\": {"
|
||||
<< " \"dhcp4\": {"
|
||||
<< " \"socket-type\": \"unix\","
|
||||
<< " \"socket-name\": \"/second/dhcp4/socket\""
|
||||
<< " },"
|
||||
<< " \"dhcp6\": {"
|
||||
<< " \"socket-type\": \"unix\","
|
||||
<< " \"socket-name\": \"/second/dhcp6/socket\""
|
||||
<< " }"
|
||||
<< " }"
|
||||
<< "}";
|
||||
|
||||
const HttpListener* listener_ptr = 0;
|
||||
|
||||
// This check callback is called before the shutdown.
|
||||
auto check_callback = [&] {
|
||||
CtrlAgentProcessPtr process = getCtrlAgentProcess();
|
||||
ASSERT_TRUE(process);
|
||||
|
||||
// Check that the HTTP listener still exists after reconfiguration.
|
||||
ConstHttpListenerPtr listener = process->getHttpListener();
|
||||
ASSERT_TRUE(listener);
|
||||
ASSERT_EQ(listener_ptr, listener.get());
|
||||
ASSERT_FALSE(listener->getTlsContext());
|
||||
EXPECT_TRUE(process->isListening());
|
||||
|
||||
EXPECT_EQ("127.0.0.1", listener->getLocalAddress().toText());
|
||||
EXPECT_EQ(8081, listener->getLocalPort());
|
||||
};
|
||||
|
||||
// Schedule reconfiguration.
|
||||
scheduleTimedWrite(second_config_st.str(), 100);
|
||||
// Schedule SIGHUP signal to trigger reconfiguration.
|
||||
TimedSignal sighup(getIOService(), SIGHUP, 200);
|
||||
|
||||
IntervalTimer timer(getIOService());
|
||||
timer.setup([&] {
|
||||
CtrlAgentProcessPtr process = getCtrlAgentProcess();
|
||||
ASSERT_TRUE(process);
|
||||
ConstHttpListenerPtr listener = process->getHttpListener();
|
||||
ASSERT_TRUE(listener);
|
||||
listener_ptr = listener.get();
|
||||
ASSERT_FALSE(listener->getTlsContext());
|
||||
}, 50, IntervalTimer::ONE_SHOT);
|
||||
|
||||
// Start the server.
|
||||
time_duration elapsed_time;
|
||||
runWithConfig(valid_agent_config, 500,
|
||||
static_cast<const TestCallback&>(check_callback),
|
||||
elapsed_time);
|
||||
|
||||
CtrlAgentCfgContextPtr ctx = getCtrlAgentCfgContext();
|
||||
ASSERT_TRUE(ctx);
|
||||
|
||||
// The server should use a correct listener configuration.
|
||||
EXPECT_EQ("127.0.0.1", ctx->getHttpHost());
|
||||
EXPECT_EQ(8081, ctx->getHttpPort());
|
||||
|
||||
// The forwarding configuration should have been updated.
|
||||
testUnixSocketInfo("dhcp4", "/second/dhcp4/socket");
|
||||
testUnixSocketInfo("dhcp6", "/second/dhcp6/socket");
|
||||
|
||||
CtrlAgentProcessPtr process = getCtrlAgentProcess();
|
||||
ASSERT_TRUE(process);
|
||||
ConstHttpListenerPtr listener = process->getHttpListener();
|
||||
ASSERT_FALSE(listener);
|
||||
EXPECT_FALSE(process->isListening());
|
||||
}
|
||||
|
||||
// Verify that the reload will reuse listener
|
||||
TEST_F(CtrlAgentControllerTest, ignoreHttpsToHttpSwitch) {
|
||||
string ca_dir(string(TEST_CA_DIR));
|
||||
ostringstream agent_st;
|
||||
agent_st << "{"
|
||||
<< " \"http-host\": \"127.0.0.1\","
|
||||
<< " \"http-port\": 8081,"
|
||||
<< " \"trust-anchor\": \"" << ca_dir << "/kea-ca.crt\", \n"
|
||||
<< " \"cert-file\": \"" << ca_dir << "/kea-server.crt\", \n"
|
||||
<< " \"key-file\": \"" << ca_dir << "/kea-server.key\", \n"
|
||||
<< " \"control-sockets\": {"
|
||||
<< " \"dhcp4\": {"
|
||||
<< " \"socket-type\": \"unix\","
|
||||
<< " \"socket-name\": \"/first/dhcp4/socket\""
|
||||
<< " },"
|
||||
<< " \"dhcp6\": {"
|
||||
<< " \"socket-type\": \"unix\","
|
||||
<< " \"socket-name\": \"/first/dhcp6/socket\""
|
||||
<< " }"
|
||||
<< " }"
|
||||
<< "}";
|
||||
|
||||
// This configuration should be used to override the initial configuration.
|
||||
ostringstream second_config_st;
|
||||
second_config_st << "{"
|
||||
<< " \"http-host\": \"127.0.0.1\","
|
||||
<< " \"http-port\": 8081,"
|
||||
<< " \"control-sockets\": {"
|
||||
<< " \"dhcp4\": {"
|
||||
<< " \"socket-type\": \"unix\","
|
||||
<< " \"socket-name\": \"/second/dhcp4/socket\""
|
||||
<< " },"
|
||||
<< " \"dhcp6\": {"
|
||||
<< " \"socket-type\": \"unix\","
|
||||
<< " \"socket-name\": \"/second/dhcp6/socket\""
|
||||
<< " }"
|
||||
<< " }"
|
||||
<< "}";
|
||||
|
||||
const HttpListener* listener_ptr = 0;
|
||||
TlsContext* context = 0;
|
||||
|
||||
// This check callback is called before the shutdown.
|
||||
auto check_callback = [&] {
|
||||
CtrlAgentProcessPtr process = getCtrlAgentProcess();
|
||||
ASSERT_TRUE(process);
|
||||
|
||||
// Check that the HTTP listener still exists after reconfiguration.
|
||||
ConstHttpListenerPtr listener = process->getHttpListener();
|
||||
ASSERT_TRUE(listener);
|
||||
ASSERT_EQ(listener_ptr, listener.get());
|
||||
ASSERT_TRUE(listener->getTlsContext());
|
||||
// The TLS settings have not changed
|
||||
ASSERT_EQ(context, listener->getTlsContext().get());
|
||||
EXPECT_TRUE(process->isListening());
|
||||
|
||||
EXPECT_EQ("127.0.0.1", listener->getLocalAddress().toText());
|
||||
EXPECT_EQ(8081, listener->getLocalPort());
|
||||
};
|
||||
|
||||
// Schedule reconfiguration.
|
||||
scheduleTimedWrite(second_config_st.str(), 100);
|
||||
// Schedule SIGHUP signal to trigger reconfiguration.
|
||||
TimedSignal sighup(getIOService(), SIGHUP, 200);
|
||||
|
||||
IntervalTimer timer(getIOService());
|
||||
timer.setup([&] {
|
||||
CtrlAgentProcessPtr process = getCtrlAgentProcess();
|
||||
ASSERT_TRUE(process);
|
||||
ConstHttpListenerPtr listener = process->getHttpListener();
|
||||
ASSERT_TRUE(listener);
|
||||
listener_ptr = listener.get();
|
||||
ASSERT_TRUE(listener->getTlsContext());
|
||||
context = listener->getTlsContext().get();
|
||||
}, 50, IntervalTimer::ONE_SHOT);
|
||||
|
||||
// Start the server.
|
||||
time_duration elapsed_time;
|
||||
runWithConfig(agent_st.str(), 500,
|
||||
static_cast<const TestCallback&>(check_callback),
|
||||
elapsed_time);
|
||||
|
||||
CtrlAgentCfgContextPtr ctx = getCtrlAgentCfgContext();
|
||||
ASSERT_TRUE(ctx);
|
||||
|
||||
// The server should use a correct listener configuration.
|
||||
EXPECT_EQ("127.0.0.1", ctx->getHttpHost());
|
||||
EXPECT_EQ(8081, ctx->getHttpPort());
|
||||
|
||||
// The forwarding configuration should have been updated.
|
||||
testUnixSocketInfo("dhcp4", "/second/dhcp4/socket");
|
||||
testUnixSocketInfo("dhcp6", "/second/dhcp6/socket");
|
||||
|
||||
CtrlAgentProcessPtr process = getCtrlAgentProcess();
|
||||
ASSERT_TRUE(process);
|
||||
ConstHttpListenerPtr listener = process->getHttpListener();
|
||||
ASSERT_FALSE(listener);
|
||||
EXPECT_FALSE(process->isListening());
|
||||
}
|
||||
|
||||
// Tests that registerCommands actually registers anything.
|
||||
TEST_F(CtrlAgentControllerTest, registeredCommands) {
|
||||
ASSERT_NO_THROW(initProcess());
|
||||
|
@@ -522,16 +522,11 @@ D2Process::reconfigureCommandChannel() {
|
||||
ConstElementPtr http_config =
|
||||
getD2CfgMgr()->getHttpControlSocketInfo();
|
||||
|
||||
sock_changed = (http_config && current_http_control_socket_ &&
|
||||
!http_config->equals(*current_http_control_socket_));
|
||||
|
||||
if (!http_config || !current_http_control_socket_ || sock_changed) {
|
||||
// Open the new sockets and close old ones, keeping reused.
|
||||
if (http_config) {
|
||||
HttpCommandMgr::instance().openCommandSockets(http_config);
|
||||
} else if (current_http_control_socket_) {
|
||||
HttpCommandMgr::instance().closeCommandSockets();
|
||||
}
|
||||
// Open the new sockets and close old ones, keeping reused.
|
||||
if (http_config) {
|
||||
HttpCommandMgr::instance().openCommandSockets(http_config);
|
||||
} else if (current_http_control_socket_) {
|
||||
HttpCommandMgr::instance().closeCommandSockets();
|
||||
}
|
||||
|
||||
// Commit the new socket configuration.
|
||||
|
@@ -1218,7 +1218,7 @@ TEST_F(HttpCtrlChannelD2Test, configSet) {
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener());
|
||||
|
||||
// Create a config with invalid content that should fail to parse.
|
||||
string config_test_txt =
|
||||
string config_set_txt =
|
||||
"{ \"command\": \"config-set\", \n"
|
||||
" \"arguments\": { \n"
|
||||
" \"DhcpDdns\": \n"
|
||||
@@ -1242,7 +1242,7 @@ TEST_F(HttpCtrlChannelD2Test, configSet) {
|
||||
|
||||
// Send the config-set command.
|
||||
string response;
|
||||
sendHttpCommand(config_test_txt, response);
|
||||
sendHttpCommand(config_set_txt, response);
|
||||
|
||||
// Should fail with a syntax error.
|
||||
EXPECT_EQ("[ { \"result\": 1, \"text\": \"missing parameter 'name' (<string>:10:14)\" } ]",
|
||||
@@ -1255,7 +1255,7 @@ TEST_F(HttpCtrlChannelD2Test, configSet) {
|
||||
EXPECT_EQ(1, keys->size());
|
||||
|
||||
// Create a valid config with two keys and no command channel.
|
||||
config_test_txt =
|
||||
config_set_txt =
|
||||
"{ \"command\": \"config-set\", \n"
|
||||
" \"arguments\": { \n"
|
||||
" \"DhcpDdns\": \n"
|
||||
@@ -1280,7 +1280,7 @@ TEST_F(HttpCtrlChannelD2Test, configSet) {
|
||||
EXPECT_TRUE(HttpCommandMgr::instance().getHttpListener());
|
||||
|
||||
// Send the config-set command.
|
||||
sendHttpCommand(config_test_txt, response);
|
||||
sendHttpCommand(config_set_txt, response);
|
||||
|
||||
// Verify the HTTP control channel socket no longer exists.
|
||||
ASSERT_NO_THROW(HttpCommandMgr::instance().closeCommandSockets());
|
||||
@@ -1355,7 +1355,7 @@ TEST_F(HttpsCtrlChannelD2Test, configSet) {
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener());
|
||||
|
||||
// Create a config with invalid content that should fail to parse.
|
||||
string config_test_txt =
|
||||
string config_set_txt =
|
||||
"{ \"command\": \"config-set\", \n"
|
||||
" \"arguments\": { \n"
|
||||
" \"DhcpDdns\": \n"
|
||||
@@ -1379,7 +1379,7 @@ TEST_F(HttpsCtrlChannelD2Test, configSet) {
|
||||
|
||||
// Send the config-set command.
|
||||
string response;
|
||||
sendHttpCommand(config_test_txt, response);
|
||||
sendHttpCommand(config_set_txt, response);
|
||||
|
||||
// Should fail with a syntax error.
|
||||
EXPECT_EQ("[ { \"result\": 1, \"text\": \"missing parameter 'name' (<string>:10:14)\" } ]",
|
||||
@@ -1392,7 +1392,7 @@ TEST_F(HttpsCtrlChannelD2Test, configSet) {
|
||||
EXPECT_EQ(1, keys->size());
|
||||
|
||||
// Create a valid config with two keys and no command channel.
|
||||
config_test_txt =
|
||||
config_set_txt =
|
||||
"{ \"command\": \"config-set\", \n"
|
||||
" \"arguments\": { \n"
|
||||
" \"DhcpDdns\": \n"
|
||||
@@ -1417,7 +1417,7 @@ TEST_F(HttpsCtrlChannelD2Test, configSet) {
|
||||
EXPECT_TRUE(HttpCommandMgr::instance().getHttpListener());
|
||||
|
||||
// Send the config-set command.
|
||||
sendHttpCommand(config_test_txt, response);
|
||||
sendHttpCommand(config_set_txt, response);
|
||||
|
||||
// Verify the HTTP control channel socket no longer exists.
|
||||
ASSERT_NO_THROW(HttpCommandMgr::instance().closeCommandSockets());
|
||||
@@ -1984,4 +1984,374 @@ TEST_F(HttpsCtrlChannelD2Test, connectionTimeoutNoData) {
|
||||
testConnectionTimeoutNoData();
|
||||
}
|
||||
|
||||
// Verify that the "config-set" command will reuse listener
|
||||
TEST_F(HttpCtrlChannelD2Test, noListenerChange) {
|
||||
|
||||
string d2_cfg_txt =
|
||||
" { \n"
|
||||
" \"ip-address\": \"192.168.77.1\", \n"
|
||||
" \"port\": 777, \n"
|
||||
" \"forward-ddns\" : {}, \n"
|
||||
" \"reverse-ddns\" : {}, \n"
|
||||
" \"tsig-keys\": [ \n"
|
||||
" {\"name\": \"d2_key.example.com\", \n"
|
||||
" \"algorithm\": \"hmac-md5\", \n"
|
||||
" \"secret\": \"LSWXnfkKZjdPJI5QxlpnfQ==\"} \n"
|
||||
" ], \n"
|
||||
" \"control-socket\": { \n"
|
||||
" \"socket-type\": \"http\", \n"
|
||||
" \"socket-address\": \"127.0.0.1\", \n"
|
||||
" \"socket-port\": 18125 \n"
|
||||
" } \n"
|
||||
" } \n";
|
||||
|
||||
ASSERT_TRUE(server_);
|
||||
|
||||
ConstElementPtr config;
|
||||
ASSERT_NO_THROW(config = parseDHCPDDNS(d2_cfg_txt, true));
|
||||
ASSERT_NO_THROW(d2Controller()->initProcess());
|
||||
D2ProcessPtr proc = d2Controller()->getProcess();
|
||||
ASSERT_TRUE(proc);
|
||||
ConstElementPtr answer = proc->configure(config, false);
|
||||
ASSERT_TRUE(answer);
|
||||
EXPECT_EQ("{ \"arguments\": { \"hash\": \"029AE1208415D6911B5651A6F82D054F55B7877D2589CFD1DCEB5BFFCD3B13A3\" }, \"result\": 0, \"text\": \"Configuration applied successfully.\" }",
|
||||
answer->str());
|
||||
ASSERT_NO_THROW(d2Controller()->registerCommands());
|
||||
|
||||
// Check that the config was indeed applied.
|
||||
D2CfgMgrPtr cfg_mgr = proc->getD2CfgMgr();
|
||||
ASSERT_TRUE(cfg_mgr);
|
||||
D2CfgContextPtr d2_context = cfg_mgr->getD2CfgContext();
|
||||
ASSERT_TRUE(d2_context);
|
||||
TSIGKeyInfoMapPtr keys = d2_context->getKeys();
|
||||
ASSERT_TRUE(keys);
|
||||
EXPECT_EQ(1, keys->size());
|
||||
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener());
|
||||
auto const listener = HttpCommandMgr::instance().getHttpListener().get();
|
||||
ASSERT_FALSE(HttpCommandMgr::instance().getHttpListener()->getTlsContext());
|
||||
|
||||
// Create a config with same content that should not recreate listener.
|
||||
string config_set_txt =
|
||||
"{ \"command\": \"config-set\", \n"
|
||||
" \"arguments\": { \n"
|
||||
" \"DhcpDdns\": \n";
|
||||
|
||||
config_set_txt += d2_cfg_txt;
|
||||
config_set_txt += "}} \n";
|
||||
|
||||
// Send the config-set command.
|
||||
string response;
|
||||
sendHttpCommand(config_set_txt, response);
|
||||
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener());
|
||||
EXPECT_EQ(listener, HttpCommandMgr::instance().getHttpListener().get());
|
||||
ASSERT_FALSE(HttpCommandMgr::instance().getHttpListener()->getTlsContext());
|
||||
|
||||
// Verify the configuration was successful.
|
||||
EXPECT_EQ("[ { \"arguments\": { \"hash\": \"029AE1208415D6911B5651A6F82D054F55B7877D2589CFD1DCEB5BFFCD3B13A3\" }, \"result\": 0, \"text\": \"Configuration applied successfully.\" } ]",
|
||||
response);
|
||||
|
||||
// Check that the config was applied.
|
||||
d2_context = cfg_mgr->getD2CfgContext();
|
||||
keys = d2_context->getKeys();
|
||||
ASSERT_TRUE(keys);
|
||||
EXPECT_EQ(1, keys->size());
|
||||
}
|
||||
|
||||
// Verify that the "config-set" command will reuse listener
|
||||
TEST_F(HttpsCtrlChannelD2Test, noListenerChange) {
|
||||
|
||||
string ca_dir(string(TEST_CA_DIR));
|
||||
ostringstream d2_st;
|
||||
d2_st << " { \n"
|
||||
<< " \"ip-address\": \"192.168.77.1\", \n"
|
||||
<< " \"port\": 777, \n"
|
||||
<< " \"forward-ddns\" : {}, \n"
|
||||
<< " \"reverse-ddns\" : {}, \n"
|
||||
<< " \"tsig-keys\": [ \n"
|
||||
<< " {\"name\": \"d2_key.example.com\", \n"
|
||||
<< " \"algorithm\": \"hmac-md5\", \n"
|
||||
<< " \"secret\": \"LSWXnfkKZjdPJI5QxlpnfQ==\"} \n"
|
||||
<< " ], \n"
|
||||
<< " \"control-socket\": { \n"
|
||||
<< " \"socket-type\": \"https\", \n"
|
||||
<< " \"socket-address\": \"127.0.0.1\", \n"
|
||||
<< " \"socket-port\": 18125, \n"
|
||||
<< " \"trust-anchor\": \"" << ca_dir << "/kea-ca.crt\", \n"
|
||||
<< " \"cert-file\": \"" << ca_dir << "/kea-server.crt\", \n"
|
||||
<< " \"key-file\": \"" << ca_dir << "/kea-server.key\" \n"
|
||||
<< " } \n"
|
||||
<< " } \n";
|
||||
|
||||
ASSERT_TRUE(server_);
|
||||
|
||||
ConstElementPtr config;
|
||||
ASSERT_NO_THROW(config = parseDHCPDDNS(d2_st.str(), true));
|
||||
ASSERT_NO_THROW(d2Controller()->initProcess());
|
||||
D2ProcessPtr proc = d2Controller()->getProcess();
|
||||
ASSERT_TRUE(proc);
|
||||
ConstElementPtr answer = proc->configure(config, false);
|
||||
ASSERT_TRUE(answer);
|
||||
// Verify the configuration was successful. The config contains random
|
||||
// file paths (CA directory), 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 applied successfully." is there
|
||||
string answer_txt = answer->str();
|
||||
EXPECT_NE(answer_txt.find("\"result\": 0"), std::string::npos);
|
||||
EXPECT_NE(answer_txt.find("\"text\": \"Configuration applied successfully.\""),
|
||||
std::string::npos);
|
||||
ASSERT_NO_THROW(d2Controller()->registerCommands());
|
||||
|
||||
// Check that the config was indeed applied.
|
||||
D2CfgMgrPtr cfg_mgr = proc->getD2CfgMgr();
|
||||
ASSERT_TRUE(cfg_mgr);
|
||||
D2CfgContextPtr d2_context = cfg_mgr->getD2CfgContext();
|
||||
ASSERT_TRUE(d2_context);
|
||||
TSIGKeyInfoMapPtr keys = d2_context->getKeys();
|
||||
ASSERT_TRUE(keys);
|
||||
EXPECT_EQ(1, keys->size());
|
||||
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener());
|
||||
auto const listener = HttpCommandMgr::instance().getHttpListener().get();
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener()->getTlsContext());
|
||||
auto const context = HttpCommandMgr::instance().getHttpListener()->getTlsContext().get();
|
||||
|
||||
// Create a config with same content that should not recreate listener.
|
||||
string config_set_txt =
|
||||
"{ \"command\": \"config-set\", \n"
|
||||
" \"arguments\": { \n"
|
||||
" \"DhcpDdns\": \n";
|
||||
|
||||
config_set_txt += d2_st.str();
|
||||
config_set_txt += "}} \n";
|
||||
|
||||
// Send the config-set command.
|
||||
string response;
|
||||
sendHttpCommand(config_set_txt, response);
|
||||
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener());
|
||||
EXPECT_EQ(listener, HttpCommandMgr::instance().getHttpListener().get());
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener()->getTlsContext());
|
||||
// The TLS settings have been applied
|
||||
EXPECT_NE(context, HttpCommandMgr::instance().getHttpListener()->getTlsContext().get());
|
||||
|
||||
// Verify the configuration was successful.
|
||||
EXPECT_NE(response.find("\"result\": 0"), std::string::npos);
|
||||
EXPECT_NE(response.find("\"text\": \"Configuration applied successfully.\""),
|
||||
std::string::npos);
|
||||
|
||||
// Check that the config was applied.
|
||||
d2_context = cfg_mgr->getD2CfgContext();
|
||||
keys = d2_context->getKeys();
|
||||
ASSERT_TRUE(keys);
|
||||
EXPECT_EQ(1, keys->size());
|
||||
}
|
||||
|
||||
// Verify that the "config-set" command will reuse listener
|
||||
TEST_F(HttpCtrlChannelD2Test, ignoreHttpToHttpsSwitch) {
|
||||
|
||||
string d2_cfg_txt =
|
||||
" { \n"
|
||||
" \"ip-address\": \"192.168.77.1\", \n"
|
||||
" \"port\": 777, \n"
|
||||
" \"forward-ddns\" : {}, \n"
|
||||
" \"reverse-ddns\" : {}, \n"
|
||||
" \"tsig-keys\": [ \n"
|
||||
" {\"name\": \"d2_key.example.com\", \n"
|
||||
" \"algorithm\": \"hmac-md5\", \n"
|
||||
" \"secret\": \"LSWXnfkKZjdPJI5QxlpnfQ==\"} \n"
|
||||
" ], \n"
|
||||
" \"control-socket\": { \n"
|
||||
" \"socket-type\": \"http\", \n"
|
||||
" \"socket-address\": \"127.0.0.1\", \n"
|
||||
" \"socket-port\": 18125 \n"
|
||||
" } \n"
|
||||
" } \n";
|
||||
|
||||
ASSERT_TRUE(server_);
|
||||
|
||||
ConstElementPtr config;
|
||||
ASSERT_NO_THROW(config = parseDHCPDDNS(d2_cfg_txt, true));
|
||||
ASSERT_NO_THROW(d2Controller()->initProcess());
|
||||
D2ProcessPtr proc = d2Controller()->getProcess();
|
||||
ASSERT_TRUE(proc);
|
||||
ConstElementPtr answer = proc->configure(config, false);
|
||||
ASSERT_TRUE(answer);
|
||||
EXPECT_EQ("{ \"arguments\": { \"hash\": \"029AE1208415D6911B5651A6F82D054F55B7877D2589CFD1DCEB5BFFCD3B13A3\" }, \"result\": 0, \"text\": \"Configuration applied successfully.\" }",
|
||||
answer->str());
|
||||
ASSERT_NO_THROW(d2Controller()->registerCommands());
|
||||
|
||||
// Check that the config was indeed applied.
|
||||
D2CfgMgrPtr cfg_mgr = proc->getD2CfgMgr();
|
||||
ASSERT_TRUE(cfg_mgr);
|
||||
D2CfgContextPtr d2_context = cfg_mgr->getD2CfgContext();
|
||||
ASSERT_TRUE(d2_context);
|
||||
TSIGKeyInfoMapPtr keys = d2_context->getKeys();
|
||||
ASSERT_TRUE(keys);
|
||||
EXPECT_EQ(1, keys->size());
|
||||
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener());
|
||||
auto const listener = HttpCommandMgr::instance().getHttpListener().get();
|
||||
ASSERT_FALSE(HttpCommandMgr::instance().getHttpListener()->getTlsContext());
|
||||
|
||||
string ca_dir(string(TEST_CA_DIR));
|
||||
ostringstream d2_st;
|
||||
d2_st << " { \n"
|
||||
<< " \"ip-address\": \"192.168.77.1\", \n"
|
||||
<< " \"port\": 777, \n"
|
||||
<< " \"forward-ddns\" : {}, \n"
|
||||
<< " \"reverse-ddns\" : {}, \n"
|
||||
<< " \"tsig-keys\": [ \n"
|
||||
<< " {\"name\": \"d2_key.example.com\", \n"
|
||||
<< " \"algorithm\": \"hmac-md5\", \n"
|
||||
<< " \"secret\": \"LSWXnfkKZjdPJI5QxlpnfQ==\"} \n"
|
||||
<< " ], \n"
|
||||
<< " \"control-socket\": { \n"
|
||||
<< " \"socket-type\": \"https\", \n"
|
||||
<< " \"socket-address\": \"127.0.0.1\", \n"
|
||||
<< " \"socket-port\": 18125, \n"
|
||||
<< " \"trust-anchor\": \"" << ca_dir << "/kea-ca.crt\", \n"
|
||||
<< " \"cert-file\": \"" << ca_dir << "/kea-server.crt\", \n"
|
||||
<< " \"key-file\": \"" << ca_dir << "/kea-server.key\" \n"
|
||||
<< " } \n"
|
||||
<< " } \n";
|
||||
|
||||
// Create a config with HTTPS and same content that should not recreate listener.
|
||||
string config_set_txt =
|
||||
"{ \"command\": \"config-set\", \n"
|
||||
" \"arguments\": { \n"
|
||||
" \"DhcpDdns\": \n";
|
||||
|
||||
config_set_txt += d2_st.str();
|
||||
config_set_txt += "}} \n";
|
||||
|
||||
// Send the config-set command.
|
||||
string response;
|
||||
sendHttpCommand(config_set_txt, response);
|
||||
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener());
|
||||
EXPECT_EQ(listener, HttpCommandMgr::instance().getHttpListener().get());
|
||||
ASSERT_FALSE(HttpCommandMgr::instance().getHttpListener()->getTlsContext());
|
||||
|
||||
// Verify the configuration was successful.
|
||||
EXPECT_NE(response.find("\"result\": 0"), std::string::npos);
|
||||
EXPECT_NE(response.find("\"text\": \"Configuration applied successfully.\""),
|
||||
std::string::npos);
|
||||
|
||||
// Check that the config was applied.
|
||||
d2_context = cfg_mgr->getD2CfgContext();
|
||||
keys = d2_context->getKeys();
|
||||
ASSERT_TRUE(keys);
|
||||
EXPECT_EQ(1, keys->size());
|
||||
}
|
||||
|
||||
// Verify that the "config-set" command will reuse listener
|
||||
TEST_F(HttpsCtrlChannelD2Test, ignoreHttpsToHttpSwitch) {
|
||||
|
||||
string ca_dir(string(TEST_CA_DIR));
|
||||
ostringstream d2_st;
|
||||
d2_st << " { \n"
|
||||
<< " \"ip-address\": \"192.168.77.1\", \n"
|
||||
<< " \"port\": 777, \n"
|
||||
<< " \"forward-ddns\" : {}, \n"
|
||||
<< " \"reverse-ddns\" : {}, \n"
|
||||
<< " \"tsig-keys\": [ \n"
|
||||
<< " {\"name\": \"d2_key.example.com\", \n"
|
||||
<< " \"algorithm\": \"hmac-md5\", \n"
|
||||
<< " \"secret\": \"LSWXnfkKZjdPJI5QxlpnfQ==\"} \n"
|
||||
<< " ], \n"
|
||||
<< " \"control-socket\": { \n"
|
||||
<< " \"socket-type\": \"https\", \n"
|
||||
<< " \"socket-address\": \"127.0.0.1\", \n"
|
||||
<< " \"socket-port\": 18125, \n"
|
||||
<< " \"trust-anchor\": \"" << ca_dir << "/kea-ca.crt\", \n"
|
||||
<< " \"cert-file\": \"" << ca_dir << "/kea-server.crt\", \n"
|
||||
<< " \"key-file\": \"" << ca_dir << "/kea-server.key\" \n"
|
||||
<< " } \n"
|
||||
<< " } \n";
|
||||
|
||||
ASSERT_TRUE(server_);
|
||||
|
||||
ConstElementPtr config;
|
||||
ASSERT_NO_THROW(config = parseDHCPDDNS(d2_st.str(), true));
|
||||
ASSERT_NO_THROW(d2Controller()->initProcess());
|
||||
D2ProcessPtr proc = d2Controller()->getProcess();
|
||||
ASSERT_TRUE(proc);
|
||||
ConstElementPtr answer = proc->configure(config, false);
|
||||
ASSERT_TRUE(answer);
|
||||
// Verify the configuration was successful. The config contains random
|
||||
// file paths (CA directory), 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 applied successfully." is there
|
||||
string answer_txt = answer->str();
|
||||
EXPECT_NE(answer_txt.find("\"result\": 0"), std::string::npos);
|
||||
EXPECT_NE(answer_txt.find("\"text\": \"Configuration applied successfully.\""),
|
||||
std::string::npos);
|
||||
ASSERT_NO_THROW(d2Controller()->registerCommands());
|
||||
|
||||
// Check that the config was indeed applied.
|
||||
D2CfgMgrPtr cfg_mgr = proc->getD2CfgMgr();
|
||||
ASSERT_TRUE(cfg_mgr);
|
||||
D2CfgContextPtr d2_context = cfg_mgr->getD2CfgContext();
|
||||
ASSERT_TRUE(d2_context);
|
||||
TSIGKeyInfoMapPtr keys = d2_context->getKeys();
|
||||
ASSERT_TRUE(keys);
|
||||
EXPECT_EQ(1, keys->size());
|
||||
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener());
|
||||
auto const listener = HttpCommandMgr::instance().getHttpListener().get();
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener()->getTlsContext());
|
||||
auto const context = HttpCommandMgr::instance().getHttpListener()->getTlsContext().get();
|
||||
|
||||
string d2_cfg_txt =
|
||||
" { \n"
|
||||
" \"ip-address\": \"192.168.77.1\", \n"
|
||||
" \"port\": 777, \n"
|
||||
" \"forward-ddns\" : {}, \n"
|
||||
" \"reverse-ddns\" : {}, \n"
|
||||
" \"tsig-keys\": [ \n"
|
||||
" {\"name\": \"d2_key.example.com\", \n"
|
||||
" \"algorithm\": \"hmac-md5\", \n"
|
||||
" \"secret\": \"LSWXnfkKZjdPJI5QxlpnfQ==\"} \n"
|
||||
" ], \n"
|
||||
" \"control-socket\": { \n"
|
||||
" \"socket-type\": \"http\", \n"
|
||||
" \"socket-address\": \"127.0.0.1\", \n"
|
||||
" \"socket-port\": 18125 \n"
|
||||
" } \n"
|
||||
" } \n";
|
||||
|
||||
// Create a config with HTTP and same content that should not recreate listener.
|
||||
string config_set_txt =
|
||||
"{ \"command\": \"config-set\", \n"
|
||||
" \"arguments\": { \n"
|
||||
" \"DhcpDdns\": \n";
|
||||
|
||||
config_set_txt += d2_cfg_txt;
|
||||
config_set_txt += "}} \n";
|
||||
|
||||
// Send the config-set command.
|
||||
string response;
|
||||
sendHttpCommand(config_set_txt, response);
|
||||
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener());
|
||||
EXPECT_EQ(listener, HttpCommandMgr::instance().getHttpListener().get());
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener()->getTlsContext());
|
||||
// The TLS settings have not changed
|
||||
EXPECT_EQ(context, HttpCommandMgr::instance().getHttpListener()->getTlsContext().get());
|
||||
|
||||
// Verify the configuration was successful.
|
||||
EXPECT_EQ("[ { \"arguments\": { \"hash\": \"029AE1208415D6911B5651A6F82D054F55B7877D2589CFD1DCEB5BFFCD3B13A3\" }, \"result\": 0, \"text\": \"Configuration applied successfully.\" } ]",
|
||||
response);
|
||||
|
||||
// Check that the config was applied.
|
||||
d2_context = cfg_mgr->getD2CfgContext();
|
||||
keys = d2_context->getKeys();
|
||||
ASSERT_TRUE(keys);
|
||||
EXPECT_EQ(1, keys->size());
|
||||
}
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
@@ -338,15 +338,10 @@ void configureCommandChannel() {
|
||||
ConstElementPtr current_http_config =
|
||||
CfgMgr::instance().getCurrentCfg()->getHttpControlSocketInfo();
|
||||
|
||||
sock_changed = (http_config && current_http_config &&
|
||||
!http_config->equals(*current_http_config));
|
||||
|
||||
if (!http_config || !current_http_config || sock_changed) {
|
||||
if (http_config) {
|
||||
HttpCommandMgr::instance().openCommandSockets(http_config);
|
||||
} else if (current_http_config) {
|
||||
HttpCommandMgr::instance().closeCommandSockets();
|
||||
}
|
||||
if (http_config) {
|
||||
HttpCommandMgr::instance().openCommandSockets(http_config);
|
||||
} else if (current_http_config) {
|
||||
HttpCommandMgr::instance().closeCommandSockets();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -983,7 +983,7 @@ TEST_F(HttpCtrlChannelDhcpv4Test, configSet) {
|
||||
|
||||
// Define strings to permutate the config arguments
|
||||
// (Note the line feeds makes errors easy to find)
|
||||
string set_config_txt = "{ \"command\": \"config-set\" \n";
|
||||
string config_set_txt = "{ \"command\": \"config-set\" \n";
|
||||
string args_txt = " \"arguments\": { \n";
|
||||
string dhcp4_cfg_txt =
|
||||
" \"Dhcp4\": { \n"
|
||||
@@ -1056,7 +1056,7 @@ TEST_F(HttpCtrlChannelDhcpv4Test, configSet) {
|
||||
std::ostringstream os;
|
||||
|
||||
// Create a valid config with all the parts should parse
|
||||
os << set_config_txt << ","
|
||||
os << config_set_txt << ","
|
||||
<< args_txt
|
||||
<< dhcp4_cfg_txt
|
||||
<< subnet1
|
||||
@@ -1085,7 +1085,7 @@ TEST_F(HttpCtrlChannelDhcpv4Test, configSet) {
|
||||
|
||||
// Create a config with malformed subnet that should fail to parse.
|
||||
os.str("");
|
||||
os << set_config_txt << ","
|
||||
os << config_set_txt << ","
|
||||
<< args_txt
|
||||
<< dhcp4_cfg_txt
|
||||
<< bad_subnet
|
||||
@@ -1114,7 +1114,7 @@ TEST_F(HttpCtrlChannelDhcpv4Test, configSet) {
|
||||
// Create a valid config with two subnets and no command channel.
|
||||
// It should succeed, client should still receive the response
|
||||
os.str("");
|
||||
os << set_config_txt << ","
|
||||
os << config_set_txt << ","
|
||||
<< args_txt
|
||||
<< dhcp4_cfg_txt
|
||||
<< subnet1
|
||||
@@ -1153,7 +1153,7 @@ TEST_F(HttpsCtrlChannelDhcpv4Test, configSet) {
|
||||
// Define strings to permutate the config arguments
|
||||
// (Note the line feeds makes errors easy to find)
|
||||
string ca_dir(string(TEST_CA_DIR));
|
||||
string set_config_txt = "{ \"command\": \"config-set\" \n";
|
||||
string config_set_txt = "{ \"command\": \"config-set\" \n";
|
||||
string args_txt = " \"arguments\": { \n";
|
||||
string dhcp4_cfg_txt =
|
||||
" \"Dhcp4\": { \n"
|
||||
@@ -1227,7 +1227,7 @@ TEST_F(HttpsCtrlChannelDhcpv4Test, configSet) {
|
||||
std::ostringstream os;
|
||||
|
||||
// Create a valid config with all the parts should parse
|
||||
os << set_config_txt << ","
|
||||
os << config_set_txt << ","
|
||||
<< args_txt
|
||||
<< dhcp4_cfg_txt
|
||||
<< subnet1
|
||||
@@ -1266,7 +1266,7 @@ TEST_F(HttpsCtrlChannelDhcpv4Test, configSet) {
|
||||
|
||||
// Create a config with malformed subnet that should fail to parse.
|
||||
os.str("");
|
||||
os << set_config_txt << ","
|
||||
os << config_set_txt << ","
|
||||
<< args_txt
|
||||
<< dhcp4_cfg_txt
|
||||
<< bad_subnet
|
||||
@@ -1299,7 +1299,7 @@ TEST_F(HttpsCtrlChannelDhcpv4Test, configSet) {
|
||||
// Create a valid config with two subnets and no command channel.
|
||||
// It should succeed, client should still receive the response
|
||||
os.str("");
|
||||
os << set_config_txt << ","
|
||||
os << config_set_txt << ","
|
||||
<< args_txt
|
||||
<< dhcp4_cfg_txt
|
||||
<< subnet1
|
||||
@@ -1411,7 +1411,7 @@ TEST_F(HttpCtrlChannelDhcpv4Test, configTest) {
|
||||
|
||||
// Define strings to permutate the config arguments
|
||||
// (Note the line feeds makes errors easy to find)
|
||||
string set_config_txt = "{ \"command\": \"config-set\" \n";
|
||||
string config_set_txt = "{ \"command\": \"config-set\" \n";
|
||||
string config_test_txt = "{ \"command\": \"config-test\" \n";
|
||||
string args_txt = " \"arguments\": { \n";
|
||||
string dhcp4_cfg_txt =
|
||||
@@ -1463,7 +1463,7 @@ TEST_F(HttpCtrlChannelDhcpv4Test, configTest) {
|
||||
std::ostringstream os;
|
||||
|
||||
// Create a valid config with all the parts should parse
|
||||
os << set_config_txt << ","
|
||||
os << config_set_txt << ","
|
||||
<< args_txt
|
||||
<< dhcp4_cfg_txt
|
||||
<< subnet1
|
||||
@@ -1552,7 +1552,7 @@ TEST_F(HttpsCtrlChannelDhcpv4Test, configTest) {
|
||||
// Define strings to permutate the config arguments
|
||||
// (Note the line feeds makes errors easy to find)
|
||||
string ca_dir(string(TEST_CA_DIR));
|
||||
string set_config_txt = "{ \"command\": \"config-set\" \n";
|
||||
string config_set_txt = "{ \"command\": \"config-set\" \n";
|
||||
string config_test_txt = "{ \"command\": \"config-test\" \n";
|
||||
string args_txt = " \"arguments\": { \n";
|
||||
string dhcp4_cfg_txt =
|
||||
@@ -1605,7 +1605,7 @@ TEST_F(HttpsCtrlChannelDhcpv4Test, configTest) {
|
||||
std::ostringstream os;
|
||||
|
||||
// Create a valid config with all the parts should parse
|
||||
os << set_config_txt << ","
|
||||
os << config_set_txt << ","
|
||||
<< args_txt
|
||||
<< dhcp4_cfg_txt
|
||||
<< subnet1
|
||||
@@ -3392,4 +3392,567 @@ TEST_F(HttpsCtrlChannelDhcpv4Test, connectionTimeoutNoData) {
|
||||
testConnectionTimeoutNoData();
|
||||
}
|
||||
|
||||
// Verify that the "config-set" command will reuse listener
|
||||
TEST_F(HttpCtrlChannelDhcpv4Test, noListenerChange) {
|
||||
createHttpChannelServer();
|
||||
|
||||
// Define strings to permutate the config arguments
|
||||
// (Note the line feeds makes errors easy to find)
|
||||
string config_set_txt = "{ \"command\": \"config-set\" \n";
|
||||
string args_txt = " \"arguments\": { \n";
|
||||
string dhcp4_cfg_txt =
|
||||
" \"Dhcp4\": { \n"
|
||||
" \"interfaces-config\": { \n"
|
||||
" \"interfaces\": [\"*\"] \n"
|
||||
" }, \n"
|
||||
" \"valid-lifetime\": 4000, \n"
|
||||
" \"renew-timer\": 1000, \n"
|
||||
" \"rebind-timer\": 2000, \n"
|
||||
" \"lease-database\": { \n"
|
||||
" \"type\": \"memfile\", \n"
|
||||
" \"persist\":false, \n"
|
||||
" \"lfc-interval\": 0 \n"
|
||||
" }, \n"
|
||||
" \"expired-leases-processing\": { \n"
|
||||
" \"reclaim-timer-wait-time\": 0, \n"
|
||||
" \"hold-reclaimed-time\": 0, \n"
|
||||
" \"flush-reclaimed-timer-wait-time\": 0 \n"
|
||||
" },"
|
||||
" \"subnet4\": [ \n";
|
||||
string subnet1 =
|
||||
" {\"subnet\": \"192.2.0.0/24\", \"id\": 1, \n"
|
||||
" \"pools\": [{ \"pool\": \"192.2.0.1-192.2.0.50\" }]}\n";
|
||||
string subnet_footer =
|
||||
" ] \n";
|
||||
string option_def =
|
||||
" ,\"option-def\": [\n"
|
||||
" {\n"
|
||||
" \"name\": \"foo\",\n"
|
||||
" \"code\": 163,\n"
|
||||
" \"type\": \"uint32\",\n"
|
||||
" \"array\": false,\n"
|
||||
" \"record-types\": \"\",\n"
|
||||
" \"space\": \"dhcp4\",\n"
|
||||
" \"encapsulate\": \"\"\n"
|
||||
" }\n"
|
||||
"]\n";
|
||||
string option_data =
|
||||
" ,\"option-data\": [\n"
|
||||
" {\n"
|
||||
" \"name\": \"foo\",\n"
|
||||
" \"code\": 163,\n"
|
||||
" \"space\": \"dhcp4\",\n"
|
||||
" \"csv-format\": true,\n"
|
||||
" \"data\": \"12345\"\n"
|
||||
" }\n"
|
||||
"]\n";
|
||||
string control_socket =
|
||||
" ,\"control-socket\": { \n"
|
||||
" \"socket-type\": \"http\", \n"
|
||||
" \"socket-address\": \"127.0.0.1\", \n"
|
||||
" \"socket-port\": 18124 \n"
|
||||
" } \n";
|
||||
string logger_txt =
|
||||
" ,\"loggers\": [ { \n"
|
||||
" \"name\": \"kea\", \n"
|
||||
" \"severity\": \"FATAL\", \n"
|
||||
" \"output-options\": [{ \n"
|
||||
" \"output\": \"/dev/null\", \n"
|
||||
" \"maxsize\": 0"
|
||||
" }] \n"
|
||||
" }] \n";
|
||||
|
||||
std::ostringstream os;
|
||||
|
||||
// Create a valid config with all the parts should parse
|
||||
os << config_set_txt << ","
|
||||
<< args_txt
|
||||
<< dhcp4_cfg_txt
|
||||
<< subnet1
|
||||
<< subnet_footer
|
||||
<< option_def
|
||||
<< option_data
|
||||
<< control_socket
|
||||
<< logger_txt
|
||||
<< "}\n" // close dhcp4
|
||||
<< "}}";
|
||||
|
||||
// Send the config-set command
|
||||
std::string response;
|
||||
sendHttpCommand(os.str(), response);
|
||||
EXPECT_EQ("[ { \"arguments\": { \"hash\": \"F6137301FF10D81585E041FD5FD8E91347ACADDE64F92ED03432FB100874DE02\" }, \"result\": 0, \"text\": \"Configuration successful.\" } ]",
|
||||
response);
|
||||
|
||||
// Check that the config was indeed applied.
|
||||
const Subnet4Collection* subnets =
|
||||
CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getAll();
|
||||
EXPECT_EQ(1, subnets->size());
|
||||
|
||||
OptionDefinitionPtr def =
|
||||
LibDHCP::getRuntimeOptionDef(DHCP4_OPTION_SPACE, 163);
|
||||
ASSERT_TRUE(def);
|
||||
|
||||
// Verify the HTTP control channel socket exists.
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener());
|
||||
auto const listener = HttpCommandMgr::instance().getHttpListener().get();
|
||||
ASSERT_FALSE(HttpCommandMgr::instance().getHttpListener()->getTlsContext());
|
||||
|
||||
// Send the config-set command.
|
||||
sendHttpCommand(os.str(), response);
|
||||
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener());
|
||||
EXPECT_EQ(listener, HttpCommandMgr::instance().getHttpListener().get());
|
||||
ASSERT_FALSE(HttpCommandMgr::instance().getHttpListener()->getTlsContext());
|
||||
|
||||
EXPECT_EQ("[ { \"arguments\": { \"hash\": \"F6137301FF10D81585E041FD5FD8E91347ACADDE64F92ED03432FB100874DE02\" }, \"result\": 0, \"text\": \"Configuration successful.\" } ]",
|
||||
response);
|
||||
|
||||
// Check that the config was not lost
|
||||
subnets = CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getAll();
|
||||
EXPECT_EQ(1, subnets->size());
|
||||
|
||||
// Clean up after the test.
|
||||
CfgMgr::instance().clear();
|
||||
}
|
||||
|
||||
// Verify that the "config-set" command will reuse listener
|
||||
TEST_F(HttpsCtrlChannelDhcpv4Test, noListenerChange) {
|
||||
createHttpChannelServer();
|
||||
|
||||
// Define strings to permutate the config arguments
|
||||
// (Note the line feeds makes errors easy to find)
|
||||
string ca_dir(string(TEST_CA_DIR));
|
||||
string config_set_txt = "{ \"command\": \"config-set\" \n";
|
||||
string args_txt = " \"arguments\": { \n";
|
||||
string dhcp4_cfg_txt =
|
||||
" \"Dhcp4\": { \n"
|
||||
" \"interfaces-config\": { \n"
|
||||
" \"interfaces\": [\"*\"] \n"
|
||||
" }, \n"
|
||||
" \"valid-lifetime\": 4000, \n"
|
||||
" \"renew-timer\": 1000, \n"
|
||||
" \"rebind-timer\": 2000, \n"
|
||||
" \"lease-database\": { \n"
|
||||
" \"type\": \"memfile\", \n"
|
||||
" \"persist\":false, \n"
|
||||
" \"lfc-interval\": 0 \n"
|
||||
" }, \n"
|
||||
" \"expired-leases-processing\": { \n"
|
||||
" \"reclaim-timer-wait-time\": 0, \n"
|
||||
" \"hold-reclaimed-time\": 0, \n"
|
||||
" \"flush-reclaimed-timer-wait-time\": 0 \n"
|
||||
" },"
|
||||
" \"subnet4\": [ \n";
|
||||
string subnet1 =
|
||||
" {\"subnet\": \"192.2.0.0/24\", \"id\": 1, \n"
|
||||
" \"pools\": [{ \"pool\": \"192.2.0.1-192.2.0.50\" }]}\n";
|
||||
string subnet_footer =
|
||||
" ] \n";
|
||||
string option_def =
|
||||
" ,\"option-def\": [\n"
|
||||
" {\n"
|
||||
" \"name\": \"foo\",\n"
|
||||
" \"code\": 163,\n"
|
||||
" \"type\": \"uint32\",\n"
|
||||
" \"array\": false,\n"
|
||||
" \"record-types\": \"\",\n"
|
||||
" \"space\": \"dhcp4\",\n"
|
||||
" \"encapsulate\": \"\"\n"
|
||||
" }\n"
|
||||
"]\n";
|
||||
string option_data =
|
||||
" ,\"option-data\": [\n"
|
||||
" {\n"
|
||||
" \"name\": \"foo\",\n"
|
||||
" \"code\": 163,\n"
|
||||
" \"space\": \"dhcp4\",\n"
|
||||
" \"csv-format\": true,\n"
|
||||
" \"data\": \"12345\"\n"
|
||||
" }\n"
|
||||
"]\n";
|
||||
string control_socket_header =
|
||||
" ,\"control-socket\": { \n";
|
||||
string control_socket_footer =
|
||||
" \"socket-type\": \"http\", \n"
|
||||
" \"socket-address\": \"127.0.0.1\", \n"
|
||||
" \"socket-port\": 18124 \n"
|
||||
" } \n";
|
||||
string logger_txt =
|
||||
" ,\"loggers\": [ { \n"
|
||||
" \"name\": \"kea\", \n"
|
||||
" \"severity\": \"FATAL\", \n"
|
||||
" \"output-options\": [{ \n"
|
||||
" \"output\": \"/dev/null\", \n"
|
||||
" \"maxsize\": 0"
|
||||
" }] \n"
|
||||
" }] \n";
|
||||
|
||||
std::ostringstream os;
|
||||
|
||||
// Create a valid config with all the parts should parse
|
||||
os << config_set_txt << ","
|
||||
<< args_txt
|
||||
<< dhcp4_cfg_txt
|
||||
<< subnet1
|
||||
<< subnet_footer
|
||||
<< option_def
|
||||
<< option_data
|
||||
<< control_socket_header
|
||||
<< " \"trust-anchor\": \"" << ca_dir << "/kea-ca.crt\", \n"
|
||||
<< " \"cert-file\": \"" << ca_dir << "/kea-server.crt\", \n"
|
||||
<< " \"key-file\": \"" << ca_dir << "/kea-server.key\", \n"
|
||||
<< control_socket_footer
|
||||
<< logger_txt
|
||||
<< "}\n" // close dhcp4
|
||||
<< "}}";
|
||||
|
||||
// Send the config-set command
|
||||
std::string response;
|
||||
sendHttpCommand(os.str(), response);
|
||||
// Verify the configuration was successful. The config contains random
|
||||
// file paths (CA directory), 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 Subnet4Collection* subnets =
|
||||
CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getAll();
|
||||
EXPECT_EQ(1, subnets->size());
|
||||
|
||||
OptionDefinitionPtr def =
|
||||
LibDHCP::getRuntimeOptionDef(DHCP4_OPTION_SPACE, 163);
|
||||
ASSERT_TRUE(def);
|
||||
|
||||
// Verify the HTTP control channel socket exists.
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener());
|
||||
auto const listener = HttpCommandMgr::instance().getHttpListener().get();
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener()->getTlsContext());
|
||||
auto const context = HttpCommandMgr::instance().getHttpListener()->getTlsContext().get();
|
||||
|
||||
// Send the config-set command.
|
||||
sendHttpCommand(os.str(), response);
|
||||
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener());
|
||||
EXPECT_EQ(listener, HttpCommandMgr::instance().getHttpListener().get());
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener()->getTlsContext());
|
||||
// The TLS settings have been applied
|
||||
EXPECT_NE(context, HttpCommandMgr::instance().getHttpListener()->getTlsContext().get());
|
||||
|
||||
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()->getCfgSubnets4()->getAll();
|
||||
EXPECT_EQ(1, subnets->size());
|
||||
|
||||
// Clean up after the test.
|
||||
CfgMgr::instance().clear();
|
||||
}
|
||||
|
||||
// Verify that the "config-set" command will reuse listener
|
||||
TEST_F(HttpCtrlChannelDhcpv4Test, ignoredHttpToHttpsSwitch) {
|
||||
createHttpChannelServer();
|
||||
|
||||
// Define strings to permutate the config arguments
|
||||
// (Note the line feeds makes errors easy to find)
|
||||
string ca_dir(string(TEST_CA_DIR));
|
||||
string config_set_txt = "{ \"command\": \"config-set\" \n";
|
||||
string args_txt = " \"arguments\": { \n";
|
||||
string dhcp4_cfg_txt =
|
||||
" \"Dhcp4\": { \n"
|
||||
" \"interfaces-config\": { \n"
|
||||
" \"interfaces\": [\"*\"] \n"
|
||||
" }, \n"
|
||||
" \"valid-lifetime\": 4000, \n"
|
||||
" \"renew-timer\": 1000, \n"
|
||||
" \"rebind-timer\": 2000, \n"
|
||||
" \"lease-database\": { \n"
|
||||
" \"type\": \"memfile\", \n"
|
||||
" \"persist\":false, \n"
|
||||
" \"lfc-interval\": 0 \n"
|
||||
" }, \n"
|
||||
" \"expired-leases-processing\": { \n"
|
||||
" \"reclaim-timer-wait-time\": 0, \n"
|
||||
" \"hold-reclaimed-time\": 0, \n"
|
||||
" \"flush-reclaimed-timer-wait-time\": 0 \n"
|
||||
" },"
|
||||
" \"subnet4\": [ \n";
|
||||
string subnet1 =
|
||||
" {\"subnet\": \"192.2.0.0/24\", \"id\": 1, \n"
|
||||
" \"pools\": [{ \"pool\": \"192.2.0.1-192.2.0.50\" }]}\n";
|
||||
string subnet_footer =
|
||||
" ] \n";
|
||||
string option_def =
|
||||
" ,\"option-def\": [\n"
|
||||
" {\n"
|
||||
" \"name\": \"foo\",\n"
|
||||
" \"code\": 163,\n"
|
||||
" \"type\": \"uint32\",\n"
|
||||
" \"array\": false,\n"
|
||||
" \"record-types\": \"\",\n"
|
||||
" \"space\": \"dhcp4\",\n"
|
||||
" \"encapsulate\": \"\"\n"
|
||||
" }\n"
|
||||
"]\n";
|
||||
string option_data =
|
||||
" ,\"option-data\": [\n"
|
||||
" {\n"
|
||||
" \"name\": \"foo\",\n"
|
||||
" \"code\": 163,\n"
|
||||
" \"space\": \"dhcp4\",\n"
|
||||
" \"csv-format\": true,\n"
|
||||
" \"data\": \"12345\"\n"
|
||||
" }\n"
|
||||
"]\n";
|
||||
string control_socket_header =
|
||||
" ,\"control-socket\": { \n";
|
||||
string control_socket_footer =
|
||||
" \"socket-type\": \"http\", \n"
|
||||
" \"socket-address\": \"127.0.0.1\", \n"
|
||||
" \"socket-port\": 18124 \n"
|
||||
" } \n";
|
||||
string logger_txt =
|
||||
" ,\"loggers\": [ { \n"
|
||||
" \"name\": \"kea\", \n"
|
||||
" \"severity\": \"FATAL\", \n"
|
||||
" \"output-options\": [{ \n"
|
||||
" \"output\": \"/dev/null\", \n"
|
||||
" \"maxsize\": 0"
|
||||
" }] \n"
|
||||
" }] \n";
|
||||
|
||||
std::ostringstream os;
|
||||
|
||||
// Create a valid config with all the parts should parse
|
||||
os << config_set_txt << ","
|
||||
<< args_txt
|
||||
<< dhcp4_cfg_txt
|
||||
<< subnet1
|
||||
<< subnet_footer
|
||||
<< option_def
|
||||
<< option_data
|
||||
<< control_socket_header
|
||||
<< control_socket_footer
|
||||
<< logger_txt
|
||||
<< "}\n" // close dhcp4
|
||||
<< "}}";
|
||||
|
||||
// Send the config-set command
|
||||
std::string response;
|
||||
sendHttpCommand(os.str(), response);
|
||||
EXPECT_EQ("[ { \"arguments\": { \"hash\": \"F6137301FF10D81585E041FD5FD8E91347ACADDE64F92ED03432FB100874DE02\" }, \"result\": 0, \"text\": \"Configuration successful.\" } ]",
|
||||
response);
|
||||
|
||||
// Check that the config was indeed applied.
|
||||
const Subnet4Collection* subnets =
|
||||
CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getAll();
|
||||
EXPECT_EQ(1, subnets->size());
|
||||
|
||||
OptionDefinitionPtr def =
|
||||
LibDHCP::getRuntimeOptionDef(DHCP4_OPTION_SPACE, 163);
|
||||
ASSERT_TRUE(def);
|
||||
|
||||
// Verify the HTTP control channel socket exists.
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener());
|
||||
auto const listener = HttpCommandMgr::instance().getHttpListener().get();
|
||||
ASSERT_FALSE(HttpCommandMgr::instance().getHttpListener()->getTlsContext());
|
||||
|
||||
std::ostringstream second_config_os;
|
||||
|
||||
// Create a valid config with all the parts should parse
|
||||
second_config_os << config_set_txt << ","
|
||||
<< args_txt
|
||||
<< dhcp4_cfg_txt
|
||||
<< subnet1
|
||||
<< subnet_footer
|
||||
<< option_def
|
||||
<< option_data
|
||||
<< control_socket_header
|
||||
<< " \"trust-anchor\": \"" << ca_dir << "/kea-ca.crt\", \n"
|
||||
<< " \"cert-file\": \"" << ca_dir << "/kea-server.crt\", \n"
|
||||
<< " \"key-file\": \"" << ca_dir << "/kea-server.key\", \n"
|
||||
<< control_socket_footer
|
||||
<< logger_txt
|
||||
<< "}\n" // close dhcp4
|
||||
<< "}}";
|
||||
|
||||
// Send the config-set command.
|
||||
sendHttpCommand(second_config_os.str(), response);
|
||||
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener());
|
||||
EXPECT_EQ(listener, HttpCommandMgr::instance().getHttpListener().get());
|
||||
ASSERT_FALSE(HttpCommandMgr::instance().getHttpListener()->getTlsContext());
|
||||
|
||||
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()->getCfgSubnets4()->getAll();
|
||||
EXPECT_EQ(1, subnets->size());
|
||||
|
||||
// Clean up after the test.
|
||||
CfgMgr::instance().clear();
|
||||
}
|
||||
|
||||
// Verify that the "config-set" command will reuse listener
|
||||
TEST_F(HttpsCtrlChannelDhcpv4Test, ignoreHttpsToHttpSwitch) {
|
||||
createHttpChannelServer();
|
||||
|
||||
// Define strings to permutate the config arguments
|
||||
// (Note the line feeds makes errors easy to find)
|
||||
string ca_dir(string(TEST_CA_DIR));
|
||||
string config_set_txt = "{ \"command\": \"config-set\" \n";
|
||||
string args_txt = " \"arguments\": { \n";
|
||||
string dhcp4_cfg_txt =
|
||||
" \"Dhcp4\": { \n"
|
||||
" \"interfaces-config\": { \n"
|
||||
" \"interfaces\": [\"*\"] \n"
|
||||
" }, \n"
|
||||
" \"valid-lifetime\": 4000, \n"
|
||||
" \"renew-timer\": 1000, \n"
|
||||
" \"rebind-timer\": 2000, \n"
|
||||
" \"lease-database\": { \n"
|
||||
" \"type\": \"memfile\", \n"
|
||||
" \"persist\":false, \n"
|
||||
" \"lfc-interval\": 0 \n"
|
||||
" }, \n"
|
||||
" \"expired-leases-processing\": { \n"
|
||||
" \"reclaim-timer-wait-time\": 0, \n"
|
||||
" \"hold-reclaimed-time\": 0, \n"
|
||||
" \"flush-reclaimed-timer-wait-time\": 0 \n"
|
||||
" },"
|
||||
" \"subnet4\": [ \n";
|
||||
string subnet1 =
|
||||
" {\"subnet\": \"192.2.0.0/24\", \"id\": 1, \n"
|
||||
" \"pools\": [{ \"pool\": \"192.2.0.1-192.2.0.50\" }]}\n";
|
||||
string subnet_footer =
|
||||
" ] \n";
|
||||
string option_def =
|
||||
" ,\"option-def\": [\n"
|
||||
" {\n"
|
||||
" \"name\": \"foo\",\n"
|
||||
" \"code\": 163,\n"
|
||||
" \"type\": \"uint32\",\n"
|
||||
" \"array\": false,\n"
|
||||
" \"record-types\": \"\",\n"
|
||||
" \"space\": \"dhcp4\",\n"
|
||||
" \"encapsulate\": \"\"\n"
|
||||
" }\n"
|
||||
"]\n";
|
||||
string option_data =
|
||||
" ,\"option-data\": [\n"
|
||||
" {\n"
|
||||
" \"name\": \"foo\",\n"
|
||||
" \"code\": 163,\n"
|
||||
" \"space\": \"dhcp4\",\n"
|
||||
" \"csv-format\": true,\n"
|
||||
" \"data\": \"12345\"\n"
|
||||
" }\n"
|
||||
"]\n";
|
||||
string control_socket_header =
|
||||
" ,\"control-socket\": { \n";
|
||||
string control_socket_footer =
|
||||
" \"socket-type\": \"http\", \n"
|
||||
" \"socket-address\": \"127.0.0.1\", \n"
|
||||
" \"socket-port\": 18124 \n"
|
||||
" } \n";
|
||||
string logger_txt =
|
||||
" ,\"loggers\": [ { \n"
|
||||
" \"name\": \"kea\", \n"
|
||||
" \"severity\": \"FATAL\", \n"
|
||||
" \"output-options\": [{ \n"
|
||||
" \"output\": \"/dev/null\", \n"
|
||||
" \"maxsize\": 0"
|
||||
" }] \n"
|
||||
" }] \n";
|
||||
|
||||
std::ostringstream os;
|
||||
|
||||
// Create a valid config with all the parts should parse
|
||||
os << config_set_txt << ","
|
||||
<< args_txt
|
||||
<< dhcp4_cfg_txt
|
||||
<< subnet1
|
||||
<< subnet_footer
|
||||
<< option_def
|
||||
<< option_data
|
||||
<< control_socket_header
|
||||
<< " \"trust-anchor\": \"" << ca_dir << "/kea-ca.crt\", \n"
|
||||
<< " \"cert-file\": \"" << ca_dir << "/kea-server.crt\", \n"
|
||||
<< " \"key-file\": \"" << ca_dir << "/kea-server.key\", \n"
|
||||
<< control_socket_footer
|
||||
<< logger_txt
|
||||
<< "}\n" // close dhcp4
|
||||
<< "}}";
|
||||
|
||||
// Send the config-set command
|
||||
std::string response;
|
||||
sendHttpCommand(os.str(), response);
|
||||
// Verify the configuration was successful. The config contains random
|
||||
// file paths (CA directory), 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 Subnet4Collection* subnets =
|
||||
CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getAll();
|
||||
EXPECT_EQ(1, subnets->size());
|
||||
|
||||
OptionDefinitionPtr def =
|
||||
LibDHCP::getRuntimeOptionDef(DHCP4_OPTION_SPACE, 163);
|
||||
ASSERT_TRUE(def);
|
||||
|
||||
// Verify the HTTP control channel socket exists.
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener());
|
||||
auto const listener = HttpCommandMgr::instance().getHttpListener().get();
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener()->getTlsContext());
|
||||
// The TLS settings have not changed
|
||||
auto const context = HttpCommandMgr::instance().getHttpListener()->getTlsContext().get();
|
||||
|
||||
std::ostringstream second_config_os;
|
||||
|
||||
// Create a valid config with all the parts should parse
|
||||
second_config_os << config_set_txt << ","
|
||||
<< args_txt
|
||||
<< dhcp4_cfg_txt
|
||||
<< subnet1
|
||||
<< subnet_footer
|
||||
<< option_def
|
||||
<< option_data
|
||||
<< control_socket_header
|
||||
<< control_socket_footer
|
||||
<< logger_txt
|
||||
<< "}\n" // close dhcp4
|
||||
<< "}}";
|
||||
|
||||
// Send the config-set command.
|
||||
sendHttpCommand(second_config_os.str(), response);
|
||||
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener());
|
||||
EXPECT_EQ(listener, HttpCommandMgr::instance().getHttpListener().get());
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener()->getTlsContext());
|
||||
EXPECT_EQ(context, HttpCommandMgr::instance().getHttpListener()->getTlsContext().get());
|
||||
|
||||
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()->getCfgSubnets4()->getAll();
|
||||
EXPECT_EQ(1, subnets->size());
|
||||
|
||||
// Clean up after the test.
|
||||
CfgMgr::instance().clear();
|
||||
}
|
||||
|
||||
} // End of anonymous namespace
|
||||
|
@@ -440,15 +440,10 @@ void configureCommandChannel() {
|
||||
ConstElementPtr current_http_config =
|
||||
CfgMgr::instance().getCurrentCfg()->getHttpControlSocketInfo();
|
||||
|
||||
sock_changed = (http_config && current_http_config &&
|
||||
!http_config->equals(*current_http_config));
|
||||
|
||||
if (!http_config || !current_http_config || sock_changed) {
|
||||
if (http_config) {
|
||||
HttpCommandMgr::instance().openCommandSockets(http_config);
|
||||
} else if (current_http_config) {
|
||||
HttpCommandMgr::instance().closeCommandSockets();
|
||||
}
|
||||
if (http_config) {
|
||||
HttpCommandMgr::instance().openCommandSockets(http_config);
|
||||
} else if (current_http_config) {
|
||||
HttpCommandMgr::instance().closeCommandSockets();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1013,7 +1013,7 @@ TEST_F(HttpCtrlChannelDhcpv6Test, configSet) {
|
||||
|
||||
// Define strings to permutate the config arguments
|
||||
// (Note the line feeds makes errors easy to find)
|
||||
string set_config_txt = "{ \"command\": \"config-set\" \n";
|
||||
string config_set_txt = "{ \"command\": \"config-set\" \n";
|
||||
string args_txt = " \"arguments\": { \n";
|
||||
string dhcp6_cfg_txt =
|
||||
" \"Dhcp6\": { \n"
|
||||
@@ -1087,7 +1087,7 @@ TEST_F(HttpCtrlChannelDhcpv6Test, configSet) {
|
||||
std::ostringstream os;
|
||||
|
||||
// Create a valid config with all the parts should parse
|
||||
os << set_config_txt << ","
|
||||
os << config_set_txt << ","
|
||||
<< args_txt
|
||||
<< dhcp6_cfg_txt
|
||||
<< subnet1
|
||||
@@ -1116,7 +1116,7 @@ TEST_F(HttpCtrlChannelDhcpv6Test, configSet) {
|
||||
|
||||
// Create a config with malformed subnet that should fail to parse.
|
||||
os.str("");
|
||||
os << set_config_txt << ","
|
||||
os << config_set_txt << ","
|
||||
<< args_txt
|
||||
<< dhcp6_cfg_txt
|
||||
<< bad_subnet
|
||||
@@ -1145,7 +1145,7 @@ TEST_F(HttpCtrlChannelDhcpv6Test, configSet) {
|
||||
// Create a valid config with two subnets and no command channel.
|
||||
// It should succeed, client should still receive the response
|
||||
os.str("");
|
||||
os << set_config_txt << ","
|
||||
os << config_set_txt << ","
|
||||
<< args_txt
|
||||
<< dhcp6_cfg_txt
|
||||
<< subnet1
|
||||
@@ -1184,7 +1184,7 @@ TEST_F(HttpsCtrlChannelDhcpv6Test, configSet) {
|
||||
// Define strings to permutate the config arguments
|
||||
// (Note the line feeds makes errors easy to find)
|
||||
string ca_dir(string(TEST_CA_DIR));
|
||||
string set_config_txt = "{ \"command\": \"config-set\" \n";
|
||||
string config_set_txt = "{ \"command\": \"config-set\" \n";
|
||||
string args_txt = " \"arguments\": { \n";
|
||||
string dhcp6_cfg_txt =
|
||||
" \"Dhcp6\": { \n"
|
||||
@@ -1259,7 +1259,7 @@ TEST_F(HttpsCtrlChannelDhcpv6Test, configSet) {
|
||||
std::ostringstream os;
|
||||
|
||||
// Create a valid config with all the parts should parse
|
||||
os << set_config_txt << ","
|
||||
os << config_set_txt << ","
|
||||
<< args_txt
|
||||
<< dhcp6_cfg_txt
|
||||
<< subnet1
|
||||
@@ -1298,7 +1298,7 @@ TEST_F(HttpsCtrlChannelDhcpv6Test, configSet) {
|
||||
|
||||
// Create a config with malformed subnet that should fail to parse.
|
||||
os.str("");
|
||||
os << set_config_txt << ","
|
||||
os << config_set_txt << ","
|
||||
<< args_txt
|
||||
<< dhcp6_cfg_txt
|
||||
<< bad_subnet
|
||||
@@ -1331,7 +1331,7 @@ TEST_F(HttpsCtrlChannelDhcpv6Test, configSet) {
|
||||
// Create a valid config with two subnets and no command channel.
|
||||
// It should succeed, client should still receive the response
|
||||
os.str("");
|
||||
os << set_config_txt << ","
|
||||
os << config_set_txt << ","
|
||||
<< args_txt
|
||||
<< dhcp6_cfg_txt
|
||||
<< subnet1
|
||||
@@ -1443,7 +1443,7 @@ TEST_F(HttpCtrlChannelDhcpv6Test, configTest) {
|
||||
|
||||
// Define strings to permutate the config arguments
|
||||
// (Note the line feeds makes errors easy to find)
|
||||
string set_config_txt = "{ \"command\": \"config-set\" \n";
|
||||
string config_set_txt = "{ \"command\": \"config-set\" \n";
|
||||
string config_test_txt = "{ \"command\": \"config-test\" \n";
|
||||
string args_txt = " \"arguments\": { \n";
|
||||
string dhcp6_cfg_txt =
|
||||
@@ -1496,7 +1496,7 @@ TEST_F(HttpCtrlChannelDhcpv6Test, configTest) {
|
||||
std::ostringstream os;
|
||||
|
||||
// Create a valid config with all the parts should parse
|
||||
os << set_config_txt << ","
|
||||
os << config_set_txt << ","
|
||||
<< args_txt
|
||||
<< dhcp6_cfg_txt
|
||||
<< subnet1
|
||||
@@ -1585,7 +1585,7 @@ TEST_F(HttpsCtrlChannelDhcpv6Test, configTest) {
|
||||
// Define strings to permutate the config arguments
|
||||
// (Note the line feeds makes errors easy to find)
|
||||
string ca_dir(string(TEST_CA_DIR));
|
||||
string set_config_txt = "{ \"command\": \"config-set\" \n";
|
||||
string config_set_txt = "{ \"command\": \"config-set\" \n";
|
||||
string config_test_txt = "{ \"command\": \"config-test\" \n";
|
||||
string args_txt = " \"arguments\": { \n";
|
||||
string dhcp6_cfg_txt =
|
||||
@@ -1639,7 +1639,7 @@ TEST_F(HttpsCtrlChannelDhcpv6Test, configTest) {
|
||||
std::ostringstream os;
|
||||
|
||||
// Create a valid config with all the parts should parse
|
||||
os << set_config_txt << ","
|
||||
os << config_set_txt << ","
|
||||
<< args_txt
|
||||
<< dhcp6_cfg_txt
|
||||
<< subnet1
|
||||
@@ -3401,4 +3401,571 @@ TEST_F(HttpsCtrlChannelDhcpv6Test, connectionTimeoutNoData) {
|
||||
testConnectionTimeoutNoData();
|
||||
}
|
||||
|
||||
// Verify that the "config-set" command will reuse listener
|
||||
TEST_F(HttpCtrlChannelDhcpv6Test, noListenerChange) {
|
||||
createHttpChannelServer();
|
||||
|
||||
// Define strings to permutate the config arguments
|
||||
// (Note the line feeds makes errors easy to find)
|
||||
string config_set_txt = "{ \"command\": \"config-set\" \n";
|
||||
string args_txt = " \"arguments\": { \n";
|
||||
string dhcp6_cfg_txt =
|
||||
" \"Dhcp6\": { \n"
|
||||
" \"interfaces-config\": { \n"
|
||||
" \"interfaces\": [\"*\"] \n"
|
||||
" }, \n"
|
||||
" \"preferred-lifetime\": 3000, \n"
|
||||
" \"valid-lifetime\": 4000, \n"
|
||||
" \"renew-timer\": 1000, \n"
|
||||
" \"rebind-timer\": 2000, \n"
|
||||
" \"lease-database\": { \n"
|
||||
" \"type\": \"memfile\", \n"
|
||||
" \"persist\":false, \n"
|
||||
" \"lfc-interval\": 0 \n"
|
||||
" }, \n"
|
||||
" \"expired-leases-processing\": { \n"
|
||||
" \"reclaim-timer-wait-time\": 0, \n"
|
||||
" \"hold-reclaimed-time\": 0, \n"
|
||||
" \"flush-reclaimed-timer-wait-time\": 0 \n"
|
||||
" },"
|
||||
" \"subnet6\": [ \n";
|
||||
string subnet1 =
|
||||
" {\"subnet\": \"3002::/64\", \"id\": 1, \n"
|
||||
" \"pools\": [{ \"pool\": \"3002::100-3002::200\" }]}\n";
|
||||
string subnet_footer =
|
||||
" ] \n";
|
||||
string option_def =
|
||||
" ,\"option-def\": [\n"
|
||||
" {\n"
|
||||
" \"name\": \"foo\",\n"
|
||||
" \"code\": 163,\n"
|
||||
" \"type\": \"uint32\",\n"
|
||||
" \"array\": false,\n"
|
||||
" \"record-types\": \"\",\n"
|
||||
" \"space\": \"dhcp6\",\n"
|
||||
" \"encapsulate\": \"\"\n"
|
||||
" }\n"
|
||||
"]\n";
|
||||
string option_data =
|
||||
" ,\"option-data\": [\n"
|
||||
" {\n"
|
||||
" \"name\": \"foo\",\n"
|
||||
" \"code\": 163,\n"
|
||||
" \"space\": \"dhcp6\",\n"
|
||||
" \"csv-format\": true,\n"
|
||||
" \"data\": \"12345\"\n"
|
||||
" }\n"
|
||||
"]\n";
|
||||
string control_socket =
|
||||
" ,\"control-socket\": { \n"
|
||||
" \"socket-type\": \"http\", \n"
|
||||
" \"socket-address\": \"::1\", \n"
|
||||
" \"socket-port\": 18126 \n"
|
||||
" } \n";
|
||||
string logger_txt =
|
||||
" ,\"loggers\": [ { \n"
|
||||
" \"name\": \"kea\", \n"
|
||||
" \"severity\": \"FATAL\", \n"
|
||||
" \"output-options\": [{ \n"
|
||||
" \"output\": \"/dev/null\", \n"
|
||||
" \"maxsize\": 0"
|
||||
" }] \n"
|
||||
" }] \n";
|
||||
|
||||
std::ostringstream os;
|
||||
|
||||
// Create a valid config with all the parts should parse
|
||||
os << config_set_txt << ","
|
||||
<< args_txt
|
||||
<< dhcp6_cfg_txt
|
||||
<< subnet1
|
||||
<< subnet_footer
|
||||
<< option_def
|
||||
<< option_data
|
||||
<< control_socket
|
||||
<< logger_txt
|
||||
<< "}\n" // close dhcp6
|
||||
<< "}}";
|
||||
|
||||
// Send the config-set command
|
||||
std::string response;
|
||||
sendHttpCommand(os.str(), response);
|
||||
EXPECT_EQ("[ { \"arguments\": { \"hash\": \"BCE3D0CC68CBBB49C3F5967E3FFCB4E44E55CBFB53814761B12ADB5C7CD95C1F\" }, \"result\": 0, \"text\": \"Configuration successful.\" } ]",
|
||||
response);
|
||||
|
||||
// Check that the config was indeed applied.
|
||||
const Subnet6Collection* subnets =
|
||||
CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getAll();
|
||||
EXPECT_EQ(1, subnets->size());
|
||||
|
||||
OptionDefinitionPtr def =
|
||||
LibDHCP::getRuntimeOptionDef(DHCP6_OPTION_SPACE, 163);
|
||||
ASSERT_TRUE(def);
|
||||
|
||||
// Verify the HTTP control channel socket exists.
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener());
|
||||
auto const listener = HttpCommandMgr::instance().getHttpListener().get();
|
||||
ASSERT_FALSE(HttpCommandMgr::instance().getHttpListener()->getTlsContext());
|
||||
|
||||
// Send the config-set command.
|
||||
sendHttpCommand(os.str(), response);
|
||||
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener());
|
||||
EXPECT_EQ(listener, HttpCommandMgr::instance().getHttpListener().get());
|
||||
ASSERT_FALSE(HttpCommandMgr::instance().getHttpListener()->getTlsContext());
|
||||
|
||||
EXPECT_EQ("[ { \"arguments\": { \"hash\": \"BCE3D0CC68CBBB49C3F5967E3FFCB4E44E55CBFB53814761B12ADB5C7CD95C1F\" }, \"result\": 0, \"text\": \"Configuration successful.\" } ]",
|
||||
response);
|
||||
|
||||
// Check that the config was not lost
|
||||
subnets = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getAll();
|
||||
EXPECT_EQ(1, subnets->size());
|
||||
|
||||
// Clean up after the test.
|
||||
CfgMgr::instance().clear();
|
||||
}
|
||||
|
||||
// Verify that the "config-set" command will reuse listener
|
||||
TEST_F(HttpsCtrlChannelDhcpv6Test, noListenerChange) {
|
||||
createHttpChannelServer();
|
||||
|
||||
// Define strings to permutate the config arguments
|
||||
// (Note the line feeds makes errors easy to find)
|
||||
string ca_dir(string(TEST_CA_DIR));
|
||||
string config_set_txt = "{ \"command\": \"config-set\" \n";
|
||||
string args_txt = " \"arguments\": { \n";
|
||||
string dhcp6_cfg_txt =
|
||||
" \"Dhcp6\": { \n"
|
||||
" \"interfaces-config\": { \n"
|
||||
" \"interfaces\": [\"*\"] \n"
|
||||
" }, \n"
|
||||
" \"preferred-lifetime\": 3000, \n"
|
||||
" \"valid-lifetime\": 4000, \n"
|
||||
" \"renew-timer\": 1000, \n"
|
||||
" \"rebind-timer\": 2000, \n"
|
||||
" \"lease-database\": { \n"
|
||||
" \"type\": \"memfile\", \n"
|
||||
" \"persist\":false, \n"
|
||||
" \"lfc-interval\": 0 \n"
|
||||
" }, \n"
|
||||
" \"expired-leases-processing\": { \n"
|
||||
" \"reclaim-timer-wait-time\": 0, \n"
|
||||
" \"hold-reclaimed-time\": 0, \n"
|
||||
" \"flush-reclaimed-timer-wait-time\": 0 \n"
|
||||
" },"
|
||||
" \"subnet6\": [ \n";
|
||||
string subnet1 =
|
||||
" {\"subnet\": \"3002::/64\", \"id\": 1, \n"
|
||||
" \"pools\": [{ \"pool\": \"3002::100-3002::200\" }]}\n";
|
||||
string subnet_footer =
|
||||
" ] \n";
|
||||
string option_def =
|
||||
" ,\"option-def\": [\n"
|
||||
" {\n"
|
||||
" \"name\": \"foo\",\n"
|
||||
" \"code\": 163,\n"
|
||||
" \"type\": \"uint32\",\n"
|
||||
" \"array\": false,\n"
|
||||
" \"record-types\": \"\",\n"
|
||||
" \"space\": \"dhcp6\",\n"
|
||||
" \"encapsulate\": \"\"\n"
|
||||
" }\n"
|
||||
"]\n";
|
||||
string option_data =
|
||||
" ,\"option-data\": [\n"
|
||||
" {\n"
|
||||
" \"name\": \"foo\",\n"
|
||||
" \"code\": 163,\n"
|
||||
" \"space\": \"dhcp6\",\n"
|
||||
" \"csv-format\": true,\n"
|
||||
" \"data\": \"12345\"\n"
|
||||
" }\n"
|
||||
"]\n";
|
||||
string control_socket_header =
|
||||
" ,\"control-socket\": { \n";
|
||||
string control_socket_footer =
|
||||
" \"socket-type\": \"http\", \n"
|
||||
" \"socket-address\": \"::1\", \n"
|
||||
" \"socket-port\": 18126 \n"
|
||||
" } \n";
|
||||
string logger_txt =
|
||||
" ,\"loggers\": [ { \n"
|
||||
" \"name\": \"kea\", \n"
|
||||
" \"severity\": \"FATAL\", \n"
|
||||
" \"output-options\": [{ \n"
|
||||
" \"output\": \"/dev/null\", \n"
|
||||
" \"maxsize\": 0"
|
||||
" }] \n"
|
||||
" }] \n";
|
||||
|
||||
std::ostringstream os;
|
||||
|
||||
// Create a valid config with all the parts should parse
|
||||
os << config_set_txt << ","
|
||||
<< args_txt
|
||||
<< dhcp6_cfg_txt
|
||||
<< subnet1
|
||||
<< subnet_footer
|
||||
<< option_def
|
||||
<< option_data
|
||||
<< control_socket_header
|
||||
<< " \"trust-anchor\": \"" << ca_dir << "/kea-ca.crt\", \n"
|
||||
<< " \"cert-file\": \"" << ca_dir << "/kea-server.crt\", \n"
|
||||
<< " \"key-file\": \"" << ca_dir << "/kea-server.key\", \n"
|
||||
<< control_socket_footer
|
||||
<< logger_txt
|
||||
<< "}\n" // close dhcp6
|
||||
<< "}}";
|
||||
|
||||
// Send the config-set command
|
||||
std::string response;
|
||||
sendHttpCommand(os.str(), response);
|
||||
// Verify the configuration was successful. The config contains random
|
||||
// file paths (CA directory), 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 =
|
||||
CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getAll();
|
||||
EXPECT_EQ(1, subnets->size());
|
||||
|
||||
OptionDefinitionPtr def =
|
||||
LibDHCP::getRuntimeOptionDef(DHCP6_OPTION_SPACE, 163);
|
||||
ASSERT_TRUE(def);
|
||||
|
||||
// Verify the HTTP control channel socket exists.
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener());
|
||||
auto const listener = HttpCommandMgr::instance().getHttpListener().get();
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener()->getTlsContext());
|
||||
auto const context = HttpCommandMgr::instance().getHttpListener()->getTlsContext().get();
|
||||
|
||||
// Send the config-set command.
|
||||
sendHttpCommand(os.str(), response);
|
||||
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener());
|
||||
EXPECT_EQ(listener, HttpCommandMgr::instance().getHttpListener().get());
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener()->getTlsContext());
|
||||
// The TLS settings have been applied
|
||||
EXPECT_NE(context, HttpCommandMgr::instance().getHttpListener()->getTlsContext().get());
|
||||
|
||||
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();
|
||||
EXPECT_EQ(1, subnets->size());
|
||||
|
||||
// Clean up after the test.
|
||||
CfgMgr::instance().clear();
|
||||
}
|
||||
|
||||
// Verify that the "config-set" command will reuse listener
|
||||
TEST_F(HttpCtrlChannelDhcpv6Test, ignoreHttpToHttpsSwitch) {
|
||||
createHttpChannelServer();
|
||||
|
||||
// Define strings to permutate the config arguments
|
||||
// (Note the line feeds makes errors easy to find)
|
||||
string ca_dir(string(TEST_CA_DIR));
|
||||
string config_set_txt = "{ \"command\": \"config-set\" \n";
|
||||
string args_txt = " \"arguments\": { \n";
|
||||
string dhcp6_cfg_txt =
|
||||
" \"Dhcp6\": { \n"
|
||||
" \"interfaces-config\": { \n"
|
||||
" \"interfaces\": [\"*\"] \n"
|
||||
" }, \n"
|
||||
" \"preferred-lifetime\": 3000, \n"
|
||||
" \"valid-lifetime\": 4000, \n"
|
||||
" \"renew-timer\": 1000, \n"
|
||||
" \"rebind-timer\": 2000, \n"
|
||||
" \"lease-database\": { \n"
|
||||
" \"type\": \"memfile\", \n"
|
||||
" \"persist\":false, \n"
|
||||
" \"lfc-interval\": 0 \n"
|
||||
" }, \n"
|
||||
" \"expired-leases-processing\": { \n"
|
||||
" \"reclaim-timer-wait-time\": 0, \n"
|
||||
" \"hold-reclaimed-time\": 0, \n"
|
||||
" \"flush-reclaimed-timer-wait-time\": 0 \n"
|
||||
" },"
|
||||
" \"subnet6\": [ \n";
|
||||
string subnet1 =
|
||||
" {\"subnet\": \"3002::/64\", \"id\": 1, \n"
|
||||
" \"pools\": [{ \"pool\": \"3002::100-3002::200\" }]}\n";
|
||||
string subnet_footer =
|
||||
" ] \n";
|
||||
string option_def =
|
||||
" ,\"option-def\": [\n"
|
||||
" {\n"
|
||||
" \"name\": \"foo\",\n"
|
||||
" \"code\": 163,\n"
|
||||
" \"type\": \"uint32\",\n"
|
||||
" \"array\": false,\n"
|
||||
" \"record-types\": \"\",\n"
|
||||
" \"space\": \"dhcp6\",\n"
|
||||
" \"encapsulate\": \"\"\n"
|
||||
" }\n"
|
||||
"]\n";
|
||||
string option_data =
|
||||
" ,\"option-data\": [\n"
|
||||
" {\n"
|
||||
" \"name\": \"foo\",\n"
|
||||
" \"code\": 163,\n"
|
||||
" \"space\": \"dhcp6\",\n"
|
||||
" \"csv-format\": true,\n"
|
||||
" \"data\": \"12345\"\n"
|
||||
" }\n"
|
||||
"]\n";
|
||||
string control_socket_header =
|
||||
" ,\"control-socket\": { \n";
|
||||
string control_socket_footer =
|
||||
" \"socket-type\": \"http\", \n"
|
||||
" \"socket-address\": \"::1\", \n"
|
||||
" \"socket-port\": 18126 \n"
|
||||
" } \n";
|
||||
string logger_txt =
|
||||
" ,\"loggers\": [ { \n"
|
||||
" \"name\": \"kea\", \n"
|
||||
" \"severity\": \"FATAL\", \n"
|
||||
" \"output-options\": [{ \n"
|
||||
" \"output\": \"/dev/null\", \n"
|
||||
" \"maxsize\": 0"
|
||||
" }] \n"
|
||||
" }] \n";
|
||||
|
||||
std::ostringstream os;
|
||||
|
||||
// Create a valid config with all the parts should parse
|
||||
os << config_set_txt << ","
|
||||
<< args_txt
|
||||
<< dhcp6_cfg_txt
|
||||
<< subnet1
|
||||
<< subnet_footer
|
||||
<< option_def
|
||||
<< option_data
|
||||
<< control_socket_header
|
||||
<< control_socket_footer
|
||||
<< logger_txt
|
||||
<< "}\n" // close dhcp6
|
||||
<< "}}";
|
||||
|
||||
// Send the config-set command
|
||||
std::string response;
|
||||
sendHttpCommand(os.str(), response);
|
||||
EXPECT_EQ("[ { \"arguments\": { \"hash\": \"BCE3D0CC68CBBB49C3F5967E3FFCB4E44E55CBFB53814761B12ADB5C7CD95C1F\" }, \"result\": 0, \"text\": \"Configuration successful.\" } ]",
|
||||
response);
|
||||
|
||||
// Check that the config was indeed applied.
|
||||
const Subnet6Collection* subnets =
|
||||
CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getAll();
|
||||
EXPECT_EQ(1, subnets->size());
|
||||
|
||||
OptionDefinitionPtr def =
|
||||
LibDHCP::getRuntimeOptionDef(DHCP6_OPTION_SPACE, 163);
|
||||
ASSERT_TRUE(def);
|
||||
|
||||
// Verify the HTTP control channel socket exists.
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener());
|
||||
auto const listener = HttpCommandMgr::instance().getHttpListener().get();
|
||||
ASSERT_FALSE(HttpCommandMgr::instance().getHttpListener()->getTlsContext());
|
||||
|
||||
std::ostringstream second_config_os;
|
||||
|
||||
// Create a valid config with all the parts should parse
|
||||
second_config_os << config_set_txt << ","
|
||||
<< args_txt
|
||||
<< dhcp6_cfg_txt
|
||||
<< subnet1
|
||||
<< subnet_footer
|
||||
<< option_def
|
||||
<< option_data
|
||||
<< control_socket_header
|
||||
<< " \"trust-anchor\": \"" << ca_dir << "/kea-ca.crt\", \n"
|
||||
<< " \"cert-file\": \"" << ca_dir << "/kea-server.crt\", \n"
|
||||
<< " \"key-file\": \"" << ca_dir << "/kea-server.key\", \n"
|
||||
<< control_socket_footer
|
||||
<< logger_txt
|
||||
<< "}\n" // close dhcp6
|
||||
<< "}}";
|
||||
|
||||
// Send the config-set command.
|
||||
sendHttpCommand(second_config_os.str(), response);
|
||||
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener());
|
||||
EXPECT_EQ(listener, HttpCommandMgr::instance().getHttpListener().get());
|
||||
ASSERT_FALSE(HttpCommandMgr::instance().getHttpListener()->getTlsContext());
|
||||
|
||||
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();
|
||||
EXPECT_EQ(1, subnets->size());
|
||||
|
||||
// Clean up after the test.
|
||||
CfgMgr::instance().clear();
|
||||
}
|
||||
|
||||
// Verify that the "config-set" command will reuse listener
|
||||
TEST_F(HttpsCtrlChannelDhcpv6Test, ignoreHttpsToHttpSwitch) {
|
||||
createHttpChannelServer();
|
||||
|
||||
// Define strings to permutate the config arguments
|
||||
// (Note the line feeds makes errors easy to find)
|
||||
string ca_dir(string(TEST_CA_DIR));
|
||||
string config_set_txt = "{ \"command\": \"config-set\" \n";
|
||||
string args_txt = " \"arguments\": { \n";
|
||||
string dhcp6_cfg_txt =
|
||||
" \"Dhcp6\": { \n"
|
||||
" \"interfaces-config\": { \n"
|
||||
" \"interfaces\": [\"*\"] \n"
|
||||
" }, \n"
|
||||
" \"preferred-lifetime\": 3000, \n"
|
||||
" \"valid-lifetime\": 4000, \n"
|
||||
" \"renew-timer\": 1000, \n"
|
||||
" \"rebind-timer\": 2000, \n"
|
||||
" \"lease-database\": { \n"
|
||||
" \"type\": \"memfile\", \n"
|
||||
" \"persist\":false, \n"
|
||||
" \"lfc-interval\": 0 \n"
|
||||
" }, \n"
|
||||
" \"expired-leases-processing\": { \n"
|
||||
" \"reclaim-timer-wait-time\": 0, \n"
|
||||
" \"hold-reclaimed-time\": 0, \n"
|
||||
" \"flush-reclaimed-timer-wait-time\": 0 \n"
|
||||
" },"
|
||||
" \"subnet6\": [ \n";
|
||||
string subnet1 =
|
||||
" {\"subnet\": \"3002::/64\", \"id\": 1, \n"
|
||||
" \"pools\": [{ \"pool\": \"3002::100-3002::200\" }]}\n";
|
||||
string subnet_footer =
|
||||
" ] \n";
|
||||
string option_def =
|
||||
" ,\"option-def\": [\n"
|
||||
" {\n"
|
||||
" \"name\": \"foo\",\n"
|
||||
" \"code\": 163,\n"
|
||||
" \"type\": \"uint32\",\n"
|
||||
" \"array\": false,\n"
|
||||
" \"record-types\": \"\",\n"
|
||||
" \"space\": \"dhcp6\",\n"
|
||||
" \"encapsulate\": \"\"\n"
|
||||
" }\n"
|
||||
"]\n";
|
||||
string option_data =
|
||||
" ,\"option-data\": [\n"
|
||||
" {\n"
|
||||
" \"name\": \"foo\",\n"
|
||||
" \"code\": 163,\n"
|
||||
" \"space\": \"dhcp6\",\n"
|
||||
" \"csv-format\": true,\n"
|
||||
" \"data\": \"12345\"\n"
|
||||
" }\n"
|
||||
"]\n";
|
||||
string control_socket_header =
|
||||
" ,\"control-socket\": { \n";
|
||||
string control_socket_footer =
|
||||
" \"socket-type\": \"http\", \n"
|
||||
" \"socket-address\": \"::1\", \n"
|
||||
" \"socket-port\": 18126 \n"
|
||||
" } \n";
|
||||
string logger_txt =
|
||||
" ,\"loggers\": [ { \n"
|
||||
" \"name\": \"kea\", \n"
|
||||
" \"severity\": \"FATAL\", \n"
|
||||
" \"output-options\": [{ \n"
|
||||
" \"output\": \"/dev/null\", \n"
|
||||
" \"maxsize\": 0"
|
||||
" }] \n"
|
||||
" }] \n";
|
||||
|
||||
std::ostringstream os;
|
||||
|
||||
// Create a valid config with all the parts should parse
|
||||
os << config_set_txt << ","
|
||||
<< args_txt
|
||||
<< dhcp6_cfg_txt
|
||||
<< subnet1
|
||||
<< subnet_footer
|
||||
<< option_def
|
||||
<< option_data
|
||||
<< control_socket_header
|
||||
<< " \"trust-anchor\": \"" << ca_dir << "/kea-ca.crt\", \n"
|
||||
<< " \"cert-file\": \"" << ca_dir << "/kea-server.crt\", \n"
|
||||
<< " \"key-file\": \"" << ca_dir << "/kea-server.key\", \n"
|
||||
<< control_socket_footer
|
||||
<< logger_txt
|
||||
<< "}\n" // close dhcp6
|
||||
<< "}}";
|
||||
|
||||
// Send the config-set command
|
||||
std::string response;
|
||||
sendHttpCommand(os.str(), response);
|
||||
// Verify the configuration was successful. The config contains random
|
||||
// file paths (CA directory), 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 =
|
||||
CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getAll();
|
||||
EXPECT_EQ(1, subnets->size());
|
||||
|
||||
OptionDefinitionPtr def =
|
||||
LibDHCP::getRuntimeOptionDef(DHCP6_OPTION_SPACE, 163);
|
||||
ASSERT_TRUE(def);
|
||||
|
||||
// Verify the HTTP control channel socket exists.
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener());
|
||||
auto const listener = HttpCommandMgr::instance().getHttpListener().get();
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener()->getTlsContext());
|
||||
// The TLS settings have not changed
|
||||
auto const context = HttpCommandMgr::instance().getHttpListener()->getTlsContext().get();
|
||||
|
||||
std::ostringstream second_config_os;
|
||||
|
||||
// Create a valid config with all the parts should parse
|
||||
second_config_os << config_set_txt << ","
|
||||
<< args_txt
|
||||
<< dhcp6_cfg_txt
|
||||
<< subnet1
|
||||
<< subnet_footer
|
||||
<< option_def
|
||||
<< option_data
|
||||
<< control_socket_header
|
||||
<< control_socket_footer
|
||||
<< logger_txt
|
||||
<< "}\n" // close dhcp6
|
||||
<< "}}";
|
||||
|
||||
// Send the config-set command.
|
||||
sendHttpCommand(second_config_os.str(), response);
|
||||
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener());
|
||||
EXPECT_EQ(listener, HttpCommandMgr::instance().getHttpListener().get());
|
||||
ASSERT_TRUE(HttpCommandMgr::instance().getHttpListener()->getTlsContext());
|
||||
EXPECT_EQ(context, HttpCommandMgr::instance().getHttpListener()->getTlsContext().get());
|
||||
|
||||
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();
|
||||
EXPECT_EQ(1, subnets->size());
|
||||
|
||||
// Clean up after the test.
|
||||
CfgMgr::instance().clear();
|
||||
}
|
||||
|
||||
} // End of anonymous namespace
|
||||
|
@@ -34,7 +34,8 @@ extern const isc::log::MessageID COMMAND_SOCKET_WRITE_FAIL = "COMMAND_SOCKET_WRI
|
||||
extern const isc::log::MessageID COMMAND_WATCH_SOCKET_CLEAR_ERROR = "COMMAND_WATCH_SOCKET_CLEAR_ERROR";
|
||||
extern const isc::log::MessageID COMMAND_WATCH_SOCKET_CLOSE_ERROR = "COMMAND_WATCH_SOCKET_CLOSE_ERROR";
|
||||
extern const isc::log::MessageID COMMAND_WATCH_SOCKET_MARK_READY_ERROR = "COMMAND_WATCH_SOCKET_MARK_READY_ERROR";
|
||||
extern const isc::log::MessageID HTTP_COMMAND_MGR_IGNORED_TLS_SETUP_CHANGES = "HTTP_COMMAND_MGR_IGNORED_TLS_SETUP_CHANGES";
|
||||
extern const isc::log::MessageID HTTP_COMMAND_MGR_HTTPS_SERVICE_REUSED = "HTTP_COMMAND_MGR_HTTPS_SERVICE_REUSED";
|
||||
extern const isc::log::MessageID HTTP_COMMAND_MGR_HTTP_SERVICE_REUSED = "HTTP_COMMAND_MGR_HTTP_SERVICE_REUSED";
|
||||
extern const isc::log::MessageID HTTP_COMMAND_MGR_SERVICE_STARTED = "HTTP_COMMAND_MGR_SERVICE_STARTED";
|
||||
extern const isc::log::MessageID HTTP_COMMAND_MGR_SERVICE_STOPPING = "HTTP_COMMAND_MGR_SERVICE_STOPPING";
|
||||
extern const isc::log::MessageID HTTP_COMMAND_MGR_SERVICE_STOPPING_ALL = "HTTP_COMMAND_MGR_SERVICE_STOPPING_ALL";
|
||||
@@ -73,7 +74,8 @@ const char* values[] = {
|
||||
"COMMAND_WATCH_SOCKET_CLEAR_ERROR", "watch socket failed to clear: %1",
|
||||
"COMMAND_WATCH_SOCKET_CLOSE_ERROR", "watch socket failed to close: %1",
|
||||
"COMMAND_WATCH_SOCKET_MARK_READY_ERROR", "watch socket failed to mark ready: %1",
|
||||
"HTTP_COMMAND_MGR_IGNORED_TLS_SETUP_CHANGES", "ignore a change in TLS setup of the http control socket",
|
||||
"HTTP_COMMAND_MGR_HTTPS_SERVICE_REUSED", "reused HTTPS service bound to address %1:%2",
|
||||
"HTTP_COMMAND_MGR_HTTP_SERVICE_REUSED", "reused HTTP service bound to address %1:%2",
|
||||
"HTTP_COMMAND_MGR_SERVICE_STARTED", "started %1 service bound to address %2 port %3",
|
||||
"HTTP_COMMAND_MGR_SERVICE_STOPPING", "Server is stopping %1 service %2",
|
||||
"HTTP_COMMAND_MGR_SERVICE_STOPPING_ALL", "stopping %1 service %2",
|
||||
|
@@ -35,7 +35,8 @@ extern const isc::log::MessageID COMMAND_SOCKET_WRITE_FAIL;
|
||||
extern const isc::log::MessageID COMMAND_WATCH_SOCKET_CLEAR_ERROR;
|
||||
extern const isc::log::MessageID COMMAND_WATCH_SOCKET_CLOSE_ERROR;
|
||||
extern const isc::log::MessageID COMMAND_WATCH_SOCKET_MARK_READY_ERROR;
|
||||
extern const isc::log::MessageID HTTP_COMMAND_MGR_IGNORED_TLS_SETUP_CHANGES;
|
||||
extern const isc::log::MessageID HTTP_COMMAND_MGR_HTTPS_SERVICE_REUSED;
|
||||
extern const isc::log::MessageID HTTP_COMMAND_MGR_HTTP_SERVICE_REUSED;
|
||||
extern const isc::log::MessageID HTTP_COMMAND_MGR_SERVICE_STARTED;
|
||||
extern const isc::log::MessageID HTTP_COMMAND_MGR_SERVICE_STOPPING;
|
||||
extern const isc::log::MessageID HTTP_COMMAND_MGR_SERVICE_STOPPING_ALL;
|
||||
|
@@ -153,11 +153,14 @@ ready status after scheduling asynchronous send. This is programmatic error
|
||||
that should be reported. The command manager may or may not continue
|
||||
to operate correctly.
|
||||
|
||||
% HTTP_COMMAND_MGR_IGNORED_TLS_SETUP_CHANGES ignore a change in TLS setup of the http control socket
|
||||
The warning message is issued when the HTTP/HTTPS control socket was
|
||||
reconfigured with a different TLS setup but keeping the address and port.
|
||||
These changes are ignored because they can't be applied without opening a new
|
||||
socket which will conflict with the existing one.
|
||||
% HTTP_COMMAND_MGR_HTTPS_SERVICE_REUSED reused HTTPS service bound to address %1:%2
|
||||
This informational message indicates that the server has reused existing
|
||||
HTTPS service on the specified address and port. Note that any change in
|
||||
the TLS setup was ignored.
|
||||
|
||||
% HTTP_COMMAND_MGR_HTTP_SERVICE_REUSED reused HTTP service bound to address %1:%2
|
||||
This informational message indicates that the server has reused existing
|
||||
HTTP service on the specified address and port.
|
||||
|
||||
% HTTP_COMMAND_MGR_SERVICE_STARTED started %1 service bound to address %2 port %3
|
||||
This informational message indicates that the server has started
|
||||
|
@@ -127,15 +127,37 @@ HttpCommandMgrImpl::openCommandSocket(const isc::data::ConstElementPtr config) {
|
||||
// Search for the specific connection and reuse the existing one if found.
|
||||
auto it = sockets_.find(std::make_pair(server_address, server_port));
|
||||
if (it != sockets_.end()) {
|
||||
if ((cmd_config->getTrustAnchor() != it->second->config_->getTrustAnchor()) ||
|
||||
(cmd_config->getCertFile() != it->second->config_->getCertFile()) ||
|
||||
(cmd_config->getKeyFile() != it->second->config_->getKeyFile()) ||
|
||||
(cmd_config->getCertRequired() != it->second->config_->getCertRequired())) {
|
||||
LOG_WARN(command_logger, HTTP_COMMAND_MGR_IGNORED_TLS_SETUP_CHANGES);
|
||||
// Overwrite the authentication setup and the emulation flag
|
||||
// in the response creator config.
|
||||
it->second->config_->setAuthConfig(cmd_config->getAuthConfig());
|
||||
it->second->config_->setEmulateAgentResponse(cmd_config->getEmulateAgentResponse());
|
||||
auto listener = it->second->listener_;
|
||||
if (listener) {
|
||||
// Reconfig keeping the same address and port.
|
||||
if (listener->getTlsContext()) {
|
||||
if (cmd_config->getTrustAnchor().empty()) {
|
||||
// Can not switch from HTTPS to HTTP
|
||||
LOG_INFO(command_logger, HTTP_COMMAND_MGR_HTTPS_SERVICE_REUSED)
|
||||
.arg(server_address.toText())
|
||||
.arg(server_port);
|
||||
} else {
|
||||
// Apply TLS settings each time.
|
||||
TlsContextPtr tls_context;
|
||||
TlsContext::configure(tls_context,
|
||||
TlsRole::SERVER,
|
||||
cmd_config->getTrustAnchor(),
|
||||
cmd_config->getCertFile(),
|
||||
cmd_config->getKeyFile(),
|
||||
cmd_config->getCertRequired());
|
||||
// Overwrite the authentication setup, the http headers and the emulation flag
|
||||
// in the response creator config.
|
||||
it->second->config_->setAuthConfig(cmd_config->getAuthConfig());
|
||||
it->second->config_->setHttpHeaders(cmd_config->getHttpHeaders());
|
||||
it->second->config_->setEmulateAgentResponse(cmd_config->getEmulateAgentResponse());
|
||||
io_service_->post([listener, tls_context]() { listener->setTlsContext(tls_context); });
|
||||
}
|
||||
} else if (!cmd_config->getTrustAnchor().empty()) {
|
||||
// Can not switch from HTTP to HTTPS
|
||||
LOG_INFO(command_logger, HTTP_COMMAND_MGR_HTTP_SERVICE_REUSED)
|
||||
.arg(server_address.toText())
|
||||
.arg(server_port);
|
||||
}
|
||||
}
|
||||
// If the connection can be reused, mark it as usable.
|
||||
it->second->usable_ = true;
|
||||
|
@@ -47,6 +47,11 @@ HttpListener::getTlsContext() const {
|
||||
return (impl_->getTlsContext());
|
||||
}
|
||||
|
||||
void
|
||||
HttpListener::setTlsContext(const TlsContextPtr& context) {
|
||||
impl_->setTlsContext(context);
|
||||
}
|
||||
|
||||
int
|
||||
HttpListener::getNative() const {
|
||||
return (impl_->getNative());
|
||||
|
@@ -118,6 +118,9 @@ public:
|
||||
/// @brief Returns reference to the current TLS context.
|
||||
const asiolink::TlsContextPtr& getTlsContext() const;
|
||||
|
||||
/// @brief Sets reference of the current TLS context.
|
||||
void setTlsContext(const asiolink::TlsContextPtr& context);
|
||||
|
||||
/// @brief file descriptor of the underlying acceptor socket.
|
||||
int getNative() const;
|
||||
|
||||
|
@@ -75,6 +75,11 @@ HttpListenerImpl::getTlsContext() const {
|
||||
return (tls_context_);
|
||||
}
|
||||
|
||||
void
|
||||
HttpListenerImpl::setTlsContext(const TlsContextPtr& context) {
|
||||
tls_context_ = context;
|
||||
}
|
||||
|
||||
int
|
||||
HttpListenerImpl::getNative() const {
|
||||
return (acceptor_ ? acceptor_->getNative() : -1);
|
||||
|
@@ -63,6 +63,9 @@ public:
|
||||
/// @brief Returns reference to the current TLS context.
|
||||
const asiolink::TlsContextPtr& getTlsContext() const;
|
||||
|
||||
/// @brief Sets reference of the current TLS context.
|
||||
void setTlsContext(const asiolink::TlsContextPtr& context);
|
||||
|
||||
/// @brief file descriptor of the underlying acceptor socket.
|
||||
int getNative() const;
|
||||
|
||||
|
Reference in New Issue
Block a user