MXS-3013: Add reload endpoint for services

The endpoint reloads the database users. This can also be used in the
future to refresh encrypted credentials when they are no longer loaded
every time an encrypted password is used.
This commit is contained in:
Markus Mäkelä 2020-05-29 09:06:15 +03:00
parent e565a6d9b8
commit f013d3ccd9
No known key found for this signature in database
GPG Key ID: 5CE746D557ACC499
4 changed files with 69 additions and 27 deletions

View File

@ -93,6 +93,11 @@ public:
*/
bool refresh_users();
/**
* Unconditionally refreshes the users for all listeners of the service
*/
void load_users();
/**
* Dump service configuration into a file
*
@ -131,6 +136,9 @@ private:
// Update the local filter list on the current worker
void update_local_filters();
// Load the users
bool do_load_users();
// Callback for updating the local filter list
static void update_filters_cb(void* data)
{

View File

@ -683,6 +683,16 @@ HttpResponse cb_flush(const HttpRequest& request)
return HttpResponse(code);
}
HttpResponse cb_reload_users(const HttpRequest& request)
{
Service* service = service_internal_find(request.uri_part(1).c_str());
mxb_assert(service);
service->load_users();
return HttpResponse(MHD_HTTP_NO_CONTENT);
}
HttpResponse cb_all_threads(const HttpRequest& request)
{
return HttpResponse(MHD_HTTP_OK, mxs_rworker_list_to_json(request.host()));
@ -1051,6 +1061,7 @@ public:
/** For all module commands that modify state/data */
m_post.push_back(SResource(new Resource(cb_modulecmd, 4, "maxscale", "modules", ":module", "?")));
m_post.push_back(SResource(new Resource(cb_flush, 3, "maxscale", "logs", "flush")));
m_post.push_back(SResource(new Resource(cb_reload_users, 3, "services", ":service", "reload")));
/** Update resources */
m_patch.push_back(SResource(new Resource(cb_alter_server, 2, "servers", ":server")));

View File

@ -1070,6 +1070,50 @@ void dListListeners(DCB* dcb)
}
}
bool Service::do_load_users()
{
bool ret = true;
for (const auto& listener : listener_find_by_service(this))
{
switch (listener->load_users())
{
case MXS_AUTH_LOADUSERS_FATAL:
MXS_ERROR("[%s] Fatal error when loading users for listener '%s', authentication will not work.",
name(), listener->name());
ret = false;
break;
case MXS_AUTH_LOADUSERS_ERROR:
MXS_WARNING("[%s] Failed to load users for listener '%s', authentication might not work.",
name(), listener->name());
ret = false;
break;
default:
break;
}
}
return ret;
}
void Service::load_users()
{
if (capabilities & ACAP_TYPE_ASYNC)
{
mxs::RoutingWorker::execute_concurrently(
[this]() {
do_load_users();
});
}
else
{
std::lock_guard<std::mutex> guard(lock);
do_load_users();
}
}
bool Service::refresh_users()
{
mxs::WatchdogWorkaround workaround;
@ -1109,33 +1153,7 @@ bool Service::refresh_users()
{
m_rate_limits[self].last = now;
m_rate_limits[self].warned = false;
for (const auto& listener : listener_find_by_service(this))
{
/** Load the authentication users before before starting the listener */
switch (listener->load_users())
{
case MXS_AUTH_LOADUSERS_FATAL:
MXS_ERROR("[%s] Fatal error when loading users for listener '%s',"
" authentication will not work.",
name(),
listener->name());
ret = false;
break;
case MXS_AUTH_LOADUSERS_ERROR:
MXS_WARNING("[%s] Failed to load users for listener '%s', authentication"
" might not work.",
name(),
listener->name());
ret = false;
break;
default:
break;
}
}
ret = do_load_users();
}
return ret;

View File

@ -168,5 +168,10 @@ describe("Service", function() {
.should.be.fulfilled
});
it("reload users", function() {
return request.post(base_url + "/services/RW-Split-Router/reload")
.should.be.fulfilled
});
after(stopMaxScale)
});