Skip to content

Commit 570fbd9

Browse files
committed
WL#15154 patch #9 Implement rules for node startup
If a data node starts up with RequireCertificate, it must have a valid TLS certificate. This adds three new tests: testMgmd -n NdbdWithoutCertificate testMgmd -n NdbdWithCertificate testMgmd -n NdbdWithExpiredCertificate Change-Id: I23cb96e14136c78cc295d586b044a99b13ec50bc
1 parent e3b5576 commit 570fbd9

File tree

5 files changed

+226
-28
lines changed

5 files changed

+226
-28
lines changed

storage/ndb/include/portlib/ndb_openssl_version.h

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,17 @@
2626
In general, OpenSSL 1.1 is required for the availability of TLS 1.3.
2727
1.1.1d is chosen as a 1.1 release that is mature, but not unreasonably new
2828
(about three years old at the time the TLS feature is released).
29-
*/
30-
31-
#define NDB_TLS_MINIMUM_OPENSSL 0x1010104fL
29+
This version is represented as 0x1010104fL
3230
33-
/* Ubuntu 18.04 maintains an OpenSSL 1.1 tree that backports
31+
Ubuntu 18.04 maintains an OpenSSL 1.1 tree that backports
3432
patches from OpenSSL 1.1 but is always identified as
35-
"OpenSSL 1.1.1 Sep 2018."
36-
*/
37-
#define UBUNTU18_OPENSSL_VER_ID 0x1010100fL
33+
"OpenSSL 1.1.1 Sep 2018." This version is also usable.
34+
It version is represented as 0x1010100fL
3835
36+
Use the Ubuntu 18.04 OpenSSL version number as the minimum
37+
supported version for NDB TLS.
38+
*/
39+
#define NDB_TLS_MINIMUM_OPENSSL 0x1010100fL
3940

4041
/* NDB_OPENSSL_TOO_OLD is used as an error return value from functions
4142
to report a OpenSSL library version less than NDB_TLS_MINIMUM_OPENSSL

storage/ndb/src/common/util/NdbSocket.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,7 @@
3333
#include "portlib/ndb_openssl_version.h"
3434

3535
static constexpr bool openssl_version_ok =
36-
((OPENSSL_VERSION_NUMBER >= NDB_TLS_MINIMUM_OPENSSL) ||
37-
(OPENSSL_VERSION_NUMBER == UBUNTU18_OPENSSL_VER_ID));
36+
(OPENSSL_VERSION_NUMBER >= NDB_TLS_MINIMUM_OPENSSL);
3837

3938
/* Utility Functions */
4039

storage/ndb/src/common/util/NodeCertificate.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1351,8 +1351,7 @@ static constexpr bool isWin32 = 0;
13511351
#endif
13521352

13531353
static constexpr bool openssl_version_ok =
1354-
((OPENSSL_VERSION_NUMBER >= NDB_TLS_MINIMUM_OPENSSL) ||
1355-
(OPENSSL_VERSION_NUMBER == UBUNTU18_OPENSSL_VER_ID));
1354+
(OPENSSL_VERSION_NUMBER >= NDB_TLS_MINIMUM_OPENSSL);
13561355

13571356
/*
13581357
Test name parsing

storage/ndb/src/kernel/ndbd.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,6 +1171,22 @@ ndbd_run(bool foreground, int report_fd,
11711171

11721172
globalTransporterRegistry.init_tls(tls_search_path, NODE_TYPE_DB, true);
11731173

1174+
const ndb_mgm_configuration_iterator *p =
1175+
globalEmulatorData.theConfiguration->getOwnConfigIterator();
1176+
require(p != nullptr);
1177+
1178+
{
1179+
Uint32 require_cert = 0;
1180+
ndb_mgm_get_int_parameter(p, CFG_NODE_REQUIRE_CERT, &require_cert);
1181+
if(require_cert && ! globalTransporterRegistry.hasTlsCert())
1182+
{
1183+
g_eventLogger->error(
1184+
"Shutting down. This node does not have a valid TLS certificate.");
1185+
stop_async_log_func(log_threadvar, thread_args);
1186+
ndbd_exit(-1);
1187+
}
1188+
}
1189+
11741190
/**
11751191
Printout various information about the threads in the
11761192
run-time environment
@@ -1213,10 +1229,6 @@ ndbd_run(bool foreground, int report_fd,
12131229

12141230
log_memusage("Global memory pools allocated");
12151231

1216-
const ndb_mgm_configuration_iterator *p =
1217-
globalEmulatorData.theConfiguration->getOwnConfigIterator();
1218-
require(p != nullptr);
1219-
12201232
bool have_password_option = g_filesystem_password_state.have_password_option();
12211233
Uint32 encrypted_file_system = 0;
12221234
ndb_mgm_get_int_parameter(p, CFG_DB_ENCRYPTED_FILE_SYSTEM,

storage/ndb/test/ndbapi/testMgmd.cpp

Lines changed: 200 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727
#include <iostream>
2828
#include <string>
2929

30+
#include "util/ndb_openssl3_compat.h"
3031
#include "util/require.h"
32+
#include "util/TlsKeyManager.hpp"
3133
#include <NDBT.hpp>
3234
#include <NDBT_Test.hpp>
3335
#include <portlib/NdbDir.hpp>
@@ -167,10 +169,8 @@ class Mgmd
167169
return (m_proc != NULL);
168170
}
169171

170-
bool start_from_config_ini(const char* working_dir,
171-
const char* first_extra_arg = NULL, ...)
172+
void common_args(NdbProcess::Args & args, const char * working_dir)
172173
{
173-
NdbProcess::Args args;
174174
args.add("--no-defaults");
175175
args.add("--configdir=", working_dir);
176176
args.add("-f config.ini");
@@ -181,6 +181,13 @@ class Mgmd
181181
args.add("--nodaemon");
182182
args.add("--log-name=", name());
183183
args.add("--verbose");
184+
}
185+
186+
bool start_from_config_ini(const char* working_dir,
187+
const char* first_extra_arg = NULL, ...)
188+
{
189+
NdbProcess::Args args;
190+
common_args(args, working_dir);
184191

185192
if (first_extra_arg)
186193
{
@@ -238,7 +245,7 @@ class Mgmd
238245
return false; // Can't kill with -9 -> fatal error
239246
}
240247
int ret;
241-
if (!m_proc->wait(ret, 300))
248+
if (!m_proc->wait(ret, 1000))
242249
{
243250
fprintf(stderr, "Failed to wait for process %s\n", name());
244251
return false; // Can't wait after kill with -9 -> fatal error
@@ -387,20 +394,26 @@ class MgmdProcessList : public Vector<Mgmd*>
387394
class Ndbd : public Mgmd
388395
{
389396
public:
390-
Ndbd(int nodeid) : Mgmd(nodeid)
397+
Ndbd(int nodeid) : Mgmd(nodeid), m_args()
391398
{
399+
m_args.add("--ndb-nodeid=", m_nodeid);
400+
m_args.add("--foreground");
392401
m_name.assfmt("ndbd_%d", nodeid);
393402
NDBT_find_ndbd(m_exe);
394403
}
395404

405+
NdbProcess::Args & args() { return m_args; }
406+
407+
void set_connect_string(BaseString connect_string)
408+
{
409+
m_args.add("-c");
410+
m_args.add(connect_string.c_str());
411+
}
412+
396413
bool start(const char *working_dir, BaseString connect_string)
397414
{
398-
NdbProcess::Args args;
399-
args.add("-c");
400-
args.add(connect_string.c_str());
401-
args.add("--ndb-nodeid=", m_nodeid);
402-
args.add("--foreground");
403-
return Mgmd::start(working_dir, args);
415+
set_connect_string(connect_string);
416+
return Mgmd::start(working_dir, m_args);
404417
}
405418

406419
bool wait_started(NdbMgmHandle & mgm_handle,
@@ -435,6 +448,8 @@ class Ndbd : public Mgmd
435448
return false;
436449
}
437450

451+
private:
452+
NdbProcess::Args m_args;
438453
};
439454

440455
static
@@ -447,9 +462,65 @@ bool create_CA(NDBT_Workingdir & wd, const BaseString &exe)
447462
args.add("--create-CA");
448463
args.add("--CA-search-path=", wd.path());
449464
NdbProcess * proc = NdbProcess::create("Create CA", exe, wd.path(), args);
450-
bool r = proc->wait(ret, 1000);
465+
bool r = proc->wait(ret, 3000);
466+
delete proc;
467+
468+
return (r && (ret == 0));
469+
}
470+
471+
static
472+
bool sign_tls_keys(NDBT_Workingdir & wd)
473+
{
474+
int ret;
475+
BaseString cfg_path = path(wd.path(), "config.ini", nullptr);
476+
477+
/* Find executable */
478+
BaseString exe;
479+
NDBT_find_sign_keys(exe);
480+
481+
/* Create CA */
482+
if(! create_CA(wd, exe))
483+
return false;
484+
485+
/* Create keys and certificates for all nodes in config */
486+
NdbProcess::Args args;
487+
args.add("--config-file=", cfg_path.c_str());
488+
args.add("--passphrase=", "Trondheim");
489+
args.add("--ndb-tls-search-path=", wd.path());
490+
args.add("--create-key");
491+
NdbProcess * proc = NdbProcess::create("Create Keys", exe, wd.path(), args);
492+
bool r = proc->wait(ret, 3000);
451493
delete proc;
494+
return (r && (ret == 0));
495+
}
452496

497+
static
498+
bool create_expired_cert(NDBT_Workingdir & wd)
499+
{
500+
int ret;
501+
502+
BaseString cfg_path = path(wd.path(), "config.ini", nullptr);
503+
504+
/* Find executable */
505+
BaseString exe;
506+
NDBT_find_sign_keys(exe);
507+
508+
/* Create CA */
509+
if(! create_CA(wd, exe))
510+
return false;
511+
512+
/* Create an expired certificate for a data node */
513+
NdbProcess::Args args;
514+
args.add("--create-key");
515+
args.add("--ndb-tls-search-path=", wd.path());
516+
args.add("--passphrase=", "Trondheim");
517+
args.add("-l"); // no-config mode
518+
args.add("-t db"); // type db
519+
args.add("--duration=", "-50000"); // negative seconds; already expired
520+
521+
NdbProcess * proc = NdbProcess::create("Create Keys", exe, wd.path(), args);
522+
bool r = proc->wait(ret, 3000);
523+
delete proc;
453524
return (r && (ret == 0));
454525
}
455526

@@ -1851,7 +1922,7 @@ runTestSshKeySigning(NDBT_Context* ctx, NDBT_Step* step)
18511922
args.add("--create-key");
18521923
args.add("--remote-CA-host=", "localhost");
18531924
NdbProcess * proc = NdbProcess::create("Create Keys", exe, wd.path(), args);
1854-
bool r = proc->wait(ret, 1500);
1925+
bool r = proc->wait(ret, 3000);
18551926
CHECK(r);
18561927
if(! r) proc->stop();
18571928
delete proc;
@@ -1860,6 +1931,101 @@ runTestSshKeySigning(NDBT_Context* ctx, NDBT_Step* step)
18601931
return NDBT_OK;
18611932
}
18621933

1934+
int
1935+
runTestNdbdWithoutCert(NDBT_Context* ctx, NDBT_Step* step)
1936+
{
1937+
NDBT_Workingdir wd("test_mgmd"); // temporary working directory
1938+
BaseString cfg_path = path(wd.path(), "config.ini", nullptr);
1939+
1940+
Properties config = ConfigFactory::create();
1941+
Properties db;
1942+
db.put("RequireCertificate", "true");
1943+
config.put("DB Default", & db);
1944+
1945+
CHECK(ConfigFactory::write_config_ini(config, cfg_path.c_str()));
1946+
1947+
Mgmd mgmd(1);
1948+
Ndbd ndbd(2);
1949+
1950+
CHECK(mgmd.start_from_config_ini(wd.path())); // Start management node
1951+
CHECK(mgmd.connect(config)); // Connect to management node
1952+
CHECK(mgmd.wait_confirmed_config()); // Wait for configuration
1953+
1954+
int exit_code; // Start ndbd; it will fail
1955+
CHECK(ndbd.start(wd.path(), mgmd.connectstring(config)));
1956+
CHECK(ndbd.wait(exit_code, 100)); // should fail quickly
1957+
require(exit_code == 255);
1958+
1959+
CHECK(mgmd.stop());
1960+
return NDBT_OK;
1961+
}
1962+
1963+
int
1964+
runTestNdbdWithExpiredCert(NDBT_Context* ctx, NDBT_Step* step)
1965+
{
1966+
NDBT_Workingdir wd("test_tls"); // temporary working directory
1967+
1968+
BaseString cfg_path = path(wd.path(), "config.ini", nullptr);
1969+
1970+
Properties config = ConfigFactory::create();
1971+
Properties db;
1972+
db.put("RequireCertificate", "true");
1973+
config.put("DB Default", & db);
1974+
CHECK(ConfigFactory::write_config_ini(config, cfg_path.c_str()));
1975+
1976+
CHECK(create_expired_cert(wd));
1977+
1978+
Mgmd mgmd(1);
1979+
Ndbd ndbd(2);
1980+
1981+
CHECK(mgmd.start_from_config_ini(wd.path())); // Start management node
1982+
CHECK(mgmd.connect(config)); // Connect to management node
1983+
CHECK(mgmd.wait_confirmed_config()); // Wait for configuration
1984+
1985+
ndbd.args().add("--ndb-tls-search-path=", wd.path());
1986+
ndbd.start(wd.path(), mgmd.connectstring(config)); // Start data node
1987+
1988+
int exit_code;
1989+
CHECK(ndbd.wait(exit_code, 100)); // should fail quickly
1990+
CHECK(exit_code == 255);
1991+
1992+
CHECK(mgmd.stop());
1993+
return NDBT_OK;
1994+
}
1995+
1996+
int
1997+
runTestNdbdWithCert(NDBT_Context* ctx, NDBT_Step* step)
1998+
{
1999+
NDBT_Workingdir wd("test_tls"); // temporary working directory
2000+
2001+
BaseString cfg_path = path(wd.path(), "config.ini", nullptr);
2002+
Properties config = ConfigFactory::create();
2003+
Properties db;
2004+
db.put("RequireCertificate", "true");
2005+
config.put("DB Default", & db);
2006+
CHECK(ConfigFactory::write_config_ini(config, cfg_path.c_str()));
2007+
2008+
CHECK(sign_tls_keys(wd));
2009+
2010+
Mgmd mgmd(1);
2011+
Ndbd ndbd(2);
2012+
2013+
NdbProcess::Args mgmdArgs;
2014+
mgmd.common_args(mgmdArgs, wd.path());
2015+
mgmdArgs.add("--ndb-tls-search-path=", wd.path());
2016+
2017+
CHECK(mgmd.start(wd.path(), mgmdArgs)); // Start management node
2018+
CHECK(mgmd.connect(config)); // Connect to management node
2019+
CHECK(mgmd.wait_confirmed_config()); // Wait for configuration
2020+
2021+
ndbd.args().add("--ndb-tls-search-path=", wd.path());
2022+
ndbd.start(wd.path(), mgmd.connectstring(config)); // Start data node
2023+
NdbMgmHandle handle = mgmd.handle();
2024+
CHECK(ndbd.wait_started(handle));
2025+
2026+
CHECK(mgmd.stop());
2027+
return NDBT_OK;
2028+
}
18632029

18642030
NDBT_TESTSUITE(testMgmd);
18652031
DRIVER(DummyDriver); /* turn off use of NdbApi */
@@ -1955,12 +2121,33 @@ TESTCASE("MultiMGMDDisconnection",
19552121
INITIALIZER(runTestMultiMGMDDisconnection);
19562122
}
19572123

2124+
#if OPENSSL_VERSION_NUMBER >= NDB_TLS_MINIMUM_OPENSSL
2125+
19582126
TESTCASE("SshKeySigning",
19592127
"Test remote key signing over ssh using ndb_sign_keys")
19602128
{
19612129
INITIALIZER(runTestSshKeySigning);
19622130
}
19632131

2132+
TESTCASE("NdbdWithoutCertificate",
2133+
"Test data node startup with TLS required but no certificate")
2134+
{
2135+
INITIALIZER(runTestNdbdWithoutCert)
2136+
}
2137+
2138+
TESTCASE("NdbdWithExpiredCertificate",
2139+
"Test data node startup with expired certificate")
2140+
{
2141+
INITIALIZER(runTestNdbdWithExpiredCert)
2142+
}
2143+
2144+
TESTCASE("NdbdWithCertificate", "Test data node startup with certificate")
2145+
{
2146+
INITIALIZER(runTestNdbdWithCert)
2147+
}
2148+
2149+
#endif
2150+
19642151
NDBT_TESTSUITE_END(testMgmd)
19652152

19662153
int main(int argc, const char** argv)

0 commit comments

Comments
 (0)