From cbbe8e8680387878bb5e7e447587891319086ada Mon Sep 17 00:00:00 2001 From: Daniel Gryniewicz Date: Wed, 17 Mar 2021 09:22:22 -0400 Subject: [PATCH] RGW Zipper - Remove rgw_pool/sysobj from API rgw_pool and sysobj are part of the RADOS backend, and do not belong in the API. Instead, pull the objects using them into the API. These are: RGWOIDCProvider, RGWRole, and a new object LuaScript. Signed-off-by: Daniel Gryniewicz --- src/rgw/rgw_admin.cc | 68 ++-- src/rgw/rgw_lua.cc | 72 +---- src/rgw/rgw_lua.h | 4 +- src/rgw/rgw_oidc_provider.cc | 129 +------- src/rgw/rgw_oidc_provider.h | 109 +++---- src/rgw/rgw_rest_oidc_provider.cc | 31 +- src/rgw/rgw_rest_role.cc | 55 ++-- src/rgw/rgw_rest_role.h | 4 +- src/rgw/rgw_rest_s3.cc | 12 +- src/rgw/rgw_rest_sts.cc | 14 +- src/rgw/rgw_rest_sts.h | 2 +- src/rgw/rgw_role.cc | 341 +------------------- src/rgw/rgw_role.h | 136 +++----- src/rgw/rgw_sal.h | 47 ++- src/rgw/rgw_sal_rados.cc | 517 ++++++++++++++++++++++++++++-- src/rgw/rgw_sal_rados.h | 91 +++++- src/rgw/rgw_sts.cc | 24 +- src/rgw/rgw_sts.h | 4 +- 18 files changed, 843 insertions(+), 817 deletions(-) diff --git a/src/rgw/rgw_admin.cc b/src/rgw/rgw_admin.cc index cafe1ea7ebaaa..204df3aae0e38 100644 --- a/src/rgw/rgw_admin.cc +++ b/src/rgw/rgw_admin.cc @@ -1084,20 +1084,20 @@ static void show_policy_names(std::vector policy_names, Formatter* forma formatter->flush(cout); } -static void show_role_info(RGWRole& role, Formatter* formatter) +static void show_role_info(rgw::sal::RGWRole* role, Formatter* formatter) { formatter->open_object_section("role"); - role.dump(formatter); + role->dump(formatter); formatter->close_section(); formatter->flush(cout); } -static void show_roles_info(vector& roles, Formatter* formatter) +static void show_roles_info(vector>& roles, Formatter* formatter) { formatter->open_array_section("Roles"); for (const auto& it : roles) { formatter->open_object_section("role"); - it.dump(formatter); + it->dump(formatter); formatter->close_section(); } formatter->close_section(); @@ -5798,12 +5798,12 @@ int main(int argc, const char **argv) cerr << "failed to parse policy: " << e.what() << std::endl; return -EINVAL; } - RGWRole role(g_ceph_context, store, role_name, path, assume_role_doc, tenant); - ret = role.create(dpp(), true, null_yield); + std::unique_ptr role = store->get_role(role_name, tenant, path, assume_role_doc); + ret = role->create(dpp(), true, null_yield); if (ret < 0) { return -ret; } - show_role_info(role, formatter.get()); + show_role_info(role.get(), formatter.get()); return 0; } case OPT::ROLE_DELETE: @@ -5812,8 +5812,8 @@ int main(int argc, const char **argv) cerr << "ERROR: empty role name" << std::endl; return -EINVAL; } - RGWRole role(g_ceph_context, store, role_name, tenant); - ret = role.delete_obj(dpp(), null_yield); + std::unique_ptr role = store->get_role(role_name, tenant); + ret = role->delete_obj(dpp(), null_yield); if (ret < 0) { return -ret; } @@ -5826,12 +5826,12 @@ int main(int argc, const char **argv) cerr << "ERROR: empty role name" << std::endl; return -EINVAL; } - RGWRole role(g_ceph_context, store, role_name, tenant); - ret = role.get(dpp(), null_yield); + std::unique_ptr role = store->get_role(role_name, tenant); + ret = role->get(dpp(), null_yield); if (ret < 0) { return -ret; } - show_role_info(role, formatter.get()); + show_role_info(role.get(), formatter.get()); return 0; } case OPT::ROLE_MODIFY: @@ -5854,13 +5854,13 @@ int main(int argc, const char **argv) return -EINVAL; } - RGWRole role(g_ceph_context, store, role_name, tenant); - ret = role.get(dpp(), null_yield); + std::unique_ptr role = store->get_role(role_name, tenant); + ret = role->get(dpp(), null_yield); if (ret < 0) { return -ret; } - role.update_trust_policy(assume_role_doc); - ret = role.update(null_yield); + role->update_trust_policy(assume_role_doc); + ret = role->update(dpp(), null_yield); if (ret < 0) { return -ret; } @@ -5869,8 +5869,8 @@ int main(int argc, const char **argv) } case OPT::ROLE_LIST: { - vector result; - ret = RGWRole::get_roles_by_path_prefix(dpp(), store, g_ceph_context, path_prefix, tenant, result, null_yield); + vector> result; + ret = store->get_roles(dpp(), null_yield, path_prefix, tenant, result); if (ret < 0) { return -ret; } @@ -5902,13 +5902,13 @@ int main(int argc, const char **argv) return -EINVAL; } - RGWRole role(g_ceph_context, store, role_name, tenant); - ret = role.get(dpp(), null_yield); + std::unique_ptr role = store->get_role(role_name, tenant); + ret = role->get(dpp(), null_yield); if (ret < 0) { return -ret; } - role.set_perm_policy(policy_name, perm_policy_doc); - ret = role.update(null_yield); + role->set_perm_policy(policy_name, perm_policy_doc); + ret = role->update(dpp(), null_yield); if (ret < 0) { return -ret; } @@ -5921,12 +5921,12 @@ int main(int argc, const char **argv) cerr << "ERROR: Role name is empty" << std::endl; return -EINVAL; } - RGWRole role(g_ceph_context, store, role_name, tenant); - ret = role.get(dpp(), null_yield); + std::unique_ptr role = store->get_role(role_name, tenant); + ret = role->get(dpp(), null_yield); if (ret < 0) { return -ret; } - std::vector policy_names = role.get_role_policy_names(); + std::vector policy_names = role->get_role_policy_names(); show_policy_names(policy_names, formatter.get()); return 0; } @@ -5941,13 +5941,13 @@ int main(int argc, const char **argv) cerr << "ERROR: policy name is empty" << std::endl; return -EINVAL; } - RGWRole role(g_ceph_context, store, role_name, tenant); - int ret = role.get(dpp(), null_yield); + std::unique_ptr role = store->get_role(role_name, tenant); + int ret = role->get(dpp(), null_yield); if (ret < 0) { return -ret; } string perm_policy; - ret = role.get_role_policy(policy_name, perm_policy); + ret = role->get_role_policy(dpp(), policy_name, perm_policy); if (ret < 0) { return -ret; } @@ -5965,16 +5965,16 @@ int main(int argc, const char **argv) cerr << "ERROR: policy name is empty" << std::endl; return -EINVAL; } - RGWRole role(g_ceph_context, store, role_name, tenant); - ret = role.get(dpp(), null_yield); + std::unique_ptr role = store->get_role(role_name, tenant); + ret = role->get(dpp(), null_yield); if (ret < 0) { return -ret; } - ret = role.delete_policy(policy_name); + ret = role->delete_policy(dpp(), policy_name); if (ret < 0) { return -ret; } - ret = role.update(null_yield); + ret = role->update(dpp(), null_yield); if (ret < 0) { return -ret; } @@ -9312,7 +9312,7 @@ next: cerr << "ERROR: invalid script context: " << *str_script_ctx << ". must be one of: preRequest, postRequest" << std::endl; return EINVAL; } - rc = rgw::lua::write_script(store, tenant, null_yield, script_ctx, script); + rc = rgw::lua::write_script(dpp(), store, tenant, null_yield, script_ctx, script); if (rc < 0) { cerr << "ERROR: failed to put script. error: " << rc << std::endl; return -rc; @@ -9352,7 +9352,7 @@ next: cerr << "ERROR: invalid script context: " << *str_script_ctx << ". must be one of: preRequest, postRequest" << std::endl; return EINVAL; } - const auto rc = rgw::lua::delete_script(store, tenant, null_yield, script_ctx); + const auto rc = rgw::lua::delete_script(dpp(), store, tenant, null_yield, script_ctx); if (rc < 0) { cerr << "ERROR: failed to remove script. error: " << rc << std::endl; return -rc; diff --git a/src/rgw/rgw_lua.cc b/src/rgw/rgw_lua.cc index 6ad5ff04d76c6..384ef2787c407 100644 --- a/src/rgw/rgw_lua.cc +++ b/src/rgw/rgw_lua.cc @@ -65,79 +65,23 @@ std::string script_oid(context ctx, const std::string& tenant) { int read_script(const DoutPrefixProvider *dpp, rgw::sal::Store* store, const std::string& tenant, optional_yield y, context ctx, std::string& script) { - RGWObjVersionTracker objv_tracker; + auto lua_script = store->get_lua_script_manager(); - rgw_raw_obj obj(store->get_zone()->get_params().log_pool, script_oid(ctx, tenant)); - - bufferlist bl; - - const auto rc = store->get_system_obj( - dpp, - obj.pool, - obj.oid, - bl, - &objv_tracker, - nullptr, - y, - nullptr, - nullptr); - - if (rc < 0) { - return rc; - } - - auto iter = bl.cbegin(); - try { - ceph::decode(script, iter); - } catch (buffer::error& err) { - return -EIO; - } - - return 0; + return lua_script->get(dpp, y, script_oid(ctx, tenant), script); } -int write_script(rgw::sal::Store* store, const std::string& tenant, optional_yield y, context ctx, const std::string& script) +int write_script(const DoutPrefixProvider *dpp, rgw::sal::Store* store, const std::string& tenant, optional_yield y, context ctx, const std::string& script) { - RGWObjVersionTracker objv_tracker; - - rgw_raw_obj obj(store->get_zone()->get_params().log_pool, script_oid(ctx, tenant)); - - bufferlist bl; - ceph::encode(script, bl); + auto lua_script = store->get_lua_script_manager(); - const auto rc = store->put_system_obj( - obj.pool, - obj.oid, - bl, - false, - &objv_tracker, - real_time(), - y); - - if (rc < 0) { - return rc; - } - - return 0; + return lua_script->put(dpp, y, script_oid(ctx, tenant), script); } -int delete_script(rgw::sal::Store* store, const std::string& tenant, optional_yield y, context ctx) +int delete_script(const DoutPrefixProvider *dpp, rgw::sal::Store* store, const std::string& tenant, optional_yield y, context ctx) { - RGWObjVersionTracker objv_tracker; - - rgw_raw_obj obj(store->get_zone()->get_params().log_pool, script_oid(ctx, tenant)); + auto lua_script = store->get_lua_script_manager(); - const auto rc = store->delete_system_obj( - obj.pool, - obj.oid, - &objv_tracker, - y); - - if (rc < 0 && rc != -ENOENT) { - return rc; - } - - return 0; + return lua_script->del(dpp, y, script_oid(ctx, tenant)); } #ifdef WITH_RADOSGW_LUA_PACKAGES diff --git a/src/rgw/rgw_lua.h b/src/rgw/rgw_lua.h index a282335299110..9af85d7685f90 100644 --- a/src/rgw/rgw_lua.h +++ b/src/rgw/rgw_lua.h @@ -26,13 +26,13 @@ context to_context(const std::string& s); bool verify(const std::string& script, std::string& err_msg); // store a lua script in a context -int write_script(rgw::sal::Store* store, const std::string& tenant, optional_yield y, context ctx, const std::string& script); +int write_script(const DoutPrefixProvider *dpp, rgw::sal::Store* store, const std::string& tenant, optional_yield y, context ctx, const std::string& script); // read the stored lua script from a context int read_script(const DoutPrefixProvider *dpp, rgw::sal::Store* store, const std::string& tenant, optional_yield y, context ctx, std::string& script); // delete the stored lua script from a context -int delete_script(rgw::sal::Store* store, const std::string& tenant, optional_yield y, context ctx); +int delete_script(const DoutPrefixProvider *dpp, rgw::sal::Store* store, const std::string& tenant, optional_yield y, context ctx); #ifdef WITH_RADOSGW_LUA_PACKAGES #include diff --git a/src/rgw/rgw_oidc_provider.cc b/src/rgw/rgw_oidc_provider.cc index b76a0c2431129..3e86a12173a9d 100644 --- a/src/rgw/rgw_oidc_provider.cc +++ b/src/rgw/rgw_oidc_provider.cc @@ -24,21 +24,11 @@ #define dout_subsys ceph_subsys_rgw +namespace rgw { namespace sal { + const string RGWOIDCProvider::oidc_url_oid_prefix = "oidc_url."; const string RGWOIDCProvider::oidc_arn_prefix = "arn:aws:iam::"; -int RGWOIDCProvider::store_url(const string& url, bool exclusive, - optional_yield y) -{ - using ceph::encode; - string oid = tenant + get_url_oid_prefix() + url; - - bufferlist bl; - encode(*this, bl); - return store->put_system_obj(store->get_zone()->get_params().oidc_pool, oid, - bl, exclusive, NULL, real_time(), y); -} - int RGWOIDCProvider::get_tenant_url_from_arn(string& tenant, string& url) { auto provider_arn = rgw::ARN::parse(arn); @@ -58,7 +48,7 @@ int RGWOIDCProvider::create(const DoutPrefixProvider *dpp, bool exclusive, optio { int ret; - if (! validate_input()) { + if (! validate_input(dpp)) { return -EINVAL; } @@ -92,10 +82,9 @@ int RGWOIDCProvider::create(const DoutPrefixProvider *dpp, bool exclusive, optio sprintf(buf + strlen(buf),".%dZ",(int)tv.tv_usec/1000); creation_date.assign(buf, strlen(buf)); - auto& pool = store->get_zone()->get_params().oidc_pool; - ret = store_url(idp_url, exclusive, y); + ret = store_url(dpp, idp_url, exclusive, y); if (ret < 0) { - ldpp_dout(dpp, 0) << "ERROR: storing role info in pool: " << pool.name << ": " + ldpp_dout(dpp, 0) << "ERROR: storing role info in OIDC pool: " << provider_url << ": " << cpp_strerror(-ret) << dendl; return ret; } @@ -103,34 +92,6 @@ int RGWOIDCProvider::create(const DoutPrefixProvider *dpp, bool exclusive, optio return 0; } -int RGWOIDCProvider::delete_obj(optional_yield y) -{ - auto& pool = store->get_zone()->get_params().oidc_pool; - - string url, tenant; - auto ret = get_tenant_url_from_arn(tenant, url); - if (ret < 0) { - ldout(cct, 0) << "ERROR: failed to parse arn" << dendl; - return -EINVAL; - } - - if (this->tenant != tenant) { - ldout(cct, 0) << "ERROR: tenant in arn doesn't match that of user " << this->tenant << ", " - << tenant << ": " << dendl; - return -EINVAL; - } - - // Delete url - string oid = tenant + get_url_oid_prefix() + url; - ret = store->delete_system_obj(pool, oid, NULL, y); - if (ret < 0) { - ldout(cct, 0) << "ERROR: deleting oidc url from pool: " << pool.name << ": " - << provider_url << ": " << cpp_strerror(-ret) << dendl; - } - - return ret; -} - int RGWOIDCProvider::get(const DoutPrefixProvider *dpp) { string url, tenant; @@ -180,38 +141,14 @@ void RGWOIDCProvider::decode_json(JSONObj *obj) JSONDecoder::decode_json("OpenIDConnectProviderArn", arn, obj); } -int RGWOIDCProvider::read_url(const DoutPrefixProvider *dpp, const string& url, const string& tenant) -{ - auto& pool = store->get_zone()->get_params().oidc_pool; - string oid = tenant + get_url_oid_prefix() + url; - bufferlist bl; - - int ret = store->get_system_obj(dpp, pool, oid, bl, NULL, NULL, null_yield); - if (ret < 0) { - return ret; - } - - try { - using ceph::decode; - auto iter = bl.cbegin(); - decode(*this, iter); - } catch (buffer::error& err) { - ldpp_dout(dpp, 0) << "ERROR: failed to decode oidc provider info from pool: " << pool.name << - ": " << url << dendl; - return -EIO; - } - - return 0; -} - -bool RGWOIDCProvider::validate_input() +bool RGWOIDCProvider::validate_input(const DoutPrefixProvider *dpp) { if (provider_url.length() > MAX_OIDC_URL_LEN) { - ldout(cct, 0) << "ERROR: Invalid length of url " << dendl; + ldpp_dout(dpp, 0) << "ERROR: Invalid length of url " << dendl; return false; } if (client_ids.size() > MAX_OIDC_NUM_CLIENT_IDS) { - ldout(cct, 0) << "ERROR: Invalid number of client ids " << dendl; + ldpp_dout(dpp, 0) << "ERROR: Invalid number of client ids " << dendl; return false; } @@ -222,7 +159,7 @@ bool RGWOIDCProvider::validate_input() } if (thumbprints.size() > MAX_OIDC_NUM_THUMBPRINTS) { - ldout(cct, 0) << "ERROR: Invalid number of thumbprints " << thumbprints.size() << dendl; + ldpp_dout(dpp, 0) << "ERROR: Invalid number of thumbprints " << thumbprints.size() << dendl; return false; } @@ -235,53 +172,9 @@ bool RGWOIDCProvider::validate_input() return true; } -int RGWOIDCProvider::get_providers(const DoutPrefixProvider *dpp, - rgw::sal::Store* store, - const string& tenant, - vector& providers) -{ - auto pool = store->get_zone()->get_params().oidc_pool; - string prefix = tenant + oidc_url_oid_prefix; - - //Get the filtered objects - list result; - bool is_truncated; - RGWListRawObjsCtx ctx; - do { - list oids; - int r = store->list_raw_objects(pool, prefix, 1000, ctx, oids, &is_truncated); - if (r < 0) { - ldpp_dout(dpp, 0) << "ERROR: listing filtered objects failed: " << pool.name << ": " - << prefix << ": " << cpp_strerror(-r) << dendl; - return r; - } - for (const auto& iter : oids) { - RGWOIDCProvider provider(store->ctx(), store); - bufferlist bl; - - int ret = store->get_system_obj(dpp, pool, iter, bl, NULL, NULL, null_yield); - if (ret < 0) { - return ret; - } - - try { - using ceph::decode; - auto iter = bl.cbegin(); - decode(provider, iter); - } catch (buffer::error& err) { - ldpp_dout(dpp, 0) << "ERROR: failed to decode oidc provider info from pool: " << pool.name << - ": " << iter << dendl; - return -EIO; - } - - providers.push_back(std::move(provider)); - } - } while (is_truncated); - - return 0; -} - const string& RGWOIDCProvider::get_url_oid_prefix() { return oidc_url_oid_prefix; } + +} } // namespace rgw::sal diff --git a/src/rgw/rgw_oidc_provider.h b/src/rgw/rgw_oidc_provider.h index 0301485f2692c..a25920add7b78 100644 --- a/src/rgw/rgw_oidc_provider.h +++ b/src/rgw/rgw_oidc_provider.h @@ -11,73 +11,72 @@ #include "rgw/rgw_sal.h" +namespace rgw { namespace sal { class RGWOIDCProvider { - using string = std::string; - static const string oidc_url_oid_prefix; - static const string oidc_arn_prefix; +public: + static const std::string oidc_url_oid_prefix; + static const std::string oidc_arn_prefix; static constexpr int MAX_OIDC_NUM_CLIENT_IDS = 100; static constexpr int MAX_OIDC_CLIENT_ID_LEN = 255; static constexpr int MAX_OIDC_NUM_THUMBPRINTS = 5; static constexpr int MAX_OIDC_THUMBPRINT_LEN = 40; static constexpr int MAX_OIDC_URL_LEN = 255; - CephContext *cct; - rgw::sal::Store* store; - string id; - string provider_url; - string arn; - string creation_date; - string tenant; - vector client_ids; - vector thumbprints; - - int get_tenant_url_from_arn(string& tenant, string& url); - int store_url(const string& url, bool exclusive, optional_yield y); - int read_url(const DoutPrefixProvider *dpp, const string& url, const string& tenant); - bool validate_input(); +protected: + std::string id; + std::string provider_url; + std::string arn; + std::string creation_date; + std::string tenant; + vector client_ids; + vector thumbprints; + + int get_tenant_url_from_arn(std::string& tenant, std::string& url); + virtual int store_url(const DoutPrefixProvider *dpp, const std::string& url, bool exclusive, optional_yield y) = 0; + virtual int read_url(const DoutPrefixProvider *dpp, const std::string& url, const std::string& tenant) = 0; + bool validate_input(const DoutPrefixProvider *dpp); public: - RGWOIDCProvider(CephContext *cct, - rgw::sal::Store* store, - string provider_url, - string tenant, - vector client_ids, - vector thumbprints) - : cct(cct), - store(store), - provider_url(std::move(provider_url)), + void set_arn(std::string _arn) { + arn = _arn; + } + void set_url(std::string _provider_url) { + provider_url = _provider_url; + } + void set_tenant(std::string _tenant) { + tenant = _tenant; + } + void set_client_ids(std::vector& _client_ids) { + client_ids = std::move(_client_ids); + } + void set_thumbprints(std::vector& _thumbprints) { + thumbprints = std::move(_thumbprints); + } + + RGWOIDCProvider(std::string provider_url, + std::string tenant, + vector client_ids, + vector thumbprints) + : provider_url(std::move(provider_url)), tenant(std::move(tenant)), client_ids(std::move(client_ids)), thumbprints(std::move(thumbprints)) { } - RGWOIDCProvider(CephContext *cct, - rgw::sal::Store* store, - string arn, - string tenant) - : cct(cct), - store(store), - arn(std::move(arn)), + RGWOIDCProvider( std::string arn, + std::string tenant) + : arn(std::move(arn)), tenant(std::move(tenant)) { } - RGWOIDCProvider(CephContext *cct, - rgw::sal::Store* store, - string tenant) - : cct(cct), - store(store), - tenant(std::move(tenant)) {} - - RGWOIDCProvider(CephContext *cct, - rgw::sal::Store* store) - : cct(cct), - store(store) {} + RGWOIDCProvider(std::string tenant) + : tenant(std::move(tenant)) {} RGWOIDCProvider() {} - ~RGWOIDCProvider() = default; + virtual ~RGWOIDCProvider() = default; void encode(bufferlist& bl) const { ENCODE_START(3, 1, bl); @@ -103,25 +102,23 @@ public: DECODE_FINISH(bl); } - const string& get_provider_url() const { return provider_url; } - const string& get_arn() const { return arn; } - const string& get_create_date() const { return creation_date; } - const vector& get_client_ids() const { return client_ids;} - const vector& get_thumbprints() const { return thumbprints; } + const std::string& get_provider_url() const { return provider_url; } + const std::string& get_arn() const { return arn; } + const std::string& get_create_date() const { return creation_date; } + const vector& get_client_ids() const { return client_ids;} + const vector& get_thumbprints() const { return thumbprints; } int create(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y); - int delete_obj(optional_yield y); + virtual int delete_obj(const DoutPrefixProvider *dpp, optional_yield y) = 0; int get(const DoutPrefixProvider *dpp); void dump(Formatter *f) const; void dump_all(Formatter *f) const; void decode_json(JSONObj *obj); - static const string& get_url_oid_prefix(); - static int get_providers(const DoutPrefixProvider *dpp, - rgw::sal::Store* store, - const string& tenant, - vector& providers); + static const std::string& get_url_oid_prefix(); }; WRITE_CLASS_ENCODER(RGWOIDCProvider) + +} } // namespace rgw::sal #endif /* CEPH_RGW_OIDC_PROVIDER_H */ diff --git a/src/rgw/rgw_rest_oidc_provider.cc b/src/rgw/rgw_rest_oidc_provider.cc index 764f69b27efa8..519b92d42870d 100644 --- a/src/rgw/rgw_rest_oidc_provider.cc +++ b/src/rgw/rgw_rest_oidc_provider.cc @@ -121,14 +121,17 @@ void RGWCreateOIDCProvider::execute(optional_yield y) return; } - RGWOIDCProvider provider(s->cct, store, provider_url, - s->user->get_tenant(), client_ids, thumbprints); - op_ret = provider.create(s, true, y); + std::unique_ptr provider = store->get_oidc_provider(); + provider->set_url(provider_url); + provider->set_tenant(s->user->get_tenant()); + provider->set_client_ids(client_ids); + provider->set_thumbprints(thumbprints); + op_ret = provider->create(s, true, y); if (op_ret == 0) { s->formatter->open_object_section("CreateOpenIDConnectProviderResponse"); s->formatter->open_object_section("CreateOpenIDConnectProviderResult"); - provider.dump(s->formatter); + provider->dump(s->formatter); s->formatter->close_section(); s->formatter->open_object_section("ResponseMetadata"); s->formatter->dump_string("RequestId", s->trans_id); @@ -140,8 +143,10 @@ void RGWCreateOIDCProvider::execute(optional_yield y) void RGWDeleteOIDCProvider::execute(optional_yield y) { - RGWOIDCProvider provider(s->cct, store, provider_arn, s->user->get_tenant()); - op_ret = provider.delete_obj(y); + std::unique_ptr provider = store->get_oidc_provider(); + provider->set_arn(provider_arn); + provider->set_tenant(s->user->get_tenant()); + op_ret = provider->delete_obj(this, y); if (op_ret < 0 && op_ret != -ENOENT && op_ret != -EINVAL) { op_ret = ERR_INTERNAL_ERROR; @@ -158,8 +163,10 @@ void RGWDeleteOIDCProvider::execute(optional_yield y) void RGWGetOIDCProvider::execute(optional_yield y) { - RGWOIDCProvider provider(s->cct, store, provider_arn, s->user->get_tenant()); - op_ret = provider.get(s); + std::unique_ptr provider = store->get_oidc_provider(); + provider->set_arn(provider_arn); + provider->set_tenant(s->user->get_tenant()); + op_ret = provider->get(s); if (op_ret < 0 && op_ret != -ENOENT && op_ret != -EINVAL) { op_ret = ERR_INTERNAL_ERROR; @@ -171,7 +178,7 @@ void RGWGetOIDCProvider::execute(optional_yield y) s->formatter->dump_string("RequestId", s->trans_id); s->formatter->close_section(); s->formatter->open_object_section("GetOpenIDConnectProviderResult"); - provider.dump_all(s->formatter); + provider->dump_all(s->formatter); s->formatter->close_section(); s->formatter->close_section(); } @@ -199,8 +206,8 @@ int RGWListOIDCProviders::verify_permission(optional_yield y) void RGWListOIDCProviders::execute(optional_yield y) { - vector result; - op_ret = RGWOIDCProvider::get_providers(s, store, s->user->get_tenant(), result); + vector> result; + op_ret = store->get_oidc_providers(s, s->user->get_tenant(), result); if (op_ret == 0) { s->formatter->open_array_section("ListOpenIDConnectProvidersResponse"); @@ -211,7 +218,7 @@ void RGWListOIDCProviders::execute(optional_yield y) s->formatter->open_array_section("OpenIDConnectProviderList"); for (const auto& it : result) { s->formatter->open_object_section("Arn"); - auto& arn = it.get_arn(); + auto& arn = it->get_arn(); ldpp_dout(s, 0) << "ARN: " << arn << dendl; s->formatter->dump_string("Arn", arn); s->formatter->close_section(); diff --git a/src/rgw/rgw_rest_role.cc b/src/rgw/rgw_rest_role.cc index 68239081566a9..c133f5fe9083d 100644 --- a/src/rgw/rgw_rest_role.cc +++ b/src/rgw/rgw_rest_role.cc @@ -26,8 +26,9 @@ int RGWRestRole::verify_permission(optional_yield y) } string role_name = s->info.args.get("RoleName"); - RGWRole role(s->cct, store, role_name, s->user->get_tenant()); - if (op_ret = role.get(s, y); op_ret < 0) { + std::unique_ptr role = store->get_role(role_name, + s->user->get_tenant()); + if (op_ret = role->get(s, y); op_ret < 0) { if (op_ret == -ENOENT) { op_ret = -ERR_NO_ROLE_FOUND; } @@ -39,7 +40,7 @@ int RGWRestRole::verify_permission(optional_yield y) return ret; } - string resource_name = role.get_path() + role_name; + string resource_name = role->get_path() + role_name; uint64_t op = get_op(); if (!verify_user_permission(this, s, @@ -130,9 +131,12 @@ void RGWCreateRole::execute(optional_yield y) if (op_ret < 0) { return; } - RGWRole role(s->cct, store, role_name, role_path, trust_policy, - s->user->get_tenant(), max_session_duration); - op_ret = role.create(s, true, y); + std::unique_ptr role = store->get_role(role_name, + s->user->get_tenant(), + role_path, + trust_policy, + max_session_duration); + op_ret = role->create(s, true, y); if (op_ret == -EEXIST) { op_ret = -ERR_ROLE_EXISTS; @@ -142,7 +146,7 @@ void RGWCreateRole::execute(optional_yield y) s->formatter->open_object_section("CreateRoleResponse"); s->formatter->open_object_section("CreateRoleResult"); s->formatter->open_object_section("Role"); - role.dump(s->formatter); + role->dump(s->formatter); s->formatter->close_section(); s->formatter->close_section(); s->formatter->open_object_section("ResponseMetadata"); @@ -171,7 +175,7 @@ void RGWDeleteRole::execute(optional_yield y) return; } - op_ret = _role.delete_obj(s, y); + op_ret = _role->delete_obj(s, y); if (op_ret == -ENOENT) { op_ret = -ERR_NO_ROLE_FOUND; @@ -189,7 +193,7 @@ int RGWGetRole::verify_permission(optional_yield y) return 0; } -int RGWGetRole::_verify_permission(const RGWRole& role) +int RGWGetRole::_verify_permission(const rgw::sal::RGWRole* role) { if (s->auth.identity->is_anonymous()) { return -EACCES; @@ -199,7 +203,7 @@ int RGWGetRole::_verify_permission(const RGWRole& role) return ret; } - string resource_name = role.get_path() + role.get_name(); + string resource_name = role->get_path() + role->get_name(); if (!verify_user_permission(this, s, rgw::ARN(resource_name, @@ -229,15 +233,16 @@ void RGWGetRole::execute(optional_yield y) if (op_ret < 0) { return; } - RGWRole role(s->cct, store, role_name, s->user->get_tenant()); - op_ret = role.get(s, y); + std::unique_ptr role = store->get_role(role_name, + s->user->get_tenant()); + op_ret = role->get(s, y); if (op_ret == -ENOENT) { op_ret = -ERR_NO_ROLE_FOUND; return; } - op_ret = _verify_permission(role); + op_ret = _verify_permission(role.get()); if (op_ret == 0) { s->formatter->open_object_section("GetRoleResponse"); @@ -246,7 +251,7 @@ void RGWGetRole::execute(optional_yield y) s->formatter->close_section(); s->formatter->open_object_section("GetRoleResult"); s->formatter->open_object_section("Role"); - role.dump(s->formatter); + role->dump(s->formatter); s->formatter->close_section(); s->formatter->close_section(); s->formatter->close_section(); @@ -278,8 +283,8 @@ void RGWModifyRole::execute(optional_yield y) return; } - _role.update_trust_policy(trust_policy); - op_ret = _role.update(y); + _role->update_trust_policy(trust_policy); + op_ret = _role->update(this, y); s->formatter->open_object_section("UpdateAssumeRolePolicyResponse"); s->formatter->open_object_section("ResponseMetadata"); @@ -321,8 +326,8 @@ void RGWListRoles::execute(optional_yield y) if (op_ret < 0) { return; } - vector result; - op_ret = RGWRole::get_roles_by_path_prefix(s, store, s->cct, path_prefix, s->user->get_tenant(), result, y); + vector> result; + op_ret = store->get_roles(s, y, path_prefix, s->user->get_tenant(), result); if (op_ret == 0) { s->formatter->open_array_section("ListRolesResponse"); @@ -333,7 +338,7 @@ void RGWListRoles::execute(optional_yield y) s->formatter->open_object_section("Roles"); for (const auto& it : result) { s->formatter->open_object_section("member"); - it.dump(s->formatter); + it->dump(s->formatter); s->formatter->close_section(); } s->formatter->close_section(); @@ -370,8 +375,8 @@ void RGWPutRolePolicy::execute(optional_yield y) return; } - _role.set_perm_policy(policy_name, perm_policy); - op_ret = _role.update(y); + _role->set_perm_policy(policy_name, perm_policy); + op_ret = _role->update(this, y); if (op_ret == 0) { s->formatter->open_object_section("PutRolePolicyResponse"); @@ -402,7 +407,7 @@ void RGWGetRolePolicy::execute(optional_yield y) } string perm_policy; - op_ret = _role.get_role_policy(policy_name, perm_policy); + op_ret = _role->get_role_policy(this, policy_name, perm_policy); if (op_ret == -ENOENT) { op_ret = -ERR_NO_SUCH_ENTITY; } @@ -439,7 +444,7 @@ void RGWListRolePolicies::execute(optional_yield y) return; } - std::vector policy_names = _role.get_role_policy_names(); + std::vector policy_names = _role->get_role_policy_names(); s->formatter->open_object_section("ListRolePoliciesResponse"); s->formatter->open_object_section("ResponseMetadata"); s->formatter->dump_string("RequestId", s->trans_id); @@ -473,13 +478,13 @@ void RGWDeleteRolePolicy::execute(optional_yield y) return; } - op_ret = _role.delete_policy(policy_name); + op_ret = _role->delete_policy(this, policy_name); if (op_ret == -ENOENT) { op_ret = -ERR_NO_ROLE_FOUND; } if (op_ret == 0) { - op_ret = _role.update(y); + op_ret = _role->update(this, y); } s->formatter->open_object_section("DeleteRolePoliciesResponse"); diff --git a/src/rgw/rgw_rest_role.h b/src/rgw/rgw_rest_role.h index 09f556b6cf6ee..4dc04186dc41a 100644 --- a/src/rgw/rgw_rest_role.h +++ b/src/rgw/rgw_rest_role.h @@ -17,7 +17,7 @@ protected: string perm_policy; string path_prefix; string max_session_duration; - RGWRole _role; + std::unique_ptr _role; public: int verify_permission(optional_yield y) override; void send_response() override; @@ -58,7 +58,7 @@ public: }; class RGWGetRole : public RGWRoleRead { - int _verify_permission(const RGWRole& role); + int _verify_permission(const rgw::sal::RGWRole* role); public: RGWGetRole() = default; int verify_permission(optional_yield y) override; diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index 41579f26bc7e1..f6c045881d81c 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -6020,18 +6020,18 @@ rgw::auth::s3::STSEngine::authenticate( string role_id; rgw::auth::RoleApplier::Role r; if (! token.roleId.empty()) { - RGWRole role(s->cct, store, token.roleId); - if (role.get_by_id(dpp, y) < 0) { + std::unique_ptr role = store->get_role(token.roleId); + if (role->get_by_id(dpp, y) < 0) { return result_t::deny(-EPERM); } r.id = token.roleId; - r.name = role.get_name(); - r.tenant = role.get_tenant(); + r.name = role->get_name(); + r.tenant = role->get_tenant(); - vector role_policy_names = role.get_role_policy_names(); + vector role_policy_names = role->get_role_policy_names(); for (auto& policy_name : role_policy_names) { string perm_policy; - if (int ret = role.get_role_policy(policy_name, perm_policy); ret == 0) { + if (int ret = role->get_role_policy(dpp, policy_name, perm_policy); ret == 0) { r.role_policies.push_back(std::move(perm_policy)); } } diff --git a/src/rgw/rgw_rest_sts.cc b/src/rgw/rgw_rest_sts.cc index baebc867dd561..986afefdc70e2 100644 --- a/src/rgw/rgw_rest_sts.cc +++ b/src/rgw/rgw_rest_sts.cc @@ -60,7 +60,7 @@ WebTokenEngine::get_role_tenant(const string& role_arn) const return tenant; } -boost::optional +std::unique_ptr WebTokenEngine::get_provider(const DoutPrefixProvider *dpp, const string& role_arn, const string& iss) const { string tenant = get_role_tenant(role_arn); @@ -82,12 +82,14 @@ WebTokenEngine::get_provider(const DoutPrefixProvider *dpp, const string& role_a } auto provider_arn = rgw::ARN(idp_url, "oidc-provider", tenant); string p_arn = provider_arn.to_string(); - RGWOIDCProvider provider(cct, store, p_arn, tenant); - auto ret = provider.get(dpp); + std::unique_ptr provider = store->get_oidc_provider(); + provider->set_arn(p_arn); + provider->set_tenant(tenant); + auto ret = provider->get(dpp); if (ret < 0) { - return boost::none; + return nullptr; } - return provider; + return std::move(provider); } bool @@ -368,7 +370,7 @@ int RGWREST_STS::verify_permission(optional_yield y) ldpp_dout(this, 0) << "failed to get role info using role arn: " << rArn << dendl; return ret; } - string policy = role.get_assume_role_policy(); + string policy = role->get_assume_role_policy(); buffer::list bl = buffer::list::static_from_string(policy); //Parse the policy diff --git a/src/rgw/rgw_rest_sts.h b/src/rgw/rgw_rest_sts.h index 12834d89e57b1..59c7fa59cb642 100644 --- a/src/rgw/rgw_rest_sts.h +++ b/src/rgw/rgw_rest_sts.h @@ -29,7 +29,7 @@ class WebTokenEngine : public rgw::auth::Engine { bool is_cert_valid(const vector& thumbprints, const string& cert) const; - boost::optional get_provider(const DoutPrefixProvider *dpp, const string& role_arn, const string& iss) const; + std::unique_ptr get_provider(const DoutPrefixProvider *dpp, const string& role_arn, const string& iss) const; std::string get_role_tenant(const string& role_arn) const; diff --git a/src/rgw/rgw_role.cc b/src/rgw/rgw_role.cc index c076524ea589b..78ad6327e834d 100644 --- a/src/rgw/rgw_role.cc +++ b/src/rgw/rgw_role.cc @@ -24,181 +24,13 @@ #define dout_subsys ceph_subsys_rgw +namespace rgw { namespace 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::"; -int RGWRole::store_info(bool exclusive, optional_yield y) -{ - using ceph::encode; - string oid = get_info_oid_prefix() + id; - - bufferlist bl; - encode(*this, bl); - - return store->put_system_obj(store->get_zone()->get_params().roles_pool, oid, - bl, exclusive, NULL, real_time(), y, NULL); -} - -int RGWRole::store_name(bool exclusive, optional_yield y) -{ - RGWNameToId nameToId; - nameToId.obj_id = id; - - string oid = tenant + get_names_oid_prefix() + name; - - bufferlist bl; - using ceph::encode; - encode(nameToId, bl); - - return store->put_system_obj(store->get_zone()->get_params().roles_pool, oid, - bl, exclusive, NULL, real_time(), y, NULL); -} - -int RGWRole::store_path(bool exclusive, optional_yield y) -{ - string oid = tenant + get_path_oid_prefix() + path + get_info_oid_prefix() + id; - - bufferlist bl; - return store->put_system_obj(store->get_zone()->get_params().roles_pool, oid, - bl, exclusive, NULL, real_time(), y, NULL); -} - -int RGWRole::create(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y) -{ - int ret; - - if (! validate_input()) { - return -EINVAL; - } - - /* check to see the name is not used */ - ret = read_id(dpp, name, tenant, id, y); - if (exclusive && ret == 0) { - ldpp_dout(dpp, 0) << "ERROR: name " << name << " already in use for role id " - << id << dendl; - return -EEXIST; - } else if ( ret < 0 && ret != -ENOENT) { - ldpp_dout(dpp, 0) << "failed reading role id " << id << ": " - << cpp_strerror(-ret) << dendl; - return ret; - } - - /* create unique id */ - uuid_d new_uuid; - char uuid_str[37]; - new_uuid.generate_random(); - new_uuid.print(uuid_str); - id = uuid_str; - - //arn - arn = role_arn_prefix + tenant + ":role" + path + name; - - // 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),".%dZ",(int)tv.tv_usec/1000); - creation_date.assign(buf, strlen(buf)); - - auto& pool = store->get_zone()->get_params().roles_pool; - ret = store_info(exclusive, y); - if (ret < 0) { - ldpp_dout(dpp, 0) << "ERROR: storing role info in pool: " << pool.name << ": " - << id << ": " << cpp_strerror(-ret) << dendl; - return ret; - } - - ret = store_name(exclusive, y); - if (ret < 0) { - ldpp_dout(dpp, 0) << "ERROR: storing role name in pool: " << pool.name << ": " - << name << ": " << cpp_strerror(-ret) << dendl; - - //Delete the role info that was stored in the previous call - string oid = get_info_oid_prefix() + id; - int info_ret = store->delete_system_obj(pool, oid, nullptr, y); - if (info_ret < 0) { - ldpp_dout(dpp, 0) << "ERROR: cleanup of role id from pool: " << pool.name << ": " - << id << ": " << cpp_strerror(-info_ret) << dendl; - } - return ret; - } - - ret = store_path(exclusive, y); - if (ret < 0) { - ldpp_dout(dpp, 0) << "ERROR: storing role path in pool: " << pool.name << ": " - << path << ": " << cpp_strerror(-ret) << dendl; - //Delete the role info that was stored in the previous call - string oid = get_info_oid_prefix() + id; - int info_ret = store->delete_system_obj(pool, oid, nullptr, y); - if (info_ret < 0) { - ldpp_dout(dpp, 0) << "ERROR: cleanup of role id from pool: " << pool.name << ": " - << id << ": " << cpp_strerror(-info_ret) << dendl; - } - //Delete role name that was stored in previous call - oid = tenant + get_names_oid_prefix() + name; - int name_ret = store->delete_system_obj(pool, oid, nullptr, y); - if (name_ret < 0) { - ldpp_dout(dpp, 0) << "ERROR: cleanup of role name from pool: " << pool.name << ": " - << name << ": " << cpp_strerror(-name_ret) << dendl; - } - return ret; - } - return 0; -} - -int RGWRole::delete_obj(const DoutPrefixProvider *dpp, optional_yield y) -{ - auto& pool = store->get_zone()->get_params().roles_pool; - - int ret = read_name(dpp, y); - if (ret < 0) { - return ret; - } - - ret = read_info(dpp, y); - if (ret < 0) { - return ret; - } - - if (! perm_policy_map.empty()) { - return -ERR_DELETE_CONFLICT; - } - - // Delete id - string oid = get_info_oid_prefix() + id; - ret = store->delete_system_obj(pool, oid, nullptr, y); - if (ret < 0) { - ldpp_dout(dpp, 0) << "ERROR: deleting role id from pool: " << pool.name << ": " - << id << ": " << cpp_strerror(-ret) << dendl; - } - - // Delete name - oid = tenant + get_names_oid_prefix() + name; - ret = store->delete_system_obj(pool, oid, nullptr, y); - if (ret < 0) { - ldpp_dout(dpp, 0) << "ERROR: deleting role name from pool: " << pool.name << ": " - << name << ": " << cpp_strerror(-ret) << dendl; - } - - // Delete path - oid = tenant + get_path_oid_prefix() + path + get_info_oid_prefix() + id; - ret = store->delete_system_obj(pool, oid, nullptr, y); - if (ret < 0) { - ldpp_dout(dpp, 0) << "ERROR: deleting role path from pool: " << pool.name << ": " - << path << ": " << cpp_strerror(-ret) << dendl; - } - return ret; -} - int RGWRole::get(const DoutPrefixProvider *dpp, optional_yield y) { int ret = read_name(dpp, y); @@ -224,13 +56,11 @@ int RGWRole::get_by_id(const DoutPrefixProvider *dpp, optional_yield y) return 0; } -int RGWRole::update(optional_yield y) +int RGWRole::update(const DoutPrefixProvider *dpp, optional_yield y) { - auto& pool = store->get_zone()->get_params().roles_pool; - - int ret = store_info(false, y); + int ret = store_info(dpp, false, y); if (ret < 0) { - ldout(cct, 0) << "ERROR: storing info in pool: " << pool.name << ": " + ldpp_dout(dpp, 0) << "ERROR: storing info in Role pool: " << id << ": " << cpp_strerror(-ret) << dendl; return ret; } @@ -254,11 +84,11 @@ vector RGWRole::get_role_policy_names() return policy_names; } -int RGWRole::get_role_policy(const string& policy_name, string& perm_policy) +int RGWRole::get_role_policy(const DoutPrefixProvider* dpp, const string& policy_name, string& perm_policy) { const auto it = perm_policy_map.find(policy_name); if (it == perm_policy_map.end()) { - ldout(cct, 0) << "ERROR: Policy name: " << policy_name << " not found" << dendl; + ldpp_dout(dpp, 0) << "ERROR: Policy name: " << policy_name << " not found" << dendl; return -ENOENT; } else { perm_policy = it->second; @@ -266,11 +96,11 @@ int RGWRole::get_role_policy(const string& policy_name, string& perm_policy) return 0; } -int RGWRole::delete_policy(const string& policy_name) +int RGWRole::delete_policy(const DoutPrefixProvider* dpp, const string& policy_name) { const auto& it = perm_policy_map.find(policy_name); if (it == perm_policy_map.end()) { - ldout(cct, 0) << "ERROR: Policy name: " << policy_name << " not found" << dendl; + ldpp_dout(dpp, 0) << "ERROR: Policy name: " << policy_name << " not found" << dendl; return -ENOENT; } else { perm_policy_map.erase(it); @@ -300,111 +130,33 @@ void RGWRole::decode_json(JSONObj *obj) JSONDecoder::decode_json("assume_role_policy_document", trust_policy, obj); } -int RGWRole::read_id(const DoutPrefixProvider *dpp, const string& role_name, const string& tenant, string& role_id, optional_yield y) -{ - auto& pool = store->get_zone()->get_params().roles_pool; - string oid = tenant + get_names_oid_prefix() + role_name; - bufferlist bl; - - int ret = store->get_system_obj(dpp, pool, oid, bl, NULL, NULL, y); - 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 pool: " << pool.name << ": " - << role_name << dendl; - return -EIO; - } - role_id = nameToId.obj_id; - return 0; -} - -int RGWRole::read_info(const DoutPrefixProvider *dpp, optional_yield y) -{ - auto& pool = store->get_zone()->get_params().roles_pool; - string oid = get_info_oid_prefix() + id; - bufferlist bl; - - int ret = store->get_system_obj(dpp, pool, oid, bl, NULL, NULL, y); - if (ret < 0) { - ldpp_dout(dpp, 0) << "ERROR: failed reading role info from pool: " << pool.name << - ": " << id << ": " << cpp_strerror(-ret) << dendl; - return ret; - } - - try { - using ceph::decode; - auto iter = bl.cbegin(); - decode(*this, iter); - } catch (buffer::error& err) { - ldpp_dout(dpp, 0) << "ERROR: failed to decode role info from pool: " << pool.name << - ": " << id << dendl; - return -EIO; - } - - return 0; -} - -int RGWRole::read_name(const DoutPrefixProvider *dpp, optional_yield y) -{ - auto& pool = store->get_zone()->get_params().roles_pool; - string oid = tenant + get_names_oid_prefix() + name; - bufferlist bl; - - int ret = store->get_system_obj(dpp, pool, oid, bl, NULL, NULL, y); - if (ret < 0) { - ldpp_dout(dpp, 0) << "ERROR: failed reading role name from pool: " << pool.name << ": " - << 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 pool: " << pool.name << ": " - << name << dendl; - return -EIO; - } - id = nameToId.obj_id; - return 0; -} - -bool RGWRole::validate_input() +bool RGWRole::validate_input(const DoutPrefixProvider* dpp) { if (name.length() > MAX_ROLE_NAME_LEN) { - ldout(cct, 0) << "ERROR: Invalid name length " << dendl; + ldpp_dout(dpp, 0) << "ERROR: Invalid name length " << dendl; return false; } if (path.length() > MAX_PATH_NAME_LEN) { - ldout(cct, 0) << "ERROR: Invalid path length " << dendl; + ldpp_dout(dpp, 0) << "ERROR: Invalid path length " << dendl; return false; } std::regex regex_name("[A-Za-z0-9:=,.@-]+"); if (! std::regex_match(name, regex_name)) { - ldout(cct, 0) << "ERROR: Invalid chars in name " << dendl; + ldpp_dout(dpp, 0) << "ERROR: Invalid chars in name " << dendl; return false; } std::regex regex_path("(/[!-~]+/)|(/)"); if (! std::regex_match(path,regex_path)) { - ldout(cct, 0) << "ERROR: Invalid chars in path " << dendl; + ldpp_dout(dpp, 0) << "ERROR: Invalid chars in path " << dendl; return false; } if (max_session_duration < SESSION_DURATION_MIN || max_session_duration > SESSION_DURATION_MAX) { - ldout(cct, 0) << "ERROR: Invalid session duration, should be between 3600 and 43200 seconds " << dendl; + ldpp_dout(dpp, 0) << "ERROR: Invalid session duration, should be between 3600 and 43200 seconds " << dendl; return false; } return true; @@ -424,69 +176,6 @@ void RGWRole::update_trust_policy(string& trust_policy) this->trust_policy = trust_policy; } -int RGWRole::get_roles_by_path_prefix(const DoutPrefixProvider *dpp, - rgw::sal::Store* store, - CephContext *cct, - const string& path_prefix, - const string& tenant, - vector& roles, - optional_yield y) -{ - auto pool = store->get_zone()->get_params().roles_pool; - string prefix; - - // List all roles if path prefix is empty - if (! path_prefix.empty()) { - prefix = tenant + role_path_oid_prefix + path_prefix; - } else { - prefix = tenant + role_path_oid_prefix; - } - - //Get the filtered objects - list result; - bool is_truncated; - RGWListRawObjsCtx ctx; - do { - list oids; - int r = store->list_raw_objects(pool, prefix, 1000, ctx, oids, &is_truncated); - if (r < 0) { - ldpp_dout(dpp, 0) << "ERROR: listing filtered objects failed: " << pool.name << ": " - << prefix << ": " << cpp_strerror(-r) << dendl; - return r; - } - for (const auto& iter : oids) { - result.push_back(iter.substr(role_path_oid_prefix.size())); - } - } while (is_truncated); - - for (const auto& it : result) { - //Find the role oid prefix from the end - size_t pos = it.rfind(role_oid_prefix); - if (pos == string::npos) { - continue; - } - // Split the result into path and info_oid + id - string path = it.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) != string::npos) { - //Get id from info oid prefix + id - string id = it.substr(pos + role_oid_prefix.length()); - - RGWRole role(cct, store); - role.set_id(id); - int ret = role.read_info(dpp, y); - if (ret < 0) { - return ret; - } - roles.push_back(std::move(role)); - } - } - - return 0; -} - const string& RGWRole::get_names_oid_prefix() { return role_name_oid_prefix; @@ -501,3 +190,5 @@ const string& RGWRole::get_path_oid_prefix() { return role_path_oid_prefix; } + +} } // namespace rgw::sal diff --git a/src/rgw/rgw_role.h b/src/rgw/rgw_role.h index 5b6e7034cf265..e94fde18ffde0 100644 --- a/src/rgw/rgw_role.h +++ b/src/rgw/rgw_role.h @@ -13,52 +13,47 @@ #include "rgw/rgw_rados.h" -namespace rgw { namespace sal { class Store; } } +namespace rgw { namespace sal { class RGWRole { - using string = std::string; - static const string role_name_oid_prefix; - static const string role_oid_prefix; - static const string role_path_oid_prefix; - static const string role_arn_prefix; +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; static constexpr uint64_t SESSION_DURATION_MIN = 3600; // in seconds static constexpr uint64_t SESSION_DURATION_MAX = 43200; // in seconds - - CephContext *cct; - rgw::sal::Store* store; - string id; - string name; - string path; - string arn; - string creation_date; - string trust_policy; - map perm_policy_map; - string tenant; +protected: + + std::string id; + std::string name; + std::string path; + std::string arn; + std::string creation_date; + std::string trust_policy; + map perm_policy_map; + std::string tenant; uint64_t max_session_duration; - int store_info(bool exclusive, optional_yield y); - int store_name(bool exclusive, optional_yield y); - int store_path(bool exclusive, optional_yield y); - int read_id(const DoutPrefixProvider *dpp, const string& role_name, const string& tenant, string& role_id, optional_yield y); - int read_name(const DoutPrefixProvider *dpp, optional_yield y); - int read_info(const DoutPrefixProvider *dpp, optional_yield y); - bool validate_input(); +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_input(const DoutPrefixProvider* dpp); void extract_name_tenant(const std::string& str); -public: - RGWRole(CephContext *cct, - rgw::sal::Store* store, - string name, - string path, - string trust_policy, - string tenant, - string max_session_duration_str="") - : cct(cct), - store(store), - name(std::move(name)), + RGWRole(std::string name, + std::string tenant, + std::string path="", + std::string trust_policy="", + std::string max_session_duration_str="") + : name(std::move(name)), path(std::move(path)), trust_policy(std::move(trust_policy)), tenant(std::move(tenant)) { @@ -72,32 +67,9 @@ public: } } - RGWRole(CephContext *cct, - rgw::sal::Store* store, - string name, - string tenant) - : cct(cct), - store(store), - name(std::move(name)), - tenant(std::move(tenant)) { - extract_name_tenant(this->name); - } - - RGWRole(CephContext *cct, - rgw::sal::Store* store, - string id) - : cct(cct), - store(store), - id(std::move(id)) {} - - RGWRole(CephContext *cct, - rgw::sal::Store* store) - : cct(cct), - store(store) {} - - RGWRole() {} + RGWRole(std::string id) : id(std::move(id)) {} - ~RGWRole() = default; + virtual ~RGWRole() = default; void encode(bufferlist& bl) const { ENCODE_START(3, 1, bl); @@ -131,39 +103,33 @@ public: DECODE_FINISH(bl); } - const string& get_id() const { return id; } - const string& get_name() const { return name; } - const string& get_tenant() const { return tenant; } - const string& get_path() const { return path; } - const string& get_create_date() const { return creation_date; } - const string& get_assume_role_policy() const { return trust_policy;} + const std::string& get_id() const { return id; } + const std::string& get_name() const { return name; } + const std::string& get_tenant() const { return tenant; } + const std::string& get_path() const { return path; } + const std::string& get_create_date() const { return creation_date; } + const std::string& get_assume_role_policy() const { return trust_policy;} const uint64_t& get_max_session_duration() const { return max_session_duration; } - void set_id(const string& id) { this->id = id; } + void set_id(const std::string& id) { this->id = id; } - int create(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y); - int delete_obj(const DoutPrefixProvider *dpp, optional_yield y); + virtual int create(const DoutPrefixProvider *dpp, bool exclusive, 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(optional_yield y); - void update_trust_policy(string& trust_policy); - void set_perm_policy(const string& policy_name, const string& perm_policy); - vector get_role_policy_names(); - int get_role_policy(const string& policy_name, string& perm_policy); - int delete_policy(const string& policy_name); + int update(const DoutPrefixProvider *dpp, 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); + vector get_role_policy_names(); + int get_role_policy(const DoutPrefixProvider* dpp, const std::string& policy_name, std::string& perm_policy); + int delete_policy(const DoutPrefixProvider* dpp, const std::string& policy_name); void dump(Formatter *f) const; void decode_json(JSONObj *obj); - static const string& get_names_oid_prefix(); - static const string& get_info_oid_prefix(); - static const string& get_path_oid_prefix(); - static int get_roles_by_path_prefix(const DoutPrefixProvider *dpp, - rgw::sal::Store* store, - CephContext *cct, - const string& path_prefix, - const string& tenant, - vector& roles, - optional_yield y); + static const std::string& get_names_oid_prefix(); + static const std::string& get_info_oid_prefix(); + static const std::string& get_path_oid_prefix(); }; WRITE_CLASS_ENCODER(RGWRole) +} } // namespace rgw::sal #endif /* CEPH_RGW_ROLE_H */ diff --git a/src/rgw/rgw_sal.h b/src/rgw/rgw_sal.h index e4f351d2f2f57..1a00e407ffb85 100644 --- a/src/rgw/rgw_sal.h +++ b/src/rgw/rgw_sal.h @@ -105,6 +105,9 @@ class Notification; class GCChain; class Writer; class Zone; +class LuaScriptManager; +class RGWOIDCProvider; +class RGWRole; enum AttrsMod { ATTRSMOD_NONE = 0, @@ -184,9 +187,6 @@ class Store { virtual int register_to_service_map(const std::string& daemon_type, const map& meta) = 0; virtual void get_quota(RGWQuotaInfo& bucket_quota, RGWQuotaInfo& user_quota) = 0; - virtual int list_raw_objects(const rgw_pool& pool, const std::string& prefix_filter, - int max, RGWListRawObjsCtx& ctx, std::list& oids, - bool* is_truncated) = 0; virtual int set_buckets_enabled(const DoutPrefixProvider* dpp, vector& buckets, bool enabled) = 0; virtual uint64_t get_new_req_id() = 0; virtual int get_sync_policy_handler(const DoutPrefixProvider* dpp, @@ -204,19 +204,6 @@ class Store { map& usage) = 0; virtual int trim_all_usage(uint64_t start_epoch, uint64_t end_epoch) = 0; virtual int get_config_key_val(std::string name, bufferlist* bl) = 0; - virtual int put_system_obj(const rgw_pool& pool, const std::string& oid, - bufferlist& data, bool exclusive, - RGWObjVersionTracker* objv_tracker, real_time set_mtime, - optional_yield y, map* pattrs = nullptr) = 0; - virtual int get_system_obj(const DoutPrefixProvider* dpp, - const rgw_pool& pool, const std::string& key, - bufferlist& bl, - RGWObjVersionTracker* objv_tracker, real_time* pmtime, - optional_yield y, map* pattrs = nullptr, - rgw_cache_entry_info* cache_info = nullptr, - boost::optional refresh_version = boost::none) = 0; - virtual int delete_system_obj(const rgw_pool& pool, const std::string& oid, - RGWObjVersionTracker* objv_tracker, optional_yield y) = 0; virtual int meta_list_keys_init(const std::string& section, const std::string& marker, void** phandle) = 0; virtual int meta_list_keys_next(void* handle, int max, list& keys, bool* truncated) = 0; virtual void meta_list_keys_complete(void* handle) = 0; @@ -224,6 +211,22 @@ class Store { virtual int meta_remove(const DoutPrefixProvider* dpp, std::string& metadata_key, optional_yield y) = 0; virtual const RGWSyncModuleInstanceRef& get_sync_module() = 0; virtual std::string get_host_id() = 0; + virtual std::unique_ptr get_lua_script_manager() = 0; + virtual std::unique_ptr get_role(std::string name, + std::string tenant, + std::string path="", + std::string trust_policy="", + std::string max_session_duration_str="") = 0; + virtual std::unique_ptr get_role(std::string id) = 0; + virtual int get_roles(const DoutPrefixProvider *dpp, + optional_yield y, + const std::string& path_prefix, + const std::string& tenant, + vector>& roles) = 0; + virtual std::unique_ptr get_oidc_provider() = 0; + virtual int get_oidc_providers(const DoutPrefixProvider *dpp, + const std::string& tenant, + vector>& providers) = 0; virtual void finalize(void) = 0; @@ -912,6 +915,18 @@ class Zone { virtual const std::string& get_current_period_id() = 0; }; +class LuaScriptManager { +protected: + std::string script; + +public: + virtual ~LuaScriptManager() = default; + + virtual int get(const DoutPrefixProvider* dpp, optional_yield y, const std::string& key, std::string& script) = 0; + virtual int put(const DoutPrefixProvider* dpp, optional_yield y, const std::string& key, const std::string& script) = 0; + virtual int del(const DoutPrefixProvider* dpp, optional_yield y, const std::string& key) = 0; +}; + } } // namespace rgw::sal class StoreManager { diff --git a/src/rgw/rgw_sal_rados.cc b/src/rgw/rgw_sal_rados.cc index 6ad17e12378aa..486b875782b58 100644 --- a/src/rgw/rgw_sal_rados.cc +++ b/src/rgw/rgw_sal_rados.cc @@ -953,13 +953,6 @@ void RadosStore::get_quota(RGWQuotaInfo& bucket_quota, RGWQuotaInfo& user_quota) user_quota = svc()->quota->get_user_quota(); } -int RadosStore::list_raw_objects(const rgw_pool& pool, const std::string& prefix_filter, - int max, RGWListRawObjsCtx& ctx, list& oids, - bool* is_truncated) -{ - return rados->list_raw_objects(pool, prefix_filter, max, ctx, oids, is_truncated); -} - int RadosStore::set_buckets_enabled(const DoutPrefixProvider* dpp, vector& buckets, bool enabled) { return rados->set_buckets_enabled(buckets, enabled, dpp); @@ -1004,33 +997,6 @@ int RadosStore::get_config_key_val(std::string name, bufferlist* bl) return svc()->config_key->get(name, true, bl); } -int RadosStore::put_system_obj(const rgw_pool& pool, const std::string& oid, - bufferlist& data, bool exclusive, - RGWObjVersionTracker* objv_tracker, real_time set_mtime, - optional_yield y, map* pattrs) -{ - auto obj_ctx = svc()->sysobj->init_obj_ctx(); - return rgw_put_system_obj(obj_ctx, pool, oid, data, exclusive, objv_tracker, set_mtime, y, pattrs); -} - -int RadosStore::get_system_obj(const DoutPrefixProvider* dpp, - const rgw_pool& pool, const std::string& key, - bufferlist& bl, - RGWObjVersionTracker* objv_tracker, real_time* pmtime, - optional_yield y, map* pattrs, - rgw_cache_entry_info* cache_info, - boost::optional refresh_version) -{ - auto obj_ctx = svc()->sysobj->init_obj_ctx(); - return rgw_get_system_obj(obj_ctx, pool, key, bl, objv_tracker, pmtime, y, dpp, pattrs, cache_info, refresh_version); -} - -int RadosStore::delete_system_obj(const rgw_pool& pool, const std::string& oid, - RGWObjVersionTracker* objv_tracker, optional_yield y) -{ - return rgw_delete_system_obj(svc()->sysobj, pool, oid, objv_tracker, y); -} - int RadosStore::meta_list_keys_init(const std::string& section, const std::string& marker, void** phandle) { return ctl()->meta.mgr->list_keys_init(section, marker, phandle); @@ -1062,6 +1028,136 @@ void RadosStore::finalize(void) rados->finalize(); } +std::unique_ptr RadosStore::get_lua_script_manager() +{ + return std::unique_ptr(new RadosLuaScriptManager(this)); +} + +std::unique_ptr RadosStore::get_role(std::string name, + std::string tenant, + std::string path, + std::string trust_policy, + std::string max_session_duration_str) +{ + return std::unique_ptr(new RadosRole(this, name, tenant, path, trust_policy, max_session_duration_str)); +} + +std::unique_ptr RadosStore::get_role(std::string id) +{ + return std::unique_ptr(new RadosRole(this, id)); +} + +int RadosStore::get_roles(const DoutPrefixProvider *dpp, + optional_yield y, + const std::string& path_prefix, + const std::string& tenant, + vector>& roles) +{ + auto pool = get_zone()->get_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 + list result; + bool is_truncated; + RGWListRawObjsCtx ctx; + do { + list oids; + int r = rados->list_raw_objects(pool, prefix, 1000, ctx, oids, &is_truncated); + if (r < 0) { + ldpp_dout(dpp, 0) << "ERROR: listing filtered objects failed: " + << prefix << ": " << cpp_strerror(-r) << dendl; + return r; + } + for (const auto& iter : oids) { + result.push_back(iter.substr(RGWRole::role_path_oid_prefix.size())); + } + } while (is_truncated); + + for (const auto& it : result) { + //Find the role oid prefix from the end + size_t pos = it.rfind(RGWRole::role_oid_prefix); + if (pos == std::string::npos) { + continue; + } + // Split the result into path and info_oid + id + std::string path = it.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 = it.substr(pos + RGWRole::role_oid_prefix.length()); + + std::unique_ptr role = get_role(id); + int ret = role->read_info(dpp, y); + if (ret < 0) { + return ret; + } + roles.push_back(std::move(role)); + } + } + + return 0; +} + +std::unique_ptr RadosStore::get_oidc_provider() +{ + return std::unique_ptr(new RadosOIDCProvider(this)); +} + +int RadosStore::get_oidc_providers(const DoutPrefixProvider *dpp, + const std::string& tenant, + vector>& providers) +{ + std::string prefix = tenant + RGWOIDCProvider::oidc_url_oid_prefix; + auto pool = zone.get_params().oidc_pool; + auto obj_ctx = svc()->sysobj->init_obj_ctx(); + + //Get the filtered objects + list result; + bool is_truncated; + RGWListRawObjsCtx ctx; + do { + list oids; + int r = rados->list_raw_objects(pool, prefix, 1000, ctx, oids, &is_truncated); + if (r < 0) { + ldpp_dout(dpp, 0) << "ERROR: listing filtered objects failed: OIDC pool: " + << pool.name << ": " << prefix << ": " << cpp_strerror(-r) << dendl; + return r; + } + for (const auto& iter : oids) { + std::unique_ptr provider = get_oidc_provider(); + bufferlist bl; + + r = rgw_get_system_obj(obj_ctx, pool, iter, bl, nullptr, nullptr, null_yield, dpp); + if (r < 0) { + return r; + } + + try { + using ceph::decode; + auto iter = bl.cbegin(); + decode(*provider, iter); + } catch (buffer::error& err) { + ldpp_dout(dpp, 0) << "ERROR: failed to decode oidc provider info from pool: " + << pool.name << ": " << iter << dendl; + return -EIO; + } + + providers.push_back(std::move(provider)); + } + } while (is_truncated); + + return 0; +} + int RadosStore::get_obj_head_ioctx(const RGWBucketInfo& bucket_info, const rgw_obj& obj, librados::IoCtx* ioctx) { return rados->get_obj_head_ioctx(bucket_info, obj, ioctx); @@ -1929,6 +2025,359 @@ const std::string& RadosZone::get_current_period_id() return store->svc()->zone->get_current_period_id(); } +int RadosLuaScriptManager::get(const DoutPrefixProvider* dpp, optional_yield y, const std::string& key, std::string& script) +{ + auto obj_ctx = store->svc()->sysobj->init_obj_ctx(); + bufferlist bl; + + int r = rgw_get_system_obj(obj_ctx, pool, key, bl, nullptr, nullptr, y, dpp); + if (r < 0) { + return r; + } + + auto iter = bl.cbegin(); + try { + ceph::decode(script, iter); + } catch (buffer::error& err) { + return -EIO; + } + + return 0; +} + +int RadosLuaScriptManager::put(const DoutPrefixProvider* dpp, optional_yield y, const std::string& key, const std::string& script) +{ + auto obj_ctx = store->svc()->sysobj->init_obj_ctx(); + bufferlist bl; + ceph::encode(script, bl); + + int r = rgw_put_system_obj(obj_ctx, pool, key, bl, false, nullptr, real_time(), y); + if (r < 0) { + return r; + } + + return 0; +} + +int RadosLuaScriptManager::del(const DoutPrefixProvider* dpp, optional_yield y, const std::string& key) +{ + int r = rgw_delete_system_obj(store->svc()->sysobj, pool, key, nullptr, y); + if (r < 0 && r != -ENOENT) { + return r; + } + + return 0; +} + +int RadosOIDCProvider::store_url(const DoutPrefixProvider *dpp, const std::string& url, bool exclusive, optional_yield y) +{ + auto obj_ctx = store->svc()->sysobj->init_obj_ctx(); + std::string oid = tenant + get_url_oid_prefix() + url; + + bufferlist bl; + using ceph::encode; + encode(*this, bl); + return rgw_put_system_obj(obj_ctx, store->get_zone()->get_params().oidc_pool, oid, bl, exclusive, nullptr, real_time(), y); +} + +int RadosOIDCProvider::read_url(const DoutPrefixProvider *dpp, const std::string& url, const std::string& tenant) +{ + auto obj_ctx = store->svc()->sysobj->init_obj_ctx(); + auto& pool = store->get_zone()->get_params().oidc_pool; + std::string oid = tenant + get_url_oid_prefix() + url; + bufferlist bl; + + int ret = rgw_get_system_obj(obj_ctx, pool, oid, bl, nullptr, nullptr, null_yield, dpp); + if (ret < 0) { + return ret; + } + + try { + using ceph::decode; + auto iter = bl.cbegin(); + decode(*this, iter); + } catch (buffer::error& err) { + ldpp_dout(dpp, 0) << "ERROR: failed to decode oidc provider info from pool: " << pool.name << + ": " << url << dendl; + return -EIO; + } + + return 0; +} + +int RadosOIDCProvider::delete_obj(const DoutPrefixProvider *dpp, optional_yield y) +{ + auto& pool = store->get_zone()->get_params().oidc_pool; + + std::string url, tenant; + auto ret = get_tenant_url_from_arn(tenant, url); + if (ret < 0) { + ldpp_dout(dpp, 0) << "ERROR: failed to parse arn" << dendl; + return -EINVAL; + } + + if (this->tenant != tenant) { + ldpp_dout(dpp, 0) << "ERROR: tenant in arn doesn't match that of user " << this->tenant << ", " + << tenant << ": " << dendl; + return -EINVAL; + } + + // Delete url + std::string oid = tenant + get_url_oid_prefix() + url; + ret = rgw_delete_system_obj(store->svc()->sysobj, pool, oid, nullptr, y); + if (ret < 0) { + ldpp_dout(dpp, 0) << "ERROR: deleting oidc url from pool: " << pool.name << ": " + << provider_url << ": " << cpp_strerror(-ret) << dendl; + } + + return ret; +} + +int RadosRole::store_info(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y) +{ + using ceph::encode; + auto obj_ctx = store->svc()->sysobj->init_obj_ctx(); + std::string oid = get_info_oid_prefix() + id; + + bufferlist bl; + encode(*this, bl); + + return rgw_put_system_obj(obj_ctx, store->get_zone()->get_params().roles_pool, oid, bl, exclusive, nullptr, real_time(), y); +} + +int RadosRole::store_name(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y) +{ + auto obj_ctx = store->svc()->sysobj->init_obj_ctx(); + RGWNameToId nameToId; + nameToId.obj_id = id; + + std::string oid = tenant + get_names_oid_prefix() + name; + + bufferlist bl; + using ceph::encode; + encode(nameToId, bl); + + return rgw_put_system_obj(obj_ctx, store->get_zone()->get_params().roles_pool, oid, bl, exclusive, nullptr, real_time(), y); +} + +int RadosRole::store_path(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y) +{ + auto obj_ctx = store->svc()->sysobj->init_obj_ctx(); + std::string oid = tenant + get_path_oid_prefix() + path + get_info_oid_prefix() + id; + + bufferlist bl; + + return rgw_put_system_obj(obj_ctx, store->get_zone()->get_params().roles_pool, oid, bl, exclusive, nullptr, 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 obj_ctx = store->svc()->sysobj->init_obj_ctx(); + std::string oid = tenant + get_names_oid_prefix() + role_name; + bufferlist bl; + + int ret = rgw_get_system_obj(obj_ctx, store->get_zone()->get_params().roles_pool, oid, bl, nullptr, nullptr, null_yield, 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 obj_ctx = store->svc()->sysobj->init_obj_ctx(); + std::string oid = tenant + get_names_oid_prefix() + name; + bufferlist bl; + + int ret = rgw_get_system_obj(obj_ctx, store->get_zone()->get_params().roles_pool, oid, bl, nullptr, nullptr, null_yield, dpp); + if (ret < 0) { + ldpp_dout(dpp, 0) << "ERROR: failed reading role name from Role pool: " << 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: " << name << dendl; + return -EIO; + } + id = nameToId.obj_id; + return 0; +} + +int RadosRole::read_info(const DoutPrefixProvider *dpp, optional_yield y) +{ + auto obj_ctx = store->svc()->sysobj->init_obj_ctx(); + std::string oid = get_info_oid_prefix() + id; + bufferlist bl; + + int ret = rgw_get_system_obj(obj_ctx, store->get_zone()->get_params().roles_pool, oid, bl, nullptr, nullptr, null_yield, dpp); + if (ret < 0) { + ldpp_dout(dpp, 0) << "ERROR: failed reading role info from Role pool: " << id << ": " << cpp_strerror(-ret) << dendl; + return ret; + } + + try { + using ceph::decode; + auto iter = bl.cbegin(); + decode(*this, iter); + } catch (buffer::error& err) { + ldpp_dout(dpp, 0) << "ERROR: failed to decode role info from Role pool: " << id << dendl; + return -EIO; + } + + return 0; +} + +int RadosRole::create(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y) +{ + int ret; + + if (! validate_input(dpp)) { + return -EINVAL; + } + + /* check to see the name is not used */ + ret = read_id(dpp, name, tenant, id, y); + if (exclusive && ret == 0) { + ldpp_dout(dpp, 0) << "ERROR: name " << name << " already in use for role id " + << id << dendl; + return -EEXIST; + } else if ( ret < 0 && ret != -ENOENT) { + ldpp_dout(dpp, 0) << "failed reading role id " << id << ": " + << cpp_strerror(-ret) << dendl; + return ret; + } + + /* create unique id */ + uuid_d new_uuid; + char uuid_str[37]; + new_uuid.generate_random(); + new_uuid.print(uuid_str); + id = uuid_str; + + //arn + arn = role_arn_prefix + tenant + ":role" + path + name; + + // 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),".%dZ",(int)tv.tv_usec/1000); + creation_date.assign(buf, strlen(buf)); + + auto& pool = store->get_zone()->get_params().roles_pool; + ret = store_info(dpp, exclusive, y); + if (ret < 0) { + ldpp_dout(dpp, 0) << "ERROR: storing role info in Role pool: " + << 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: " + << name << ": " << cpp_strerror(-ret) << dendl; + + //Delete the role info that was stored in the previous call + std::string oid = get_info_oid_prefix() + id; + int info_ret = rgw_delete_system_obj(store->svc()->sysobj, pool, oid, nullptr, y); + if (info_ret < 0) { + ldpp_dout(dpp, 0) << "ERROR: cleanup of role id from Role pool: " + << 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: " + << path << ": " << cpp_strerror(-ret) << dendl; + //Delete the role info that was stored in the previous call + std::string oid = get_info_oid_prefix() + id; + int info_ret = rgw_delete_system_obj(store->svc()->sysobj, pool, oid, nullptr, y); + if (info_ret < 0) { + ldpp_dout(dpp, 0) << "ERROR: cleanup of role id from Role pool: " + << id << ": " << cpp_strerror(-info_ret) << dendl; + } + //Delete role name that was stored in previous call + oid = tenant + get_names_oid_prefix() + name; + int name_ret = rgw_delete_system_obj(store->svc()->sysobj, pool, oid, nullptr, y); + if (name_ret < 0) { + ldpp_dout(dpp, 0) << "ERROR: cleanup of role name from Role pool: " + << name << ": " << cpp_strerror(-name_ret) << dendl; + } + return ret; + } + return 0; +} + +int RadosRole::delete_obj(const DoutPrefixProvider *dpp, optional_yield y) +{ + auto& pool = store->get_zone()->get_params().roles_pool; + + int ret = read_name(dpp, y); + if (ret < 0) { + return ret; + } + + ret = read_info(dpp, y); + if (ret < 0) { + return ret; + } + + if (! perm_policy_map.empty()) { + return -ERR_DELETE_CONFLICT; + } + + // Delete id + std::string oid = get_info_oid_prefix() + id; + ret = rgw_delete_system_obj(store->svc()->sysobj, pool, oid, nullptr, y); + if (ret < 0) { + ldpp_dout(dpp, 0) << "ERROR: deleting role id from Role pool: " + << id << ": " << cpp_strerror(-ret) << dendl; + } + + // Delete name + oid = tenant + get_names_oid_prefix() + name; + ret = rgw_delete_system_obj(store->svc()->sysobj, pool, oid, nullptr, y); + if (ret < 0) { + ldpp_dout(dpp, 0) << "ERROR: deleting role name from Role pool: " + << name << ": " << cpp_strerror(-ret) << dendl; + } + + // Delete path + oid = tenant + get_path_oid_prefix() + path + get_info_oid_prefix() + id; + ret = rgw_delete_system_obj(store->svc()->sysobj, pool, oid, nullptr, y); + if (ret < 0) { + ldpp_dout(dpp, 0) << "ERROR: deleting role path from Role pool: " + << path << ": " << cpp_strerror(-ret) << dendl; + } + return ret; +} + + } // namespace rgw::sal extern "C" { diff --git a/src/rgw/rgw_sal_rados.h b/src/rgw/rgw_sal_rados.h index c54d726c24cbc..7b5e0c5e4bdf1 100644 --- a/src/rgw/rgw_sal_rados.h +++ b/src/rgw/rgw_sal_rados.h @@ -18,6 +18,8 @@ #include "rgw_sal.h" #include "rgw_rados.h" #include "rgw_notify.h" +#include "rgw_oidc_provider.h" +#include "rgw_role.h" #include "cls/lock/cls_lock_client.h" namespace rgw { namespace sal { @@ -416,9 +418,6 @@ class RadosStore : public Store { virtual int register_to_service_map(const std::string& daemon_type, const map& meta) override; virtual void get_quota(RGWQuotaInfo& bucket_quota, RGWQuotaInfo& user_quota) override; - virtual int list_raw_objects(const rgw_pool& pool, const std::string& prefix_filter, - int max, RGWListRawObjsCtx& ctx, std::list& oids, - bool* is_truncated) override; virtual int set_buckets_enabled(const DoutPrefixProvider* dpp, vector& buckets, bool enabled) override; virtual uint64_t get_new_req_id() override { return rados->get_new_req_id(); } virtual int get_sync_policy_handler(const DoutPrefixProvider* dpp, @@ -436,20 +435,6 @@ class RadosStore : public Store { map& usage) override; virtual int trim_all_usage(uint64_t start_epoch, uint64_t end_epoch) override; virtual int get_config_key_val(std::string name, bufferlist* bl) override; - virtual int put_system_obj(const rgw_pool& pool, const std::string& oid, - bufferlist& data, bool exclusive, - RGWObjVersionTracker* objv_tracker, real_time set_mtime, - optional_yield y, map *pattrs = nullptr) - override; - virtual int get_system_obj(const DoutPrefixProvider* dpp, - const rgw_pool& pool, const std::string& key, - bufferlist& bl, - RGWObjVersionTracker* objv_tracker, real_time* pmtime, - optional_yield y, map *pattrs = nullptr, - rgw_cache_entry_info* cache_info = nullptr, - boost::optional refresh_version = boost::none) override; - virtual int delete_system_obj(const rgw_pool& pool, const std::string& oid, - RGWObjVersionTracker* objv_tracker, optional_yield y) override; virtual int meta_list_keys_init(const std::string& section, const std::string& marker, void** phandle) override; virtual int meta_list_keys_next(void* handle, int max, list& keys, bool* truncated) override; virtual void meta_list_keys_complete(void* handle) override; @@ -457,6 +442,22 @@ class RadosStore : public Store { virtual int meta_remove(const DoutPrefixProvider* dpp, std::string& metadata_key, optional_yield y) override; virtual const RGWSyncModuleInstanceRef& get_sync_module() { return rados->get_sync_module(); } virtual std::string get_host_id() { return rados->host_id; } + virtual std::unique_ptr get_lua_script_manager() override; + virtual std::unique_ptr get_role(string name, + string tenant, + string path="", + string trust_policy="", + string max_session_duration_str="") override; + virtual std::unique_ptr get_role(std::string id) override; + virtual int get_roles(const DoutPrefixProvider *dpp, + optional_yield y, + const std::string& path_prefix, + const std::string& tenant, + vector>& roles) override; + virtual std::unique_ptr get_oidc_provider() override; + virtual int get_oidc_providers(const DoutPrefixProvider *dpp, + const std::string& tenant, + vector>& providers) override; virtual void finalize(void) override; @@ -583,4 +584,60 @@ class RadosWriter : public Writer { virtual int drain() override; }; +class RadosLuaScriptManager : public LuaScriptManager { + RadosStore* store; + rgw_pool pool; + +public: + RadosLuaScriptManager(RadosStore* _s) : store(_s) + { + pool = store->get_zone()->get_params().log_pool; + } + virtual ~RadosLuaScriptManager() = default; + + virtual int get(const DoutPrefixProvider* dpp, optional_yield y, const std::string& key, std::string& script) override; + virtual int put(const DoutPrefixProvider* dpp, optional_yield y, const std::string& key, const std::string& script) override; + virtual int del(const DoutPrefixProvider* dpp, optional_yield y, const std::string& key) override; +}; + +class RadosOIDCProvider : public RGWOIDCProvider { + RadosStore* store; +public: + RadosOIDCProvider(RadosStore* _store) : store(_store) {} + ~RadosOIDCProvider() = default; + + virtual int store_url(const DoutPrefixProvider *dpp, const std::string& url, bool exclusive, optional_yield y) override; + virtual int read_url(const DoutPrefixProvider *dpp, const std::string& url, const std::string& tenant) override; + virtual int delete_obj(const DoutPrefixProvider *dpp, optional_yield y) override; + void encode(bufferlist& bl) const { + RGWOIDCProvider::encode(bl); + } + void decode(bufferlist::const_iterator& bl) { + RGWOIDCProvider::decode(bl); + } +}; + +class RadosRole : public RGWRole { + RadosStore* store; +public: + RadosRole(RadosStore* _store, std::string name, + std::string tenant, + std::string path, + std::string trust_policy, + std::string max_session_duration) : RGWRole(name, tenant, path, trust_policy, max_session_duration), store(_store) {} + RadosRole(RadosStore* _store, std::string id) : RGWRole(id), 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, optional_yield y) override; + virtual int delete_obj(const DoutPrefixProvider *dpp, optional_yield y) override; +}; + } } // namespace rgw::sal + +WRITE_CLASS_ENCODER(rgw::sal::RadosOIDCProvider) diff --git a/src/rgw/rgw_sts.cc b/src/rgw/rgw_sts.cc index b4a2c4a28c090..c7863c57e71f2 100644 --- a/src/rgw/rgw_sts.cc +++ b/src/rgw/rgw_sts.cc @@ -276,20 +276,20 @@ int AssumeRoleRequest::validate_input() const return AssumeRoleRequestBase::validate_input(); } -std::tuple STSService::getRoleInfo(const DoutPrefixProvider *dpp, +std::tuple STSService::getRoleInfo(const DoutPrefixProvider *dpp, const string& arn, optional_yield y) { if (auto r_arn = rgw::ARN::parse(arn); r_arn) { auto pos = r_arn->resource.find_last_of('/'); string roleName = r_arn->resource.substr(pos + 1); - RGWRole role(cct, store, roleName, r_arn->account); - if (int ret = role.get(dpp, y); ret < 0) { + std::unique_ptr role = store->get_role(roleName, r_arn->account); + if (int ret = role->get(dpp, y); ret < 0) { if (ret == -ENOENT) { ldpp_dout(dpp, 0) << "Role doesn't exist: " << roleName << dendl; ret = -ERR_NO_ROLE_FOUND; } - return make_tuple(ret, this->role); + return make_tuple(ret, nullptr); } else { auto path_pos = r_arn->resource.find('/'); string path; @@ -298,17 +298,17 @@ std::tuple STSService::getRoleInfo(const DoutPrefixProvider *dpp, } else { path = r_arn->resource.substr(path_pos, ((pos - path_pos) + 1)); } - string r_path = role.get_path(); + string r_path = role->get_path(); if (path != r_path) { ldpp_dout(dpp, 0) << "Invalid Role ARN: Path in ARN does not match with the role path: " << path << " " << r_path << dendl; - return make_tuple(-EACCES, this->role); + return make_tuple(-EACCES, nullptr); } this->role = std::move(role); - return make_tuple(0, this->role); + return make_tuple(0, this->role.get()); } } else { ldpp_dout(dpp, 0) << "Invalid role arn: " << arn << dendl; - return make_tuple(-EINVAL, this->role); + return make_tuple(-EINVAL, nullptr); } } @@ -355,8 +355,8 @@ AssumeRoleWithWebIdentityResponse STSService::assumeRoleWithWebIdentity(AssumeRo return response; } - string roleId = role.get_id(); - uint64_t roleMaxSessionDuration = role.get_max_session_duration(); + string roleId = role->get_id(); + uint64_t roleMaxSessionDuration = role->get_max_session_duration(); req.setMaxDuration(roleMaxSessionDuration); //Validate input @@ -409,8 +409,8 @@ AssumeRoleResponse STSService::assumeRole(const DoutPrefixProvider *dpp, return response; } - string roleId = role.get_id(); - uint64_t roleMaxSessionDuration = role.get_max_session_duration(); + string roleId = role->get_id(); + uint64_t roleMaxSessionDuration = role->get_max_session_duration(); req.setMaxDuration(roleMaxSessionDuration); //Validate input diff --git a/src/rgw/rgw_sts.h b/src/rgw/rgw_sts.h index 19c00c3e57294..9730c2a1185c0 100644 --- a/src/rgw/rgw_sts.h +++ b/src/rgw/rgw_sts.h @@ -227,7 +227,7 @@ class STSService { CephContext* cct; rgw::sal::Store* store; rgw_user user_id; - RGWRole role; + std::unique_ptr role; rgw::auth::Identity* identity; int storeARN(const DoutPrefixProvider *dpp, string& arn, optional_yield y); public: @@ -235,7 +235,7 @@ public: STSService(CephContext* cct, rgw::sal::Store* store, rgw_user user_id, rgw::auth::Identity* identity) : cct(cct), store(store), user_id(user_id), identity(identity) {} - std::tuple getRoleInfo(const DoutPrefixProvider *dpp, const string& arn, optional_yield y); + std::tuple getRoleInfo(const DoutPrefixProvider *dpp, const string& arn, optional_yield y); AssumeRoleResponse assumeRole(const DoutPrefixProvider *dpp, AssumeRoleRequest& req, optional_yield y); GetSessionTokenResponse getSessionToken(GetSessionTokenRequest& req); AssumeRoleWithWebIdentityResponse assumeRoleWithWebIdentity(AssumeRoleWithWebIdentityRequest& req); -- 2.47.3