From: Francis Dupont Date: Mon, 13 Jul 2020 07:31:02 +0000 (+0200) Subject: [#1304] Added CA test X-Git-Tag: Kea-1.9.0~146 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=59159be343dca945b832742ab3940bb98bb26510;p=thirdparty%2Fkea.git [#1304] Added CA test --- diff --git a/src/bin/agent/ca_response_creator.cc b/src/bin/agent/ca_response_creator.cc index 5995ee5fc1..c102157f21 100644 --- a/src/bin/agent/ca_response_creator.cc +++ b/src/bin/agent/ca_response_creator.cc @@ -82,10 +82,13 @@ createDynamicHttpResponse(const ConstHttpRequestPtr& request) { ctx = cfgmgr->getCtrlAgentCfgContext(); if (ctx) { const BasicHttpAuthConfig& auth = ctx->getBasicAuthConfig(); - http_response = - checkBasicHttpAuth(*this, request, - auth.getCredentialMap(), - ctx->getBasicAuthRealm()); + const BasicHttpAuthMap& auth_map = auth.getCredentialMap(); + // Check authentication when required. + if (!auth_map.empty()) { + http_response = + checkBasicHttpAuth(*this, request, auth_map, + ctx->getBasicAuthRealm()); + } } } } diff --git a/src/bin/agent/tests/ca_response_creator_unittests.cc b/src/bin/agent/tests/ca_response_creator_unittests.cc index 2af027f964..35028cdb4a 100644 --- a/src/bin/agent/tests/ca_response_creator_unittests.cc +++ b/src/bin/agent/tests/ca_response_creator_unittests.cc @@ -5,26 +5,31 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #include +#include +#include #include #include #include #include #include #include +#include #include #include #include +using namespace isc; using namespace isc::agent; using namespace isc::config; using namespace isc::data; using namespace isc::http; +using namespace isc::process; namespace ph = std::placeholders; namespace { /// @brief Test fixture class for @ref CtrlAgentResponseCreator. -class CtrlAgentResponseCreatorTest : public ::testing::Test { +class CtrlAgentResponseCreatorTest : public DControllerTest { public: /// @brief Constructor. @@ -33,7 +38,8 @@ public: /// create "empty" request. It also removes registered commands from the /// command manager. CtrlAgentResponseCreatorTest() - : response_creator_(), + : DControllerTest(CtrlAgentController::instance), + response_creator_(), request_(response_creator_.createNewHttpRequest()) { // Deregisters commands. CtrlAgentCommandMgr::instance().deregisterAll(); @@ -47,6 +53,13 @@ public: ADD_FAILURE() << "CtrlAgentResponseCreator::createNewHttpRequest" " returns NULL!"; } + // Initialize process and cfgmgr. + try { + initProcess(); + static_cast(getCtrlAgentCfgContext()); + } catch (const std::exception& ex) { + ADD_FAILURE() << "Initialization failed: " << ex.what(); + } } /// @brief Destructor. @@ -112,6 +125,24 @@ public: return (createAnswer(CONTROL_RESULT_SUCCESS, arguments)); } + /// @brief Returns a pointer to the configuration context. + CtrlAgentCfgContextPtr getCtrlAgentCfgContext() { + CtrlAgentProcessPtr process = + boost::dynamic_pointer_cast(getProcess()); + if (!process) { + isc_throw(Unexpected, "no process"); + } + CtrlAgentCfgMgrPtr cfgmgr = process->getCtrlAgentCfgMgr(); + if (!cfgmgr) { + isc_throw(Unexpected, "no cfgmgr"); + } + CtrlAgentCfgContextPtr ctx = cfgmgr->getCtrlAgentCfgContext(); + if (!ctx) { + isc_throw(Unexpected, "no context"); + } + return (ctx); + } + /// @brief Instance of the response creator. CtrlAgentResponseCreator response_creator_; @@ -120,7 +151,6 @@ public: /// The context belonging to this request may be modified by the unit /// tests to verify various scenarios of response creation. HttpRequestPtr request_; - }; // This test verifies that the created "empty" request has valid type. @@ -204,7 +234,80 @@ TEST_F(CtrlAgentResponseCreatorTest, createDynamicHttpResponseInvalidType) { // Response must contain Internal Server Error status code. EXPECT_TRUE(response_json->toString().find("HTTP/1.1 500 Internal Server Error") != std::string::npos); +} + +// This test verifies that Unauthorized is returned when authentication is +// required but not provided by request. +TEST_F(CtrlAgentResponseCreatorTest, noAuth) { + setBasicContext(request_); + + // Body: "list-commands" is natively supported by the command manager. + request_->context()->body_ = "{ \"command\": \"list-commands\" }"; + + // All requests must be finalized before they can be processed. + ASSERT_NO_THROW(request_->finalize()); + + // Require authentication. + CtrlAgentCfgContextPtr ctx = getCtrlAgentCfgContext(); + ASSERT_TRUE(ctx); + ctx->setBasicAuthRealm("ISC.ORG"); + BasicHttpAuthConfig& auth = ctx->getBasicAuthConfig(); + auth.add("foo", "bar"); + + HttpResponsePtr response; + ASSERT_NO_THROW(response = response_creator_.createHttpResponse(request_)); + ASSERT_TRUE(response); + // Response must be convertible to HttpResponseJsonPtr. + HttpResponseJsonPtr response_json = boost::dynamic_pointer_cast< + HttpResponseJson>(response); + ASSERT_TRUE(response_json); + + // Response must contain Unauthorized status code. + std::string expected = "HTTP/1.1 401 Unauthorized"; + EXPECT_TRUE(response_json->toString().find(expected) != std::string::npos); + // Reponse should contain WWW-Authenticate header with configured realm. + expected = "WWW-Authenticate: Basic realm=\"ISC.ORG\""; + EXPECT_TRUE(response_json->toString().find(expected) != std::string::npos); +} + +// Test successful server response when the client is authenticated. +TEST_F(CtrlAgentResponseCreatorTest, basicAuth) { + setBasicContext(request_); + + // Body: "list-commands" is natively supported by the command manager. + request_->context()->body_ = "{ \"command\": \"list-commands\" }"; + + // Add basic HTTP authentication header. + const BasicHttpAuth& basic_auth = BasicHttpAuth("foo", "bar"); + const BasicAuthHttpHeaderContext& basic_auth_header = + BasicAuthHttpHeaderContext(basic_auth); + request_->context()->headers_.push_back(basic_auth_header); + + // All requests must be finalized before they can be processed. + ASSERT_NO_THROW(request_->finalize()); + + // Require authentication. + CtrlAgentCfgContextPtr ctx = getCtrlAgentCfgContext(); + ASSERT_TRUE(ctx); + BasicHttpAuthConfig& auth = ctx->getBasicAuthConfig(); + auth.add("foo", "bar"); + + HttpResponsePtr response; + ASSERT_NO_THROW(response = response_creator_.createHttpResponse(request_)); + ASSERT_TRUE(response); + + // Response must be convertible to HttpResponseJsonPtr. + HttpResponseJsonPtr response_json = boost::dynamic_pointer_cast< + HttpResponseJson>(response); + ASSERT_TRUE(response_json); + + // Response must be successful. + EXPECT_TRUE(response_json->toString().find("HTTP/1.1 200 OK") != + std::string::npos); + // Response must contain JSON body with "result" of 0. + EXPECT_TRUE(response_json->toString().find("\"result\": 0") != + std::string::npos); } }