]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.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>
Fri, 12 Apr 2024 19:34:26 +0000 (15:34 -0400)
Signed-off-by: Casey Bodley <cbodley@redhat.com>
(cherry picked from commit e69ce01774be57259bef76fb3267c607513f28e7)

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 b282083c824c56709ce8477827a0bfd69081d45e..a4b00a9b5e9f63b1de790abdafdfabe370a140f6 100644 (file)
@@ -5,6 +5,7 @@
 
 #include "rgw_user.h"
 
+#include "rgw_account.h"
 #include "rgw_bucket.h"
 #include "rgw_quota.h"
 
@@ -1610,6 +1611,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)
 {
@@ -1670,6 +1695,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();
@@ -1957,6 +1998,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 377e7ea18cfc9c57cf856f52b517a58134302949..c802f7d02035422517f837fbb20343c286da0e7a 100644 (file)
@@ -6552,6 +6552,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;