From: Krunal Chheda Date: Wed, 25 Feb 2026 21:30:49 +0000 (-0500) Subject: rgw/oidc rados: add rgwrados::oidcs namespace abstraction for cls_user for accounts. X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=6c0ca320f9418bd212769b33ef1185d324062024;p=ceph.git rgw/oidc rados: add rgwrados::oidcs namespace abstraction for cls_user for accounts. Signed-off-by: Krunal Chheda --- diff --git a/src/rgw/CMakeLists.txt b/src/rgw/CMakeLists.txt index 41b349bdd9fb..86578969ddc1 100644 --- a/src/rgw/CMakeLists.txt +++ b/src/rgw/CMakeLists.txt @@ -217,6 +217,7 @@ if(WITH_RADOSGW_RADOS) driver/rados/rgw_trim_mdlog.cc driver/rados/rgw_user.cc driver/rados/oidc.cc + driver/rados/oidcs.cc driver/rados/role.cc driver/rados/roles.cc driver/rados/sync_fairness.cc diff --git a/src/rgw/driver/rados/account.cc b/src/rgw/driver/rados/account.cc index cd65f0fdd0f4..d746c7d2dbff 100644 --- a/src/rgw/driver/rados/account.cc +++ b/src/rgw/driver/rados/account.cc @@ -37,6 +37,7 @@ static constexpr std::string_view users_oid_prefix = "users."; static constexpr std::string_view groups_oid_prefix = "groups."; static constexpr std::string_view roles_oid_prefix = "roles."; static constexpr std::string_view topics_oid_prefix = "topics."; +static constexpr std::string_view oidcs_oid_prefix = "oidcs."; static const std::string account_oid_prefix = "account."; static constexpr std::string_view name_oid_prefix = "name."; @@ -81,6 +82,14 @@ rgw_raw_obj get_topics_obj(const RGWZoneParams& zone, return {zone.account_pool, get_topics_key(account_id)}; } +static std::string get_oidcs_key(std::string_view account_id) { + return string_cat_reserve(oidcs_oid_prefix, account_id); +} +rgw_raw_obj get_oidcs_obj(const RGWZoneParams& zone, + std::string_view account_id) { + return {zone.account_pool, get_oidcs_key(account_id)}; +} + static std::string get_account_key(std::string_view account_id) { return string_cat_reserve(account_oid_prefix, account_id); } diff --git a/src/rgw/driver/rados/account.h b/src/rgw/driver/rados/account.h index 2a54e4b5c166..9fb407911ec0 100644 --- a/src/rgw/driver/rados/account.h +++ b/src/rgw/driver/rados/account.h @@ -66,6 +66,12 @@ rgw_raw_obj get_roles_obj(const RGWZoneParams& zone, rgw_raw_obj get_topics_obj(const RGWZoneParams& zone, std::string_view account_id); +/// Return the rados object that tracks the given account's OIDC providers. This +/// can be used with the cls_user interface in namespace rgwrados::oidcs. +rgw_raw_obj get_oidcs_obj( + const RGWZoneParams& zone, + std::string_view account_id); + /// Read account info by id int read(const DoutPrefixProvider* dpp, diff --git a/src/rgw/driver/rados/oidc.cc b/src/rgw/driver/rados/oidc.cc index d4df60ef5e97..31881d3e3a9f 100644 --- a/src/rgw/driver/rados/oidc.cc +++ b/src/rgw/driver/rados/oidc.cc @@ -15,7 +15,12 @@ #include "oidc.h" +#include + +#include "account.h" +#include "oidcs.h" #include "common/errno.h" +#include "rgw_account.h" #include "rgw_common.h" #include "rgw_metadata.h" #include "rgw_metadata_lister.h" @@ -151,6 +156,17 @@ write( return r; } + if (rgw::account::validate_id(info.tenant)) { + // link the OIDC provider to its account + const auto& oidcs = account::get_oidcs_obj(zone, info.tenant); + r = oidcs::add( + dpp, y, rados, oidcs, info, false, + std::numeric_limits::max()); + if (r < 0) { + ldpp_dout(dpp, 0) << "WARNING: could not link OIDC provider to account " + << info.tenant << ": " << cpp_strerror(r) << dendl; + } // not fatal + } // record in the mdlog on success if (mdlog) { @@ -183,6 +199,15 @@ remove( return r; } + if (rgw::account::validate_id(tenant)) { + // unlink the OIDC provider from its account + const auto& oidcs = account::get_oidcs_obj(zone, std::string(tenant)); + r = oidcs::remove(dpp, y, rados, oidcs, url); + if (r < 0) { + ldpp_dout(dpp, 0) << "ERROR: could not unlink OIDC provider from account " + << tenant << ": " << cpp_strerror(r) << dendl; + } // not fatal + } // record in the mdlog on success if (mdlog) { @@ -201,6 +226,11 @@ list( std::string_view tenant, std::vector& providers) { + // Use optimized account index if tenant is an account + if (rgw::account::validate_id(tenant)) { + return list_account_oidcs(dpp, y, sysobj, rados, zone, tenant, providers); + } + // Prefix format: "{tenant}oidc_url." to match original implementation std::string prefix = string_cat_reserve(tenant, oidc_url_oid_prefix); auto& pool = zone.oidc_pool; @@ -253,6 +283,69 @@ list( return 0; } +int +list_oidc_urls( + const DoutPrefixProvider* dpp, + optional_yield y, + librados::Rados& rados, + const RGWZoneParams& zone, + std::string_view account_id, + std::string_view marker, + uint32_t max_items, + std::vector& urls, + std::string& next_marker) +{ + const rgw_raw_obj obj = account::get_oidcs_obj(zone, account_id); + return oidcs::list(dpp, y, rados, obj, marker, max_items, urls, next_marker); +} + +int +list_account_oidcs( + const DoutPrefixProvider* dpp, + optional_yield y, + RGWSI_SysObj& sysobj, + librados::Rados& rados, + const RGWZoneParams& zone, + std::string_view account_id, + std::vector& providers) +{ + // Use the account index to get OIDC provider URLs + std::vector urls; + std::string marker; + std::string next_marker; + + do { + urls.clear(); + int r = list_oidc_urls(dpp, y, rados, zone, account_id, marker, + 1000, urls, next_marker); + if (r < 0) { + ldpp_dout(dpp, 0) << "ERROR: failed to list OIDC provider URLs for account " + << account_id << ": " << cpp_strerror(r) << dendl; + return r; + } + + for (const auto& url : urls) { + RGWOIDCProviderInfo info; + r = read(dpp, y, sysobj, zone, account_id, url, info); + if (r == -ENOENT) { + // OIDC provider was deleted, skip it + ldpp_dout(dpp, 10) << "OIDC provider " << url << " not found, skipping" << dendl; + continue; + } + if (r < 0) { + ldpp_dout(dpp, 0) << "ERROR: failed to read OIDC provider " << url + << ": " << cpp_strerror(r) << dendl; + return r; + } + providers.push_back(std::move(info)); + } + + marker = next_marker; + } while (!next_marker.empty()); + + return 0; +} + class MetadataObject : public RGWMetadataObject { RGWOIDCProviderInfo info; diff --git a/src/rgw/driver/rados/oidc.h b/src/rgw/driver/rados/oidc.h index ab1e845570c4..91e39fc12d51 100644 --- a/src/rgw/driver/rados/oidc.h +++ b/src/rgw/driver/rados/oidc.h @@ -79,6 +79,28 @@ int list( std::string_view tenant, std::vector& providers); +/// List OIDC provider URLs for an account (paginated). +int list_oidc_urls( + const DoutPrefixProvider* dpp, + optional_yield y, + librados::Rados& rados, + const RGWZoneParams& zone, + std::string_view account_id, + std::string_view marker, + uint32_t max_items, + std::vector& urls, + std::string& next_marker); + +/// List all OIDC providers for an account using optimized account index. +int list_account_oidcs( + const DoutPrefixProvider* dpp, + optional_yield y, + RGWSI_SysObj& sysobj, + librados::Rados& rados, + const RGWZoneParams& zone, + std::string_view account_id, + std::vector& providers); + /// OIDC provider metadata handler factory. auto create_metadata_handler( librados::Rados& rados, diff --git a/src/rgw/driver/rados/oidcs.cc b/src/rgw/driver/rados/oidcs.cc new file mode 100644 index 000000000000..4d38cb2c53a3 --- /dev/null +++ b/src/rgw/driver/rados/oidcs.cc @@ -0,0 +1,116 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:nil -*- +// vim: ts=8 sw=2 sts=2 expandtab 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 "oidcs.h" + +#include "include/rados/librados.hpp" +#include "cls/user/cls_user_client.h" +#include "rgw_common.h" +#include "rgw_oidc_provider.h" +#include "rgw_sal.h" + +namespace rgwrados::oidcs { + +int +add( + const DoutPrefixProvider* dpp, + optional_yield y, + librados::Rados& rados, + const rgw_raw_obj& obj, + const RGWOIDCProviderInfo& info, + bool exclusive, + uint32_t limit) +{ + cls_user_account_resource resource; + resource.name = url_remove_prefix(info.provider_url); + + rgw_rados_ref ref; + int r = rgw_get_rados_ref(dpp, &rados, obj, &ref); + if (r < 0) { + return r; + } + + librados::ObjectWriteOperation op; + ::cls_user_account_resource_add(op, resource, exclusive, limit); + return ref.operate(dpp, std::move(op), y); +} + +int +remove( + const DoutPrefixProvider* dpp, + optional_yield y, + librados::Rados& rados, + const rgw_raw_obj& obj, + std::string_view provider_url) +{ + rgw_rados_ref ref; + int r = rgw_get_rados_ref(dpp, &rados, obj, &ref); + if (r < 0) { + return r; + } + + librados::ObjectWriteOperation op; + ::cls_user_account_resource_rm(op, provider_url); + return ref.operate(dpp, std::move(op), y); +} + +int +list( + const DoutPrefixProvider* dpp, + optional_yield y, + librados::Rados& rados, + const rgw_raw_obj& obj, + std::string_view marker, + uint32_t max_items, + std::vector& provider_urls, + std::string& next_marker) +{ + rgw_rados_ref ref; + int r = rgw_get_rados_ref(dpp, &rados, obj, &ref); + if (r < 0) { + return r; + } + + librados::ObjectReadOperation op; + const std::string path_prefix; // unused + std::vector entries; + bool truncated = false; + int ret = 0; + ::cls_user_account_resource_list( + op, marker, path_prefix, max_items, + entries, &truncated, &next_marker, &ret); + + r = ref.operate(dpp, std::move(op), nullptr, y); + if (r == -ENOENT) { + next_marker.clear(); + return 0; + } + if (r < 0) { + return r; + } + if (ret < 0) { + return ret; + } + + for (auto& resource : entries) { + provider_urls.push_back(std::move(resource.name)); + } + + return 0; +} + +} // namespace rgwrados::oidcs + + diff --git a/src/rgw/driver/rados/oidcs.h b/src/rgw/driver/rados/oidcs.h new file mode 100644 index 000000000000..af833b3e5a7c --- /dev/null +++ b/src/rgw/driver/rados/oidcs.h @@ -0,0 +1,59 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:nil -*- +// vim: ts=8 sw=2 sts=2 expandtab 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 +#include +#include +#include "include/rados/librados_fwd.hpp" +#include "rgw_sal_fwd.h" + +class DoutPrefixProvider; +class optional_yield; +struct rgw_raw_obj; +struct RGWOIDCProviderInfo; + + +namespace rgwrados::oidcs { + +/// Add the given OIDC provider to the list. +int add(const DoutPrefixProvider* dpp, + optional_yield y, + librados::Rados& rados, + const rgw_raw_obj& obj, + const RGWOIDCProviderInfo& info, + bool exclusive, uint32_t limit); + +/// Remove the given OIDC provider from the list. +int remove(const DoutPrefixProvider* dpp, + optional_yield y, + librados::Rados& rados, + const rgw_raw_obj& obj, + std::string_view provider_url); + +/// Return a paginated listing of OIDC provider URLs. +int list(const DoutPrefixProvider* dpp, + optional_yield y, + librados::Rados& rados, + const rgw_raw_obj& obj, + std::string_view marker, + uint32_t max_items, + std::vector& provider_urls, + std::string& next_marker); + +} // namespace rgwrados::oidcs + +