]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: Add is_identity to AuthApplier class
authorAdam C. Emerson <aemerson@redhat.com>
Mon, 13 Feb 2017 21:53:18 +0000 (16:53 -0500)
committerAdam C. Emerson <aemerson@redhat.com>
Wed, 17 May 2017 18:22:18 +0000 (14:22 -0400)
Eventually this will allow us to match all authentication information
against all specified principals in a policy.

Right now it handles users and wildcards.

Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
src/rgw/rgw_auth.cc
src/rgw/rgw_auth.h
src/rgw/rgw_auth_filters.h
src/rgw/rgw_basic_types.h

index 6311d4b16ab323e47a1f01b840559de44bb69121..c63db0ccec53e571e079249b139fe5ad4bf293dc 100644 (file)
@@ -56,6 +56,21 @@ transform_old_authinfo(const req_state* const s)
       return id == acct_id;
     }
 
+    bool is_identity(const idset_t& ids) const override {
+      for (auto& p : ids) {
+       if (p.is_wildcard()) {
+         return true;
+       } else if (p.is_tenant() && p.get_tenant() == id.tenant) {
+         return true;
+       } else if (p.is_user() &&
+                  (p.get_tenant() == id.tenant) &&
+                  (p.get_id() == id.id)) {
+         return true;
+       }
+      }
+      return false;
+    }
+
     uint32_t get_perm_mask() const override {
       return perm_mask;
     }
@@ -291,6 +306,29 @@ bool rgw::auth::RemoteApplier::is_owner_of(const rgw_user& uid) const
   return info.acct_user == uid;
 }
 
+bool rgw::auth::RemoteApplier::is_identity(const idset_t& ids) const {
+  for (auto& id : ids) {
+    if (id.is_wildcard()) {
+      return true;
+
+      // We also need to cover cases where rgw_keystone_implicit_tenants
+      // was enabled. */
+    } else if (id.is_tenant() &&
+              (info.acct_user.tenant.empty() ?
+               info.acct_user.id :
+               info.acct_user.tenant) == id.get_tenant()) {
+      return true;
+    } else if (id.is_user() &&
+              info.acct_user.id == id.get_id() &&
+              (info.acct_user.tenant.empty() ?
+               info.acct_user.id :
+               info.acct_user.tenant) == id.get_tenant()) {
+      return true;
+    }
+  }
+  return false;
+}
+
 void rgw::auth::RemoteApplier::to_str(std::ostream& out) const
 {
   out << "rgw::auth::RemoteApplier(acct_user=" << info.acct_user
@@ -383,8 +421,23 @@ bool rgw::auth::LocalApplier::is_owner_of(const rgw_user& uid) const
   return uid == user_info.user_id;
 }
 
-void rgw::auth::LocalApplier::to_str(std::ostream& out) const
-{
+bool rgw::auth::LocalApplier::is_identity(const idset_t& ids) const {
+  for (auto& id : ids) {
+    if (id.is_wildcard()) {
+      return true;
+    } else if (id.is_tenant() &&
+              id.get_tenant() == user_info.user_id.tenant) {
+      return true;
+    } else if (id.is_user() &&
+              (id.get_tenant() == user_info.user_id.tenant) &&
+              (id.get_id() == user_info.user_id.id)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+void rgw::auth::LocalApplier::to_str(std::ostream& out) const {
   out << "rgw::auth::LocalApplier(acct_user=" << user_info.user_id
       << ", acct_name=" << user_info.display_name
       << ", subuser=" << subuser
index 8118ac150d3912a41dc89ee5994d8ae312d501c7..819a338038546d288d983b1445c4aff4fc19286c 100644 (file)
@@ -16,7 +16,6 @@
 
 #define RGW_USER_ANON_ID "anonymous"
 
-
 namespace rgw {
 namespace auth {
 
@@ -28,6 +27,7 @@ using Exception = std::system_error;
 class Identity {
 public:
   typedef std::map<std::string, int> aclspec_t;
+  using idset_t = boost::container::flat_set<Principal>;
 
   virtual ~Identity() = default;
 
@@ -64,6 +64,10 @@ public:
   }
 
   virtual void to_str(std::ostream& out) const = 0;
+
+  /* Verify whether a given identity corresponds to an identity in the
+     provided set */
+  virtual bool is_identity(const idset_t& ids) const = 0;
 };
 
 inline std::ostream& operator<<(std::ostream& out,
@@ -404,6 +408,8 @@ public:
   uint32_t get_perms_from_aclspec(const aclspec_t& aclspec) const override;
   bool is_admin_of(const rgw_user& uid) const override;
   bool is_owner_of(const rgw_user& uid) const override;
+  bool is_identity(const idset_t& ids) const override;
+
   uint32_t get_perm_mask() const override { return info.perm_mask; }
   void to_str(std::ostream& out) const override;
   void load_acct_info(RGWUserInfo& user_info) const override; /* out */
@@ -449,6 +455,7 @@ public:
   uint32_t get_perms_from_aclspec(const aclspec_t& aclspec) const override;
   bool is_admin_of(const rgw_user& uid) const override;
   bool is_owner_of(const rgw_user& uid) const override;
+  bool is_identity(const idset_t& ids) const override;
   uint32_t get_perm_mask() const override {
     return get_perm_mask(subuser, user_info);
   }
index 204a43e73f80e4bd01bebf228c30a9641643719c..78846fc28d914246419e29fb854dc9d7e9ef4eaf 100644 (file)
@@ -80,6 +80,11 @@ public:
     return get_decoratee().get_perm_mask();
   }
 
+  bool is_identity(
+    const boost::container::flat_set<Principal>& ids) const override {
+    return get_decoratee().is_identity(ids);
+  }
+
   void to_str(std::ostream& out) const override {
     get_decoratee().to_str(out);
   }
index 261b201369a1dd0598da2f52fc53dc21281faaab..4e76fa8c07e05e0b13f147aa4fe939a05cfd2a53 100644 (file)
@@ -1,3 +1,5 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
+// vim: ts=8 sw=2 smarttab
 #ifndef CEPH_RGW_BASIC_TYPES_H
 #define CEPH_RGW_BASIC_TYPES_H
 
@@ -18,6 +20,10 @@ struct rgw_user {
     : tenant(tenant),
       id(id) {
   }
+  rgw_user(std::string&& tenant, std::string&& id)
+    : tenant(std::move(tenant)),
+      id(std::move(id)) {
+  }
 
   void encode(bufferlist& bl) const {
     ENCODE_START(1, 1, bl);
@@ -100,6 +106,79 @@ struct rgw_user {
 };
 WRITE_CLASS_ENCODER(rgw_user)
 
+// Represents an identity. This is more wide-ranging than a
+// 'User'. Its purposes is to be matched against by an
+// IdentityApplier. The internal representation will doubtless change as
+// more types are added. We may want to expose the type enum and make
+// the member public so people can switch/case on it.
+
+namespace rgw {
+namespace auth {
+class Principal {
+  enum types { User, Role, Tenant, Wildcard };
+  types t;
+  rgw_user u;
+
+  Principal(types t)
+    : t(t) {}
+
+  Principal(types t, std::string&& n, std::string i)
+    : t(t), u(std::move(n), std::move(i)) {}
+
+public:
+
+  static Principal wildcard() {
+    return Principal(Wildcard);
+  }
+
+  static Principal user(std::string&& t, std::string&& u) {
+    return Principal(User, std::move(t), std::move(u));
+  }
+
+  static Principal role(std::string&& t, std::string&& u) {
+    return Principal(Role, std::move(t), std::move(u));
+  }
+
+  static Principal tenant(std::string&& t) {
+    return Principal(Tenant, std::move(t), {});
+  }
+
+  bool is_wildcard() const {
+    return t == Wildcard;
+  }
+
+  bool is_user() const {
+    return t == User;
+  }
+
+  bool is_role() const {
+    return t == Role;
+  }
+
+  bool is_tenant() const {
+    return t == Tenant;
+  }
+
+  const std::string& get_tenant() const {
+    ceph_assert(t != Wildcard);
+    return u.tenant;
+  }
+
+  const std::string& get_id() const {
+    ceph_assert(t != Wildcard && t != Tenant);
+    return u.id;
+  }
+
+  bool operator ==(const Principal& o) const {
+    return (t == o.t) && (u == o.u);
+  }
+
+  bool operator <(const Principal& o) const {
+    return (t < o.t) || ((t == o.t) && (u < o.u));
+  }
+};
+}
+}
 
 class JSONObj;