From 56167d19f8ef1f718c7f6660739db08cc7346c05 Mon Sep 17 00:00:00 2001 From: "Adam C. Emerson" Date: Mon, 13 Feb 2017 16:53:18 -0500 Subject: [PATCH] rgw: Add is_identity to AuthApplier class 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 --- src/rgw/rgw_auth.cc | 57 ++++++++++++++++++++++++++- src/rgw/rgw_auth.h | 9 ++++- src/rgw/rgw_auth_filters.h | 5 +++ src/rgw/rgw_basic_types.h | 79 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 147 insertions(+), 3 deletions(-) diff --git a/src/rgw/rgw_auth.cc b/src/rgw/rgw_auth.cc index 6311d4b16ab32..c63db0ccec53e 100644 --- a/src/rgw/rgw_auth.cc +++ b/src/rgw/rgw_auth.cc @@ -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 diff --git a/src/rgw/rgw_auth.h b/src/rgw/rgw_auth.h index 8118ac150d391..819a338038546 100644 --- a/src/rgw/rgw_auth.h +++ b/src/rgw/rgw_auth.h @@ -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 aclspec_t; + using idset_t = boost::container::flat_set; 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); } diff --git a/src/rgw/rgw_auth_filters.h b/src/rgw/rgw_auth_filters.h index 204a43e73f80e..78846fc28d914 100644 --- a/src/rgw/rgw_auth_filters.h +++ b/src/rgw/rgw_auth_filters.h @@ -80,6 +80,11 @@ public: return get_decoratee().get_perm_mask(); } + bool is_identity( + const boost::container::flat_set& ids) const override { + return get_decoratee().is_identity(ids); + } + void to_str(std::ostream& out) const override { get_decoratee().to_str(out); } diff --git a/src/rgw/rgw_basic_types.h b/src/rgw/rgw_basic_types.h index 261b201369a1d..4e76fa8c07e05 100644 --- a/src/rgw/rgw_basic_types.h +++ b/src/rgw/rgw_basic_types.h @@ -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; -- 2.39.5