]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: adds code for role session to be used an ARN.
authorPritha Srivastava <prsrivas@redhat.com>
Tue, 31 Mar 2020 10:07:20 +0000 (15:37 +0530)
committerPritha Srivastava <prsrivas@redhat.com>
Fri, 5 Jun 2020 16:01:58 +0000 (21:31 +0530)
Signed-off-by: Pritha Srivastava <prsrivas@redhat.com>
src/rgw/rgw_auth.cc
src/rgw/rgw_auth.h
src/rgw/rgw_auth_s3.h
src/rgw/rgw_basic_types.h
src/rgw/rgw_iam_policy.cc
src/rgw/rgw_rest_s3.cc
src/rgw/rgw_rest_sts.cc
src/rgw/rgw_rest_sts.h
src/rgw/rgw_role.h
src/rgw/rgw_sts.cc
src/rgw/rgw_sts.h

index a949ed10eed0e4a3f01f2f3d72e675ae84b730de..45e44e89fce4c922465bd8748fb043d932a9aeea 100644 (file)
@@ -2,6 +2,7 @@
 // vim: ts=8 sw=2 smarttab ft=cpp
 
 #include <array>
+#include <string>
 
 #include "rgw_common.h"
 #include "rgw_auth.h"
@@ -359,11 +360,12 @@ void rgw::auth::WebIdentityApplier::modify_request_state(const DoutPrefixProvide
 
   string idp_url = get_idp_url();
   string condition = idp_url + ":app_id";
-  if (! token_claims.client_id.empty()) {
-    s->env.emplace(condition, token_claims.client_id);
-  } else {
-    s->env.emplace(condition, token_claims.aud);
-  }
+
+  s->env.emplace(condition, token_claims.aud);
+
+  condition.clear();
+  condition = idp_url + ":sub";
+  s->env.emplace(condition, token_claims.sub);
 }
 
 bool rgw::auth::WebIdentityApplier::is_identity(const idset_t& ids) const
@@ -661,26 +663,35 @@ void rgw::auth::LocalApplier::load_acct_info(const DoutPrefixProvider* dpp, RGWU
 }
 
 void rgw::auth::RoleApplier::to_str(std::ostream& out) const {
-  out << "rgw::auth::LocalApplier(role name =" << role_name;
-  for (auto policy : role_policies) {
+  out << "rgw::auth::LocalApplier(role name =" << role.name;
+  for (auto& policy: role.role_policies) {
     out << ", role policy =" << policy;
   }
+  out << ", token policy =" << token_policy;
   out << ")";
 }
 
 bool rgw::auth::RoleApplier::is_identity(const idset_t& ids) const {
   for (auto& p : ids) {
-    string name;
-    string tenant = p.get_tenant();
-    if (tenant.empty()) {
-      name = p.get_id();
-    } else {
-      name = tenant + "$" + p.get_id();
-    }
     if (p.is_wildcard()) {
       return true;
-    } else if (p.is_role() && name == role_name) {
-      return true;
+    } else if (p.is_role()) {
+      string name = p.get_id();
+      string tenant = p.get_tenant();
+      if (name == role.name && tenant == role.tenant) {
+        return true;
+      }
+    } else if (p.is_assumed_role()) {
+      string tenant = p.get_tenant();
+      string role_session = role.name + "/" + role_session_name; //role/role-session
+      if (role.tenant == tenant && role_session == p.get_role_session()) {
+        return true;
+      }
+    } else {
+      string id = p.get_id();
+      if (user_id.id == id) {
+        return true;
+      }
     }
   }
   return false;
@@ -690,21 +701,38 @@ void rgw::auth::RoleApplier::load_acct_info(const DoutPrefixProvider* dpp, RGWUs
 {
   /* Load the user id */
   user_info.user_id = this->user_id;
+
+  user_info.user_id.tenant = role.tenant;
 }
 
 void rgw::auth::RoleApplier::modify_request_state(const DoutPrefixProvider *dpp, req_state* s) const
 {
-  for (auto it : role_policies) {
+  for (auto it: role.role_policies) {
     try {
       bufferlist bl = bufferlist::static_from_string(it);
-      const rgw::IAM::Policy p(s->cct, s->user->get_tenant(), bl);
+      const rgw::IAM::Policy p(s->cct, role.tenant, bl);
       s->iam_user_policies.push_back(std::move(p));
     } catch (rgw::IAM::PolicyParseException& e) {
       //Control shouldn't reach here as the policy has already been
       //verified earlier
-      ldpp_dout(dpp, 20) << "failed to parse policy: " << e.what() << dendl;
+      ldpp_dout(dpp, 20) << "failed to parse role policy: " << e.what() << dendl;
     }
   }
+
+  try {
+    string policy = this->token_policy;
+    bufferlist bl = bufferlist::static_from_string(policy);
+    const rgw::IAM::Policy p(s->cct, role.tenant, bl);
+    s->iam_user_policies.push_back(std::move(p));
+  } catch (rgw::IAM::PolicyParseException& e) {
+    //Control shouldn't reach here as the policy has already been
+    //verified earlier
+    ldpp_dout(dpp, 20) << "failed to parse token policy: " << e.what() << dendl;
+  }
+
+  string condition = "aws:userid";
+  string value = role.id + ":" + role_session_name;
+  s->env.emplace(condition, value);
 }
 
 rgw::auth::Engine::result_t
index a08a7f3024e2a20f27e07b5e386646c956590c78..b970f9235721c0b0f64eb5f8fa129f1b9666587b 100644 (file)
@@ -362,6 +362,7 @@ class WebIdentityApplier : public IdentityApplier {
 protected:
   CephContext* const cct;
   RGWCtl* const ctl;
+  string role_session;
   rgw::web_idp::WebTokenClaims token_claims;
 
   string get_idp_url() const;
@@ -369,9 +370,11 @@ protected:
 public:
   WebIdentityApplier( CephContext* const cct,
                       RGWCtl* const ctl,
+                      const string& role_session,
                       const rgw::web_idp::WebTokenClaims& token_claims)
     : cct(cct),
       ctl(ctl),
+      role_session(role_session),
       token_claims(token_claims) {
   }
 
@@ -415,6 +418,7 @@ public:
 
     virtual aplptr_t create_apl_web_identity( CephContext* cct,
                                               const req_state* s,
+                                              const string& role_session,
                                               const rgw::web_idp::WebTokenClaims& token) const = 0;
   };
 };
@@ -615,20 +619,29 @@ public:
 };
 
 class RoleApplier : public IdentityApplier {
+public:
+  struct Role {
+    string id;
+    string name;
+    string tenant;
+    vector<string> role_policies;
+  } role;
 protected:
-  const string role_name;
   const rgw_user user_id;
-  vector<std::string> role_policies;
+  string token_policy;
+  string role_session_name;
 
 public:
 
   RoleApplier(CephContext* const cct,
-               const string& role_name,
+               const Role& role,
                const rgw_user& user_id,
-               const vector<std::string>& role_policies)
-    : role_name(role_name),
+               const string& token_policy,
+               const string& role_session_name)
+    : role(role),
       user_id(user_id),
-      role_policies(role_policies) {}
+      token_policy(token_policy),
+      role_session_name(role_session_name) {}
 
   uint32_t get_perms_from_aclspec(const DoutPrefixProvider* dpp, const aclspec_t& aclspec) const override {
     return 0;
@@ -653,9 +666,10 @@ public:
     virtual ~Factory() {}
     virtual aplptr_t create_apl_role( CephContext* cct,
                                       const req_state* s,
-                                      const string& role_name,
+                                      const rgw::auth::RoleApplier::Role& role_name,
                                       const rgw_user& user_id,
-                                      const vector<std::string>& role_policies) const = 0;
+                                      const std::string& token_policy,
+                                      const std::string& role_session) const = 0;
     };
 };
 
index 9e79ee162136e15fdb48d2b88d92c5f2158e08e5..0809ee854eb8783c3a2f6fe970a69f06b3997a98 100644 (file)
@@ -65,11 +65,12 @@ class STSAuthStrategy : public rgw::auth::Strategy,
 
   aplptr_t create_apl_role(CephContext* const cct,
                             const req_state* const s,
-                            const string& role_name,
+                            const rgw::auth::RoleApplier::Role& role,
                             const rgw_user& user_id,
-                            const vector<std::string>& role_policies) const override {
+                            const std::string& token_policy,
+                            const std::string& role_session_name) const override {
     auto apl = rgw::auth::add_sysreq(cct, ctl, s,
-      rgw::auth::RoleApplier(cct, role_name, user_id, role_policies));
+      rgw::auth::RoleApplier(cct, role, user_id, token_policy, role_session_name));
     return aplptr_t(new decltype(apl)(std::move(apl)));
   }
 
index 238fa223bbd276bb47fea762d8102931e852f263..df6ad59b96aa8e301a0860362a0e733ce0bf7612 100644 (file)
@@ -486,7 +486,7 @@ void decode_json_obj(rgw_zone_id& zid, JSONObj *obj);
 namespace rgw {
 namespace auth {
 class Principal {
-  enum types { User, Role, Tenant, Wildcard, OidcProvider };
+  enum types { User, Role, Tenant, Wildcard, OidcProvider, AssumedRole };
   types t;
   rgw_user u;
   std::string idp_url;
@@ -522,6 +522,10 @@ public:
     return Principal(std::move(idp_url));
   }
 
+  static Principal assumed_role(std::string&& t, std::string&& u) {
+    return Principal(AssumedRole, std::move(t), std::move(u));
+  }
+
   bool is_wildcard() const {
     return t == Wildcard;
   }
@@ -542,6 +546,10 @@ public:
     return t == OidcProvider;
   }
 
+  bool is_assumed_role() const {
+    return t == AssumedRole;
+  }
+
   const std::string& get_tenant() const {
     return u.tenant;
   }
@@ -554,6 +562,14 @@ public:
     return idp_url;
   }
 
+  const string& get_role_session() const {
+    return u.id;
+  }
+
+  const string& get_role() const {
+    return u.id;
+  }
+
   bool operator ==(const Principal& o) const {
     return (t == o.t) && (u == o.u);
   }
index f89a61d461eb2ec99b81d5bf28e96ba27dbee3f6..60d8ba68e529321b03f6e5682c00a0cec7199385 100644 (file)
@@ -466,6 +466,9 @@ static boost::optional<Principal> parse_principal(CephContext* cct, TokenID t,
         if (match[1] == "oidc-provider") {
                 return Principal::oidc_provider(std::move(match[2]));
         }
+   if (match[1] == "assumed-role") {
+     return Principal::assumed_role(std::move(a->account), match[2]);
+   }
       }
     } else {
       if (std::none_of(s.begin(), s.end(),
index 781df84a401bb3b108813f84a8768d268a4ae38c..fad3b3f35e2a6b5e3958eeeb325b3529f551b637 100644 (file)
@@ -5856,26 +5856,26 @@ rgw::auth::s3::STSEngine::authenticate(
   // Get all the authorization info
   RGWUserInfo user_info;
   rgw_user user_id;
-  vector<string> role_policies;
-  string role_name;
+  string role_id;
+  rgw::auth::RoleApplier::Role r;
   if (! token.roleId.empty()) {
     RGWRole role(s->cct, ctl, token.roleId);
     if (role.get_by_id() < 0) {
       return result_t::deny(-EPERM);
     }
+    r.id = token.roleId;
+    r.name = role.get_name();
+    r.tenant = role.get_tenant();
+
     vector<string> role_policy_names = role.get_role_policy_names();
     for (auto& policy_name : role_policy_names) {
       string perm_policy;
       if (int ret = role.get_role_policy(policy_name, perm_policy); ret == 0) {
-        role_policies.push_back(std::move(perm_policy));
+        r.role_policies.push_back(std::move(perm_policy));
       }
     }
-    if (! token.policy.empty()) {
-      role_policies.push_back(std::move(token.policy));
-    }
     // This is mostly needed to assign the owner of a bucket during its creation
     user_id = token.user;
-    role_name = role.get_name();
   }
 
   if (! token.user.empty() && token.acct_type != TYPE_ROLE) {
@@ -5892,7 +5892,7 @@ rgw::auth::s3::STSEngine::authenticate(
                                             get_creds_info(token));
     return result_t::grant(std::move(apl), completer_factory(boost::none));
   } else if (token.acct_type == TYPE_ROLE) {
-    auto apl = role_apl_factory->create_apl_role(cct, s, role_name, user_id, role_policies);
+    auto apl = role_apl_factory->create_apl_role(cct, s, r, user_id, token.policy, token.role_session);
     return result_t::grant(std::move(apl), completer_factory(token.secret_access_key));
   } else { // This is for all local users of type TYPE_RGW or TYPE_NONE
     string subuser;
index e229b0a95054635d31c7220ee053027562cc4a06..729c61e2e515f19350342bcbb9e59f2a7abf5627 100644 (file)
@@ -328,7 +328,11 @@ WebTokenEngine::authenticate( const DoutPrefixProvider* dpp,
   }
 
   if (t) {
-    auto apl = apl_factory->create_apl_web_identity(cct, s, *t);
+    string role_session = s->info.args.get("RoleSessionName");
+    if (role_session.empty()) {
+      return result_t::deny(-EACCES);
+    }
+    auto apl = apl_factory->create_apl_web_identity(cct, s, role_session, *t);
     return result_t::grant(std::move(apl));
   }
   return result_t::deny(-EACCES);
index 79333f5043ae8a3ffd8e0e771adec6f1ea38e613..d7227fe5af6c63c1d497d7e85ba9923983cc0590 100644 (file)
@@ -77,9 +77,10 @@ class DefaultStrategy : public rgw::auth::Strategy,
 
   aplptr_t create_apl_web_identity( CephContext* cct,
                                     const req_state* s,
+                                    const string& role_session,
                                     const rgw::web_idp::WebTokenClaims& token) const override {
     auto apl = rgw::auth::add_sysreq(cct, ctl, s,
-      rgw::auth::WebIdentityApplier(cct, ctl, token));
+      rgw::auth::WebIdentityApplier(cct, ctl, role_session, token));
     return aplptr_t(new decltype(apl)(std::move(apl)));
   }
 
index 8df22f6844fb6ed6bdf340b2462589961bb3bb55..fceb4fb635474712932eab8372ac9fee79630f1c 100644 (file)
@@ -40,7 +40,6 @@ class RGWRole
   int read_id(const string& role_name, const string& tenant, string& role_id);
   int read_name();
   int read_info();
-  void set_id(const string& id) { this->id = id; }
   bool validate_input();
   void extract_name_tenant(const std::string& str);
 
@@ -129,11 +128,14 @@ public:
 
   const string& get_id() const { return id; }
   const string& get_name() const { return name; }
+  const string& get_tenant() const { return tenant; }
   const string& get_path() const { return path; }
   const string& get_create_date() const { return creation_date; }
   const string& get_assume_role_policy() const { return trust_policy;}
   const uint64_t& get_max_session_duration() const { return max_session_duration; }
 
+  void set_id(const string& id) { this->id = id; }
+
   int create(bool exclusive);
   int delete_obj();
   int get();
index de4e33fb4aa788956d5af909e97656a23b709b1a..ca813c244b614d422f88386b2c8f2cd80393d92d 100644 (file)
@@ -44,6 +44,7 @@ int Credentials::generateCredentials(CephContext* cct,
                           const uint64_t& duration,
                           const boost::optional<string>& policy,
                           const boost::optional<string>& roleId,
+                          const boost::optional<string>& role_session,
                           boost::optional<rgw_user> user,
                           rgw::auth::Identity* identity)
 {
@@ -117,6 +118,7 @@ int Credentials::generateCredentials(CephContext* cct,
     token.perm_mask = 0;
     token.is_admin = 0;
     token.acct_type = TYPE_ROLE;
+    token.role_session = role_session.get();
   }
 
   buffer::list input, enc_output;
@@ -335,6 +337,7 @@ AssumeRoleWithWebIdentityResponse STSService::assumeRoleWithWebIdentity(AssumeRo
   //Role and Policy provide the authorization info, user id and applier info are not needed
   response.assumeRoleResp.retCode = response.assumeRoleResp.creds.generateCredentials(cct, req.getDuration(),
                                                                                       req.getPolicy(), roleId,
+                                                                                      req.getRoleSessionName(),
                                                                                       user_id, nullptr);
   if (response.assumeRoleResp.retCode < 0) {
     return response;
@@ -380,6 +383,7 @@ AssumeRoleResponse STSService::assumeRole(AssumeRoleRequest& req)
   //Role and Policy provide the authorization info, user id and applier info are not needed
   response.retCode = response.creds.generateCredentials(cct, req.getDuration(),
                                               req.getPolicy(), roleId,
+                                              req.getRoleSessionName(),
                                               user_id, nullptr);
   if (response.retCode < 0) {
     return response;
@@ -417,6 +421,7 @@ GetSessionTokenResponse STSService::getSessionToken(GetSessionTokenRequest& req)
                                       req.getDuration(),
                                       boost::none,
                                       boost::none,
+                                      boost::none,
                                       user_id,
                                       identity); ret < 0) {
     return make_tuple(ret, cred);
index 86b621a30852e3ca81b29490fb62906c55ddf1c8..fa8cc70295da39fd1dbbd3393c29b7190237db4e 100644 (file)
@@ -128,11 +128,12 @@ struct SessionToken {
   uint32_t perm_mask;
   bool is_admin;
   uint32_t acct_type;
+  string role_session;
 
   SessionToken() {}
 
   void encode(bufferlist& bl) const {
-    ENCODE_START(1, 1, bl);
+    ENCODE_START(2, 1, bl);
     encode(access_key_id, bl);
     encode(secret_access_key, bl);
     encode(expiration, bl);
@@ -143,11 +144,12 @@ struct SessionToken {
     encode(perm_mask, bl);
     encode(is_admin, bl);
     encode(acct_type, bl);
+    encode(role_session, bl);
     ENCODE_FINISH(bl);
   }
 
   void decode(bufferlist::const_iterator& bl) {
-    DECODE_START(1, bl);
+    DECODE_START(2, bl);
     decode(access_key_id, bl);
     decode(secret_access_key, bl);
     decode(expiration, bl);
@@ -158,6 +160,9 @@ struct SessionToken {
     decode(perm_mask, bl);
     decode(is_admin, bl);
     decode(acct_type, bl);
+    if (struct_v >= 2) {
+      decode(role_session, bl);
+    }
     DECODE_FINISH(bl);
   }
 };
@@ -175,6 +180,7 @@ public:
                           const uint64_t& duration,
                           const boost::optional<string>& policy,
                           const boost::optional<string>& roleId,
+                          const boost::optional<string>& role_session,
                           boost::optional<rgw_user> user,
                           rgw::auth::Identity* identity);
   const string& getAccessKeyId() const { return accessKeyId; }