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
#include "common/Clock.h"
#include "common/errno.h"
+#include "role.h"
#include "rgw_sal.h"
#include "rgw_sal_rados.h"
#include "rgw_bucket.h"
// 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;
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.";
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
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
#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"
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(
--- /dev/null
+// -*- 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
--- /dev/null
+// -*- 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
}
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;
}
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;
}
}
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;
}
}
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;
}
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;
}
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;
}
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;
}
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;
}
}
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;
}
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;
}
}
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;
}
}
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;
}
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;
}
}
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;
}
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;
}
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();
}
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;
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;
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");
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) {
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;
});
[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;
});
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) {
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)
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) {
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) {
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;
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;
}
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);
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,
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 ||
}
}
-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)
}
}
-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);
-}
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;
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;
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);
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; }
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();
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>;
}
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;