]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw/role: add rgwrados::role interface for role metadata
authorCasey Bodley <cbodley@redhat.com>
Mon, 4 Dec 2023 21:47:12 +0000 (16:47 -0500)
committerCasey Bodley <cbodley@redhat.com>
Thu, 12 Sep 2024 20:55:01 +0000 (16:55 -0400)
move everything from class RadosRole into driver/rados/role.cc and use
RGWSI_SysObj instead of the metadata backend. narrows the RGWRole
interface by handling the name/path objects internally

rgwrados::role::write() adds/remove name and path linkages in case they
change. admin ops don't allow this, but 'metadata put' could upload
arbitrary json that does change them

Signed-off-by: Casey Bodley <cbodley@redhat.com>
15 files changed:
src/rgw/CMakeLists.txt
src/rgw/driver/rados/rgw_sal_rados.cc
src/rgw/driver/rados/rgw_sal_rados.h
src/rgw/driver/rados/rgw_service.cc
src/rgw/driver/rados/role.cc [new file with mode: 0644]
src/rgw/driver/rados/role.h [new file with mode: 0644]
src/rgw/rgw_admin.cc
src/rgw/rgw_rest_iam.h
src/rgw/rgw_rest_role.cc
src/rgw/rgw_rest_role.h
src/rgw/rgw_rest_s3.cc
src/rgw/rgw_rest_sts.cc
src/rgw/rgw_role.cc
src/rgw/rgw_role.h
src/rgw/rgw_sts.cc

index 792569ff482a6b6ca5148777e1105c4ed4ace986..c09491200c6b127b29ecdad83e61b1d634837960 100644 (file)
@@ -202,6 +202,7 @@ set(librgw_common_srcs
   driver/rados/rgw_trim_mdlog.cc
   driver/rados/rgw_user.cc
   driver/rados/rgw_zone.cc
+  driver/rados/role.cc
   driver/rados/roles.cc
   driver/rados/sync_fairness.cc
   driver/rados/topic.cc
index e3b435d283919c01457e85b28ecea8857bff256a..92b8582e92f2ab89967ffe1524bb88ff1b97d9b6 100644 (file)
@@ -28,6 +28,7 @@
 #include "common/Clock.h"
 #include "common/errno.h"
 
+#include "role.h"
 #include "rgw_sal.h"
 #include "rgw_sal_rados.h"
 #include "rgw_bucket.h"
@@ -1286,15 +1287,16 @@ int RadosStore::list_account_roles(const DoutPrefixProvider* dpp,
 
   // load the role metadata for each
   for (const auto& id : ids) {
-    std::unique_ptr<rgw::sal::RGWRole> role = get_role(id);
-    r = role->read_info(dpp, y);
+    RGWRoleInfo info;
+    r = rgwrados::role::read_by_id(dpp, y, *svc()->sysobj, zone, id,
+                                   info, nullptr, nullptr, nullptr);
     if (r == -ENOENT) {
       continue;
     }
     if (r < 0) {
       return r;
     }
-    listing.roles.push_back(std::move(role->get_info()));
+    listing.roles.push_back(std::move(info));
   }
 
   return 0;
@@ -2016,67 +2018,10 @@ int RadosStore::list_roles(const DoutPrefixProvider *dpp,
                           uint32_t max_items,
                           RoleList& listing)
 {
-  listing.roles.clear();
-
-  const auto& pool = svc()->zone->get_zone_params().roles_pool;
-  std::string prefix;
-
-  // List all roles if path prefix is empty
-  if (! path_prefix.empty()) {
-    prefix = tenant + RGWRole::role_path_oid_prefix + path_prefix;
-  } else {
-    prefix = tenant + RGWRole::role_path_oid_prefix;
-  }
-
-  //Get the filtered objects
-  RGWListRawObjsCtx ctx;
-  int r = rados->list_raw_objects_init(dpp, pool, marker, &ctx);
-  if (r < 0) {
-    return r;
-  }
-
-  bool is_truncated = false;
-  list<std::string> oids;
-  r = rados->list_raw_objects(dpp, pool, prefix, max_items,
-                              ctx, oids, &is_truncated);
-  if (r == -ENOENT) {
-    r = 0;
-  } else if (r < 0) {
-    return r;
-  }
-
-  for (const auto& oid : oids) {
-    const std::string key = oid.substr(RGWRole::role_path_oid_prefix.size());
-
-    //Find the role oid prefix from the end
-    size_t pos = key.rfind(RGWRole::role_oid_prefix);
-    if (pos == std::string::npos) {
-      continue;
-    }
-    // Split the result into path and info_oid + id
-    std::string path = key.substr(0, pos);
-
-    /*Make sure that prefix is part of path (False results could've been returned)
-      because of the role info oid + id appended to the path)*/
-    if(path_prefix.empty() || path.find(path_prefix) != std::string::npos) {
-      //Get id from info oid prefix + id
-      std::string id = key.substr(pos + RGWRole::role_oid_prefix.length());
-
-      std::unique_ptr<rgw::sal::RGWRole> role = get_role(id);
-      r = role->read_info(dpp, y);
-      if (r < 0) {
-        return r;
-      }
-      listing.roles.push_back(std::move(role->get_info()));
-    }
-  }
-
-  if (is_truncated) {
-    listing.next_marker = rados->list_raw_objs_get_cursor(ctx);
-  } else {
-    listing.next_marker.clear();
-  }
-  return 0;
+  const RGWZoneParams& zone = svc()->zone->get_zone_params();
+  return rgwrados::role::list_tenant(dpp, y, *svc()->sysobj, zone,
+                                     tenant, marker, max_items, path_prefix,
+                                     listing.roles, listing.next_marker);
 }
 
 static constexpr std::string_view oidc_url_oid_prefix = "oidc_url.";
@@ -4434,321 +4379,39 @@ std::ostream& RadosLuaManager::PackagesWatcher::gen_prefix(std::ostream& out) co
 
 int RadosRole::store_info(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y)
 {
-  using ceph::encode;
-  std::string oid;
-
-  oid = info.id;
-
-  bufferlist bl;
-  encode(this->info, bl);
-
-  if (!this->info.tags.empty()) {
-    bufferlist bl_tags;
-    encode(this->info.tags, bl_tags);
-    map<string, bufferlist> attrs;
-    attrs.emplace("tagging", bl_tags);
-
-    RGWSI_MBSObj_PutParams params(bl, &attrs, info.mtime, exclusive);
-    std::unique_ptr<RGWSI_MetaBackend::Context> ctx(store->svc()->role->svc.meta_be->alloc_ctx());
-    ctx->init(store->svc()->role->get_be_handler());
-    return store->svc()->role->svc.meta_be->put(ctx.get(), oid, params, &info.objv_tracker, y, dpp);
-  } else {
-    RGWSI_MBSObj_PutParams params(bl, nullptr, info.mtime, exclusive);
-    std::unique_ptr<RGWSI_MetaBackend::Context> ctx(store->svc()->role->svc.meta_be->alloc_ctx());
-    ctx->init(store->svc()->role->get_be_handler());
-    return store->svc()->role->svc.meta_be->put(ctx.get(), oid, params, &info.objv_tracker, y, dpp);
-  }
-}
-
-static std::string role_name_oid(const RGWRoleInfo& r, std::string_view prefix)
-{
-  if (!r.account_id.empty()) {
-    // names are case-insensitive, so store them in lower case
-    std::string lower_name = r.name;
-    boost::algorithm::to_lower(lower_name);
-    // use account id as prefix
-    return string_cat_reserve(r.account_id, prefix, lower_name);
-  } else {
-    // use tenant as prefix
-    return string_cat_reserve(r.tenant, prefix, r.name);
-  }
-}
-
-int RadosRole::store_name(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y)
-{
-  auto sysobj = store->svc()->sysobj;
-  RGWNameToId nameToId;
-  nameToId.obj_id = info.id;
-
-  std::string oid = role_name_oid(info, get_names_oid_prefix());
-
-  bufferlist bl;
-  using ceph::encode;
-  encode(nameToId, bl);
-
-  return rgw_put_system_obj(dpp, sysobj, store->svc()->zone->get_zone_params().roles_pool, oid, bl, exclusive, &info.objv_tracker, real_time(), y);
-}
-
-int RadosRole::store_path(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y)
-{
-  if (!info.account_id.empty()) {
-    librados::Rados& rados = *store->getRados()->get_rados_handle();
-    const RGWZoneParams& zone = store->svc()->zone->get_zone_params();
-    const rgw_raw_obj& obj = rgwrados::account::get_roles_obj(zone, info.account_id);
-    constexpr uint32_t no_limit = std::numeric_limits<uint32_t>::max();
-    return rgwrados::roles::add(dpp, y, rados, obj, info, false, no_limit);
-  }
-
-  auto sysobj = store->svc()->sysobj;
-  std::string oid = info.tenant + get_path_oid_prefix() + info.path + get_info_oid_prefix() + info.id;
-
-  bufferlist bl;
-
-  return rgw_put_system_obj(dpp, sysobj, store->svc()->zone->get_zone_params().roles_pool, oid, bl, exclusive, &info.objv_tracker, real_time(), y);
-}
-
-int RadosRole::read_id(const DoutPrefixProvider *dpp, const std::string& role_name, const std::string& tenant, std::string& role_id, optional_yield y)
-{
-  auto sysobj = store->svc()->sysobj;
-  std::string oid = info.tenant + get_names_oid_prefix() + role_name;
-  bufferlist bl;
-
-  int ret = rgw_get_system_obj(sysobj, store->svc()->zone->get_zone_params().roles_pool, oid, bl, nullptr, nullptr, y, dpp);
-  if (ret < 0) {
-    return ret;
-  }
-
-  RGWNameToId nameToId;
-  try {
-    auto iter = bl.cbegin();
-    using ceph::decode;
-    decode(nameToId, iter);
-  } catch (buffer::error& err) {
-    ldpp_dout(dpp, 0) << "ERROR: failed to decode role from Role pool: " << role_name << dendl;
-    return -EIO;
-  }
-  role_id = nameToId.obj_id;
-  return 0;
-}
-
-int RadosRole::read_name(const DoutPrefixProvider *dpp, optional_yield y)
-{
-  auto sysobj = store->svc()->sysobj;
-  std::string oid = role_name_oid(info, get_names_oid_prefix());
-  bufferlist bl;
-
-  int ret = rgw_get_system_obj(sysobj, store->svc()->zone->get_zone_params().roles_pool, oid, bl, nullptr, nullptr, y, dpp);
-  if (ret < 0) {
-    ldpp_dout(dpp, 0) << "ERROR: failed reading role name from Role pool: " << info.name <<
-      ": " << cpp_strerror(-ret) << dendl;
-    return ret;
-  }
-
-  RGWNameToId nameToId;
-  try {
-    using ceph::decode;
-    auto iter = bl.cbegin();
-    decode(nameToId, iter);
-  } catch (buffer::error& err) {
-    ldpp_dout(dpp, 0) << "ERROR: failed to decode role name from Role pool: " << info.name << dendl;
-    return -EIO;
-  }
-  info.id = nameToId.obj_id;
-  return 0;
+  librados::Rados& rados = *store->getRados()->get_rados_handle();
+  RGWServices* svc = store->svc();
+  const RGWZoneParams& zone = svc->zone->get_zone_params();
+  return rgwrados::role::write(dpp, y, rados, *svc->sysobj, svc->mdlog,
+                               zone, info, info.objv_tracker,
+                               ceph::real_time{}, exclusive);
 }
 
-int RadosRole::read_info(const DoutPrefixProvider *dpp, optional_yield y)
+int RadosRole::load_by_name(const DoutPrefixProvider *dpp, optional_yield y)
 {
-  std::string oid;
-
-  oid = info.id;
-  ldpp_dout(dpp, 20) << "INFO: oid in read_info is: " << oid << dendl;
-
-  bufferlist bl;
-
-  RGWSI_MBSObj_GetParams params(&bl, &info.attrs, &info.mtime);
-  std::unique_ptr<RGWSI_MetaBackend::Context> ctx(store->svc()->role->svc.meta_be->alloc_ctx());
-  ctx->init(store->svc()->role->get_be_handler());
-  int ret = store->svc()->role->svc.meta_be->get(ctx.get(), oid, params, &info.objv_tracker, y, dpp, true);
-  if (ret < 0) {
-    ldpp_dout(dpp, 0) << "ERROR: failed reading role info from Role pool: " << info.id << ": " << cpp_strerror(-ret) << dendl;
-    return ret;
-  }
-
-  try {
-    using ceph::decode;
-    auto iter = bl.cbegin();
-    decode(this->info, iter);
-  } catch (buffer::error& err) {
-    ldpp_dout(dpp, 0) << "ERROR: failed to decode role info from Role pool: " << info.id << dendl;
-    return -EIO;
-  }
-
-  auto it = info.attrs.find("tagging");
-  if (it != info.attrs.end()) {
-    bufferlist bl_tags = it->second;
-    try {
-      using ceph::decode;
-      auto iter = bl_tags.cbegin();
-      decode(info.tags, iter);
-    } catch (buffer::error& err) {
-      ldpp_dout(dpp, 0) << "ERROR: failed to decode attrs" << info.id << dendl;
-      return -EIO;
-    }
-  }
-
-  return 0;
+  RGWServices* svc = store->svc();
+  const RGWZoneParams& zone = svc->zone->get_zone_params();
+  return rgwrados::role::read_by_name(dpp, y, *svc->sysobj, zone,
+                                      info.tenant, info.account_id,
+                                      info.name, info, &info.mtime,
+                                      &info.objv_tracker);
 }
 
-int RadosRole::create(const DoutPrefixProvider *dpp, bool exclusive, const std::string& role_id, optional_yield y)
+int RadosRole::load_by_id(const DoutPrefixProvider *dpp, optional_yield y)
 {
-  int ret;
-
-  if (! validate_input(dpp)) {
-    return -EINVAL;
-  }
-
-  if (!role_id.empty()) {
-    info.id = role_id;
-  }
-
-  /* check to see the name is not used */
-  ret = read_id(dpp, info.name, info.tenant, info.id, y);
-  if (exclusive && ret == 0) {
-    ldpp_dout(dpp, 0) << "ERROR: name " << info.name << " already in use for role id "
-                    << info.id << dendl;
-    return -EEXIST;
-  } else if ( ret < 0 && ret != -ENOENT) {
-    ldpp_dout(dpp, 0) << "failed reading role id  " << info.id << ": "
-                  << cpp_strerror(-ret) << dendl;
-    return ret;
-  }
-
-  if (info.id.empty()) {
-    /* create unique id */
-    uuid_d new_uuid;
-    char uuid_str[37];
-    new_uuid.generate_random();
-    new_uuid.print(uuid_str);
-    info.id = uuid_str;
-  }
-
-  //arn
-  std::string_view account = !info.account_id.empty() ? info.account_id : info.tenant;
-  info.arn = string_cat_reserve(role_arn_prefix, account, ":role", info.path, info.name);
-
-  if (info.creation_date.empty()) {
-    // Creation time
-    real_clock::time_point t = real_clock::now();
-
-    struct timeval tv;
-    real_clock::to_timeval(t, tv);
-
-    char buf[30];
-    struct tm result;
-    gmtime_r(&tv.tv_sec, &result);
-    strftime(buf,30,"%Y-%m-%dT%H:%M:%S", &result);
-    sprintf(buf + strlen(buf),".%03dZ",(int)tv.tv_usec/1000);
-    info.creation_date.assign(buf, strlen(buf));
-  }
-
-  auto& pool = store->svc()->zone->get_zone_params().roles_pool;
-  ret = store_info(dpp, exclusive, y);
-  if (ret < 0) {
-    ldpp_dout(dpp, 0) << "ERROR:  storing role info in Role pool: "
-                  << info.id << ": " << cpp_strerror(-ret) << dendl;
-    return ret;
-  }
-
-  ret = store_name(dpp, exclusive, y);
-  if (ret < 0) {
-    ldpp_dout(dpp, 0) << "ERROR: storing role name in Role pool: "
-                  << info.name << ": " << cpp_strerror(-ret) << dendl;
-
-    //Delete the role info that was stored in the previous call
-    std::string oid = get_info_oid_prefix() + info.id;
-    int info_ret = rgw_delete_system_obj(dpp, store->svc()->sysobj, pool, oid, nullptr, y);
-    if (info_ret < 0) {
-      ldpp_dout(dpp, 0) << "ERROR: cleanup of role id from Role pool: "
-                  << info.id << ": " << cpp_strerror(-info_ret) << dendl;
-    }
-    return ret;
-  }
-
-  ret = store_path(dpp, exclusive, y);
-  if (ret < 0) {
-    ldpp_dout(dpp, 0) << "ERROR: storing role path in Role pool: "
-                  << info.path << ": " << cpp_strerror(-ret) << dendl;
-    //Delete the role info that was stored in the previous call
-    std::string oid = get_info_oid_prefix() + info.id;
-    int info_ret = rgw_delete_system_obj(dpp, store->svc()->sysobj, pool, oid, nullptr, y);
-    if (info_ret < 0) {
-      ldpp_dout(dpp, 0) << "ERROR: cleanup of role id from Role pool: "
-                  << info.id << ": " << cpp_strerror(-info_ret) << dendl;
-    }
-    //Delete role name that was stored in previous call
-    oid = role_name_oid(info, get_names_oid_prefix());
-    int name_ret = rgw_delete_system_obj(dpp, store->svc()->sysobj, pool, oid, nullptr, y);
-    if (name_ret < 0) {
-      ldpp_dout(dpp, 0) << "ERROR: cleanup of role name from Role pool: "
-                  << info.name << ": " << cpp_strerror(-name_ret) << dendl;
-    }
-    return ret;
-  }
-  return 0;
+  RGWServices* svc = store->svc();
+  const RGWZoneParams& zone = svc->zone->get_zone_params();
+  return rgwrados::role::read_by_id(dpp, y, *svc->sysobj, zone, info.id,
+                                    info, &info.mtime, &info.objv_tracker);
 }
 
 int RadosRole::delete_obj(const DoutPrefixProvider *dpp, optional_yield y)
 {
-  auto& pool = store->svc()->zone->get_zone_params().roles_pool;
-
-  int ret = read_name(dpp, y);
-  if (ret < 0) {
-    return ret;
-  }
-
-  ret = read_info(dpp, y);
-  if (ret < 0) {
-    return ret;
-  }
-
-  // Delete id & insert MD Log
-  RGWSI_MBSObj_RemoveParams params;
-  std::unique_ptr<RGWSI_MetaBackend::Context> ctx(store->svc()->role->svc.meta_be->alloc_ctx());
-  ctx->init(store->svc()->role->get_be_handler());
-  ret = store->svc()->role->svc.meta_be->remove(ctx.get(), info.id, params, &info.objv_tracker, y, dpp);
-  if (ret < 0) {
-    ldpp_dout(dpp, 0) << "ERROR: deleting role id: " << info.id << " failed with code: " << cpp_strerror(-ret) << dendl;
-    return ret;
-  }
-
-  // Delete name
-  std::string oid = role_name_oid(info, get_names_oid_prefix());
-  ret = rgw_delete_system_obj(dpp, store->svc()->sysobj, pool, oid, nullptr, y);
-  if (ret < 0) {
-    ldpp_dout(dpp, 0) << "ERROR: deleting role name from Role pool: "
-                  << info.name << ": " << cpp_strerror(-ret) << dendl;
-  }
-
-  // Delete path
-  if (!info.account_id.empty()) {
-    librados::Rados& rados = *store->getRados()->get_rados_handle();
-    const RGWZoneParams& zone = store->svc()->zone->get_zone_params();
-    const rgw_raw_obj& obj = rgwrados::account::get_roles_obj(zone, info.account_id);
-    ret = rgwrados::roles::remove(dpp, y, rados, obj, info.name);
-    if (ret < 0) {
-      ldpp_dout(dpp, 4) << "ERROR: deleting role path from account list: "
-                    << info.path << ": " << cpp_strerror(-ret) << dendl;
-    }
-  } else {
-    oid = info.tenant + get_path_oid_prefix() + info.path + get_info_oid_prefix() + info.id;
-    ret = rgw_delete_system_obj(dpp, store->svc()->sysobj, pool, oid, nullptr, y);
-    if (ret < 0) {
-      ldpp_dout(dpp, 4) << "ERROR: deleting role path from Role pool: "
-                    << info.path << ": " << cpp_strerror(-ret) << dendl;
-    }
-  }
-  return 0;
+  librados::Rados& rados = *store->getRados()->get_rados_handle();
+  RGWServices* svc = store->svc();
+  const RGWZoneParams& zone = svc->zone->get_zone_params();
+  return rgwrados::role::remove(dpp, y, rados, *svc->sysobj, svc->mdlog, zone,
+                                info.tenant, info.account_id, info.name);
 }
 
 } // namespace rgw::sal
index d359f733ab352aeb54f59118a6a30116e371e3bf..0372c5882aa16e09665b1378d2edbd91531508d7 100644 (file)
@@ -1164,13 +1164,10 @@ public:
   RadosRole(RadosStore* _store) : store(_store) {}
   ~RadosRole() = default;
 
-  virtual int store_info(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y) override;
-  virtual int store_name(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y) override;
-  virtual int store_path(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y) override;
-  virtual int read_id(const DoutPrefixProvider *dpp, const std::string& role_name, const std::string& tenant, std::string& role_id, optional_yield y) override;
-  virtual int read_name(const DoutPrefixProvider *dpp, optional_yield y) override;
-  virtual int read_info(const DoutPrefixProvider *dpp, optional_yield y) override;
-  virtual int create(const DoutPrefixProvider *dpp, bool exclusive, const std::string& role_id, optional_yield y) override;
-  virtual int delete_obj(const DoutPrefixProvider *dpp, optional_yield y) override;
+  int load_by_name(const DoutPrefixProvider *dpp, optional_yield y) override;
+  int load_by_id(const DoutPrefixProvider *dpp, optional_yield y) override;
+  int store_info(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y) override;
+  int delete_obj(const DoutPrefixProvider *dpp, optional_yield y) override;
 };
+
 }} // namespace rgw::sal
index 792e4eb65b077b48dcfb98d7b6f7ebd12ec99ad8..6a177a4acd5eab54ec77e46a6fdd9acc1914e189 100644 (file)
@@ -36,7 +36,7 @@
 #include "rgw_otp.h"
 #include "rgw_sal_rados.h"
 #include "rgw_user.h"
-#include "rgw_role.h"
+#include "role.h"
 #include "rgw_pubsub.h"
 #include "topic.h"
 
@@ -385,7 +385,8 @@ int RGWCtlDef::init(RGWServices& svc, rgw::sal::Driver* driver,
 
   meta.otp = rgwrados::otp::create_metadata_handler(
       *svc.sysobj, *svc.cls, *svc.mdlog, svc.zone->get_zone_params());
-  meta.role = create_role_metadata_handler(*driver, *svc.sysobj);
+  meta.role = rgwrados::role::create_metadata_handler(
+      rados, *svc.sysobj, *svc.mdlog, svc.zone->get_zone_params());
   meta.account = rgwrados::account::create_metadata_handler(
       *svc.sysobj, svc.zone->get_zone_params());
   meta.group = rgwrados::group::create_metadata_handler(
diff --git a/src/rgw/driver/rados/role.cc b/src/rgw/driver/rados/role.cc
new file mode 100644 (file)
index 0000000..1dd0aba
--- /dev/null
@@ -0,0 +1,720 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab ft=cpp
+
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright contributors to the Ceph project
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+#include "role.h"
+
+#include <optional>
+#include <variant>
+
+#include "common/errno.h"
+#include "rgw_common.h"
+#include "rgw_metadata.h"
+#include "rgw_metadata_lister.h"
+#include "rgw_role.h"
+#include "rgw_string.h"
+#include "rgw_tools.h"
+#include "rgw_zone.h"
+#include "svc_mdlog.h"
+
+#include "account.h"
+#include "roles.h"
+
+namespace rgwrados::role {
+
+// RGWRoleInfo is stored in rados objects named "roles.{id}",
+// where ids are assumed to be globally unique
+static const std::string oid_prefix = "roles.";
+// read_by_name() is enabled by rados objects
+// "{tenant}role_names.{name}" for tenant roles, or
+// "{account}role_names.{name}" for account roles
+constexpr std::string_view name_oid_prefix = "role_names.";
+// list() by path/prefix is enabled by rados objects
+// "{tenant}role_paths.{path}roles.{id}" for tenant roles.
+// see rgwrados::roles::list() for account roles
+constexpr std::string_view path_oid_prefix = "role_paths.";
+
+
+static rgw_raw_obj get_id_obj(const RGWZoneParams& zone,
+                              std::string_view id)
+{
+  return {zone.roles_pool, string_cat_reserve(oid_prefix, id)};
+}
+
+static int read_info(const DoutPrefixProvider* dpp, optional_yield y,
+                     RGWSI_SysObj& sysobj, const rgw_raw_obj& obj,
+                     RGWRoleInfo& info, ceph::real_time* pmtime,
+                     RGWObjVersionTracker* pobjv,
+                     rgw_cache_entry_info* pcache_info)
+{
+  bufferlist bl;
+  std::map<std::string, bufferlist> attrs;
+  // "tagging" doesn't start with RGW_ATTR_PREFIX, don't filter it out
+  constexpr bool raw_attrs = true;
+  int r = rgw_get_system_obj(&sysobj, obj.pool, obj.oid, bl, pobjv,
+                             pmtime, y, dpp, &attrs, pcache_info,
+                             boost::none, raw_attrs);
+  if (r < 0) {
+    return r;
+  }
+
+  try {
+    auto p = bl.cbegin();
+    decode(info, p);
+  } catch (const buffer::error&) {
+    return -EIO;
+  }
+
+  if (auto i = attrs.find("tagging"); i != attrs.end()) {
+    try {
+      using ceph::decode;
+      auto p = i->second.cbegin();
+      decode(info.tags, p);
+    } catch (const buffer::error&) {
+      ldpp_dout(dpp, 0) << "ERROR: failed to decode attrs " << info.id << dendl;
+      return -EIO;
+    }
+  }
+
+  return 0;
+}
+
+int read_by_id(const DoutPrefixProvider* dpp, optional_yield y,
+               RGWSI_SysObj& sysobj, const RGWZoneParams& zone,
+               std::string_view role_id, RGWRoleInfo& info,
+               ceph::real_time* pmtime, RGWObjVersionTracker* pobjv,
+               rgw_cache_entry_info* pcache_info)
+{
+  const rgw_raw_obj& obj = get_id_obj(zone, role_id);
+  return read_info(dpp, y, sysobj, obj, info, pmtime, pobjv, pcache_info);
+}
+
+static int write_info(const DoutPrefixProvider* dpp, optional_yield y,
+                      RGWSI_SysObj& sysobj, const RGWZoneParams& zone,
+                      const RGWRoleInfo& info, RGWObjVersionTracker& objv,
+                      ceph::real_time mtime, bool exclusive)
+{
+  std::map<std::string, bufferlist> attrs;
+  if (!info.tags.empty()) {
+    using ceph::encode;
+    bufferlist tagbl;
+    encode(info.tags, tagbl);
+    attrs.emplace("tagging", std::move(tagbl));
+  }
+
+  bufferlist bl;
+  encode(info, bl);
+
+  const rgw_raw_obj& obj = get_id_obj(zone, info.id);
+  int r = rgw_put_system_obj(dpp, &sysobj, obj.pool, obj.oid,
+                             bl, exclusive, &objv, mtime, y, &attrs);
+  if (r < 0) {
+    ldpp_dout(dpp, 1) << "ERROR: failed to write role obj " << obj
+        << " with: " << cpp_strerror(r) << dendl;
+    return r;
+  }
+  return 0;
+}
+
+struct IndexObj {
+  rgw_raw_obj obj;
+  RGWObjVersionTracker objv;
+};
+
+static rgw_raw_obj get_name_obj(const RGWZoneParams& zone,
+                                std::string_view tenant,
+                                const rgw_account_id& account,
+                                std::string_view name)
+{
+  if (account.empty()) {
+    // use tenant as prefix
+    std::string oid = string_cat_reserve(tenant, name_oid_prefix, name);
+    return {zone.roles_pool, std::move(oid)};
+  } else {
+    // names are case-insensitive, so store them in lower case
+    std::string lower_name{name};
+    boost::algorithm::to_lower(lower_name);
+    // use account id as prefix
+    std::string oid = string_cat_reserve(account, name_oid_prefix, lower_name);
+    return {zone.roles_pool, std::move(oid)};
+  }
+}
+static rgw_raw_obj get_name_obj(const RGWZoneParams& zone,
+                                const RGWRoleInfo& info)
+{
+  return get_name_obj(zone, info.tenant, info.account_id, info.name);
+}
+
+static int write_name(const DoutPrefixProvider* dpp, optional_yield y,
+                      RGWSI_SysObj& sysobj, const std::string& role_id,
+                      IndexObj& index)
+{
+  RGWNameToId nameToId;
+  nameToId.obj_id = role_id;
+
+  bufferlist bl;
+  encode(nameToId, bl);
+
+  return rgw_put_system_obj(dpp, &sysobj, index.obj.pool, index.obj.oid, bl,
+                            true, &index.objv, ceph::real_time(), y);
+}
+
+static int read_name(const DoutPrefixProvider* dpp, optional_yield y,
+                     RGWSI_SysObj& sysobj, IndexObj& name,
+                     RGWNameToId& name_to_id)
+{
+  bufferlist bl;
+  int r = rgw_get_system_obj(&sysobj, name.obj.pool, name.obj.oid,
+                             bl, &name.objv, nullptr, y, dpp);
+  if (r < 0) {
+    ldpp_dout(dpp, 4) << "failed to read role name object " << name.obj
+        << " with: " << cpp_strerror(r) << dendl;
+    return r;
+  }
+
+  try {
+    auto p = bl.cbegin();
+    decode(name_to_id, p);
+  } catch (const buffer::error& e) {
+    ldpp_dout(dpp, 4) << "failed to decode role name object: "
+        << e.what() << dendl;
+    return -EIO;
+  }
+  return 0;
+}
+
+static int remove_index(const DoutPrefixProvider* dpp, optional_yield y,
+                        RGWSI_SysObj& sysobj, IndexObj& index)
+{
+  int r = rgw_delete_system_obj(dpp, &sysobj, index.obj.pool,
+                                index.obj.oid, &index.objv, y);
+  if (r < 0) {
+    ldpp_dout(dpp, 20) << "WARNING: failed to remove "
+        << index.obj << " with " << cpp_strerror(r) << dendl;
+  }
+  return r;
+}
+
+using NameIndex = std::optional<IndexObj>;
+
+static int remove_index(const DoutPrefixProvider* dpp, optional_yield y,
+                        RGWSI_SysObj& sysobj, NameIndex& index)
+{
+  if (index) {
+    return remove_index(dpp, y, sysobj, *index);
+  }
+  return 0;
+}
+
+
+static rgw_raw_obj get_tenant_path_obj(const RGWZoneParams& zone,
+                                       const RGWRoleInfo& info)
+{
+  std::string oid = string_cat_reserve(info.tenant, path_oid_prefix,
+                                       info.path, oid_prefix, info.id);
+  return {zone.roles_pool, std::move(oid)};
+}
+
+static int write_tenant_path(const DoutPrefixProvider* dpp, optional_yield y,
+                             RGWSI_SysObj& sysobj, IndexObj& path)
+{
+  bufferlist bl;
+  return rgw_put_system_obj(dpp, &sysobj, path.obj.pool, path.obj.oid, bl,
+                            true, &path.objv, ceph::real_time(), y);
+}
+
+static int read_tenant_path(const DoutPrefixProvider* dpp, optional_yield y,
+                            RGWSI_SysObj& sysobj, IndexObj& path)
+{
+  bufferlist bl;
+  return rgw_get_system_obj(&sysobj, path.obj.pool, path.obj.oid,
+                            bl, &path.objv, nullptr, y, dpp);
+}
+
+struct AccountIndex {
+  rgw_raw_obj obj;
+  std::string_view name;
+};
+
+static int remove_index(const DoutPrefixProvider* dpp,
+                        optional_yield y, librados::Rados& rados,
+                        const AccountIndex& index)
+{
+  return roles::remove(dpp, y, rados, index.obj, index.name);
+}
+
+using PathIndex = std::variant<std::monostate, IndexObj, AccountIndex>;
+
+static int write_path(const DoutPrefixProvider* dpp, optional_yield y,
+                      librados::Rados& rados, RGWSI_SysObj& sysobj,
+                      const RGWZoneParams& zone, const RGWRoleInfo& info,
+                      PathIndex& index)
+{
+  if (!info.account_id.empty()) {
+    // add the new role to its account
+    AccountIndex path;
+    path.obj = account::get_roles_obj(zone, info.account_id);
+    path.name = info.name;
+
+    constexpr bool exclusive = true;
+    constexpr uint32_t no_limit = std::numeric_limits<uint32_t>::max();
+    int r = roles::add(dpp, y, rados, path.obj, info, exclusive, no_limit);
+    if (r < 0) {
+      ldpp_dout(dpp, 1) << "failed to add role to account "
+          << path.obj << " with: " << cpp_strerror(r) << dendl;
+      return r;
+    }
+    index = std::move(path);
+  } else {
+    // write the new path object
+    IndexObj path;
+    path.obj = get_tenant_path_obj(zone, info);
+    path.objv.generate_new_write_ver(dpp->get_cct());
+
+    int r = write_tenant_path(dpp, y, sysobj, path);
+    if (r < 0) {
+      ldpp_dout(dpp, 1) << "failed to write role path obj "
+          << path.obj << " with: " << cpp_strerror(r) << dendl;
+      return r;
+    }
+    index = std::move(path);
+  }
+  return 0;
+}
+
+static int remove_index(const DoutPrefixProvider* dpp,
+                        optional_yield y, librados::Rados& rados,
+                        RGWSI_SysObj& sysobj, PathIndex& index)
+{
+  return std::visit(fu2::overload(
+          [&] (std::monostate&) { return 0; },
+          [&] (IndexObj& path) {
+            return remove_index(dpp, y, sysobj, path);
+          },
+          [&] (AccountIndex& path) {
+            return remove_index(dpp, y, rados, path);
+          }), index);
+}
+
+int read_by_name(const DoutPrefixProvider* dpp, optional_yield y,
+                 RGWSI_SysObj& sysobj, const RGWZoneParams& zone,
+                 std::string_view tenant, const rgw_account_id& account,
+                 std::string_view name, RGWRoleInfo& info,
+                 ceph::real_time* pmtime, RGWObjVersionTracker* pobjv,
+                 rgw_cache_entry_info* pcache_info)
+{
+  IndexObj n;
+  n.obj = get_name_obj(zone, tenant, account, name);
+
+  RGWNameToId name_to_id;
+  int r = read_name(dpp, y, sysobj, n, name_to_id);
+  if (r < 0) {
+    return r;
+  }
+
+  return read_by_id(dpp, y, sysobj, zone, name_to_id.obj_id,
+                    info, pmtime, pobjv, pcache_info);
+}
+
+int write(const DoutPrefixProvider* dpp, optional_yield y,
+          librados::Rados& rados, RGWSI_SysObj& sysobj, RGWSI_MDLog* mdlog,
+          const RGWZoneParams& zone, const RGWRoleInfo& info,
+          RGWObjVersionTracker& objv, ceph::real_time mtime,
+          bool exclusive)
+{
+  int r = 0;
+
+  // read existing info in case we need to remove its name/path
+  RGWRoleInfo old;
+  RGWRoleInfo* old_info = nullptr;
+  if (!exclusive) {
+    r = read_by_id(dpp, y, sysobj, zone, info.id, old);
+    if (r == -ENOENT) {
+    } else if (r < 0) {
+      return r;
+    } else {
+      old_info = &old;
+    }
+  }
+
+  const bool same_name = old_info &&
+      old_info->tenant == info.tenant &&
+      old_info->account_id == info.account_id &&
+      old_info->name == info.name;
+  const bool same_path = old_info &&
+      old_info->tenant == info.tenant &&
+      old_info->account_id == info.account_id &&
+      old_info->path == info.path;
+
+  NameIndex remove_name;
+  PathIndex remove_path;
+  if (old_info) {
+    if (old_info->id != info.id) {
+      ldpp_dout(dpp, 1) << "ERROR: can't modify role id" << dendl;
+      return -EINVAL;
+    }
+    if (!same_name && !old_info->name.empty()) {
+      IndexObj name;
+      name.obj = get_name_obj(zone, *old_info);
+      RGWNameToId name_to_id;
+      r = read_name(dpp, y, sysobj, name, name_to_id);
+      if (r == -ENOENT) {
+        // leave remove_name empty
+      } else if (r < 0) {
+        return r;
+      } else if (name_to_id.obj_id == info.id) {
+        remove_name = std::move(name);
+      }
+    }
+    if (!same_path) {
+      if (!old_info->account_id.empty()) {
+        AccountIndex path;
+        path.obj = account::get_roles_obj(zone, old_info->account_id);
+        path.name = old_info->name;
+        remove_path = std::move(path);
+      } else {
+        // look up tenant path
+        IndexObj path;
+        path.obj = get_tenant_path_obj(zone, *old_info);
+        r = read_tenant_path(dpp, y, sysobj, path);
+        if (r == -ENOENT) {
+          // leave remove_path empty
+        } else if (r < 0) {
+          return r;
+        } else {
+          remove_path = std::move(path);
+        }
+      }
+    }
+  } // old_info
+
+  // write the new name object, fail on conflict
+  NameIndex new_name;
+  if (!same_name && !info.name.empty()) {
+    IndexObj name;
+    name.obj = get_name_obj(zone, info);
+    name.objv.generate_new_write_ver(dpp->get_cct());
+
+    r = write_name(dpp, y, sysobj, info.id, name);
+    if (r < 0) {
+      ldpp_dout(dpp, 1) << "failed to write name obj "
+          << name.obj << " with: " << cpp_strerror(r) << dendl;
+      return r;
+    }
+    new_name = std::move(name);
+  }
+
+  // check for path conflict
+  PathIndex new_path;
+  if (!same_path) {
+    r = write_path(dpp, y, rados, sysobj, zone, info, new_path);
+    if (r < 0) {
+      // roll back new name object
+      std::ignore = remove_index(dpp, y, sysobj, new_name);
+      return r;
+    }
+  }
+
+  // write info by id
+  r = write_info(dpp, y, sysobj, zone, info, objv, mtime, exclusive);
+  if (r < 0) {
+    // roll back the new name/path indices
+    std::ignore = remove_index(dpp, y, sysobj, new_name);
+    std::ignore = remove_index(dpp, y, rados, sysobj, new_path);
+    return r;
+  }
+
+  // remove the old name/path indices
+  std::ignore = remove_index(dpp, y, sysobj, remove_name);
+  std::ignore = remove_index(dpp, y, rados, sysobj, remove_path);
+
+  // record in the mdlog on success
+  if (mdlog) {
+    return mdlog->complete_entry(dpp, y, "roles", info.id, &objv);
+  }
+  return 0;
+}
+
+static int remove_by_id(const DoutPrefixProvider* dpp, optional_yield y,
+                        librados::Rados& rados, RGWSI_SysObj& sysobj,
+                        RGWSI_MDLog* mdlog, const RGWZoneParams& zone,
+                        std::string_view role_id)
+{
+  const rgw_raw_obj& obj = get_id_obj(zone, role_id);
+
+  RGWRoleInfo info;
+  int r = read_info(dpp, y, sysobj, obj, info,
+                    nullptr, &info.objv_tracker, nullptr);
+  if (r < 0) {
+    return r;
+  }
+
+  // delete role info
+  r = rgw_delete_system_obj(dpp, &sysobj, obj.pool, obj.oid,
+                            &info.objv_tracker, y);
+  if (r < 0) {
+    ldpp_dout(dpp, 1) << "ERROR: failed to remove role "
+        << info.id << " with: " << cpp_strerror(r) << dendl;
+    return r;
+  }
+
+  // delete the name object
+  if (!info.name.empty()) {
+    IndexObj name;
+    name.obj = get_name_obj(zone, info);
+    std::ignore = remove_index(dpp, y, sysobj, name);
+  }
+
+  // delete the path object
+  if (!info.account_id.empty()) {
+    AccountIndex path;
+    path.obj = account::get_roles_obj(zone, info.account_id);
+    path.name = info.name;
+    std::ignore = remove_index(dpp, y, rados, path);
+  } else {
+    IndexObj path;
+    path.obj = get_tenant_path_obj(zone, info);
+    std::ignore = remove_index(dpp, y, sysobj, path);
+  }
+
+  // record in the mdlog on success
+  if (mdlog) {
+    return mdlog->complete_entry(dpp, y, "roles", info.id, &info.objv_tracker);
+  }
+  return 0;
+}
+
+int remove(const DoutPrefixProvider* dpp, optional_yield y,
+           librados::Rados& rados, RGWSI_SysObj& sysobj, RGWSI_MDLog* mdlog,
+           const RGWZoneParams& zone, std::string_view tenant,
+           const rgw_account_id& account, std::string_view name)
+{
+  IndexObj n;
+  n.obj = get_name_obj(zone, tenant, account, name);
+  RGWNameToId name_to_id;
+
+  int r = read_name(dpp, y, sysobj, n, name_to_id);
+  if (r < 0) {
+    return r;
+  }
+
+  return remove_by_id(dpp, y, rados, sysobj, mdlog, zone, name_to_id.obj_id);
+}
+
+
+int list_tenant(const DoutPrefixProvider* dpp, optional_yield y,
+                RGWSI_SysObj& sysobj, const RGWZoneParams& zone,
+                std::string_view tenant, const std::string& marker,
+                int max_items, std::string_view path_prefix,
+                std::vector<RGWRoleInfo>& roles, std::string& next_marker)
+{
+  // List all roles if path prefix is empty
+  std::string prefix;
+  if (!path_prefix.empty()) {
+    prefix = string_cat_reserve(tenant, path_oid_prefix, path_prefix);
+  } else {
+    prefix = string_cat_reserve(tenant, path_oid_prefix, "/");
+  }
+
+  auto pool = sysobj.get_pool(zone.roles_pool);
+  auto listing = pool.op();
+  int r = listing.init(dpp, marker, prefix);
+  if (r < 0) {
+    return r;
+  }
+
+  std::vector<std::string> oids;
+  bool truncated = false;
+  r = listing.get_next(dpp, max_items, &oids, &truncated);
+  if (r < 0) {
+    return r;
+  }
+
+  for (auto& oid : oids) {
+    // remove the entire prefix
+    oid.erase(0, prefix.size());
+    // verify that the entire oid_prefix is still present (path_prefix may have
+    // matched part of it)
+    size_t pos = oid.rfind(oid_prefix);
+    if (pos == std::string::npos) {
+      continue;
+    }
+    // after trimming the oid_prefix, we should be left with just the role id
+    oid.erase(0, pos + oid_prefix.size());
+
+    RGWRoleInfo info;
+    r = read_by_id(dpp, y, sysobj, zone, oid, info, nullptr, nullptr, nullptr);
+    if (r == -ENOENT) {
+      continue; // ok, listing race with deletion
+    }
+    if (r < 0) {
+      return r;
+    }
+    roles.push_back(std::move(info));
+  }
+
+  if (truncated) {
+    listing.get_marker(&next_marker);
+  }
+  return 0;
+}
+
+
+class MetadataObject : public RGWMetadataObject {
+  RGWRoleInfo info;
+public:
+  MetadataObject(const RGWRoleInfo& info, const obj_version& v, real_time m)
+    : RGWMetadataObject(v, m), info(info) {}
+
+  void dump(Formatter *f) const override {
+    info.dump(f);
+  }
+
+  RGWRoleInfo& get_role_info() {
+    return info;
+  }
+};
+
+class MetadataLister : public RGWMetadataLister {
+ public:
+  using RGWMetadataLister::RGWMetadataLister;
+
+  virtual void filter_transform(std::vector<std::string>& oids,
+                                std::list<std::string>& keys) {
+    // remove the oid prefix from keys
+    constexpr auto trim = [] (const std::string& oid) {
+      return oid.substr(oid_prefix.size());
+    };
+    std::transform(oids.begin(), oids.end(),
+                   std::back_inserter(keys),
+                   trim);
+  }
+};
+
+class MetadataHandler : public RGWMetadataHandler {
+  librados::Rados& rados;
+  RGWSI_SysObj& sysobj;
+  RGWSI_MDLog& mdlog;
+  const RGWZoneParams& zone;
+ public:
+  MetadataHandler(librados::Rados& rados, RGWSI_SysObj& sysobj,
+                  RGWSI_MDLog& mdlog, const RGWZoneParams& zone)
+    : rados(rados), sysobj(sysobj), mdlog(mdlog), zone(zone) {}
+
+  std::string get_type() final { return "roles";  }
+
+  RGWMetadataObject* get_meta_obj(JSONObj *jo,
+                                  const obj_version& objv,
+                                  const ceph::real_time& mtime) override
+  {
+    RGWRoleInfo info;
+
+    try {
+      info.decode_json(jo);
+    } catch (JSONDecoder:: err& e) {
+      return nullptr;
+    }
+
+    return new MetadataObject(info, objv, mtime);
+  }
+
+  int get(std::string& entry, RGWMetadataObject** obj,
+          optional_yield y, const DoutPrefixProvider* dpp) override
+  {
+    RGWRoleInfo info;
+    int ret = read_by_id(dpp, y, sysobj, zone, entry, info,
+                         &info.mtime, &info.objv_tracker);
+    if (ret < 0) {
+      return ret;
+    }
+
+    *obj = new MetadataObject(info, info.objv_tracker.read_version, info.mtime);
+    return 0;
+  }
+
+  int put(std::string& entry, RGWMetadataObject* obj,
+          RGWObjVersionTracker& objv_tracker,
+          optional_yield y, const DoutPrefixProvider* dpp,
+          RGWMDLogSyncType type, bool from_remote_zone) override
+  {
+    auto robj = static_cast<MetadataObject*>(obj);
+    auto& info = robj->get_role_info();
+    info.mtime = robj->get_mtime();
+
+    constexpr bool exclusive = false;
+    int ret = write(dpp, y, rados, sysobj, &mdlog, zone, info,
+                    info.objv_tracker, info.mtime, exclusive);
+    return ret < 0 ? ret : STATUS_APPLIED;
+  }
+
+  int remove(std::string& entry, RGWObjVersionTracker& objv_tracker,
+             optional_yield y, const DoutPrefixProvider *dpp) override
+  {
+    return remove_by_id(dpp, y, rados, sysobj, &mdlog, zone, entry);
+  }
+
+  int mutate(const std::string& entry, const ceph::real_time& mtime,
+             RGWObjVersionTracker* objv_tracker, optional_yield y,
+             const DoutPrefixProvider* dpp, RGWMDLogStatus op_type,
+             std::function<int()> f) override
+  {
+    return -ENOTSUP; // unused
+  }
+
+  int list_keys_init(const DoutPrefixProvider* dpp,
+                     const std::string& marker,
+                     void** phandle) override
+  {
+    const auto& pool = zone.roles_pool;
+    auto lister = std::make_unique<MetadataLister>(sysobj.get_pool(pool));
+    int ret = lister->init(dpp, marker, oid_prefix);
+    if (ret < 0) {
+      return ret;
+    }
+    *phandle = lister.release(); // release ownership
+    return 0;
+  }
+
+  int list_keys_next(const DoutPrefixProvider* dpp,
+                     void* handle, int max,
+                     std::list<std::string>& keys,
+                     bool* truncated) override
+  {
+    auto lister = static_cast<RGWMetadataLister*>(handle);
+    return lister->get_next(dpp, max, keys, truncated);
+  }
+
+  void list_keys_complete(void *handle) override
+  {
+    delete static_cast<RGWMetadataLister*>(handle);
+  }
+
+  std::string get_marker(void *handle) override
+  {
+    auto lister = static_cast<RGWMetadataLister*>(handle);
+    return lister->get_marker();
+  }
+};
+
+
+auto create_metadata_handler(librados::Rados& rados,
+                             RGWSI_SysObj& sysobj,
+                             RGWSI_MDLog& mdlog,
+                             const RGWZoneParams& zone)
+    -> std::unique_ptr<RGWMetadataHandler>
+{
+  return std::make_unique<MetadataHandler>(rados, sysobj, mdlog, zone);
+}
+
+} // rgwrados::role
diff --git a/src/rgw/driver/rados/role.h b/src/rgw/driver/rados/role.h
new file mode 100644 (file)
index 0000000..7dc721c
--- /dev/null
@@ -0,0 +1,81 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab ft=cpp
+
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright contributors to the Ceph project
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+#pragma once
+
+#include <memory>
+#include <string>
+#include <vector>
+#include "include/rados/librados_fwd.hpp"
+#include "common/ceph_time.h"
+
+class DoutPrefixProvider;
+class optional_yield;
+struct rgw_account_id;
+struct rgw_cache_entry_info;
+class RGWMetadataHandler;
+class RGWObjVersionTracker;
+struct RGWRoleInfo;
+class RGWSI_MDLog;
+class RGWSI_SysObj;
+class RGWZoneParams;
+
+namespace rgwrados::role {
+
+/// Read role info by id.
+int read_by_id(const DoutPrefixProvider* dpp, optional_yield y,
+               RGWSI_SysObj& sysobj, const RGWZoneParams& zone,
+               std::string_view role_id, RGWRoleInfo& info,
+               ceph::real_time* pmtime = nullptr,
+               RGWObjVersionTracker* pobjv = nullptr,
+               rgw_cache_entry_info* pcache_info = nullptr);
+
+/// Read role info by name.
+int read_by_name(const DoutPrefixProvider* dpp, optional_yield y,
+                 RGWSI_SysObj& sysobj, const RGWZoneParams& zone,
+                 std::string_view tenant, const rgw_account_id& account,
+                 std::string_view name, RGWRoleInfo& info,
+                 ceph::real_time* pmtime = nullptr,
+                 RGWObjVersionTracker* pobjv = nullptr,
+                 rgw_cache_entry_info* pcache_info = nullptr);
+
+/// Write or overwrite role info and update its name/path objects.
+int write(const DoutPrefixProvider* dpp, optional_yield y,
+          librados::Rados& rados, RGWSI_SysObj& sysobj, RGWSI_MDLog* mdlog,
+          const RGWZoneParams& zone, const RGWRoleInfo& info,
+          RGWObjVersionTracker& objv, ceph::real_time mtime,
+          bool exclusive);
+
+/// Remove a role by name, including its name/path objects.
+int remove(const DoutPrefixProvider* dpp, optional_yield y,
+           librados::Rados& rados, RGWSI_SysObj& sysobj, RGWSI_MDLog* mdlog,
+           const RGWZoneParams& zone, std::string_view tenant,
+           const rgw_account_id& account, std::string_view name);
+
+/// Return a paginated listing of roles for the given tenant.
+int list_tenant(const DoutPrefixProvider* dpp, optional_yield y,
+                RGWSI_SysObj& sysobj, const RGWZoneParams& zone,
+                std::string_view tenant, const std::string& marker,
+                int max_items, std::string_view path_prefix,
+                std::vector<RGWRoleInfo>& roles, std::string& next_marker);
+
+/// Role metadata handler factory.
+auto create_metadata_handler(librados::Rados& rados,
+                             RGWSI_SysObj& sysobj,
+                             RGWSI_MDLog& mdlog,
+                             const RGWZoneParams& zone)
+    -> std::unique_ptr<RGWMetadataHandler>;
+
+} // rgwrados::role
index 6e894ae2d24e93132e916020d9fc5014b1e933df..d1b041f2423febad8a3203016b25d8a58b8ef5b7 100644 (file)
@@ -6855,7 +6855,7 @@ int main(int argc, const char **argv)
       }
       std::unique_ptr<rgw::sal::RGWRole> role = driver->get_role(role_name, tenant, account_id, path,
                                                                  assume_role_doc, description, max_session_duration);
-      ret = role->create(dpp(), true, "", null_yield);
+      ret = role->create(dpp(), "", null_yield);
       if (ret < 0) {
         return -ret;
       }
@@ -6884,7 +6884,7 @@ int main(int argc, const char **argv)
         return -EINVAL;
       }
       std::unique_ptr<rgw::sal::RGWRole> role = driver->get_role(role_name, tenant, account_id);
-      ret = role->get(dpp(), null_yield);
+      ret = role->load_by_name(dpp(), null_yield);
       if (ret < 0) {
         return -ret;
       }
@@ -6914,12 +6914,13 @@ int main(int argc, const char **argv)
       }
 
       std::unique_ptr<rgw::sal::RGWRole> role = driver->get_role(role_name, tenant, account_id);
-      ret = role->get(dpp(), null_yield);
+      ret = role->load_by_name(dpp(), null_yield);
       if (ret < 0) {
         return -ret;
       }
       role->update_trust_policy(assume_role_doc);
-      ret = role->update(dpp(), null_yield);
+      constexpr bool exclusive = false;
+      ret = role->store_info(dpp(), exclusive, null_yield);
       if (ret < 0) {
         return -ret;
       }
@@ -7009,12 +7010,13 @@ int main(int argc, const char **argv)
       }
 
       std::unique_ptr<rgw::sal::RGWRole> role = driver->get_role(role_name, tenant, account_id);
-      ret = role->get(dpp(), null_yield);
+      ret = role->load_by_name(dpp(), null_yield);
       if (ret < 0) {
         return -ret;
       }
       role->set_perm_policy(policy_name, perm_policy_doc);
-      ret = role->update(dpp(), null_yield);
+      constexpr bool exclusive = false;
+      ret = role->store_info(dpp(), exclusive, null_yield);
       if (ret < 0) {
         return -ret;
       }
@@ -7028,7 +7030,7 @@ int main(int argc, const char **argv)
         return -EINVAL;
       }
       std::unique_ptr<rgw::sal::RGWRole> role = driver->get_role(role_name, tenant, account_id);
-      ret = role->get(dpp(), null_yield);
+      ret = role->load_by_name(dpp(), null_yield);
       if (ret < 0) {
         return -ret;
       }
@@ -7048,7 +7050,7 @@ int main(int argc, const char **argv)
         return -EINVAL;
       }
       std::unique_ptr<rgw::sal::RGWRole> role = driver->get_role(role_name, tenant, account_id);
-      int ret = role->get(dpp(), null_yield);
+      int ret = role->load_by_name(dpp(), null_yield);
       if (ret < 0) {
         return -ret;
       }
@@ -7072,7 +7074,7 @@ int main(int argc, const char **argv)
         return -EINVAL;
       }
       std::unique_ptr<rgw::sal::RGWRole> role = driver->get_role(role_name, tenant, account_id);
-      ret = role->get(dpp(), null_yield);
+      ret = role->load_by_name(dpp(), null_yield);
       if (ret < 0) {
         return -ret;
       }
@@ -7080,7 +7082,8 @@ int main(int argc, const char **argv)
       if (ret < 0) {
         return -ret;
       }
-      ret = role->update(dpp(), null_yield);
+      constexpr bool exclusive = false;
+      ret = role->store_info(dpp(), exclusive, null_yield);
       if (ret < 0) {
         return -ret;
       }
@@ -7109,7 +7112,7 @@ int main(int argc, const char **argv)
       }
 
       std::unique_ptr<rgw::sal::RGWRole> role = driver->get_role(role_name, tenant, account_id);
-      ret = role->get(dpp(), null_yield);
+      ret = role->load_by_id(dpp(), null_yield);
       if (ret < 0) {
         return -ret;
       }
@@ -7124,7 +7127,8 @@ int main(int argc, const char **argv)
         cout << "That managed policy is already attached." << std::endl;
         return EEXIST;
       }
-      ret = role->update(dpp(), null_yield);
+      constexpr bool exclusive = false;
+      ret = role->store_info(dpp(), exclusive, null_yield);
       if (ret < 0) {
         return -ret;
       }
@@ -7143,7 +7147,7 @@ int main(int argc, const char **argv)
       }
 
       std::unique_ptr<rgw::sal::RGWRole> role = driver->get_role(role_name, tenant, account_id);
-      ret = role->get(dpp(), null_yield);
+      ret = role->load_by_id(dpp(), null_yield);
       if (ret < 0) {
         return -ret;
       }
@@ -7156,7 +7160,8 @@ int main(int argc, const char **argv)
       }
       policies.arns.erase(i);
 
-      ret = role->update(dpp(), null_yield);
+      constexpr bool exclusive = false;
+      ret = role->store_info(dpp(), exclusive, null_yield);
       if (ret < 0) {
         return -ret;
       }
@@ -7170,7 +7175,7 @@ int main(int argc, const char **argv)
         return EINVAL;
       }
       std::unique_ptr<rgw::sal::RGWRole> role = driver->get_role(role_name, tenant, account_id);
-      ret = role->get(dpp(), null_yield);
+      ret = role->load_by_id(dpp(), null_yield);
       if (ret < 0) {
         return -ret;
       }
@@ -7186,7 +7191,7 @@ int main(int argc, const char **argv)
       }
 
       std::unique_ptr<rgw::sal::RGWRole> role = driver->get_role(role_name, tenant, account_id);
-      ret = role->get(dpp(), null_yield);
+      ret = role->load_by_name(dpp(), null_yield);
       if (ret < 0) {
         return -ret;
       }
@@ -7195,7 +7200,8 @@ int main(int argc, const char **argv)
         ret = -EINVAL;
         return ret;
       }
-      ret = role->update(dpp(), null_yield);
+      constexpr bool exclusive = false;
+      ret = role->store_info(dpp(), exclusive, null_yield);
       if (ret < 0) {
         return -ret;
       }
index 00f6ff7dfc4aad8fa48fd1e7de1bb42daccdba70..5a4a8329b2b5d27d2397992d17921370faff4f7f 100644 (file)
@@ -83,7 +83,7 @@ int retry_raced_role_write(const DoutPrefixProvider* dpp, optional_yield y,
   int r = f();
   for (int i = 0; i < 10 && r == -ECANCELED; ++i) {
     role->get_objv_tracker().clear();
-    r = role->get_by_id(dpp, y);
+    r = role->load_by_id(dpp, y);
     if (r >= 0) {
       r = f();
     }
index b3d6b42ae6b9bb9e14f6b8dab349366fa6bf972b..a3733c175cc3c1c0b5d50e9bcef6b2f050883830 100644 (file)
@@ -114,7 +114,7 @@ static int load_role(const DoutPrefixProvider* dpp, optional_yield y,
                      rgw::ARN& resource, std::string& message)
 {
   role = driver->get_role(name, tenant, account_id);
-  const int r = role->get(dpp, y);
+  const int r = role->load_by_name(dpp, y);
   if (r == -ENOENT) {
     message = "No such RoleName in the tenant";
     return -ERR_NO_ROLE_FOUND;
@@ -312,7 +312,7 @@ void RGWCreateRole::execute(optional_yield y)
     ldpp_dout(this, 0) << "role_id decoded from master zonegroup response is " << role_id << dendl;
   }
 
-  op_ret = role->create(s, true, role_id, y);
+  op_ret = role->create(s, role_id, y);
   if (op_ret == -EEXIST) {
     if (site.is_meta_master()) {
       op_ret = -ERR_ROLE_EXISTS;
@@ -489,7 +489,8 @@ void RGWModifyRoleTrustPolicy::execute(optional_yield y)
   op_ret = retry_raced_role_write(this, y, role.get(),
       [this, y] {
         role->update_trust_policy(trust_policy);
-        return role->update(this, y);
+        constexpr bool exclusive = false;
+        return role->store_info(this, exclusive, y);
       });
 
   s->formatter->open_object_section("UpdateAssumeRolePolicyResponse");
@@ -625,7 +626,8 @@ void RGWPutRolePolicy::execute(optional_yield y)
   op_ret = retry_raced_role_write(this, y, role.get(),
       [this, y] {
         role->set_perm_policy(policy_name, perm_policy);
-        return role->update(this, y);
+        constexpr bool exclusive = false;
+        return role->store_info(this, exclusive, y);
       });
 
   if (op_ret == 0) {
@@ -766,7 +768,8 @@ void RGWDeleteRolePolicy::execute(optional_yield y)
           return -ERR_NO_SUCH_ENTITY;
         }
         if (r == 0) {
-          r = role->update(this, y);
+          constexpr bool exclusive = false;
+          r = role->store_info(this, exclusive, y);
         }
         return r;
       });
@@ -833,7 +836,8 @@ void RGWTagRole::execute(optional_yield y)
       [this, y] {
         int r = role->set_tags(this, tags);
         if (r == 0) {
-          r = role->update(this, y);
+          constexpr bool exclusive = false;
+          r = role->store_info(this, exclusive, y);
         }
         return r;
       });
@@ -940,7 +944,8 @@ void RGWUntagRole::execute(optional_yield y)
   op_ret = retry_raced_role_write(this, y, role.get(),
       [this, y] {
         role->erase_tags(untag);
-        return role->update(this, y);
+        constexpr bool exclusive = false;
+        return role->store_info(this, exclusive, y);
       });
 
   if (op_ret == 0) {
@@ -1009,15 +1014,18 @@ void RGWUpdateRole::execute(optional_yield y)
           return -EINVAL;
         }
 
-        return role->update(this, y);
+        constexpr bool exclusive = false;
+        return role->store_info(this, exclusive, y);
       });
 
-  s->formatter->open_object_section("UpdateRoleResponse");
-  s->formatter->open_object_section("UpdateRoleResult");
-  s->formatter->open_object_section("ResponseMetadata");
-  s->formatter->dump_string("RequestId", s->trans_id);
-  s->formatter->close_section();
-  s->formatter->close_section();
+  if (op_ret == 0) {
+    s->formatter->open_object_section("UpdateRoleResponse");
+    s->formatter->open_object_section("UpdateRoleResult");
+    s->formatter->open_object_section("ResponseMetadata");
+    s->formatter->dump_string("RequestId", s->trans_id);
+    s->formatter->close_section();
+    s->formatter->close_section();
+  }
 }
 
 static bool validate_policy_arn(const std::string& arn, std::string& err)
@@ -1127,7 +1135,8 @@ void RGWAttachRolePolicy_IAM::execute(optional_yield y)
         if (!policies.arns.insert(policy_arn).second) {
           return 0;
         }
-        return role->update(this, y);
+        constexpr bool exclusive = false;
+        return role->store_info(this, exclusive, y);
       });
 
   if (op_ret == 0) {
@@ -1217,7 +1226,9 @@ void RGWDetachRolePolicy_IAM::execute(optional_yield y)
           return -ERR_NO_SUCH_ENTITY;
         }
         policies.arns.erase(p);
-        return role->update(this, y);
+
+        constexpr bool exclusive = false;
+        return role->store_info(this, exclusive, y);
       });
 
   if (op_ret == 0) {
index b7c662c02c66fb5bf6b66a6df6384bb42de94b22..97f9deafeb626f7293b8762de4f389a3a1eac29f 100644 (file)
@@ -85,7 +85,6 @@ class RGWListRoles : public RGWRestRole {
   std::string path_prefix;
   std::string marker;
   int max_items = 100;
-  std::string next_marker;
 public:
   RGWListRoles() : RGWRestRole(rgw::IAM::iamListRoles, RGW_CAP_READ) {}
   int init_processing(optional_yield y) override;
index 8da355dd8162c9e7fa45dbf6808906733a84b14f..4a50baf1cb20195b763828215bb9013898832a1b 100644 (file)
@@ -6537,7 +6537,7 @@ rgw::auth::s3::STSEngine::authenticate(
   rgw::auth::RoleApplier::TokenAttrs t_attrs;
   if (! token.roleId.empty()) {
     std::unique_ptr<rgw::sal::RGWRole> role = driver->get_role(token.roleId);
-    if (role->get_by_id(dpp, y) < 0) {
+    if (role->load_by_id(dpp, y) < 0) {
       return result_t::deny(-EPERM);
     }
     r.id = token.roleId;
index dbe4994cfa52827c722ead050bfd2f6b325f7b69..f2bd9429a5538014bdaba8dd79f9b9f399a490d2 100644 (file)
@@ -496,7 +496,7 @@ WebTokenEngine::authenticate( const DoutPrefixProvider* dpp,
       }
 
       std::unique_ptr<rgw::sal::RGWRole> role = driver->get_role(role_name, role_tenant, role_account);
-      int ret = role->get(dpp, y);
+      int ret = role->load_by_name(dpp, y);
       if (ret < 0) {
         ldpp_dout(dpp, 0) << "Role not found: name:" << role_name << " tenant: " << role_tenant << dendl;
         return result_t::deny(-EACCES);
index c85f29d903572d859b2f775b3fb6b646803541da..d7070e4785e2b31ca588c3143e310a851d1cec3b 100644 (file)
@@ -131,9 +131,6 @@ void RGWRoleInfo::decode_json(JSONObj *obj)
 
 namespace rgw::sal {
 
-const string RGWRole::role_name_oid_prefix = "role_names.";
-const string RGWRole::role_oid_prefix = "roles.";
-const string RGWRole::role_path_oid_prefix = "role_paths.";
 const string RGWRole::role_arn_prefix = "arn:aws:iam::";
 
 RGWRole::RGWRole(std::string name,
@@ -168,31 +165,6 @@ RGWRole::RGWRole(std::string id)
   info.id = std::move(id);
 }
 
-int RGWRole::get(const DoutPrefixProvider *dpp, optional_yield y)
-{
-  int ret = read_name(dpp, y);
-  if (ret < 0) {
-    return ret;
-  }
-
-  ret = read_info(dpp, y);
-  if (ret < 0) {
-    return ret;
-  }
-
-  return 0;
-}
-
-int RGWRole::get_by_id(const DoutPrefixProvider *dpp, optional_yield y)
-{
-  int ret = read_info(dpp, y);
-  if (ret < 0) {
-    return ret;
-  }
-
-  return 0;
-}
-
 bool RGWRole::validate_max_session_duration(const DoutPrefixProvider* dpp)
 {
   if (info.max_session_duration < SESSION_DURATION_MIN ||
@@ -241,16 +213,46 @@ void RGWRole::extract_name_tenant(const std::string& str) {
   }
 }
 
-int RGWRole::update(const DoutPrefixProvider *dpp, optional_yield y)
+int RGWRole::create(const DoutPrefixProvider *dpp, const std::string& role_id, optional_yield y)
 {
-  int ret = store_info(dpp, false, y);
-  if (ret < 0) {
-    ldpp_dout(dpp, 0) << "ERROR:  storing info in Role pool: "
-                  << info.id << ": " << cpp_strerror(-ret) << dendl;
-    return ret;
+  if (! validate_input(dpp)) {
+    return -EINVAL;
   }
 
-  return 0;
+  if (!role_id.empty()) {
+    info.id = role_id;
+  }
+
+  if (info.id.empty()) {
+    /* create unique id */
+    uuid_d new_uuid;
+    char uuid_str[37];
+    new_uuid.generate_random();
+    new_uuid.print(uuid_str);
+    info.id = uuid_str;
+  }
+
+  //arn
+  std::string_view account = !info.account_id.empty() ? info.account_id : info.tenant;
+  info.arn = string_cat_reserve(role_arn_prefix, account, ":role", info.path, info.name);
+
+  if (info.creation_date.empty()) {
+    // Creation time
+    real_clock::time_point t = real_clock::now();
+
+    struct timeval tv;
+    real_clock::to_timeval(t, tv);
+
+    char buf[30];
+    struct tm result;
+    gmtime_r(&tv.tv_sec, &result);
+    strftime(buf,30,"%Y-%m-%dT%H:%M:%S", &result);
+    sprintf(buf + strlen(buf),".%03dZ",(int)tv.tv_usec/1000);
+    info.creation_date.assign(buf, strlen(buf));
+  }
+
+  constexpr bool exclusive = true;
+  return store_info(dpp, exclusive, y);
 }
 
 void RGWRole::set_perm_policy(const string& policy_name, const string& perm_policy)
@@ -334,203 +336,4 @@ void RGWRole::update_max_session_duration(const std::string& max_session_duratio
   }
 }
 
-const string& RGWRole::get_names_oid_prefix()
-{
-  return role_name_oid_prefix;
-}
-
-const string& RGWRole::get_info_oid_prefix()
-{
-  return role_oid_prefix;
-}
-
-const string& RGWRole::get_path_oid_prefix()
-{
-  return role_path_oid_prefix;
-}
-
 } // namespace rgw::sal
-
-
-class RGWRoleMetadataObject: public RGWMetadataObject {
-  RGWRoleInfo info;
-public:
-  RGWRoleMetadataObject(const RGWRoleInfo& info, const obj_version& v, real_time m)
-    : RGWMetadataObject(v, m), info(info) {}
-
-  void dump(Formatter *f) const override {
-    info.dump(f);
-  }
-
-  RGWRoleInfo& get_role_info() {
-    return info;
-  }
-};
-
-class RGWRoleMetadataHandler: public RGWMetadataHandler {
-  rgw::sal::Driver& driver;
-  RGWSI_SysObj& sysobj;
- public:
-  RGWRoleMetadataHandler(rgw::sal::Driver& driver, RGWSI_SysObj& sysobj)
-    : driver(driver), sysobj(sysobj) {}
-
-  std::string get_type() final { return "roles";  }
-
-  RGWMetadataObject *get_meta_obj(JSONObj *jo,
-                                 const obj_version& objv,
-                                 const ceph::real_time& mtime);
-
-  int get(std::string& entry, RGWMetadataObject** obj, optional_yield y,
-          const DoutPrefixProvider *dpp) override;
-  int put(std::string& entry, RGWMetadataObject* obj,
-          RGWObjVersionTracker& objv_tracker,
-          optional_yield y, const DoutPrefixProvider* dpp,
-          RGWMDLogSyncType type, bool from_remote_zone) override;
-  int remove(std::string& entry, RGWObjVersionTracker& objv_tracker,
-             optional_yield y, const DoutPrefixProvider *dpp) override;
-
-  int mutate(const std::string& entry, const ceph::real_time& mtime,
-             RGWObjVersionTracker* objv_tracker, optional_yield y,
-             const DoutPrefixProvider* dpp, RGWMDLogStatus op_type,
-             std::function<int()> f) override;
-
-  int list_keys_init(const DoutPrefixProvider* dpp, const std::string& marker,
-                     void** phandle) override;
-  int list_keys_next(const DoutPrefixProvider* dpp, void* handle, int max,
-                     std::list<std::string>& keys, bool* truncated) override;
-  void list_keys_complete(void *handle) override;
-  std::string get_marker(void *handle) override;
-};
-
-RGWMetadataObject *RGWRoleMetadataHandler::get_meta_obj(JSONObj *jo,
-                                                       const obj_version& objv,
-                                                       const ceph::real_time& mtime)
-{
-  RGWRoleInfo info;
-
-  try {
-    info.decode_json(jo);
-  } catch (JSONDecoder:: err& e) {
-    return nullptr;
-  }
-
-  return new RGWRoleMetadataObject(info, objv, mtime);
-}
-
-int RGWRoleMetadataHandler::get(std::string& entry, RGWMetadataObject **obj,
-                                optional_yield y, const DoutPrefixProvider *dpp)
-{
-  std::unique_ptr<rgw::sal::RGWRole> role = driver.get_role(entry);
-  int ret = role->read_info(dpp, y);
-  if (ret < 0) {
-    return ret;
-  }
-
-  const RGWRoleInfo& info = role->get_info();
-  RGWObjVersionTracker objv_tracker = role->get_objv_tracker();
-  real_time mtime = role->get_mtime();
-
-  *obj = new RGWRoleMetadataObject(info, objv_tracker.read_version, mtime);
-
-  return 0;
-}
-
-int RGWRoleMetadataHandler::put(std::string& entry, RGWMetadataObject *obj,
-                                RGWObjVersionTracker& objv_tracker,
-                                optional_yield y, const DoutPrefixProvider *dpp,
-                                RGWMDLogSyncType type, bool from_remote_zone)
-{
-  auto robj = static_cast<RGWRoleMetadataObject*>(obj);
-  auto& info = robj->get_role_info();
-  auto mtime = robj->get_mtime();
-  info.mtime = mtime;
-
-  std::unique_ptr<rgw::sal::RGWRole> role = driver.get_role(info);
-  int ret = role->create(dpp, true, info.id, y);
-  if (ret == -EEXIST) {
-    ret = role->update(dpp, y);
-  }
-
-  return ret < 0 ? ret : STATUS_APPLIED;
-}
-
-int RGWRoleMetadataHandler::remove(std::string& entry,
-                                   RGWObjVersionTracker& objv_tracker,
-                                   optional_yield y,
-                                   const DoutPrefixProvider *dpp)
-{
-  std::unique_ptr<rgw::sal::RGWRole> role = driver.get_role(entry);
-  int ret = role->read_info(dpp, y);
-  if (ret < 0) {
-    return ret == -ENOENT? 0 : ret;
-  }
-
-  return role->delete_obj(dpp, y);
-}
-
-int RGWRoleMetadataHandler::mutate(const std::string& entry, const ceph::real_time& mtime,
-                                   RGWObjVersionTracker* objv_tracker, optional_yield y,
-                                   const DoutPrefixProvider* dpp, RGWMDLogStatus op_type,
-                                   std::function<int()> f)
-{
-  return -ENOTSUP; // unused
-}
-
-class RoleLister : public RGWMetadataLister {
- public:
-  using RGWMetadataLister::RGWMetadataLister;
-
-  virtual void filter_transform(std::vector<std::string>& oids,
-                                std::list<std::string>& keys) {
-    // remove the oid prefix from keys
-    constexpr auto trim = [] (const std::string& oid) {
-      return oid.substr(rgw::sal::RGWRole::role_oid_prefix.size());
-    };
-    std::transform(oids.begin(), oids.end(),
-                   std::back_inserter(keys),
-                   trim);
-  }
-};
-
-int RGWRoleMetadataHandler::list_keys_init(const DoutPrefixProvider* dpp,
-                                           const std::string& marker,
-                                           void** phandle)
-{
-  auto svc_zone = sysobj.get_zone_svc();
-  const auto& pool = svc_zone->get_zone_params().roles_pool;
-  auto lister = std::make_unique<RoleLister>(sysobj.get_pool(pool));
-  int ret = lister->init(dpp, marker, rgw::sal::RGWRole::role_oid_prefix);
-  if (ret < 0) {
-    return ret;
-  }
-  *phandle = lister.release(); // release ownership
-  return 0;
-}
-
-int RGWRoleMetadataHandler::list_keys_next(const DoutPrefixProvider* dpp,
-                                           void* handle, int max,
-                                           std::list<std::string>& keys,
-                                           bool* truncated)
-{
-  auto lister = static_cast<RGWMetadataLister*>(handle);
-  return lister->get_next(dpp, max, keys, truncated);
-}
-
-void RGWRoleMetadataHandler::list_keys_complete(void *handle)
-{
-  delete static_cast<RGWMetadataLister*>(handle);
-}
-
-std::string RGWRoleMetadataHandler::get_marker(void *handle)
-{
-  auto lister = static_cast<RGWMetadataLister*>(handle);
-  return lister->get_marker();
-}
-
-
-auto create_role_metadata_handler(rgw::sal::Driver& driver,
-                                  RGWSI_SysObj& sysobj)
-    -> std::unique_ptr<RGWMetadataHandler>
-{
-  return std::make_unique<RGWRoleMetadataHandler>(driver, sysobj);
-}
index eae42a752fb17b2ec1428f53d00c09cbd4d03486..081259ceaa4db685bf4dd352a8fa21b14c2ae902 100644 (file)
@@ -30,7 +30,6 @@ struct RGWRoleInfo // TODO: move to rgw_common.h
   std::string description;
   uint64_t max_session_duration = 0;
   std::multimap<std::string,std::string> tags;
-  std::map<std::string, bufferlist> attrs;
   RGWObjVersionTracker objv_tracker;
   ceph::real_time mtime;
   rgw_account_id account_id;
@@ -89,9 +88,6 @@ namespace rgw::sal {
 class RGWRole
 {
 public:
-  static const std::string role_name_oid_prefix;
-  static const std::string role_oid_prefix;
-  static const std::string role_path_oid_prefix;
   static const std::string role_arn_prefix;
   static constexpr int MAX_ROLE_NAME_LEN = 64;
   static constexpr int MAX_PATH_NAME_LEN = 512;
@@ -100,12 +96,6 @@ public:
 protected:
   RGWRoleInfo info;
 public:
-  virtual int store_info(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y) = 0;
-  virtual int store_name(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y) = 0;
-  virtual int store_path(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y) = 0;
-  virtual int read_id(const DoutPrefixProvider *dpp, const std::string& role_name, const std::string& tenant, std::string& role_id, optional_yield y) = 0;
-  virtual int read_name(const DoutPrefixProvider *dpp, optional_yield y) = 0;
-  virtual int read_info(const DoutPrefixProvider *dpp, optional_yield y) = 0;
   bool validate_max_session_duration(const DoutPrefixProvider* dpp);
   bool validate_input(const DoutPrefixProvider* dpp);
   void extract_name_tenant(const std::string& str);
@@ -127,6 +117,12 @@ public:
 
   virtual ~RGWRole() = default;
 
+  // virtual interface
+  virtual int load_by_name(const DoutPrefixProvider *dpp, optional_yield y) = 0;
+  virtual int load_by_id(const DoutPrefixProvider *dpp, optional_yield y) = 0;
+  virtual int store_info(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y) = 0;
+  virtual int delete_obj(const DoutPrefixProvider *dpp, optional_yield y) = 0;
+
   const std::string& get_id() const { return info.id; }
   const std::string& get_name() const { return info.name; }
   const std::string& get_tenant() const { return info.tenant; }
@@ -138,17 +134,12 @@ public:
   RGWObjVersionTracker& get_objv_tracker() { return info.objv_tracker; }
   const RGWObjVersionTracker& get_objv_tracker() const { return info.objv_tracker; }
   const real_time& get_mtime() const { return info.mtime; }
-  std::map<std::string, bufferlist>& get_attrs() { return info.attrs; }
   RGWRoleInfo& get_info() { return info; }
 
   void set_id(const std::string& id) { this->info.id = id; }
   void set_mtime(const real_time& mtime) { this->info.mtime = mtime; }
 
-  virtual int create(const DoutPrefixProvider *dpp, bool exclusive, const std::string &role_id, optional_yield y) = 0;
-  virtual int delete_obj(const DoutPrefixProvider *dpp, optional_yield y) = 0;
-  int get(const DoutPrefixProvider *dpp, optional_yield y);
-  int get_by_id(const DoutPrefixProvider *dpp, optional_yield y);
-  int update(const DoutPrefixProvider *dpp, optional_yield y);
+  int create(const DoutPrefixProvider *dpp, const std::string &role_id, optional_yield y);
   void update_trust_policy(std::string& trust_policy);
   void set_perm_policy(const std::string& policy_name, const std::string& perm_policy);
   std::vector<std::string> get_role_policy_names();
@@ -158,18 +149,6 @@ public:
   boost::optional<std::multimap<std::string,std::string>> get_tags();
   void erase_tags(const std::vector<std::string>& tagKeys);
   void update_max_session_duration(const std::string& max_session_duration_str);
-
-  static const std::string& get_names_oid_prefix();
-  static const std::string& get_info_oid_prefix();
-  static const std::string& get_path_oid_prefix();
 };
 
 } // namespace rgw::sal
-
-
-class RGWMetadataHandler;
-class RGWSI_SysObj;
-
-auto create_role_metadata_handler(rgw::sal::Driver& driver,
-                                  RGWSI_SysObj& sysobj)
-    -> std::unique_ptr<RGWMetadataHandler>;
index f879e0f45c19df0786f5e1eb7b64e946821a8a92..7e8e37b3419d09fd99d196d3dc4ad087d7e45a9f 100644 (file)
@@ -300,7 +300,7 @@ std::tuple<int, rgw::sal::RGWRole*> STSService::getRoleInfo(const DoutPrefixProv
     }
 
     std::unique_ptr<rgw::sal::RGWRole> role = driver->get_role(roleName, tenant, account);
-    if (int ret = role->get(dpp, y); ret < 0) {
+    if (int ret = role->load_by_name(dpp, y); ret < 0) {
       if (ret == -ENOENT) {
         ldpp_dout(dpp, 0) << "Role doesn't exist: " << roleName << dendl;
         ret = -ERR_NO_ROLE_FOUND;