From: Casey Bodley Date: Tue, 12 Dec 2023 21:36:04 +0000 (-0500) Subject: rgw/pubsub: use rgw_owner for topic ownership X-Git-Tag: v19.1.0~99^2~142 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=5777a349088ba8a017dce734f41ce5d50790773c;p=ceph.git rgw/pubsub: use rgw_owner for topic ownership allow topics to be owned by accounts instead of users. radosgw-admin topic list can now filter by --account-id Signed-off-by: Casey Bodley (cherry picked from commit 13d1c803f6a90ad1747f21faa7a6e89d7e8af8c1) --- diff --git a/src/rgw/driver/rados/rgw_sal_rados.cc b/src/rgw/driver/rados/rgw_sal_rados.cc index d0a3bac1896..e965a8e233a 100644 --- a/src/rgw/driver/rados/rgw_sal_rados.cc +++ b/src/rgw/driver/rados/rgw_sal_rados.cc @@ -1317,7 +1317,7 @@ int RadosStore::update_bucket_topic_mapping(const rgw_pubsub_topic& topic, const DoutPrefixProvider* dpp) { librados::Rados& rados = *getRados()->get_rados_handle(); const RGWZoneParams& zone = svc()->zone->get_zone_params(); - const std::string key = get_topic_metadata_key(topic.user.tenant, topic.name); + const std::string key = get_topic_metadata_key(topic); int ret = 0; if (add_mapping) { ret = rgwrados::topic::link_bucket(dpp, y, rados, zone, key, bucket_key); @@ -1343,7 +1343,7 @@ int RadosStore::get_bucket_topic_mapping(const rgw_pubsub_topic& topic, { librados::Rados& rados = *getRados()->get_rados_handle(); const RGWZoneParams& zone = svc()->zone->get_zone_params(); - const std::string key = get_topic_metadata_key(topic.user.tenant, topic.name); + const std::string key = get_topic_metadata_key(topic); constexpr int max_chunk = 1024; std::string marker; diff --git a/src/rgw/driver/rados/topic.cc b/src/rgw/driver/rados/topic.cc index 86ce6bb819b..9366b6fa3dd 100644 --- a/src/rgw/driver/rados/topic.cc +++ b/src/rgw/driver/rados/topic.cc @@ -99,7 +99,7 @@ int write(const DoutPrefixProvider* dpp, optional_yield y, const rgw_pubsub_topic& info, RGWObjVersionTracker& objv, ceph::real_time mtime, bool exclusive) { - const std::string topic_key = get_topic_metadata_key(info.user.tenant, info.name); + const std::string topic_key = get_topic_metadata_key(info); const rgw_raw_obj obj = get_topic_obj(zone, topic_key); bufferlist bl; diff --git a/src/rgw/rgw_admin.cc b/src/rgw/rgw_admin.cc index c802f7d0203..05afc60ceb1 100644 --- a/src/rgw/rgw_admin.cc +++ b/src/rgw/rgw_admin.cc @@ -10732,6 +10732,13 @@ next: RGWPubSub ps(driver, tenant, *site); std::string next_token = marker; + std::optional owner; + if (!rgw::sal::User::empty(user)) { + owner = user->get_id(); + } else if (!account_id.empty()) { + owner = rgw_account_id{account_id}; + } + formatter->open_object_section("result"); formatter->open_array_section("topics"); do { @@ -10743,7 +10750,7 @@ next: return -ret; } for (const auto& [_, topic] : result.topics) { - if (!rgw::sal::User::empty(user) && user->get_id() != topic.user) { + if (owner && *owner != topic.owner) { continue; } std::set subscribed_buckets; diff --git a/src/rgw/rgw_pubsub.cc b/src/rgw/rgw_pubsub.cc index 3ce0f720a38..15e9ad7616b 100644 --- a/src/rgw/rgw_pubsub.cc +++ b/src/rgw/rgw_pubsub.cc @@ -12,6 +12,7 @@ #include "rgw_pubsub_push.h" #include "rgw_bucket.h" #include "common/errno.h" +#include "include/function2.hpp" #include #include @@ -26,6 +27,16 @@ std::string get_topic_metadata_key(std::string_view tenant, return string_cat_reserve(tenant, topic_tenant_delim, topic_name); } +std::string get_topic_metadata_key(const rgw_pubsub_topic& topic) +{ + // use account id or tenant name + std::string_view tenant = std::visit(fu2::overload( + [] (const rgw_user& u) -> std::string_view { return u.tenant; }, + [] (const rgw_account_id& a) -> std::string_view { return a; } + ), topic.owner); + return get_topic_metadata_key(tenant, topic.name); +} + void parse_topic_metadata_key(const std::string& key, std::string& tenant, std::string& name) @@ -359,7 +370,7 @@ void rgw_pubsub_s3_event::dump(Formatter *f) const { void rgw_pubsub_topic::dump(Formatter *f) const { - encode_json("user", user, f); + encode_json("owner", owner, f); encode_json("name", name, f); encode_json("dest", dest, f); encode_json("arn", arn, f); @@ -369,7 +380,7 @@ void rgw_pubsub_topic::dump(Formatter *f) const void rgw_pubsub_topic::dump_xml(Formatter *f) const { - encode_xml("User", user, f); + encode_xml("User", to_string(owner), f); encode_xml("Name", name, f); encode_xml("EndPoint", dest, f); encode_xml("TopicArn", arn, f); @@ -387,9 +398,7 @@ void encode_xml_key_value_entry(const std::string& key, const std::string& value void rgw_pubsub_topic::dump_xml_as_attributes(Formatter *f) const { f->open_array_section("Attributes"); - std::string str_user; - user.to_str(str_user); - encode_xml_key_value_entry("User", str_user, f); + encode_xml_key_value_entry("User", to_string(owner), f); encode_xml_key_value_entry("Name", name, f); encode_xml_key_value_entry("EndPoint", dest.to_json_str(), f); encode_xml_key_value_entry("TopicArn", arn, f); @@ -400,7 +409,7 @@ void rgw_pubsub_topic::dump_xml_as_attributes(Formatter *f) const } void rgw_pubsub_topic::decode_json(JSONObj* f) { - JSONDecoder::decode_json("user", user, f); + JSONDecoder::decode_json("owner", owner, f); JSONDecoder::decode_json("name", name, f); JSONDecoder::decode_json("dest", dest, f); JSONDecoder::decode_json("arn", arn, f); @@ -963,7 +972,7 @@ int RGWPubSub::create_topic(const DoutPrefixProvider* dpp, const std::string& name, const rgw_pubsub_dest& dest, const std::string& arn, const std::string& opaque_data, - const rgw_user& user, + const rgw_owner& owner, const std::string& policy_text, optional_yield y) const { if (use_notification_v2) { @@ -973,7 +982,7 @@ int RGWPubSub::create_topic(const DoutPrefixProvider* dpp, return -ERR_SERVICE_UNAVAILABLE; } rgw_pubsub_topic new_topic; - new_topic.user = user; + new_topic.owner = owner; new_topic.name = name; new_topic.dest = dest; new_topic.arn = arn; @@ -992,7 +1001,7 @@ int RGWPubSub::create_topic(const DoutPrefixProvider* dpp, } rgw_pubsub_topic& new_topic = topics.topics[name]; - new_topic.user = user; + new_topic.owner = owner; new_topic.name = name; new_topic.dest = dest; new_topic.arn = arn; diff --git a/src/rgw/rgw_pubsub.h b/src/rgw/rgw_pubsub.h index 89b6e5d7251..6891c6ebd15 100644 --- a/src/rgw/rgw_pubsub.h +++ b/src/rgw/rgw_pubsub.h @@ -3,7 +3,8 @@ #pragma once -#include "rgw_sal.h" +#include "common/versioned_variant.h" +#include "rgw_sal_fwd.h" #include "rgw_tools.h" #include "rgw_zone.h" #include "rgw_notify_event_type.h" @@ -394,7 +395,7 @@ struct rgw_pubsub_dest { WRITE_CLASS_ENCODER(rgw_pubsub_dest) struct rgw_pubsub_topic { - rgw_user user; + rgw_owner owner; std::string name; rgw_pubsub_dest dest; std::string arn; @@ -403,7 +404,8 @@ struct rgw_pubsub_topic { void encode(bufferlist& bl) const { ENCODE_START(4, 1, bl); - encode(user, bl); + // converted from rgw_user to rgw_owner + ceph::converted_variant::encode(owner, bl); encode(name, bl); encode(dest, bl); encode(arn, bl); @@ -414,7 +416,8 @@ struct rgw_pubsub_topic { void decode(bufferlist::const_iterator& bl) { DECODE_START(4, bl); - decode(user, bl); + // converted from rgw_user to rgw_owner + ceph::converted_variant::decode(owner, bl); decode(name, bl); if (struct_v >= 2) { decode(dest, bl); @@ -429,18 +432,10 @@ struct rgw_pubsub_topic { DECODE_FINISH(bl); } - std::string to_str() const { - return user.tenant + "/" + name; - } - void dump(Formatter *f) const; void dump_xml(Formatter *f) const; void dump_xml_as_attributes(Formatter *f) const; void decode_json(JSONObj* obj); - - bool operator<(const rgw_pubsub_topic& t) const { - return to_str().compare(t.to_str()); - } }; WRITE_CLASS_ENCODER(rgw_pubsub_topic) @@ -640,7 +635,7 @@ public: // return 0 on success, error code otherwise int create_topic(const DoutPrefixProvider* dpp, const std::string& name, const rgw_pubsub_dest& dest, const std::string& arn, - const std::string& opaque_data, const rgw_user& user, + const std::string& opaque_data, const rgw_owner& owner, const std::string& policy_text, optional_yield y) const; // remove a topic according to its name // if the topic does not exists it is a no-op (considered success) @@ -690,8 +685,9 @@ int get_bucket_notifications(const DoutPrefixProvider* dpp, rgw_pubsub_bucket_topics& bucket_topics); // format and parse topic metadata keys as tenant:name -std::string get_topic_metadata_key(std::string_view topic_name, - std::string_view tenant); +std::string get_topic_metadata_key(std::string_view tenant, + std::string_view topic_name); +std::string get_topic_metadata_key(const rgw_pubsub_topic& topic); void parse_topic_metadata_key(const std::string& key, std::string& tenant_name, std::string& topic_name); diff --git a/src/rgw/rgw_rest_pubsub.cc b/src/rgw/rgw_rest_pubsub.cc index 27fad86a58b..4fb1051ebf6 100644 --- a/src/rgw/rgw_rest_pubsub.cc +++ b/src/rgw/rgw_rest_pubsub.cc @@ -106,7 +106,7 @@ int verify_topic_owner_or_policy(req_state* const s, const rgw_pubsub_topic& topic, const std::string& zonegroup_name, const uint64_t op) { - if (topic.user == s->owner.id) { + if (s->auth.identity->is_owner_of(topic.owner)) { return 0; } // no policy set. @@ -115,7 +115,7 @@ int verify_topic_owner_or_policy(req_state* const s, if (op == rgw::IAM::snsPublish && !s->cct->_conf->rgw_topic_require_publish_policy) { return 0; } - if (topic.user.empty()) { + if (std::visit([] (const auto& o) { return o.empty(); }, topic.owner)) { // if we don't know the original user and there is no policy // we will not reject the request. // this is for compatibility with versions that did not store the user in the topic @@ -563,7 +563,7 @@ class RGWPSSetTopicAttributesOp : public RGWOp { std::string opaque_data; std::string policy_text; rgw_pubsub_dest dest; - rgw_user topic_owner; + rgw_owner topic_owner; std::string attribute_name; int get_params() { @@ -669,7 +669,7 @@ class RGWPSSetTopicAttributesOp : public RGWOp { << "', ret=" << ret << dendl; return ret; } - topic_owner = result.user; + topic_owner = result.owner; ret = verify_topic_owner_or_policy( s, result, driver->get_zone()->get_zonegroup().get_name(), rgw::IAM::snsSetTopicAttributes); diff --git a/src/test/rgw/bucket_notification/test_bn.py b/src/test/rgw/bucket_notification/test_bn.py index 25770487cca..df69fbaf059 100644 --- a/src/test/rgw/bucket_notification/test_bn.py +++ b/src/test/rgw/bucket_notification/test_bn.py @@ -621,7 +621,7 @@ def test_ps_s3_topic_admin_on_master(): parsed_result = json.loads(result[0]) assert_equal(parsed_result['arn'], topic_arn3) matches = [tenant, UID_PREFIX] - assert_true( all([x in parsed_result['user'] for x in matches])) + assert_true( all([x in parsed_result['owner'] for x in matches])) # delete topic 3 _, result = admin(['topic', 'rm', '--topic', topic_name+'_3', '--tenant', tenant], get_config_cluster())