diff options
Diffstat (limited to 'src/rgw/rgw_acl.h')
-rw-r--r-- | src/rgw/rgw_acl.h | 290 |
1 files changed, 159 insertions, 131 deletions
diff --git a/src/rgw/rgw_acl.h b/src/rgw/rgw_acl.h index c520501583b..e2887a7049b 100644 --- a/src/rgw/rgw_acl.h +++ b/src/rgw/rgw_acl.h @@ -6,6 +6,7 @@ #include <map> #include <string> #include <string_view> +#include <variant> #include <include/types.h> #include <boost/optional.hpp> @@ -15,118 +16,180 @@ #include "rgw_basic_types.h" //includes rgw_acl_types.h +// acl grantee types +struct ACLGranteeCanonicalUser { + rgw_user id; + std::string name; + + friend auto operator<=>(const ACLGranteeCanonicalUser&, + const ACLGranteeCanonicalUser&) = default; +}; +struct ACLGranteeEmailUser { + std::string address; + + friend auto operator<=>(const ACLGranteeEmailUser&, + const ACLGranteeEmailUser&) = default; +}; +struct ACLGranteeGroup { + ACLGroupTypeEnum type = ACL_GROUP_NONE; + + friend auto operator<=>(const ACLGranteeGroup&, + const ACLGranteeGroup&) = default; +}; +struct ACLGranteeUnknown { + friend auto operator<=>(const ACLGranteeUnknown&, + const ACLGranteeUnknown&) = default; +}; +struct ACLGranteeReferer { + std::string url_spec; + + friend auto operator<=>(const ACLGranteeReferer&, + const ACLGranteeReferer&) = default; +}; + class ACLGrant { protected: - ACLGranteeType type; - rgw_user id; - std::string email; - mutable rgw_user email_id; + // acl grantee variant, where variant index matches ACLGranteeTypeEnum + using ACLGrantee = std::variant< + ACLGranteeCanonicalUser, + ACLGranteeEmailUser, + ACLGranteeGroup, + ACLGranteeUnknown, + ACLGranteeReferer>; + + ACLGrantee grantee; ACLPermission permission; - std::string name; - ACLGroupTypeEnum group; - std::string url_spec; public: - ACLGrant() : group(ACL_GROUP_NONE) {} - virtual ~ACLGrant() {} - - /* there's an assumption here that email/uri/id encodings are - different and there can't be any overlap */ - bool get_id(rgw_user& _id) const { - switch(type.get_type()) { - case ACL_TYPE_EMAIL_USER: - _id = email; // implies from_str() that parses the 't:u' syntax - return true; - case ACL_TYPE_GROUP: - case ACL_TYPE_REFERER: - return false; - default: - _id = id; - return true; - } + ACLGranteeType get_type() const { + return static_cast<ACLGranteeTypeEnum>(grantee.index()); } + ACLPermission get_permission() const { return permission; } - const rgw_user* get_id() const { - switch(type.get_type()) { - case ACL_TYPE_EMAIL_USER: - email_id.from_str(email); - return &email_id; - case ACL_TYPE_GROUP: - case ACL_TYPE_REFERER: - return nullptr; - default: - return &id; - } + // return the user grantee, or nullptr + const ACLGranteeCanonicalUser* get_user() const { + return std::get_if<ACLGranteeCanonicalUser>(&grantee); + } + // return the email grantee, or nullptr + const ACLGranteeEmailUser* get_email() const { + return std::get_if<ACLGranteeEmailUser>(&grantee); + } + // return the group grantee, or nullptr + const ACLGranteeGroup* get_group() const { + return std::get_if<ACLGranteeGroup>(&grantee); + } + // return the referer grantee, or nullptr + const ACLGranteeReferer* get_referer() const { + return std::get_if<ACLGranteeReferer>(&grantee); } - - ACLGranteeType& get_type() { return type; } - const ACLGranteeType& get_type() const { return type; } - ACLPermission& get_permission() { return permission; } - const ACLPermission& get_permission() const { return permission; } - ACLGroupTypeEnum get_group() const { return group; } - const std::string& get_referer() const { return url_spec; } void encode(bufferlist& bl) const { ENCODE_START(5, 3, bl); + ACLGranteeType type = get_type(); encode(type, bl); - std::string s; - id.to_str(s); - encode(s, bl); - std::string uri; + + if (const ACLGranteeCanonicalUser* user = get_user(); user) { + encode(user->id.to_str(), bl); + } else { + encode(std::string{}, bl); // encode empty id + } + + std::string uri; // always empty, v2 converted to 'ACLGroupTypeEnum g' below encode(uri, bl); - encode(email, bl); + + if (const ACLGranteeEmailUser* email = get_email(); email) { + encode(email->address, bl); + } else { + encode(std::string{}, bl); // encode empty email address + } encode(permission, bl); - encode(name, bl); - __u32 g = (__u32)group; + if (const ACLGranteeCanonicalUser* user = get_user(); user) { + encode(user->name, bl); + } else { + encode(std::string{}, bl); // encode empty name + } + + __u32 g; + if (const ACLGranteeGroup* group = get_group(); group) { + g = static_cast<__u32>(group->type); + } else { + g = static_cast<__u32>(ACL_GROUP_NONE); + } encode(g, bl); - encode(url_spec, bl); + + if (const ACLGranteeReferer* referer = get_referer(); referer) { + encode(referer->url_spec, bl); + } else { + encode(std::string{}, bl); // encode empty referer + } ENCODE_FINISH(bl); } void decode(bufferlist::const_iterator& bl) { DECODE_START_LEGACY_COMPAT_LEN(5, 3, 3, bl); + ACLGranteeType type; decode(type, bl); + + ACLGranteeCanonicalUser user; std::string s; decode(s, bl); - id.from_str(s); + user.id.from_str(s); + std::string uri; decode(uri, bl); - decode(email, bl); + + ACLGranteeEmailUser email; + decode(email.address, bl); + decode(permission, bl); - decode(name, bl); - if (struct_v > 1) { - __u32 g; - decode(g, bl); - group = (ACLGroupTypeEnum)g; - } else { - group = uri_to_group(uri); - } + decode(user.name, bl); + + ACLGranteeGroup group; + __u32 g; + decode(g, bl); + group.type = static_cast<ACLGroupTypeEnum>(g); + + ACLGranteeReferer referer; if (struct_v >= 5) { - decode(url_spec, bl); - } else { - url_spec.clear(); + decode(referer.url_spec, bl); + } + + // construct the grantee type + switch (type) { + case ACL_TYPE_CANON_USER: + grantee = std::move(user); + break; + case ACL_TYPE_EMAIL_USER: + grantee = std::move(email); + break; + case ACL_TYPE_GROUP: + grantee = std::move(group); + break; + case ACL_TYPE_REFERER: + grantee = std::move(referer); + break; + case ACL_TYPE_UNKNOWN: + default: + grantee = ACLGranteeUnknown{}; + break; } DECODE_FINISH(bl); } void dump(Formatter *f) const; static void generate_test_instances(std::list<ACLGrant*>& o); - ACLGroupTypeEnum uri_to_group(std::string& uri); + static ACLGroupTypeEnum uri_to_group(std::string_view uri); - void set_canon(const rgw_user& _id, const std::string& _name, const uint32_t perm) { - type.set(ACL_TYPE_CANON_USER); - id = _id; - name = _name; + void set_canon(const rgw_user& id, const std::string& name, uint32_t perm) { + grantee = ACLGranteeCanonicalUser{id, name}; permission.set_permissions(perm); } - void set_group(ACLGroupTypeEnum _group, const uint32_t perm) { - type.set(ACL_TYPE_GROUP); - group = _group; + void set_group(ACLGroupTypeEnum group, uint32_t perm) { + grantee = ACLGranteeGroup{group}; permission.set_permissions(perm); } - void set_referer(const std::string& _url_spec, const uint32_t perm) { - type.set(ACL_TYPE_REFERER); - url_spec = _url_spec; + void set_referer(const std::string& url_spec, uint32_t perm) { + grantee = ACLGranteeReferer{url_spec}; permission.set_permissions(perm); } @@ -219,31 +282,22 @@ using ACLGrantMap = std::multimap<std::string, ACLGrant>; class RGWAccessControlList { protected: - CephContext *cct; /* FIXME: in the feature we should consider switching to uint32_t also * in data structures. */ std::map<std::string, int> acl_user_map; std::map<uint32_t, int> acl_group_map; std::list<ACLReferer> referer_list; ACLGrantMap grant_map; - void _add_grant(ACLGrant *grant); + // register a grant in the correspoding acl_user/group_map + void register_grant(const ACLGrant& grant); public: - explicit RGWAccessControlList(CephContext *_cct) : cct(_cct) {} - RGWAccessControlList() : cct(NULL) {} - - void set_ctx(CephContext *ctx) { - cct = ctx; - } - - virtual ~RGWAccessControlList() {} - uint32_t get_perm(const DoutPrefixProvider* dpp, const rgw::auth::Identity& auth_identity, - uint32_t perm_mask); + uint32_t perm_mask) const; uint32_t get_group_perm(const DoutPrefixProvider *dpp, ACLGroupTypeEnum group, uint32_t perm_mask) const; uint32_t get_referer_perm(const DoutPrefixProvider *dpp, uint32_t current_perm, std::string http_referer, - uint32_t perm_mask); + uint32_t perm_mask) const; void encode(bufferlist& bl) const { ENCODE_START(4, 3, bl); bool maps_initialized = true; @@ -263,10 +317,9 @@ public: if (struct_v >= 2) { decode(acl_group_map, bl); } else if (!maps_initialized) { - ACLGrantMap::iterator iter; - for (iter = grant_map.begin(); iter != grant_map.end(); ++iter) { - ACLGrant& grant = iter->second; - _add_grant(&grant); + // register everything in the grant_map + for (const auto& [id, grant] : grant_map) { + register_grant(grant); } } if (struct_v >= 4) { @@ -277,20 +330,20 @@ public: void dump(Formatter *f) const; static void generate_test_instances(std::list<RGWAccessControlList*>& o); - void add_grant(ACLGrant *grant); - void remove_canon_user_grant(rgw_user& user_id); + void add_grant(const ACLGrant& grant); + void remove_canon_user_grant(const rgw_user& user_id); ACLGrantMap& get_grant_map() { return grant_map; } const ACLGrantMap& get_grant_map() const { return grant_map; } - void create_default(const rgw_user& id, std::string name) { + void create_default(const rgw_user& id, const std::string& name) { acl_user_map.clear(); acl_group_map.clear(); referer_list.clear(); ACLGrant grant; grant.set_canon(id, name, RGW_PERM_FULL_CONTROL); - add_grant(&grant); + add_grant(grant); } friend bool operator==(const RGWAccessControlList& lhs, const RGWAccessControlList& rhs); @@ -298,15 +351,9 @@ public: }; WRITE_CLASS_ENCODER(RGWAccessControlList) -class ACLOwner -{ -protected: +struct ACLOwner { rgw_user id; std::string display_name; -public: - ACLOwner() {} - ACLOwner(const rgw_user& _id) : id(_id) {} - ~ACLOwner() {} void encode(bufferlist& bl) const { ENCODE_START(3, 2, bl); @@ -327,46 +374,29 @@ public: void dump(Formatter *f) const; void decode_json(JSONObj *obj); static void generate_test_instances(std::list<ACLOwner*>& o); - void set_id(const rgw_user& _id) { id = _id; } - void set_name(const std::string& name) { display_name = name; } - - rgw_user& get_id() { return id; } - const rgw_user& get_id() const { return id; } - std::string& get_display_name() { return display_name; } - const std::string& get_display_name() const { return display_name; } - friend bool operator==(const ACLOwner& lhs, const ACLOwner& rhs); - friend bool operator!=(const ACLOwner& lhs, const ACLOwner& rhs); + + auto operator<=>(const ACLOwner&) const = default; }; WRITE_CLASS_ENCODER(ACLOwner) class RGWAccessControlPolicy { protected: - CephContext *cct; RGWAccessControlList acl; ACLOwner owner; public: - explicit RGWAccessControlPolicy(CephContext *_cct) : cct(_cct), acl(_cct) {} - RGWAccessControlPolicy() : cct(NULL), acl(NULL) {} - virtual ~RGWAccessControlPolicy() {} - - void set_ctx(CephContext *ctx) { - cct = ctx; - acl.set_ctx(ctx); - } - uint32_t get_perm(const DoutPrefixProvider* dpp, const rgw::auth::Identity& auth_identity, uint32_t perm_mask, const char * http_referer, - bool ignore_public_acls=false); + bool ignore_public_acls=false) const; bool verify_permission(const DoutPrefixProvider* dpp, const rgw::auth::Identity& auth_identity, uint32_t user_perm_mask, uint32_t perm, const char * http_referer = nullptr, - bool ignore_public_acls=false); + bool ignore_public_acls=false) const; void encode(bufferlist& bl) const { ENCODE_START(2, 2, bl); @@ -388,15 +418,14 @@ public: DECODE_FINISH(bl); } - void set_owner(ACLOwner& o) { owner = o; } - ACLOwner& get_owner() { - return owner; - } + void set_owner(const ACLOwner& o) { owner = o; } + const ACLOwner& get_owner() const { return owner; } + ACLOwner& get_owner() { return owner; } - void create_default(const rgw_user& id, std::string& name) { + void create_default(const rgw_user& id, const std::string& name) { acl.create_default(id, name); - owner.set_id(id); - owner.set_name(name); + owner.id = id; + owner.display_name = name; } RGWAccessControlList& get_acl() { return acl; @@ -405,7 +434,6 @@ public: return acl; } - virtual bool compare_group_name(std::string& id, ACLGroupTypeEnum group) { return false; } bool is_public(const DoutPrefixProvider *dpp) const; friend bool operator==(const RGWAccessControlPolicy& lhs, const RGWAccessControlPolicy& rhs); |