From b7d0b740c0ae731c1de7d505c405f72bb0f47249 Mon Sep 17 00:00:00 2001 From: "Adam C. Emerson" Date: Wed, 8 Mar 2017 16:31:18 -0500 Subject: [PATCH] rgw: RESTful bucket policy ops Signed-off-by: Adam C. Emerson --- src/rgw/rgw_common.h | 3 ++ src/rgw/rgw_op.cc | 107 +++++++++++++++++++++++++++++++++++++++ src/rgw/rgw_op.h | 60 ++++++++++++++++++++++ src/rgw/rgw_rest_role.cc | 2 + src/rgw/rgw_rest_role.h | 2 + src/rgw/rgw_rest_s3.cc | 9 +++- src/rgw/rgw_rest_s3.h | 3 ++ 7 files changed, 185 insertions(+), 1 deletion(-) diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h index 099f6df79cd..a403fc688db 100644 --- a/src/rgw/rgw_common.h +++ b/src/rgw/rgw_common.h @@ -459,6 +459,9 @@ enum RGWOpType { RGW_OP_GET_ROLE_POLICY, RGW_OP_LIST_ROLE_POLICIES, RGW_OP_DELETE_ROLE_POLICY, + RGW_OP_PUT_BUCKET_POLICY, + RGW_OP_GET_BUCKET_POLICY, + RGW_OP_DELETE_BUCKET_POLICY, /* rgw specific */ RGW_OP_ADMIN_SET_METADATA, diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 49c910ec3e2..6ddd6748a1b 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -6362,3 +6362,110 @@ int RGWHandler::error_handler(int err_no, string *error_content) { // This is the do-nothing error handler return err_no; } + + +void RGWPutBucketPolicy::send_response() +{ + if (op_ret) { + set_req_state_err(s, op_ret); + } + dump_errno(s); + end_header(s); +} + +int RGWPutBucketPolicy::verify_permission() +{ + if (!verify_bucket_permission(s, rgw::IAM::s3PutBucketPolicy)) { + return -EACCES; + } + + return 0; +} + +int RGWPutBucketPolicy::get_params() +{ + const auto max_size = s->cct->_conf->rgw_max_put_param_size; + // At some point when I have more time I want to make a version of + // rgw_rest_read_all_input that doesn't use malloc. + op_ret = rgw_rest_read_all_input(s, &data, &len, max_size, false); + // And throws exceptions. + return op_ret; +} + +void RGWPutBucketPolicy::execute() +{ + op_ret = get_params(); + if (op_ret < 0) { + return; + } + + try { + Policy p(s->cct, s->bucket_tenant, + bufferlist::static_from_mem(data, len)); + auto attrs = s->bucket_attrs; + attrs[RGW_ATTR_IAM_POLICY].append(p.text); + op_ret = rgw_bucket_set_attrs(store, s->bucket_info, attrs, + &s->bucket_info.objv_tracker); + if (op_ret == -ECANCELED) { + op_ret = 0; /* lost a race, but it's ok because policies are immutable */ + } + } catch (rgw::IAM::PolicyParseException& e) { + op_ret = -EINVAL; + } +} + +void RGWGetBucketPolicy::send_response() +{ + if (op_ret) { + set_req_state_err(s, op_ret); + } + dump_errno(s); + end_header(s); + dump_start(s); + rgw_flush_formatter(s, s->formatter); + dump_body(s, policy); +} + +int RGWGetBucketPolicy::verify_permission() +{ + if (!verify_bucket_permission(s, rgw::IAM::s3GetBucketPolicy)) { + return -EACCES; + } + + return 0; +} + +void RGWGetBucketPolicy::execute() +{ + auto attrs = s->bucket_attrs; + policy = attrs[RGW_ATTR_IAM_POLICY]; +} + +void RGWDeleteBucketPolicy::send_response() +{ + if (op_ret) { + set_req_state_err(s, op_ret); + } + dump_errno(s); + end_header(s); +} + +int RGWDeleteBucketPolicy::verify_permission() +{ + if (!verify_bucket_permission(s, rgw::IAM::s3DeleteBucketPolicy)) { + return -EACCES; + } + + return 0; +} + +void RGWDeleteBucketPolicy::execute() +{ + auto attrs = s->bucket_attrs; + attrs.erase(RGW_ATTR_IAM_POLICY); + op_ret = rgw_bucket_set_attrs(store, s->bucket_info, attrs, + &s->bucket_info.objv_tracker); + if (op_ret == -ECANCELED) { + op_ret = 0; /* lost a race, but it's ok because policies are immutable */ + } +} diff --git a/src/rgw/rgw_op.h b/src/rgw/rgw_op.h index e0d3aacb5e3..64e29c09925 100644 --- a/src/rgw/rgw_op.h +++ b/src/rgw/rgw_op.h @@ -1951,6 +1951,66 @@ public: virtual uint32_t op_mask() { return RGW_OP_TYPE_READ; } }; +class RGWPutBucketPolicy : public RGWOp { + int len; + char *data = nullptr; +public: + RGWPutBucketPolicy() = default; + ~RGWPutBucketPolicy() { + if (data) { + free(static_cast(data)); + } + } + void send_response() override; + int verify_permission() override; + uint32_t op_mask() override { + return RGW_OP_TYPE_WRITE; + } + void execute() override; + int get_params(); + const std::string name() override { + return "put_bucket_policy"; + } + RGWOpType get_type() override { + return RGW_OP_PUT_BUCKET_POLICY; + } +}; + +class RGWGetBucketPolicy : public RGWOp { + buffer::list policy; +public: + RGWGetBucketPolicy() = default; + void send_response() override; + int verify_permission() override; + uint32_t op_mask() override { + return RGW_OP_TYPE_READ; + } + void execute() override; + const std::string name() override { + return "get_bucket_policy"; + } + RGWOpType get_type() override { + return RGW_OP_GET_BUCKET_POLICY; + } +}; + +class RGWDeleteBucketPolicy : public RGWOp { +public: + RGWDeleteBucketPolicy() = default; + void send_response() override; + int verify_permission() override; + uint32_t op_mask() override { + return RGW_OP_TYPE_WRITE; + } + void execute() override; + int get_params(); + const std::string name() override { + return "delete_bucket_policy"; + } + RGWOpType get_type() override { + return RGW_OP_DELETE_BUCKET_POLICY; + } +}; #endif /* CEPH_RGW_OP_H */ diff --git a/src/rgw/rgw_rest_role.cc b/src/rgw/rgw_rest_role.cc index 386504398fe..ef8462ce30b 100644 --- a/src/rgw/rgw_rest_role.cc +++ b/src/rgw/rgw_rest_role.cc @@ -1,3 +1,5 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab #include #include "common/errno.h" diff --git a/src/rgw/rgw_rest_role.h b/src/rgw/rgw_rest_role.h index de3ec97a637..7a99dbe45c6 100644 --- a/src/rgw/rgw_rest_role.h +++ b/src/rgw/rgw_rest_role.h @@ -1,3 +1,5 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab #ifndef CEPH_RGW_REST_ROLE_H #define CEPH_RGW_REST_ROLE_H diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index a45521b597a..96285e258ff 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -2787,6 +2787,8 @@ RGWOp *RGWHandler_REST_Bucket_S3::op_get() return new RGWListBucketMultiparts_ObjStore_S3; } else if(is_lc_op()) { return new RGWGetLC_ObjStore_S3; + } else if(is_policy_op()) { + return new RGWGetBucketPolicy; } return get_obj_op(true); } @@ -2821,6 +2823,8 @@ RGWOp *RGWHandler_REST_Bucket_S3::op_put() return new RGWSetRequestPayment_ObjStore_S3; } else if(is_lc_op()) { return new RGWPutLC_ObjStore_S3; + } else if(is_policy_op()) { + return new RGWPutBucketPolicy; } return new RGWCreateBucket_ObjStore_S3; } @@ -2831,6 +2835,8 @@ RGWOp *RGWHandler_REST_Bucket_S3::op_delete() return new RGWDeleteCORS_ObjStore_S3; } else if(is_lc_op()) { return new RGWDeleteLC_ObjStore_S3; + } else if(is_policy_op()) { + return new RGWDeleteBucketPolicy; } if (s->info.args.sub_resource_exists("website")) { @@ -3650,7 +3656,8 @@ int RGW_Auth_S3::authorize_v4(RGWRados *store, struct req_state *s, bool force_b case RGW_OP_DELETE_MULTI_OBJ: case RGW_OP_ADMIN_SET_METADATA: case RGW_OP_SET_BUCKET_WEBSITE: - break; + case RGW_OP_PUT_BUCKET_POLICY: + break; default: dout(10) << "ERROR: AWS4 completion for this operation NOT IMPLEMENTED" << dendl; return -ERR_NOT_IMPLEMENTED; diff --git a/src/rgw/rgw_rest_s3.h b/src/rgw/rgw_rest_s3.h index 072717a6822..8dcf242b283 100644 --- a/src/rgw/rgw_rest_s3.h +++ b/src/rgw/rgw_rest_s3.h @@ -511,6 +511,9 @@ protected: bool is_request_payment_op() { return s->info.args.exists("requestPayment"); } + bool is_policy_op() { + return s->info.args.exists("policy"); + } RGWOp *get_obj_op(bool get_data); RGWOp *op_get() override; -- 2.39.5