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,
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;
}
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);
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,
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 {
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,
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;
}
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,
s->object_acl.get(),
s->iam_policy,
s->iam_user_policies,
+ s->session_policies,
op);
}
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)
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
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) {
/* 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;
}
}
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;
}
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;
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;
}
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;
}
}
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;
}
}
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)) {
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;
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;
}
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;
}
/* 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)
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;
}
}