diff options
author | Abhishek Lekshmanan <abhishek@suse.com> | 2020-01-29 11:26:21 +0100 |
---|---|---|
committer | Abhishek Lekshmanan <abhishek@suse.com> | 2020-02-03 17:53:30 +0100 |
commit | e0b4562c61e4523a73e6170c2b502fbf648c7e73 (patch) | |
tree | ccf28a49f41006a2fe0e0e5156fdaed80e1eb7cd /src | |
parent | rgw: acl: drop unused function & make get_group_perm const (diff) | |
download | ceph-e0b4562c61e4523a73e6170c2b502fbf648c7e73.tar.xz ceph-e0b4562c61e4523a73e6170c2b502fbf648c7e73.zip |
rgw: s3: implement GetBucketPolicyStatus API
This API returns whether the Bucket Policies/ACLs are public. There are a couple
of caveats:
- AWS currently returns PolicyNotFound error in case a bucket policy doesn't
exist, though a non existant bucket policy would mean the default ACLs apply
where the bucket is private, so error return here seems like an error
- the API spec mentions TRUE and FALSE as the response IsPublic element value,
however in practice both boto/aws clients and AWS S3 return/expect a lowercase
response.
Signed-off-by: Abhishek Lekshmanan <abhishek@suse.com>
Conflicts:
src/rgw/rgw_rest_s3.h
merge conflict after zipper rework, dropped a spurious newline in rgw_rest_s3.h
after get_obj_op decl.
src/rgw/rgw_common.h
src/rgw/rgw_rest_s3.cc
src/rgw/rgw_rest_s3.h:
merge conflict after bucket replication merge, trivial conflicts
Diffstat (limited to 'src')
-rw-r--r-- | src/rgw/rgw_auth_s3.cc | 1 | ||||
-rw-r--r-- | src/rgw/rgw_common.cc | 3 | ||||
-rw-r--r-- | src/rgw/rgw_common.h | 2 | ||||
-rw-r--r-- | src/rgw/rgw_iam_policy.h | 4 | ||||
-rw-r--r-- | src/rgw/rgw_op.cc | 23 | ||||
-rw-r--r-- | src/rgw/rgw_op.h | 12 | ||||
-rw-r--r-- | src/rgw/rgw_rest_s3.cc | 21 | ||||
-rw-r--r-- | src/rgw/rgw_rest_s3.h | 9 |
8 files changed, 72 insertions, 3 deletions
diff --git a/src/rgw/rgw_auth_s3.cc b/src/rgw/rgw_auth_s3.cc index 93e46bc4621..9a40fd86dbb 100644 --- a/src/rgw/rgw_auth_s3.cc +++ b/src/rgw/rgw_auth_s3.cc @@ -33,6 +33,7 @@ static const auto signed_subresources = { "notification", "partNumber", "policy", + "policyStatus", "requestPayment", "response-cache-control", "response-content-disposition", diff --git a/src/rgw/rgw_common.cc b/src/rgw/rgw_common.cc index d3c84343690..93c625ab599 100644 --- a/src/rgw/rgw_common.cc +++ b/src/rgw/rgw_common.cc @@ -848,7 +848,8 @@ void RGWHTTPArgs::append(const string& name, const string& val) (name.compare("torrent") == 0) || (name.compare("tagging") == 0) || (name.compare("append") == 0) || - (name.compare("position") == 0)) { + (name.compare("position") == 0) || + (name.compare("policyStatus") == 0)) { sub_resources[name] = val; } else if (name[0] == 'r') { // root of all evil if ((name.compare("response-content-type") == 0) || diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h index 739b26720af..30df2dcfcba 100644 --- a/src/rgw/rgw_common.h +++ b/src/rgw/rgw_common.h @@ -534,6 +534,8 @@ enum RGWOpType { RGW_OP_GET_BUCKET_REPLICATION, RGW_OP_PUT_BUCKET_REPLICATION, RGW_OP_DELETE_BUCKET_REPLICATION, + + RGW_OP_GET_BUCKET_POLICY_STATUS }; class RGWAccessControlPolicy; diff --git a/src/rgw/rgw_iam_policy.h b/src/rgw/rgw_iam_policy.h index dfe1a857cc9..21f8ead8e72 100644 --- a/src/rgw/rgw_iam_policy.h +++ b/src/rgw/rgw_iam_policy.h @@ -100,7 +100,8 @@ static constexpr std::uint64_t s3GetObjectRetention = 57; static constexpr std::uint64_t s3PutObjectLegalHold = 58; static constexpr std::uint64_t s3GetObjectLegalHold = 59; static constexpr std::uint64_t s3BypassGovernanceRetention = 60; -static constexpr std::uint64_t s3All = 61; +static constexpr std::uint64_t s3GetBucketPolicyStatus = 61; +static constexpr std::uint64_t s3All = 62; static constexpr std::uint64_t iamPutUserPolicy = s3All + 1; static constexpr std::uint64_t iamGetUserPolicy = s3All + 2; @@ -190,6 +191,7 @@ inline int op_to_perm(std::uint64_t op) { case s3GetBucketLogging: case s3GetBucketNotification: case s3GetBucketPolicy: + case s3GetBucketPolicyStatus: case s3GetBucketRequestPayment: case s3GetBucketTagging: case s3GetBucketVersioning: diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index e02e1f9d965..c2f4a98d255 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -8063,3 +8063,26 @@ void RGWGetClusterStat::execute() } +int RGWGetBucketPolicyStatus::verify_permission() +{ + if (!verify_bucket_permission(this, s, rgw::IAM::s3GetBucketPolicyStatus)) { + return -EACCES; + } + + return 0; +} + +void RGWGetBucketPolicyStatus::execute() +{ + static constexpr auto public_groups = {ACL_GROUP_ALL_USERS, + ACL_GROUP_AUTHENTICATED_USERS}; + + const auto& bucket_acl = s->bucket_acl->get_acl(); + isPublic = std::any_of(public_groups.begin(), public_groups.end(), + [&bucket_acl](ACLGroupTypeEnum g) { + auto p = bucket_acl.get_group_perm(g, RGW_PERM_FULL_CONTROL); + return (p != RGW_PERM_NONE) && (p != RGW_PERM_INVALID); + } + ); + ldout(s->cct,20) << __func__ << "ACL public status=" << isPublic << dendl; +} diff --git a/src/rgw/rgw_op.h b/src/rgw/rgw_op.h index e6d90341c5f..131db7c91a8 100644 --- a/src/rgw/rgw_op.h +++ b/src/rgw/rgw_op.h @@ -2384,6 +2384,18 @@ public: dmc::client_id dmclock_client() override { return dmc::client_id::admin; } }; +class RGWGetBucketPolicyStatus : public RGWOp { +protected: + bool isPublic {false}; +public: + int verify_permission() override; + const char* name() const override { return "get_bucket_policy_status"; } + virtual RGWOpType get_type() override { return RGW_OP_GET_BUCKET_POLICY_STATUS; } + virtual uint32_t op_mask() override { return RGW_OP_TYPE_READ; } + void execute() override; + dmc::client_id dmclock_client() override { return dmc::client_id::metadata; } +}; + static inline int parse_value_and_bound( const string &input, int &output, diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index 4867a252cfd..95df630396a 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -4163,6 +4163,25 @@ void RGWGetObjLegalHold_ObjStore_S3::send_response() rgw_flush_formatter_and_reset(s, s->formatter); } +void RGWGetBucketPolicyStatus_ObjStore_S3::send_response() +{ + if (op_ret) { + set_req_state_err(s, op_ret); + } + dump_errno(s); + end_header(s, this, "application/xml"); + dump_start(s); + + s->formatter->open_object_section_in_ns("PolicyStatus", XMLNS_AWS_S3); + // https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGETPolicyStatus.html + // mentions TRUE and FALSE, but boto/aws official clients seem to want lower + // case which is returned by AWS as well; so let's be bug to bug compatible + // with the API + s->formatter->dump_string("IsPublic", isPublic ? "true" : "false"); + s->formatter->close_section(); + rgw_flush_formatter_and_reset(s, s->formatter); + +} RGWOp *RGWHandler_REST_Service_S3::op_get() { @@ -4283,6 +4302,8 @@ RGWOp *RGWHandler_REST_Bucket_S3::op_get() return RGWHandler_REST_PSNotifs_S3::create_get_op(); } else if (is_replication_op()) { return new RGWGetBucketReplication_ObjStore_S3; + } else if (is_policy_status_op()) { + return new RGWGetBucketPolicyStatus_ObjStore_S3; } return get_obj_op(true); } diff --git a/src/rgw/rgw_rest_s3.h b/src/rgw/rgw_rest_s3.h index 513be8a0ebc..b0e080b2550 100644 --- a/src/rgw/rgw_rest_s3.h +++ b/src/rgw/rgw_rest_s3.h @@ -570,6 +570,11 @@ public: void send_response() override; }; +class RGWGetBucketPolicyStatus_ObjStore_S3 : public RGWGetBucketPolicyStatus { +public: + void send_response() override; +}; + class RGW_Auth_S3 { public: static int authorize(const DoutPrefixProvider *dpp, @@ -676,9 +681,11 @@ protected: bool is_replication_op() const { return s->info.args.exists("replication"); } + bool is_policy_status_op() { + return s->info.args.exists("policyStatus"); + } RGWOp *get_obj_op(bool get_data) const; - RGWOp *op_get() override; RGWOp *op_head() override; RGWOp *op_put() override; |