]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw/sts: correcting the evaluation of session policies 42632/head
authorPritha Srivastava <prsrivas@redhat.com>
Thu, 27 May 2021 13:36:44 +0000 (19:06 +0530)
committerCory Snyder <csnyder@iland.com>
Wed, 18 Aug 2021 09:29:43 +0000 (05:29 -0400)
passed in with AssumeRoleWithWebIdentity.

Session Policies are used to restrict the permissions
granted by identity-based (Role's permission policy
and resource-policy (bucket policy) in some cases.

Fixes: https://tracker.ceph.com/issues/51019
Signed-off-by: Pritha Srivastava <prsrivas@redhat.com>
(cherry picked from commit bd611d451aaaba65c6c1b7a91ec4486142c90522)

Conflicts:
src/rgw/rgw_op.cc

Cherry-pick notes:
- conflict due to rgw::sal::RGWObject renaming to rgw::sal::Object after Pacific

src/rgw/rgw_auth.cc
src/rgw/rgw_common.cc
src/rgw/rgw_common.h
src/rgw/rgw_iam_policy.cc
src/rgw/rgw_iam_policy.h
src/rgw/rgw_op.cc
src/test/rgw/test_rgw_iam_policy.cc

index 9d0d3ea42b3347d5a6ab1b0f27fca00db1943d87..ce613f40d1be021b52607f0ee46de8f5d96c9c18 100644 (file)
@@ -804,15 +804,17 @@ void rgw::auth::RoleApplier::modify_request_state(const DoutPrefixProvider *dpp,
     }
   }
 
-  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;
+  if (!this->token_policy.empty()) {
+    try {
+      string policy = this->token_policy;
+      bufferlist bl = bufferlist::static_from_string(policy);
+      const rgw::IAM::Policy p(s->cct, role.tenant, bl);
+      s->session_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";
index 57765bbfe922c14665c6d036ea6d879fcd1f8867..bbd8ab6f70b9429c48b3f1c89617f2a52d5ede66 100644 (file)
@@ -1048,30 +1048,31 @@ Effect eval_or_pass(const boost::optional<Policy>& policy,
                    const rgw::IAM::Environment& env,
                    boost::optional<const rgw::auth::Identity&> id,
                    const uint64_t op,
-                   const ARN& arn) {
+                   const ARN& arn,
+                               boost::optional<rgw::IAM::PolicyPrincipal&> princ_type=boost::none) {
   if (!policy)
     return Effect::Pass;
   else
-    return policy->eval(env, id, op, arn);
+    return policy->eval(env, id, op, arn, princ_type);
 }
 
 }
 
-Effect eval_user_policies(const vector<Policy>& user_policies,
+Effect eval_identity_or_session_policies(const vector<Policy>& policies,
                           const rgw::IAM::Environment& env,
                           boost::optional<const rgw::auth::Identity&> id,
                           const uint64_t op,
                           const ARN& arn) {
-  auto usr_policy_res = Effect::Pass, prev_res = Effect::Pass;
-  for (auto& user_policy : user_policies) {
-    if (usr_policy_res = eval_or_pass(user_policy, env, id, op, arn); usr_policy_res == Effect::Deny)
-      return usr_policy_res;
-    else if (usr_policy_res == Effect::Allow)
+  auto policy_res = Effect::Pass, prev_res = Effect::Pass;
+  for (auto& policy : policies) {
+    if (policy_res = eval_or_pass(policy, env, id, op, arn); policy_res == Effect::Deny)
+      return policy_res;
+    else if (policy_res == Effect::Allow)
       prev_res = Effect::Allow;
-    else if (usr_policy_res == Effect::Pass && prev_res == Effect::Allow)
-      usr_policy_res = Effect::Allow;
+    else if (policy_res == Effect::Pass && prev_res == Effect::Allow)
+      policy_res = Effect::Allow;
   }
-  return usr_policy_res;
+  return policy_res;
 }
 
 bool verify_user_permission(const DoutPrefixProvider* dpp,
@@ -1081,7 +1082,7 @@ bool verify_user_permission(const DoutPrefixProvider* dpp,
                             const rgw::ARN& res,
                             const uint64_t op)
 {
-  auto usr_policy_res = eval_user_policies(user_policies, s->env, boost::none, op, res);
+  auto usr_policy_res = eval_identity_or_session_policies(user_policies, s->env, boost::none, op, res);
   if (usr_policy_res == Effect::Deny) {
     return false;
   }
@@ -1160,26 +1161,49 @@ bool verify_bucket_permission(const DoutPrefixProvider* dpp,
                               RGWAccessControlPolicy * const user_acl,
                               RGWAccessControlPolicy * const bucket_acl,
                              const boost::optional<Policy>& bucket_policy,
-                              const vector<Policy>& user_policies,
+                              const vector<Policy>& identity_policies,
+                              const vector<Policy>& session_policies,
                               const uint64_t op)
 {
   if (!verify_requester_payer_permission(s))
     return false;
 
-  auto usr_policy_res = eval_user_policies(user_policies, s->env, boost::none, op, ARN(bucket));
-  if (usr_policy_res == Effect::Deny)
+  auto identity_policy_res = eval_identity_or_session_policies(identity_policies, s->env, boost::none, op, ARN(bucket));
+  if (identity_policy_res == Effect::Deny)
     return false;
 
+  rgw::IAM::PolicyPrincipal princ_type = rgw::IAM::PolicyPrincipal::Other;
   auto r = eval_or_pass(bucket_policy, s->env, *s->identity,
-                       op, ARN(bucket));
-  if (r == Effect::Allow)
+                       op, ARN(bucket), princ_type);
+  if (r == Effect::Deny)
+    return false;
+
+  //Take into account session policies, if the identity making a request is a role
+  if (!session_policies.empty()) {
+    auto session_policy_res = eval_identity_or_session_policies(session_policies, s->env, boost::none, op, ARN(bucket));
+    if (session_policy_res == Effect::Deny) {
+        return false;
+    }
+    if (princ_type == rgw::IAM::PolicyPrincipal::Role) {
+      //Intersection of session policy and identity policy plus intersection of session policy and bucket policy
+      if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) ||
+          (session_policy_res == Effect::Allow && r == Effect::Allow))
+        return true;
+    } else if (princ_type == rgw::IAM::PolicyPrincipal::Session) {
+      //Intersection of session policy and identity policy plus bucket policy
+      if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) || r == Effect::Allow)
+        return true;
+    } else if (princ_type == rgw::IAM::PolicyPrincipal::Other) {// there was no match in the bucket policy
+      if (session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow)
+        return true;
+    }
+    return false;
+  }
+
+  if (r == Effect::Allow || identity_policy_res == Effect::Allow)
     // It looks like S3 ACLs only GRANT permissions rather than
     // denying them, so this should be safe.
     return true;
-  else if (r == Effect::Deny)
-    return false;
-  else if (usr_policy_res == Effect::Allow) // r is Effect::Pass at this point
-    return true;
 
   const auto perm = op_to_perm(op);
 
@@ -1193,13 +1217,14 @@ bool verify_bucket_permission(const DoutPrefixProvider* dpp,
                               RGWAccessControlPolicy * const bucket_acl,
                              const boost::optional<Policy>& bucket_policy,
                               const vector<Policy>& user_policies,
+                              const vector<Policy>& session_policies,
                               const uint64_t op)
 {
   perm_state_from_req_state ps(s);
   return verify_bucket_permission(dpp, &ps, bucket,
                                   user_acl, bucket_acl,
                                   bucket_policy, user_policies,
-                                  op);
+                                  session_policies, op);
 }
 
 bool verify_bucket_permission_no_policy(const DoutPrefixProvider* dpp, struct perm_state_base * const s,
@@ -1263,31 +1288,54 @@ bool verify_bucket_permission(const DoutPrefixProvider* dpp, struct req_state *
                                   s->bucket_acl.get(),
                                   s->iam_policy,
                                   s->iam_user_policies,
+                                  s->session_policies,
                                   op);
 }
 
-// Authorize anyone permitted by the policy and the bucket owner
+// Authorize anyone permitted by the bucket policy, identity policies, session policies and the bucket owner
 // unless explicitly denied by the policy.
 
 int verify_bucket_owner_or_policy(struct req_state* const s,
                                  const uint64_t op)
 {
-  auto usr_policy_res = eval_user_policies(s->iam_user_policies, s->env, boost::none, op, ARN(s->bucket->get_key()));
-  if (usr_policy_res == Effect::Deny) {
+  auto identity_policy_res = eval_identity_or_session_policies(s->iam_user_policies, s->env, boost::none, op, ARN(s->bucket->get_key()));
+  if (identity_policy_res == Effect::Deny) {
     return -EACCES;
   }
 
+  rgw::IAM::PolicyPrincipal princ_type = rgw::IAM::PolicyPrincipal::Other;
   auto e = eval_or_pass(s->iam_policy,
                        s->env, *s->auth.identity,
-                       op, ARN(s->bucket->get_key()));
+                       op, ARN(s->bucket->get_key()), princ_type);
   if (e == Effect::Deny) {
     return -EACCES;
   }
 
+  if (!s->session_policies.empty()) {
+    auto session_policy_res = eval_identity_or_session_policies(s->session_policies, s->env, boost::none, op, ARN(s->bucket->get_key()));
+    if (session_policy_res == Effect::Deny) {
+        return -EACCES;
+    }
+    if (princ_type == rgw::IAM::PolicyPrincipal::Role) {
+      //Intersection of session policy and identity policy plus intersection of session policy and bucket policy
+      if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) ||
+          (session_policy_res == Effect::Allow && e == Effect::Allow))
+        return 0;
+    } else if (princ_type == rgw::IAM::PolicyPrincipal::Session) {
+      //Intersection of session policy and identity policy plus bucket policy
+      if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) || e == Effect::Allow)
+        return 0;
+    } else if (princ_type == rgw::IAM::PolicyPrincipal::Other) {// there was no match in the bucket policy
+      if (session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow)
+        return 0;
+    }
+    return -EACCES;
+  }
+
   if (e == Effect::Allow ||
-      usr_policy_res == Effect::Allow ||
+      identity_policy_res == Effect::Allow ||
       (e == Effect::Pass &&
-       usr_policy_res == Effect::Pass &&
+       identity_policy_res == Effect::Pass &&
        s->auth.identity->is_owner_of(s->bucket_owner.get_id()))) {
     return 0;
   } else {
@@ -1302,12 +1350,13 @@ static inline bool check_deferred_bucket_perms(const DoutPrefixProvider* dpp,
                                               RGWAccessControlPolicy * const user_acl,
                                               RGWAccessControlPolicy * const bucket_acl,
                                               const boost::optional<Policy>& bucket_policy,
-                 const vector<Policy>& user_policies,
+                 const vector<Policy>& identity_policies,
+                 const vector<Policy>& session_policies,
                                               const uint8_t deferred_check,
                                               const uint64_t op)
 {
   return (s->defer_to_bucket_acls == deferred_check \
-         && verify_bucket_permission(dpp, s, bucket, user_acl, bucket_acl, bucket_policy, user_policies,op));
+         && verify_bucket_permission(dpp, s, bucket, user_acl, bucket_acl, bucket_policy, identity_policies, session_policies,op));
 }
 
 static inline bool check_deferred_bucket_only_acl(const DoutPrefixProvider* dpp,
@@ -1327,32 +1376,54 @@ bool verify_object_permission(const DoutPrefixProvider* dpp, struct perm_state_b
                               RGWAccessControlPolicy * const bucket_acl,
                               RGWAccessControlPolicy * const object_acl,
                               const boost::optional<Policy>& bucket_policy,
-                              const vector<Policy>& user_policies,
+                              const vector<Policy>& identity_policies,
+                              const vector<Policy>& session_policies,
                               const uint64_t op)
 {
   if (!verify_requester_payer_permission(s))
     return false;
 
-  auto usr_policy_res = eval_user_policies(user_policies, s->env, boost::none, op, ARN(obj));
-  if (usr_policy_res == Effect::Deny)
+  auto identity_policy_res = eval_identity_or_session_policies(identity_policies, s->env, boost::none, op, ARN(obj));
+  if (identity_policy_res == Effect::Deny)
     return false;
 
-  auto r = eval_or_pass(bucket_policy, s->env, *s->identity, op, ARN(obj));
-  if (r == Effect::Allow)
+  rgw::IAM::PolicyPrincipal princ_type = rgw::IAM::PolicyPrincipal::Other;
+  auto r = eval_or_pass(bucket_policy, s->env, *s->identity, op, ARN(obj), princ_type);
+  if (r == Effect::Deny)
+    return false;
+
+  if (!session_policies.empty()) {
+    auto session_policy_res = eval_identity_or_session_policies(session_policies, s->env, boost::none, op, ARN(obj));
+    if (session_policy_res == Effect::Deny) {
+        return false;
+    }
+    if (princ_type == rgw::IAM::PolicyPrincipal::Role) {
+      //Intersection of session policy and identity policy plus intersection of session policy and bucket policy
+      if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) ||
+          (session_policy_res == Effect::Allow && r == Effect::Allow))
+        return true;
+    } else if (princ_type == rgw::IAM::PolicyPrincipal::Session) {
+      //Intersection of session policy and identity policy plus bucket policy
+      if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) || r == Effect::Allow)
+        return true;
+    } else if (princ_type == rgw::IAM::PolicyPrincipal::Other) {// there was no match in the bucket policy
+      if (session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow)
+        return true;
+    }
+    return false;
+  }
+
+  if (r == Effect::Allow || identity_policy_res == Effect::Allow)
     // It looks like S3 ACLs only GRANT permissions rather than
     // denying them, so this should be safe.
     return true;
-  else if (r == Effect::Deny)
-    return false;
-  else if (usr_policy_res == Effect::Allow)
-    return true;
 
   const auto perm = op_to_perm(op);
 
   if (check_deferred_bucket_perms(dpp, s, obj.bucket, user_acl, bucket_acl, bucket_policy,
-                                 user_policies, RGW_DEFER_TO_BUCKET_ACLS_RECURSE, op) ||
+                                 identity_policies, session_policies, RGW_DEFER_TO_BUCKET_ACLS_RECURSE, op) ||
       check_deferred_bucket_perms(dpp, s, obj.bucket, user_acl, bucket_acl, bucket_policy,
-                                 user_policies, RGW_DEFER_TO_BUCKET_ACLS_FULL_CONTROL, rgw::IAM::s3All)) {
+                                 identity_policies, session_policies, RGW_DEFER_TO_BUCKET_ACLS_FULL_CONTROL, rgw::IAM::s3All)) {
     return true;
   }
 
@@ -1401,14 +1472,15 @@ bool verify_object_permission(const DoutPrefixProvider* dpp, struct req_state *
                               RGWAccessControlPolicy * const bucket_acl,
                               RGWAccessControlPolicy * const object_acl,
                               const boost::optional<Policy>& bucket_policy,
-                              const vector<Policy>& user_policies,
+                              const vector<Policy>& identity_policies,
+                              const vector<Policy>& session_policies,
                               const uint64_t op)
 {
   perm_state_from_req_state ps(s);
   return verify_object_permission(dpp, &ps, obj,
                                   user_acl, bucket_acl,
                                   object_acl, bucket_policy,
-                                  user_policies, op);
+                                  identity_policies, session_policies, op);
 }
 
 bool verify_object_permission_no_policy(const DoutPrefixProvider* dpp,
@@ -1489,6 +1561,7 @@ bool verify_object_permission(const DoutPrefixProvider* dpp, struct req_state *s
                                   s->object_acl.get(),
                                   s->iam_policy,
                                   s->iam_user_policies,
+                                  s->session_policies,
                                   op);
 }
 
index 7b20466775d2b209cbc11aed373a9c96cdab7989..41413b077bb31f3d84f79ebf0a8d2eebab875f81 100644 (file)
@@ -1620,6 +1620,8 @@ struct req_state : DoutPrefixProvider {
   //token claims from STS token for ops log (can be used for Keystone token also)
   std::vector<string> token_claims;
 
+  vector<rgw::IAM::Policy> session_policies;
+
   req_state(CephContext* _cct, RGWEnv* e, uint64_t id);
   ~req_state();
 
@@ -2085,7 +2087,7 @@ bool verify_object_permission_no_policy(const DoutPrefixProvider* dpp,
 
 /** Check if the req_state's user has the necessary permissions
  * to do the requested action */
-rgw::IAM::Effect eval_user_policies(const vector<rgw::IAM::Policy>& user_policies,
+rgw::IAM::Effect eval_identity_or_session_policies(const vector<rgw::IAM::Policy>& user_policies,
                           const rgw::IAM::Environment& env,
                           boost::optional<const rgw::auth::Identity&> id,
                           const uint64_t op,
@@ -2114,7 +2116,8 @@ bool verify_bucket_permission(
   RGWAccessControlPolicy * const user_acl,
   RGWAccessControlPolicy * const bucket_acl,
   const boost::optional<rgw::IAM::Policy>& bucket_policy,
-  const vector<rgw::IAM::Policy>& user_policies,
+  const vector<rgw::IAM::Policy>& identity_policies,
+  const vector<rgw::IAM::Policy>& session_policies,
   const uint64_t op);
 bool verify_bucket_permission(const DoutPrefixProvider* dpp, struct req_state * const s, const uint64_t op);
 bool verify_bucket_permission_no_policy(
@@ -2136,7 +2139,8 @@ extern bool verify_object_permission(
   RGWAccessControlPolicy * const bucket_acl,
   RGWAccessControlPolicy * const object_acl,
   const boost::optional<rgw::IAM::Policy>& bucket_policy,
-  const vector<rgw::IAM::Policy>& user_policies,
+  const vector<rgw::IAM::Policy>& identity_policies,
+  const vector<rgw::IAM::Policy>& session_policies,
   const uint64_t op);
 extern bool verify_object_permission(const DoutPrefixProvider* dpp, struct req_state *s, uint64_t op);
 extern bool verify_object_permission_no_policy(
index 2265334a76f427b6de1ef993b1ec11eff3733ba0..48780c2efbb020e6dd904dd66e57193879390899 100644 (file)
@@ -976,9 +976,9 @@ ostream& operator <<(ostream& m, const Condition& c) {
 
 Effect Statement::eval(const Environment& e,
                       boost::optional<const rgw::auth::Identity&> ida,
-                      uint64_t act, const ARN& res) const {
+                      uint64_t act, const ARN& res, boost::optional<PolicyPrincipal&> princ_type) const {
 
-  if (eval_principal(e, ida) == Effect::Deny) {
+  if (eval_principal(e, ida, princ_type) == Effect::Deny) {
     return Effect::Pass;
   }
 
@@ -1012,13 +1012,34 @@ Effect Statement::eval(const Environment& e,
 }
 
 Effect Statement::eval_principal(const Environment& e,
-                      boost::optional<const rgw::auth::Identity&> ida) const {
+                      boost::optional<const rgw::auth::Identity&> ida, boost::optional<PolicyPrincipal&> princ_type) const {
+  if (princ_type) {
+    *princ_type = PolicyPrincipal::Other;
+  }
   if (ida) {
     if (princ.empty() && noprinc.empty()) {
       return Effect::Deny;
     }
-    if (!princ.empty() && !ida->is_identity(princ)) {
+    if (ida->get_identity_type() != TYPE_ROLE && !princ.empty() && !ida->is_identity(princ)) {
       return Effect::Deny;
+    }
+    if (ida->get_identity_type() == TYPE_ROLE && !princ.empty()) {
+      bool princ_matched = false;
+      for (auto p : princ) { // Check each principal to determine the type of the one that has matched
+        boost::container::flat_set<Principal> id;
+        id.insert(p);
+        if (ida->is_identity(id)) {
+          if (p.is_assumed_role() || p.is_user()) {
+            if (princ_type) *princ_type = PolicyPrincipal::Session;
+          } else {
+            if (princ_type) *princ_type = PolicyPrincipal::Role;
+          }
+          princ_matched = true;
+        }
+      }
+      if (!princ_matched) {
+        return Effect::Deny;
+      }
     } else if (!noprinc.empty() && ida->is_identity(noprinc)) {
       return Effect::Deny;
     }
@@ -1391,10 +1412,11 @@ Policy::Policy(CephContext* cct, const string& tenant,
 
 Effect Policy::eval(const Environment& e,
                    boost::optional<const rgw::auth::Identity&> ida,
-                   std::uint64_t action, const ARN& resource) const {
+                   std::uint64_t action, const ARN& resource,
+        boost::optional<PolicyPrincipal&> princ_type) const {
   auto allowed = false;
   for (auto& s : statements) {
-    auto g = s.eval(e, ida, action, resource);
+    auto g = s.eval(e, ida, action, resource, princ_type);
     if (g == Effect::Deny) {
       return g;
     } else if (g == Effect::Allow) {
@@ -1405,10 +1427,10 @@ Effect Policy::eval(const Environment& e,
 }
 
 Effect Policy::eval_principal(const Environment& e,
-                   boost::optional<const rgw::auth::Identity&> ida) const {
+                   boost::optional<const rgw::auth::Identity&> ida, boost::optional<PolicyPrincipal&> princ_type) const {
   auto allowed = false;
   for (auto& s : statements) {
-    auto g = s.eval_principal(e, ida);
+    auto g = s.eval_principal(e, ida, princ_type);
     if (g == Effect::Deny) {
       return g;
     } else if (g == Effect::Allow) {
index 4f2c144f29f4b362fa80208787910338b448022c..808c2296c941fbfa9924eae109845ca8bb1c60d9 100644 (file)
@@ -242,6 +242,12 @@ inline int op_to_perm(std::uint64_t op) {
 }
 }
 
+enum class PolicyPrincipal {
+  Role,
+  Session,
+  Other
+};
+
 using Environment = boost::container::flat_map<std::string, std::string>;
 
 using Address = std::bitset<128>;
@@ -439,10 +445,10 @@ struct Statement {
 
   Effect eval(const Environment& e,
              boost::optional<const rgw::auth::Identity&> ida,
-             std::uint64_t action, const ARN& resource) const;
+             std::uint64_t action, const ARN& resource, boost::optional<PolicyPrincipal&> princ_type=boost::none) const;
 
   Effect eval_principal(const Environment& e,
-                      boost::optional<const rgw::auth::Identity&> ida) const;
+                      boost::optional<const rgw::auth::Identity&> ida, boost::optional<PolicyPrincipal&> princ_type=boost::none) const;
 
   Effect eval_conditions(const Environment& e) const;
 };
@@ -471,10 +477,10 @@ struct Policy {
 
   Effect eval(const Environment& e,
              boost::optional<const rgw::auth::Identity&> ida,
-             std::uint64_t action, const ARN& resource) const;
+             std::uint64_t action, const ARN& resource, boost::optional<PolicyPrincipal&> princ_type=boost::none) const;
 
   Effect eval_principal(const Environment& e,
-             boost::optional<const rgw::auth::Identity&> ida) const;
+             boost::optional<const rgw::auth::Identity&> ida, boost::optional<PolicyPrincipal&> princ_type=boost::none) const;
 
   Effect eval_conditions(const Environment& e) const;
 
index 4a371e7a2796ee63604ac806651f79826495b37f..cd05f8ab8dbe0c039024cdaa63865a614e82d34e 100644 (file)
@@ -491,7 +491,7 @@ static int read_obj_policy(const DoutPrefixProvider *dpp,
     const rgw_user& bucket_owner = bucket_policy.get_owner().get_id();
     if (bucket_owner.compare(s->user->get_id()) != 0 &&
         ! s->auth.identity->is_admin_of(bucket_owner)) {
-      auto r = eval_user_policies(s->iam_user_policies, s->env,
+      auto r = eval_identity_or_session_policies(s->iam_user_policies, s->env,
                                   *s->auth.identity, rgw::IAM::s3ListBucket,
                                   ARN(bucket->get_key()));
       if (r == Effect::Allow)
@@ -505,6 +505,15 @@ static int read_obj_policy(const DoutPrefixProvider *dpp,
         if (r == Effect::Deny)
           return -EACCES;
       }
+      if (! s->session_policies.empty()) {
+        r = eval_identity_or_session_policies(s->session_policies, s->env,
+                                  *s->auth.identity, rgw::IAM::s3ListBucket,
+                                  ARN(bucket->get_key()));
+        if (r == Effect::Allow)
+          return -ENOENT;
+        if (r == Effect::Deny)
+          return -EACCES;
+      }
       if (! bucket_policy.verify_permission(s, *s->auth.identity, s->perm_mask, RGW_PERM_READ))
         ret = -EACCES;
       else
@@ -1569,7 +1578,7 @@ int RGWGetObj::read_user_manifest_part(rgw::sal::RGWBucket* bucket,
     ldpp_dout(this, 2) << "overriding permissions due to admin operation" << dendl;
   } else if (!verify_object_permission(this, s, part->get_obj(), s->user_acl.get(),
                                       bucket_acl, &obj_policy, bucket_policy,
-                                      s->iam_user_policies, action)) {
+                                      s->iam_user_policies, s->session_policies, action)) {
     return -EPERM;
   }
   if (ent.meta.size == 0) {
@@ -3565,24 +3574,49 @@ int RGWPutObj::verify_permission(optional_yield y)
     /* Object needs a bucket from this point */
     s->object->set_bucket(s->bucket.get());
 
-    auto usr_policy_res = eval_user_policies(s->iam_user_policies, s->env,
+    auto identity_policy_res = eval_identity_or_session_policies(s->iam_user_policies, s->env,
                                             boost::none,
                                             rgw::IAM::s3PutObject,
                                             s->object->get_obj());
-    if (usr_policy_res == Effect::Deny)
+    if (identity_policy_res == Effect::Deny)
       return -EACCES;
 
     rgw::IAM::Effect e = Effect::Pass;
+    rgw::IAM::PolicyPrincipal princ_type = rgw::IAM::PolicyPrincipal::Other;
     if (s->iam_policy) {
       e = s->iam_policy->eval(s->env, *s->auth.identity,
           rgw::IAM::s3PutObject,
-          s->object->get_obj());
+          s->object->get_obj(),
+          princ_type);
     }
-    if (e == Effect::Allow) {
-      return 0;
-    } else if (e == Effect::Deny) {
+    if (e == Effect::Deny) {
       return -EACCES;
-    } else if (usr_policy_res == Effect::Allow) {
+    }
+
+    if (!s->session_policies.empty()) {
+      auto session_policy_res = eval_identity_or_session_policies(s->session_policies, s->env,
+                                              boost::none,
+                                              rgw::IAM::s3PutObject,
+                                              s->object->get_obj());
+      if (session_policy_res == Effect::Deny) {
+          return -EACCES;
+      }
+      if (princ_type == rgw::IAM::PolicyPrincipal::Role) {
+        //Intersection of session policy and identity policy plus intersection of session policy and bucket policy
+        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) ||
+            (session_policy_res == Effect::Allow && e == Effect::Allow))
+          return 0;
+      } else if (princ_type == rgw::IAM::PolicyPrincipal::Session) {
+        //Intersection of session policy and identity policy plus bucket policy
+        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) || e == Effect::Allow)
+          return 0;
+      } else if (princ_type == rgw::IAM::PolicyPrincipal::Other) {// there was no match in the bucket policy
+        if (session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow)
+          return 0;
+      }
+      return -EACCES;
+    }
+    if (e == Effect::Allow || identity_policy_res == Effect::Allow) {
       return 0;
     }
   }
@@ -4119,26 +4153,61 @@ void RGWPostObj::execute(optional_yield y)
     return;
   }
 
-  if (s->iam_policy || ! s->iam_user_policies.empty()) {
-    auto usr_policy_res = eval_user_policies(s->iam_user_policies, s->env,
+  if (s->iam_policy || ! s->iam_user_policies.empty() || !s->session_policies.empty()) {
+    auto identity_policy_res = eval_identity_or_session_policies(s->iam_user_policies, s->env,
                                             boost::none,
                                             rgw::IAM::s3PutObject,
                                             s->object->get_obj());
-    if (usr_policy_res == Effect::Deny) {
+    if (identity_policy_res == Effect::Deny) {
       op_ret = -EACCES;
       return;
     }
 
     rgw::IAM::Effect e = Effect::Pass;
+    rgw::IAM::PolicyPrincipal princ_type = rgw::IAM::PolicyPrincipal::Other;
     if (s->iam_policy) {
       e = s->iam_policy->eval(s->env, *s->auth.identity,
                                 rgw::IAM::s3PutObject,
-                                s->object->get_obj());
+                                s->object->get_obj(),
+         princ_type);
     }
     if (e == Effect::Deny) {
       op_ret = -EACCES;
       return;
-    } else if (usr_policy_res == Effect::Pass && e == Effect::Pass && !verify_bucket_permission_no_policy(this, s, RGW_PERM_WRITE)) {
+    }
+
+    if (!s->session_policies.empty()) {
+      auto session_policy_res = eval_identity_or_session_policies(s->session_policies, s->env,
+                                              boost::none,
+                                              rgw::IAM::s3PutObject,
+                                              s->object->get_obj());
+      if (session_policy_res == Effect::Deny) {
+          op_ret = -EACCES;
+          return;
+      }
+      if (princ_type == rgw::IAM::PolicyPrincipal::Role) {
+        //Intersection of session policy and identity policy plus intersection of session policy and bucket policy
+        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) ||
+            (session_policy_res == Effect::Allow && e == Effect::Allow)) {
+          op_ret = 0;
+          return;
+        }
+      } else if (princ_type == rgw::IAM::PolicyPrincipal::Session) {
+        //Intersection of session policy and identity policy plus bucket policy
+        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) || e == Effect::Allow) {
+          op_ret = 0;
+          return;
+        }
+      } else if (princ_type == rgw::IAM::PolicyPrincipal::Other) {// there was no match in the bucket policy
+        if (session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) {
+          op_ret = 0;
+          return;
+        }
+      }
+      op_ret = -EACCES;
+      return;
+    }
+    if (identity_policy_res == Effect::Pass && e == Effect::Pass && !verify_bucket_permission_no_policy(this, s, RGW_PERM_WRITE)) {
       op_ret = -EACCES;
       return;
     }
@@ -4666,9 +4735,9 @@ int RGWDeleteObj::verify_permission(optional_yield y)
   if (op_ret) {
     return op_ret;
   }
-  if (s->iam_policy || ! s->iam_user_policies.empty()) {
+  if (s->iam_policy || ! s->iam_user_policies.empty() || ! s->session_policies.empty()) {
     if (s->bucket->get_info().obj_lock_enabled() && bypass_governance_mode) {
-      auto r = eval_user_policies(s->iam_user_policies, s->env, boost::none,
+      auto r = eval_identity_or_session_policies(s->iam_user_policies, s->env, boost::none,
                                                rgw::IAM::s3BypassGovernanceRetention, ARN(s->bucket->get_key(), s->object->get_name()));
       if (r == Effect::Deny) {
         bypass_perm = false;
@@ -4678,31 +4747,66 @@ int RGWDeleteObj::verify_permission(optional_yield y)
         if (r == Effect::Deny) {
           bypass_perm = false;
         }
+      } else if (r == Effect::Pass && !s->session_policies.empty()) {
+        r = eval_identity_or_session_policies(s->session_policies, s->env, boost::none,
+                                               rgw::IAM::s3BypassGovernanceRetention, ARN(s->bucket->get_key(), s->object->get_name()));
+        if (r == Effect::Deny) {
+          bypass_perm = false;
+        }
       }
     }
-    auto usr_policy_res = eval_user_policies(s->iam_user_policies, s->env,
+    auto identity_policy_res = eval_identity_or_session_policies(s->iam_user_policies, s->env,
                                               boost::none,
                                               s->object->get_instance().empty() ?
                                               rgw::IAM::s3DeleteObject :
                                               rgw::IAM::s3DeleteObjectVersion,
                                               ARN(s->bucket->get_key(), s->object->get_name()));
-    if (usr_policy_res == Effect::Deny) {
+    if (identity_policy_res == Effect::Deny) {
       return -EACCES;
     }
 
     rgw::IAM::Effect r = Effect::Pass;
+    rgw::IAM::PolicyPrincipal princ_type = rgw::IAM::PolicyPrincipal::Other;
     if (s->iam_policy) {
       r = s->iam_policy->eval(s->env, *s->auth.identity,
                                 s->object->get_instance().empty() ?
                                 rgw::IAM::s3DeleteObject :
                                 rgw::IAM::s3DeleteObjectVersion,
-                                ARN(s->bucket->get_key(), s->object->get_name()));
+                                ARN(s->bucket->get_key(), s->object->get_name()),
+         princ_type);
     }
-    if (r == Effect::Allow)
-      return 0;
-    else if (r == Effect::Deny)
+    if (r == Effect::Deny)
+      return -EACCES;
+
+    if (!s->session_policies.empty()) {
+      auto session_policy_res = eval_identity_or_session_policies(s->session_policies, s->env,
+                                              boost::none,
+                                              s->object->get_instance().empty() ?
+                                              rgw::IAM::s3DeleteObject :
+                                              rgw::IAM::s3DeleteObjectVersion,
+                                              ARN(s->bucket->get_key(), s->object->get_name()));
+      if (session_policy_res == Effect::Deny) {
+          return -EACCES;
+      }
+      if (princ_type == rgw::IAM::PolicyPrincipal::Role) {
+        //Intersection of session policy and identity policy plus intersection of session policy and bucket policy
+        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) ||
+            (session_policy_res == Effect::Allow && r == Effect::Allow)) {
+          return 0;
+        }
+      } else if (princ_type == rgw::IAM::PolicyPrincipal::Session) {
+        //Intersection of session policy and identity policy plus bucket policy
+        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) || r == Effect::Allow) {
+          return 0;
+        }
+      } else if (princ_type == rgw::IAM::PolicyPrincipal::Other) {// there was no match in the bucket policy
+        if (session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) {
+          return 0;
+        }
+      }
       return -EACCES;
-    else if (usr_policy_res == Effect::Allow)
+    }
+    if (r == Effect::Allow || identity_policy_res == Effect::Allow)
       return 0;
   }
 
@@ -5738,26 +5842,54 @@ void RGWSetRequestPayment::execute(optional_yield y)
 
 int RGWInitMultipart::verify_permission(optional_yield y)
 {
-  if (s->iam_policy || ! s->iam_user_policies.empty()) {
-    auto usr_policy_res = eval_user_policies(s->iam_user_policies, s->env,
+  if (s->iam_policy || ! s->iam_user_policies.empty() || !s->session_policies.empty()) {
+    auto identity_policy_res = eval_identity_or_session_policies(s->iam_user_policies, s->env,
                                               boost::none,
                                               rgw::IAM::s3PutObject,
                                               s->object->get_obj());
-    if (usr_policy_res == Effect::Deny) {
+    if (identity_policy_res == Effect::Deny) {
       return -EACCES;
     }
 
     rgw::IAM::Effect e = Effect::Pass;
+    rgw::IAM::PolicyPrincipal princ_type = rgw::IAM::PolicyPrincipal::Other;
     if (s->iam_policy) {
       e = s->iam_policy->eval(s->env, *s->auth.identity,
                                 rgw::IAM::s3PutObject,
-                                s->object->get_obj());
+                                s->object->get_obj(),
+         princ_type);
     }
-    if (e == Effect::Allow) {
-      return 0;
-    } else if (e == Effect::Deny) {
+    if (e == Effect::Deny) {
+      return -EACCES;
+    }
+
+    if (!s->session_policies.empty()) {
+      auto session_policy_res = eval_identity_or_session_policies(s->session_policies, s->env,
+                                              boost::none,
+                                              rgw::IAM::s3PutObject,
+                                              s->object->get_obj());
+      if (session_policy_res == Effect::Deny) {
+          return -EACCES;
+      }
+      if (princ_type == rgw::IAM::PolicyPrincipal::Role) {
+        //Intersection of session policy and identity policy plus intersection of session policy and bucket policy
+        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) ||
+            (session_policy_res == Effect::Allow && e == Effect::Allow)) {
+          return 0;
+        }
+      } else if (princ_type == rgw::IAM::PolicyPrincipal::Session) {
+        //Intersection of session policy and identity policy plus bucket policy
+        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) || e == Effect::Allow) {
+          return 0;
+        }
+      } else if (princ_type == rgw::IAM::PolicyPrincipal::Other) {// there was no match in the bucket policy
+        if (session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) {
+          return 0;
+        }
+      }
       return -EACCES;
-    } else if (usr_policy_res == Effect::Allow) {
+    }
+    if (e == Effect::Allow || identity_policy_res == Effect::Allow) {
       return 0;
     }
   }
@@ -5855,26 +5987,54 @@ void RGWInitMultipart::execute(optional_yield y)
 
 int RGWCompleteMultipart::verify_permission(optional_yield y)
 {
-  if (s->iam_policy || ! s->iam_user_policies.empty()) {
-    auto usr_policy_res = eval_user_policies(s->iam_user_policies, s->env,
+  if (s->iam_policy || ! s->iam_user_policies.empty() || ! s->session_policies.empty()) {
+    auto identity_policy_res = eval_identity_or_session_policies(s->iam_user_policies, s->env,
                                               boost::none,
                                               rgw::IAM::s3PutObject,
                                               s->object->get_obj());
-    if (usr_policy_res == Effect::Deny) {
+    if (identity_policy_res == Effect::Deny) {
       return -EACCES;
     }
 
     rgw::IAM::Effect e = Effect::Pass;
+    rgw::IAM::PolicyPrincipal princ_type = rgw::IAM::PolicyPrincipal::Other;
     if (s->iam_policy) {
       e = s->iam_policy->eval(s->env, *s->auth.identity,
                                 rgw::IAM::s3PutObject,
-                                s->object->get_obj());
+                                s->object->get_obj(),
+         princ_type);
     }
-    if (e == Effect::Allow) {
-      return 0;
-    } else if (e == Effect::Deny) {
+    if (e == Effect::Deny) {
+      return -EACCES;
+    }
+
+    if (!s->session_policies.empty()) {
+      auto session_policy_res = eval_identity_or_session_policies(s->session_policies, s->env,
+                                              boost::none,
+                                              rgw::IAM::s3PutObject,
+                                              s->object->get_obj());
+      if (session_policy_res == Effect::Deny) {
+          return -EACCES;
+      }
+      if (princ_type == rgw::IAM::PolicyPrincipal::Role) {
+        //Intersection of session policy and identity policy plus intersection of session policy and bucket policy
+        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) ||
+            (session_policy_res == Effect::Allow && e == Effect::Allow)) {
+          return 0;
+        }
+      } else if (princ_type == rgw::IAM::PolicyPrincipal::Session) {
+        //Intersection of session policy and identity policy plus bucket policy
+        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) || e == Effect::Allow) {
+          return 0;
+        }
+      } else if (princ_type == rgw::IAM::PolicyPrincipal::Other) {// there was no match in the bucket policy
+        if (session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) {
+          return 0;
+        }
+      }
       return -EACCES;
-    } else if (usr_policy_res == Effect::Allow) {
+    }
+    if (e == Effect::Allow || identity_policy_res == Effect::Allow) {
       return 0;
     }
   }
@@ -6195,27 +6355,56 @@ void RGWCompleteMultipart::complete()
 
 int RGWAbortMultipart::verify_permission(optional_yield y)
 {
-  if (s->iam_policy || ! s->iam_user_policies.empty()) {
-    auto usr_policy_res = eval_user_policies(s->iam_user_policies, s->env,
+  if (s->iam_policy || ! s->iam_user_policies.empty() || !s->session_policies.empty()) {
+    auto identity_policy_res = eval_identity_or_session_policies(s->iam_user_policies, s->env,
                                               boost::none,
                                               rgw::IAM::s3AbortMultipartUpload,
                                               s->object->get_obj());
-    if (usr_policy_res == Effect::Deny) {
+    if (identity_policy_res == Effect::Deny) {
       return -EACCES;
     }
 
     rgw::IAM::Effect e = Effect::Pass;
+    rgw::IAM::PolicyPrincipal princ_type = rgw::IAM::PolicyPrincipal::Other;
     if (s->iam_policy) {
       e = s->iam_policy->eval(s->env, *s->auth.identity,
                                 rgw::IAM::s3AbortMultipartUpload,
-                                s->object->get_obj());
+                                s->object->get_obj(), princ_type);
     }
-    if (e == Effect::Allow) {
-      return 0;
-    } else if (e == Effect::Deny) {
+
+    if (e == Effect::Deny) {
       return -EACCES;
-    } else if (usr_policy_res == Effect::Allow)
+    }
+
+    if (!s->session_policies.empty()) {
+      auto session_policy_res = eval_identity_or_session_policies(s->session_policies, s->env,
+                                              boost::none,
+                                              rgw::IAM::s3PutObject,
+                                              s->object->get_obj());
+      if (session_policy_res == Effect::Deny) {
+          return -EACCES;
+      }
+      if (princ_type == rgw::IAM::PolicyPrincipal::Role) {
+        //Intersection of session policy and identity policy plus intersection of session policy and bucket policy
+        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) ||
+            (session_policy_res == Effect::Allow && e == Effect::Allow)) {
+          return 0;
+        }
+      } else if (princ_type == rgw::IAM::PolicyPrincipal::Session) {
+        //Intersection of session policy and identity policy plus bucket policy
+        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) || e == Effect::Allow) {
+          return 0;
+        }
+      } else if (princ_type == rgw::IAM::PolicyPrincipal::Other) {// there was no match in the bucket policy
+        if (session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) {
+          return 0;
+        }
+      }
+      return -EACCES;
+    }
+    if (e == Effect::Allow || identity_policy_res == Effect::Allow) {
       return 0;
+    }
   }
 
   if (!verify_bucket_permission_no_policy(this, s, RGW_PERM_WRITE)) {
@@ -6362,9 +6551,9 @@ int RGWDeleteMultiObj::verify_permission(optional_yield y)
     return op_ret;
   }
 
-  if (s->iam_policy || ! s->iam_user_policies.empty()) {
+  if (s->iam_policy || ! s->iam_user_policies.empty() || ! s->session_policies.empty()) {
     if (s->bucket->get_info().obj_lock_enabled() && bypass_governance_mode) {
-      auto r = eval_user_policies(s->iam_user_policies, s->env, boost::none,
+      auto r = eval_identity_or_session_policies(s->iam_user_policies, s->env, boost::none,
                                                rgw::IAM::s3BypassGovernanceRetention, ARN(s->bucket->get_key()));
       if (r == Effect::Deny) {
         bypass_perm = false;
@@ -6374,34 +6563,69 @@ int RGWDeleteMultiObj::verify_permission(optional_yield y)
         if (r == Effect::Deny) {
           bypass_perm = false;
         }
+      } else if (r == Effect::Pass && !s->session_policies.empty()) {
+        r = eval_identity_or_session_policies(s->session_policies, s->env, boost::none,
+                                               rgw::IAM::s3BypassGovernanceRetention, ARN(s->bucket->get_key()));
+        if (r == Effect::Deny) {
+          bypass_perm = false;
+        }
       }
     }
 
     bool not_versioned = rgw::sal::RGWObject::empty(s->object.get()) || s->object->get_instance().empty();
 
-    auto usr_policy_res = eval_user_policies(s->iam_user_policies, s->env,
+    auto identity_policy_res = eval_identity_or_session_policies(s->iam_user_policies, s->env,
                                               boost::none,
                                               not_versioned ?
                                               rgw::IAM::s3DeleteObject :
                                               rgw::IAM::s3DeleteObjectVersion,
                                               ARN(s->bucket->get_key()));
-    if (usr_policy_res == Effect::Deny) {
+    if (identity_policy_res == Effect::Deny) {
       return -EACCES;
     }
 
     rgw::IAM::Effect r = Effect::Pass;
+    rgw::IAM::PolicyPrincipal princ_type = rgw::IAM::PolicyPrincipal::Other;
     if (s->iam_policy) {
       r = s->iam_policy->eval(s->env, *s->auth.identity,
                                 not_versioned ?
                                 rgw::IAM::s3DeleteObject :
                                 rgw::IAM::s3DeleteObjectVersion,
-                                ARN(s->bucket->get_key()));
+                                ARN(s->bucket->get_key()),
+         princ_type);
     }
-    if (r == Effect::Allow)
-      return 0;
-    else if (r == Effect::Deny)
+    if (r == Effect::Deny)
       return -EACCES;
-    else if (usr_policy_res == Effect::Allow)
+
+    if (!s->session_policies.empty()) {
+      auto session_policy_res = eval_identity_or_session_policies(s->session_policies, s->env,
+                                              boost::none,
+                                              not_versioned ?
+                                              rgw::IAM::s3DeleteObject :
+                                              rgw::IAM::s3DeleteObjectVersion,
+                                              ARN(s->bucket->get_key()));
+      if (session_policy_res == Effect::Deny) {
+          return -EACCES;
+      }
+      if (princ_type == rgw::IAM::PolicyPrincipal::Role) {
+        //Intersection of session policy and identity policy plus intersection of session policy and bucket policy
+        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) ||
+            (session_policy_res == Effect::Allow && r == Effect::Allow)) {
+          return 0;
+        }
+      } else if (princ_type == rgw::IAM::PolicyPrincipal::Session) {
+        //Intersection of session policy and identity policy plus bucket policy
+        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) || r == Effect::Allow) {
+          return 0;
+        }
+      } else if (princ_type == rgw::IAM::PolicyPrincipal::Other) {// there was no match in the bucket policy
+        if (session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) {
+          return 0;
+        }
+      }
+      return -EACCES;
+    }
+    if (r == Effect::Allow || identity_policy_res == Effect::Allow)
       return 0;
   }
 
@@ -6485,30 +6709,70 @@ void RGWDeleteMultiObj::execute(optional_yield y)
         iter != multi_delete->objects.end();
         ++iter) {
     std::string version_id;
-    std::unique_ptr<rgw::sal::RGWObject> obj = bucket->get_object(*iter);
-    if (s->iam_policy || ! s->iam_user_policies.empty()) {
-      auto usr_policy_res = eval_user_policies(s->iam_user_policies, s->env,
+        std::unique_ptr<rgw::sal::RGWObject> obj = bucket->get_object(*iter);
+    if (s->iam_policy || ! s->iam_user_policies.empty() || !s->session_policies.empty()) {
+      auto identity_policy_res = eval_identity_or_session_policies(s->iam_user_policies, s->env,
                                               boost::none,
                                               iter->instance.empty() ?
                                               rgw::IAM::s3DeleteObject :
                                               rgw::IAM::s3DeleteObjectVersion,
                                               ARN(obj->get_obj()));
-      if (usr_policy_res == Effect::Deny) {
+      if (identity_policy_res == Effect::Deny) {
         send_partial_response(*iter, false, "", -EACCES);
         continue;
       }
 
       rgw::IAM::Effect e = Effect::Pass;
+      rgw::IAM::PolicyPrincipal princ_type = rgw::IAM::PolicyPrincipal::Other;
       if (s->iam_policy) {
         e = s->iam_policy->eval(s->env,
                                   *s->auth.identity,
                                   iter->instance.empty() ?
                                   rgw::IAM::s3DeleteObject :
                                   rgw::IAM::s3DeleteObjectVersion,
-                                  ARN(obj->get_obj()));
+                                  ARN(obj->get_obj()),
+           princ_type);
+      }
+      if (e == Effect::Deny) {
+        send_partial_response(*iter, false, "", -EACCES);
+             continue;
+      }
+
+      if (!s->session_policies.empty()) {
+        auto session_policy_res = eval_identity_or_session_policies(s->session_policies, s->env,
+                                                boost::none,
+                                              iter->instance.empty() ?
+                                              rgw::IAM::s3DeleteObject :
+                                              rgw::IAM::s3DeleteObjectVersion,
+                                              ARN(obj->get_obj()));
+        if (session_policy_res == Effect::Deny) {
+          send_partial_response(*iter, false, "", -EACCES);
+               continue;
+        }
+        if (princ_type == rgw::IAM::PolicyPrincipal::Role) {
+          //Intersection of session policy and identity policy plus intersection of session policy and bucket policy
+          if ((session_policy_res != Effect::Allow || identity_policy_res != Effect::Allow) &&
+              (session_policy_res != Effect::Allow || e != Effect::Allow)) {
+            send_partial_response(*iter, false, "", -EACCES);
+                 continue;
+          }
+        } else if (princ_type == rgw::IAM::PolicyPrincipal::Session) {
+          //Intersection of session policy and identity policy plus bucket policy
+          if ((session_policy_res != Effect::Allow || identity_policy_res != Effect::Allow) && e != Effect::Allow) {
+            send_partial_response(*iter, false, "", -EACCES);
+                 continue;
+          }
+        } else if (princ_type == rgw::IAM::PolicyPrincipal::Other) {// there was no match in the bucket policy
+          if (session_policy_res != Effect::Allow || identity_policy_res != Effect::Allow) {
+            send_partial_response(*iter, false, "", -EACCES);
+                 continue;
+          }
+        }
+        send_partial_response(*iter, false, "", -EACCES);
+             continue;
       }
-      if ((e == Effect::Deny) || 
-          (usr_policy_res == Effect::Pass && e == Effect::Pass && !acl_allowed)) {
+
+      if ((identity_policy_res == Effect::Pass && e == Effect::Pass && !acl_allowed)) {
              send_partial_response(*iter, false, "", -EACCES);
              continue;
       }
@@ -6603,7 +6867,7 @@ bool RGWBulkDelete::Deleter::verify_permission(RGWBucketInfo& binfo,
   /* We can use global user_acl because each BulkDelete request is allowed
    * to work on entities from a single account only. */
   return verify_bucket_permission(dpp, s, binfo.bucket, s->user_acl.get(),
-                                 &bacl, policy, s->iam_user_policies, rgw::IAM::s3DeleteBucket);
+                                 &bacl, policy, s->iam_user_policies, s->session_policies, rgw::IAM::s3DeleteBucket);
 }
 
 bool RGWBulkDelete::Deleter::delete_single(const acct_path_t& path, optional_yield y)
@@ -6962,20 +7226,47 @@ bool RGWBulkUploadOp::handle_file_verify_permission(RGWBucketInfo& binfo,
   auto policy = get_iam_policy_from_attr(s->cct, battrs, binfo.bucket.tenant);
 
   bucket_owner = bacl.get_owner();
-  if (policy || ! s->iam_user_policies.empty()) {
-    auto usr_policy_res = eval_user_policies(s->iam_user_policies, s->env,
+  if (policy || ! s->iam_user_policies.empty() || !s->session_policies.empty()) {
+    auto identity_policy_res = eval_identity_or_session_policies(s->iam_user_policies, s->env,
                                               boost::none,
                                               rgw::IAM::s3PutObject, obj);
-    if (usr_policy_res == Effect::Deny) {
+    if (identity_policy_res == Effect::Deny) {
       return false;
     }
+
+    rgw::IAM::PolicyPrincipal princ_type = rgw::IAM::PolicyPrincipal::Other;
     auto e = policy->eval(s->env, *s->auth.identity,
-                         rgw::IAM::s3PutObject, obj);
-    if (e == Effect::Allow) {
-      return true;
-    } else if (e == Effect::Deny) {
+                         rgw::IAM::s3PutObject, obj, princ_type);
+    if (e == Effect::Deny) {
+      return false;
+    }
+  
+    if (!s->session_policies.empty()) {
+      auto session_policy_res = eval_identity_or_session_policies(s->session_policies, s->env,
+                                              boost::none,
+                                              rgw::IAM::s3PutObject, obj);
+      if (session_policy_res == Effect::Deny) {
+          return false;
+      }
+      if (princ_type == rgw::IAM::PolicyPrincipal::Role) {
+        //Intersection of session policy and identity policy plus intersection of session policy and bucket policy
+        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) ||
+            (session_policy_res == Effect::Allow && e == Effect::Allow)) {
+          return true;
+        }
+      } else if (princ_type == rgw::IAM::PolicyPrincipal::Session) {
+        //Intersection of session policy and identity policy plus bucket policy
+        if ((session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) || e == Effect::Allow) {
+          return true;
+        }
+      } else if (princ_type == rgw::IAM::PolicyPrincipal::Other) {// there was no match in the bucket policy
+        if (session_policy_res == Effect::Allow && identity_policy_res == Effect::Allow) {
+          return true;
+        }
+      }
       return false;
-    } else if (usr_policy_res == Effect::Allow) {
+    }
+    if (e == Effect::Allow || identity_policy_res == Effect::Allow) {
       return true;
     }
   }
index 0970540eb197f96c469afd31740beec17808a356..46fd9a2ac4cdf7a4ce5b91db0c122df45be68a31 100644 (file)
@@ -119,11 +119,6 @@ public:
     return 0;
   }
 
-  uint32_t get_identity_type() const override {
-    abort();
-    return 0;
-  }
-
   string get_acct_name() const override {
     abort();
     return 0;
@@ -144,6 +139,10 @@ public:
     }
     return ids.find(id) != ids.end() || ids.find(Principal::wildcard()) != ids.end();
   }
+
+  uint32_t get_identity_type() const override {
+    return TYPE_RGW;
+  }
 };
 
 class PolicyTest : public ::testing::Test {