Skip to content

Commit

Permalink
WL#15524 Patch #8 TLS options in ndb_mgm
Browse files Browse the repository at this point in the history
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
  • Loading branch information
jdduncan committed Jul 21, 2023
1 parent 7e11997 commit 024e2c8
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 8 deletions.
1 change: 1 addition & 0 deletions storage/ndb/include/mgmapi/mgmapi_config_parameters.h
Original file line number Diff line number Diff line change
Expand Up @@ -393,5 +393,6 @@

#define CLIENT_TLS_RELAXED 0
#define CLIENT_TLS_STRICT 1
#define CLIENT_TLS_DEFERRED 2

#endif
85 changes: 80 additions & 5 deletions storage/ndb/src/mgmclient/CommandInterpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <ndbd_exit_codes.h>

#include <util/BaseString.hpp>
#include "util/TlsKeyManager.hpp"
#include <util/Vector.hpp>
#include <kernel/BlockNumbers.h>
#include <kernel/signaldata/DumpStateOrd.hpp>
Expand All @@ -51,7 +52,9 @@ class CommandInterpreter {
CommandInterpreter(const char* host,
const char* default_prompt,
int verbose,
int connect_retry_delay);
int connect_retry_delay,
const char * tls_search_path,
int tls_start_type);
~CommandInterpreter();

int setDefaultBackupPassword(const char backup_password[]);
Expand Down Expand Up @@ -146,12 +149,14 @@ class CommandInterpreter {
int *node_ids, int no_of_nodes);
int executeCreateNodeGroup(char* parameters);
int executeDropNodeGroup(char* parameters);
int executeStartTls();
const char* get_current_prompt() const
{
// return the current prompt
return m_prompt;
}
public:
int test_tls();
bool connect(bool interactive);
void disconnect(void);

Expand All @@ -175,6 +180,7 @@ class CommandInterpreter {
ExecuteFunction fun,
const char * param);

TlsKeyManager m_tlsKeyManager;
NdbMgmHandle m_mgmsrv;
NdbMgmHandle m_mgmsrv2;
const char *m_constr;
Expand All @@ -192,6 +198,7 @@ class CommandInterpreter {
bool m_always_encrypt_backup;
char m_onetime_backup_password[1024];
bool m_onetime_backup_password_set;
int m_tls_start_type;
};

NdbMutex* print_mutex;
Expand All @@ -203,10 +210,12 @@ NdbMutex* print_mutex;
#include "ndb_mgmclient.hpp"

Ndb_mgmclient::Ndb_mgmclient(const char *host, const char* default_prompt,
int verbose, int connect_retry_delay)
int verbose, int connect_retry_delay,
const char * tls_search_path, int tls_start_type)
{
m_cmd= new CommandInterpreter(host, default_prompt,
verbose, connect_retry_delay);
verbose, connect_retry_delay,
tls_search_path, tls_start_type);
}
Ndb_mgmclient::~Ndb_mgmclient()
{
Expand Down Expand Up @@ -234,6 +243,11 @@ int Ndb_mgmclient::set_always_encrypt_backup(bool on) const
return m_cmd->setAlwaysEncryptBackup(on);
}

int Ndb_mgmclient::test_tls()
{
return m_cmd->test_tls();
}

/*
* The CommandInterpreter
*/
Expand Down Expand Up @@ -265,6 +279,7 @@ static const char* helpText =
"SHOW Print information about cluster\n"
"CREATE NODEGROUP <id>,<id>... Add a Nodegroup containing nodes\n"
"DROP NODEGROUP <NG> Drop nodegroup with id NG\n"
"START TLS Start TLS on connection\n"
"START BACKUP [<backup id>] [ENCRYPT [PASSWORD='<password>']] "
"[SNAPSHOTSTART | SNAPSHOTEND] [NOWAIT | WAIT STARTED | WAIT COMPLETED]\n"
" Start backup "
Expand Down Expand Up @@ -722,7 +737,9 @@ convert(const char* s, int& val) {
*/
CommandInterpreter::CommandInterpreter(const char *host,
const char* default_prompt,
int verbose, int connect_retry_delay) :
int verbose, int connect_retry_delay,
const char * tls_search_path,
int tls_start_type) :
m_constr(host),
m_connected(false),
m_verbose(verbose),
Expand All @@ -734,8 +751,10 @@ CommandInterpreter::CommandInterpreter(const char *host,
m_prompt(default_prompt),
m_default_backup_password(nullptr),
m_always_encrypt_backup(false),
m_onetime_backup_password_set(false)
m_onetime_backup_password_set(false),
m_tls_start_type(tls_start_type)
{
m_tlsKeyManager.init_mgm_client(tls_search_path);
m_print_mutex= NdbMutex_Create();
}

Expand Down Expand Up @@ -996,6 +1015,13 @@ event_thread_run(void* p)
DBUG_RETURN(NULL);
}

int
CommandInterpreter::test_tls()
{
m_try_reconnect = 1;
return connect(false) ? 0 : 1;
}

bool
CommandInterpreter::connect(bool interactive)
{
Expand All @@ -1010,6 +1036,13 @@ CommandInterpreter::connect(bool interactive)
exit(-1);
}

if((m_tls_start_type == CLIENT_TLS_STRICT) &&
(m_tlsKeyManager.ctx() == nullptr))
{
ndbout_c("No valid certificate.");
exit(-1);
}

if (interactive) {
m_mgmsrv2 = ndb_mgm_create_handle();
if(m_mgmsrv2 == NULL) {
Expand Down Expand Up @@ -1045,6 +1078,29 @@ CommandInterpreter::connect(bool interactive)
DBUG_RETURN(m_connected); // couldn't connect, always false
}

ndb_mgm_set_ssl_ctx(m_mgmsrv, m_tlsKeyManager.ctx());

if(m_tls_start_type != CLIENT_TLS_DEFERRED)
{
if(ndb_mgm_start_tls(m_mgmsrv) != 0)
{
if(interactive)
{
ndbout_c("Connected to server, but failed to start TLS.");
}

if(m_tls_start_type == CLIENT_TLS_STRICT)
{
printError();
ndb_mgm_destroy_handle(&m_mgmsrv);
if(interactive)
{
ndb_mgm_destroy_handle(&m_mgmsrv2);
}
DBUG_RETURN(m_connected);
}
}
}

const char *host= ndb_mgm_get_connected_host(m_mgmsrv);
unsigned port= ndb_mgm_get_connected_port(m_mgmsrv);
Expand All @@ -1056,6 +1112,10 @@ CommandInterpreter::connect(bool interactive)
{
DBUG_PRINT("info",("2:ndb connected to Management Server ok at: %s:%d",
host, port));
if(m_tls_start_type != CLIENT_TLS_DEFERRED)
{
ndb_mgm_start_tls(m_mgmsrv2);
}
assert(m_event_thread == NULL);
assert(do_event_thread == 0);
do_event_thread= 0;
Expand Down Expand Up @@ -1363,6 +1423,12 @@ CommandInterpreter::execute_impl(const char *_line, bool interactive)
executeClusterLog(allAfterFirstToken);
DBUG_RETURN(true);
}
else if(native_strcasecmp(firstToken, "START") == 0 &&
allAfterFirstToken != NULL &&
native_strncasecmp(allAfterFirstToken, "TLS", 3) == 0) {
m_error = executeStartTls();
DBUG_RETURN(true);
}
else if(native_strcasecmp(firstToken, "START") == 0 &&
allAfterFirstToken != NULL &&
native_strncasecmp(allAfterFirstToken, "BACKUP", sizeof("BACKUP") - 1) == 0){
Expand Down Expand Up @@ -2057,6 +2123,15 @@ CommandInterpreter::executeConnect(char* parameters, bool interactive)
return 0;
}

int
CommandInterpreter::executeStartTls()
{
int result = ndb_mgm_start_tls(m_mgmsrv);
if(result == 0) ndbout_c("TLS started.");
else printError();
return result;
}

//*****************************************************************************
//*****************************************************************************
void
Expand Down
32 changes: 31 additions & 1 deletion storage/ndb/src/mgmclient/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const char *load_default_groups[]= { "mysql_cluster","ndb_mgm",0 };
static char *opt_execute_str= 0;
static char *opt_prompt= 0;
static unsigned opt_verbose = 1;
static bool opt_test_tls = true;

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

static bool opt_encrypt_backup = false;

/* ndb_mgm uses an extended form of the --ndb-mgm-tls enum, which accepts
an extra option, "disabled"
*/
static const char * tls_names[] = { "relaxed", "strict", "deferred", nullptr };
static TYPELIB mgm_tls_typelib = { 3 , "TLS requirement", tls_names, nullptr };

static struct my_option my_long_options[] =
{
NdbStdOpt::usage,
Expand All @@ -72,6 +79,7 @@ static struct my_option my_long_options[] =
NdbStdOpt::ndb_nodeid,
NdbStdOpt::connect_retry_delay,
NdbStdOpt::connect_retries,
NdbStdOpt::tls_search_path,
NDB_STD_OPT_DEBUG
{ "backup-password", NDB_OPT_NOSHORT, "Encryption password for backup file",
nullptr, nullptr, nullptr, GET_PASSWORD, OPT_ARG,
Expand All @@ -96,6 +104,13 @@ static struct my_option my_long_options[] =
{"try-reconnect", 't', "Same as --connect-retries",
&opt_connect_retries, nullptr, nullptr, GET_INT, REQUIRED_ARG,
12, 0, INT_MAX, nullptr, 0, nullptr},
{ "ndb-mgm-tls", NDB_OPT_NOSHORT,
"MGM client TLS requirement level",
&opt_mgm_tls, nullptr, &mgm_tls_typelib, GET_ENUM, REQUIRED_ARG,
0, 0, 2, nullptr, 0, nullptr},
{ "test-tls", NDB_OPT_NOSHORT, "Connect using TLS then exit",
&opt_test_tls, nullptr, nullptr, GET_BOOL, NO_ARG,
0, 0, 0, nullptr, 0, nullptr},
NdbStdOpt::end_of_options
};

Expand Down Expand Up @@ -172,10 +187,19 @@ int main(int argc, char** argv){
opt_prompt= 0;
}

int tls_option = opt_mgm_tls;
if(opt_test_tls)
{
tls_option = CLIENT_TLS_STRICT;
opt_verbose = 1;
}

Ndb_mgmclient* com = new Ndb_mgmclient(connect_str.c_str(),
"ndb_mgm> ",
opt_verbose,
opt_connect_retry_delay);
opt_connect_retry_delay,
opt_tls_search_path,
tls_option);
com->set_always_encrypt_backup(opt_encrypt_backup);
if (opt_backup_password_state.get_password())
{
Expand All @@ -196,6 +220,12 @@ int main(int argc, char** argv){
prompt_args.append(opt_prompt);
com->execute(prompt_args.c_str(), opt_connect_retries, 0);
}

if (opt_test_tls)
{
return com->test_tls();
}

int ret= 0;
BaseString histfile;
if (!opt_execute_str)
Expand Down
5 changes: 4 additions & 1 deletion storage/ndb/src/mgmclient/ndb_mgmclient.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,16 @@ class Ndb_mgmclient
Ndb_mgmclient(const char* host,
const char* default_prompt,
int verbose,
int connect_retry_delay);
int connect_retry_delay,
const char * tls_search_path,
int tls_start_type);
~Ndb_mgmclient();
bool execute(const char *line, int try_reconnect = -1,
bool interactive = true, int *error = NULL);
const char* get_current_prompt() const;
int set_default_backup_password(const char backup_password[]) const;
int set_always_encrypt_backup(bool on) const;
int test_tls();
private:
CommandInterpreter *m_cmd;
};
Expand Down
3 changes: 2 additions & 1 deletion storage/ndb/src/mgmsrv/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,8 @@ static void mgmd_run()
con_str.appfmt("host=%s %d", opts.bind_address, port);
else
con_str.appfmt("localhost:%d", port);
Ndb_mgmclient com(con_str.c_str(), "ndb_mgm> ", 1, 5);
Ndb_mgmclient com(con_str.c_str(), "ndb_mgm> ", 1, 5, opt_tls_search_path,
CLIENT_TLS_RELAXED);
while(!g_StopServer){
if (!read_and_execute(&com, "ndb_mgm> ", 1))
g_StopServer = true;
Expand Down

0 comments on commit 024e2c8

Please sign in to comment.