Skip to content

Commit 024e2c8

Browse files
committed
WL#15524 Patch #8 TLS options in ndb_mgm
Support the standard --ndb-tls-search-path in ndb_mgm. Also support the --ndb-mgm-tls option, but in ndb_mgm, this enum option can take a third value, "deferred", that is not supported by other programs. Add a --test-tls option, which makes a single, verbose attempt to connect using TLS, then exits with status 0 on success or 1 on error. Add a new interactive command, "START TLS". This can perform the TLS negotiation that was deferred with --ndb-mgm-tls=deferred. Change-Id: I711245b723183ffe97f87dd0d7d15d2349730c77
1 parent 7e11997 commit 024e2c8

File tree

5 files changed

+118
-8
lines changed

5 files changed

+118
-8
lines changed

storage/ndb/include/mgmapi/mgmapi_config_parameters.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,5 +393,6 @@
393393

394394
#define CLIENT_TLS_RELAXED 0
395395
#define CLIENT_TLS_STRICT 1
396+
#define CLIENT_TLS_DEFERRED 2
396397

397398
#endif

storage/ndb/src/mgmclient/CommandInterpreter.cpp

Lines changed: 80 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <ndbd_exit_codes.h>
3030

3131
#include <util/BaseString.hpp>
32+
#include "util/TlsKeyManager.hpp"
3233
#include <util/Vector.hpp>
3334
#include <kernel/BlockNumbers.h>
3435
#include <kernel/signaldata/DumpStateOrd.hpp>
@@ -51,7 +52,9 @@ class CommandInterpreter {
5152
CommandInterpreter(const char* host,
5253
const char* default_prompt,
5354
int verbose,
54-
int connect_retry_delay);
55+
int connect_retry_delay,
56+
const char * tls_search_path,
57+
int tls_start_type);
5558
~CommandInterpreter();
5659

5760
int setDefaultBackupPassword(const char backup_password[]);
@@ -146,12 +149,14 @@ class CommandInterpreter {
146149
int *node_ids, int no_of_nodes);
147150
int executeCreateNodeGroup(char* parameters);
148151
int executeDropNodeGroup(char* parameters);
152+
int executeStartTls();
149153
const char* get_current_prompt() const
150154
{
151155
// return the current prompt
152156
return m_prompt;
153157
}
154158
public:
159+
int test_tls();
155160
bool connect(bool interactive);
156161
void disconnect(void);
157162

@@ -175,6 +180,7 @@ class CommandInterpreter {
175180
ExecuteFunction fun,
176181
const char * param);
177182

183+
TlsKeyManager m_tlsKeyManager;
178184
NdbMgmHandle m_mgmsrv;
179185
NdbMgmHandle m_mgmsrv2;
180186
const char *m_constr;
@@ -192,6 +198,7 @@ class CommandInterpreter {
192198
bool m_always_encrypt_backup;
193199
char m_onetime_backup_password[1024];
194200
bool m_onetime_backup_password_set;
201+
int m_tls_start_type;
195202
};
196203

197204
NdbMutex* print_mutex;
@@ -203,10 +210,12 @@ NdbMutex* print_mutex;
203210
#include "ndb_mgmclient.hpp"
204211

205212
Ndb_mgmclient::Ndb_mgmclient(const char *host, const char* default_prompt,
206-
int verbose, int connect_retry_delay)
213+
int verbose, int connect_retry_delay,
214+
const char * tls_search_path, int tls_start_type)
207215
{
208216
m_cmd= new CommandInterpreter(host, default_prompt,
209-
verbose, connect_retry_delay);
217+
verbose, connect_retry_delay,
218+
tls_search_path, tls_start_type);
210219
}
211220
Ndb_mgmclient::~Ndb_mgmclient()
212221
{
@@ -234,6 +243,11 @@ int Ndb_mgmclient::set_always_encrypt_backup(bool on) const
234243
return m_cmd->setAlwaysEncryptBackup(on);
235244
}
236245

246+
int Ndb_mgmclient::test_tls()
247+
{
248+
return m_cmd->test_tls();
249+
}
250+
237251
/*
238252
* The CommandInterpreter
239253
*/
@@ -265,6 +279,7 @@ static const char* helpText =
265279
"SHOW Print information about cluster\n"
266280
"CREATE NODEGROUP <id>,<id>... Add a Nodegroup containing nodes\n"
267281
"DROP NODEGROUP <NG> Drop nodegroup with id NG\n"
282+
"START TLS Start TLS on connection\n"
268283
"START BACKUP [<backup id>] [ENCRYPT [PASSWORD='<password>']] "
269284
"[SNAPSHOTSTART | SNAPSHOTEND] [NOWAIT | WAIT STARTED | WAIT COMPLETED]\n"
270285
" Start backup "
@@ -722,7 +737,9 @@ convert(const char* s, int& val) {
722737
*/
723738
CommandInterpreter::CommandInterpreter(const char *host,
724739
const char* default_prompt,
725-
int verbose, int connect_retry_delay) :
740+
int verbose, int connect_retry_delay,
741+
const char * tls_search_path,
742+
int tls_start_type) :
726743
m_constr(host),
727744
m_connected(false),
728745
m_verbose(verbose),
@@ -734,8 +751,10 @@ CommandInterpreter::CommandInterpreter(const char *host,
734751
m_prompt(default_prompt),
735752
m_default_backup_password(nullptr),
736753
m_always_encrypt_backup(false),
737-
m_onetime_backup_password_set(false)
754+
m_onetime_backup_password_set(false),
755+
m_tls_start_type(tls_start_type)
738756
{
757+
m_tlsKeyManager.init_mgm_client(tls_search_path);
739758
m_print_mutex= NdbMutex_Create();
740759
}
741760

@@ -996,6 +1015,13 @@ event_thread_run(void* p)
9961015
DBUG_RETURN(NULL);
9971016
}
9981017

1018+
int
1019+
CommandInterpreter::test_tls()
1020+
{
1021+
m_try_reconnect = 1;
1022+
return connect(false) ? 0 : 1;
1023+
}
1024+
9991025
bool
10001026
CommandInterpreter::connect(bool interactive)
10011027
{
@@ -1010,6 +1036,13 @@ CommandInterpreter::connect(bool interactive)
10101036
exit(-1);
10111037
}
10121038

1039+
if((m_tls_start_type == CLIENT_TLS_STRICT) &&
1040+
(m_tlsKeyManager.ctx() == nullptr))
1041+
{
1042+
ndbout_c("No valid certificate.");
1043+
exit(-1);
1044+
}
1045+
10131046
if (interactive) {
10141047
m_mgmsrv2 = ndb_mgm_create_handle();
10151048
if(m_mgmsrv2 == NULL) {
@@ -1045,6 +1078,29 @@ CommandInterpreter::connect(bool interactive)
10451078
DBUG_RETURN(m_connected); // couldn't connect, always false
10461079
}
10471080

1081+
ndb_mgm_set_ssl_ctx(m_mgmsrv, m_tlsKeyManager.ctx());
1082+
1083+
if(m_tls_start_type != CLIENT_TLS_DEFERRED)
1084+
{
1085+
if(ndb_mgm_start_tls(m_mgmsrv) != 0)
1086+
{
1087+
if(interactive)
1088+
{
1089+
ndbout_c("Connected to server, but failed to start TLS.");
1090+
}
1091+
1092+
if(m_tls_start_type == CLIENT_TLS_STRICT)
1093+
{
1094+
printError();
1095+
ndb_mgm_destroy_handle(&m_mgmsrv);
1096+
if(interactive)
1097+
{
1098+
ndb_mgm_destroy_handle(&m_mgmsrv2);
1099+
}
1100+
DBUG_RETURN(m_connected);
1101+
}
1102+
}
1103+
}
10481104

10491105
const char *host= ndb_mgm_get_connected_host(m_mgmsrv);
10501106
unsigned port= ndb_mgm_get_connected_port(m_mgmsrv);
@@ -1056,6 +1112,10 @@ CommandInterpreter::connect(bool interactive)
10561112
{
10571113
DBUG_PRINT("info",("2:ndb connected to Management Server ok at: %s:%d",
10581114
host, port));
1115+
if(m_tls_start_type != CLIENT_TLS_DEFERRED)
1116+
{
1117+
ndb_mgm_start_tls(m_mgmsrv2);
1118+
}
10591119
assert(m_event_thread == NULL);
10601120
assert(do_event_thread == 0);
10611121
do_event_thread= 0;
@@ -1363,6 +1423,12 @@ CommandInterpreter::execute_impl(const char *_line, bool interactive)
13631423
executeClusterLog(allAfterFirstToken);
13641424
DBUG_RETURN(true);
13651425
}
1426+
else if(native_strcasecmp(firstToken, "START") == 0 &&
1427+
allAfterFirstToken != NULL &&
1428+
native_strncasecmp(allAfterFirstToken, "TLS", 3) == 0) {
1429+
m_error = executeStartTls();
1430+
DBUG_RETURN(true);
1431+
}
13661432
else if(native_strcasecmp(firstToken, "START") == 0 &&
13671433
allAfterFirstToken != NULL &&
13681434
native_strncasecmp(allAfterFirstToken, "BACKUP", sizeof("BACKUP") - 1) == 0){
@@ -2057,6 +2123,15 @@ CommandInterpreter::executeConnect(char* parameters, bool interactive)
20572123
return 0;
20582124
}
20592125

2126+
int
2127+
CommandInterpreter::executeStartTls()
2128+
{
2129+
int result = ndb_mgm_start_tls(m_mgmsrv);
2130+
if(result == 0) ndbout_c("TLS started.");
2131+
else printError();
2132+
return result;
2133+
}
2134+
20602135
//*****************************************************************************
20612136
//*****************************************************************************
20622137
void

storage/ndb/src/mgmclient/main.cpp

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ const char *load_default_groups[]= { "mysql_cluster","ndb_mgm",0 };
5353
static char *opt_execute_str= 0;
5454
static char *opt_prompt= 0;
5555
static unsigned opt_verbose = 1;
56+
static bool opt_test_tls = true;
5657

5758
static ndb_password_state opt_backup_password_state("backup", nullptr);
5859
static ndb_password_option opt_backup_password(opt_backup_password_state);
@@ -61,6 +62,12 @@ static ndb_password_from_stdin_option opt_backup_password_from_stdin(
6162

6263
static bool opt_encrypt_backup = false;
6364

65+
/* ndb_mgm uses an extended form of the --ndb-mgm-tls enum, which accepts
66+
an extra option, "disabled"
67+
*/
68+
static const char * tls_names[] = { "relaxed", "strict", "deferred", nullptr };
69+
static TYPELIB mgm_tls_typelib = { 3 , "TLS requirement", tls_names, nullptr };
70+
6471
static struct my_option my_long_options[] =
6572
{
6673
NdbStdOpt::usage,
@@ -72,6 +79,7 @@ static struct my_option my_long_options[] =
7279
NdbStdOpt::ndb_nodeid,
7380
NdbStdOpt::connect_retry_delay,
7481
NdbStdOpt::connect_retries,
82+
NdbStdOpt::tls_search_path,
7583
NDB_STD_OPT_DEBUG
7684
{ "backup-password", NDB_OPT_NOSHORT, "Encryption password for backup file",
7785
nullptr, nullptr, nullptr, GET_PASSWORD, OPT_ARG,
@@ -96,6 +104,13 @@ static struct my_option my_long_options[] =
96104
{"try-reconnect", 't', "Same as --connect-retries",
97105
&opt_connect_retries, nullptr, nullptr, GET_INT, REQUIRED_ARG,
98106
12, 0, INT_MAX, nullptr, 0, nullptr},
107+
{ "ndb-mgm-tls", NDB_OPT_NOSHORT,
108+
"MGM client TLS requirement level",
109+
&opt_mgm_tls, nullptr, &mgm_tls_typelib, GET_ENUM, REQUIRED_ARG,
110+
0, 0, 2, nullptr, 0, nullptr},
111+
{ "test-tls", NDB_OPT_NOSHORT, "Connect using TLS then exit",
112+
&opt_test_tls, nullptr, nullptr, GET_BOOL, NO_ARG,
113+
0, 0, 0, nullptr, 0, nullptr},
99114
NdbStdOpt::end_of_options
100115
};
101116

@@ -172,10 +187,19 @@ int main(int argc, char** argv){
172187
opt_prompt= 0;
173188
}
174189

190+
int tls_option = opt_mgm_tls;
191+
if(opt_test_tls)
192+
{
193+
tls_option = CLIENT_TLS_STRICT;
194+
opt_verbose = 1;
195+
}
196+
175197
Ndb_mgmclient* com = new Ndb_mgmclient(connect_str.c_str(),
176198
"ndb_mgm> ",
177199
opt_verbose,
178-
opt_connect_retry_delay);
200+
opt_connect_retry_delay,
201+
opt_tls_search_path,
202+
tls_option);
179203
com->set_always_encrypt_backup(opt_encrypt_backup);
180204
if (opt_backup_password_state.get_password())
181205
{
@@ -196,6 +220,12 @@ int main(int argc, char** argv){
196220
prompt_args.append(opt_prompt);
197221
com->execute(prompt_args.c_str(), opt_connect_retries, 0);
198222
}
223+
224+
if (opt_test_tls)
225+
{
226+
return com->test_tls();
227+
}
228+
199229
int ret= 0;
200230
BaseString histfile;
201231
if (!opt_execute_str)

storage/ndb/src/mgmclient/ndb_mgmclient.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,16 @@ class Ndb_mgmclient
3232
Ndb_mgmclient(const char* host,
3333
const char* default_prompt,
3434
int verbose,
35-
int connect_retry_delay);
35+
int connect_retry_delay,
36+
const char * tls_search_path,
37+
int tls_start_type);
3638
~Ndb_mgmclient();
3739
bool execute(const char *line, int try_reconnect = -1,
3840
bool interactive = true, int *error = NULL);
3941
const char* get_current_prompt() const;
4042
int set_default_backup_password(const char backup_password[]) const;
4143
int set_always_encrypt_backup(bool on) const;
44+
int test_tls();
4245
private:
4346
CommandInterpreter *m_cmd;
4447
};

storage/ndb/src/mgmsrv/main.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,8 @@ static void mgmd_run()
304304
con_str.appfmt("host=%s %d", opts.bind_address, port);
305305
else
306306
con_str.appfmt("localhost:%d", port);
307-
Ndb_mgmclient com(con_str.c_str(), "ndb_mgm> ", 1, 5);
307+
Ndb_mgmclient com(con_str.c_str(), "ndb_mgm> ", 1, 5, opt_tls_search_path,
308+
CLIENT_TLS_RELAXED);
308309
while(!g_StopServer){
309310
if (!read_and_execute(&com, "ndb_mgm> ", 1))
310311
g_StopServer = true;

0 commit comments

Comments
 (0)