]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw/iam: role apis override init_processing/verify_permission
authorCasey Bodley <cbodley@redhat.com>
Mon, 15 Jan 2024 01:36:28 +0000 (20:36 -0500)
committerCasey Bodley <cbodley@redhat.com>
Fri, 12 Apr 2024 19:34:28 +0000 (15:34 -0400)
replace get_params() with init_processing() override which runs before
verify_permission(). use this to validate request parameters and load
the existing role if necessary. simplify verify_permission() by
forwarding to RGWRESTOp::verify_permission() which calls check_caps()

simplify inheritence hierarchy by taking cap perm and iam action as
constructor arguments

Signed-off-by: Casey Bodley <cbodley@redhat.com>
(cherry picked from commit 46053028cabc8e089401363b15d81890dc9fb8e8)

src/rgw/rgw_rest_iam.cc
src/rgw/rgw_rest_iam.h
src/rgw/rgw_rest_role.cc
src/rgw/rgw_rest_role.h

index 96af3566e353940c7f97f7776a29874738cdb6cd..490a91ed44b00c9327cd0638d2556511d87e629d 100644 (file)
@@ -165,6 +165,24 @@ bool validate_iam_user_name(const std::string& name, std::string& err)
   return true;
 }
 
+bool validate_iam_role_name(const std::string& name, std::string& err)
+{
+  if (name.empty()) {
+    err = "Missing required element RoleName";
+    return false;
+  }
+  if (name.size() > rgw::sal::RGWRole::MAX_ROLE_NAME_LEN) {
+    err = "RoleName too long";
+    return false;
+  }
+  const std::regex pattern("[\\w+=,.@-]+");
+  if (!std::regex_match(name, pattern)) {
+    err = "RoleName contains invalid characters";
+    return false;
+  }
+  return true;
+}
+
 static constexpr size_t MAX_PATH_LEN = 512;
 
 bool validate_iam_path(const std::string& path, std::string& err)
index 69143118d3dea5007034e8d54dc77d6f5197d43b..a9bb7127e0304a40fb239fbe72c9c0faf2529cd2 100644 (file)
@@ -16,6 +16,7 @@ struct RGWUserInfo;
 bool validate_iam_policy_name(const std::string& name, std::string& err);
 bool validate_iam_policy_arn(const std::string& arn, std::string& err);
 bool validate_iam_user_name(const std::string& name, std::string& err);
+bool validate_iam_role_name(const std::string& name, std::string& err);
 bool validate_iam_path(const std::string& path, std::string& err);
 
 std::string iam_user_arn(const RGWUserInfo& info);
index 620a1adc0d8fafb6b235e232e9958c8c16493d85..b44634e83b615ae4ebe2e3e9fecd0e24a84fe069 100644 (file)
@@ -28,42 +28,16 @@ using namespace std;
 
 int RGWRestRole::verify_permission(optional_yield y)
 {
-  if (s->auth.identity->is_anonymous()) {
-    return -EACCES;
-  }
-  
-  string role_name = s->info.args.get("RoleName");
-  if (int ret = check_caps(s->user->get_caps()); ret == 0) {
-    return ret;
-  }
-
-  string resource_name = _role->get_path() + role_name;
-  uint64_t op = get_op();
-  if (!verify_user_permission(this,
-                              s,
-                              rgw::ARN(resource_name,
-                                            "role",
-                                             s->user->get_tenant(), true),
-                                             op)) {
-    return -EACCES;
+  if (verify_user_permission(this, s, resource, action)) {
+    return 0;
   }
 
-  return 0;
+  return RGWRESTOp::verify_permission(y);
 }
 
-int RGWRestRole::init_processing(optional_yield y)
+int RGWRestRole::check_caps(const RGWUserCaps& caps)
 {
-  string role_name = s->info.args.get("RoleName");
-  std::unique_ptr<rgw::sal::RGWRole> role = driver->get_role(role_name,
-                                                             s->user->get_tenant());
-  if (int ret = role->get(s, y); ret < 0) {
-    if (ret == -ENOENT) {
-      return -ERR_NO_ROLE_FOUND;
-    }
-    return ret;
-  }
-  _role = std::move(role);
-  return 0;
+  return caps.check_cap("roles", perm);
 }
 
 static int parse_tags(const DoutPrefixProvider* dpp,
@@ -114,68 +88,57 @@ static int parse_tags(const DoutPrefixProvider* dpp,
   return 0;
 }
 
-void RGWRestRole::send_response()
-{
-  if (op_ret) {
-    set_req_state_err(s, op_ret);
-  }
-  dump_errno(s);
-  end_header(s, this);
-}
-
-int RGWRoleRead::check_caps(const RGWUserCaps& caps)
-{
-    return caps.check_cap("roles", RGW_CAP_READ);
-}
-
-int RGWRoleWrite::check_caps(const RGWUserCaps& caps)
+static rgw::ARN make_role_arn(const std::string& path,
+                              const std::string& name,
+                              const std::string& account)
 {
-    return caps.check_cap("roles", RGW_CAP_WRITE);
+  return {string_cat_reserve(path, name), "role", account, true};
 }
 
-int RGWCreateRole::verify_permission(optional_yield y)
+static int load_role(const DoutPrefixProvider* dpp, optional_yield y,
+                     rgw::sal::Driver* driver,
+                     const std::string& tenant,
+                     const std::string& name,
+                     std::unique_ptr<rgw::sal::RGWRole>& role,
+                     rgw::ARN& resource,
+                     std::string& message)
 {
-  if (s->auth.identity->is_anonymous()) {
-    return -EACCES;
+  role = driver->get_role(name, tenant);
+  const int r = role->get(dpp, y);
+  if (r == -ENOENT) {
+    message = "No such RoleName in the tenant";
+    return -ERR_NO_ROLE_FOUND;
   }
-
-  if (int ret = check_caps(s->user->get_caps()); ret == 0) {
-    return ret;
-  }
-
-  string role_name = s->info.args.get("RoleName");
-  string role_path = s->info.args.get("Path");
-
-  string resource_name = role_path + role_name;
-  if (!verify_user_permission(this,
-                              s,
-                              rgw::ARN(resource_name,
-                                            "role",
-                                             s->user->get_tenant(), true),
-                                             get_op())) {
-    return -EACCES;
+  if (r >= 0) {
+    resource = make_role_arn(role->get_path(),
+                             role->get_name(),
+                             role->get_tenant());
   }
-  return 0;
+  return r;
 }
 
-int RGWCreateRole::init_processing(optional_yield y)
-{
-  return 0; // avoid calling RGWRestRole::init_processing()
-}
 
-int RGWCreateRole::get_params()
+int RGWCreateRole::init_processing(optional_yield y)
 {
   role_name = s->info.args.get("RoleName");
+  if (!validate_iam_role_name(role_name, s->err.message)) {
+    return -EINVAL;
+  }
+
   role_path = s->info.args.get("Path");
+  if (role_path.empty()) {
+    role_path = "/";
+  } else if (!validate_iam_path(role_path, s->err.message)) {
+    return -EINVAL;
+  }
+
   trust_policy = s->info.args.get("AssumeRolePolicyDocument");
   max_session_duration = s->info.args.get("MaxSessionDuration");
 
-  if (role_name.empty() || trust_policy.empty()) {
-    ldpp_dout(this, 20) << "ERROR: one of role name or assume role policy document is empty"
-    << dendl;
+  if (trust_policy.empty()) {
+    s->err.message = "Missing required element AssumeRolePolicyDocument";
     return -EINVAL;
   }
-
   bufferlist bl = bufferlist::static_from_string(trust_policy);
   try {
     const rgw::IAM::Policy p(
@@ -198,15 +161,12 @@ int RGWCreateRole::get_params()
     return -ERR_LIMIT_EXCEEDED;
   }
 
+  resource = make_role_arn(role_path, role_name, s->user->get_tenant());
   return 0;
 }
 
 void RGWCreateRole::execute(optional_yield y)
 {
-  op_ret = get_params();
-  if (op_ret < 0) {
-    return;
-  }
   std::string user_tenant = s->user->get_tenant();
   std::unique_ptr<rgw::sal::RGWRole> role = driver->get_role(role_name,
                                                            user_tenant,
@@ -309,25 +269,20 @@ void RGWCreateRole::execute(optional_yield y)
   }
 }
 
-int RGWDeleteRole::get_params()
+int RGWDeleteRole::init_processing(optional_yield y)
 {
   role_name = s->info.args.get("RoleName");
-
-  if (role_name.empty()) {
-    ldpp_dout(this, 20) << "ERROR: Role name is empty"<< dendl;
+  if (!validate_iam_role_name(role_name, s->err.message)) {
     return -EINVAL;
   }
 
-  return 0;
+  return load_role(this, y, driver, s->user->get_tenant(), role_name,
+                   role, resource, s->err.message);
 }
 
 void RGWDeleteRole::execute(optional_yield y)
 {
   bool is_master = true;
-  op_ret = get_params();
-  if (op_ret < 0) {
-    return;
-  }
 
   const rgw::SiteConfig& site = *s->penv.site;
   if (!site.is_meta_master()) {
@@ -351,7 +306,7 @@ void RGWDeleteRole::execute(optional_yield y)
     }
   }
 
-  op_ret = _role->delete_obj(s, y);
+  op_ret = role->delete_obj(s, y);
 
   if (op_ret == -ENOENT) {
     //Role has been deleted since metadata from master has synced up
@@ -371,106 +326,56 @@ void RGWDeleteRole::execute(optional_yield y)
   }
 }
 
-int RGWGetRole::verify_permission(optional_yield y)
-{
-  return 0;
-}
-
-int RGWGetRole::_verify_permission(const rgw::sal::RGWRole* role)
-{
-  if (s->auth.identity->is_anonymous()) {
-    return -EACCES;
-  }
-
-  if (int ret = check_caps(s->user->get_caps()); ret == 0) {
-    return ret;
-  }
-
-  string resource_name = role->get_path() + role->get_name();
-  if (!verify_user_permission(this,
-                              s,
-                              rgw::ARN(resource_name,
-                                            "role",
-                                             s->user->get_tenant(), true),
-                                             get_op())) {
-    return -EACCES;
-  }
-  return 0;
-}
-
 int RGWGetRole::init_processing(optional_yield y)
-{
-  return 0; // avoid calling RGWRestRole::init_processing()
-}
-
-int RGWGetRole::get_params()
 {
   role_name = s->info.args.get("RoleName");
-
-  if (role_name.empty()) {
-    ldpp_dout(this, 20) << "ERROR: Role name is empty"<< dendl;
+  if (!validate_iam_role_name(role_name, s->err.message)) {
     return -EINVAL;
   }
 
-  return 0;
+  return load_role(this, y, driver, s->user->get_tenant(), role_name,
+                   role, resource, s->err.message);
 }
 
 void RGWGetRole::execute(optional_yield y)
 {
-  op_ret = get_params();
-  if (op_ret < 0) {
-    return;
-  }
-  std::unique_ptr<rgw::sal::RGWRole> role = driver->get_role(role_name,
-                                                           s->user->get_tenant());
-  op_ret = role->get(s, y);
-
-  if (op_ret == -ENOENT) {
-    op_ret = -ERR_NO_ROLE_FOUND;
-    return;
-  }
-
-  op_ret = _verify_permission(role.get());
-
-  if (op_ret == 0) {
-    s->formatter->open_object_section("GetRoleResponse");
-    s->formatter->open_object_section("ResponseMetadata");
-    s->formatter->dump_string("RequestId", s->trans_id);
-    s->formatter->close_section();
-    s->formatter->open_object_section("GetRoleResult");
-    s->formatter->open_object_section("Role");
-    role->dump(s->formatter);
-    s->formatter->close_section();
-    s->formatter->close_section();
-    s->formatter->close_section();
-  }
+  s->formatter->open_object_section("GetRoleResponse");
+  s->formatter->open_object_section("ResponseMetadata");
+  s->formatter->dump_string("RequestId", s->trans_id);
+  s->formatter->close_section();
+  s->formatter->open_object_section("GetRoleResult");
+  s->formatter->open_object_section("Role");
+  role->dump(s->formatter);
+  s->formatter->close_section();
+  s->formatter->close_section();
+  s->formatter->close_section();
 }
 
-int RGWModifyRoleTrustPolicy::get_params()
+int RGWModifyRoleTrustPolicy::init_processing(optional_yield y)
 {
   role_name = s->info.args.get("RoleName");
-  trust_policy = s->info.args.get("PolicyDocument");
+  if (!validate_iam_role_name(role_name, s->err.message)) {
+    return -EINVAL;
+  }
 
-  if (role_name.empty() || trust_policy.empty()) {
-    ldpp_dout(this, 20) << "ERROR: One of role name or trust policy is empty"<< dendl;
+  trust_policy = s->info.args.get("PolicyDocument");
+  if (trust_policy.empty()) {
+    s->err.message = "Missing required element PolicyDocument";
     return -EINVAL;
   }
+
   JSONParser p;
   if (!p.parse(trust_policy.c_str(), trust_policy.length())) {
     ldpp_dout(this, 20) << "ERROR: failed to parse assume role policy doc" << dendl;
     return -ERR_MALFORMED_DOC;
   }
 
-  return 0;
+  return load_role(this, y, driver, s->user->get_tenant(), role_name,
+                   role, resource, s->err.message);
 }
 
 void RGWModifyRoleTrustPolicy::execute(optional_yield y)
 {
-  op_ret = get_params();
-  if (op_ret < 0) {
-    return;
-  }
-
   const rgw::SiteConfig& site = *s->penv.site;
   if (!site.is_meta_master()) {
     RGWXMLDecoder::XMLParser parser;
@@ -494,8 +399,8 @@ void RGWModifyRoleTrustPolicy::execute(optional_yield y)
     }
   }
 
-  _role->update_trust_policy(trust_policy);
-  op_ret = _role->update(this, y);
+  role->update_trust_policy(trust_policy);
+  op_ret = role->update(this, y);
 
   s->formatter->open_object_section("UpdateAssumeRolePolicyResponse");
   s->formatter->open_object_section("ResponseMetadata");
@@ -504,32 +409,7 @@ void RGWModifyRoleTrustPolicy::execute(optional_yield y)
   s->formatter->close_section();
 }
 
-int RGWListRoles::verify_permission(optional_yield y)
-{
-  if (s->auth.identity->is_anonymous()) {
-    return -EACCES;
-  }
-
-  if (int ret = check_caps(s->user->get_caps()); ret == 0) {
-    return ret;
-  }
-
-  if (!verify_user_permission(this, 
-                              s,
-                              rgw::ARN(),
-                              get_op())) {
-    return -EACCES;
-  }
-
-  return 0;
-}
-
 int RGWListRoles::init_processing(optional_yield y)
-{
-  return 0; // avoid calling RGWRestRole::init_processing()
-}
-
-int RGWListRoles::get_params()
 {
   path_prefix = s->info.args.get("PathPrefix");
 
@@ -538,10 +418,6 @@ int RGWListRoles::get_params()
 
 void RGWListRoles::execute(optional_yield y)
 {
-  op_ret = get_params();
-  if (op_ret < 0) {
-    return;
-  }
   vector<std::unique_ptr<rgw::sal::RGWRole>> result;
   op_ret = driver->get_roles(s, y, path_prefix, s->user->get_tenant(), result);
 
@@ -563,14 +439,22 @@ void RGWListRoles::execute(optional_yield y)
   }
 }
 
-int RGWPutRolePolicy::get_params()
+int RGWPutRolePolicy::init_processing(optional_yield y)
 {
   role_name = s->info.args.get("RoleName");
+  if (!validate_iam_role_name(role_name, s->err.message)) {
+    return -EINVAL;
+  }
+
   policy_name = s->info.args.get("PolicyName");
   perm_policy = s->info.args.get("PolicyDocument");
 
-  if (role_name.empty() || policy_name.empty() || perm_policy.empty()) {
-    ldpp_dout(this, 20) << "ERROR: One of role name, policy name or perm policy is empty"<< dendl;
+  if (policy_name.empty()) {
+    s->err.message = "Missing required element PolicyName";
+    return -EINVAL;
+  }
+  if (perm_policy.empty()) {
+    s->err.message = "Missing required element PolicyDocument";
     return -EINVAL;
   }
   bufferlist bl = bufferlist::static_from_string(perm_policy);
@@ -584,16 +468,13 @@ int RGWPutRolePolicy::get_params()
     s->err.message = e.what();
     return -ERR_MALFORMED_DOC;
   }
-  return 0;
+
+  return load_role(this, y, driver, s->user->get_tenant(), role_name,
+                   role, resource, s->err.message);
 }
 
 void RGWPutRolePolicy::execute(optional_yield y)
 {
-  op_ret = get_params();
-  if (op_ret < 0) {
-    return;
-  }
-
   const rgw::SiteConfig& site = *s->penv.site;
   if (!site.is_meta_master()) {
     RGWXMLDecoder::XMLParser parser;
@@ -618,8 +499,8 @@ void RGWPutRolePolicy::execute(optional_yield y)
     }
   }
 
-  _role->set_perm_policy(policy_name, perm_policy);
-  op_ret = _role->update(this, y);
+  role->set_perm_policy(policy_name, perm_policy);
+  op_ret = role->update(this, y);
 
   if (op_ret == 0) {
     s->formatter->open_object_section("PutRolePolicyResponse");
@@ -630,27 +511,27 @@ void RGWPutRolePolicy::execute(optional_yield y)
   }
 }
 
-int RGWGetRolePolicy::get_params()
+int RGWGetRolePolicy::init_processing(optional_yield y)
 {
   role_name = s->info.args.get("RoleName");
-  policy_name = s->info.args.get("PolicyName");
+  if (!validate_iam_role_name(role_name, s->err.message)) {
+    return -EINVAL;
+  }
 
-  if (role_name.empty() || policy_name.empty()) {
-    ldpp_dout(this, 20) << "ERROR: One of role name or policy name is empty"<< dendl;
+  policy_name = s->info.args.get("PolicyName");
+  if (policy_name.empty()) {
+    s->err.message = "Missing required element PolicyName";
     return -EINVAL;
   }
-  return 0;
+
+  return load_role(this, y, driver, s->user->get_tenant(), role_name,
+                   role, resource, s->err.message);
 }
 
 void RGWGetRolePolicy::execute(optional_yield y)
 {
-  op_ret = get_params();
-  if (op_ret < 0) {
-    return;
-  }
-
   string perm_policy;
-  op_ret = _role->get_role_policy(this, policy_name, perm_policy);
+  op_ret = role->get_role_policy(this, policy_name, perm_policy);
   if (op_ret == -ENOENT) {
     op_ret = -ERR_NO_SUCH_ENTITY;
   }
@@ -669,25 +550,20 @@ void RGWGetRolePolicy::execute(optional_yield y)
   }
 }
 
-int RGWListRolePolicies::get_params()
+int RGWListRolePolicies::init_processing(optional_yield y)
 {
   role_name = s->info.args.get("RoleName");
-
-  if (role_name.empty()) {
-    ldpp_dout(this, 20) << "ERROR: Role name is empty"<< dendl;
+  if (!validate_iam_role_name(role_name, s->err.message)) {
     return -EINVAL;
   }
-  return 0;
+
+  return load_role(this, y, driver, s->user->get_tenant(), role_name,
+                   role, resource, s->err.message);
 }
 
 void RGWListRolePolicies::execute(optional_yield y)
 {
-  op_ret = get_params();
-  if (op_ret < 0) {
-    return;
-  }
-
-  std::vector<string> policy_names = _role->get_role_policy_names();
+  std::vector<string> policy_names = role->get_role_policy_names();
   s->formatter->open_object_section("ListRolePoliciesResponse");
   s->formatter->open_object_section("ResponseMetadata");
   s->formatter->dump_string("RequestId", s->trans_id);
@@ -702,25 +578,25 @@ void RGWListRolePolicies::execute(optional_yield y)
   s->formatter->close_section();
 }
 
-int RGWDeleteRolePolicy::get_params()
+int RGWDeleteRolePolicy::init_processing(optional_yield y)
 {
   role_name = s->info.args.get("RoleName");
-  policy_name = s->info.args.get("PolicyName");
+  if (!validate_iam_role_name(role_name, s->err.message)) {
+    return -EINVAL;
+  }
 
-  if (role_name.empty() || policy_name.empty()) {
-    ldpp_dout(this, 20) << "ERROR: One of role name or policy name is empty"<< dendl;
+  policy_name = s->info.args.get("PolicyName");
+  if (policy_name.empty()) {
+    s->err.message = "Missing required element PolicyName";
     return -EINVAL;
   }
-  return 0;
+
+  return load_role(this, y, driver, s->user->get_tenant(), role_name,
+                   role, resource, s->err.message);
 }
 
 void RGWDeleteRolePolicy::execute(optional_yield y)
 {
-  op_ret = get_params();
-  if (op_ret < 0) {
-    return;
-  }
-
   const rgw::SiteConfig& site = *s->penv.site;
   if (!site.is_meta_master()) {
     RGWXMLDecoder::XMLParser parser;
@@ -744,14 +620,14 @@ void RGWDeleteRolePolicy::execute(optional_yield y)
     }
   }
 
-  op_ret = _role->delete_policy(this, policy_name);
+  op_ret = role->delete_policy(this, policy_name);
   if (op_ret == -ENOENT) {
     op_ret = -ERR_NO_ROLE_FOUND;
     return;
   }
 
   if (op_ret == 0) {
-    op_ret = _role->update(this, y);
+    op_ret = role->update(this, y);
   }
 
   s->formatter->open_object_section("DeleteRolePoliciesResponse");
@@ -761,29 +637,24 @@ void RGWDeleteRolePolicy::execute(optional_yield y)
   s->formatter->close_section();
 }
 
-int RGWTagRole::get_params()
+int RGWTagRole::init_processing(optional_yield y)
 {
   role_name = s->info.args.get("RoleName");
-
-  if (role_name.empty()) {
-    ldout(s->cct, 0) << "ERROR: Role name is empty" << dendl;
+  if (!validate_iam_role_name(role_name, s->err.message)) {
     return -EINVAL;
   }
-  int ret = parse_tags(this, s->info.args.get_params(), tags, s->err.message);
-  if (ret < 0) {
-    return ret;
+
+  int r = parse_tags(this, s->info.args.get_params(), tags, s->err.message);
+  if (r < 0) {
+    return r;
   }
 
-  return 0;
+  return load_role(this, y, driver, s->user->get_tenant(), role_name,
+                   role, resource, s->err.message);
 }
 
 void RGWTagRole::execute(optional_yield y)
 {
-  op_ret = get_params();
-  if (op_ret < 0) {
-    return;
-  }
-
   const rgw::SiteConfig& site = *s->penv.site;
   if (!site.is_meta_master()) {
     RGWXMLDecoder::XMLParser parser;
@@ -812,9 +683,9 @@ void RGWTagRole::execute(optional_yield y)
     }
   }
 
-  op_ret = _role->set_tags(this, tags);
+  op_ret = role->set_tags(this, tags);
   if (op_ret == 0) {
-    op_ret = _role->update(this, y);
+    op_ret = role->update(this, y);
   }
 
   if (op_ret == 0) {
@@ -826,26 +697,20 @@ void RGWTagRole::execute(optional_yield y)
   }
 }
 
-int RGWListRoleTags::get_params()
+int RGWListRoleTags::init_processing(optional_yield y)
 {
   role_name = s->info.args.get("RoleName");
-
-  if (role_name.empty()) {
-    ldout(s->cct, 0) << "ERROR: Role name is empty" << dendl;
+  if (!validate_iam_role_name(role_name, s->err.message)) {
     return -EINVAL;
   }
 
-  return 0;
+  return load_role(this, y, driver, s->user->get_tenant(), role_name,
+                   role, resource, s->err.message);
 }
 
 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();
+  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) {
@@ -867,12 +732,10 @@ void RGWListRoleTags::execute(optional_yield y)
   s->formatter->close_section();
 }
 
-int RGWUntagRole::get_params()
+int RGWUntagRole::init_processing(optional_yield y)
 {
   role_name = s->info.args.get("RoleName");
-
-  if (role_name.empty()) {
-    ldout(s->cct, 0) << "ERROR: Role name is empty" << dendl;
+  if (!validate_iam_role_name(role_name, s->err.message)) {
     return -EINVAL;
   }
 
@@ -885,16 +748,13 @@ int RGWUntagRole::get_params()
           return p.second;
         });
   }
-  return 0;
+
+  return load_role(this, y, driver, s->user->get_tenant(), role_name,
+                   role, resource, s->err.message);
 }
 
 void RGWUntagRole::execute(optional_yield y)
 {
-  op_ret = get_params();
-  if (op_ret < 0) {
-    return;
-  }
-
   const rgw::SiteConfig& site = *s->penv.site;
   if (!site.is_meta_master()) {
     RGWXMLDecoder::XMLParser parser;
@@ -921,8 +781,8 @@ void RGWUntagRole::execute(optional_yield y)
     }
   }
 
-  _role->erase_tags(untag);
-  op_ret = _role->update(this, y);
+  role->erase_tags(untag);
+  op_ret = role->update(this, y);
 
   if (op_ret == 0) {
     s->formatter->open_object_section("UntagRoleResponse");
@@ -933,26 +793,21 @@ void RGWUntagRole::execute(optional_yield y)
   }
 }
 
-int RGWUpdateRole::get_params()
+int RGWUpdateRole::init_processing(optional_yield y)
 {
   role_name = s->info.args.get("RoleName");
-  max_session_duration = s->info.args.get("MaxSessionDuration");
-
-  if (role_name.empty()) {
-    ldpp_dout(this, 20) << "ERROR: Role name is empty"<< dendl;
+  if (!validate_iam_role_name(role_name, s->err.message)) {
     return -EINVAL;
   }
 
-  return 0;
+  max_session_duration = s->info.args.get("MaxSessionDuration");
+
+  return load_role(this, y, driver, s->user->get_tenant(), role_name,
+                   role, resource, s->err.message);
 }
 
 void RGWUpdateRole::execute(optional_yield y)
 {
-  op_ret = get_params();
-  if (op_ret < 0) {
-    return;
-  }
-
   const rgw::SiteConfig& site = *s->penv.site;
   if (!site.is_meta_master()) {
     RGWXMLDecoder::XMLParser parser;
@@ -976,13 +831,13 @@ void RGWUpdateRole::execute(optional_yield y)
     }
   }
 
-  _role->update_max_session_duration(max_session_duration);
-  if (!_role->validate_max_session_duration(this)) {
+  role->update_max_session_duration(max_session_duration);
+  if (!role->validate_max_session_duration(this)) {
     op_ret = -EINVAL;
     return;
   }
 
-  op_ret = _role->update(this, y);
+  op_ret = role->update(this, y);
 
   s->formatter->open_object_section("UpdateRoleResponse");
   s->formatter->open_object_section("UpdateRoleResult");
index b2eb6132d0c9a92fb7e4c18d13941bb69b68d14e..d26fbe125753ad498cdfd1f174a5027f012dd72c 100644 (file)
@@ -5,31 +5,23 @@
 
 #include "common/async/yield_context.h"
 
+#include "rgw_arn.h"
 #include "rgw_role.h"
 #include "rgw_rest.h"
 
 class RGWRestRole : public RGWRESTOp {
-protected:
-  std::unique_ptr<rgw::sal::RGWRole> _role;
-  int verify_permission(optional_yield y) override;
-  int init_processing(optional_yield y) override;
-  void send_response() override;
-  virtual uint64_t get_op() = 0;
-};
-
-class RGWRoleRead : public RGWRestRole {
-public:
-  RGWRoleRead() = default;
+  const uint64_t action;
+  const uint32_t perm;
+ protected:
+  rgw::ARN resource; // must be initialized before verify_permission()
   int check_caps(const RGWUserCaps& caps) override;
-};
 
-class RGWRoleWrite : public RGWRestRole {
-public:
-  RGWRoleWrite() = default;
-  int check_caps(const RGWUserCaps& caps) override;
+  RGWRestRole(uint64_t action, uint32_t perm) : action(action), perm(perm) {}
+ public:
+  int verify_permission(optional_yield y) override;
 };
 
-class RGWCreateRole : public RGWRoleWrite {
+class RGWCreateRole : public RGWRestRole {
   bufferlist bl_post_body;
   std::string role_name;
   std::string role_path;
@@ -37,166 +29,173 @@ class RGWCreateRole : public RGWRoleWrite {
   std::string max_session_duration;
   std::multimap<std::string, std::string> tags;
 public:
-  RGWCreateRole(const bufferlist& bl_post_body) : bl_post_body(bl_post_body) {};
-  int verify_permission(optional_yield y) override;
+  explicit RGWCreateRole(const bufferlist& bl_post_body)
+    : RGWRestRole(rgw::IAM::iamCreateRole, RGW_CAP_WRITE),
+      bl_post_body(bl_post_body) {}
   int init_processing(optional_yield y) override;
   void execute(optional_yield y) override;
-  int get_params();
   const char* name() const override { return "create_role"; }
   RGWOpType get_type() override { return RGW_OP_CREATE_ROLE; }
-  uint64_t get_op() override { return rgw::IAM::iamCreateRole; }
 };
 
-class RGWDeleteRole : public RGWRoleWrite {
+class RGWDeleteRole : public RGWRestRole {
   bufferlist bl_post_body;
   std::string role_name;
+  std::unique_ptr<rgw::sal::RGWRole> role;
 public:
-  RGWDeleteRole(const bufferlist& bl_post_body) : bl_post_body(bl_post_body) {};
+  explicit RGWDeleteRole(const bufferlist& bl_post_body)
+    : RGWRestRole(rgw::IAM::iamDeleteRole, RGW_CAP_WRITE),
+      bl_post_body(bl_post_body) {}
+  int init_processing(optional_yield y) override;
   void execute(optional_yield y) override;
-  int get_params();
   const char* name() const override { return "delete_role"; }
   RGWOpType get_type() override { return RGW_OP_DELETE_ROLE; }
-  uint64_t get_op() override { return rgw::IAM::iamDeleteRole; }
 };
 
-class RGWGetRole : public RGWRoleRead {
+class RGWGetRole : public RGWRestRole {
   std::string role_name;
-  int _verify_permission(const rgw::sal::RGWRole* role);
+  std::unique_ptr<rgw::sal::RGWRole> role;
 public:
-  RGWGetRole() = default;
-  int verify_permission(optional_yield y) override;
-  int init_processing(optional_yield y) override; 
+  RGWGetRole() : RGWRestRole(rgw::IAM::iamGetRole, RGW_CAP_READ) {}
+  int init_processing(optional_yield y) override;
   void execute(optional_yield y) override;
-  int get_params();
   const char* name() const override { return "get_role"; }
   RGWOpType get_type() override { return RGW_OP_GET_ROLE; }
-  uint64_t get_op() override { return rgw::IAM::iamGetRole; }
 };
 
-class RGWModifyRoleTrustPolicy : public RGWRoleWrite {
+class RGWModifyRoleTrustPolicy : public RGWRestRole {
   bufferlist bl_post_body;
   std::string role_name;
   std::string trust_policy;
+  std::unique_ptr<rgw::sal::RGWRole> role;
 public:
-  RGWModifyRoleTrustPolicy(const bufferlist& bl_post_body) : bl_post_body(bl_post_body) {};
+  explicit RGWModifyRoleTrustPolicy(const bufferlist& bl_post_body)
+    : RGWRestRole(rgw::IAM::iamModifyRoleTrustPolicy, RGW_CAP_WRITE),
+      bl_post_body(bl_post_body) {}
+  int init_processing(optional_yield y) override;
   void execute(optional_yield y) override;
-  int get_params();
   const char* name() const override { return "modify_role_trust_policy"; }
   RGWOpType get_type() override { return RGW_OP_MODIFY_ROLE_TRUST_POLICY; }
-  uint64_t get_op() override { return rgw::IAM::iamModifyRoleTrustPolicy; }
 };
 
-class RGWListRoles : public RGWRoleRead {
+class RGWListRoles : public RGWRestRole {
   std::string path_prefix;
 public:
-  RGWListRoles() = default;
-  int verify_permission(optional_yield y) override;
+  RGWListRoles() : RGWRestRole(rgw::IAM::iamListRoles, RGW_CAP_READ) {}
   int init_processing(optional_yield y) override;
   void execute(optional_yield y) override;
-  int get_params();
   const char* name() const override { return "list_roles"; }
   RGWOpType get_type() override { return RGW_OP_LIST_ROLES; }
-  uint64_t get_op() override { return rgw::IAM::iamListRoles; }
 };
 
-class RGWPutRolePolicy : public RGWRoleWrite {
+class RGWPutRolePolicy : public RGWRestRole {
   bufferlist bl_post_body;
   std::string role_name;
   std::string policy_name;
   std::string perm_policy;
+  std::unique_ptr<rgw::sal::RGWRole> role;
 public:
-  RGWPutRolePolicy(const bufferlist& bl_post_body) : bl_post_body(bl_post_body) {};
+  explicit RGWPutRolePolicy(const bufferlist& bl_post_body)
+    : RGWRestRole(rgw::IAM::iamPutRolePolicy, RGW_CAP_WRITE),
+      bl_post_body(bl_post_body) {}
+  int init_processing(optional_yield y) override;
   void execute(optional_yield y) override;
-  int get_params();
   const char* name() const override { return "put_role_policy"; }
   RGWOpType get_type() override { return RGW_OP_PUT_ROLE_POLICY; }
-  uint64_t get_op() override { return rgw::IAM::iamPutRolePolicy; }
 };
 
-class RGWGetRolePolicy : public RGWRoleRead {
+class RGWGetRolePolicy : public RGWRestRole {
   std::string role_name;
   std::string policy_name;
   std::string perm_policy;
+  std::unique_ptr<rgw::sal::RGWRole> role;
 public:
-  RGWGetRolePolicy() = default;
+  RGWGetRolePolicy() : RGWRestRole(rgw::IAM::iamGetRolePolicy, RGW_CAP_READ) {}
+  int init_processing(optional_yield y) override;
   void execute(optional_yield y) override;
-  int get_params();
   const char* name() const override { return "get_role_policy"; }
   RGWOpType get_type() override { return RGW_OP_GET_ROLE_POLICY; }
-  uint64_t get_op() override { return rgw::IAM::iamGetRolePolicy; }
 };
 
-class RGWListRolePolicies : public RGWRoleRead {
+class RGWListRolePolicies : public RGWRestRole {
   std::string role_name;
+  std::unique_ptr<rgw::sal::RGWRole> role;
 public:
-  RGWListRolePolicies() = default;
+  RGWListRolePolicies() : RGWRestRole(rgw::IAM::iamListRolePolicies, RGW_CAP_READ) {}
+  int init_processing(optional_yield y) override;
   void execute(optional_yield y) override;
-  int get_params();
   const char* name() const override { return "list_role_policies"; }
   RGWOpType get_type() override { return RGW_OP_LIST_ROLE_POLICIES; }
-  uint64_t get_op() override { return rgw::IAM::iamListRolePolicies; }
 };
 
-class RGWDeleteRolePolicy : public RGWRoleWrite {
+class RGWDeleteRolePolicy : public RGWRestRole {
   bufferlist bl_post_body;
   std::string role_name;
   std::string policy_name;
+  std::unique_ptr<rgw::sal::RGWRole> role;
 public:
-  RGWDeleteRolePolicy(const bufferlist& bl_post_body) : bl_post_body(bl_post_body) {};
+  explicit RGWDeleteRolePolicy(const bufferlist& bl_post_body)
+    : RGWRestRole(rgw::IAM::iamDeleteRolePolicy, RGW_CAP_WRITE),
+      bl_post_body(bl_post_body) {}
+  int init_processing(optional_yield y) override;
   void execute(optional_yield y) override;
-  int get_params();
   const char* name() const override { return "delete_role_policy"; }
   RGWOpType get_type() override { return RGW_OP_DELETE_ROLE_POLICY; }
-  uint64_t get_op() override { return rgw::IAM::iamDeleteRolePolicy; }
 };
 
-class RGWTagRole : public RGWRoleWrite {
+class RGWTagRole : public RGWRestRole {
   bufferlist bl_post_body;
   std::string role_name;
   std::multimap<std::string, std::string> tags;
+  std::unique_ptr<rgw::sal::RGWRole> role;
 public:
-  RGWTagRole(const bufferlist& bl_post_body) : bl_post_body(bl_post_body) {};
+  explicit RGWTagRole(const bufferlist& bl_post_body)
+    : RGWRestRole(rgw::IAM::iamTagRole, RGW_CAP_WRITE),
+      bl_post_body(bl_post_body) {}
+  int init_processing(optional_yield y) override;
   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 {
+class RGWListRoleTags : public RGWRestRole {
   std::string role_name;
   std::multimap<std::string, std::string> tags;
+  std::unique_ptr<rgw::sal::RGWRole> role;
 public:
-  RGWListRoleTags() = default;
+  RGWListRoleTags() : RGWRestRole(rgw::IAM::iamListRoleTags, RGW_CAP_READ) {}
+  int init_processing(optional_yield y) override;
   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 {
+class RGWUntagRole : public RGWRestRole {
   bufferlist bl_post_body;
   std::string role_name;
   std::vector<std::string> untag;
+  std::unique_ptr<rgw::sal::RGWRole> role;
 public:
-  RGWUntagRole(const bufferlist& bl_post_body) : bl_post_body(bl_post_body) {};
+  explicit RGWUntagRole(const bufferlist& bl_post_body)
+    : RGWRestRole(rgw::IAM::iamUntagRole, RGW_CAP_WRITE),
+      bl_post_body(bl_post_body) {}
+  int init_processing(optional_yield y) override;
   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; }
 };
 
-class RGWUpdateRole : public RGWRoleWrite {
+class RGWUpdateRole : public RGWRestRole {
   bufferlist bl_post_body;
   std::string role_name;
   std::string max_session_duration;
+  std::unique_ptr<rgw::sal::RGWRole> role;
 public:
-  RGWUpdateRole(const bufferlist& bl_post_body) : bl_post_body(bl_post_body) {};
+  explicit RGWUpdateRole(const bufferlist& bl_post_body)
+    : RGWRestRole(rgw::IAM::iamUpdateRole, RGW_CAP_WRITE),
+      bl_post_body(bl_post_body) {}
+  int init_processing(optional_yield y) override;
   void execute(optional_yield y) override;
-  int get_params();
   const char* name() const override { return "update_role"; }
   RGWOpType get_type() override { return RGW_OP_UPDATE_ROLE; }
-  uint64_t get_op() override { return rgw::IAM::iamUpdateRole; }
 };