Merge branch '2.2' into develop

This commit is contained in:
Markus Mäkelä
2018-03-20 13:14:54 +02:00
33 changed files with 811 additions and 91 deletions

View File

@ -87,7 +87,7 @@ if (HAVE_LIBDL)
target_link_libraries(maxscale-common dl)
endif()
add_dependencies(maxscale-common pcre2 connector-c libmicrohttpd)
add_dependencies(maxscale-common pcre2 connector-c libmicrohttpd jansson)
set_target_properties(maxscale-common PROPERTIES VERSION "1.0.0")
install_module(maxscale-common core)

View File

@ -69,6 +69,7 @@ const char CN_ADMIN_SSL_CERT[] = "admin_ssl_cert";
const char CN_ADMIN_SSL_CA_CERT[] = "admin_ssl_ca_cert";
const char CN_ATTRIBUTES[] = "attributes";
const char CN_AUTHENTICATOR[] = "authenticator";
const char CN_AUTHENTICATOR_DIAGNOSTICS[] = "authenticator_diagnostics";
const char CN_AUTHENTICATOR_OPTIONS[] = "authenticator_options";
const char CN_AUTH_ALL_SERVERS[] = "auth_all_servers";
const char CN_AUTH_CONNECT_TIMEOUT[] = "auth_connect_timeout";
@ -82,6 +83,7 @@ const char CN_DESCRIPTION[] = "description";
const char CN_ENABLE_ROOT_USER[] = "enable_root_user";
const char CN_FILTERS[] = "filters";
const char CN_FILTER[] = "filter";
const char CN_FILTER_DIAGNOSTICS[] = "filter_diagnostics";
const char CN_GATEWAY[] = "gateway";
const char CN_ID[] = "id";
const char CN_INET[] = "inet";
@ -100,6 +102,7 @@ const char CN_MODULES[] = "modules";
const char CN_MODULE_COMMAND[] = "module_command";
const char CN_MONITORS[] = "monitors";
const char CN_MONITOR[] = "monitor";
const char CN_MONITOR_DIAGNOSTICS[] = "monitor_diagnostics";
const char CN_MS_TIMESTAMP[] = "ms_timestamp";
const char CN_NAME[] = "name";
const char CN_NON_BLOCKING_POLLS[] = "non_blocking_polls";
@ -120,6 +123,7 @@ const char CN_LOCAL_ADDRESS[] = "local_address";
const char CN_REQUIRED[] = "required";
const char CN_RETRY_ON_FAILURE[] = "retry_on_failure";
const char CN_ROUTER[] = "router";
const char CN_ROUTER_DIAGNOSTICS[] = "router_diagnostics";
const char CN_ROUTER_OPTIONS[] = "router_options";
const char CN_SELF[] = "self";
const char CN_SERVERS[] = "servers";

View File

@ -516,7 +516,7 @@ json_t* filter_json_data(const MXS_FILTER_DEF* filter, const char* host)
if (diag)
{
json_object_set_new(attr, "filter_diagnostics", diag);
json_object_set_new(attr, CN_FILTER_DIAGNOSTICS, diag);
}
}

View File

@ -526,6 +526,16 @@ json_t* listener_to_json(const SERV_LISTENER* listener)
json_t* attr = json_object();
json_object_set_new(attr, CN_PARAMETERS, param);
if (listener->listener->authfunc.diagnostic_json)
{
json_t* diag = listener->listener->authfunc.diagnostic_json(listener);
if (diag)
{
json_object_set_new(attr, CN_AUTHENTICATOR_DIAGNOSTICS, diag);
}
}
json_t* rval = json_object();
json_object_set_new(rval, CN_ATTRIBUTES, attr);
json_object_set_new(rval, CN_ID, json_string(listener->name));

View File

@ -1864,13 +1864,13 @@ json_t* monitor_json_data(const MXS_MONITOR* monitor, const char* host)
/** Monitor parameters */
json_object_set_new(attr, CN_PARAMETERS, monitor_parameters_to_json(monitor));
if (monitor->handle && monitor->module->diagnostics)
if (monitor->handle && monitor->module->diagnostics_json)
{
json_t* diag = monitor->module->diagnostics_json(monitor);
if (diag)
{
json_object_set_new(attr, "monitor_diagnostics", diag);
json_object_set_new(attr, CN_MONITOR_DIAGNOSTICS, diag);
}
}

View File

@ -2654,13 +2654,13 @@ json_t* service_attributes(const SERVICE* service)
json_object_set_new(attr, CN_ROUTER, json_string(service->routerModule));
json_object_set_new(attr, CN_STATE, json_string(service_state_to_string(service->state)));
if (service->router && service->router_instance)
if (service->router && service->router_instance && service->router->diagnostics_json)
{
json_t* diag = service->router->diagnostics_json(service->router_instance);
if (diag)
{
json_object_set_new(attr, "router_diagnostics", diag);
json_object_set_new(attr, CN_ROUTER_DIAGNOSTICS, diag);
}
}

View File

@ -674,7 +674,7 @@ json_t* mysql_auth_diagnostic_json(const SERV_LISTENER *port)
sqlite3* handle = get_handle(instance);
if (sqlite3_exec(handle, "SELECT user, host FROM " MYSQLAUTH_USERS_TABLE_NAME,
diag_cb, rval, &err) != SQLITE_OK)
diag_cb_json, rval, &err) != SQLITE_OK)
{
MXS_ERROR("Failed to print users: %s", err);
sqlite3_free(err);

View File

@ -12,6 +12,7 @@
*/
#include"pam_auth.hh"
#include <string>
#include <maxscale/authenticator.h>
#include <maxscale/users.h>
@ -19,6 +20,14 @@
#include "pam_client_session.hh"
#include "../pam_auth_common.hh"
using std::string;
const string FIELD_USER = "user";
const string FIELD_HOST = "host";
const string FIELD_DB = "db";
const string FIELD_ANYDB = "anydb";
const string FIELD_AUTHSTR = "authentication_string";
const int NUM_FIELDS = 5;
/**
* Initialize PAM authenticator
*
@ -131,6 +140,18 @@ static int pam_auth_load_users(SERV_LISTENER *listener)
return inst->load_users(listener->service);
}
static void pam_auth_diagnostic(DCB *dcb, SERV_LISTENER *listener)
{
PamInstance *inst = static_cast<PamInstance*>(listener->auth_instance);
inst->diagnostic(dcb);
}
static json_t* pam_auth_diagnostic_json(const SERV_LISTENER *listener)
{
PamInstance *inst = static_cast<PamInstance*>(listener->auth_instance);
return inst->diagnostic_json();
}
MXS_BEGIN_DECLS
/**
* Module handle entry point
@ -147,8 +168,8 @@ MXS_MODULE* MXS_CREATE_MODULE()
pam_auth_free_data, /* Free the client data held in DCB */
pam_auth_free, /* Free authenticator data */
pam_auth_load_users, /* Load database users */
users_default_diagnostic, /* Default user diagnostic */
users_default_diagnostic_json, /* Default user diagnostic */
pam_auth_diagnostic, /* Default user diagnostic */
pam_auth_diagnostic_json, /* Default user diagnostic */
NULL /* No user reauthentication */
};

View File

@ -19,9 +19,17 @@
#include <maxscale/cppdefs.hh>
#include <string>
#include <maxscale/alloc.h>
#include <maxscale/buffer.hh>
#include <maxscale/dcb.h>
#include <maxscale/protocol/mysql.h>
using std::string;
extern const string FIELD_USER;
extern const string FIELD_HOST;
extern const string FIELD_DB;
extern const string FIELD_ANYDB;
extern const string FIELD_AUTHSTR;
extern const int NUM_FIELDS;

View File

@ -231,11 +231,11 @@ PamClientSession* PamClientSession::create(const PamInstance& inst)
void PamClientSession::get_pam_user_services(const DCB* dcb, const MYSQL_session* session,
StringVector* services_out)
{
string services_query = string("SELECT authentication_string FROM ") +
m_instance.m_tablename + " WHERE user = '" + session->user +
"' AND '" + dcb->remote + "' LIKE host AND (anydb = '1' OR '" +
session->db + "' = '' OR '" + session->db +
"' LIKE db) ORDER BY authentication_string";
string services_query = string("SELECT authentication_string FROM ") + m_instance.m_tablename +
" WHERE " + FIELD_USER + " = '" + session->user + "' AND '" + dcb->remote +
"' LIKE " + FIELD_HOST + " AND (" + FIELD_ANYDB + " = '1' OR '" + session->db +
"' = '' OR '" + session->db + "' LIKE " + FIELD_DB +
") ORDER BY authentication_string;";
MXS_DEBUG("PAM services search sql: '%s'.", services_query.c_str());
char *err;
if (sqlite3_exec(m_dbhandle, services_query.c_str(), user_services_cb,

View File

@ -15,6 +15,7 @@
#include <string>
#include <string.h>
#include <maxscale/jansson.hh>
#include <maxscale/log_manager.h>
#include <maxscale/secrets.h>
#include <maxscale/mysql_utils.h>
@ -36,9 +37,10 @@ PamInstance* PamInstance::create(char **options)
/** The table name where we store the users */
const string pam_table_name = DEFAULT_PAM_TABLE_NAME;
/** CREATE TABLE statement for the in-memory table */
const string create_sql = "CREATE TABLE IF NOT EXISTS " + pam_table_name +
" (user varchar(255), host varchar(255), db varchar(255), "
"anydb boolean, authentication_string text)";
const string create_sql = string("CREATE TABLE IF NOT EXISTS ") + pam_table_name +
" (" + FIELD_USER + " varchar(255), " + FIELD_HOST + " varchar(255), " +
FIELD_DB + " varchar(255), " + FIELD_ANYDB + " boolean, " +
FIELD_AUTHSTR + " text);";
if (sqlite3_threadsafe() == 0)
{
MXS_WARNING("SQLite3 was compiled with thread safety off. May cause "
@ -172,12 +174,12 @@ int PamInstance::load_users(SERVICE* service)
/** Query that gets all users that authenticate via the pam plugin */
const char PAM_USERS_QUERY[] =
"SELECT u.user, u.host, d.db, u.select_priv, u.authentication_string FROM "
"mysql.user AS u LEFT JOIN mysql.db AS d "
"ON (u.user = d.user AND u.host = d.host) WHERE u.plugin = 'pam' "
"mysql.user AS u LEFT JOIN mysql.db AS d ON (u.user = d.user AND u.host = d.host) WHERE "
"(u.plugin = 'pam' AND (d.db IS NOT NULL OR u.select_priv = 'Y')) "
"UNION "
"SELECT u.user, u.host, t.db, u.select_priv, u.authentication_string FROM "
"mysql.user AS u LEFT JOIN mysql.tables_priv AS t "
"ON (u.user = t.user AND u.host = t.host) WHERE u.plugin = 'pam' "
"mysql.user AS u LEFT JOIN mysql.tables_priv AS t ON (u.user = t.user AND u.host = t.host) WHERE "
"(u.plugin = 'pam' AND t.db IS NOT NULL AND u.select_priv = 'N') "
"ORDER BY user";
#if defined(SS_DEBUG)
const unsigned int PAM_USERS_QUERY_NUM_FIELDS = 5;
@ -228,5 +230,60 @@ int PamInstance::load_users(SERVICE* service)
}
MXS_FREE(pw);
}
return rval;
}
void PamInstance::diagnostic(DCB* dcb)
{
json_t* array = diagnostic_json();
ss_dassert(json_is_array(array));
string result, separator;
size_t index;
json_t* value;
json_array_foreach(array, index, value)
{
// Only print user@host for the non-json version, as this should fit nicely on the console. Add the
// other fields if deemed useful.
const char* user = json_string_value(json_object_get(value, FIELD_USER.c_str()));
const char* host = json_string_value(json_object_get(value, FIELD_HOST.c_str()));
if (user && host)
{
result += separator + user + "@" + host;
separator = " ";
}
}
if (!result.empty())
{
dcb_printf(dcb, "%s", result.c_str());
}
json_decref(array);
}
static int diag_cb_json(void *data, int columns, char **row, char **field_names)
{
ss_dassert(columns == NUM_FIELDS);
json_t* obj = json_object();
for (int i = 0; i < columns; i++)
{
json_object_set_new(obj, field_names[i], json_string(row[i]));
}
json_t* arr = static_cast<json_t*>(data);
json_array_append_new(arr, obj);
return 0;
}
json_t* PamInstance::diagnostic_json()
{
json_t* rval = json_array();
char *err;
string select = "SELECT * FROM " + m_tablename + ";";
if (sqlite3_exec(m_dbhandle, select.c_str(), diag_cb_json, rval, &err) != SQLITE_OK)
{
MXS_ERROR("Failed to print users: %s", err);
sqlite3_free(err);
}
return rval;
}

View File

@ -26,6 +26,8 @@ public:
static PamInstance* create(char **options);
~PamInstance();
int load_users(SERVICE* service);
void diagnostic(DCB* dcb);
json_t* diagnostic_json();
const std::string m_dbname; /**< Name of the in-memory database */
const std::string m_tablename; /**< The table where users are stored */