]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
rgw: enable 'user modify --account-id'
authorCasey Bodley <cbodley@redhat.com>
Wed, 1 Nov 2023 22:28:34 +0000 (18:28 -0400)
committerCasey Bodley <cbodley@redhat.com>
Wed, 10 Apr 2024 16:53:05 +0000 (12:53 -0400)
Signed-off-by: Casey Bodley <cbodley@redhat.com>
src/rgw/driver/rados/rgw_rest_user.cc
src/rgw/driver/rados/rgw_user.cc
src/rgw/driver/rados/rgw_user.h
src/rgw/rgw_admin.cc

index 58623cd646895e84c541c64b4f6d2c72319e1060..748a61c3f837e7d1a0d451c9bb7a8ab189f2f39b 100644 (file)
@@ -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;
index 4e48506202fbe2a140b7425da9878b3f715c5120..a6881502210152ffdaa87c2f3a8724a10851d2a6 100644 (file)
@@ -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
index 46500fb1acaead4ffb8c2721b16978cc037c66a0..ef847df5c1d04254af22d8de5d18a4179da1c431 100644 (file)
@@ -123,6 +123,7 @@ struct RGWUserAdminOpState {
   RGWObjVersionTracker objv;
   uint32_t op_mask{0};
   std::map<int, std::string> temp_url_keys;
+  std::string account_id;
 
   // subuser attributes
   std::string subuser;
index 33d6febed208cce076c3b98347b8048b6793dfe1..c318490ed00ed7496271164906d3dd9922721a9d 100644 (file)
@@ -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;