Merge branch '2.3' into 2.4

This commit is contained in:
Markus Mäkelä 2020-01-07 11:12:02 +02:00
commit b555115fa2
No known key found for this signature in database
GPG Key ID: 72D48FCE664F7B19
6 changed files with 67 additions and 45 deletions

View File

@ -195,6 +195,10 @@ following fields.
* `data.attributes.account`
* Set to `admin` for administrative users and `basic` to read-only users
Only admin accounts can perform POST, PUT, DELETE and PATCH requests. If a basic
account performs one of the aforementioned request, the REST API will respond
with a `401 Unauthorized` error.
Here is an example request body defining the network user _my-user_ with the
password _my-password_ that is allowed to execute only read-only operations.

View File

@ -354,7 +354,8 @@ exports.builder = function(yargs) {
return yargs.epilog('The created user can be used with the MaxScale REST API as ' +
'well as the MaxAdmin network interface. By default the created ' +
'user will have read-only privileges. To make the user an ' +
'administrative user, use the `--type=admin` option.')
'administrative user, use the `--type=admin` option. ' +
'Basic users can only perform `list` and `show` commands.')
.usage('Usage: create user <name> <password>')
.group(['type'], 'Create user options:')
.option('type', {

View File

@ -872,11 +872,6 @@ DCB* Listener::accept_one_dcb(int fd, const sockaddr_storage* addr, const char*
}
}
if (client_dcb)
{
mxb::atomic::add(&m_service->client_count, 1);
}
return client_dcb;
}

View File

@ -257,18 +257,7 @@ private:
static void session_free(MXS_SESSION* session)
{
MXS_INFO("Stopped %s client session [%" PRIu64 "]", session->service->name(), session->ses_id);
Service* service = static_cast<Service*>(session->service);
session_final_free(session);
bool should_destroy = !mxb::atomic::load(&service->active);
if (mxb::atomic::add(&service->client_count, -1) == 1 && should_destroy)
{
// Destroy the service in the main routing worker thread
mxs::RoutingWorker* main_worker = mxs::RoutingWorker::get(mxs::RoutingWorker::MAIN);
main_worker->execute(std::unique_ptr<ServiceDestroyTask>(new ServiceDestroyTask(service)),
Worker::EXECUTE_AUTO);
}
}
static void session_final_free(MXS_SESSION* ses)
@ -1162,6 +1151,7 @@ Session::Session(const SListener& listener)
mxb::atomic::add(&service->stats.n_current, 1, mxb::atomic::RELAXED);
mxb_assert(service->stats.n_current >= 0);
mxb::atomic::add(&service->client_count, 1, mxb::atomic::RELAXED);
}
Session::~Session()
@ -1179,6 +1169,17 @@ Session::~Session()
mxb::atomic::add(&service->stats.n_current, -1, mxb::atomic::RELAXED);
mxb_assert(service->stats.n_current >= 0);
bool should_destroy = !mxb::atomic::load(&service->active);
if (mxb::atomic::add(&service->client_count, -1) == 1 && should_destroy)
{
// Destroy the service in the main routing worker thread
mxs::RoutingWorker* main_worker = mxs::RoutingWorker::get(mxs::RoutingWorker::MAIN);
main_worker->execute(
std::unique_ptr<ServiceDestroyTask>(new ServiceDestroyTask(static_cast<Service*>(service))),
Worker::EXECUTE_AUTO);
}
}
void Session::set_client_dcb(DCB* dcb)

View File

@ -478,6 +478,10 @@ int validate_mysql_user(MYSQL_AUTH* instance,
rval = MXS_AUTH_FAILED_DB;
}
}
else
{
rval = MXS_AUTH_FAILED_WRONG_PASSWORD;
}
}
return rval;

View File

@ -37,6 +37,8 @@
#include <maxscale/utils.h>
#include <maxscale/routingworker.hh>
#include <sstream>
static void* mysql_auth_init(char** options);
static bool mysql_auth_set_protocol_data(DCB* dcb, GWBUF* buf);
static bool mysql_auth_is_client_ssl_capable(DCB* dcb);
@ -305,6 +307,48 @@ static GWBUF* gen_auth_switch_request_packet(MySQLProtocol* proto, MYSQL_session
*bufdata = '\0';
return buffer;
}
static void log_auth_failure(DCB* dcb, int auth_ret)
{
MYSQL_session* client_data = (MYSQL_session*)dcb->data;
std::ostringstream extra;
if (auth_ret == MXS_AUTH_FAILED_DB)
{
extra << "Unknown database: " << client_data->db;
}
else if (auth_ret == MXS_AUTH_FAILED_WRONG_PASSWORD)
{
extra << "Wrong password.";
}
else
{
extra << "User not found.";
}
std::ostringstream host;
host << "[" << dcb->remote << "]:" << dcb_get_port(dcb);
std::ostringstream db;
if (*client_data->db)
{
db << " to database '" << client_data->db << "'";
}
MXS_LOG_EVENT(maxscale::event::AUTHENTICATION_FAILURE,
"%s: login attempt for user '%s'@%s%s, authentication failed. %s",
dcb->service->name(), client_data->user, host.str().c_str(),
db.str().c_str(), extra.str().c_str());
if (is_localhost_address(&dcb->ip) && !dcb->service->localhost_match_wildcard_host)
{
MXS_NOTICE("If you have a wildcard grant that covers this address, "
"try adding 'localhost_match_wildcard_host=true' for "
"service '%s'. ", dcb->service->name());
}
}
/**
* @brief Authenticates a MySQL user who is a client to MaxScale.
*
@ -368,34 +412,7 @@ static int mysql_auth_authenticate(DCB* dcb)
}
else if (dcb->service->log_auth_warnings)
{
// The default failure is a `User not found` one
char extra[256] = "User not found.";
if (auth_ret == MXS_AUTH_FAILED_DB)
{
snprintf(extra, sizeof(extra), "Unknown database: %s", client_data->db);
}
else if (auth_ret == MXS_AUTH_FAILED_WRONG_PASSWORD)
{
strcpy(extra, "Wrong password.");
}
MXS_LOG_EVENT(maxscale::event::AUTHENTICATION_FAILURE,
"%s: login attempt for user '%s'@[%s]:%d, authentication failed. %s",
dcb->service->name(),
client_data->user,
dcb->remote,
dcb_get_port(dcb),
extra);
if (is_localhost_address(&dcb->ip)
&& !dcb->service->localhost_match_wildcard_host)
{
MXS_NOTICE("If you have a wildcard grant that covers this address, "
"try adding 'localhost_match_wildcard_host=true' for "
"service '%s'. ",
dcb->service->name());
}
log_auth_failure(dcb, auth_ret);
}
/* let's free the auth_token now */