diff options
Diffstat (limited to 'src/rgw/rgw_common.h')
-rw-r--r-- | src/rgw/rgw_common.h | 190 |
1 files changed, 165 insertions, 25 deletions
diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h index a70b043318d..5e44eeed89b 100644 --- a/src/rgw/rgw_common.h +++ b/src/rgw/rgw_common.h @@ -22,10 +22,13 @@ #include <unordered_map> #include <fmt/format.h> +#include <boost/container/flat_map.hpp> +#include <boost/container/flat_set.hpp> #include "common/ceph_crypto.h" #include "common/random_string.h" #include "common/tracer.h" +#include "common/versioned_variant.h" #include "rgw_acl.h" #include "rgw_bucket_layout.h" #include "rgw_cors.h" @@ -150,6 +153,7 @@ using ceph::crypto::MD5; /* IAM Policy */ #define RGW_ATTR_IAM_POLICY RGW_ATTR_PREFIX "iam-policy" #define RGW_ATTR_USER_POLICY RGW_ATTR_PREFIX "user-policy" +#define RGW_ATTR_MANAGED_POLICY RGW_ATTR_PREFIX "managed-policy" #define RGW_ATTR_PUBLIC_ACCESS RGW_ATTR_PREFIX "public-access" /* RGW File Attributes */ @@ -212,7 +216,16 @@ static inline const char* to_mime_type(const RGWFormat f) #define RGW_REST_WEBSITE 0x8 #define RGW_REST_STS 0x10 #define RGW_REST_IAM 0x20 -#define RGW_REST_SNS 0x30 +#define RGW_REST_SNS 0x40 + +inline constexpr const char* RGW_REST_IAM_XMLNS = + "https://iam.amazonaws.com/doc/2010-05-08/"; + +inline constexpr const char* RGW_REST_SNS_XMLNS = + "https://sns.amazonaws.com/doc/2010-03-31/"; + +inline constexpr const char* RGW_REST_STS_XMLNS = + "https://sts.amazonaws.com/doc/2011-06-15/"; #define RGW_SUSPENDED_USER_AUID (uint64_t)-2 @@ -312,6 +325,7 @@ static inline const char* to_mime_type(const RGWFormat f) #define ERR_INVALID_OBJECT_STATE 2222 #define ERR_PRESIGNED_URL_EXPIRED 2223 #define ERR_PRESIGNED_URL_DISABLED 2224 +#define ERR_AUTHORIZATION 2225 // SNS 403 AuthorizationError #define ERR_BUSY_RESHARDING 2300 #define ERR_NO_SUCH_ENTITY 2301 @@ -322,6 +336,7 @@ static inline const char* to_mime_type(const RGWFormat f) #define ERR_INVALID_IDENTITY_TOKEN 2401 #define ERR_NO_SUCH_TAG_SET 2402 +#define ERR_ACCOUNT_EXISTS 2403 #ifndef UINT32_MAX #define UINT32_MAX (0xffffffffu) @@ -514,6 +529,7 @@ enum RGWIdentityType TYPE_LDAP=3, TYPE_ROLE=4, TYPE_WEB=5, + TYPE_ROOT=6, // account root user }; void encode_json(const char *name, const rgw_placement_rule& val, ceph::Formatter *f); @@ -571,21 +587,24 @@ struct RGWUserInfo int32_t max_buckets; uint32_t op_mask; RGWUserCaps caps; - __u8 admin; - __u8 system; + __u8 admin = 0; + __u8 system = 0; rgw_placement_rule default_placement; std::list<std::string> placement_tags; std::map<int, std::string> temp_url_keys; RGWQuota quota; uint32_t type; std::set<std::string> mfa_ids; + rgw_account_id account_id; + std::string path = "/"; + ceph::real_time create_date; + std::multimap<std::string, std::string> tags; + boost::container::flat_set<std::string, std::less<>> group_ids; RGWUserInfo() : suspended(0), max_buckets(RGW_DEFAULT_MAX_BUCKETS), op_mask(RGW_OP_TYPE_ALL), - admin(0), - system(0), type(TYPE_NONE) { } @@ -601,7 +620,7 @@ struct RGWUserInfo } void encode(bufferlist& bl) const { - ENCODE_START(22, 9, bl); + ENCODE_START(23, 9, bl); encode((uint64_t)0, bl); // old auid std::string access_key; std::string secret_key; @@ -648,10 +667,15 @@ struct RGWUserInfo encode(assumed_role_arn, bl); } encode(user_id.ns, bl); + encode(account_id, bl); + encode(path, bl); + encode(create_date, bl); + encode(tags, bl); + encode(group_ids, bl); ENCODE_FINISH(bl); } void decode(bufferlist::const_iterator& bl) { - DECODE_START_LEGACY_COMPAT_LEN_32(22, 9, 9, bl); + DECODE_START_LEGACY_COMPAT_LEN_32(23, 9, 9, bl); if (struct_v >= 2) { uint64_t old_auid; decode(old_auid, bl); @@ -738,6 +762,15 @@ struct RGWUserInfo } else { user_id.ns.clear(); } + if (struct_v >= 23) { + decode(account_id, bl); + decode(path, bl); + decode(create_date, bl); + decode(tags, bl); + decode(group_ids, bl); + } else { + path = "/"; + } DECODE_FINISH(bl); } void dump(Formatter *f) const; @@ -747,6 +780,99 @@ struct RGWUserInfo }; WRITE_CLASS_ENCODER(RGWUserInfo) +// user account metadata +struct RGWAccountInfo { + rgw_account_id id; + std::string tenant; + std::string name; + std::string email; + RGWQuotaInfo quota; + + static constexpr int32_t DEFAULT_USER_LIMIT = 1000; + int32_t max_users = DEFAULT_USER_LIMIT; + + static constexpr int32_t DEFAULT_ROLE_LIMIT = 1000; + int32_t max_roles = DEFAULT_ROLE_LIMIT; + + static constexpr int32_t DEFAULT_GROUP_LIMIT = 1000; + int32_t max_groups = DEFAULT_GROUP_LIMIT; + + static constexpr int32_t DEFAULT_BUCKET_LIMIT = 1000; + int32_t max_buckets = DEFAULT_BUCKET_LIMIT; + + static constexpr int32_t DEFAULT_ACCESS_KEY_LIMIT = 4; + int32_t max_access_keys = DEFAULT_ACCESS_KEY_LIMIT; + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + encode(id, bl); + encode(tenant, bl); + encode(name, bl); + encode(email, bl); + encode(quota, bl); + encode(max_users, bl); + encode(max_roles, bl); + encode(max_groups, bl); + encode(max_buckets, bl); + encode(max_access_keys, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::const_iterator& bl) { + DECODE_START(1, bl); + decode(id, bl); + decode(tenant, bl); + decode(name, bl); + decode(email, bl); + decode(quota, bl); + decode(max_users, bl); + decode(max_roles, bl); + decode(max_groups, bl); + decode(max_buckets, bl); + decode(max_access_keys, bl); + DECODE_FINISH(bl); + } + + void dump(Formatter* f) const; + void decode_json(JSONObj* obj); + static void generate_test_instances(std::list<RGWAccountInfo*>& o); +}; +WRITE_CLASS_ENCODER(RGWAccountInfo) + +// user group metadata +struct RGWGroupInfo { + std::string id; + std::string tenant; + std::string name; + std::string path; + rgw_account_id account_id; + + void encode(bufferlist& bl) const { + ENCODE_START(1, 1, bl); + encode(id, bl); + encode(tenant, bl); + encode(name, bl); + encode(path, bl); + encode(account_id, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::const_iterator& bl) { + DECODE_START(1, bl); + decode(id, bl); + decode(tenant, bl); + decode(name, bl); + decode(path, bl); + decode(account_id, bl); + DECODE_FINISH(bl); + } + + void dump(Formatter* f) const; + void decode_json(JSONObj* obj); + static void generate_test_instances(std::list<RGWGroupInfo*>& o); +}; +WRITE_CLASS_ENCODER(RGWGroupInfo) + /// `RGWObjVersionTracker` /// ====================== /// @@ -898,7 +1024,7 @@ class RGWSI_Zone; struct RGWBucketInfo { rgw_bucket bucket; - rgw_user owner; + rgw_owner owner; uint32_t flags{0}; std::string zonegroup; ceph::real_time creation_time; @@ -973,7 +1099,7 @@ WRITE_CLASS_ENCODER(RGWBucketInfo) struct RGWBucketEntryPoint { rgw_bucket bucket; - rgw_user owner; + rgw_owner owner; ceph::real_time creation_time; bool linked; @@ -983,13 +1109,19 @@ struct RGWBucketEntryPoint RGWBucketEntryPoint() : linked(false), has_bucket_info(false) {} void encode(bufferlist& bl) const { + const rgw_user* user = std::get_if<rgw_user>(&owner); ENCODE_START(10, 8, bl); encode(bucket, bl); - encode(owner.id, bl); + if (user) { + encode(user->id, bl); + } else { + encode(std::string{}, bl); // empty user id + } encode(linked, bl); uint64_t ctime = (uint64_t)real_clock::to_time_t(creation_time); encode(ctime, bl); - encode(owner, bl); + // 'rgw_user owner' converted to 'rgw_owner' + ceph::converted_variant::encode(owner, bl); encode(creation_time, bl); ENCODE_FINISH(bl); } @@ -1004,7 +1136,8 @@ struct RGWBucketEntryPoint } has_bucket_info = false; decode(bucket, bl); - decode(owner.id, bl); + std::string user_id; + decode(user_id, bl); decode(linked, bl); uint64_t ctime; decode(ctime, bl); @@ -1012,7 +1145,9 @@ struct RGWBucketEntryPoint creation_time = real_clock::from_time_t((time_t)ctime); } if (struct_v >= 9) { - decode(owner, bl); + ceph::converted_variant::decode(owner, bl); + } else { + owner = rgw_user{"", user_id}; } if (struct_v >= 10) { decode(creation_time, bl); @@ -1138,6 +1273,7 @@ struct req_state : DoutPrefixProvider { std::string src_bucket_name; std::unique_ptr<rgw::sal::Object> src_object; ACLOwner bucket_owner; + // Resource owner for the authenticated identity, initialized in authorize() ACLOwner owner; std::string zonegroup_name; @@ -1196,7 +1332,7 @@ struct req_state : DoutPrefixProvider { rgw::IAM::Environment env; boost::optional<rgw::IAM::Policy> iam_policy; boost::optional<PublicAccessBlockConfiguration> bucket_access_conf; - std::vector<rgw::IAM::Policy> iam_user_policies; + std::vector<rgw::IAM::Policy> iam_identity_policies; /* Is the request made by an user marked as a system one? * Being system user means we also have the admin status. */ @@ -1627,13 +1763,16 @@ bool verify_object_permission_no_policy(const DoutPrefixProvider* dpp, const RGWAccessControlPolicy& object_acl, const int perm); -/** Check if the req_state's user has the necessary permissions - * to do the requested action */ -rgw::IAM::Effect eval_identity_or_session_policies(const DoutPrefixProvider* dpp, - const std::vector<rgw::IAM::Policy>& user_policies, - const rgw::IAM::Environment& env, - const uint64_t op, - const rgw::ARN& arn); +// determine whether a request is allowed or denied within an account +rgw::IAM::Effect evaluate_iam_policies( + const DoutPrefixProvider* dpp, + const rgw::IAM::Environment& env, + const rgw::auth::Identity& identity, + bool account_root, uint64_t op, const rgw::ARN& arn, + const boost::optional<rgw::IAM::Policy>& resource_policy, + const std::vector<rgw::IAM::Policy>& identity_policies, + const std::vector<rgw::IAM::Policy>& session_policies); + bool verify_user_permission(const DoutPrefixProvider* dpp, req_state * const s, const RGWAccessControlPolicy& user_acl, @@ -1657,14 +1796,17 @@ bool verify_user_permission_no_policy(const DoutPrefixProvider* dpp, bool verify_bucket_permission( const DoutPrefixProvider* dpp, req_state * const s, - const rgw_bucket& bucket, + const rgw::ARN& arn, const RGWAccessControlPolicy& user_acl, const RGWAccessControlPolicy& bucket_acl, const boost::optional<rgw::IAM::Policy>& bucket_policy, const std::vector<rgw::IAM::Policy>& identity_policies, const std::vector<rgw::IAM::Policy>& session_policies, const uint64_t op); -bool verify_bucket_permission(const DoutPrefixProvider* dpp, req_state * const s, const uint64_t op); +bool verify_bucket_permission(const DoutPrefixProvider* dpp, req_state* s, + const rgw::ARN& arn, uint64_t op); +bool verify_bucket_permission(const DoutPrefixProvider* dpp, + req_state* s, uint64_t op); bool verify_bucket_permission_no_policy( const DoutPrefixProvider* dpp, req_state * const s, @@ -1674,8 +1816,6 @@ bool verify_bucket_permission_no_policy( bool verify_bucket_permission_no_policy(const DoutPrefixProvider* dpp, req_state * const s, const int perm); -int verify_bucket_owner_or_policy(req_state* const s, - const uint64_t op); extern bool verify_object_permission( const DoutPrefixProvider* dpp, req_state * const s, |