]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw/sts: added code to tag, untag and list role tags.
authorPritha Srivastava <prsrivas@redhat.com>
Tue, 1 Jun 2021 16:15:37 +0000 (21:45 +0530)
committerPritha Srivastava <prsrivas@redhat.com>
Mon, 22 Aug 2022 08:33:31 +0000 (14:03 +0530)
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 <prsrivas@redhat.com>
(cherry picked from commit bd066abd4145e1793c7c426c13e7d7049f86cb0a)

13 files changed:
src/rgw/rgw_auth_s3.cc
src/rgw/rgw_auth_s3.h
src/rgw/rgw_iam_policy.cc
src/rgw/rgw_iam_policy.h
src/rgw/rgw_op_type.h
src/rgw/rgw_rest_iam.cc
src/rgw/rgw_rest_role.cc
src/rgw/rgw_rest_role.h
src/rgw/rgw_rest_s3.cc
src/rgw/rgw_role.cc
src/rgw/rgw_role.h
src/rgw/rgw_tools.cc
src/rgw/rgw_tools.h

index 6fa6e651e50cad95847e26e94cfeddf95ddfb5c6..bdf64e16bbdbb96eddb8de3434f20ddf7616635a 100644 (file)
@@ -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 */
index 0a1390a1eecfeed5a66970874ff6040eabce32be..cebc05933e35f7ea89ebbc8a372984631381a092 100644 (file)
@@ -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 */
index 6d0a59443d28385955ba573ea680c8b1f9d67c06..15642cc801c63beeff29675bc0d1f3e4bb47ecbb 100644 (file)
@@ -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";
 
index 179f0ffb3cbdaa973a639deb6450538dd9f2c739..a74ddc83d8f370dcb3a860c6720d1495181f2b33 100644 (file)
@@ -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;
index ff474f00728afff4e7a5f0ce23851c34e4b1fe13..979ee943c2eabb1be507bb224927355e9b3fe3ac 100644 (file)
@@ -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,
index fc050ae8bccfe7fca16c6c8554873bd884bec56e..ffd450f79db89b5ad960938ff62267cc1e2bf172 100644 (file)
@@ -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;
index beb72493a16d187a31e7d341cd4ed5c7a35c2513..66c38aedfa5357115e8bd49206c6f91eed955e0c 100644 (file)
@@ -2,6 +2,7 @@
 // vim: ts=8 sw=2 smarttab ft=cpp
 
 #include <errno.h>
+#include <regex>
 
 #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<string> 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<multimap<string,string>> 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
index 09f556b6cf6ee10083a1c0ec3e3dca63a85003e3..5467502a7bfdd42e204c924a555133111fe19172 100644 (file)
@@ -17,11 +17,14 @@ protected:
   string perm_policy;
   string path_prefix;
   string max_session_duration;
+  std::multimap<std::string,std::string> tags;
+  std::vector<std::string> 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; }
+};
index 948ffb81b4d51fe7dc7df0424cbb8eef53f81fd4..541e3c5df59a06798b33aff0353d2997994a04c1 100644 (file)
@@ -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;
index f69134174fe658846c84a2b52c0c6ea0799a4ebe..089cd190346e2aac6492d53d1a1c1f42501d1aee 100644 (file)
@@ -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<string, bufferlist> 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<string, bufferlist> 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<string,string>& 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<multimap<string,string>> RGWRole::get_tags()
+{
+  if(this->tags.empty()) {
+    return boost::none;
+  }
+  return this->tags;
+}
+
+void RGWRole::erase_tags(const vector<string>& tagKeys)
+{
+  for (auto& it : tagKeys) {
+    this->tags.erase(it);
+  }
+}
+
 const string& RGWRole::get_names_oid_prefix()
 {
   return role_name_oid_prefix;
index 91b4846d0060452478050282dcfc8eec3cef3f87..44ffa1c19bc3cdc36fb4d1a395921a50d3155425 100644 (file)
@@ -38,6 +38,7 @@ class RGWRole
   map<string, string> perm_policy_map;
   string tenant;
   uint64_t max_session_duration;
+  std::multimap<std::string,std::string> 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<std::string,std::string> 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<string> 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<std::string,std::string>& tags_map);
+  boost::optional<std::multimap<std::string,std::string>> get_tags();
+  void erase_tags(const std::vector<std::string>& tagKeys);
   void dump(Formatter *f) const;
   void decode_json(JSONObj *obj);
 
index 4770da5f015022a2c991fe5626e07a8a3e441053..5a73d7e363b44162dcbf0d8543b7c77c65d4ece1 100644 (file)
@@ -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<string, bufferlist> *pattrs,
                        rgw_cache_entry_info *cache_info,
-                      boost::optional<obj_version> refresh_version)
+                      boost::optional<obj_version> 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;
index 90512ad98e9b53cdf97aae5395642d22c2a849b9..c945f1d9ab35c9631c4a2249a014a5cc2ee5b31d 100644 (file)
@@ -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<string, bufferlist> *pattrs = NULL,
                        rgw_cache_entry_info *cache_info = NULL,
-                      boost::optional<obj_version> refresh_version = boost::none);
+                      boost::optional<obj_version> 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);