virtual void SetUp() {
resetHooksPath();
setSocketTestPath();
+ file::PathChecker::enableEnforcement(false);
}
virtual void TearDown() {
resetHooksPath();
resetSocketPath();
+ file::PathChecker::enableEnforcement(true);
}
/// @brief Sets the Hooks path from which hooks can be loaded.
#include <http/post_request.h>
#include <http/post_request_json.h>
#include <http/response_json.h>
+#include <util/filesystem.h>
#include <process/testutils/d_test_stubs.h>
#include <agent/tests/test_basic_auth_libraries.h>
#include <gtest/gtest.h>
using namespace isc::hooks;
using namespace isc::http;
using namespace isc::process;
+using namespace isc::util;
namespace ph = std::placeholders;
namespace {
: DControllerTest(CtrlAgentController::instance),
response_creator_(),
request_(response_creator_.createNewHttpRequest()) {
+ file::PathChecker::enableEnforcement(true);
// Deregisters commands.
CtrlAgentCommandMgr::instance().deregisterAll();
CtrlAgentCommandMgr::instance().
CtrlAgentCommandMgr::instance().deregisterAll();
HooksManager::prepareUnloadLibraries();
static_cast<void>(HooksManager::unloadLibraries());
+ file::PathChecker::enableEnforcement(true);
}
/// @brief Fills request context with required data to create new request.
// required but not provided by request using the hook.
TEST_F(CtrlAgentResponseCreatorTest, hookNoAuth) {
setBasicContext(request_);
+ file::PathChecker::enableEnforcement(false);
// Body: "list-commands" is natively supported by the command manager.
// We add a random value in the extra entry: see next unit test
// auth response provided by the hool.
TEST_F(CtrlAgentResponseCreatorTest, hookNoAuthHeaders) {
setBasicContext(request_);
+ file::PathChecker::enableEnforcement(false);
// Body: "list-commands" is natively supported by the command manager.
// We add a random value in the extra entry: see next unit test
// Test successful server response when the client is authenticated.
TEST_F(CtrlAgentResponseCreatorTest, hookBasicAuth) {
setBasicContext(request_);
+ file::PathChecker::enableEnforcement(false);
// Body: "list-commands" is natively supported by the command manager.
// We add a random value in the extra entry:
// Create fresh context.
resetConfiguration();
setSocketTestPath();
+ file::PathChecker::enableEnforcement(true);
}
~CtrlAgentGetCfgTest() {
resetConfiguration();
resetHooksPath();
resetSocketPath();
+ file::PathChecker::enableEnforcement(true);
}
/// @brief Sets the Hooks path from which hooks can be loaded.
/// Test a configuration
TEST_F(CtrlAgentGetCfgTest, simple) {
setHooksTestPath();
+ file::PathChecker::enableEnforcement(false);
// get the simple configuration
std::string simple_file = string(CFG_EXAMPLES) + "/" + "simple.json";
D2CfgMgrTest():cfg_mgr_(new D2CfgMgr()), d2_params_() {
resetHooksPath();
resetSocketPath();
+ file::PathChecker::enableEnforcement(true);
}
/// @brief Destructor
~D2CfgMgrTest() {
resetHooksPath();
resetSocketPath();
+ file::PathChecker::enableEnforcement(true);
}
/// @brief Sets the Hooks path from which hooks can be loaded.
TEST_F(D2CfgMgrTest, fullConfig) {
setHooksTestPath();
setSocketTestPath();
+ file::PathChecker::enableEnforcement(false);
// Create a configuration with all of application level parameters, plus
// both the forward and reverse ddns managers. Both managers have two
TEST_F(D2CfgMgrTest, configPermutations) {
std::string test_file = testDataFile("d2_cfg_tests.json");
isc::data::ConstElementPtr tests;
+ file::PathChecker::enableEnforcement(false);
// Read contents of the file and parse it as JSON. Note it must contain
// all valid JSON, we aren't testing JSON parsing.
/// @brief Tests comments.
TEST_F(D2CfgMgrTest, comments) {
setSocketTestPath();
+ file::PathChecker::enableEnforcement(false);
std::string config = "{ "
"\"comment\": \"D2 config\" , "
"\"ip-address\" : \"192.168.1.33\" , "
: server_(NakedD2Controller::instance()) {
setSocketTestPath();
::remove(socket_path_.c_str());
+ file::PathChecker::enableEnforcement(false);
}
/// @brief Destructor.
CommandMgr::instance().deregisterAll();
UnixCommandMgr::instance().setConnectionTimeout(TIMEOUT_DHCP_SERVER_RECEIVE_COMMAND);
resetSocketPath();
+ file::PathChecker::enableEnforcement(true);
}
/// @brief Returns pointer to the server's IO service.
#include <d2srv/testutils/nc_test_utils.h>
#include <d2/d2_controller.h>
#include <d2/d2_process.h>
+#include <util/filesystem.h>
#include <process/testutils/d_test_stubs.h>
#include <testutils/gtest_utils.h>
using namespace isc::asiolink::test;
using namespace isc::process;
+using namespace isc::util;
using namespace boost::posix_time;
namespace isc {
/// Note the constructor passes in the static D2Controller instance
/// method.
D2ControllerTest() : DControllerTest(D2Controller::instance) {
+ file::PathChecker::enableEnforcement(false);
+ }
+
+ /// @brief Destructor
+ virtual ~D2ControllerTest() {
+ file::PathChecker::enableEnforcement(true);
}
/// @brief Fetches the D2Controller's D2Process
#include <http/response.h>
#include <http/response_parser.h>
#include <http/testutils/test_http_client.h>
+#include <util/filesystem.h>
#include <gtest/gtest.h>
#include <boost/pointer_cast.hpp>
#include <atomic>
using namespace isc::data;
using namespace isc::http;
using namespace isc::process;
+using namespace isc::util;
namespace ph = std::placeholders;
namespace isc {
/// Sets socket path to its default value.
BaseCtrlChannelD2Test()
: server_(NakedD2Controller::instance()) {
+ file::PathChecker::enableEnforcement(false);
}
/// @brief Destructor.
// Reset command manager.
CommandMgr::instance().deregisterAll();
HttpCommandMgr::instance().setConnectionTimeout(TIMEOUT_AGENT_RECEIVE_COMMAND);
+ file::PathChecker::enableEnforcement(true);
}
/// @brief Returns pointer to the server's IO service.
#include <dhcp_ddns/ncr_io.h>
#include <hooks/hooks_manager.h>
#include <hooks/hooks_parser.h>
+#include <util/filesystem.h>
#include <process/testutils/d_test_stubs.h>
#include <boost/date_time/posix_time/posix_time.hpp>
using namespace isc::data;
using namespace isc::hooks;
using namespace isc::process;
+using namespace isc::util;
using namespace boost::posix_time;
namespace {
HooksManager::setTestMode(false);
D2Controller::instance();
init();
+ file::PathChecker::enableEnforcement(false);
}
/// @brief Destructor
virtual ~D2ProcessTest() {
D2Controller::instance().reset();
resetHooksPath();
+ file::PathChecker::enableEnforcement(true);
}
/// @brief Sets the Hooks path from which hooks can be loaded.
#include <d2/tests/parser_unittest.h>
#include <d2srv/d2_simple_parser.h>
#include <testutils/test_to_element.h>
+#include <util/filesystem.h>
#include <boost/lexical_cast.hpp>
#include <fstream>
using namespace isc::data;
using namespace isc::d2;
using namespace isc::test;
+using namespace isc::util;
namespace {
parser_type = D2ParserContext::PARSER_JSON)
: parser_type_(parser_type) {
reset();
+ file::PathChecker::enableEnforcement(false);
}
/// @brief Destructor
virtual ~D2SimpleParserTest() {
reset();
+ file::PathChecker::enableEnforcement(true);
}
/// @brief Parses JSON text and compares the results against an expected
resetConfiguration();
// Fill test secret file.
fillSecretFile();
+ file::PathChecker::enableEnforcement(false);
}
~D2GetConfigTest() {
resetConfiguration();
resetHooksPath();
resetSocketPath();
+ file::PathChecker::enableEnforcement(true);
}
/// @brief Sets the Hooks path from which hooks can be loaded.
resetHooksPath();
Dhcpv4SrvTest::resetSocketPath();
+ file::PathChecker::enableEnforcement(true);
}
~Dhcp4ParserTest() {
resetHooksPath();
Dhcpv4SrvTest::resetSocketPath();
+ file::PathChecker::enableEnforcement(true);
};
/// @brief Sets the Hooks path from which hooks can be loaded.
// This test checks comments. Please keep it last.
TEST_F(Dhcp4ParserTest, comments) {
Dhcpv4SrvTest::setSocketTestPath();
+ file::PathChecker::enableEnforcement(false);
string config = PARSER_CONFIGS[6];
extractConfig(config);
void
Dhcpv4SrvTest::checkConfigFiles() {
setSocketTestPath();
+ file::PathChecker::enableEnforcement(false);
#if defined (HAVE_MYSQL)
MySqlHostDataSourceInit mysql_init;
#endif
Dhcpv4SrvTest::Dhcpv4SrvTest()
: rcode_(-1), srv_(new NakedDhcpv4Srv(0)), multi_threading_(false), start_time_(PktEvent::now()) {
+ file::PathChecker::enableEnforcement(true);
// Wipe any existing statistics
isc::stats::StatsMgr::instance().removeAll();
Dhcpv4SrvTest::~Dhcpv4SrvTest() {
resetSocketPath();
+ file::PathChecker::enableEnforcement(true);
// Make sure that we revert to default value
CfgMgr::instance().clear();
#include <dhcp4/tests/dhcp4_test_utils.h>
#include <dhcp4/tests/get_config_unittest.h>
#include <dhcpsrv/cfgmgr.h>
+#include <util/filesystem.h>
#include <testutils/gtest_utils.h>
#include <testutils/user_context_utils.h>
using namespace isc::dhcp;
using namespace isc::dhcp::test;
using namespace isc::test;
+using namespace isc::util;
namespace {
// Create fresh context.
resetConfiguration();
Dhcpv4SrvTest::setSocketTestPath();
+ file::PathChecker::enableEnforcement(false);
}
~Dhcp4GetConfigTest() {
resetConfiguration();
Dhcpv4SrvTest::resetSocketPath();
- };
+ file::PathChecker::enableEnforcement(true);
+ }
/// @brief Parse and Execute configuration
///
#include <dhcp4/tests/dhcp4_test_utils.h>
#include <dhcp4/tests/get_config_unittest.h>
#include <dhcpsrv/cfgmgr.h>
+#include <util/filesystem.h>
#include <testutils/gtest_utils.h>
#include <testutils/user_context_utils.h>
using namespace isc::dhcp;
using namespace isc::dhcp::test;
using namespace isc::test;
+using namespace isc::util;
namespace {
srv_.reset(new ControlledDhcpv4Srv(0));
// Create fresh context.
resetConfiguration();
+ Dhcpv4SrvTest::setSocketTestPath();
+ file::PathChecker::enableEnforcement(false);
}
~Dhcp4GetConfigTest() {
resetConfiguration();
- };
+ Dhcpv4SrvTest::resetSocketPath();
+ file::PathChecker::enableEnforcement(true);
+ }
/// @brief Parse and Execute configuration
///
#include <process/log_parser.h>
#include <stats/stats_mgr.h>
#include <util/chrono_time_utils.h>
+#include <util/filesystem.h>
#include "marker_file.h"
IfaceMgr::instance().setDetectCallback(std::bind(&IfaceMgr::checkDetectIfaces,
IfaceMgr::instancePtr().get(), ph::_1));
setLogTestPath("/dev");
+ file::PathChecker::enableEnforcement(false);
}
/// @brief Destructor
IfaceMgr::instance().closeSockets();
IfaceMgr::instance().detectIfaces();
resetLogPath();
+ file::PathChecker::enableEnforcement(true);
}
/// @brief Sets the log path where log output may be written.
#include <testutils/log_utils.h>
#include <testutils/test_to_element.h>
#include <util/chrono_time_utils.h>
+#include <util/filesystem.h>
#include <util/doubles.h>
#include <boost/foreach.hpp>
using namespace isc::dhcp::test;
using namespace isc::hooks;
using namespace isc::test;
+using namespace isc::util;
using namespace std;
namespace {
resetConfiguration();
resetHooksPath();
+ file::PathChecker::enableEnforcement(true);
}
~Dhcp6ParserTest() {
static_cast<void>(remove(UNLOAD_MARKER_FILE));
resetHooksPath();
+ file::PathChecker::enableEnforcement(true);
};
/// @brief Sets the Hooks path from which hooks can be loaded.
// This test checks comments. Please keep it last.
TEST_F(Dhcp6ParserTest, comments) {
setSocketTestPath();
+ file::PathChecker::enableEnforcement(false);
string config = PARSER_CONFIGS[9];
extractConfig(config);
void
Dhcpv6SrvTest::checkConfigFiles() {
setSocketTestPath();
+ file::PathChecker::enableEnforcement(false);
#if defined (HAVE_MYSQL)
MySqlHostDataSourceInit mysql_init;
#endif
#include <log/logger_support.h>
#include <process/log_parser.h>
#include <stats/stats_mgr.h>
+#include <util/filesystem.h>
#include <util/pointer_util.h>
#include <cstdio>
#include <sstream>
CfgMgr::instance().getDataDir(true, TEST_DATA_BUILDDIR);
resetLogPath();
resetSocketPath();
+ file::PathChecker::enableEnforcement(true);
}
BaseServerTest::~BaseServerTest() {
isc::log::initLogger();
resetLogPath();
resetSocketPath();
+ file::PathChecker::enableEnforcement(true);
}
void
#include <cc/command_interpreter.h>
#include <cc/data.h>
#include <cc/simple_parser.h>
-#include <config/unix_command_config.h>
#include <dhcp/testutils/iface_mgr_test_config.h>
#include <dhcp6/ctrl_dhcp6_srv.h>
#include <dhcp6/dhcp6_srv.h>
// Reset configuration for each test.
resetConfiguration();
BaseServerTest::setSocketTestPath();
+ file::PathChecker::enableEnforcement(false);
}
~Dhcp6GetConfigTest() {
// Reset configuration database after each test.
resetConfiguration();
BaseServerTest::resetSocketPath();
+ file::PathChecker::enableEnforcement(true);
};
/// @brief Parse and Execute configuration
#include <dhcp6/tests/dhcp6_test_utils.h>
#include <dhcp6/tests/get_config_unittest.h>
#include <dhcpsrv/cfgmgr.h>
+#include <util/filesystem.h>
#include <testutils/gtest_utils.h>
#include <testutils/user_context_utils.h>
using namespace isc::dhcp;
using namespace isc::dhcp::test;
using namespace isc::test;
+using namespace isc::util;
namespace {
// Reset configuration for each test.
resetConfiguration();
+ BaseServerTest::setSocketTestPath();
+ file::PathChecker::enableEnforcement(false);
}
~Dhcp6GetConfigTest() {
// Reset configuration database after each test.
resetConfiguration();
+ BaseServerTest::resetSocketPath();
+ file::PathChecker::enableEnforcement(true);
};
/// @brief Parse and Execute configuration
: BaseServerTest() {
reset();
setLogTestPath("/dev");
+ file::PathChecker::enableEnforcement(false);
}
virtual ~HttpCtrlDhcpv6Test() {
// This test verifies a HTTP control socket configuration with authentication
// can be parsed and unparsed.
TEST_F(HttpCommandConfigTest, authentication) {
+ file::PathChecker::enableEnforcement(false);
// Configure with authentication.
string config = R"(
{
using namespace isc::data;
using namespace isc::process;
+using namespace isc::util;
namespace isc {
namespace d2 {
}
} else {
secret = getString(key_config, "secret");
+ if (file::PathChecker::shouldEnforceSecurity()) {
+ isc_throw(D2CfgError, "use of clear text TSIG 'secret' is NOT SECURE ("
+ << " (" << getPosition("secret", key_config)
+ << ")");
+ } else {
+ LOG_WARN(dhcp_to_d2_logger, DHCP_DDNS_TSIG_SECRET_SECURITY_WARN)
+ .arg(getPosition("secret", key_config).str());
+ }
}
+
ConstElementPtr user_context = key_config->get("user-context");
// Algorithm must be valid.
extern const isc::log::MessageID DHCP_DDNS_STARTING_TRANSACTION = "DHCP_DDNS_STARTING_TRANSACTION";
extern const isc::log::MessageID DHCP_DDNS_STATE_MODEL_UNEXPECTED_ERROR = "DHCP_DDNS_STATE_MODEL_UNEXPECTED_ERROR";
extern const isc::log::MessageID DHCP_DDNS_TRANS_SEND_ERROR = "DHCP_DDNS_TRANS_SEND_ERROR";
+extern const isc::log::MessageID DHCP_DDNS_TSIG_SECRET_SECURITY_WARN = "DHCP_DDNS_TSIG_SECRET_SECURITY_WARN";
extern const isc::log::MessageID DHCP_DDNS_UPDATE_REQUEST_SENT = "DHCP_DDNS_UPDATE_REQUEST_SENT";
extern const isc::log::MessageID DHCP_DDNS_UPDATE_RESPONSE_RECEIVED = "DHCP_DDNS_UPDATE_RESPONSE_RECEIVED";
"DHCP_DDNS_STARTING_TRANSACTION", "Request ID %1:",
"DHCP_DDNS_STATE_MODEL_UNEXPECTED_ERROR", "Request ID %1: application encountered an unexpected error while carrying out a NameChangeRequest: %2",
"DHCP_DDNS_TRANS_SEND_ERROR", "Request ID %1: application encountered an unexpected error while attempting to send a DNS update: %2",
+ "DHCP_DDNS_TSIG_SECRET_SECURITY_WARN", "use of clear text TSIG 'secret' is NOT SECURE: %1",
"DHCP_DDNS_UPDATE_REQUEST_SENT", "Request ID %1: %2 to server: %3",
"DHCP_DDNS_UPDATE_RESPONSE_RECEIVED", "Request ID %1: to server: %2 status: %3",
NULL
extern const isc::log::MessageID DHCP_DDNS_STARTING_TRANSACTION;
extern const isc::log::MessageID DHCP_DDNS_STATE_MODEL_UNEXPECTED_ERROR;
extern const isc::log::MessageID DHCP_DDNS_TRANS_SEND_ERROR;
+extern const isc::log::MessageID DHCP_DDNS_TSIG_SECRET_SECURITY_WARN;
extern const isc::log::MessageID DHCP_DDNS_UPDATE_REQUEST_SENT;
extern const isc::log::MessageID DHCP_DDNS_UPDATE_RESPONSE_RECEIVED;
Logged at debug log level 50.
This is a debug message issued when DHCP_DDNS receives sends a DNS update
response from a DNS server.
+
+% DHCP_DDNS_SECURITY_CHECKS_DISABLED Invoked with command line option -X, Security checks are disabled!!
+This warning is emitted when internal security checks normally
+performed by kea-dhcp-ddns have been disabled via command line option '-X'.
+This means the server is not enforcing restrictions on resource
+paths or permissions. This mode of operation may expose your
+environment to security vulnerabilities and should only be used
+after consideration.
+
+% DHCP_DDNS_TSIG_SECRET_SECURITY_WARN use of clear text TSIG 'secret' is NOT SECURE: %1
+This warning message is issued when security enforcement is disabled
+and TSIG key configuration uses clear text 'secret' rather
+than 'secret-file'. The server will still use the key as configured
+but is warning that doing so may pose a security risk.
namespace isc {
namespace http {
+extern const isc::log::MessageID HTTP_CLIENT_PASSWORD_SECURITY_WARN = "HTTP_CLIENT_PASSWORD_SECURITY_WARN";
extern const isc::log::MessageID HTTP_CLIENT_REQUEST_AUTHORIZED = "HTTP_CLIENT_REQUEST_AUTHORIZED";
extern const isc::log::MessageID HTTP_CLIENT_REQUEST_BAD_AUTH_HEADER = "HTTP_CLIENT_REQUEST_BAD_AUTH_HEADER";
extern const isc::log::MessageID HTTP_CLIENT_REQUEST_NOT_AUTHORIZED = "HTTP_CLIENT_REQUEST_NOT_AUTHORIZED";
extern const isc::log::MessageID HTTP_CLIENT_REQUEST_NO_AUTH_HEADER = "HTTP_CLIENT_REQUEST_NO_AUTH_HEADER";
+extern const isc::log::MessageID HTTP_CLIENT_USER_SECURITY_WARN = "HTTP_CLIENT_USER_SECURITY_WARN";
} // namespace http
} // namespace isc
namespace {
const char* values[] = {
+ "HTTP_CLIENT_PASSWORD_SECURITY_WARN", "use of clear text 'password' is NOT SECURE: %1",
"HTTP_CLIENT_REQUEST_AUTHORIZED", "received HTTP request authorized for '%1'",
"HTTP_CLIENT_REQUEST_BAD_AUTH_HEADER", "received HTTP request with malformed authentication header: %1",
"HTTP_CLIENT_REQUEST_NOT_AUTHORIZED", "received HTTP request with not matching authentication header",
"HTTP_CLIENT_REQUEST_NO_AUTH_HEADER", "received HTTP request without required authentication header",
+ "HTTP_CLIENT_USER_SECURITY_WARN", "use of clear text 'user' is NOT SECURE: %1",
NULL
};
namespace isc {
namespace http {
+extern const isc::log::MessageID HTTP_CLIENT_PASSWORD_SECURITY_WARN;
extern const isc::log::MessageID HTTP_CLIENT_REQUEST_AUTHORIZED;
extern const isc::log::MessageID HTTP_CLIENT_REQUEST_BAD_AUTH_HEADER;
extern const isc::log::MessageID HTTP_CLIENT_REQUEST_NOT_AUTHORIZED;
extern const isc::log::MessageID HTTP_CLIENT_REQUEST_NO_AUTH_HEADER;
+extern const isc::log::MessageID HTTP_CLIENT_USER_SECURITY_WARN;
} // namespace http
} // namespace isc
% HTTP_CLIENT_REQUEST_NO_AUTH_HEADER received HTTP request without required authentication header
This information message is issued when the server receives a request without
a required authentication header.
+
+% HTTP_CLIENT_PASSWORD_SECURITY_WARN use of clear text 'password' is NOT SECURE: %1
+This warning message is issued when security enforcement is disabled
+and command socket configuration uses clear text 'password' rather
+than 'password-file'. The server will still use the socket as configured
+but is warning that doing so may pose a security risk.
+
+% HTTP_CLIENT_USER_SECURITY_WARN use of clear text 'user' is NOT SECURE: %1
+This warning message is issued when security enforcement is disabled
+and command socket configuration uses clear text 'user' rather
+than 'user-file'. The server will still use the socket as configured
+but is warning that doing so may pose a security risk.
"password must not be a default one ("
<< password_cfg->getPosition() << ")");
}
+
+ if (file::PathChecker::shouldEnforceSecurity()) {
+ isc_throw(DhcpConfigError, "use of clear text 'password' is NOT SECURE ("
+ << password_cfg->getPosition() << ")");
+ } else {
+ LOG_INFO(auth_logger, HTTP_CLIENT_PASSWORD_SECURITY_WARN)
+ .arg(password_cfg->getPosition().str());
+ }
}
// password file.
isc_throw(DhcpConfigError, "user must not contain a ':': '"
<< user << "' (" << user_cfg->getPosition() << ")");
}
+
+ if (file::PathChecker::shouldEnforceSecurity()) {
+ isc_throw(DhcpConfigError, "use of clear text 'user' is NOT SECURE ("
+ << user_cfg->getPosition() << ")");
+ } else {
+ LOG_INFO(auth_logger, HTTP_CLIENT_USER_SECURITY_WARN)
+ .arg(user_cfg->getPosition().str());
+ }
}
// user file.
#include <http/basic_auth_config.h>
#include <testutils/gtest_utils.h>
#include <testutils/test_to_element.h>
+#include <testutils/log_utils.h>
+#include <util/filesystem.h>
#include <gtest/gtest.h>
using namespace isc;
using namespace isc::dhcp;
using namespace isc::http;
using namespace isc::test;
+using namespace isc::util;
+using namespace isc::dhcp::test;
using namespace std;
namespace {
runToElementTest<BasicHttpAuthClient>(expected, client);
}
+
+/// @brief Test fixture for testing BasicHttpAuthConfig.
+class BasicHttpAuthConfigTest : public LogContentTest {
+public:
+
+ /// @brief Constructor.
+ BasicHttpAuthConfigTest() {
+ file::PathChecker::enableEnforcement(true);
+ }
+
+ /// @brief Desstructor.
+ virtual ~BasicHttpAuthConfigTest() {
+ file::PathChecker::enableEnforcement(true);
+ }
+};
+
// Test that basic auth configuration works as expected.
-TEST(BasicHttpAuthConfigTest, basic) {
+TEST_F(BasicHttpAuthConfigTest, basic) {
// Create a configuration.
BasicHttpAuthConfig config;
}
// Test that basic auth configuration with files works as expected.
-TEST(BasicHttpAuthConfigTest, basicFiles) {
+TEST_F(BasicHttpAuthConfigTest, basicFiles) {
// Create a configuration.
BasicHttpAuthConfig config;
}
// Test that basic auth configuration parses.
-TEST(BasicHttpAuthConfigTest, parse) {
+TEST_F(BasicHttpAuthConfigTest, parse) {
+ file::PathChecker::enableEnforcement(false);
BasicHttpAuthConfig config;
ElementPtr cfg;
cfg->set("clients", clients_cfg);
EXPECT_NO_THROW(config.parse(cfg));
runToElementTest<BasicHttpAuthConfig>(cfg, config);
+ std::cout << "TKM config: " << prettyPrint(config.toElement()) << std::endl;
// Check a working not empty config with files.
config.clear();
cfg->set("clients", clients_cfg);
EXPECT_NO_THROW(config.parse(cfg));
runToElementTest<BasicHttpAuthConfig>(cfg, config);
+
+ EXPECT_EQ(4, countFile("HTTP_CLIENT_PASSWORD_SECURITY_WARN"
+ " use of clear text 'password' is NOT SECURE: :0:0"));
+}
+
+// Test that basic auth configuration catches use of 'user'
+// and warns if security is disabled or throws if enabled.
+TEST_F(BasicHttpAuthConfigTest, clearUser) {
+ BasicHttpAuthConfig auth;
+
+ std::string json = R"(
+ {
+ "type": "basic",
+ "clients": [
+ {
+ "user": "foo"
+ }]
+ }
+ )";
+
+ ConstElementPtr config;
+ ASSERT_NO_THROW_LOG(config = Element::fromJSON(json));
+ ASSERT_THROW_MSG(auth.parse(config), DhcpConfigError,
+ "use of clear text 'user' is NOT SECURE (<string>:6:21)");
+
+ // Disable security.
+ file::PathChecker::enableEnforcement(false);
+ ASSERT_NO_THROW_LOG(auth.parse(config));
+ EXPECT_EQ(1, countFile("HTTP_CLIENT_USER_SECURITY_WARN "
+ "use of clear text 'user' is NOT SECURE: <string>:6:21"));
+}
+
+// Test that basic auth configuration catches use of 'password'
+// and warns if security is disabled or throws if enabled.
+TEST_F(BasicHttpAuthConfigTest, clearPassword) {
+ BasicHttpAuthConfig auth;
+
+ std::string json = R"(
+ {
+ "type": "basic",
+ "clients": [
+ {
+ "user": "foo",
+ "password": "bar"
+ }]
+ }
+ )";
+
+ ConstElementPtr config;
+ ASSERT_NO_THROW_LOG(config = Element::fromJSON(json));
+ ASSERT_THROW_MSG(auth.parse(config), DhcpConfigError,
+ "use of clear text 'password' is NOT SECURE (<string>:7:25)");
+
+ // Disable security.
+ file::PathChecker::enableEnforcement(false);
+ ASSERT_NO_THROW_LOG(auth.parse(config));
+ EXPECT_EQ(1, countFile("HTTP_CLIENT_PASSWORD_SECURITY_WARN "
+ "use of clear text 'password' is NOT SECURE: <string>:7:25"));
+ EXPECT_EQ(1, countFile("HTTP_CLIENT_USER_SECURITY_WARN "
+ "use of clear text 'user' is NOT SECURE: <string>:6:21"));
}
} // end of anonymous namespace
test_lib_error "binary name must be specified for start_kea"
clean_exit 1
fi
- printf "Running command %s.\n" "\"${bin} -c ${CFG_FILE}\""
- "${bin}" -c "${CFG_FILE}" &
+ printf "Running command %s.\n" "\"${bin} -X -c ${CFG_FILE}\""
+ "${bin}" -X -c "${CFG_FILE}" &
}
# Waits with timeout for Kea to start.
# Instruct Control Agent to log to the specific file.
set_logger
# Check it
- printf "Running command %s.\n" "\"${bin_path}/${bin} -d -t ${CFG_FILE}\""
+ printf "Running command %s.\n" "\"${bin_path}/${bin} -X -d -t ${CFG_FILE}\""
run_command \
- "${bin_path}/${bin}" -d -t "${CFG_FILE}"
+ "${bin_path}/${bin}" -X -d -t "${CFG_FILE}"
if [ "${EXIT_CODE}" -ne "${expected_code}" ]; then
printf 'ERROR: expected exit code %s, got %s\n' "${expected_code}" "${EXIT_CODE}"
clean_exit 1