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
"notification",
"partNumber",
"policy",
+ "policyStatus",
"requestPayment",
"response-cache-control",
"response-content-disposition",
(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) ||
RGW_OP_GET_BUCKET_REPLICATION,
RGW_OP_PUT_BUCKET_REPLICATION,
RGW_OP_DELETE_BUCKET_REPLICATION,
+
+ RGW_OP_GET_BUCKET_POLICY_STATUS
};
class RGWAccessControlPolicy;
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;
case s3GetBucketLogging:
case s3GetBucketNotification:
case s3GetBucketPolicy:
+ case s3GetBucketPolicyStatus:
case s3GetBucketRequestPayment:
case s3GetBucketTagging:
case s3GetBucketVersioning:
}
+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;
+}
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,
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()
{
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);
}
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,
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;