]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: Adding manager, handler etc for STS.
authorPritha Srivastava <prsrivas@redhat.com>
Mon, 30 Apr 2018 07:28:52 +0000 (12:58 +0530)
committerPritha Srivastava <prsrivas@redhat.com>
Fri, 21 Sep 2018 05:39:32 +0000 (11:09 +0530)
Signed-off-by: Pritha Srivastava <prsrivas@redhat.com>
src/common/legacy_config_opts.h
src/common/options.cc
src/rgw/CMakeLists.txt
src/rgw/rgw_common.cc
src/rgw/rgw_common.h
src/rgw/rgw_http_errors.h
src/rgw/rgw_main.cc
src/rgw/rgw_rest_sts.cc [new file with mode: 0644]
src/rgw/rgw_rest_sts.h [new file with mode: 0644]
src/rgw/sts-assume-role.cc
src/rgw/sts-assume-role.h

index dd9cf3e2fdcf3bfd885fde6259858f267492c669..76ec765113b18e58a72fd91f617cfb5654ab1c2e 100644 (file)
@@ -1545,3 +1545,4 @@ OPTION(rgw_acl_grants_max_num, OPT_INT) // According to AWS S3(http://docs.aws.a
 OPTION(rgw_cors_rules_max_num, OPT_INT) // According to AWS S3(http://docs.aws.amazon.com/AmazonS3/latest/dev/cors.html), An cors can have up to 100 rules.
 OPTION(rgw_delete_multi_obj_max_num, OPT_INT) // According to AWS S3(https://docs.aws.amazon.com/AmazonS3/latest/dev/DeletingObjects.html), Amazon S3 also provides the Multi-Object Delete API that you can use to delete up to 1000 objects in a single HTTP request.
 OPTION(rgw_website_routing_rules_max_num, OPT_INT) // According to AWS S3, An website routing config can have up to 50 rules.
+OPTION(rgw_sts_entry, OPT_STR)
index 32244382055789e52ed5b51993e15f32306aafb6..f8a7390a106433874f5854906853aef9de1c680a 100644 (file)
@@ -5102,7 +5102,7 @@ std::vector<Option> get_rgw_options() {
         "will be located in the path that is specified here. "),
 
     Option("rgw_enable_apis", Option::TYPE_STR, Option::LEVEL_ADVANCED)
-    .set_default("s3, s3website, swift, swift_auth, admin")
+    .set_default("s3, s3website, swift, swift_auth, admin, sts")
     .set_description("A list of set of RESTful APIs that rgw handles."),
 
     Option("rgw_cache_enabled", Option::TYPE_BOOL, Option::LEVEL_ADVANCED)
@@ -6348,6 +6348,10 @@ std::vector<Option> get_rgw_options() {
                          "increasing this value may cause some operations to "
                          "take longer in exceptional cases and thus may, "
                          "rarely, cause clients to time out."),
+    Option("rgw_sts_entry", Option::TYPE_STR, Option::LEVEL_ADVANCED)
+    .set_default("sts")
+    .set_description("STS URL prefix")
+    .set_long_description("URL path prefix for internal STS requests.")
   });
 }
 
index aac221e541fa2a1dfe3cc5d38dfb71c736cea9c6..b4056ede33f8a43ce9809d44b24b282647687ddb 100644 (file)
@@ -140,7 +140,8 @@ set(rgw_a_srcs
   rgw_swift_auth.cc
   rgw_usage.cc
   rgw_opa.cc
-  sts-assume-role.cc)
+  sts-assume-role.cc
+  rgw_rest_sts.cc)
 
 gperf_generate(${CMAKE_SOURCE_DIR}/src/rgw/rgw_iam_policy_keywords.gperf
   rgw_iam_policy_keywords.frag.cc)
index beb06d7ed8494223d43cbb63356bd0464c1efc16..9efa225034f3509af6113c86291600cc081e676a 100644 (file)
@@ -140,6 +140,10 @@ rgw_http_errors rgw_http_swift_errors({
     { ERR_ZERO_IN_URL, {412, "Invalid UTF8 or contains NULL"}},
 });
 
+rgw_http_errors rgw_http_sts_errors({
+    { ERR_PACKED_POLICY_TOO_LARGE, {400, "PackedPolicyTooLarge" }},
+});
+
 int rgw_perf_start(CephContext *cct)
 {
   PerfCountersBuilder plb(cct, "rgw", l_rgw_first, l_rgw_last);
@@ -328,6 +332,11 @@ void set_req_state_err(struct rgw_err& err,        /* out */
       return;
   }
 
+  if (prot_flags & RGW_REST_STS) {
+    if (search_err(rgw_http_sts_errors, err_no, err.http_ret, err.err_code))
+      return;
+  }
+
   //Default to searching in s3 errors
   if (search_err(rgw_http_s3_errors, err_no, err.http_ret, err.err_code))
       return;
index 0ae4583fe45deb628f402da892cbcfac19ae0caa..795423dd5b5caf383d4d6aad7c0379c7726f0725 100644 (file)
@@ -133,6 +133,7 @@ using ceph::crypto::MD5;
 #define RGW_REST_SWIFT_AUTH     0x2
 #define RGW_REST_S3             0x4
 #define RGW_REST_WEBSITE     0x8
+#define RGW_REST_STS            0x10
 
 #define RGW_SUSPENDED_USER_AUID (uint64_t)-2
 
@@ -223,6 +224,10 @@ using ceph::crypto::MD5;
 
 #define ERR_BUSY_RESHARDING      2300
 #define ERR_NO_SUCH_ENTITY       2301
+
+// STS Errors
+#define ERR_PACKED_POLICY_TOO_LARGE 2400
+
 #ifndef UINT32_MAX
 #define UINT32_MAX (0xffffffffu)
 #endif
@@ -516,6 +521,8 @@ enum RGWOpType {
   RGW_OP_CONFIG_BUCKET_META_SEARCH,
   RGW_OP_GET_BUCKET_META_SEARCH,
   RGW_OP_DEL_BUCKET_META_SEARCH,
+  /* sts specific*/
+  RGW_STS_ASSUME_ROLE,
 };
 
 class RGWAccessControlPolicy;
index e2aec310c88b331c2bedbd4d291d076a021501ba..a4d0999467d5d549d8b2fc07feed57b06e18487b 100644 (file)
@@ -12,6 +12,8 @@ extern rgw_http_errors rgw_http_s3_errors;
 
 extern rgw_http_errors rgw_http_swift_errors;
 
+extern rgw_http_errors rgw_http_sts_errors;
+
 static inline int rgw_http_error_to_errno(int http_err)
 {
   if (http_err >= 200 && http_err <= 299)
index 3ac76c47dadb1c38987739b068a268745bfd72ca..abbeaade68f82113f968a5b2c2a9ab62d5c9dca3 100644 (file)
@@ -27,6 +27,7 @@
 #include "rgw_rest_log.h"
 #include "rgw_rest_config.h"
 #include "rgw_rest_realm.h"
+#include "rgw_rest_sts.h"
 #include "rgw_swift_auth.h"
 #include "rgw_log.h"
 #include "rgw_tools.h"
@@ -401,6 +402,11 @@ int main(int argc, const char **argv)
     rest.register_resource(g_conf()->rgw_admin_entry, admin_resource);
   }
 
+  if (apis_map.count("sts") > 0) {
+    auto *sts = new RGWRESTMgr_STS;
+    rest.register_resource(g_conf()->rgw_sts_entry, set_logging(sts));
+  }
+
   /* Initialize the registry of auth strategies which will coordinate
    * the dynamic reconfiguration. */
   auto auth_registry = \
diff --git a/src/rgw/rgw_rest_sts.cc b/src/rgw/rgw_rest_sts.cc
new file mode 100644 (file)
index 0000000..5cf2620
--- /dev/null
@@ -0,0 +1,161 @@
+#include <boost/algorithm/string/predicate.hpp>
+#include <boost/format.hpp>
+#include <boost/optional.hpp>
+#include <boost/utility/in_place_factory.hpp>
+
+#include "include/assert.h"
+#include "ceph_ver.h"
+
+#include "common/Formatter.h"
+#include "common/utf8.h"
+#include "common/ceph_json.h"
+
+#include "rgw_rest.h"
+#include "rgw_auth.h"
+#include "rgw_auth_s3.h"
+#include "rgw_rest_sts.h"
+#include "rgw_formats.h"
+#include "rgw_client_io.h"
+
+#include "rgw_request.h"
+#include "rgw_process.h"
+
+#include "sts-assume-role.h"
+
+#include <array>
+#include <sstream>
+#include <memory>
+
+#include <boost/utility/string_ref.hpp>
+
+#define dout_context g_ceph_context
+#define dout_subsys ceph_subsys_rgw
+
+int RGWREST_STS::verify_permission()
+{
+  return 0;
+}
+
+void RGWREST_STS::send_response()
+{
+  if (op_ret) {
+    set_req_state_err(s, op_ret);
+  }
+  dump_errno(s);
+  end_header(s);
+}
+
+int RGWSTSAssumeRole::get_params()
+{
+  duration = s->info.args.get("DurationSeconds");
+  externalId = s->info.args.get("ExternalId");
+  policy = s->info.args.get("Policy");
+  roleArn = s->info.args.get("RoleArn");
+  roleSessionName = s->info.args.get("RoleSessionName");
+  serialNumber = s->info.args.get("SerialNumber");
+  tokenCode = s->info.args.get("TokenCode");
+
+  if (roleArn.empty() || roleSessionName.empty()) {
+    ldout(s->cct, 20) << "ERROR: one of role arn or role session name is empty" << dendl;
+    return -EINVAL;
+  }
+
+  JSONParser p;
+  if (!p.parse(policy.c_str(), policy.length())) {
+    ldout(s->cct, 20) << "ERROR: failed to parse policy doc" << dendl;
+    return -ERR_MALFORMED_DOC;
+  }
+
+  return 0;
+}
+
+void RGWSTSAssumeRole::execute()
+{
+  STS::AssumeRoleRequest req(duration, externalId, policy, roleArn,
+                        roleSessionName, serialNumber, tokenCode);
+  STS::STSService sts(s->cct, store);
+  const auto& [op_ret, assumedRoleUser, creds, packedPolicySize] = sts.assumeRole(req);
+
+  //Dump the output
+  if (op_ret == 0) {
+    s->formatter->open_object_section("AssumeRole");
+    assumedRoleUser.dump(s->formatter);
+    creds.dump(s->formatter);
+    encode_json("PackedPolicySize", packedPolicySize , s->formatter);
+    s->formatter->close_section();
+  }
+}
+
+RGWOp *RGWHandler_REST_STS::op_post()
+{
+  if (s->info.args.exists("Action"))    {
+    if (string action = s->info.args.get("Action"); action == "AssumeRole") {
+      return new RGWSTSAssumeRole;
+    }
+  }
+  return nullptr;
+}
+
+int RGWHandler_REST_STS::init(RGWRados *store,
+                              struct req_state *s,
+                              rgw::io::BasicClient *cio)
+{
+  s->dialect = "sts";
+
+  if (int ret = RGWHandler_REST_STS::init_from_header(s, RGW_FORMAT_JSON, true); ret < 0) {
+    ldout(s->cct, 10) << "init_from_header returned err=" << ret <<  dendl;
+    return ret;
+  }
+
+  return RGWHandler_REST::init(store, s, cio);
+}
+
+int RGWHandler_REST_STS::init_from_header(struct req_state* s,
+                                          int default_formatter,
+                                          bool configurable_format)
+{
+  string req;
+  string first;
+
+  s->prot_flags |= RGW_REST_STS;
+
+  const char *p, *req_name;
+  if (req_name = s->relative_uri.c_str(); *req_name == '?') {
+    p = req_name;
+  } else {
+    p = s->info.request_params.c_str();
+  }
+
+  s->info.args.set(p);
+  s->info.args.parse();
+
+  /* must be called after the args parsing */
+  if (int ret = allocate_formatter(s, default_formatter, configurable_format); ret < 0)
+    return ret;
+
+  if (*req_name != '/')
+    return 0;
+
+  req_name++;
+
+  if (!*req_name)
+    return 0;
+
+  req = req_name;
+  int pos = req.find('/');
+  if (pos >= 0) {
+    first = req.substr(0, pos);
+  } else {
+    first = req;
+  }
+
+  return 0;
+}
+
+RGWHandler_REST*
+RGWRESTMgr_STS::get_handler(struct req_state* const s,
+                              const rgw::auth::StrategyRegistry& auth_registry,
+                              const std::string& frontend_prefix)
+{
+  return new RGWHandler_REST_STS(auth_registry);
+}
diff --git a/src/rgw/rgw_rest_sts.h b/src/rgw/rgw_rest_sts.h
new file mode 100644 (file)
index 0000000..ba95308
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef CEPH_RGW_REST_STS_H
+#define CEPH_RGW_REST_STS_H
+
+class RGWREST_STS : public RGWRESTOp {
+public:
+  int verify_permission() override;
+  void send_response() override;
+};
+
+class RGWSTSAssumeRole : public RGWREST_STS {
+protected:
+  string duration;
+  string externalId;
+  string policy;
+  string roleArn;
+  string roleSessionName;
+  string serialNumber;
+  string tokenCode;
+public:
+  RGWSTSAssumeRole() = default;
+  void execute() override;
+  int get_params();
+  const string name() override { return "assume_role"; }
+  RGWOpType get_type() override { return RGW_STS_ASSUME_ROLE; }
+};
+
+class RGWHandler_REST_STS : public RGWHandler_REST {
+  const rgw::auth::StrategyRegistry& auth_registry;
+  RGWOp *op_post() override;
+public:
+  static int init_from_header(struct req_state *s, int default_formatter, bool configurable_format);
+
+  RGWHandler_REST_STS(const rgw::auth::StrategyRegistry& auth_registry)
+    : RGWHandler_REST(),
+      auth_registry(auth_registry) {}
+  ~RGWHandler_REST_STS() override = default;
+
+  int init(RGWRados *store,
+           struct req_state *s,
+           rgw::io::BasicClient *cio) override;
+  int authorize() override {
+    return RGW_Auth_S3::authorize(store, auth_registry, s);
+  }
+  int postauth_init() override { return 0; }
+};
+
+class RGWRESTMgr_STS : public RGWRESTMgr {
+public:
+  RGWRESTMgr_STS() = default;
+  ~RGWRESTMgr_STS() override = default;
+  
+  RGWRESTMgr *get_resource_mgr(struct req_state* const s,
+                               const std::string& uri,
+                               std::string* const out_uri) override {
+    return this;
+  }
+
+  RGWHandler_REST* get_handler(struct req_state*,
+                               const rgw::auth::StrategyRegistry&,
+                               const std::string&) override;
+};
+
+#endif /* CEPH_RGW_REST_STS_H */
+
index 7c8f225dc009f51017001ea701c4aa2346169c41..5fd09755d521915f6cf7f0aa7c68ebd242bd4b5b 100644 (file)
 #define dout_subsys ceph_subsys_rgw
 
 namespace STS {
-  
+
+void Credentials::dump(Formatter *f) const
+{
+  encode_json("AccessKeyId", accessKeyId , f);
+  encode_json("Expiration", expiration , f);
+  encode_json("SecretAccessKey", secretAccessKey , f);
+  encode_json("SessionToken", sessionToken , f);
+}
+
 int Credentials::generateCredentials(CephContext* cct)
 {
   uuid_d accessKey, secretKey;
@@ -101,45 +109,150 @@ int Credentials::generateCredentials(CephContext* cct)
   return ret;
 }
 
+void AssumedRoleUser::dump(Formatter *f) const
+{
+  encode_json("Arn", arn , f);
+  encode_json("AssumeRoleId", assumeRoleId , f);
+}
+
 int AssumedRoleUser::generateAssumedRoleUser(CephContext* cct,
                                               RGWRados *store,
-                                              const string& roleArn,
+                                              const string& roleId,
+                                              const boost::optional<rgw::IAM::ARN>& roleArn,
                                               const string& roleSessionName)
 {
-  auto r_arn = rgw::IAM::ARN::parse(roleArn);
-  string resource = r_arn->resource;
-  boost::replace_first(resource, "role", "assumed-role");
-  resource.append("/");
-  resource.append(roleSessionName);
+  string resource, account;
+  rgw::IAM::ARN r_arn;
+  if (roleArn) {
+    r_arn = roleArn.get();
+    resource = r_arn.resource;
+    boost::replace_first(resource, "role", "assumed-role");
+    resource.append("/");
+    resource.append(roleSessionName);
+    account = r_arn.account;
+  }
   
   rgw::IAM::ARN assumed_role_arn(rgw::IAM::Partition::aws,
                                   rgw::IAM::Service::sts,
-                                  "", r_arn->account, resource);
+                                  "", account, resource);
   arn = assumed_role_arn.to_string();
 
   //Assumeroleid = roleid:rolesessionname
-  auto pos = r_arn->resource.find_last_of('/');
-  string roleName = r_arn->resource.substr(pos + 1);
-  RGWRole role(cct, store, roleName, r_arn->account);
-  if (int ret = role.get(); ret < 0) {
-    return ret;
+  assumeRoleId = roleId + ":" + roleSessionName;
+
+  return 0;
+}
+
+AssumeRoleRequest::AssumeRoleRequest(string _duration, string _externalId, string _iamPolicy,
+                    string _roleArn, string _roleSessionName, string _serialNumber,
+                    string _tokenCode)
+    : externalId(_externalId), iamPolicy(_iamPolicy),
+      roleArn(_roleArn), roleSessionName(_roleSessionName),
+      serialNumber(_serialNumber), tokenCode(_tokenCode)
+{
+  if (_duration.empty()) {
+    duration = DEFAULT_DURATION_IN_SECS;
+  } else {
+    duration = std::stoull(_duration);
+  }
+}
+
+int AssumeRoleRequest::validate_input() const
+{
+  if (duration < MIN_DURATION_IN_SECS) {
+    return -EINVAL;
+  }
+
+  if (! externalId.empty()) {
+    if (externalId.length() < MIN_EXTERNAL_ID_LEN ||
+          externalId.length() > MAX_EXTERNAL_ID_LEN) {
+      return -EINVAL;
+    }
+
+    std::regex regex_externalId("[A-Za-z0-9_+=,.@:/-");
+    if (! std::regex_match(externalId, regex_externalId)) {
+      return -EINVAL;
+    }
+  }
+  if (! iamPolicy.empty() &&
+          (iamPolicy.size() < MIN_POLICY_SIZE || iamPolicy.size() > MAX_POLICY_SIZE)) {
+    return -ERR_PACKED_POLICY_TOO_LARGE;
+  }
+
+  if (! roleArn.empty() &&
+          (roleArn.size() < MIN_ROLE_ARN_SIZE || roleArn.size() > MAX_ROLE_ARN_SIZE)) {
+    return -EINVAL;
+  }
+
+  if (! roleSessionName.empty()) {
+    if (roleSessionName.size() < MIN_ROLE_SESSION_SIZE || roleSessionName.size() > MAX_ROLE_SESSION_SIZE) {
+      return -EINVAL;
+    }
+
+    std::regex regex_roleSession("[A-Za-z0-9_+=,.@-");
+    if (! std::regex_match(roleSessionName, regex_roleSession)) {
+      return -EINVAL;
+    }
+  }
+  if (! serialNumber.empty()){
+    if (serialNumber.size() < MIN_SERIAL_NUMBER_SIZE || serialNumber.size() > MAX_SERIAL_NUMBER_SIZE) {
+      return -EINVAL;
+    }
+
+    std::regex regex_serialNumber("[A-Za-z0-9_=/:,.@-");
+    if (! std::regex_match(serialNumber, regex_serialNumber)) {
+      return -EINVAL;
+    }
+  }
+  if (! tokenCode.empty() && tokenCode.size() == TOKEN_CODE_SIZE) {
+    return -EINVAL;
   }
-  assumeRoleId = role.get_id() + ":" + roleSessionName;
 
   return 0;
 }
 
 AssumeRoleResponse STSService::assumeRole(const AssumeRoleRequest& req)
 {
+  int ret = 0;
+  uint64_t packedPolicySize = 0;
   AssumedRoleUser user;
-  user.generateAssumedRoleUser(cct, store, req.getRoleARN(), req.getRoleSessionName());
-
   Credentials cred;
-  cred.generateCredentials(cct);
+  string roleId;
+
+  //Get the role info which is being assumed
+  auto r_arn = rgw::IAM::ARN::parse(req.getRoleARN());
+  if (r_arn) {
+    auto pos = r_arn->resource.find_last_of('/');
+    string roleName = r_arn->resource.substr(pos + 1);
+    RGWRole role(cct, store, roleName, r_arn->account);
+    if (ret = role.get(); ret < 0) {
+      return make_tuple(ret, user, cred, packedPolicySize);
+    }
+    roleId = role.get_id();
+  } else {
+    return make_tuple(-EINVAL, user, cred, packedPolicySize);
+  }
+
+  //Validate input
+  if (ret = req.validate_input(); ret < 0) {
+    return make_tuple(ret, user, cred, packedPolicySize);
+  }
 
+  //Calculate PackedPolicySize
   string policy = req.getPolicy();
-  uint64_t packedPolicySize = (policy.size() / req.getMaxPolicySize()) * 100;
-  return make_tuple(user, cred, packedPolicySize);
+  packedPolicySize = (policy.size() / req.getMaxPolicySize()) * 100;
+
+  //Generate Assumed Role User
+  if (ret = user.generateAssumedRoleUser(cct, store, roleId, r_arn, req.getRoleSessionName()); ret < 0) {
+    return make_tuple(ret, user, cred, packedPolicySize);
+  }
+
+  //Generate Credentials
+  if (ret = cred.generateCredentials(cct); ret < 0) {
+    return make_tuple(ret, user, cred, packedPolicySize);
+  }
+
+  return make_tuple(0, user, cred, packedPolicySize);
 }
 
 }
\ No newline at end of file
index 8461f58f2017d465a570e40417d55e6223458e3c..f560e2ad0e16e02dd09e8f39b00d473397ea5eeb 100644 (file)
@@ -4,7 +4,19 @@
 namespace STS {
 
 class AssumeRoleRequest {
-  static constexpr int MAX_POLICY_SIZE = 2048;
+  static constexpr uint64_t MIN_POLICY_SIZE = 1;
+  static constexpr uint64_t MAX_POLICY_SIZE = 2048;
+  static constexpr uint64_t DEFAULT_DURATION_IN_SECS = 3600;
+  static constexpr uint64_t MIN_DURATION_IN_SECS = 900;
+  static constexpr uint64_t MIN_EXTERNAL_ID_LEN = 2;
+  static constexpr uint64_t MAX_EXTERNAL_ID_LEN = 1224;
+  static constexpr uint64_t MIN_ROLE_ARN_SIZE = 2;
+  static constexpr uint64_t MAX_ROLE_ARN_SIZE = 2048;
+  static constexpr uint64_t MIN_ROLE_SESSION_SIZE = 2;
+  static constexpr uint64_t MAX_ROLE_SESSION_SIZE = 64;
+  static constexpr uint64_t MIN_SERIAL_NUMBER_SIZE = 9;
+  static constexpr uint64_t MAX_SERIAL_NUMBER_SIZE = 256;
+  static constexpr uint64_t TOKEN_CODE_SIZE = 6;
   uint64_t duration;
   string externalId;
   string iamPolicy;
@@ -13,16 +25,18 @@ class AssumeRoleRequest {
   string serialNumber;
   string tokenCode;
 public:
-  AssumeRoleRequest(uint64_t _duration, string _externalId, string _iamPolicy,
-                    string _roleArn, string _roleSessionName, string _serialNumber,
-                    string _tokenCode)
-                    : duration(_duration), externalId(_externalId), iamPolicy(_iamPolicy),
-                      roleArn(_roleArn), roleSessionName(_roleSessionName),
-                      serialNumber(_serialNumber), tokenCode(_tokenCode) {}
-  string getRoleARN() const { return roleArn; }
-  string getRoleSessionName() const { return roleSessionName; }
-  string getPolicy() const {return iamPolicy; }
-  int getMaxPolicySize() const { return MAX_POLICY_SIZE; }
+  AssumeRoleRequest( string _duration,
+                      string _externalId,
+                      string _iamPolicy,
+                      string _roleArn,
+                      string _roleSessionName,
+                      string _serialNumber,
+                      string _tokenCode);
+  const string& getRoleARN() const { return roleArn; }
+  const string& getRoleSessionName() const { return roleSessionName; }
+  const string& getPolicy() const {return iamPolicy; }
+  static uint64_t getMaxPolicySize() { return MAX_POLICY_SIZE; }
+  int validate_input() const;
 };
 
 
@@ -32,10 +46,12 @@ class AssumedRoleUser {
 public:
   int generateAssumedRoleUser( CephContext* cct,
                                 RGWRados *store,
-                                const string& roleArn,
+                                const string& roleId,
+                                const boost::optional<rgw::IAM::ARN>& roleArn,
                                 const string& roleSessionName);
-  string getARN() const { return arn; }
-  string getAssumeRoleId() const { return assumeRoleId; }
+  const string& getARN() const { return arn; }
+  const string& getAssumeRoleId() const { return assumeRoleId; }
+  void dump(Formatter *f) const;
 };
 
 class Credentials {
@@ -47,13 +63,15 @@ class Credentials {
   string sessionToken;
 public:
   int generateCredentials(CephContext* cct);
-  string getAccessKeyId() const { return accessKeyId; }
-  string getExpiration() const { return expiration; }
-  string getSecretAccessKey() const { return secretAccessKey; }
-  string getSessionToken() const { return sessionToken; }
+  const string& getAccessKeyId() const { return accessKeyId; }
+  const string& getExpiration() const { return expiration; }
+  const string& getSecretAccessKey() const { return secretAccessKey; }
+  const string& getSessionToken() const { return sessionToken; }
+  void dump(Formatter *f) const;
 };
 
-using AssumeRoleResponse = std::tuple<AssumedRoleUser, Credentials, uint64_t> ;
+//AssumedRoleUser, Credentials, PackedpolicySize
+using AssumeRoleResponse = std::tuple<int, AssumedRoleUser, Credentials, uint64_t> ;
 
 class STSService {
   CephContext* cct;