]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/rgw/rgw_role.cc
import ceph quincy 17.2.6
[ceph.git] / ceph / src / rgw / rgw_role.cc
index fe028f315971ea1a7f18f2e68ba1ffacf8f8c5b6..0188f4227779d34ce0aab5385355be73cf80ce74 100644 (file)
@@ -4,6 +4,7 @@
 #include <errno.h>
 #include <ctime>
 #include <regex>
+#include <boost/algorithm/string/replace.hpp>
 
 #include "common/errno.h"
 #include "common/Formatter.h"
@@ -21,6 +22,9 @@
 
 #include "services/svc_zone.h"
 #include "services/svc_sys_obj.h"
+#include "services/svc_meta_be_sobj.h"
+#include "services/svc_meta.h"
+#include "services/svc_role_rados.h"
 
 #define dout_subsys ceph_subsys_rgw
 
@@ -33,6 +37,113 @@ const string RGWRole::role_oid_prefix = "roles.";
 const string RGWRole::role_path_oid_prefix = "role_paths.";
 const string RGWRole::role_arn_prefix = "arn:aws:iam::";
 
+void RGWRoleInfo::dump(Formatter *f) const
+{
+  encode_json("RoleId", id , f);
+  std::string role_name;
+  if (tenant.empty()) {
+    role_name = name;
+  } else {
+    role_name = tenant + '$' + name;
+  }
+  encode_json("RoleName", role_name , f);
+  encode_json("Path", path, f);
+  encode_json("Arn", arn, f);
+  encode_json("CreateDate", creation_date, f);
+  encode_json("MaxSessionDuration", max_session_duration, f);
+  encode_json("AssumeRolePolicyDocument", trust_policy, f);
+  if (!perm_policy_map.empty()) {
+    f->open_array_section("PermissionPolicies");
+    for (const auto& it : perm_policy_map) {
+      f->open_object_section("Policy");
+      encode_json("PolicyName", it.first, f);
+      encode_json("PolicyValue", it.second, f);
+      f->close_section();
+    }
+    f->close_section();
+  }
+  if (!tags.empty()) {
+    f->open_array_section("Tags");
+    for (const auto& it : tags) {
+      f->open_object_section("Tag");
+      encode_json("Key", it.first, f);
+      encode_json("Value", it.second, f);
+      f->close_section();
+    }
+    f->close_section();
+  }
+}
+
+void RGWRoleInfo::decode_json(JSONObj *obj)
+{
+  JSONDecoder::decode_json("RoleId", id, obj);
+  JSONDecoder::decode_json("RoleName", name, obj);
+  JSONDecoder::decode_json("Path", path, obj);
+  JSONDecoder::decode_json("Arn", arn, obj);
+  JSONDecoder::decode_json("CreateDate", creation_date, obj);
+  JSONDecoder::decode_json("MaxSessionDuration", max_session_duration, obj);
+  JSONDecoder::decode_json("AssumeRolePolicyDocument", trust_policy, obj);
+
+  auto tags_iter = obj->find_first("Tags");
+  if (!tags_iter.end()) {
+    JSONObj* tags_json = *tags_iter;
+    auto iter = tags_json->find_first();
+
+    for (; !iter.end(); ++iter) {
+      std::string key, val;
+      JSONDecoder::decode_json("Key", key, *iter);
+      JSONDecoder::decode_json("Value", val, *iter);
+      this->tags.emplace(key, val);
+    }
+  }
+
+  auto perm_policy_iter = obj->find_first("PermissionPolicies");
+  if (!perm_policy_iter.end()) {
+    JSONObj* perm_policies = *perm_policy_iter;
+    auto iter = perm_policies->find_first();
+
+    for (; !iter.end(); ++iter) {
+      std::string policy_name, policy_val;
+      JSONDecoder::decode_json("PolicyName", policy_name, *iter);
+      JSONDecoder::decode_json("PolicyValue", policy_val, *iter);
+      this->perm_policy_map.emplace(policy_name, policy_val);
+    }
+  }
+
+  if (auto pos = name.find('$'); pos != std::string::npos) {
+    tenant = name.substr(0, pos);
+    name = name.substr(pos+1);
+  }
+}
+
+RGWRole::RGWRole(std::string name,
+              std::string tenant,
+              std::string path,
+              std::string trust_policy,
+              std::string max_session_duration_str,
+              std::multimap<std::string,std::string> tags)
+{
+  info.name = std::move(name);
+  info.path = std::move(path);
+  info.trust_policy = std::move(trust_policy);
+  info.tenant = std::move(tenant);
+  info.tags = std::move(tags);
+  if (this->info.path.empty())
+    this->info.path = "/";
+  extract_name_tenant(this->info.name);
+  if (max_session_duration_str.empty()) {
+    info.max_session_duration = SESSION_DURATION_MIN;
+  } else {
+    info.max_session_duration = std::stoull(max_session_duration_str);
+  }
+  info.mtime = real_time();
+}
+
+RGWRole::RGWRole(std::string id)
+{
+  info.id = std::move(id);
+}
+
 int RGWRole::get(const DoutPrefixProvider *dpp, optional_yield y)
 {
   int ret = read_name(dpp, y);
@@ -58,12 +169,62 @@ int RGWRole::get_by_id(const DoutPrefixProvider *dpp, optional_yield y)
   return 0;
 }
 
+void RGWRole::dump(Formatter *f) const
+{
+  info.dump(f);
+}
+
+void RGWRole::decode_json(JSONObj *obj)
+{
+  info.decode_json(obj);
+}
+
+bool RGWRole::validate_input(const DoutPrefixProvider* dpp)
+{
+  if (info.name.length() > MAX_ROLE_NAME_LEN) {
+    ldpp_dout(dpp, 0) << "ERROR: Invalid name length " << dendl;
+    return false;
+  }
+
+  if (info.path.length() > MAX_PATH_NAME_LEN) {
+    ldpp_dout(dpp, 0) << "ERROR: Invalid path length " << dendl;
+    return false;
+  }
+
+  std::regex regex_name("[A-Za-z0-9:=,.@-]+");
+  if (! std::regex_match(info.name, regex_name)) {
+    ldpp_dout(dpp, 0) << "ERROR: Invalid chars in name " << dendl;
+    return false;
+  }
+
+  std::regex regex_path("(/[!-~]+/)|(/)");
+  if (! std::regex_match(info.path,regex_path)) {
+    ldpp_dout(dpp, 0) << "ERROR: Invalid chars in path " << dendl;
+    return false;
+  }
+
+  if (info.max_session_duration < SESSION_DURATION_MIN ||
+          info.max_session_duration > SESSION_DURATION_MAX) {
+    ldpp_dout(dpp, 0) << "ERROR: Invalid session duration, should be between 3600 and 43200 seconds " << dendl;
+    return false;
+  }
+  return true;
+}
+
+void RGWRole::extract_name_tenant(const std::string& str) {
+  if (auto pos = str.find('$');
+      pos != std::string::npos) {
+    info.tenant = str.substr(0, pos);
+    info.name = str.substr(pos+1);
+  }
+}
+
 int RGWRole::update(const DoutPrefixProvider *dpp, optional_yield y)
 {
   int ret = store_info(dpp, false, y);
   if (ret < 0) {
     ldpp_dout(dpp, 0) << "ERROR:  storing info in Role pool: "
-                  << id << ": " << cpp_strerror(-ret) << dendl;
+                  << info.id << ": " << cpp_strerror(-ret) << dendl;
     return ret;
   }
 
@@ -72,13 +233,13 @@ int RGWRole::update(const DoutPrefixProvider *dpp, optional_yield y)
 
 void RGWRole::set_perm_policy(const string& policy_name, const string& perm_policy)
 {
-  perm_policy_map[policy_name] = perm_policy;
+  info.perm_policy_map[policy_name] = perm_policy;
 }
 
 vector<string> RGWRole::get_role_policy_names()
 {
   vector<string> policy_names;
-  for (const auto& it : perm_policy_map)
+  for (const auto& it : info.perm_policy_map)
   {
     policy_names.push_back(std::move(it.first));
   }
@@ -88,8 +249,8 @@ vector<string> RGWRole::get_role_policy_names()
 
 int RGWRole::get_role_policy(const DoutPrefixProvider* dpp, const string& policy_name, string& perm_policy)
 {
-  const auto it = perm_policy_map.find(policy_name);
-  if (it == perm_policy_map.end()) {
+  const auto it = info.perm_policy_map.find(policy_name);
+  if (it == info.perm_policy_map.end()) {
     ldpp_dout(dpp, 0) << "ERROR: Policy name: " << policy_name << " not found" << dendl;
     return -ENOENT;
   } else {
@@ -100,102 +261,27 @@ int RGWRole::get_role_policy(const DoutPrefixProvider* dpp, const string& policy
 
 int RGWRole::delete_policy(const DoutPrefixProvider* dpp, const string& policy_name)
 {
-  const auto& it = perm_policy_map.find(policy_name);
-  if (it == perm_policy_map.end()) {
+  const auto& it = info.perm_policy_map.find(policy_name);
+  if (it == info.perm_policy_map.end()) {
     ldpp_dout(dpp, 0) << "ERROR: Policy name: " << policy_name << " not found" << dendl;
     return -ENOENT;
   } else {
-    perm_policy_map.erase(it);
+    info.perm_policy_map.erase(it);
   }
   return 0;
 }
 
-void RGWRole::dump(Formatter *f) const
-{
-  encode_json("RoleId", id , f);
-  encode_json("RoleName", name , f);
-  encode_json("Path", path, f);
-  encode_json("Arn", arn, f);
-  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)
-{
-  JSONDecoder::decode_json("id", id, obj);
-  JSONDecoder::decode_json("name", name, obj);
-  JSONDecoder::decode_json("path", path, obj);
-  JSONDecoder::decode_json("arn", arn, obj);
-  JSONDecoder::decode_json("create_date", creation_date, obj);
-  JSONDecoder::decode_json("max_session_duration", max_session_duration, obj);
-  JSONDecoder::decode_json("assume_role_policy_document", trust_policy, obj);
-}
-
-bool RGWRole::validate_input(const DoutPrefixProvider* dpp)
-{
-  if (name.length() > MAX_ROLE_NAME_LEN) {
-    ldpp_dout(dpp, 0) << "ERROR: Invalid name length " << dendl;
-    return false;
-  }
-
-  if (path.length() > MAX_PATH_NAME_LEN) {
-    ldpp_dout(dpp, 0) << "ERROR: Invalid path length " << dendl;
-    return false;
-  }
-
-  std::regex regex_name("[A-Za-z0-9:=,.@-]+");
-  if (! std::regex_match(name, regex_name)) {
-    ldpp_dout(dpp, 0) << "ERROR: Invalid chars in name " << dendl;
-    return false;
-  }
-
-  std::regex regex_path("(/[!-~]+/)|(/)");
-  if (! std::regex_match(path,regex_path)) {
-    ldpp_dout(dpp, 0) << "ERROR: Invalid chars in path " << dendl;
-    return false;
-  }
-
-  if (max_session_duration < SESSION_DURATION_MIN ||
-          max_session_duration > SESSION_DURATION_MAX) {
-    ldpp_dout(dpp, 0) << "ERROR: Invalid session duration, should be between 3600 and 43200 seconds " << dendl;
-    return false;
-  }
-  return true;
-}
-
-void RGWRole::extract_name_tenant(const std::string& str)
-{
-  size_t pos = str.find('$');
-  if (pos != std::string::npos) {
-    tenant = str.substr(0, pos);
-    name = str.substr(pos + 1);
-  }
-}
-
 void RGWRole::update_trust_policy(string& trust_policy)
 {
-  this->trust_policy = trust_policy;
+  this->info.trust_policy = trust_policy;
 }
 
 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);
+    this->info.tags.emplace(it.first, it.second);
   }
-  if (this->tags.size() > 50) {
+  if (this->info.tags.size() > 50) {
     ldpp_dout(dpp, 0) << "No. of tags is greater than 50" << dendl;
     return -EINVAL;
   }
@@ -204,16 +290,16 @@ int RGWRole::set_tags(const DoutPrefixProvider* dpp, const multimap<string,strin
 
 boost::optional<multimap<string,string>> RGWRole::get_tags()
 {
-  if(this->tags.empty()) {
+  if(this->info.tags.empty()) {
     return boost::none;
   }
-  return this->tags;
+  return this->info.tags;
 }
 
 void RGWRole::erase_tags(const vector<string>& tagKeys)
 {
   for (auto& it : tagKeys) {
-    this->tags.erase(it);
+    this->info.tags.erase(it);
   }
 }
 
@@ -232,4 +318,110 @@ const string& RGWRole::get_path_oid_prefix()
   return role_path_oid_prefix;
 }
 
+RGWRoleMetadataHandler::RGWRoleMetadataHandler(Store* store,
+                                              RGWSI_Role_RADOS *role_svc)
+{
+  this->store = store;
+  base_init(role_svc->ctx(), role_svc->get_be_handler());
+}
+
+RGWMetadataObject *RGWRoleMetadataHandler::get_meta_obj(JSONObj *jo,
+                                                       const obj_version& objv,
+                                                       const ceph::real_time& mtime)
+{
+  RGWRoleInfo info;
+
+  try {
+    info.decode_json(jo);
+  } catch (JSONDecoder:: err& e) {
+    return nullptr;
+  }
+
+  return new RGWRoleMetadataObject(info, objv, mtime, store);
+}
+
+int RGWRoleMetadataHandler::do_get(RGWSI_MetaBackend_Handler::Op *op,
+                                   std::string& entry,
+                                   RGWMetadataObject **obj,
+                                   optional_yield y,
+                                   const DoutPrefixProvider *dpp)
+{
+  std::unique_ptr<rgw::sal::RGWRole> role = store->get_role(entry);
+  int ret = role->read_info(dpp, y);
+  if (ret < 0) {
+    return ret;
+  }
+
+  RGWObjVersionTracker objv_tracker = role->get_objv_tracker();
+  real_time mtime = role->get_mtime();
+
+  RGWRoleInfo info = role->get_info();
+  RGWRoleMetadataObject *rdo = new RGWRoleMetadataObject(info, objv_tracker.read_version,
+                                                         mtime, store);
+  *obj = rdo;
+
+  return 0;
+}
+
+int RGWRoleMetadataHandler::do_remove(RGWSI_MetaBackend_Handler::Op *op,
+                                      std::string& entry,
+                                      RGWObjVersionTracker& objv_tracker,
+                                      optional_yield y,
+                                      const DoutPrefixProvider *dpp)
+{
+  std::unique_ptr<rgw::sal::RGWRole> role = store->get_role(entry);
+  int ret = role->read_info(dpp, y);
+  if (ret < 0) {
+    return ret == -ENOENT? 0 : ret;
+  }
+
+  return role->delete_obj(dpp, y);
+}
+
+class RGWMetadataHandlerPut_Role : public RGWMetadataHandlerPut_SObj
+{
+  RGWRoleMetadataHandler *rhandler;
+  RGWRoleMetadataObject *mdo;
+public:
+  RGWMetadataHandlerPut_Role(RGWRoleMetadataHandler *handler,
+                             RGWSI_MetaBackend_Handler::Op *op,
+                             std::string& entry,
+                             RGWMetadataObject *obj,
+                             RGWObjVersionTracker& objv_tracker,
+                             optional_yield y,
+                             RGWMDLogSyncType type,
+                             bool from_remote_zone) :
+    RGWMetadataHandlerPut_SObj(handler, op, entry, obj, objv_tracker, y, type, from_remote_zone),
+    rhandler(handler) {
+    mdo = static_cast<RGWRoleMetadataObject*>(obj);
+  }
+
+  int put_checked(const DoutPrefixProvider *dpp) override {
+    auto& info = mdo->get_role_info();
+    auto mtime = mdo->get_mtime();
+    auto* store = mdo->get_store();
+    info.mtime = mtime;
+    std::unique_ptr<rgw::sal::RGWRole> role = store->get_role(info);
+    int ret = role->create(dpp, true, info.id, y);
+    if (ret == -EEXIST) {
+      ret = role->update(dpp, y);
+    }
+
+    return ret < 0 ? ret : STATUS_APPLIED;
+  }
+};
+
+int RGWRoleMetadataHandler::do_put(RGWSI_MetaBackend_Handler::Op *op,
+                                   std::string& entry,
+                                   RGWMetadataObject *obj,
+                                   RGWObjVersionTracker& objv_tracker,
+                                   optional_yield y,
+                                   const DoutPrefixProvider *dpp,
+                                   RGWMDLogSyncType type,
+                                   bool from_remote_zone)
+{
+  RGWMetadataHandlerPut_Role put_op(this, op , entry, obj, objv_tracker, y, type, from_remote_zone);
+  return do_put_operate(&put_op, dpp);
+}
+
 } } // namespace rgw::sal