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: v17.1.0~969^2~8 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=bd066abd4145e1793c7c426c13e7d7049f86cb0a;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 --- diff --git a/src/rgw/rgw_auth_s3.cc b/src/rgw/rgw_auth_s3.cc index d6eaf7d127af8..e46bf32681b8b 100644 --- a/src/rgw/rgw_auth_s3.cc +++ b/src/rgw/rgw_auth_s3.cc @@ -451,6 +451,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 5ad1516f369a1..ff28a27fb6d33 100644 --- a/src/rgw/rgw_auth_s3.h +++ b/src/rgw/rgw_auth_s3.h @@ -454,6 +454,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 41d49791fcb92..c6a63110e62a8 100644 --- a/src/rgw/rgw_iam_policy.cc +++ b/src/rgw/rgw_iam_policy.cc @@ -153,6 +153,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}, @@ -1345,6 +1348,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 b91718789f74c..3689657e4681c 100644 --- a/src/rgw/rgw_iam_policy.h +++ b/src/rgw/rgw_iam_policy.h @@ -128,7 +128,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 a463b51e02a51..6fe5a564da609 100644 --- a/src/rgw/rgw_op_type.h +++ b/src/rgw/rgw_op_type.h @@ -61,6 +61,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 bbc2e412f5a50..7b01133fce4a1 100644 --- a/src/rgw/rgw_rest_iam.cc +++ b/src/rgw/rgw_rest_iam.cc @@ -79,6 +79,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 6d89b9873b017..0fa0f8f011554 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" @@ -58,6 +59,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) { @@ -124,6 +171,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; } @@ -138,7 +195,8 @@ void RGWCreateRole::execute(optional_yield y) user_tenant, role_path, trust_policy, - max_session_duration); + 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; @@ -146,7 +204,6 @@ void RGWCreateRole::execute(optional_yield y) return; } op_ret = role->create(s, true, y); - if (op_ret == -EEXIST) { op_ret = -ERR_ROLE_EXISTS; } @@ -503,3 +560,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 30bf0446bb8a2..a8beb2b54052c 100644 --- a/src/rgw/rgw_rest_role.h +++ b/src/rgw/rgw_rest_role.h @@ -17,11 +17,13 @@ protected: std::string perm_policy; std::string path_prefix; std::string max_session_duration; + std::multimap tags; + std::vector tagKeys; std::unique_ptr _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 +131,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 b7ee647e727d6..d9fcd8dc1330c 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -5408,33 +5408,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 804fa892d831d..fe028f315971e 100644 --- a/src/rgw/rgw_role.cc +++ b/src/rgw/rgw_role.cc @@ -119,6 +119,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) @@ -178,6 +190,33 @@ void RGWRole::update_trust_policy(string& trust_policy) this->trust_policy = trust_policy; } +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 0563db8a27ff4..1d85dc1f06840 100644 --- a/src/rgw/rgw_role.h +++ b/src/rgw/rgw_role.h @@ -37,6 +37,7 @@ protected: std::map perm_policy_map; std::string tenant; uint64_t max_session_duration; + std::multimap tags; public: virtual int store_info(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y) = 0; @@ -52,11 +53,13 @@ public: std::string tenant, std::string path="", std::string trust_policy="", - std::string max_session_duration_str="") + std::string max_session_duration_str="", + std::multimap tags={}) : 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); @@ -86,7 +89,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); @@ -123,6 +126,9 @@ public: std::vector get_role_policy_names(); int get_role_policy(const DoutPrefixProvider* dpp, const std::string& policy_name, std::string& perm_policy); int delete_policy(const DoutPrefixProvider* dpp, const std::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_sal.h b/src/rgw/rgw_sal.h index b1b9922f8bd10..68120239214bf 100644 --- a/src/rgw/rgw_sal.h +++ b/src/rgw/rgw_sal.h @@ -246,7 +246,8 @@ class Store { std::string tenant, std::string path="", std::string trust_policy="", - std::string max_session_duration_str="") = 0; + std::string max_session_duration_str="", + std::multimap tags={}) = 0; virtual std::unique_ptr get_role(std::string id) = 0; virtual int get_roles(const DoutPrefixProvider *dpp, optional_yield y, diff --git a/src/rgw/rgw_sal_dbstore.cc b/src/rgw/rgw_sal_dbstore.cc index 898b10dd6505c..a28610f949f65 100644 --- a/src/rgw/rgw_sal_dbstore.cc +++ b/src/rgw/rgw_sal_dbstore.cc @@ -424,7 +424,8 @@ namespace rgw::sal { std::string tenant, std::string path, std::string trust_policy, - std::string max_session_duration_str) + std::string max_session_duration_str, + std::multimap tags) { RGWRole* p = nullptr; return std::unique_ptr(p); diff --git a/src/rgw/rgw_sal_dbstore.h b/src/rgw/rgw_sal_dbstore.h index 50129d9f7ed60..5d417b5defac6 100644 --- a/src/rgw/rgw_sal_dbstore.h +++ b/src/rgw/rgw_sal_dbstore.h @@ -336,11 +336,12 @@ namespace rgw { namespace sal { virtual std::string get_host_id() { return ""; } virtual std::unique_ptr get_lua_script_manager() override; - virtual std::unique_ptr get_role(string name, - string tenant, - string path="", - string trust_policy="", - string max_session_duration_str="") override; + virtual std::unique_ptr get_role(std::string name, + std::string tenant, + std::string path="", + std::string trust_policy="", + std::string max_session_duration_str="", + std::multimap tags={}) override; virtual std::unique_ptr get_role(std::string id) override; virtual int get_roles(const DoutPrefixProvider *dpp, optional_yield y, diff --git a/src/rgw/rgw_sal_rados.cc b/src/rgw/rgw_sal_rados.cc index d75069c9727ec..ae11e36a6d6ee 100644 --- a/src/rgw/rgw_sal_rados.cc +++ b/src/rgw/rgw_sal_rados.cc @@ -1318,9 +1318,10 @@ std::unique_ptr RadosStore::get_role(std::string name, std::string tenant, std::string path, std::string trust_policy, - std::string max_session_duration_str) + std::string max_session_duration_str, + std::multimap tags) { - return std::make_unique(this, name, tenant, path, trust_policy, max_session_duration_str); + return std::make_unique(this, name, tenant, path, trust_policy, max_session_duration_str, tags); } std::unique_ptr RadosStore::get_role(std::string id) @@ -2868,6 +2869,14 @@ int RadosRole::store_info(const DoutPrefixProvider *dpp, bool exclusive, optiona bufferlist bl; encode(*this, bl); + 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, store->get_zone()->get_params().roles_pool, oid, bl, exclusive, nullptr, real_time(), y, &attrs); + } + return rgw_put_system_obj(dpp, obj_ctx, store->get_zone()->get_params().roles_pool, oid, bl, exclusive, nullptr, real_time(), y); } @@ -2952,7 +2961,8 @@ int RadosRole::read_info(const DoutPrefixProvider *dpp, optional_yield y) std::string oid = get_info_oid_prefix() + id; bufferlist bl; - int ret = rgw_get_system_obj(obj_ctx, store->get_zone()->get_params().roles_pool, oid, bl, nullptr, nullptr, null_yield, dpp); + map attrs; + int ret = rgw_get_system_obj(obj_ctx, store->get_zone()->get_params().roles_pool, oid, bl, nullptr, nullptr, null_yield, dpp, &attrs, nullptr, boost::none, true); if (ret < 0) { ldpp_dout(dpp, 0) << "ERROR: failed reading role info from Role pool: " << id << ": " << cpp_strerror(-ret) << dendl; return ret; @@ -2967,6 +2977,19 @@ int RadosRole::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; } diff --git a/src/rgw/rgw_sal_rados.h b/src/rgw/rgw_sal_rados.h index d7472886d7612..14b486b1df27c 100644 --- a/src/rgw/rgw_sal_rados.h +++ b/src/rgw/rgw_sal_rados.h @@ -431,7 +431,8 @@ class RadosStore : public Store { std::string tenant, std::string path="", std::string trust_policy="", - std::string max_session_duration_str="") override; + std::string max_session_duration_str="", + std::multimap tags={}) override; virtual std::unique_ptr get_role(std::string id) override; virtual int get_roles(const DoutPrefixProvider *dpp, optional_yield y, @@ -778,7 +779,8 @@ public: std::string tenant, std::string path, std::string trust_policy, - std::string max_session_duration) : RGWRole(name, tenant, path, trust_policy, max_session_duration), store(_store) {} + std::string max_session_duration, + std::multimap tags) : RGWRole(name, tenant, path, trust_policy, max_session_duration, tags), store(_store) {} RadosRole(RadosStore* _store, std::string id) : RGWRole(id), store(_store) {} ~RadosRole() = default; diff --git a/src/rgw/rgw_tools.cc b/src/rgw/rgw_tools.cc index 7073e5c5aa551..105fcc0579c1a 100644 --- a/src/rgw/rgw_tools.cc +++ b/src/rgw/rgw_tools.cc @@ -183,7 +183,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; @@ -201,6 +201,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 a1607ca663f8c..df17f3914df06 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 std::string& key, bufferlist& bl, RGWObjVersionTracker *objv_tracker, real_time *pmtime, optional_yield y, const DoutPrefixProvider *dpp, std::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 std::string& oid, RGWObjVersionTracker *objv_tracker, optional_yield y);