summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAbhishek Lekshmanan <abhishek@suse.com>2020-01-29 11:26:21 +0100
committerAbhishek Lekshmanan <abhishek@suse.com>2020-02-03 17:53:30 +0100
commite0b4562c61e4523a73e6170c2b502fbf648c7e73 (patch)
treeccf28a49f41006a2fe0e0e5156fdaed80e1eb7cd /src
parentrgw: acl: drop unused function & make get_group_perm const (diff)
downloadceph-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.cc1
-rw-r--r--src/rgw/rgw_common.cc3
-rw-r--r--src/rgw/rgw_common.h2
-rw-r--r--src/rgw/rgw_iam_policy.h4
-rw-r--r--src/rgw/rgw_op.cc23
-rw-r--r--src/rgw/rgw_op.h12
-rw-r--r--src/rgw/rgw_rest_s3.cc21
-rw-r--r--src/rgw/rgw_rest_s3.h9
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;