]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: Fix evaluation of bucket management permissions 19810/head
authorAdam C. Emerson <aemerson@redhat.com>
Sat, 28 Oct 2017 02:48:18 +0000 (22:48 -0400)
committerAdam C. Emerson <aemerson@redhat.com>
Fri, 5 Jan 2018 22:35:38 +0000 (17:35 -0500)
I spent some more time looking through the documentation of how work
is evaluated, and the examples on

<http://docs.aws.amazon.com/AmazonS3/latest/dev/
access-control-auth-workflow-bucket-operation.html>

Have convinced me that the behavior that was requested is more correct
than what we were doing before.

Fixes: http://tracker.ceph.com/issues/21901
Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
(cherry picked from commit 343a25aa2134b6fdddeca6c9dfbaefde2dc9c66a)

src/rgw/rgw_common.cc

index a59152858687ff6e15e21f5776b3d287a7fdeb31..1a6cbbdf7da73a7d8a06fa28c868f4c5c39498c9 100644 (file)
@@ -1123,6 +1123,19 @@ bool verify_requester_payer_permission(struct req_state *s)
   return false;
 }
 
+namespace {
+Effect eval_or_pass(const optional<Policy>& policy,
+                          const rgw::IAM::Environment& env,
+                          const rgw::auth::Identity& id,
+                          const uint64_t op,
+                          const ARN& arn) {
+  if (!policy)
+    return Effect::Pass;
+  else
+    return policy->eval(env, id, op, arn);
+}
+}
+
 bool verify_bucket_permission(struct req_state * const s,
                              const rgw_bucket& bucket,
                               RGWAccessControlPolicy * const user_acl,
@@ -1133,15 +1146,14 @@ bool verify_bucket_permission(struct req_state * const s,
   if (!verify_requester_payer_permission(s))
     return false;
 
-  if (bucket_policy) {
-    auto r = bucket_policy->eval(s->env, *s->auth.identity, op, ARN(bucket));
-    if (r == 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;
-  }
+  auto r = eval_or_pass(bucket_policy, s->env, *s->auth.identity,
+                       op, ARN(bucket));
+  if (r == 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;
 
   const auto perm = op_to_perm(op);
 
@@ -1190,18 +1202,22 @@ bool verify_bucket_permission(struct req_state * const s, const uint64_t op)
                                   op);
 }
 
+// Authorize anyone permitted by the policy 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)
 {
-  if (s->iam_policy) {
-    if (s->iam_policy->eval(s->env, *s->auth.identity, op,
-                           ARN(s->bucket)) == Effect::Allow) {
-      return 0;
-    }
-  } else if (s->auth.identity->is_owner_of(s->bucket_owner.get_id())) {
+  auto e = eval_or_pass(s->iam_policy,
+                       s->env, *s->auth.identity,
+                       op, ARN(s->bucket));
+  if (e == Effect::Allow ||
+      (e == Effect::Pass &&
+       s->auth.identity->is_owner_of(s->bucket_owner.get_id()))) {
     return 0;
+  } else {
+    return -EACCES;
   }
-  return -EACCES;
 }
 
 
@@ -1238,15 +1254,14 @@ bool verify_object_permission(struct req_state * const s,
   if (!verify_requester_payer_permission(s))
     return false;
 
-  if (bucket_policy) {
-    auto r = bucket_policy->eval(s->env, *s->auth.identity, op, ARN(obj));
-    if (r == 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;
-  }
+
+  auto r = eval_or_pass(bucket_policy, s->env, *s->auth.identity, op, ARN(obj));
+  if (r == 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;
 
   const auto perm = op_to_perm(op);