MXS-2574: Add PATCH for /users/inet endpoint
The alteration of user passwords is now done inside MaxScale. This prevents the possibility of a user locking themselves out.
This commit is contained in:
parent
77671a2393
commit
aac0ecc373
@ -71,6 +71,7 @@ const char* admin_disable_linux_account(const char *uname);
|
||||
bool admin_linux_account_enabled(const char *uname);
|
||||
|
||||
const char* admin_add_inet_user(const char *uname, const char *password, enum user_account_type type);
|
||||
const char* admin_alter_inet_user(const char* uname, const char* password);
|
||||
const char* admin_remove_inet_user(const char* uname);
|
||||
bool admin_inet_user_exists(const char *uname);
|
||||
bool admin_verify_inet_user(const char *uname, const char *password);
|
||||
|
@ -97,6 +97,17 @@ bool users_auth(USERS* users, const char* user, const char* password);
|
||||
*/
|
||||
bool users_find(USERS* users, const char* user);
|
||||
|
||||
/**
|
||||
* Change password for a user
|
||||
*
|
||||
* @param users The users table
|
||||
* @param user User to alter
|
||||
* @param password The new password for the user
|
||||
*
|
||||
* @return True if password was changed
|
||||
*/
|
||||
bool users_change_password(USERS* users, const char* user, const char* password);
|
||||
|
||||
/**
|
||||
* Check if user is an administrator
|
||||
*
|
||||
|
@ -192,10 +192,6 @@ exports.builder = function(yargs) {
|
||||
}, function(argv) {
|
||||
maxctrl(argv, function(host) {
|
||||
|
||||
if (argv.u == argv.name) {
|
||||
return error('Cannot alter current user')
|
||||
}
|
||||
|
||||
var user = {
|
||||
'data': {
|
||||
'id': argv.name,
|
||||
@ -206,10 +202,7 @@ exports.builder = function(yargs) {
|
||||
}
|
||||
}
|
||||
|
||||
return getJson(host, 'users/inet/' + argv.name)
|
||||
.then((res) => user.data.attributes.account = res.data.attributes.account)
|
||||
.then(() => doRequest(host, 'users/inet/' + argv.name, null, {method: 'DELETE'}))
|
||||
.then(() => doRequest(host, 'users/inet', null, {method: 'POST', body: user}))
|
||||
return doRequest(host, 'users/inet/' + argv.name, null, {method: 'PATCH', body: user})
|
||||
})
|
||||
})
|
||||
.usage('Usage: alter <command>')
|
||||
|
@ -195,11 +195,6 @@ describe("Alter Commands", function() {
|
||||
.should.be.rejected
|
||||
})
|
||||
|
||||
it('rejects alteration to current user', function() {
|
||||
return doCommand('-u bob -p bob alter user bob bob2')
|
||||
.should.be.rejected
|
||||
})
|
||||
|
||||
it('creates user', function() {
|
||||
return verifyCommand('create user testuser test', 'users/inet/testuser')
|
||||
})
|
||||
@ -212,5 +207,13 @@ describe("Alter Commands", function() {
|
||||
return doCommand('destroy user testuser')
|
||||
})
|
||||
|
||||
it('allows alteration to current user', function() {
|
||||
return verifyCommand('create user bob bob --type=admin', 'users/inet/bob')
|
||||
.then(() => doCommand('-u bob -p bob alter user bob bob2'))
|
||||
.then(() => doCommand('-u bob -p bob2 alter user bob bob'))
|
||||
.then(() => doCommand('-u bob -p bob list servers'))
|
||||
.then(() => doCommand('-u bob -p bob destroy user bob'))
|
||||
})
|
||||
|
||||
after(stopMaxScale)
|
||||
});
|
||||
|
@ -138,6 +138,29 @@ static const char* admin_add_user(USERS** pusers,
|
||||
return ADMIN_SUCCESS;
|
||||
}
|
||||
|
||||
static const char* admin_alter_user(USERS** pusers,
|
||||
const char* fname,
|
||||
const char* uname,
|
||||
const char* password)
|
||||
{
|
||||
if (*pusers == NULL)
|
||||
{
|
||||
*pusers = users_alloc();
|
||||
}
|
||||
|
||||
if (!users_change_password(*pusers, uname, password))
|
||||
{
|
||||
return ADMIN_ERR_USERNOTFOUND;
|
||||
}
|
||||
|
||||
if (!admin_dump_users(*pusers, fname))
|
||||
{
|
||||
return ADMIN_ERR_FILEOPEN;
|
||||
}
|
||||
|
||||
return ADMIN_SUCCESS;
|
||||
}
|
||||
|
||||
static const char* admin_remove_user(USERS* users, const char* fname, const char* uname)
|
||||
{
|
||||
if (!users_delete(users, uname))
|
||||
@ -437,6 +460,19 @@ const char* admin_add_inet_user(const char* uname, const char* password, enum us
|
||||
return admin_add_user(&inet_users, INET_USERS_FILE_NAME, uname, password, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alter network user.
|
||||
*
|
||||
* @param uname The user to alter
|
||||
* @param password The new password
|
||||
*
|
||||
* @return NULL on success or an error string on failure.
|
||||
*/
|
||||
const char* admin_alter_inet_user(const char* uname, const char* password)
|
||||
{
|
||||
return admin_alter_user(&inet_users, INET_USERS_FILE_NAME, uname, password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove insecure remote (network) user
|
||||
*
|
||||
|
@ -2875,6 +2875,31 @@ bool runtime_remove_user(const char* id, enum user_type type)
|
||||
return rval;
|
||||
}
|
||||
|
||||
bool runtime_alter_user(const std::string& user, const std::string& type, json_t* json)
|
||||
{
|
||||
bool rval = false;
|
||||
const char* password = json_string_value(mxs_json_pointer(json, MXS_JSON_PTR_PASSWORD));
|
||||
|
||||
if (!password)
|
||||
{
|
||||
config_runtime_error("No password provided");
|
||||
}
|
||||
else if (type != CN_INET)
|
||||
{
|
||||
config_runtime_error("Users of type '%s' cannot be altered", type.c_str());
|
||||
}
|
||||
else if (const char* err = admin_alter_inet_user(user.c_str(), password))
|
||||
{
|
||||
config_runtime_error("%s", err);
|
||||
}
|
||||
else
|
||||
{
|
||||
rval = true;
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
bool validate_maxscale_json(json_t* json)
|
||||
{
|
||||
bool rval = false;
|
||||
|
@ -386,6 +386,17 @@ bool runtime_create_user_from_json(json_t* json);
|
||||
*/
|
||||
bool runtime_remove_user(const char* id, enum user_type type);
|
||||
|
||||
/**
|
||||
* @brief Alter admin user password
|
||||
*
|
||||
* @param user Username
|
||||
* @param type Type of the user
|
||||
* @param json JSON defining the new user
|
||||
*
|
||||
* @return True if the user was altered successfully
|
||||
*/
|
||||
bool runtime_alter_user(const std::string& user, const std::string& type, json_t* json);
|
||||
|
||||
/**
|
||||
* @brief Alter core MaxScale parameters from JSON
|
||||
*
|
||||
|
@ -760,6 +760,7 @@ HttpResponse cb_monitor_wait(const HttpRequest& request)
|
||||
MonitorManager::debug_wait_one_tick();
|
||||
return HttpResponse(MHD_HTTP_OK);
|
||||
}
|
||||
|
||||
HttpResponse cb_create_user(const HttpRequest& request)
|
||||
{
|
||||
mxb_assert(request.get_json());
|
||||
@ -772,6 +773,19 @@ HttpResponse cb_create_user(const HttpRequest& request)
|
||||
return HttpResponse(MHD_HTTP_FORBIDDEN, runtime_get_json_error());
|
||||
}
|
||||
|
||||
HttpResponse cb_alter_user(const HttpRequest& request)
|
||||
{
|
||||
auto user = request.last_uri_part();
|
||||
auto type = request.uri_part(1);
|
||||
|
||||
if (runtime_alter_user(user, type, request.get_json()))
|
||||
{
|
||||
return HttpResponse(MHD_HTTP_NO_CONTENT);
|
||||
}
|
||||
|
||||
return HttpResponse(MHD_HTTP_FORBIDDEN, runtime_get_json_error());
|
||||
}
|
||||
|
||||
HttpResponse cb_delete_user(const HttpRequest& request)
|
||||
{
|
||||
string user = request.last_uri_part();
|
||||
@ -1044,6 +1058,7 @@ public:
|
||||
m_patch.push_back(SResource(new Resource(cb_alter_logs, 2, "maxscale", "logs")));
|
||||
m_patch.push_back(SResource(new Resource(cb_alter_maxscale, 1, "maxscale")));
|
||||
m_patch.push_back(SResource(new Resource(cb_alter_qc, 2, "maxscale", "query_classifier")));
|
||||
m_patch.push_back(SResource(new Resource(cb_alter_user, 3, "users", "inet", ":inetuser")));
|
||||
|
||||
/** Update resource relationships directly */
|
||||
m_patch.push_back(SResource(new Resource(cb_alter_server_service_relationship,
|
||||
|
@ -327,6 +327,13 @@ bool users_find(USERS* users, const char* user)
|
||||
return u->get(user);
|
||||
}
|
||||
|
||||
bool users_change_password(USERS* users, const char* user, const char* password)
|
||||
{
|
||||
Users* u = reinterpret_cast<Users*>(users);
|
||||
UserInfo info;
|
||||
return u->get(user, &info) && u->remove(user) && u->add(user, password, info.permissions);
|
||||
}
|
||||
|
||||
bool users_auth(USERS* users, const char* user, const char* password)
|
||||
{
|
||||
Users* u = reinterpret_cast<Users*>(users);
|
||||
|
Loading…
x
Reference in New Issue
Block a user