From e69ce01774be57259bef76fb3267c607513f28e7 Mon Sep 17 00:00:00 2001 From: Casey Bodley Date: Wed, 1 Nov 2023 18:28:34 -0400 Subject: [PATCH] rgw: enable 'user modify --account-id' Signed-off-by: Casey Bodley --- src/rgw/driver/rados/rgw_rest_user.cc | 2 + src/rgw/driver/rados/rgw_user.cc | 60 +++++++++++++++++++++++++++ src/rgw/driver/rados/rgw_user.h | 1 + src/rgw/rgw_admin.cc | 2 + 4 files changed, 65 insertions(+) diff --git a/src/rgw/driver/rados/rgw_rest_user.cc b/src/rgw/driver/rados/rgw_rest_user.cc index 58623cd646895..748a61c3f837e 100644 --- a/src/rgw/driver/rados/rgw_rest_user.cc +++ b/src/rgw/driver/rados/rgw_rest_user.cc @@ -185,6 +185,7 @@ void RGWOp_User_Create::execute(optional_yield y) RESTArgs::get_string(s, "op-mask", op_mask_str, &op_mask_str); RESTArgs::get_string(s, "default-placement", default_placement_str, &default_placement_str); RESTArgs::get_string(s, "placement-tags", placement_tags_str, &placement_tags_str); + RESTArgs::get_string(s, "account-id", "", &op_state.account_id); if (!s->user->get_info().system && system) { ldpp_dout(this, 0) << "cannot set system flag by non-system user" << dendl; @@ -324,6 +325,7 @@ void RGWOp_User_Modify::execute(optional_yield y) RESTArgs::get_string(s, "op-mask", op_mask_str, &op_mask_str); RESTArgs::get_string(s, "default-placement", default_placement_str, &default_placement_str); RESTArgs::get_string(s, "placement-tags", placement_tags_str, &placement_tags_str); + RESTArgs::get_string(s, "account-id", "", &op_state.account_id); if (!s->user->get_info().system && system) { ldpp_dout(this, 0) << "cannot set system flag by non-system user" << dendl; diff --git a/src/rgw/driver/rados/rgw_user.cc b/src/rgw/driver/rados/rgw_user.cc index 4e48506202fbe..a688150221015 100644 --- a/src/rgw/driver/rados/rgw_user.cc +++ b/src/rgw/driver/rados/rgw_user.cc @@ -5,6 +5,7 @@ #include "rgw_user.h" +#include "rgw_account.h" #include "rgw_bucket.h" #include "rgw_quota.h" @@ -1614,6 +1615,30 @@ int RGWUser::execute_rename(const DoutPrefixProvider *dpp, RGWUserAdminOpState& return update(dpp, op_state, err_msg, y); } +// when setting RGWUserInfo::account_id, verify that the account metadata +// exists and matches the user's tenant +static int validate_account_tenant(const DoutPrefixProvider* dpp, + optional_yield y, + rgw::sal::Driver* driver, + std::string_view account_id, + std::string_view tenant, + std::string& err) +{ + RGWAccountInfo info; + rgw::sal::Attrs attrs; + RGWObjVersionTracker objv; + int r = driver->load_account_by_id(dpp, y, account_id, info, attrs, objv); + if (r < 0) { + err = "Failed to load account by id"; + return r; + } + if (info.tenant != tenant) { + err = "User tenant does not match account tenant"; + return -EINVAL; + } + return 0; +} + int RGWUser::execute_add(const DoutPrefixProvider *dpp, RGWUserAdminOpState& op_state, std::string *err_msg, optional_yield y) { @@ -1674,6 +1699,22 @@ int RGWUser::execute_add(const DoutPrefixProvider *dpp, RGWUserAdminOpState& op_ user_info.placement_tags = op_state.placement_tags; } + if (!op_state.account_id.empty()) { + if (!rgw::account::validate_id(op_state.account_id, err_msg)) { + return -EINVAL; + } + // tenant must match account.tenant + std::string err; + int ret = validate_account_tenant(dpp, y, driver, op_state.account_id, + user_info.user_id.tenant, err); + if (ret < 0) { + set_err_msg(err_msg, err); + return ret; + } + user_info.account_id = op_state.account_id; + // TODO: change account on user's buckets + } + // update the request op_state.set_user_info(user_info); op_state.set_populated(); @@ -1961,6 +2002,25 @@ int RGWUser::execute_modify(const DoutPrefixProvider *dpp, RGWUserAdminOpState& user_info.placement_tags = op_state.placement_tags; } + if (!op_state.account_id.empty()) { + if (!rgw::account::validate_id(op_state.account_id, err_msg)) { + return -EINVAL; + } + if (user_info.account_id != op_state.account_id) { + user_info.account_id = op_state.account_id; + + // tenant must match new account.tenant + std::string err; + ret = validate_account_tenant(dpp, y, driver, op_state.account_id, + user_info.user_id.tenant, err); + if (ret < 0) { + set_err_msg(err_msg, err); + return ret; + } + // TODO: change account on user's buckets + } + } + op_state.set_user_info(user_info); // if we're supposed to modify keys, do so diff --git a/src/rgw/driver/rados/rgw_user.h b/src/rgw/driver/rados/rgw_user.h index 46500fb1acaea..ef847df5c1d04 100644 --- a/src/rgw/driver/rados/rgw_user.h +++ b/src/rgw/driver/rados/rgw_user.h @@ -123,6 +123,7 @@ struct RGWUserAdminOpState { RGWObjVersionTracker objv; uint32_t op_mask{0}; std::map temp_url_keys; + std::string account_id; // subuser attributes std::string subuser; diff --git a/src/rgw/rgw_admin.cc b/src/rgw/rgw_admin.cc index 33d6febed208c..c318490ed00ed 100644 --- a/src/rgw/rgw_admin.cc +++ b/src/rgw/rgw_admin.cc @@ -6555,6 +6555,8 @@ int main(int argc, const char **argv) user_op.set_placement_tags(tags); } + user_op.account_id = account_id; + // RGWUser to use for user operations RGWUser ruser; int ret = 0; -- 2.39.5