]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
rgw: api to check bucket and object permissions without need for req_state
authorYehuda Sadeh <yehuda@redhat.com>
Fri, 22 Nov 2019 23:31:55 +0000 (15:31 -0800)
committerYehuda Sadeh <yehuda@redhat.com>
Tue, 28 Jan 2020 18:20:39 +0000 (10:20 -0800)
Signed-off-by: Yehuda Sadeh <yehuda@redhat.com>
src/rgw/rgw_common.cc
src/rgw/rgw_common.h

index 327f4f91116dd531ee50ecc7dc9e96bee5cd5f8f..34063bfff68e4a856d2fbd1b9584119197be0d44 100644 (file)
@@ -994,7 +994,39 @@ bool rgw_transport_is_secure(CephContext *cct, const RGWEnv& env)
   return false;
 }
 
+
 namespace {
+
+struct perm_state_from_req_state : public perm_state_base {
+  req_state * const s;
+  perm_state_from_req_state(req_state * const _s) : perm_state_base(_s->cct,
+                                                                    _s->env,
+                                                                    _s->auth.identity.get(),
+                                                                    _s->bucket_info,
+                                                                    _s->perm_mask,
+                                                                    _s->defer_to_bucket_acls), s(_s) {}
+  std::optional<bool> get_request_payer() const override {
+    const char *request_payer = s->info.env->get("HTTP_X_AMZ_REQUEST_PAYER");
+    if (!request_payer) {
+      bool exists;
+      request_payer = s->info.args.get("x-amz-request-payer", &exists).c_str();
+      if (!exists) {
+        return false;
+      }
+    }
+
+    if (strcasecmp(request_payer, "requester") == 0) {
+      return true;
+    }
+
+    return std::nullopt;
+  }
+
+  const char *get_referer() const override {
+    return s->info.env->get("HTTP_REFERER");
+  }
+};
+
 Effect eval_or_pass(const boost::optional<Policy>& policy,
                    const rgw::IAM::Environment& env,
                    boost::optional<const rgw::auth::Identity&> id,
@@ -1026,7 +1058,7 @@ Effect eval_user_policies(const vector<Policy>& user_policies,
 }
 
 bool verify_user_permission(const DoutPrefixProvider* dpp,
-                            struct req_state * const s,
+                            perm_state_base * const s,
                             RGWAccessControlPolicy * const user_acl,
                             const vector<rgw::IAM::Policy>& user_policies,
                             const rgw::ARN& res,
@@ -1050,11 +1082,12 @@ bool verify_user_permission(const DoutPrefixProvider* dpp,
   return false;
 }
 
-bool verify_user_permission_no_policy(const DoutPrefixProvider* dpp, struct req_state * const s,
-                            RGWAccessControlPolicy * const user_acl,
-                            const int perm)
+bool verify_user_permission_no_policy(const DoutPrefixProvider* dpp,
+                                      struct perm_state_base * const s,
+                                      RGWAccessControlPolicy * const user_acl,
+                                      const int perm)
 {
-  if (s->auth.identity->get_identity_type() == TYPE_ROLE)
+  if (s->identity->get_identity_type() == TYPE_ROLE)
     return false;
 
   /* S3 doesn't support account ACLs. */
@@ -1064,7 +1097,7 @@ bool verify_user_permission_no_policy(const DoutPrefixProvider* dpp, struct req_
   if ((perm & (int)s->perm_mask) != perm)
     return false;
 
-  return user_acl->verify_permission(dpp, *s->auth.identity, perm, perm);
+  return user_acl->verify_permission(dpp, *s->identity, perm, perm);
 }
 
 bool verify_user_permission(const DoutPrefixProvider* dpp,
@@ -1072,46 +1105,40 @@ bool verify_user_permission(const DoutPrefixProvider* dpp,
                             const rgw::ARN& res,
                             const uint64_t op)
 {
-  return verify_user_permission(dpp, s, s->user_acl.get(), s->iam_user_policies, res, op);
+  perm_state_from_req_state ps(s);
+  return verify_user_permission(dpp, &ps, s->user_acl.get(), s->iam_user_policies, res, op);
 }
 
 bool verify_user_permission_no_policy(const DoutPrefixProvider* dpp, 
                                       struct req_state * const s,
                                       const int perm)
 {
-  return verify_user_permission_no_policy(dpp, s, s->user_acl.get(), perm);
+  perm_state_from_req_state ps(s);
+  return verify_user_permission_no_policy(dpp, &ps, s->user_acl.get(), perm);
 }
 
-bool verify_requester_payer_permission(struct req_state *s)
+bool verify_requester_payer_permission(struct perm_state_base *s)
 {
   if (!s->bucket_info.requester_pays)
     return true;
 
-  if (s->auth.identity->is_owner_of(s->bucket_info.owner))
+  if (s->identity->is_owner_of(s->bucket_info.owner))
     return true;
   
-  if (s->auth.identity->is_anonymous()) {
+  if (s->identity->is_anonymous()) {
     return false;
   }
 
-  const char *request_payer = s->info.env->get("HTTP_X_AMZ_REQUEST_PAYER");
-  if (!request_payer) {
-    bool exists;
-    request_payer = s->info.args.get("x-amz-request-payer", &exists).c_str();
-    if (!exists) {
-      return false;
-    }
-  }
-
-  if (strcasecmp(request_payer, "requester") == 0) {
-    return true;
+  auto request_payer = s->get_request_payer();
+  if (request_payer) {
+    return *request_payer;
   }
 
   return false;
 }
 
 bool verify_bucket_permission(const DoutPrefixProvider* dpp,
-                              struct req_state * const s,
+                              struct perm_state_base * const s,
                              const rgw_bucket& bucket,
                               RGWAccessControlPolicy * const user_acl,
                               RGWAccessControlPolicy * const bucket_acl,
@@ -1126,7 +1153,7 @@ bool verify_bucket_permission(const DoutPrefixProvider* dpp,
   if (usr_policy_res == Effect::Deny)
     return false;
 
-  auto r = eval_or_pass(bucket_policy, s->env, *s->auth.identity,
+  auto r = eval_or_pass(bucket_policy, s->env, *s->identity,
                        op, ARN(bucket));
   if (r == Effect::Allow)
     // It looks like S3 ACLs only GRANT permissions rather than
@@ -1142,7 +1169,23 @@ bool verify_bucket_permission(const DoutPrefixProvider* dpp,
   return verify_bucket_permission_no_policy(dpp, s, user_acl, bucket_acl, perm);
 }
 
-bool verify_bucket_permission_no_policy(const DoutPrefixProvider* dpp, struct req_state * const s,
+bool verify_bucket_permission(const DoutPrefixProvider* dpp,
+                              struct req_state * const s,
+                             const rgw_bucket& bucket,
+                              RGWAccessControlPolicy * const user_acl,
+                              RGWAccessControlPolicy * const bucket_acl,
+                             const boost::optional<Policy>& bucket_policy,
+                              const vector<Policy>& user_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);
+}
+
+bool verify_bucket_permission_no_policy(const DoutPrefixProvider* dpp, struct perm_state_base * const s,
                                        RGWAccessControlPolicy * const user_acl,
                                        RGWAccessControlPolicy * const bucket_acl,
                                        const int perm)
@@ -1153,23 +1196,38 @@ bool verify_bucket_permission_no_policy(const DoutPrefixProvider* dpp, struct re
   if ((perm & (int)s->perm_mask) != perm)
     return false;
 
-  if (bucket_acl->verify_permission(dpp, *s->auth.identity, perm, perm,
-                                    s->info.env->get("HTTP_REFERER")))
+  if (bucket_acl->verify_permission(dpp, *s->identity, perm, perm,
+                                    s->get_referer()))
     return true;
 
   if (!user_acl)
     return false;
 
-  return user_acl->verify_permission(dpp, *s->auth.identity, perm, perm);
+  return user_acl->verify_permission(dpp, *s->identity, perm, perm);
+}
+
+bool verify_bucket_permission_no_policy(const DoutPrefixProvider* dpp, struct req_state * const s,
+                                       RGWAccessControlPolicy * const user_acl,
+                                       RGWAccessControlPolicy * const bucket_acl,
+                                       const int perm)
+{
+  perm_state_from_req_state ps(s);
+  return verify_bucket_permission_no_policy(dpp,
+                                            &ps,
+                                            user_acl,
+                                            bucket_acl,
+                                            perm);
 }
 
 bool verify_bucket_permission_no_policy(const DoutPrefixProvider* dpp, struct req_state * const s, const int perm)
 {
-  if (!verify_requester_payer_permission(s))
+  perm_state_from_req_state ps(s);
+
+  if (!verify_requester_payer_permission(&ps))
     return false;
 
   return verify_bucket_permission_no_policy(dpp,
-                                            s,
+                                            &ps,
                                             s->user_acl.get(),
                                             s->bucket_acl.get(),
                                             perm);
@@ -1177,8 +1235,10 @@ bool verify_bucket_permission_no_policy(const DoutPrefixProvider* dpp, struct re
 
 bool verify_bucket_permission(const DoutPrefixProvider* dpp, struct req_state * const s, const uint64_t op)
 {
+  perm_state_from_req_state ps(s);
+
   return verify_bucket_permission(dpp, 
-                                  s,
+                                  &ps,
                                   s->bucket,
                                   s->user_acl.get(),
                                   s->bucket_acl.get(),
@@ -1207,7 +1267,7 @@ int verify_bucket_owner_or_policy(struct req_state* const s,
 
 
 static inline bool check_deferred_bucket_perms(const DoutPrefixProvider* dpp,
-                                               struct req_state * const s,
+                                               struct perm_state_base * const s,
                                               const rgw_bucket& bucket,
                                               RGWAccessControlPolicy * const user_acl,
                                               RGWAccessControlPolicy * const bucket_acl,
@@ -1221,7 +1281,7 @@ static inline bool check_deferred_bucket_perms(const DoutPrefixProvider* dpp,
 }
 
 static inline bool check_deferred_bucket_only_acl(const DoutPrefixProvider* dpp,
-                                                  struct req_state * const s,
+                                                  struct perm_state_base * const s,
                                                  RGWAccessControlPolicy * const user_acl,
                                                  RGWAccessControlPolicy * const bucket_acl,
                                                  const uint8_t deferred_check,
@@ -1231,7 +1291,7 @@ static inline bool check_deferred_bucket_only_acl(const DoutPrefixProvider* dpp,
          && verify_bucket_permission_no_policy(dpp, s, user_acl, bucket_acl, perm));
 }
 
-bool verify_object_permission(const DoutPrefixProvider* dpp, struct req_state * const s,
+bool verify_object_permission(const DoutPrefixProvider* dpp, struct perm_state_base * const s,
                              const rgw_obj& obj,
                               RGWAccessControlPolicy * const user_acl,
                               RGWAccessControlPolicy * const bucket_acl,
@@ -1247,7 +1307,7 @@ bool verify_object_permission(const DoutPrefixProvider* dpp, struct req_state *
   if (usr_policy_res == Effect::Deny)
     return false;
 
-  auto r = eval_or_pass(bucket_policy, s->env, *s->auth.identity, op, ARN(obj));
+  auto r = eval_or_pass(bucket_policy, s->env, *s->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.
@@ -1270,7 +1330,7 @@ bool verify_object_permission(const DoutPrefixProvider* dpp, struct req_state *
     return false;
   }
 
-  bool ret = object_acl->verify_permission(dpp, *s->auth.identity, s->perm_mask, perm);
+  bool ret = object_acl->verify_permission(dpp, *s->identity, s->perm_mask, perm);
   if (ret) {
     return true;
   }
@@ -1292,18 +1352,34 @@ bool verify_object_permission(const DoutPrefixProvider* dpp, struct req_state *
 
   /* we already verified the user mask above, so we pass swift_perm as the mask here,
      otherwise the mask might not cover the swift permissions bits */
-  if (bucket_acl->verify_permission(dpp, *s->auth.identity, swift_perm, swift_perm,
-                                    s->info.env->get("HTTP_REFERER")))
+  if (bucket_acl->verify_permission(dpp, *s->identity, swift_perm, swift_perm,
+                                    s->get_referer()))
     return true;
 
   if (!user_acl)
     return false;
 
-  return user_acl->verify_permission(dpp, *s->auth.identity, swift_perm, swift_perm);
+  return user_acl->verify_permission(dpp, *s->identity, swift_perm, swift_perm);
+}
+
+bool verify_object_permission(const DoutPrefixProvider* dpp, struct req_state * const s,
+                             const rgw_obj& obj,
+                              RGWAccessControlPolicy * const user_acl,
+                              RGWAccessControlPolicy * const bucket_acl,
+                              RGWAccessControlPolicy * const object_acl,
+                              const boost::optional<Policy>& bucket_policy,
+                              const vector<Policy>& user_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);
 }
 
 bool verify_object_permission_no_policy(const DoutPrefixProvider* dpp,
-                                        struct req_state * const s,
+                                        struct perm_state_base * const s,
                                        RGWAccessControlPolicy * const user_acl,
                                        RGWAccessControlPolicy * const bucket_acl,
                                        RGWAccessControlPolicy * const object_acl,
@@ -1318,7 +1394,7 @@ bool verify_object_permission_no_policy(const DoutPrefixProvider* dpp,
     return false;
   }
 
-  bool ret = object_acl->verify_permission(dpp, *s->auth.identity, s->perm_mask, perm);
+  bool ret = object_acl->verify_permission(dpp, *s->identity, s->perm_mask, perm);
   if (ret) {
     return true;
   }
@@ -1340,23 +1416,25 @@ bool verify_object_permission_no_policy(const DoutPrefixProvider* dpp,
 
   /* we already verified the user mask above, so we pass swift_perm as the mask here,
      otherwise the mask might not cover the swift permissions bits */
-  if (bucket_acl->verify_permission(dpp, *s->auth.identity, swift_perm, swift_perm,
-                                    s->info.env->get("HTTP_REFERER")))
+  if (bucket_acl->verify_permission(dpp, *s->identity, swift_perm, swift_perm,
+                                    s->get_referer()))
     return true;
 
   if (!user_acl)
     return false;
 
-  return user_acl->verify_permission(dpp, *s->auth.identity, swift_perm, swift_perm);
+  return user_acl->verify_permission(dpp, *s->identity, swift_perm, swift_perm);
 }
 
 bool verify_object_permission_no_policy(const DoutPrefixProvider* dpp, struct req_state *s, int perm)
 {
-  if (!verify_requester_payer_permission(s))
+  perm_state_from_req_state ps(s);
+
+  if (!verify_requester_payer_permission(&ps))
     return false;
 
   return verify_object_permission_no_policy(dpp,
-                                            s,
+                                            &ps,
                                             s->user_acl.get(),
                                             s->bucket_acl.get(),
                                             s->object_acl.get(),
@@ -1365,8 +1443,10 @@ bool verify_object_permission_no_policy(const DoutPrefixProvider* dpp, struct re
 
 bool verify_object_permission(const DoutPrefixProvider* dpp, struct req_state *s, uint64_t op)
 {
+  perm_state_from_req_state ps(s);
+
   return verify_object_permission(dpp,
-                                  s,
+                                  &ps,
                                   rgw_obj(s->bucket, s->object),
                                   s->user_acl.get(),
                                   s->bucket_acl.get(),
index 7316a0465ff4e9a4d9524ab6eee7d7d518cb20d6..d11f6a81acfa4cae807ef6bc61b3707f241c0ae0 100644 (file)
@@ -2427,6 +2427,75 @@ extern void rgw_to_iso8601(const real_time& t, char *dest, int buf_size);
 extern void rgw_to_iso8601(const real_time& t, string *dest);
 extern std::string rgw_to_asctime(const utime_t& t);
 
+struct perm_state_base {
+  CephContext *cct;
+  const rgw::IAM::Environment& env;
+  rgw::auth::Identity *identity;
+  const RGWBucketInfo& bucket_info;
+  int perm_mask;
+  bool defer_to_bucket_acls;
+
+  perm_state_base(CephContext *_cct,
+                  const rgw::IAM::Environment& _env,
+                  rgw::auth::Identity *_identity,
+                  const RGWBucketInfo& _bucket_info,
+                  int _perm_mask,
+                  bool _defer_to_bucket_acls) : cct(_cct),
+                                                env(_env),
+                                                identity(_identity),
+                                                bucket_info(_bucket_info),
+                                                perm_mask(_perm_mask),
+                                                defer_to_bucket_acls(_defer_to_bucket_acls) {}
+  virtual ~perm_state_base() {}
+
+  virtual const char *get_referer() const = 0;
+  virtual std::optional<bool> get_request_payer() const = 0;
+
+};
+
+struct perm_state : public perm_state_base {
+  const char *referer;
+  bool request_payer;
+
+  perm_state(CephContext *_cct,
+             const rgw::IAM::Environment& _env,
+             rgw::auth::Identity *_identity,
+             const RGWBucketInfo& _bucket_info,
+             int _perm_mask,
+             bool _defer_to_bucket_acls,
+             const char *_referer,
+             bool _request_payer) : perm_state_base(_cct,
+                                                    _env,
+                                                    _identity,
+                                                    _bucket_info,
+                                                    _perm_mask,
+                                                    _defer_to_bucket_acls),
+                                    referer(_referer),
+                                    request_payer(_request_payer) {}
+
+  const char *get_referer() const override {
+    return referer;
+  }
+
+  std::optional<bool> get_request_payer() const override {
+    return request_payer;
+  }
+};
+
+/** Check if the req_state's user has the necessary permissions
+ * to do the requested action  */
+bool verify_bucket_permission_no_policy(
+  const DoutPrefixProvider* dpp,
+  struct perm_state_base * const s,
+  RGWAccessControlPolicy * const user_acl,
+  RGWAccessControlPolicy * const bucket_acl,
+  const int perm);
+
+bool verify_user_permission_no_policy(const DoutPrefixProvider* dpp,
+                                      struct perm_state_base * const s,
+                                      RGWAccessControlPolicy * const user_acl,
+                                      const int perm);
+
 /** 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,