From: Francis Dupont Date: Mon, 3 Aug 2026 08:53:35 +0000 (+0200) Subject: [#3959] Checkpoint: added UTs X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=554eece1ecbaac2a3a273f9e566265849cdf36ac;p=thirdparty%2Fkea.git [#3959] Checkpoint: added UTs --- diff --git a/changelog_unreleased/3959-add-support-for-password-file-to-db-access b/changelog_unreleased/3959-add-support-for-password-file-to-db-access new file mode 100644 index 0000000000..a8c24a6f2f --- /dev/null +++ b/changelog_unreleased/3959-add-support-for-password-file-to-db-access @@ -0,0 +1,6 @@ +[func] fdupont + Added support for using a file to configure MySql + and PostgreSQL passwords. Instead of configuring + a value, it is taken from the content of a file. + The new parameter is "password-file". + (Gitlab #3959) diff --git a/src/hooks/dhcp/mysql/tests/mysql_host_data_source_unittest.cc b/src/hooks/dhcp/mysql/tests/mysql_host_data_source_unittest.cc index 38bde7b56d..358f969a1d 100644 --- a/src/hooks/dhcp/mysql/tests/mysql_host_data_source_unittest.cc +++ b/src/hooks/dhcp/mysql/tests/mysql_host_data_source_unittest.cc @@ -251,12 +251,23 @@ TEST(MySqlHostDataSource, OpenDatabase) { EXPECT_THROW(HostMgr::addBackend(connectionString( MYSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD, VALID_TIMEOUT, INVALID_READONLY_DB)), DbInvalidReadOnly); + EXPECT_THROW(HostMgr::addBackend(connectionString( + MYSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, NOT_EXIST_FILE)), + BadValue); + EXPECT_THROW(HostMgr::addBackend(connectionString( + MYSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, INVALID_FILE)), + DbOpenError); // Check for missing parameters EXPECT_THROW(HostMgr::addBackend(connectionString( - MYSQL_VALID_TYPE, NULL, VALID_HOST, INVALID_USER, VALID_PASSWORD)), + MYSQL_VALID_TYPE, 0, VALID_HOST, INVALID_USER, VALID_PASSWORD)), NoDatabaseName); + // Check for password file. + EXPECT_NO_THROW(HostMgr::addBackend(connectionString( + MYSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_FILE))); + HostMgr::delBackend("mysql"); + // Check for SSL/TLS support. if (hasMySQLTls()) { EXPECT_NO_THROW(HostMgr::addBackend(connectionString( @@ -353,12 +364,23 @@ TEST(MySqlHostDataSource, OpenDatabaseMultiThreading) { EXPECT_THROW(HostMgr::addBackend(connectionString( MYSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD, VALID_TIMEOUT, INVALID_READONLY_DB)), DbInvalidReadOnly); + EXPECT_THROW(HostMgr::addBackend(connectionString( + MYSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, NOT_EXIST_FILE)), + BadValue); + EXPECT_THROW(HostMgr::addBackend(connectionString( + MYSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, INVALID_FILE)), + DbOpenError); // Check for missing parameters EXPECT_THROW(HostMgr::addBackend(connectionString( MYSQL_VALID_TYPE, NULL, VALID_HOST, INVALID_USER, VALID_PASSWORD)), NoDatabaseName); + // Check for password file. + EXPECT_NO_THROW(HostMgr::addBackend(connectionString( + MYSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_FILE))); + HostMgr::delBackend("mysql"); + // Tidy up after the test destroyMySQLSchema(); } diff --git a/src/hooks/dhcp/mysql/tests/mysql_lease_mgr_unittest.cc b/src/hooks/dhcp/mysql/tests/mysql_lease_mgr_unittest.cc index dab6d563cc..a7a3ecc295 100644 --- a/src/hooks/dhcp/mysql/tests/mysql_lease_mgr_unittest.cc +++ b/src/hooks/dhcp/mysql/tests/mysql_lease_mgr_unittest.cc @@ -206,6 +206,14 @@ TEST(MySqlOpenTest, OpenDatabase) { MYSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, DEFAULT_PASSWORD)), isc::data::DefaultCredential); + EXPECT_THROW(LeaseMgrFactory::create(connectionString( + MYSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, NOT_EXIST_FILE)), + BadValue); + + EXPECT_THROW(LeaseMgrFactory::create(connectionString( + MYSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, INVALID_FILE)), + DbOpenError); + // Check for invalid timeouts EXPECT_THROW(LeaseMgrFactory::create(connectionString( MYSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD, INVALID_TIMEOUT_1)), @@ -217,9 +225,13 @@ TEST(MySqlOpenTest, OpenDatabase) { // Check for missing parameters EXPECT_THROW(LeaseMgrFactory::create(connectionString( - MYSQL_VALID_TYPE, NULL, VALID_HOST, VALID_USER, VALID_PASSWORD)), + MYSQL_VALID_TYPE, 0, VALID_HOST, VALID_USER, VALID_PASSWORD)), NoDatabaseName); + // Check for password file. + EXPECT_NO_THROW(LeaseMgrFactory::create(connectionString( + MYSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_FILE))); + // Check for SSL/TLS support. if (hasMySQLTls()) { EXPECT_NO_THROW(LeaseMgrFactory::create(connectionString( diff --git a/src/hooks/dhcp/pgsql/tests/pgsql_host_data_source_unittest.cc b/src/hooks/dhcp/pgsql/tests/pgsql_host_data_source_unittest.cc index d0593473fa..0c7b1415f4 100644 --- a/src/hooks/dhcp/pgsql/tests/pgsql_host_data_source_unittest.cc +++ b/src/hooks/dhcp/pgsql/tests/pgsql_host_data_source_unittest.cc @@ -240,6 +240,12 @@ TEST(PgSqlHostDataSource, OpenDatabase) { EXPECT_THROW(HostMgr::addBackend(connectionString( PGSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, DEFAULT_PASSWORD)), DefaultCredential); + EXPECT_THROW(HostMgr::addBackend(connectionString( + PGSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, NOT_EXIST_FILE)), + BadValue); + EXPECT_THROW(HostMgr::addBackend(connectionString( + PGSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, INVALID_FILE)), + DbOpenError); EXPECT_THROW(HostMgr::addBackend(connectionString( PGSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD, INVALID_TIMEOUT_1)), DbInvalidTimeout); @@ -252,9 +258,13 @@ TEST(PgSqlHostDataSource, OpenDatabase) { // Check for missing parameters EXPECT_THROW(HostMgr::addBackend(connectionString( - PGSQL_VALID_TYPE, NULL, VALID_HOST, INVALID_USER, VALID_PASSWORD)), + PGSQL_VALID_TYPE, 0, VALID_HOST, INVALID_USER, VALID_PASSWORD)), NoDatabaseName); + // Check for password file. + EXPECT_NO_THROW(HostMgr::addBackend(connectionString( + PGSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_FILE))); + // Check for SSL/TLS support. if (hasPgSQLTls()) { EXPECT_NO_THROW(HostMgr::addBackend(connectionString( @@ -342,6 +352,12 @@ TEST(PgSqlHostDataSource, OpenDatabaseMultiThreading) { EXPECT_THROW(HostMgr::addBackend(connectionString( PGSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, DEFAULT_PASSWORD)), DefaultCredential); + EXPECT_THROW(HostMgr::addBackend(connectionString( + PGSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, NOT_EXIST_FILE)), + BadValue); + EXPECT_THROW(HostMgr::addBackend(connectionString( + PGSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, INVALID_FILE)), + DbOpenError); EXPECT_THROW(HostMgr::addBackend(connectionString( PGSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD, INVALID_TIMEOUT_1)), DbInvalidTimeout); @@ -354,9 +370,13 @@ TEST(PgSqlHostDataSource, OpenDatabaseMultiThreading) { // Check for missing parameters EXPECT_THROW(HostMgr::addBackend(connectionString( - PGSQL_VALID_TYPE, NULL, VALID_HOST, INVALID_USER, VALID_PASSWORD)), + PGSQL_VALID_TYPE, 0, VALID_HOST, INVALID_USER, VALID_PASSWORD)), NoDatabaseName); + // Check for password file. + EXPECT_NO_THROW(HostMgr::addBackend(connectionString( + PGSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_FILE))); + // Tidy up after the test destroyPgSQLSchema(); } diff --git a/src/hooks/dhcp/pgsql/tests/pgsql_lease_mgr_unittest.cc b/src/hooks/dhcp/pgsql/tests/pgsql_lease_mgr_unittest.cc index 2e99154622..cd13460ccf 100644 --- a/src/hooks/dhcp/pgsql/tests/pgsql_lease_mgr_unittest.cc +++ b/src/hooks/dhcp/pgsql/tests/pgsql_lease_mgr_unittest.cc @@ -211,6 +211,15 @@ TEST(PgSqlOpenTest, OpenDatabase) { PGSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, DEFAULT_PASSWORD)), isc::data::DefaultCredential); + EXPECT_THROW(LeaseMgrFactory::create(connectionString( + PGSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, NOT_EXIST_FILE)), + BadValue); + + // See invalid password comment. + EXPECT_THROW(LeaseMgrFactory::create(connectionString( + PGSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, INVALID_FILE)), + DbOpenError); + // Check for invalid timeouts EXPECT_THROW(LeaseMgrFactory::create(connectionString( PGSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_PASSWORD, INVALID_TIMEOUT_1)), @@ -222,9 +231,13 @@ TEST(PgSqlOpenTest, OpenDatabase) { // Check for missing parameters EXPECT_THROW(LeaseMgrFactory::create(connectionString( - PGSQL_VALID_TYPE, NULL, VALID_HOST, VALID_USER, VALID_PASSWORD)), + PGSQL_VALID_TYPE, 0, VALID_HOST, VALID_USER, VALID_PASSWORD)), NoDatabaseName); + // Check for password file. + EXPECT_NO_THROW(LeaseMgrFactory::create(connectionString( + PGSQL_VALID_TYPE, VALID_NAME, VALID_HOST, VALID_USER, VALID_FILE))); + // Check for SSL/TLS support. if (hasPgSQLTls()) { EXPECT_NO_THROW(LeaseMgrFactory::create(connectionString( @@ -1390,19 +1403,19 @@ TEST_F(PgSqlLeaseMgrTest, updateStatsOn4DifferentSubnet) { testUpdateStatsOn4DifferentSubnet(); } -TEST_F(PgSqlLeaseMgrTest, updateStatsOn6SameSubnet) { +TEST_F(PgSqlLeaseMgrTest, updateStatsOn6SameSubnet) { testUpdateStatsOn6SameSubnet(); } -TEST_F(PgSqlLeaseMgrTest, updateStatsOn6SameSubnetPD) { +TEST_F(PgSqlLeaseMgrTest, updateStatsOn6SameSubnetPD) { testUpdateStatsOn6SameSubnetPD(); } -TEST_F(PgSqlLeaseMgrTest, updateStatsOn6DifferentSubnet) { +TEST_F(PgSqlLeaseMgrTest, updateStatsOn6DifferentSubnet) { testUpdateStatsOn6DifferentSubnet(); } -TEST_F(PgSqlLeaseMgrTest, updateStatsOn6DifferentSubnetPD) { +TEST_F(PgSqlLeaseMgrTest, updateStatsOn6DifferentSubnetPD) { testUpdateStatsOn6DifferentSubnetPD(); } diff --git a/src/lib/database/testutils/bad-password b/src/lib/database/testutils/bad-password new file mode 100644 index 0000000000..323fae03f4 --- /dev/null +++ b/src/lib/database/testutils/bad-password @@ -0,0 +1 @@ +foobar diff --git a/src/lib/database/testutils/meson.build b/src/lib/database/testutils/meson.build index f11417a4d7..60e4d2de3c 100644 --- a/src/lib/database/testutils/meson.build +++ b/src/lib/database/testutils/meson.build @@ -2,10 +2,14 @@ if not TESTS_OPT.enabled() subdir_done() endif +current_source_dir = meson.current_source_dir() kea_database_testutils_lib = static_library( 'kea-database-testutils', 'schema.cc', - cpp_args: [f'-DTEST_CA_DIR="@TEST_CA_DIR@"'], + cpp_args: [ + f'-DTEST_CA_DIR="@TEST_CA_DIR@"', + f'-DFILE_DIR="@current_source_dir@"', + ], dependencies: [GTEST_DEP], include_directories: [include_directories('.')] + INCLUDES, ) diff --git a/src/lib/database/testutils/password b/src/lib/database/testutils/password new file mode 100644 index 0000000000..eadbb15e84 --- /dev/null +++ b/src/lib/database/testutils/password @@ -0,0 +1 @@ +keatest diff --git a/src/lib/database/testutils/schema.cc b/src/lib/database/testutils/schema.cc index 69e2841ab1..6530ff0f70 100644 --- a/src/lib/database/testutils/schema.cc +++ b/src/lib/database/testutils/schema.cc @@ -35,6 +35,9 @@ const char* INVALID_USER = "user=invaliduser"; const char* VALID_PASSWORD = "password=keatest"; const char* INVALID_PASSWORD = "password=invalid"; const char* DEFAULT_PASSWORD = "password=1234"; +const char* VALID_FILE = "password-file=" FILE_DIR "/password"; +const char* NOT_EXIST_FILE = "password-file=" FILE_DIR "/does-not-exit"; +const char* INVALID_FILE = "password-file=" FILE_DIR "/bad-password"; const char* VALID_TIMEOUT = "connect-timeout=10"; const char* INVALID_TIMEOUT_1 = "connect-timeout=foo"; const char* INVALID_TIMEOUT_2 = "connect-timeout=-17"; diff --git a/src/lib/database/testutils/schema.h b/src/lib/database/testutils/schema.h index 830f1a5e53..963d84533f 100644 --- a/src/lib/database/testutils/schema.h +++ b/src/lib/database/testutils/schema.h @@ -29,6 +29,9 @@ extern const char* INVALID_USER; extern const char* VALID_PASSWORD; extern const char* INVALID_PASSWORD; extern const char* DEFAULT_PASSWORD; +extern const char* VALID_FILE; +extern const char* NOT_EXIST_FILE; +extern const char* INVALID_FILE; extern const char* VALID_TIMEOUT; extern const char* INVALID_TIMEOUT_1; extern const char* INVALID_TIMEOUT_2; diff --git a/src/lib/pgsql/pgsql_connection.cc b/src/lib/pgsql/pgsql_connection.cc index d621be6008..20409ba53f 100644 --- a/src/lib/pgsql/pgsql_connection.cc +++ b/src/lib/pgsql/pgsql_connection.cc @@ -409,6 +409,7 @@ PgSqlConnection::getConnParametersInternal(bool logging) { if (!spassword_file.empty()) { // This can throw. spassword = util::file::getContent(spassword_file); + dbconnparameters += " password = '" + spassword + "'"; } if (!spassword.empty()) { // Refuse default password.