Skip to content

Commit 1334b83

Browse files
author
Razvan Becheriu
committed
[#3694] apply tls settings on reload
1 parent 6fcbddc commit 1334b83

18 files changed

+1932
-84
lines changed

src/bin/agent/ca_messages.mes

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ address and port over a TLS channel.
5555

5656
% CTRL_AGENT_HTTP_SERVICE_REUSED reused HTTP service bound to address %1:%2
5757
This informational message indicates that the server has reused existing
58-
HTTPS service on the specified address and port.
58+
HTTP service on the specified address and port.
5959

6060
% CTRL_AGENT_HTTP_SERVICE_STARTED HTTP service bound to address %1:%2
6161
This informational message indicates that the server has started HTTP service

src/bin/agent/ca_process.cc

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,14 +139,31 @@ CtrlAgentProcess::configure(isc::data::ConstElementPtr config_set,
139139
// Search for the specific connection and reuse the existing one if found.
140140
auto it = sockets_.find(std::make_pair(server_address, server_port));
141141
if (it != sockets_.end()) {
142-
auto listener = getHttpListener();
142+
auto listener = it->second->listener_;
143143
if (listener) {
144144
// Reconfig keeping the same address and port.
145145
if (listener->getTlsContext()) {
146-
LOG_INFO(agent_logger, CTRL_AGENT_HTTPS_SERVICE_REUSED)
147-
.arg(server_address.toText())
148-
.arg(server_port);
149-
} else {
146+
if (ctx->getTrustAnchor().empty()) {
147+
// Can not switch from HTTPS to HTTP
148+
LOG_INFO(agent_logger, CTRL_AGENT_HTTPS_SERVICE_REUSED)
149+
.arg(server_address.toText())
150+
.arg(server_port);
151+
} else {
152+
// Apply TLS settings each time.
153+
TlsContextPtr tls_context;
154+
TlsContext::configure(tls_context,
155+
TlsRole::SERVER,
156+
ctx->getTrustAnchor(),
157+
ctx->getCertFile(),
158+
ctx->getKeyFile(),
159+
ctx->getCertRequired());
160+
// Overwrite the authentication setup and the http headers in the response creator config.
161+
it->second->config_->setAuthConfig(ctx->getAuthConfig());
162+
it->second->config_->setHttpHeaders(ctx->getHttpHeaders());
163+
getIOService()->post([listener, tls_context]() { listener->setTlsContext(tls_context); });
164+
}
165+
} else if (!ctx->getTrustAnchor().empty()) {
166+
// Can not switch from HTTP to HTTPS
150167
LOG_INFO(agent_logger, CTRL_AGENT_HTTP_SERVICE_REUSED)
151168
.arg(server_address.toText())
152169
.arg(server_port);

src/bin/agent/tests/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ AM_CPPFLAGS += -DTEST_DATA_BUILDDIR=\"$(abs_top_builddir)/src/bin/agent/tests\"
3030
AM_CPPFLAGS += -DINSTALL_PROG=\"$(abs_top_srcdir)/install-sh\"
3131
AM_CPPFLAGS += -DCFG_EXAMPLES=\"$(abs_top_srcdir)/doc/examples/agent\"
3232
AM_CPPFLAGS += -DSYNTAX_FILE=\"$(abs_srcdir)/../agent_parser.yy\"
33+
AM_CPPFLAGS += -DTEST_CA_DIR=\"$(abs_top_srcdir)/src/lib/asiolink/testutils/ca\"
3334

3435
AM_CXXFLAGS = $(KEA_CXXFLAGS)
3536

src/bin/agent/tests/ca_controller_unittests.cc

Lines changed: 302 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include <unistd.h>
2323

24+
using namespace isc::asiolink;
2425
using namespace isc::asiolink::test;
2526
using namespace isc::agent;
2627
using namespace isc::data;
@@ -402,7 +403,7 @@ TEST_F(CtrlAgentControllerTest, unsuccessfulConfigUpdate) {
402403
// Tests that it is possible to update the configuration in such a way that the
403404
// listener configuration remains the same. The server should continue using the
404405
// listener instance it has been using prior to the reconfiguration.
405-
TEST_F(CtrlAgentControllerTest, noListenerChange) {
406+
TEST_F(CtrlAgentControllerTest, noListenerChangeHttp) {
406407
// This configuration should be used to override the initial configuration.
407408
const char* second_config =
408409
"{"
@@ -420,6 +421,8 @@ TEST_F(CtrlAgentControllerTest, noListenerChange) {
420421
" }"
421422
"}";
422423

424+
const HttpListener* listener_ptr = 0;
425+
423426
// This check callback is called before the shutdown.
424427
auto check_callback = [&] {
425428
CtrlAgentProcessPtr process = getCtrlAgentProcess();
@@ -428,6 +431,8 @@ TEST_F(CtrlAgentControllerTest, noListenerChange) {
428431
// Check that the HTTP listener still exists after reconfiguration.
429432
ConstHttpListenerPtr listener = process->getHttpListener();
430433
ASSERT_TRUE(listener);
434+
ASSERT_EQ(listener_ptr, listener.get());
435+
ASSERT_FALSE(listener->getTlsContext());
431436
EXPECT_TRUE(process->isListening());
432437

433438
EXPECT_EQ("127.0.0.1", listener->getLocalAddress().toText());
@@ -439,6 +444,202 @@ TEST_F(CtrlAgentControllerTest, noListenerChange) {
439444
// Schedule SIGHUP signal to trigger reconfiguration.
440445
TimedSignal sighup(getIOService(), SIGHUP, 200);
441446

447+
IntervalTimer timer(getIOService());
448+
timer.setup([&] {
449+
CtrlAgentProcessPtr process = getCtrlAgentProcess();
450+
ASSERT_TRUE(process);
451+
ConstHttpListenerPtr listener = process->getHttpListener();
452+
ASSERT_TRUE(listener);
453+
listener_ptr = listener.get();
454+
ASSERT_FALSE(listener->getTlsContext());
455+
}, 50, IntervalTimer::ONE_SHOT);
456+
457+
// Start the server.
458+
time_duration elapsed_time;
459+
runWithConfig(valid_agent_config, 500,
460+
static_cast<const TestCallback&>(check_callback),
461+
elapsed_time);
462+
463+
CtrlAgentCfgContextPtr ctx = getCtrlAgentCfgContext();
464+
ASSERT_TRUE(ctx);
465+
466+
// The server should use a correct listener configuration.
467+
EXPECT_EQ("127.0.0.1", ctx->getHttpHost());
468+
EXPECT_EQ(8081, ctx->getHttpPort());
469+
470+
// The forwarding configuration should have been updated.
471+
testUnixSocketInfo("dhcp4", "/second/dhcp4/socket");
472+
testUnixSocketInfo("dhcp6", "/second/dhcp6/socket");
473+
474+
CtrlAgentProcessPtr process = getCtrlAgentProcess();
475+
ASSERT_TRUE(process);
476+
ConstHttpListenerPtr listener = process->getHttpListener();
477+
ASSERT_FALSE(listener);
478+
EXPECT_FALSE(process->isListening());
479+
}
480+
481+
// Tests that it is possible to update the configuration in such a way that the
482+
// listener configuration remains the same. The server should continue using the
483+
// listener instance it has been using prior to the reconfiguration.
484+
TEST_F(CtrlAgentControllerTest, noListenerChangeHttps) {
485+
// This configuration should be used to override the initial configuration.
486+
string ca_dir(string(TEST_CA_DIR));
487+
ostringstream agent_st;
488+
agent_st << "{"
489+
<< " \"http-host\": \"127.0.0.1\","
490+
<< " \"http-port\": 8081,"
491+
<< " \"trust-anchor\": \"" << ca_dir << "/kea-ca.crt\", \n"
492+
<< " \"cert-file\": \"" << ca_dir << "/kea-server.crt\", \n"
493+
<< " \"key-file\": \"" << ca_dir << "/kea-server.key\", \n"
494+
<< " \"control-sockets\": {"
495+
<< " \"dhcp4\": {"
496+
<< " \"socket-type\": \"unix\","
497+
<< " \"socket-name\": \"/first/dhcp4/socket\""
498+
<< " },"
499+
<< " \"dhcp6\": {"
500+
<< " \"socket-type\": \"unix\","
501+
<< " \"socket-name\": \"/first/dhcp6/socket\""
502+
<< " }"
503+
<< " }"
504+
<< "}";
505+
506+
ostringstream second_config_st;
507+
second_config_st << "{"
508+
<< " \"http-host\": \"127.0.0.1\","
509+
<< " \"http-port\": 8081,"
510+
<< " \"trust-anchor\": \"" << ca_dir << "/kea-ca.crt\", \n"
511+
<< " \"cert-file\": \"" << ca_dir << "/kea-server.crt\", \n"
512+
<< " \"key-file\": \"" << ca_dir << "/kea-server.key\", \n"
513+
<< " \"control-sockets\": {"
514+
<< " \"dhcp4\": {"
515+
<< " \"socket-type\": \"unix\","
516+
<< " \"socket-name\": \"/second/dhcp4/socket\""
517+
<< " },"
518+
<< " \"dhcp6\": {"
519+
<< " \"socket-type\": \"unix\","
520+
<< " \"socket-name\": \"/second/dhcp6/socket\""
521+
<< " }"
522+
<< " }"
523+
<< "}";
524+
525+
const HttpListener* listener_ptr = 0;
526+
TlsContext* context = 0;
527+
528+
// This check callback is called before the shutdown.
529+
auto check_callback = [&] {
530+
CtrlAgentProcessPtr process = getCtrlAgentProcess();
531+
ASSERT_TRUE(process);
532+
533+
// Check that the HTTP listener still exists after reconfiguration.
534+
ConstHttpListenerPtr listener = process->getHttpListener();
535+
ASSERT_TRUE(listener);
536+
ASSERT_EQ(listener_ptr, listener.get());
537+
ASSERT_TRUE(listener->getTlsContext());
538+
// The TLS settings have been applied
539+
ASSERT_NE(context, listener->getTlsContext().get());
540+
EXPECT_TRUE(process->isListening());
541+
542+
EXPECT_EQ("127.0.0.1", listener->getLocalAddress().toText());
543+
EXPECT_EQ(8081, listener->getLocalPort());
544+
};
545+
546+
// Schedule reconfiguration.
547+
scheduleTimedWrite(second_config_st.str(), 100);
548+
// Schedule SIGHUP signal to trigger reconfiguration.
549+
TimedSignal sighup(getIOService(), SIGHUP, 200);
550+
551+
IntervalTimer timer(getIOService());
552+
timer.setup([&] {
553+
CtrlAgentProcessPtr process = getCtrlAgentProcess();
554+
ASSERT_TRUE(process);
555+
ConstHttpListenerPtr listener = process->getHttpListener();
556+
ASSERT_TRUE(listener);
557+
listener_ptr = listener.get();
558+
ASSERT_TRUE(listener->getTlsContext());
559+
context = listener->getTlsContext().get();
560+
}, 50, IntervalTimer::ONE_SHOT);
561+
562+
// Start the server.
563+
time_duration elapsed_time;
564+
runWithConfig(agent_st.str(), 500,
565+
static_cast<const TestCallback&>(check_callback),
566+
elapsed_time);
567+
568+
CtrlAgentCfgContextPtr ctx = getCtrlAgentCfgContext();
569+
ASSERT_TRUE(ctx);
570+
571+
// The server should use a correct listener configuration.
572+
EXPECT_EQ("127.0.0.1", ctx->getHttpHost());
573+
EXPECT_EQ(8081, ctx->getHttpPort());
574+
575+
// The forwarding configuration should have been updated.
576+
testUnixSocketInfo("dhcp4", "/second/dhcp4/socket");
577+
testUnixSocketInfo("dhcp6", "/second/dhcp6/socket");
578+
579+
CtrlAgentProcessPtr process = getCtrlAgentProcess();
580+
ASSERT_TRUE(process);
581+
ConstHttpListenerPtr listener = process->getHttpListener();
582+
ASSERT_FALSE(listener);
583+
EXPECT_FALSE(process->isListening());
584+
}
585+
586+
// Verify that the reload will reuse listener
587+
TEST_F(CtrlAgentControllerTest, ignoreHttpToHttpsSwitch) {
588+
string ca_dir(string(TEST_CA_DIR));
589+
590+
// This configuration should be used to override the initial configuration.
591+
ostringstream second_config_st;
592+
second_config_st << "{"
593+
<< " \"http-host\": \"127.0.0.1\","
594+
<< " \"http-port\": 8081,"
595+
<< " \"trust-anchor\": \"" << ca_dir << "/kea-ca.crt\", \n"
596+
<< " \"cert-file\": \"" << ca_dir << "/kea-server.crt\", \n"
597+
<< " \"key-file\": \"" << ca_dir << "/kea-server.key\", \n"
598+
<< " \"control-sockets\": {"
599+
<< " \"dhcp4\": {"
600+
<< " \"socket-type\": \"unix\","
601+
<< " \"socket-name\": \"/second/dhcp4/socket\""
602+
<< " },"
603+
<< " \"dhcp6\": {"
604+
<< " \"socket-type\": \"unix\","
605+
<< " \"socket-name\": \"/second/dhcp6/socket\""
606+
<< " }"
607+
<< " }"
608+
<< "}";
609+
610+
const HttpListener* listener_ptr = 0;
611+
612+
// This check callback is called before the shutdown.
613+
auto check_callback = [&] {
614+
CtrlAgentProcessPtr process = getCtrlAgentProcess();
615+
ASSERT_TRUE(process);
616+
617+
// Check that the HTTP listener still exists after reconfiguration.
618+
ConstHttpListenerPtr listener = process->getHttpListener();
619+
ASSERT_TRUE(listener);
620+
ASSERT_EQ(listener_ptr, listener.get());
621+
ASSERT_FALSE(listener->getTlsContext());
622+
EXPECT_TRUE(process->isListening());
623+
624+
EXPECT_EQ("127.0.0.1", listener->getLocalAddress().toText());
625+
EXPECT_EQ(8081, listener->getLocalPort());
626+
};
627+
628+
// Schedule reconfiguration.
629+
scheduleTimedWrite(second_config_st.str(), 100);
630+
// Schedule SIGHUP signal to trigger reconfiguration.
631+
TimedSignal sighup(getIOService(), SIGHUP, 200);
632+
633+
IntervalTimer timer(getIOService());
634+
timer.setup([&] {
635+
CtrlAgentProcessPtr process = getCtrlAgentProcess();
636+
ASSERT_TRUE(process);
637+
ConstHttpListenerPtr listener = process->getHttpListener();
638+
ASSERT_TRUE(listener);
639+
listener_ptr = listener.get();
640+
ASSERT_FALSE(listener->getTlsContext());
641+
}, 50, IntervalTimer::ONE_SHOT);
642+
442643
// Start the server.
443644
time_duration elapsed_time;
444645
runWithConfig(valid_agent_config, 500,
@@ -463,6 +664,106 @@ TEST_F(CtrlAgentControllerTest, noListenerChange) {
463664
EXPECT_FALSE(process->isListening());
464665
}
465666

667+
// Verify that the reload will reuse listener
668+
TEST_F(CtrlAgentControllerTest, ignoreHttpsToHttpSwitch) {
669+
string ca_dir(string(TEST_CA_DIR));
670+
ostringstream agent_st;
671+
agent_st << "{"
672+
<< " \"http-host\": \"127.0.0.1\","
673+
<< " \"http-port\": 8081,"
674+
<< " \"trust-anchor\": \"" << ca_dir << "/kea-ca.crt\", \n"
675+
<< " \"cert-file\": \"" << ca_dir << "/kea-server.crt\", \n"
676+
<< " \"key-file\": \"" << ca_dir << "/kea-server.key\", \n"
677+
<< " \"control-sockets\": {"
678+
<< " \"dhcp4\": {"
679+
<< " \"socket-type\": \"unix\","
680+
<< " \"socket-name\": \"/first/dhcp4/socket\""
681+
<< " },"
682+
<< " \"dhcp6\": {"
683+
<< " \"socket-type\": \"unix\","
684+
<< " \"socket-name\": \"/first/dhcp6/socket\""
685+
<< " }"
686+
<< " }"
687+
<< "}";
688+
689+
// This configuration should be used to override the initial configuration.
690+
ostringstream second_config_st;
691+
second_config_st << "{"
692+
<< " \"http-host\": \"127.0.0.1\","
693+
<< " \"http-port\": 8081,"
694+
<< " \"control-sockets\": {"
695+
<< " \"dhcp4\": {"
696+
<< " \"socket-type\": \"unix\","
697+
<< " \"socket-name\": \"/second/dhcp4/socket\""
698+
<< " },"
699+
<< " \"dhcp6\": {"
700+
<< " \"socket-type\": \"unix\","
701+
<< " \"socket-name\": \"/second/dhcp6/socket\""
702+
<< " }"
703+
<< " }"
704+
<< "}";
705+
706+
const HttpListener* listener_ptr = 0;
707+
TlsContext* context = 0;
708+
709+
// This check callback is called before the shutdown.
710+
auto check_callback = [&] {
711+
CtrlAgentProcessPtr process = getCtrlAgentProcess();
712+
ASSERT_TRUE(process);
713+
714+
// Check that the HTTP listener still exists after reconfiguration.
715+
ConstHttpListenerPtr listener = process->getHttpListener();
716+
ASSERT_TRUE(listener);
717+
ASSERT_EQ(listener_ptr, listener.get());
718+
ASSERT_TRUE(listener->getTlsContext());
719+
// The TLS settings have not changed
720+
ASSERT_EQ(context, listener->getTlsContext().get());
721+
EXPECT_TRUE(process->isListening());
722+
723+
EXPECT_EQ("127.0.0.1", listener->getLocalAddress().toText());
724+
EXPECT_EQ(8081, listener->getLocalPort());
725+
};
726+
727+
// Schedule reconfiguration.
728+
scheduleTimedWrite(second_config_st.str(), 100);
729+
// Schedule SIGHUP signal to trigger reconfiguration.
730+
TimedSignal sighup(getIOService(), SIGHUP, 200);
731+
732+
IntervalTimer timer(getIOService());
733+
timer.setup([&] {
734+
CtrlAgentProcessPtr process = getCtrlAgentProcess();
735+
ASSERT_TRUE(process);
736+
ConstHttpListenerPtr listener = process->getHttpListener();
737+
ASSERT_TRUE(listener);
738+
listener_ptr = listener.get();
739+
ASSERT_TRUE(listener->getTlsContext());
740+
context = listener->getTlsContext().get();
741+
}, 50, IntervalTimer::ONE_SHOT);
742+
743+
// Start the server.
744+
time_duration elapsed_time;
745+
runWithConfig(agent_st.str(), 500,
746+
static_cast<const TestCallback&>(check_callback),
747+
elapsed_time);
748+
749+
CtrlAgentCfgContextPtr ctx = getCtrlAgentCfgContext();
750+
ASSERT_TRUE(ctx);
751+
752+
// The server should use a correct listener configuration.
753+
EXPECT_EQ("127.0.0.1", ctx->getHttpHost());
754+
EXPECT_EQ(8081, ctx->getHttpPort());
755+
756+
// The forwarding configuration should have been updated.
757+
testUnixSocketInfo("dhcp4", "/second/dhcp4/socket");
758+
testUnixSocketInfo("dhcp6", "/second/dhcp6/socket");
759+
760+
CtrlAgentProcessPtr process = getCtrlAgentProcess();
761+
ASSERT_TRUE(process);
762+
ConstHttpListenerPtr listener = process->getHttpListener();
763+
ASSERT_FALSE(listener);
764+
EXPECT_FALSE(process->isListening());
765+
}
766+
466767
// Tests that registerCommands actually registers anything.
467768
TEST_F(CtrlAgentControllerTest, registeredCommands) {
468769
ASSERT_NO_THROW(initProcess());

0 commit comments

Comments
 (0)