mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-09-02 06:55:16 +00:00
[#1304] Added config/parse
This commit is contained in:
@@ -10,6 +10,17 @@
|
|||||||
|
|
||||||
"http-host": "127.0.0.1",
|
"http-host": "127.0.0.1",
|
||||||
"http-port": 8000,
|
"http-port": 8000,
|
||||||
|
"basic-authentication-realm": "kea-control-agent",
|
||||||
|
|
||||||
|
// In basoc HTTP authentication
|
||||||
|
"basic-authentications":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"comment": "admin is authorized",
|
||||||
|
"user": "admin",
|
||||||
|
"password": "1234"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
// In control socket
|
// In control socket
|
||||||
"control-sockets":
|
"control-sockets":
|
||||||
|
@@ -11,6 +11,28 @@
|
|||||||
// Another mandatory parameter is the HTTP port.
|
// Another mandatory parameter is the HTTP port.
|
||||||
"http-port": 8000,
|
"http-port": 8000,
|
||||||
|
|
||||||
|
// An optional parameter is the basic HTTP authentication realm.
|
||||||
|
// Its default is "kea-control-agent".
|
||||||
|
"basic-authentication-realm": "kea-control-agent",
|
||||||
|
|
||||||
|
// This list specifies the user ids and passwords to use for
|
||||||
|
// basic HTTP authentication. If empty or not present any client
|
||||||
|
// is authorized.
|
||||||
|
"basic-authentications":
|
||||||
|
[
|
||||||
|
// This specifies an authorized client.
|
||||||
|
{
|
||||||
|
"comment": "admin is authorized",
|
||||||
|
|
||||||
|
// The user id must not be empty or contain the ':' character.
|
||||||
|
// It is a mandatory parameter.
|
||||||
|
"user": "admin",
|
||||||
|
|
||||||
|
// If password is not specified an empty password is used.
|
||||||
|
"password": "1234"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
// This map specifies where control channel of each server is configured
|
// This map specifies where control channel of each server is configured
|
||||||
// to listen on. See 'control-socket' object in the respective
|
// to listen on. See 'control-socket' object in the respective
|
||||||
// servers. At this time the only supported socket type is "unix".
|
// servers. At this time the only supported socket type is "unix".
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (C) 2016-2019 Internet Systems Consortium, Inc. ("ISC")
|
// Copyright (C) 2016-2020 Internet Systems Consortium, Inc. ("ISC")
|
||||||
//
|
//
|
||||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
@@ -21,7 +21,7 @@ namespace isc {
|
|||||||
namespace agent {
|
namespace agent {
|
||||||
|
|
||||||
CtrlAgentCfgContext::CtrlAgentCfgContext()
|
CtrlAgentCfgContext::CtrlAgentCfgContext()
|
||||||
:http_host_(""), http_port_(0) {
|
: http_host_(""), http_port_(0), basic_auth_realm_("") {
|
||||||
}
|
}
|
||||||
|
|
||||||
CtrlAgentCfgContext::CtrlAgentCfgContext(const CtrlAgentCfgContext& orig)
|
CtrlAgentCfgContext::CtrlAgentCfgContext(const CtrlAgentCfgContext& orig)
|
||||||
@@ -50,6 +50,8 @@ CtrlAgentCfgMgr::getConfigSummary(const uint32_t /*selection*/) {
|
|||||||
// Then print the control-sockets
|
// Then print the control-sockets
|
||||||
s << ctx->getControlSocketInfoSummary();
|
s << ctx->getControlSocketInfoSummary();
|
||||||
|
|
||||||
|
// @todo: add something if authentication is required
|
||||||
|
|
||||||
// Finally, print the hook libraries names
|
// Finally, print the hook libraries names
|
||||||
const isc::hooks::HookLibsCollection libs = ctx->getHooksConfig().get();
|
const isc::hooks::HookLibsCollection libs = ctx->getHooksConfig().get();
|
||||||
s << ", " << libs.size() << " lib(s):";
|
s << ", " << libs.size() << " lib(s):";
|
||||||
@@ -152,6 +154,8 @@ CtrlAgentCfgContext::toElement() const {
|
|||||||
ca->set("http-host", Element::create(http_host_));
|
ca->set("http-host", Element::create(http_host_));
|
||||||
// Set http-port
|
// Set http-port
|
||||||
ca->set("http-port", Element::create(static_cast<int64_t>(http_port_)));
|
ca->set("http-port", Element::create(static_cast<int64_t>(http_port_)));
|
||||||
|
// Set basic-authentication-realm
|
||||||
|
ca->set("basic-authentication-realm", Element::create(basic_auth_realm_));
|
||||||
// Set hooks-libraries
|
// Set hooks-libraries
|
||||||
ca->set("hooks-libraries", hooks_config_.toElement());
|
ca->set("hooks-libraries", hooks_config_.toElement());
|
||||||
// Set control-sockets
|
// Set control-sockets
|
||||||
@@ -161,6 +165,7 @@ CtrlAgentCfgContext::toElement() const {
|
|||||||
control_sockets->set(si->first, socket);
|
control_sockets->set(si->first, socket);
|
||||||
}
|
}
|
||||||
ca->set("control-sockets", control_sockets);
|
ca->set("control-sockets", control_sockets);
|
||||||
|
// @todo: Set authentication.
|
||||||
// Set Control-agent
|
// Set Control-agent
|
||||||
ElementPtr result = Element::createMap();
|
ElementPtr result = Element::createMap();
|
||||||
result->set("Control-agent", ca);
|
result->set("Control-agent", ca);
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (C) 2016-2018 Internet Systems Consortium, Inc. ("ISC")
|
// Copyright (C) 2016-2020 Internet Systems Consortium, Inc. ("ISC")
|
||||||
//
|
//
|
||||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
@@ -98,6 +98,20 @@ public:
|
|||||||
return (http_port_);
|
return (http_port_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief Sets basic-authentication-realm parameter
|
||||||
|
///
|
||||||
|
/// @param real Basic HTTP authentication realm
|
||||||
|
void setBasicAuthRealm(const std::string& realm) {
|
||||||
|
basic_auth_realm_ = realm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Returns basic-authentication-realm parameter
|
||||||
|
///
|
||||||
|
/// @return Basic HTTP authentication realm.
|
||||||
|
std::string getBasicAuthRealm() const {
|
||||||
|
return (basic_auth_realm_);
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief Returns non-const reference to configured hooks libraries.
|
/// @brief Returns non-const reference to configured hooks libraries.
|
||||||
///
|
///
|
||||||
/// @return non-const reference to configured hooks libraries.
|
/// @return non-const reference to configured hooks libraries.
|
||||||
@@ -147,6 +161,9 @@ private:
|
|||||||
/// TCP port the CA should listen on.
|
/// TCP port the CA should listen on.
|
||||||
uint16_t http_port_;
|
uint16_t http_port_;
|
||||||
|
|
||||||
|
/// Basic HTTP authentication realm.
|
||||||
|
std::string basic_auth_realm_;
|
||||||
|
|
||||||
/// @brief Configured hooks libraries.
|
/// @brief Configured hooks libraries.
|
||||||
isc::hooks::HooksConfig hooks_config_;
|
isc::hooks::HooksConfig hooks_config_;
|
||||||
};
|
};
|
||||||
|
@@ -36,8 +36,9 @@ namespace agent {
|
|||||||
///
|
///
|
||||||
/// These are global Control Agent parameters.
|
/// These are global Control Agent parameters.
|
||||||
const SimpleDefaults AgentSimpleParser::AGENT_DEFAULTS = {
|
const SimpleDefaults AgentSimpleParser::AGENT_DEFAULTS = {
|
||||||
{ "http-host", Element::string, "127.0.0.1"},
|
{ "http-host", Element::string, "127.0.0.1" },
|
||||||
{ "http-port", Element::integer, "8000"}
|
{ "http-port", Element::integer, "8000" },
|
||||||
|
{ "basic-authentication-realm", Element::string, "kea-control-agent" }
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief This table defines default values for control sockets.
|
/// @brief This table defines default values for control sockets.
|
||||||
@@ -88,6 +89,8 @@ AgentSimpleParser::parse(const CtrlAgentCfgContextPtr& ctx,
|
|||||||
// Let's get the HTTP parameters first.
|
// Let's get the HTTP parameters first.
|
||||||
ctx->setHttpHost(SimpleParser::getString(config, "http-host"));
|
ctx->setHttpHost(SimpleParser::getString(config, "http-host"));
|
||||||
ctx->setHttpPort(SimpleParser::getIntType<uint16_t>(config, "http-port"));
|
ctx->setHttpPort(SimpleParser::getIntType<uint16_t>(config, "http-port"));
|
||||||
|
ctx->setBasicAuthRealm(SimpleParser::getString(config,
|
||||||
|
"basic-authentication-realm"));
|
||||||
|
|
||||||
// Control sockets are second.
|
// Control sockets are second.
|
||||||
ConstElementPtr ctrl_sockets = config->get("control-sockets");
|
ConstElementPtr ctrl_sockets = config->get("control-sockets");
|
||||||
@@ -98,6 +101,8 @@ AgentSimpleParser::parse(const CtrlAgentCfgContextPtr& ctx,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Basic HTTP authentications are third.
|
||||||
|
|
||||||
// User context can be done at anytime.
|
// User context can be done at anytime.
|
||||||
ConstElementPtr user_context = config->get("user-context");
|
ConstElementPtr user_context = config->get("user-context");
|
||||||
if (user_context) {
|
if (user_context) {
|
||||||
|
@@ -40,6 +40,7 @@ libkea_http_la_SOURCES += response_creator_factory.h
|
|||||||
libkea_http_la_SOURCES += response_json.cc response_json.h
|
libkea_http_la_SOURCES += response_json.cc response_json.h
|
||||||
libkea_http_la_SOURCES += url.cc url.h
|
libkea_http_la_SOURCES += url.cc url.h
|
||||||
libkea_http_la_SOURCES += basic_auth.cc basic_auth.h
|
libkea_http_la_SOURCES += basic_auth.cc basic_auth.h
|
||||||
|
libkea_http_la_SOURCES += basic_auth_config.cc basic_auth_config.h
|
||||||
|
|
||||||
libkea_http_la_CXXFLAGS = $(AM_CXXFLAGS)
|
libkea_http_la_CXXFLAGS = $(AM_CXXFLAGS)
|
||||||
libkea_http_la_CPPFLAGS = $(AM_CPPFLAGS)
|
libkea_http_la_CPPFLAGS = $(AM_CPPFLAGS)
|
||||||
@@ -90,6 +91,8 @@ endif
|
|||||||
# Specify the headers for copying into the installation directory tree.
|
# Specify the headers for copying into the installation directory tree.
|
||||||
libkea_http_includedir = $(pkgincludedir)/http
|
libkea_http_includedir = $(pkgincludedir)/http
|
||||||
libkea_http_include_HEADERS = \
|
libkea_http_include_HEADERS = \
|
||||||
|
basic_auth.h \
|
||||||
|
basic_auth_config.h \
|
||||||
client.h \
|
client.h \
|
||||||
connection.h \
|
connection.h \
|
||||||
connection_pool.h \
|
connection_pool.h \
|
||||||
@@ -112,6 +115,7 @@ libkea_http_include_HEADERS = \
|
|||||||
response.h \
|
response.h \
|
||||||
response_context.h \
|
response_context.h \
|
||||||
response_creator.h \
|
response_creator.h \
|
||||||
|
response_creator_auth.h \
|
||||||
response_creator_factory.h \
|
response_creator_factory.h \
|
||||||
response_json.h \
|
response_json.h \
|
||||||
response_parser.h \
|
response_parser.h \
|
||||||
|
137
src/lib/http/basic_auth_config.cc
Normal file
137
src/lib/http/basic_auth_config.cc
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
// Copyright (C) 2020 Internet Systems Consortium, Inc. ("ISC")
|
||||||
|
//
|
||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <http/basic_auth_config.h>
|
||||||
|
|
||||||
|
using namespace isc;
|
||||||
|
using namespace isc::data;
|
||||||
|
using namespace isc::dhcp;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace isc {
|
||||||
|
namespace http {
|
||||||
|
|
||||||
|
BasicHttpAuthClient::BasicHttpAuthClient(const std::string& user,
|
||||||
|
const std::string& password,
|
||||||
|
const isc::data::ConstElementPtr& user_context)
|
||||||
|
: user_(user), password_(password) {
|
||||||
|
if (user_context) {
|
||||||
|
setContext(user_context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ElementPtr
|
||||||
|
BasicHttpAuthClient::toElement() const {
|
||||||
|
ElementPtr result = Element::createMap();
|
||||||
|
|
||||||
|
// Set user-context
|
||||||
|
contextToElement(result);
|
||||||
|
|
||||||
|
// Set user
|
||||||
|
result->set("user", Element::create(user_));
|
||||||
|
|
||||||
|
// Set password
|
||||||
|
result->set("password", Element::create(password_));
|
||||||
|
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BasicHttpAuthConfig::add(const std::string& user,
|
||||||
|
const std::string& password,
|
||||||
|
const ConstElementPtr& user_context) {
|
||||||
|
BasicHttpAuth basic_auth(user, password);
|
||||||
|
list_.push_back(BasicHttpAuthClient(user, password, user_context));
|
||||||
|
map_[basic_auth.getCredential()] = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BasicHttpAuthConfig::clear() {
|
||||||
|
list_.clear();
|
||||||
|
map_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
ElementPtr
|
||||||
|
BasicHttpAuthConfig::toElement() const {
|
||||||
|
ElementPtr result = Element::createList();
|
||||||
|
|
||||||
|
for (auto client : list_) {
|
||||||
|
result->add(client.toElement());
|
||||||
|
}
|
||||||
|
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BasicHttpAuthConfig::parse(const ConstElementPtr& config) {
|
||||||
|
if (!config) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (config->getType() != Element::list) {
|
||||||
|
isc_throw(DhcpConfigError, "basic-authentications must be a list ("
|
||||||
|
<< config->getPosition() << ")");
|
||||||
|
}
|
||||||
|
for (auto client : config->listValue()) {
|
||||||
|
if (client->getType() != Element::map) {
|
||||||
|
isc_throw(DhcpConfigError, "basic-authentications items must be "
|
||||||
|
<< "maps (" << client->getPosition() << ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
// user
|
||||||
|
ConstElementPtr user_cfg = client->get("user");
|
||||||
|
if (!user_cfg) {
|
||||||
|
isc_throw(DhcpConfigError, "user is required in "
|
||||||
|
<< "basic-authentications items ("
|
||||||
|
<< client->getPosition() << ")");
|
||||||
|
}
|
||||||
|
if (user_cfg->getType() != Element::string) {
|
||||||
|
isc_throw(DhcpConfigError, "user must be a string ("
|
||||||
|
<< user_cfg->getPosition() << ")");
|
||||||
|
}
|
||||||
|
string user = user_cfg->stringValue();
|
||||||
|
if (user.empty()) {
|
||||||
|
isc_throw(DhcpConfigError, "user must be not be empty ("
|
||||||
|
<< user_cfg->getPosition() << ")");
|
||||||
|
}
|
||||||
|
if (user.find(':') != string::npos) {
|
||||||
|
isc_throw(DhcpConfigError, "user must not contain a ':': '"
|
||||||
|
<< user << "' (" << user_cfg->getPosition() << ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
// password
|
||||||
|
string password;
|
||||||
|
ConstElementPtr password_cfg = client->get("password");
|
||||||
|
if (password_cfg) {
|
||||||
|
if (password_cfg->getType() != Element::string) {
|
||||||
|
isc_throw(DhcpConfigError, "password must be a string ("
|
||||||
|
<< password_cfg->getPosition() << ")");
|
||||||
|
}
|
||||||
|
password = password_cfg->stringValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
// user context
|
||||||
|
ConstElementPtr user_context = client->get("user-context");
|
||||||
|
if (user_context) {
|
||||||
|
if (user_context->getType() != Element::map) {
|
||||||
|
isc_throw(DhcpConfigError, "user-context must be a map ("
|
||||||
|
<< user_context->getPosition() << ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add it.
|
||||||
|
try {
|
||||||
|
add(user, password, user_context);
|
||||||
|
} catch (const std::exception& ex) {
|
||||||
|
isc_throw(DhcpConfigError, ex.what() << " ("
|
||||||
|
<< client->getPosition() << ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end of namespace isc::http
|
||||||
|
} // end of namespace isc
|
120
src/lib/http/basic_auth_config.h
Normal file
120
src/lib/http/basic_auth_config.h
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
// Copyright (C) 2020 Internet Systems Consortium, Inc. ("ISC")
|
||||||
|
//
|
||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
#ifndef HTTP_BASIC_AUTH_CONFIG_H
|
||||||
|
#define HTTP_BASIC_AUTH_CONFIG_H
|
||||||
|
|
||||||
|
#include <cc/cfg_to_element.h>
|
||||||
|
#include <cc/data.h>
|
||||||
|
#include <cc/simple_parser.h>
|
||||||
|
#include <cc/user_context.h>
|
||||||
|
#include <http/basic_auth.h>
|
||||||
|
#include <list>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace isc {
|
||||||
|
namespace http {
|
||||||
|
|
||||||
|
/// @brief Type of basic HTTP authentication credential and user id map.
|
||||||
|
typedef std::unordered_map<std::string, std::string> BasicHttpAuthMap;
|
||||||
|
|
||||||
|
/// @brief Basic HTTP authentication client configuration.
|
||||||
|
class BasicHttpAuthClient : public isc::data::UserContext,
|
||||||
|
public isc::data::CfgToElement {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// @brief Constructor.
|
||||||
|
///
|
||||||
|
/// @param user User id
|
||||||
|
/// @param password Password
|
||||||
|
/// @param user_context Optional user context
|
||||||
|
BasicHttpAuthClient(const std::string& user,
|
||||||
|
const std::string& password,
|
||||||
|
const isc::data::ConstElementPtr& user_context);
|
||||||
|
|
||||||
|
/// @brief Returns the user id.
|
||||||
|
const std::string& getUser() const {
|
||||||
|
return (user_);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Returns the password.
|
||||||
|
const std::string& getPassword() const {
|
||||||
|
return (password_);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Unparses basic HTTP authentication client configuration.
|
||||||
|
///
|
||||||
|
/// @return A pointer to unparsed client configuration.
|
||||||
|
virtual isc::data::ElementPtr toElement() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/// @brief The user id.
|
||||||
|
std::string user_;
|
||||||
|
|
||||||
|
/// @brief The password.
|
||||||
|
std::string password_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @brief Type of basic HTTP authentication client configuration list.
|
||||||
|
typedef std::list<BasicHttpAuthClient> BasicHttpAuthClientList;
|
||||||
|
|
||||||
|
/// @brief Basic HTTP authentication configuration.
|
||||||
|
class BasicHttpAuthConfig : public isc::data::CfgToElement {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// @brief Add a client configuration.
|
||||||
|
///
|
||||||
|
/// @param user User id
|
||||||
|
/// @param password Password
|
||||||
|
/// @param user_context Optional user context
|
||||||
|
/// @throw BadValue if the user id contains the ':' character.
|
||||||
|
void add(const std::string& user,
|
||||||
|
const std::string& password,
|
||||||
|
const isc::data::ConstElementPtr& user_context = isc::data::ConstElementPtr());
|
||||||
|
|
||||||
|
/// @brief Clear configuration.
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
/// @brief Returns the list of client configuration.
|
||||||
|
///
|
||||||
|
/// @return List of basic HTTP authentication client configuration.
|
||||||
|
const BasicHttpAuthClientList& getClientList() const {
|
||||||
|
return (list_);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Returns the credential and user id map.
|
||||||
|
///
|
||||||
|
/// @return The basic HTTP authentication credential and user id map.
|
||||||
|
const BasicHttpAuthMap& getCredentialMap() const {
|
||||||
|
return (map_);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Parses basic HTTP authentication configuration.
|
||||||
|
///
|
||||||
|
/// @param config Element holding the basic HTTP authentication
|
||||||
|
/// configuration to be parsed.
|
||||||
|
/// @throw DhcpConfigError when the configuration is invalid.
|
||||||
|
void parse(const isc::data::ConstElementPtr& config);
|
||||||
|
|
||||||
|
/// @brief Unparses basic HTTP authentication configuration.
|
||||||
|
///
|
||||||
|
/// @return A pointer to unparsed basic HTTP authentication configuration.
|
||||||
|
virtual isc::data::ElementPtr toElement() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/// @brief The list of basic HTTP authentication client configuration.
|
||||||
|
BasicHttpAuthClientList list_;
|
||||||
|
|
||||||
|
/// @brief The basic HTTP authentication credential and user id map.
|
||||||
|
BasicHttpAuthMap map_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end of namespace isc::http
|
||||||
|
} // end of namespace isc
|
||||||
|
|
||||||
|
#endif // endif HTTP_BASIC_AUTH_CONFIG_H
|
@@ -7,6 +7,7 @@
|
|||||||
#ifndef HTTP_RESPONSE_CREATOR_AUTH_H
|
#ifndef HTTP_RESPONSE_CREATOR_AUTH_H
|
||||||
#define HTTP_RESPONSE_CREATOR_AUTH_H
|
#define HTTP_RESPONSE_CREATOR_AUTH_H
|
||||||
|
|
||||||
|
#include <http/basic_auth_config.h>
|
||||||
#include <http/response_creator.h>
|
#include <http/response_creator.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
@@ -14,9 +15,6 @@
|
|||||||
namespace isc {
|
namespace isc {
|
||||||
namespace http {
|
namespace http {
|
||||||
|
|
||||||
/// @brief Type of basic HTTP authentication credential and user id map.
|
|
||||||
typedef std::unordered_map<std::string, std::string> BasicHttpAuthMap;
|
|
||||||
|
|
||||||
/// @brief Validate basic HTTP authentication.
|
/// @brief Validate basic HTTP authentication.
|
||||||
///
|
///
|
||||||
/// @param creator The HTTP response creator.
|
/// @param creator The HTTP response creator.
|
||||||
|
@@ -21,6 +21,7 @@ if HAVE_GTEST
|
|||||||
TESTS += libhttp_unittests
|
TESTS += libhttp_unittests
|
||||||
|
|
||||||
libhttp_unittests_SOURCES = basic_auth_unittests.cc
|
libhttp_unittests_SOURCES = basic_auth_unittests.cc
|
||||||
|
libhttp_unittests_SOURCES += basic_auth_config_unittests.cc
|
||||||
libhttp_unittests_SOURCES += connection_pool_unittests.cc
|
libhttp_unittests_SOURCES += connection_pool_unittests.cc
|
||||||
libhttp_unittests_SOURCES += date_time_unittests.cc
|
libhttp_unittests_SOURCES += date_time_unittests.cc
|
||||||
libhttp_unittests_SOURCES += http_header_unittests.cc
|
libhttp_unittests_SOURCES += http_header_unittests.cc
|
||||||
|
218
src/lib/http/tests/basic_auth_config_unittests.cc
Normal file
218
src/lib/http/tests/basic_auth_config_unittests.cc
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
// Copyright (C) 2020 Internet Systems Consortium, Inc. ("ISC")
|
||||||
|
//
|
||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
#include <http/basic_auth_config.h>
|
||||||
|
#include <testutils/gtest_utils.h>
|
||||||
|
#include <testutils/test_to_element.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
using namespace isc;
|
||||||
|
using namespace isc::data;
|
||||||
|
using namespace isc::dhcp;
|
||||||
|
using namespace isc::http;
|
||||||
|
using namespace isc::test;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// Test that basic auth client works as expected.
|
||||||
|
TEST(BasicHttpAuthClientTest, basic) {
|
||||||
|
// Create a client.
|
||||||
|
ConstElementPtr ctx = Element::fromJSON("{ \"foo\": \"bar\" }");
|
||||||
|
BasicHttpAuthClient client("foo", "bar", ctx);
|
||||||
|
|
||||||
|
// Check it.
|
||||||
|
EXPECT_EQ("foo", client.getUser());
|
||||||
|
EXPECT_EQ("bar", client.getPassword());
|
||||||
|
EXPECT_TRUE(ctx->equals(*client.getContext()));
|
||||||
|
|
||||||
|
// Check toElement.
|
||||||
|
ElementPtr expected = Element::createMap();
|
||||||
|
expected->set("user", Element::create(string("foo")));
|
||||||
|
expected->set("password", Element::create(string("bar")));
|
||||||
|
expected->set("user-context", ctx);
|
||||||
|
runToElementTest<BasicHttpAuthClient>(expected, client);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that basic auth configuration works as expected.
|
||||||
|
TEST(BasicHttpAuthConfigTest, basic) {
|
||||||
|
// Create a configuration.
|
||||||
|
BasicHttpAuthConfig config;
|
||||||
|
|
||||||
|
// Initial configuration is empty.
|
||||||
|
EXPECT_TRUE(config.getClientList().empty());
|
||||||
|
EXPECT_TRUE(config.getCredentialMap().empty());
|
||||||
|
|
||||||
|
// Add rejects user id with embedded ':'.
|
||||||
|
EXPECT_THROW(config.add("foo:", "bar"), BadValue);
|
||||||
|
|
||||||
|
// Add a client.
|
||||||
|
ConstElementPtr ctx = Element::fromJSON("{ \"foo\": \"bar\" }");
|
||||||
|
EXPECT_NO_THROW(config.add("foo", "bar", ctx));
|
||||||
|
|
||||||
|
// Check the client.
|
||||||
|
ASSERT_EQ(1, config.getClientList().size());
|
||||||
|
const BasicHttpAuthClient& client = config.getClientList().front();
|
||||||
|
EXPECT_EQ("foo", client.getUser());
|
||||||
|
EXPECT_EQ("bar", client.getPassword());
|
||||||
|
EXPECT_TRUE(ctx->equals(*client.getContext()));
|
||||||
|
|
||||||
|
// Check the credential.
|
||||||
|
ASSERT_NE(0, config.getCredentialMap().count("Zm9vOmJhcg=="));
|
||||||
|
string user;
|
||||||
|
EXPECT_NO_THROW(user = config.getCredentialMap().at("Zm9vOmJhcg=="));
|
||||||
|
EXPECT_EQ("foo", user);
|
||||||
|
|
||||||
|
// Check toElement.
|
||||||
|
ElementPtr expected = Element::createList();
|
||||||
|
ElementPtr elem = Element::createMap();
|
||||||
|
elem->set("user", Element::create(string("foo")));
|
||||||
|
elem->set("password", Element::create(string("bar")));
|
||||||
|
elem->set("user-context", ctx);
|
||||||
|
expected->add(elem);
|
||||||
|
runToElementTest<BasicHttpAuthConfig>(expected, config);
|
||||||
|
|
||||||
|
// Add a second client and test it.
|
||||||
|
EXPECT_NO_THROW(config.add("test", "123\xa3"));
|
||||||
|
ASSERT_EQ(2, config.getClientList().size());
|
||||||
|
EXPECT_EQ("foo", config.getClientList().front().getUser());
|
||||||
|
EXPECT_EQ("test", config.getClientList().back().getUser());
|
||||||
|
ASSERT_NE(0, config.getCredentialMap().count("dGVzdDoxMjPCow=="));
|
||||||
|
|
||||||
|
// Check clear.
|
||||||
|
config.clear();
|
||||||
|
expected = Element::createList();
|
||||||
|
runToElementTest<BasicHttpAuthConfig>(expected, config);
|
||||||
|
|
||||||
|
// Add clients again.
|
||||||
|
EXPECT_NO_THROW(config.add("test", "123\xa3"));
|
||||||
|
EXPECT_NO_THROW(config.add("foo", "bar", ctx));
|
||||||
|
|
||||||
|
// Check that toElement keeps add order.
|
||||||
|
ElementPtr elem0 = Element::createMap();
|
||||||
|
elem0->set("user", Element::create(string("test")));
|
||||||
|
elem0->set("password", Element::create(string("123\xa3")));
|
||||||
|
expected->add(elem0);
|
||||||
|
expected->add(elem);
|
||||||
|
runToElementTest<BasicHttpAuthConfig>(expected, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that basic auth configuration parses.
|
||||||
|
TEST(BasicHttpAuthConfigTest, parse) {
|
||||||
|
BasicHttpAuthConfig config;
|
||||||
|
ElementPtr cfg;
|
||||||
|
|
||||||
|
// No config is accepted.
|
||||||
|
EXPECT_NO_THROW(config.parse(cfg));
|
||||||
|
EXPECT_TRUE(config.getClientList().empty());
|
||||||
|
EXPECT_TRUE(config.getCredentialMap().empty());
|
||||||
|
runToElementTest<BasicHttpAuthConfig>(Element::createList(), config);
|
||||||
|
|
||||||
|
// The config must be a list.
|
||||||
|
cfg = Element::createMap();
|
||||||
|
EXPECT_THROW_MSG(config.parse(cfg), DhcpConfigError,
|
||||||
|
"basic-authentications must be a list (:0:0)");
|
||||||
|
|
||||||
|
// The client config must be a map.
|
||||||
|
cfg = Element::createList();
|
||||||
|
ElementPtr client_cfg = Element::createList();
|
||||||
|
cfg->add(client_cfg);
|
||||||
|
EXPECT_THROW_MSG(config.parse(cfg), DhcpConfigError,
|
||||||
|
"basic-authentications items must be maps (:0:0)");
|
||||||
|
|
||||||
|
// The user parameter is mandatory in client config.
|
||||||
|
client_cfg = Element::createMap();
|
||||||
|
cfg = Element::createList();
|
||||||
|
cfg->add(client_cfg);
|
||||||
|
EXPECT_THROW_MSG(config.parse(cfg), DhcpConfigError,
|
||||||
|
"user is required in basic-authentications items (:0:0)");
|
||||||
|
|
||||||
|
// The user parameter must be a string.
|
||||||
|
ElementPtr user_cfg = Element::create(1);
|
||||||
|
client_cfg = Element::createMap();
|
||||||
|
client_cfg->set("user", user_cfg);
|
||||||
|
cfg = Element::createList();
|
||||||
|
cfg->add(client_cfg);
|
||||||
|
EXPECT_THROW_MSG(config.parse(cfg), DhcpConfigError,
|
||||||
|
"user must be a string (:0:0)");
|
||||||
|
|
||||||
|
// The user parameter must not be empty.
|
||||||
|
user_cfg = Element::create(string(""));
|
||||||
|
client_cfg = Element::createMap();
|
||||||
|
client_cfg->set("user", user_cfg);
|
||||||
|
cfg = Element::createList();
|
||||||
|
cfg->add(client_cfg);
|
||||||
|
EXPECT_THROW_MSG(config.parse(cfg), DhcpConfigError,
|
||||||
|
"user must be not be empty (:0:0)");
|
||||||
|
|
||||||
|
// The user parameter must not contain ':'.
|
||||||
|
user_cfg = Element::create(string("foo:bar"));
|
||||||
|
client_cfg = Element::createMap();
|
||||||
|
client_cfg->set("user", user_cfg);
|
||||||
|
cfg = Element::createList();
|
||||||
|
cfg->add(client_cfg);
|
||||||
|
EXPECT_THROW_MSG(config.parse(cfg), DhcpConfigError,
|
||||||
|
"user must not contain a ':': 'foo:bar' (:0:0)");
|
||||||
|
|
||||||
|
// Password is not required.
|
||||||
|
user_cfg = Element::create(string("foo"));
|
||||||
|
client_cfg = Element::createMap();
|
||||||
|
client_cfg->set("user", user_cfg);
|
||||||
|
cfg = Element::createList();
|
||||||
|
cfg->add(client_cfg);
|
||||||
|
EXPECT_NO_THROW(config.parse(cfg));
|
||||||
|
ASSERT_EQ(1, config.getClientList().size());
|
||||||
|
EXPECT_EQ("", config.getClientList().front().getPassword());
|
||||||
|
config.clear();
|
||||||
|
|
||||||
|
// The password parameter must be a string.
|
||||||
|
ElementPtr password_cfg = Element::create(1);
|
||||||
|
client_cfg = Element::createMap();
|
||||||
|
client_cfg->set("user", user_cfg);
|
||||||
|
client_cfg->set("password", password_cfg);
|
||||||
|
cfg = Element::createList();
|
||||||
|
cfg->add(client_cfg);
|
||||||
|
EXPECT_THROW_MSG(config.parse(cfg), DhcpConfigError,
|
||||||
|
"password must be a string (:0:0)");
|
||||||
|
|
||||||
|
// Empty password is accepted.
|
||||||
|
password_cfg = Element::create(string(""));
|
||||||
|
client_cfg = Element::createMap();
|
||||||
|
client_cfg->set("user", user_cfg);
|
||||||
|
client_cfg->set("password", password_cfg);
|
||||||
|
cfg = Element::createList();
|
||||||
|
cfg->add(client_cfg);
|
||||||
|
EXPECT_NO_THROW(config.parse(cfg));
|
||||||
|
ASSERT_EQ(1, config.getClientList().size());
|
||||||
|
EXPECT_EQ("", config.getClientList().front().getPassword());
|
||||||
|
config.clear();
|
||||||
|
|
||||||
|
// User context must be a map.
|
||||||
|
password_cfg = Element::create(string("bar"));
|
||||||
|
ElementPtr ctx = Element::createList();
|
||||||
|
client_cfg = Element::createMap();
|
||||||
|
client_cfg->set("user", user_cfg);
|
||||||
|
client_cfg->set("password", password_cfg);
|
||||||
|
client_cfg->set("user-context", ctx);
|
||||||
|
cfg = Element::createList();
|
||||||
|
cfg->add(client_cfg);
|
||||||
|
EXPECT_THROW_MSG(config.parse(cfg), DhcpConfigError,
|
||||||
|
"user-context must be a map (:0:0)");
|
||||||
|
|
||||||
|
// Check a working not empty config.
|
||||||
|
ctx = Element::fromJSON("{ \"foo\": \"bar\" }");
|
||||||
|
client_cfg = Element::createMap();
|
||||||
|
client_cfg->set("user", user_cfg);
|
||||||
|
client_cfg->set("password", password_cfg);
|
||||||
|
client_cfg->set("user-context", ctx);
|
||||||
|
cfg = Element::createList();
|
||||||
|
cfg->add(client_cfg);
|
||||||
|
EXPECT_NO_THROW(config.parse(cfg));
|
||||||
|
runToElementTest<BasicHttpAuthConfig>(cfg, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end of anonymous namespace
|
Reference in New Issue
Block a user