From: Pritha Srivastava Date: Tue, 1 Jun 2021 16:15:37 +0000 (+0530) Subject: rgw/sts: added code to tag, untag and list role tags. X-Git-Tag: v16.2.11~244^2~8 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=75a33c0c72d3e3efc3e6d29b712fbd819218cb3b;p=ceph.git rgw/sts: added code to tag, untag and list role tags. The role tags can be used as iam:ResourceTags in AssumeRoleWithWebIdentity or as aws:PrincipalTags in a session using temporary credentials. Signed-off-by: Pritha Srivastava (cherry picked from commit bd066abd4145e1793c7c426c13e7d7049f86cb0a) --- diff --git a/src/rgw/rgw_auth_s3.cc b/src/rgw/rgw_auth_s3.cc index 6fa6e651e50..bdf64e16bbd 100644 --- a/src/rgw/rgw_auth_s3.cc +++ b/src/rgw/rgw_auth_s3.cc @@ -448,6 +448,40 @@ static inline int parse_v4_auth_header(const req_info& info, /* in return 0; } +bool is_non_s3_op(RGWOpType op_type) +{ + if (op_type == RGW_STS_GET_SESSION_TOKEN || + op_type == RGW_STS_ASSUME_ROLE || + op_type == RGW_STS_ASSUME_ROLE_WEB_IDENTITY || + op_type == RGW_OP_CREATE_ROLE || + op_type == RGW_OP_DELETE_ROLE || + op_type == RGW_OP_GET_ROLE || + op_type == RGW_OP_MODIFY_ROLE || + op_type == RGW_OP_LIST_ROLES || + op_type == RGW_OP_PUT_ROLE_POLICY || + op_type == RGW_OP_GET_ROLE_POLICY || + op_type == RGW_OP_LIST_ROLE_POLICIES || + op_type == RGW_OP_DELETE_ROLE_POLICY || + op_type == RGW_OP_PUT_USER_POLICY || + op_type == RGW_OP_GET_USER_POLICY || + op_type == RGW_OP_LIST_USER_POLICIES || + op_type == RGW_OP_DELETE_USER_POLICY || + op_type == RGW_OP_CREATE_OIDC_PROVIDER || + op_type == RGW_OP_DELETE_OIDC_PROVIDER || + op_type == RGW_OP_GET_OIDC_PROVIDER || + op_type == RGW_OP_LIST_OIDC_PROVIDERS || + op_type == RGW_OP_PUBSUB_TOPIC_CREATE || + op_type == RGW_OP_PUBSUB_TOPICS_LIST || + op_type == RGW_OP_PUBSUB_TOPIC_GET || + op_type == RGW_OP_PUBSUB_TOPIC_DELETE || + op_type == RGW_OP_TAG_ROLE || + op_type == RGW_OP_LIST_ROLE_TAGS || + op_type == RGW_OP_UNTAG_ROLE) { + return true; + } + return false; +} + int parse_v4_credentials(const req_info& info, /* in */ std::string_view& access_key_id, /* out */ std::string_view& credential_scope, /* out */ diff --git a/src/rgw/rgw_auth_s3.h b/src/rgw/rgw_auth_s3.h index 0a1390a1eec..cebc05933e3 100644 --- a/src/rgw/rgw_auth_s3.h +++ b/src/rgw/rgw_auth_s3.h @@ -456,6 +456,8 @@ static constexpr char AWS4_UNSIGNED_PAYLOAD_HASH[] = "UNSIGNED-PAYLOAD"; static constexpr char AWS4_STREAMING_PAYLOAD_HASH[] = \ "STREAMING-AWS4-HMAC-SHA256-PAYLOAD"; +bool is_non_s3_op(RGWOpType op_type); + int parse_v4_credentials(const req_info& info, /* in */ std::string_view& access_key_id, /* out */ std::string_view& credential_scope, /* out */ diff --git a/src/rgw/rgw_iam_policy.cc b/src/rgw/rgw_iam_policy.cc index 6d0a59443d2..15642cc801c 100644 --- a/src/rgw/rgw_iam_policy.cc +++ b/src/rgw/rgw_iam_policy.cc @@ -149,6 +149,9 @@ static const actpair actpairs[] = { "iam:DeleteOIDCProvider", iamDeleteOIDCProvider}, { "iam:GetOIDCProvider", iamGetOIDCProvider}, { "iam:ListOIDCProviders", iamListOIDCProviders}, + { "iam:TagRole", iamTagRole}, + { "iam:ListRoleTags", iamListRoleTags}, + { "iam:UntagRole", iamUntagRole}, { "sts:AssumeRole", stsAssumeRole}, { "sts:AssumeRoleWithWebIdentity", stsAssumeRoleWithWebIdentity}, { "sts:GetSessionToken", stsGetSessionToken}, @@ -1335,6 +1338,15 @@ const char* action_bit_string(uint64_t action) { case iamListOIDCProviders: return "iam:ListOIDCProviders"; + case iamTagRole: + return "iam:TagRole"; + + case iamListRoleTags: + return "iam:ListRoleTags"; + + case iamUntagRole: + return "iam:UntagRole"; + case stsAssumeRole: return "sts:AssumeRole"; diff --git a/src/rgw/rgw_iam_policy.h b/src/rgw/rgw_iam_policy.h index 179f0ffb3cb..a74ddc83d8f 100644 --- a/src/rgw/rgw_iam_policy.h +++ b/src/rgw/rgw_iam_policy.h @@ -126,7 +126,10 @@ static constexpr std::uint64_t iamCreateOIDCProvider = s3All + 14; static constexpr std::uint64_t iamDeleteOIDCProvider = s3All + 15; static constexpr std::uint64_t iamGetOIDCProvider = s3All + 16; static constexpr std::uint64_t iamListOIDCProviders = s3All + 17; -static constexpr std::uint64_t iamAll = s3All + 18; +static constexpr std::uint64_t iamTagRole = s3All + 18; +static constexpr std::uint64_t iamListRoleTags = s3All + 19; +static constexpr std::uint64_t iamUntagRole = s3All + 20; +static constexpr std::uint64_t iamAll = s3All + 21; static constexpr std::uint64_t stsAssumeRole = iamAll + 1; static constexpr std::uint64_t stsAssumeRoleWithWebIdentity = iamAll + 2; diff --git a/src/rgw/rgw_op_type.h b/src/rgw/rgw_op_type.h index ff474f00728..979ee943c2e 100644 --- a/src/rgw/rgw_op_type.h +++ b/src/rgw/rgw_op_type.h @@ -58,6 +58,9 @@ enum RGWOpType { RGW_OP_GET_ROLE_POLICY, RGW_OP_LIST_ROLE_POLICIES, RGW_OP_DELETE_ROLE_POLICY, + RGW_OP_TAG_ROLE, + RGW_OP_LIST_ROLE_TAGS, + RGW_OP_UNTAG_ROLE, RGW_OP_PUT_BUCKET_POLICY, RGW_OP_GET_BUCKET_POLICY, RGW_OP_DELETE_BUCKET_POLICY, diff --git a/src/rgw/rgw_rest_iam.cc b/src/rgw/rgw_rest_iam.cc index fc050ae8bcc..ffd450f79db 100644 --- a/src/rgw/rgw_rest_iam.cc +++ b/src/rgw/rgw_rest_iam.cc @@ -77,6 +77,12 @@ RGWOp *RGWHandler_REST_IAM::op_post() return new RGWGetOIDCProvider; if (action.compare("DeleteOpenIDConnectProvider") == 0) return new RGWDeleteOIDCProvider; + if (action.compare("TagRole") == 0) + return new RGWTagRole; + if (action.compare("ListRoleTags") == 0) + return new RGWListRoleTags; + if (action.compare("UntagRole") == 0) + return new RGWUntagRole; } return nullptr; diff --git a/src/rgw/rgw_rest_role.cc b/src/rgw/rgw_rest_role.cc index beb72493a16..66c38aedfa5 100644 --- a/src/rgw/rgw_rest_role.cc +++ b/src/rgw/rgw_rest_role.cc @@ -2,6 +2,7 @@ // vim: ts=8 sw=2 smarttab ft=cpp #include +#include #include "common/errno.h" #include "common/Formatter.h" @@ -55,6 +56,52 @@ int RGWRestRole::verify_permission(optional_yield y) return 0; } +int RGWRestRole::parse_tags() +{ + vector keys, vals; + auto val_map = s->info.args.get_params(); + const regex pattern_key("Tags.member.([0-9]+).Key"); + const regex pattern_value("Tags.member.([0-9]+).Value"); + for (auto& v : val_map) { + string key_index="", value_index=""; + for(sregex_iterator it = sregex_iterator( + v.first.begin(), v.first.end(), pattern_key); + it != sregex_iterator(); it++) { + smatch match; + match = *it; + key_index = match.str(1); + ldout(s->cct, 20) << "Key index: " << match.str(1) << dendl; + if (!key_index.empty()) { + int index = stoi(key_index); + auto pos = keys.begin() + (index-1); + keys.insert(pos, v.second); + } + } + for(sregex_iterator it = sregex_iterator( + v.first.begin(), v.first.end(), pattern_value); + it != sregex_iterator(); it++) { + smatch match; + match = *it; + value_index = match.str(1); + ldout(s->cct, 20) << "Value index: " << match.str(1) << dendl; + if (!value_index.empty()) { + int index = stoi(value_index); + auto pos = vals.begin() + (index-1); + vals.insert(pos, v.second); + } + } + } + if (keys.size() != vals.size()) { + ldout(s->cct, 0) << "No. of keys doesn't match with no. of values in tags" << dendl; + return -EINVAL; + } + for (size_t i = 0; i < keys.size(); i++) { + tags.emplace(keys[i], vals[i]); + ldout(s->cct, 0) << "Tag Key: " << keys[i] << " Tag Value is: " << vals[i] << dendl; + } + return 0; +} + void RGWRestRole::send_response() { if (op_ret) { @@ -121,6 +168,16 @@ int RGWCreateRole::get_params() return -ERR_MALFORMED_DOC; } + int ret = parse_tags(); + if (ret < 0) { + return ret; + } + + if (tags.size() > 50) { + ldout(s->cct, 0) << "No. tags is greater than 50" << dendl; + return -EINVAL; + } + return 0; } @@ -132,7 +189,7 @@ void RGWCreateRole::execute(optional_yield y) } std::string user_tenant = s->user->get_tenant(); RGWRole role(s->cct, store->getRados()->pctl, role_name, role_path, trust_policy, - user_tenant, max_session_duration); + user_tenant, max_session_duration, tags); if (!user_tenant.empty() && role.get_tenant() != user_tenant) { ldpp_dout(this, 20) << "ERROR: the tenant provided in the role name does not match with the tenant of the user creating the role" << dendl; @@ -496,3 +553,118 @@ void RGWDeleteRolePolicy::execute(optional_yield y) s->formatter->close_section(); s->formatter->close_section(); } + +int RGWTagRole::get_params() +{ + role_name = s->info.args.get("RoleName"); + + if (role_name.empty()) { + ldout(s->cct, 0) << "ERROR: Role name is empty" << dendl; + return -EINVAL; + } + int ret = parse_tags(); + if (ret < 0) { + return ret; + } + + return 0; +} + +void RGWTagRole::execute(optional_yield y) +{ + op_ret = get_params(); + if (op_ret < 0) { + return; + } + + op_ret = _role.set_tags(this, tags); + if (op_ret == 0) { + op_ret = _role.update(this, y); + } + + if (op_ret == 0) { + s->formatter->open_object_section("TagRoleResponse"); + s->formatter->open_object_section("ResponseMetadata"); + s->formatter->dump_string("RequestId", s->trans_id); + s->formatter->close_section(); + s->formatter->close_section(); + } +} + +int RGWListRoleTags::get_params() +{ + role_name = s->info.args.get("RoleName"); + + if (role_name.empty()) { + ldout(s->cct, 0) << "ERROR: Role name is empty" << dendl; + return -EINVAL; + } + + return 0; +} + +void RGWListRoleTags::execute(optional_yield y) +{ + op_ret = get_params(); + if (op_ret < 0) { + return; + } + + boost::optional> tag_map = _role.get_tags(); + s->formatter->open_object_section("ListRoleTagsResponse"); + s->formatter->open_object_section("ListRoleTagsResult"); + if (tag_map) { + s->formatter->open_array_section("Tags"); + for (const auto& it : tag_map.get()) { + s->formatter->open_object_section("Key"); + encode_json("Key", it.first, s->formatter); + s->formatter->close_section(); + s->formatter->open_object_section("Value"); + encode_json("Value", it.second, s->formatter); + s->formatter->close_section(); + } + s->formatter->close_section(); + } + s->formatter->close_section(); + s->formatter->open_object_section("ResponseMetadata"); + s->formatter->dump_string("RequestId", s->trans_id); + s->formatter->close_section(); + s->formatter->close_section(); +} + +int RGWUntagRole::get_params() +{ + role_name = s->info.args.get("RoleName"); + + if (role_name.empty()) { + ldout(s->cct, 0) << "ERROR: Role name is empty" << dendl; + return -EINVAL; + } + + auto val_map = s->info.args.get_params(); + for (auto& it : val_map) { + if (it.first.find("TagKeys.member.") != string::npos) { + tagKeys.emplace_back(it.second); + } + } + return 0; +} + +void RGWUntagRole::execute(optional_yield y) +{ + op_ret = get_params(); + if (op_ret < 0) { + return; + } + + _role.erase_tags(tagKeys); + op_ret = _role.update(this, y); + + if (op_ret == 0) { + s->formatter->open_object_section("UntagRoleResponse"); + s->formatter->open_object_section("ResponseMetadata"); + s->formatter->dump_string("RequestId", s->trans_id); + s->formatter->close_section(); + s->formatter->close_section(); + } +} \ No newline at end of file diff --git a/src/rgw/rgw_rest_role.h b/src/rgw/rgw_rest_role.h index 09f556b6cf6..5467502a7bf 100644 --- a/src/rgw/rgw_rest_role.h +++ b/src/rgw/rgw_rest_role.h @@ -17,11 +17,14 @@ protected: string perm_policy; string path_prefix; string max_session_duration; + std::multimap tags; + std::vector tagKeys; RGWRole _role; public: int verify_permission(optional_yield y) override; void send_response() override; virtual uint64_t get_op() = 0; + int parse_tags(); }; class RGWRoleRead : public RGWRestRole { @@ -129,3 +132,33 @@ public: RGWOpType get_type() override { return RGW_OP_DELETE_ROLE_POLICY; } uint64_t get_op() override { return rgw::IAM::iamDeleteRolePolicy; } }; + +class RGWTagRole : public RGWRoleWrite { +public: + RGWTagRole() = default; + void execute(optional_yield y) override; + int get_params(); + const char* name() const override { return "tag_role"; } + RGWOpType get_type() override { return RGW_OP_TAG_ROLE; } + uint64_t get_op() override { return rgw::IAM::iamTagRole; } +}; + +class RGWListRoleTags : public RGWRoleRead { +public: + RGWListRoleTags() = default; + void execute(optional_yield y) override; + int get_params(); + const char* name() const override { return "list_role_tags"; } + RGWOpType get_type() override { return RGW_OP_LIST_ROLE_TAGS; } + uint64_t get_op() override { return rgw::IAM::iamListRoleTags; } +}; + +class RGWUntagRole : public RGWRoleWrite { +public: + RGWUntagRole() = default; + void execute(optional_yield y) override; + int get_params(); + const char* name() const override { return "untag_role"; } + RGWOpType get_type() override { return RGW_OP_UNTAG_ROLE; } + uint64_t get_op() override { return rgw::IAM::iamUntagRole; } +}; diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index 948ffb81b4d..541e3c5df59 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -5247,33 +5247,7 @@ AWSGeneralAbstractor::get_auth_data_v4(const req_state* const s, throw -EPERM; } - bool is_non_s3_op = false; - if (s->op_type == RGW_STS_GET_SESSION_TOKEN || - s->op_type == RGW_STS_ASSUME_ROLE || - s->op_type == RGW_STS_ASSUME_ROLE_WEB_IDENTITY || - s->op_type == RGW_OP_CREATE_ROLE || - s->op_type == RGW_OP_DELETE_ROLE || - s->op_type == RGW_OP_GET_ROLE || - s->op_type == RGW_OP_MODIFY_ROLE || - s->op_type == RGW_OP_LIST_ROLES || - s->op_type == RGW_OP_PUT_ROLE_POLICY || - s->op_type == RGW_OP_GET_ROLE_POLICY || - s->op_type == RGW_OP_LIST_ROLE_POLICIES || - s->op_type == RGW_OP_DELETE_ROLE_POLICY || - s->op_type == RGW_OP_PUT_USER_POLICY || - s->op_type == RGW_OP_GET_USER_POLICY || - s->op_type == RGW_OP_LIST_USER_POLICIES || - s->op_type == RGW_OP_DELETE_USER_POLICY || - s->op_type == RGW_OP_CREATE_OIDC_PROVIDER || - s->op_type == RGW_OP_DELETE_OIDC_PROVIDER || - s->op_type == RGW_OP_GET_OIDC_PROVIDER || - s->op_type == RGW_OP_LIST_OIDC_PROVIDERS || - s->op_type == RGW_OP_PUBSUB_TOPIC_CREATE || - s->op_type == RGW_OP_PUBSUB_TOPICS_LIST || - s->op_type == RGW_OP_PUBSUB_TOPIC_GET || - s->op_type == RGW_OP_PUBSUB_TOPIC_DELETE) { - is_non_s3_op = true; - } + bool is_non_s3_op = rgw::auth::s3::is_non_s3_op(s->op_type); const char* exp_payload_hash = nullptr; string payload_hash; diff --git a/src/rgw/rgw_role.cc b/src/rgw/rgw_role.cc index f69134174fe..089cd190346 100644 --- a/src/rgw/rgw_role.cc +++ b/src/rgw/rgw_role.cc @@ -41,6 +41,15 @@ int RGWRole::store_info(const DoutPrefixProvider *dpp, bool exclusive, optional_ auto svc = ctl->svc; auto obj_ctx = ctl->svc->sysobj->init_obj_ctx(); + + if (!this->tags.empty()) { + bufferlist bl_tags; + encode(this->tags, bl_tags); + map attrs; + attrs.emplace("tagging", bl_tags); + return rgw_put_system_obj(dpp, obj_ctx, svc->zone->get_zone_params().roles_pool, oid, bl, exclusive, nullptr, real_time(), y, &attrs); + } + return rgw_put_system_obj(dpp, obj_ctx, svc->zone->get_zone_params().roles_pool, oid, bl, exclusive, NULL, real_time(), y, NULL); } @@ -299,6 +308,18 @@ void RGWRole::dump(Formatter *f) const encode_json("CreateDate", creation_date, f); encode_json("MaxSessionDuration", max_session_duration, f); encode_json("AssumeRolePolicyDocument", trust_policy, f); + if (!tags.empty()) { + f->open_array_section("Tags"); + for (const auto& it : tags) { + f->open_object_section("Key"); + encode_json("Key", it.first, f); + f->close_section(); + f->open_object_section("Value"); + encode_json("Value", it.second, f); + f->close_section(); + } + f->close_section(); + } } void RGWRole::decode_json(JSONObj *obj) @@ -347,7 +368,9 @@ int RGWRole::read_info(const DoutPrefixProvider *dpp, optional_yield y) bufferlist bl; auto obj_ctx = svc->sysobj->init_obj_ctx(); - int ret = rgw_get_system_obj(obj_ctx, pool, oid, bl, NULL, NULL, y, dpp); + map attrs; + + int ret = rgw_get_system_obj(obj_ctx, pool, oid, bl, NULL, NULL, y, dpp, &attrs, nullptr, boost::none, true); if (ret < 0) { ldpp_dout(dpp, 0) << "ERROR: failed reading role info from pool: " << pool.name << ": " << id << ": " << cpp_strerror(-ret) << dendl; @@ -364,6 +387,19 @@ int RGWRole::read_info(const DoutPrefixProvider *dpp, optional_yield y) return -EIO; } + auto it = attrs.find("tagging"); + if (it != attrs.end()) { + bufferlist bl_tags = it->second; + try { + using ceph::decode; + auto iter = bl_tags.cbegin(); + decode(tags, iter); + } catch (buffer::error& err) { + ldpp_dout(dpp, 0) << "ERROR: failed to decode attrs" << id << dendl; + return -EIO; + } + } + return 0; } @@ -505,6 +541,33 @@ int RGWRole::get_roles_by_path_prefix(const DoutPrefixProvider *dpp, return 0; } +int RGWRole::set_tags(const DoutPrefixProvider* dpp, const multimap& tags_map) +{ + for (auto& it : tags_map) { + this->tags.emplace(it.first, it.second); + } + if (this->tags.size() > 50) { + ldpp_dout(dpp, 0) << "No. of tags is greater than 50" << dendl; + return -EINVAL; + } + return 0; +} + +boost::optional> RGWRole::get_tags() +{ + if(this->tags.empty()) { + return boost::none; + } + return this->tags; +} + +void RGWRole::erase_tags(const vector& tagKeys) +{ + for (auto& it : tagKeys) { + this->tags.erase(it); + } +} + const string& RGWRole::get_names_oid_prefix() { return role_name_oid_prefix; diff --git a/src/rgw/rgw_role.h b/src/rgw/rgw_role.h index 91b4846d006..44ffa1c19bc 100644 --- a/src/rgw/rgw_role.h +++ b/src/rgw/rgw_role.h @@ -38,6 +38,7 @@ class RGWRole map perm_policy_map; string tenant; uint64_t max_session_duration; + std::multimap tags; int store_info(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y); int store_name(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y); @@ -55,13 +56,15 @@ public: string path, string trust_policy, string tenant, - string max_session_duration_str="") + string max_session_duration_str="", + std::multimap tags={}) : cct(cct), ctl(ctl), name(std::move(name)), path(std::move(path)), trust_policy(std::move(trust_policy)), - tenant(std::move(tenant)) { + tenant(std::move(tenant)), + tags(std::move(tags)) { if (this->path.empty()) this->path = "/"; extract_name_tenant(this->name); @@ -114,7 +117,7 @@ public: } void decode(bufferlist::const_iterator& bl) { - DECODE_START(2, bl); + DECODE_START(3, bl); decode(id, bl); decode(name, bl); decode(path, bl); @@ -151,6 +154,9 @@ public: vector get_role_policy_names(); int get_role_policy(const string& policy_name, string& perm_policy); int delete_policy(const string& policy_name); + int set_tags(const DoutPrefixProvider* dpp, const std::multimap& tags_map); + boost::optional> get_tags(); + void erase_tags(const std::vector& tagKeys); void dump(Formatter *f) const; void decode_json(JSONObj *obj); diff --git a/src/rgw/rgw_tools.cc b/src/rgw/rgw_tools.cc index 4770da5f015..5a73d7e363b 100644 --- a/src/rgw/rgw_tools.cc +++ b/src/rgw/rgw_tools.cc @@ -170,7 +170,7 @@ int rgw_put_system_obj(const DoutPrefixProvider *dpp, int rgw_get_system_obj(RGWSysObjectCtx& obj_ctx, const rgw_pool& pool, const string& key, bufferlist& bl, RGWObjVersionTracker *objv_tracker, real_time *pmtime, optional_yield y, const DoutPrefixProvider *dpp, map *pattrs, rgw_cache_entry_info *cache_info, - boost::optional refresh_version) + boost::optional refresh_version, bool raw_attrs) { bufferlist::iterator iter; int request_len = READ_CHUNK_LEN; @@ -188,6 +188,7 @@ int rgw_get_system_obj(RGWSysObjectCtx& obj_ctx, const rgw_pool& pool, const str int ret = rop.set_attrs(pattrs) .set_last_mod(pmtime) .set_objv_tracker(objv_tracker) + .set_raw_attrs(raw_attrs) .stat(y, dpp); if (ret < 0) return ret; diff --git a/src/rgw/rgw_tools.h b/src/rgw/rgw_tools.h index 90512ad98e9..c945f1d9ab3 100644 --- a/src/rgw/rgw_tools.h +++ b/src/rgw/rgw_tools.h @@ -77,7 +77,7 @@ int rgw_put_system_obj(const DoutPrefixProvider *dpp, RGWSysObjectCtx& obj_ctx, int rgw_get_system_obj(RGWSysObjectCtx& obj_ctx, const rgw_pool& pool, const string& key, bufferlist& bl, RGWObjVersionTracker *objv_tracker, real_time *pmtime, optional_yield y, const DoutPrefixProvider *dpp, map *pattrs = NULL, rgw_cache_entry_info *cache_info = NULL, - boost::optional refresh_version = boost::none); + boost::optional refresh_version = boost::none, bool raw_attrs=false); int rgw_delete_system_obj(const DoutPrefixProvider *dpp, RGWSI_SysObj *sysobj_svc, const rgw_pool& pool, const string& oid, RGWObjVersionTracker *objv_tracker, optional_yield y);