]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
rgw: Added code for STS AssumeRole.
authorPritha Srivastava <prsrivas@redhat.com>
Mon, 23 Apr 2018 08:35:11 +0000 (14:05 +0530)
committerPritha Srivastava <prsrivas@redhat.com>
Fri, 21 Sep 2018 05:38:35 +0000 (11:08 +0530)
Signed-off-by: Pritha Srivastava <prsrivas@redhat.com>
src/rgw/CMakeLists.txt
src/rgw/sts-assume-role.cc [new file with mode: 0644]
src/rgw/sts-assume-role.h [new file with mode: 0644]

index d4e6100b01034511a138d8f781323a9a8fa91663..aac221e541fa2a1dfe3cc5d38dfb71c736cea9c6 100644 (file)
@@ -139,7 +139,8 @@ set(rgw_a_srcs
   rgw_rest_user.cc
   rgw_swift_auth.cc
   rgw_usage.cc
-  rgw_opa.cc)
+  rgw_opa.cc
+  sts-assume-role.cc)
 
 gperf_generate(${CMAKE_SOURCE_DIR}/src/rgw/rgw_iam_policy_keywords.gperf
   rgw_iam_policy_keywords.frag.cc)
diff --git a/src/rgw/sts-assume-role.cc b/src/rgw/sts-assume-role.cc
new file mode 100644 (file)
index 0000000..7c8f225
--- /dev/null
@@ -0,0 +1,145 @@
+#include <errno.h>
+#include <ctime>
+#include <regex>
+#include <boost/format.hpp>
+#include <boost/algorithm/string/replace.hpp>
+
+#include "common/errno.h"
+#include "common/Formatter.h"
+#include "common/ceph_json.h"
+#include "common/ceph_time.h"
+#include "rgw_rados.h"
+#include "auth/Crypto.h"
+#include "include/ceph_fs.h"
+
+#include "include/types.h"
+#include "rgw_string.h"
+
+#include "rgw_common.h"
+#include "rgw_tools.h"
+#include "rgw_role.h"
+#include "sts-assume-role.h"
+
+#define dout_subsys ceph_subsys_rgw
+
+namespace STS {
+  
+int Credentials::generateCredentials(CephContext* cct)
+{
+  uuid_d accessKey, secretKey;
+  char accessKeyId_str[MAX_ACCESS_KEY_LEN], secretAccessKey_str[MAX_ACCESS_KEY_LEN];
+
+  //AccessKeyId
+  accessKey.generate_random();
+  accessKey.print(accessKeyId_str);
+  accessKeyId = accessKeyId_str;
+
+  //SecretAccessKey
+  secretKey.generate_random();
+  secretKey.print(secretAccessKey_str);
+  secretAccessKey = secretAccessKey_str;
+
+  //Expiration
+  real_clock::time_point t = real_clock::now();
+
+  struct timeval tv;
+  real_clock::to_timeval(t, tv);
+  tv.tv_sec += EXPIRATION_TIME_IN_SECS;
+
+  struct tm result;
+  gmtime_r(&tv.tv_sec, &result);
+  int usec = (int)tv.tv_usec/1000;
+  expiration = boost::str(boost::format("%s-%s-%sT%s:%s:%s.%sZ")
+                                         % (result.tm_year + 1900)
+                                         % (result.tm_mon + 1)
+                                         % result.tm_mday
+                                         % result.tm_hour
+                                         % result.tm_min
+                                         % result.tm_sec
+                                         % usec);
+
+  //Session Token - Encrypt using AES & base64 encode the result
+  auto* cryptohandler = cct->get_crypto_handler(CEPH_CRYPTO_AES);
+  if (! cryptohandler) {
+    return -EINVAL;
+  }
+  char secret_s[] = {
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+  };
+  bufferptr secret(secret_s, sizeof(secret_s));
+  int ret = 0;
+  if (ret = cryptohandler->validate_secret(secret); ret < 0) {
+    ldout(cct, 0) << "ERROR: Invalid secret key" << dendl;
+    return ret;
+  }
+  string error;
+  auto* keyhandler = cryptohandler->get_key_handler(secret, error);
+  if (! keyhandler) {
+    return -EINVAL;
+  }
+  error.clear();
+  string encrypted_str, input_str = "acess_key_id=" + accessKeyId + "&" +
+                     "secret_access_key=" + secretAccessKey + "&" +
+                     "expiration=" + expiration;
+  bufferlist input, enc_output;
+  input.append(input_str);
+  if (ret = keyhandler->encrypt(input, enc_output, &error); ret < 0) {
+    return ret;
+  }
+
+  enc_output.append('\0');
+  encrypted_str = enc_output.c_str();
+
+  std::string decoded_str;
+  bufferlist enc_bp, encoded_op;
+  enc_bp.append(encrypted_str);
+  encoded_op.encode_base64(enc_bp);
+  encoded_op.append('\0');
+  sessionToken = encoded_op.c_str();
+
+  return ret;
+}
+
+int AssumedRoleUser::generateAssumedRoleUser(CephContext* cct,
+                                              RGWRados *store,
+                                              const string& 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);
+  
+  rgw::IAM::ARN assumed_role_arn(rgw::IAM::Partition::aws,
+                                  rgw::IAM::Service::sts,
+                                  "", r_arn->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 = role.get_id() + ":" + roleSessionName;
+
+  return 0;
+}
+
+AssumeRoleResponse STSService::assumeRole(const AssumeRoleRequest& req)
+{
+  AssumedRoleUser user;
+  user.generateAssumedRoleUser(cct, store, req.getRoleARN(), req.getRoleSessionName());
+
+  Credentials cred;
+  cred.generateCredentials(cct);
+
+  string policy = req.getPolicy();
+  uint64_t packedPolicySize = (policy.size() / req.getMaxPolicySize()) * 100;
+  return make_tuple(user, cred, packedPolicySize);
+}
+
+}
\ No newline at end of file
diff --git a/src/rgw/sts-assume-role.h b/src/rgw/sts-assume-role.h
new file mode 100644 (file)
index 0000000..8461f58
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef CEPH_STS_ASSUME_ROLE_H
+#define CEPH_STS_ASSUME_ROLE_H
+
+namespace STS {
+
+class AssumeRoleRequest {
+  static constexpr int MAX_POLICY_SIZE = 2048;
+  uint64_t duration;
+  string externalId;
+  string iamPolicy;
+  string roleArn;
+  string roleSessionName;
+  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; }
+};
+
+
+class AssumedRoleUser {
+  string arn;
+  string assumeRoleId;
+public:
+  int generateAssumedRoleUser( CephContext* cct,
+                                RGWRados *store,
+                                const string& roleArn,
+                                const string& roleSessionName);
+  string getARN() const { return arn; }
+  string getAssumeRoleId() const { return assumeRoleId; }
+};
+
+class Credentials {
+  static constexpr int MAX_ACCESS_KEY_LEN = 64;
+  static constexpr int EXPIRATION_TIME_IN_SECS = 86400; // 1 day
+  string accessKeyId;
+  string expiration;
+  string secretAccessKey;
+  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; }
+};
+
+using AssumeRoleResponse = std::tuple<AssumedRoleUser, Credentials, uint64_t> ;
+
+class STSService {
+  CephContext* cct;
+  RGWRados *store;
+public:
+  STSService(CephContext* _cct, RGWRados *_store) : cct(_cct), store(_store) {}
+  AssumeRoleResponse assumeRole(const AssumeRoleRequest& req);
+};
+}
+#endif /* CEPH_STS_ASSUME_ROLE_H */
+