]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
rgw/sts: adding code for UpdateRole REST API and
authorPritha Srivastava <prsrivas@redhat.com>
Mon, 23 May 2022 11:30:41 +0000 (17:00 +0530)
committerPritha Srivastava <prsrivas@redhat.com>
Wed, 15 Jun 2022 09:25:56 +0000 (14:55 +0530)
radosgw-admin command that allows modification
of max_session_duration of a role.

fixes: https://tracker.ceph.com/issues/55751

Signed-off-by: Pritha Srivastava <prsrivas@redhat.com>
12 files changed:
doc/radosgw/role.rst
src/rgw/rgw_admin.cc
src/rgw/rgw_auth_s3.cc
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_role.cc
src/rgw/rgw_role.h
src/test/cli/radosgw-admin/help.t

index dbe8810a0b8189f3090d254ee9be6ba66c6702ff..e974498722b5254375c5dd1db00ee2451949e28d 100644 (file)
@@ -291,6 +291,32 @@ For example::
   radosgw-admin role-policy delete --role-name=S3Access1 --policy-name=Policy1
 
 
+Update a role
+-------------
+
+To update a role's max-session-duration, execute the following::
+
+       radosgw-admin role update --role-name={role-name} --max-session-duration={max-session-duration}
+
+Request Parameters
+~~~~~~~~~~~~~~~~~~
+
+``role-name``
+
+:Description: Name of the role.
+:Type: String
+
+``max-session-duration``
+
+:Description: Maximum session duration for a role.
+:Type: String
+
+For example::
+
+  radosgw-admin role update --role-name=S3Access1 --max-session-duration=43200
+
+Note: This command currently can only be used to update max-session-duration.
+
 REST APIs for Manipulating a Role
 =================================
 
@@ -470,6 +496,23 @@ Example::
     </ResponseMetadata>
   </UntagRoleResponse>
 
+Update Role
+-----------
+
+Example::
+  POST "<hostname>?Action=UpdateRole&RoleName=S3Access&MaxSessionDuration=43200"
+
+.. code-block:: XML
+
+  <UpdateRoleResponse>
+    <UpdateRoleResult>
+      <ResponseMetadata>
+        <RequestId>tx000000000000000000007-00611f337e-1027-default</RequestId>
+      </ResponseMetadata>
+      </UpdateRoleResult>
+  </UpdateRoleResponse>
+
+Note: This API currently can only be used to update max-session-duration.
 
 Sample code for tagging, listing tags and untagging a role
 ----------------------------------------------------------
index 506098a224cac9bad6ca7937fc41e6ea80b48571..d4bde231a9e2414e8c4f0721e047c7d0569179f4 100644 (file)
@@ -273,6 +273,7 @@ void usage()
   cout << "  role-policy list           list policies attached to a role\n";
   cout << "  role-policy get            get the specified inline policy document embedded with the given role\n";
   cout << "  role-policy delete         remove policy attached to a role\n";
+  cout << "  role update                update max_session_duration of a role\n";
   cout << "  reshard add                schedule a resharding of a bucket\n";
   cout << "  reshard list               list all bucket resharding or scheduled to be resharded\n";
   cout << "  reshard status             read bucket resharding status\n";
@@ -796,6 +797,7 @@ enum class OPT {
   ROLE_POLICY_LIST,
   ROLE_POLICY_GET,
   ROLE_POLICY_DELETE,
+  ROLE_UPDATE,
   RESHARD_ADD,
   RESHARD_LIST,
   RESHARD_STATUS,
@@ -1027,6 +1029,7 @@ static SimpleCmd::Commands all_cmds = {
   { "role-policy get", OPT::ROLE_POLICY_GET },
   { "role policy delete", OPT::ROLE_POLICY_DELETE },
   { "role-policy delete", OPT::ROLE_POLICY_DELETE },
+  { "role update", OPT::ROLE_UPDATE },
   { "reshard bucket", OPT::BUCKET_RESHARD },
   { "reshard add", OPT::RESHARD_ADD },
   { "reshard list", OPT::RESHARD_LIST },
@@ -3456,7 +3459,7 @@ int main(int argc, const char **argv)
   std::string zonegroup_name, zonegroup_id, zonegroup_new_name;
   std::optional<string> opt_zonegroup_name, opt_zonegroup_id;
   std::string api_name;
-  std::string role_name, path, assume_role_doc, policy_name, perm_policy_doc, path_prefix;
+  std::string role_name, path, assume_role_doc, policy_name, perm_policy_doc, path_prefix, max_session_duration;
   std::string redirect_zone;
   bool redirect_zone_set = false;
   list<string> endpoints;
@@ -4051,6 +4054,8 @@ int main(int argc, const char **argv)
       perm_policy_doc = val;
     } else if (ceph_argparse_witharg(args, i, &val, "--path-prefix", (char*)NULL)) {
       path_prefix = val;
+    } else if (ceph_argparse_witharg(args, i, &val, "--max-session-duration", (char*)NULL)) {
+      max_session_duration = val;
     } else if (ceph_argparse_witharg(args, i, &val, "--totp-serial", (char*)NULL)) {
       totp_serial = val;
     } else if (ceph_argparse_witharg(args, i, &val, "--totp-pin", (char*)NULL)) {
@@ -4392,6 +4397,7 @@ int main(int argc, const char **argv)
                           && opt_cmd != OPT::ROLE_POLICY_LIST
                           && opt_cmd != OPT::ROLE_POLICY_GET
                           && opt_cmd != OPT::ROLE_POLICY_DELETE
+                          && opt_cmd != OPT::ROLE_UPDATE
                           && opt_cmd != OPT::RESHARD_ADD
                           && opt_cmd != OPT::RESHARD_CANCEL
                           && opt_cmd != OPT::RESHARD_STATUS) {
@@ -6770,6 +6776,30 @@ int main(int argc, const char **argv)
            << role_name << std::endl;
       return 0;
   }
+  case OPT::ROLE_UPDATE:
+    {
+      if (role_name.empty()) {
+        cerr << "ERROR: role name is empty" << std::endl;
+        return -EINVAL;
+      }
+
+      std::unique_ptr<rgw::sal::RGWRole> role = store->get_role(role_name, tenant);
+      ret = role->get(dpp(), null_yield);
+      if (ret < 0) {
+        return -ret;
+      }
+      if (!role->validate_max_session_duration(dpp())) {
+        ret = -EINVAL;
+        return ret;
+      }
+      role->update_max_session_duration(max_session_duration);
+      ret = role->update(dpp(), null_yield);
+      if (ret < 0) {
+        return -ret;
+      }
+      cout << "Max session duration updated successfully for role: " << role_name << std::endl;
+      return 0;
+    }
   default:
     output_user_info = false;
   }
index a48cc199ffc486cbca7c8c1c4c465c55f729d9a2..faba2c071c83f73c59096164608e88fc4159b3b0 100644 (file)
@@ -479,7 +479,8 @@ bool is_non_s3_op(RGWOpType op_type)
       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) {
+      op_type == RGW_OP_UNTAG_ROLE ||
+      op_type == RGW_OP_UPDATE_ROLE) {
     return true;
   }
   return false;
index 0ab1058d768934c7d8aa24f5c726329c56a5716a..fb978cf97b0ec0e48db942d81ad0327d368a63ba 100644 (file)
@@ -156,6 +156,7 @@ static const actpair actpairs[] =
  { "iam:TagRole", iamTagRole},
  { "iam:ListRoleTags", iamListRoleTags},
  { "iam:UntagRole", iamUntagRole},
+ { "iam:UpdateRole", iamUpdateRole},
  { "sts:AssumeRole", stsAssumeRole},
  { "sts:AssumeRoleWithWebIdentity", stsAssumeRoleWithWebIdentity},
  { "sts:GetSessionToken", stsGetSessionToken},
@@ -1364,6 +1365,9 @@ const char* action_bit_string(uint64_t action) {
   case iamUntagRole:
     return "iam:UntagRole";
 
+  case iamUpdateRole:
+    return "iam:UpdateRole";
+
   case stsAssumeRole:
     return "sts:AssumeRole";
 
index de8ba9297b41a8bada5e2024757d3b112a022fda..1cc80d54d9a6412dd37ffba4d127cdba1f10b353 100644 (file)
@@ -131,7 +131,8 @@ static constexpr std::uint64_t iamListOIDCProviders = s3All + 17;
 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 iamUpdateRole = s3All + 21;
+static constexpr std::uint64_t iamAll = s3All + 22;
 
 static constexpr std::uint64_t stsAssumeRole = iamAll + 1;
 static constexpr std::uint64_t stsAssumeRoleWithWebIdentity = iamAll + 2;
index e9b670ce2830ae5158d90aa3467d3179a61ad19f..375c7348b2482fa0758812be27ff8a9deabaa291 100644 (file)
@@ -64,6 +64,7 @@ enum RGWOpType {
   RGW_OP_TAG_ROLE,
   RGW_OP_LIST_ROLE_TAGS,
   RGW_OP_UNTAG_ROLE,
+  RGW_OP_UPDATE_ROLE,
   RGW_OP_PUT_BUCKET_POLICY,
   RGW_OP_GET_BUCKET_POLICY,
   RGW_OP_DELETE_BUCKET_POLICY,
index 35f1b367381929b14ac2d0bb135c362270d4cc8a..876f26f4e45d7a0a8fc9ca3aac136e36b46fb9cf 100644 (file)
@@ -86,6 +86,8 @@ RGWOp *RGWHandler_REST_IAM::op_post()
       return new RGWListRoleTags;
     if (action.compare("UntagRole") == 0)
       return new RGWUntagRole(this->bl_post_body);
+    if (action.compare("UpdateRole") == 0)
+      return new RGWUpdateRole(this->bl_post_body);
   }
 
   return nullptr;
index 71090c59c177b365979e978f43b96c7f908e4bb9..0fe6981cb27e976ed96650810dbb715705f11843 100644 (file)
@@ -948,4 +948,69 @@ void RGWUntagRole::execute(optional_yield y)
     s->formatter->close_section();
     s->formatter->close_section();
   }
+}
+
+int RGWUpdateRole::get_params()
+{
+  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;
+    return -EINVAL;
+  }
+
+  return 0;
+}
+
+void RGWUpdateRole::execute(optional_yield y)
+{
+  op_ret = get_params();
+  if (op_ret < 0) {
+    return;
+  }
+
+  if (!store->is_meta_master()) {
+    RGWXMLDecoder::XMLParser parser;
+    if (!parser.init()) {
+      ldpp_dout(this, 0) << "ERROR: failed to initialize xml parser" << dendl;
+      op_ret = -EINVAL;
+      return;
+    }
+
+    bufferlist data;
+    s->info.args.remove("RoleName");
+    s->info.args.remove("MaxSessionDuration");
+    s->info.args.remove("Action");
+    s->info.args.remove("Version");
+
+    RGWUserInfo info = s->user->get_info();
+    const auto& it = info.access_keys.begin();
+    RGWAccessKey key;
+    if (it != info.access_keys.end()) {
+      key.id = it->first;
+      RGWAccessKey cred = it->second;
+      key.key = cred.key;
+    }
+    op_ret = store->forward_iam_request_to_master(s, key, nullptr, bl_post_body, &parser, s->info, y);
+    if (op_ret < 0) {
+      ldpp_dout(this, 20) << "ERROR: forward_iam_request_to_master failed with error code: " << op_ret << dendl;
+      return;
+    }
+  }
+
+  if (!_role->validate_max_session_duration(this)) {
+    op_ret = -EINVAL;
+    return;
+  }
+
+  _role->update_max_session_duration(max_session_duration);
+  op_ret = _role->update(this, y);
+
+  s->formatter->open_object_section("UpdateRoleResponse");
+  s->formatter->open_object_section("UpdateRoleResult");
+  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 69e64306526e32926393a2d2ead0599cec888725..98a08833bf72bdac77090f81d943aff06d6c49fb 100644 (file)
@@ -168,3 +168,14 @@ public:
   RGWOpType get_type() override { return RGW_OP_UNTAG_ROLE; }
   uint64_t get_op() override { return rgw::IAM::iamUntagRole; }
 };
+
+class RGWUpdateRole : public RGWRoleWrite {
+  bufferlist bl_post_body;
+public:
+  RGWUpdateRole(const bufferlist& bl_post_body) : bl_post_body(bl_post_body) {};
+  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; }
+};
\ No newline at end of file
index 0188f4227779d34ce0aab5385355be73cf80ce74..b6dde215f94703921755b954f58313bfe16496cc 100644 (file)
@@ -179,6 +179,16 @@ void RGWRole::decode_json(JSONObj *obj)
   info.decode_json(obj);
 }
 
+bool RGWRole::validate_max_session_duration(const DoutPrefixProvider* dpp)
+{
+  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;
+}
+
 bool RGWRole::validate_input(const DoutPrefixProvider* dpp)
 {
   if (info.name.length() > MAX_ROLE_NAME_LEN) {
@@ -203,9 +213,7 @@ bool RGWRole::validate_input(const DoutPrefixProvider* dpp)
     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;
+  if (!validate_max_session_duration(dpp)) {
     return false;
   }
   return true;
@@ -303,6 +311,15 @@ void RGWRole::erase_tags(const vector<string>& tagKeys)
   }
 }
 
+void RGWRole::update_max_session_duration(const std::string& max_session_duration_str)
+{
+  if (max_session_duration_str.empty()) {
+    info.max_session_duration = SESSION_DURATION_MIN;
+  } else {
+    info.max_session_duration = std::stoull(max_session_duration_str);
+  }
+}
+
 const string& RGWRole::get_names_oid_prefix()
 {
   return role_name_oid_prefix;
index 6ea23e090e9b8bca056a4116c104d188de2d4402..eda04ef714e044dc31b37df285665301d53baf5e 100644 (file)
@@ -93,6 +93,7 @@ public:
   virtual int read_id(const DoutPrefixProvider *dpp, const std::string& role_name, const std::string& tenant, std::string& role_id, optional_yield y) = 0;
   virtual int read_name(const DoutPrefixProvider *dpp, optional_yield y) = 0;
   virtual int read_info(const DoutPrefixProvider *dpp, optional_yield y) = 0;
+  bool validate_max_session_duration(const DoutPrefixProvider* dpp);
   bool validate_input(const DoutPrefixProvider* dpp);
   void extract_name_tenant(const std::string& str);
 
@@ -139,6 +140,7 @@ public:
   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 update_max_session_duration(const std::string& max_session_duration_str);
   void dump(Formatter *f) const;
   void decode_json(JSONObj *obj);
 
index a70eb5ba0a5958785396f80866da8e91b48b3746..f9137f58ab5b1096d5842c87be124eaebd99da55 100644 (file)
     role-policy list           list policies attached to a role
     role-policy get            get the specified inline policy document embedded with the given role
     role-policy delete         remove policy attached to a role
+    role update                update max_session_duration of a role
     reshard add                schedule a resharding of a bucket
     reshard list               list all bucket resharding or scheduled to be resharded
     reshard status             read bucket resharding status