]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_auth_filters.h
import quincy beta 17.1.0
[ceph.git] / ceph / src / rgw / rgw_auth_filters.h
CommitLineData
7c673cae 1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
9f95a23c 2// vim: ts=8 sw=2 smarttab ft=cpp
7c673cae
FG
3
4#ifndef CEPH_RGW_AUTH_FILTERS_H
5#define CEPH_RGW_AUTH_FILTERS_H
6
7#include <type_traits>
8
9#include <boost/logic/tribool.hpp>
10#include <boost/optional.hpp>
11
f67539c2 12#include "rgw_service.h"
7c673cae
FG
13#include "rgw_common.h"
14#include "rgw_auth.h"
f67539c2 15#include "rgw_user.h"
7c673cae
FG
16
17namespace rgw {
18namespace auth {
19
20/* Abstract decorator over any implementation of rgw::auth::IdentityApplier
21 * which could be provided both as a pointer-to-object or the object itself. */
22template <typename DecorateeT>
23class DecoratedApplier : public rgw::auth::IdentityApplier {
24 typedef typename std::remove_pointer<DecorateeT>::type DerefedDecorateeT;
25
26 static_assert(std::is_base_of<rgw::auth::IdentityApplier,
27 DerefedDecorateeT>::value,
28 "DecorateeT must be a subclass of rgw::auth::IdentityApplier");
29
30 DecorateeT decoratee;
31
32 /* There is an indirection layer over accessing decoratee to share the same
33 * code base between dynamic and static decorators. The difference is about
34 * what we store internally: pointer to a decorated object versus the whole
35 * object itself. Googling for "SFINAE" can help to understand the code. */
36 template <typename T = void,
37 typename std::enable_if<
38 std::is_pointer<DecorateeT>::value, T>::type* = nullptr>
39 DerefedDecorateeT& get_decoratee() {
40 return *decoratee;
41 }
42
43 template <typename T = void,
44 typename std::enable_if<
45 ! std::is_pointer<DecorateeT>::value, T>::type* = nullptr>
46 DerefedDecorateeT& get_decoratee() {
47 return decoratee;
48 }
49
50 template <typename T = void,
51 typename std::enable_if<
52 std::is_pointer<DecorateeT>::value, T>::type* = nullptr>
53 const DerefedDecorateeT& get_decoratee() const {
54 return *decoratee;
55 }
56
57 template <typename T = void,
58 typename std::enable_if<
59 ! std::is_pointer<DecorateeT>::value, T>::type* = nullptr>
60 const DerefedDecorateeT& get_decoratee() const {
61 return decoratee;
62 }
63
64public:
11fdf7f2 65 explicit DecoratedApplier(DecorateeT&& decoratee)
7c673cae
FG
66 : decoratee(std::forward<DecorateeT>(decoratee)) {
67 }
68
11fdf7f2
TL
69 uint32_t get_perms_from_aclspec(const DoutPrefixProvider* dpp, const aclspec_t& aclspec) const override {
70 return get_decoratee().get_perms_from_aclspec(dpp, aclspec);
7c673cae
FG
71 }
72
73 bool is_admin_of(const rgw_user& uid) const override {
74 return get_decoratee().is_admin_of(uid);
75 }
76
77 bool is_owner_of(const rgw_user& uid) const override {
78 return get_decoratee().is_owner_of(uid);
79 }
80
f91f0fd5
TL
81 bool is_anonymous() const override {
82 return get_decoratee().is_anonymous();
83 }
84
7c673cae
FG
85 uint32_t get_perm_mask() const override {
86 return get_decoratee().get_perm_mask();
87 }
88
11fdf7f2
TL
89 uint32_t get_identity_type() const override {
90 return get_decoratee().get_identity_type();
91 }
92
20effc67 93 std::string get_acct_name() const override {
11fdf7f2
TL
94 return get_decoratee().get_acct_name();
95 }
96
20effc67 97 std::string get_subuser() const override {
f6b5b4d7
TL
98 return get_decoratee().get_subuser();
99 }
100
31f18b77
FG
101 bool is_identity(
102 const boost::container::flat_set<Principal>& ids) const override {
103 return get_decoratee().is_identity(ids);
104 }
105
7c673cae
FG
106 void to_str(std::ostream& out) const override {
107 get_decoratee().to_str(out);
108 }
109
20effc67 110 std::string get_role_tenant() const override { /* in/out */
f67539c2
TL
111 return get_decoratee().get_role_tenant();
112 }
113
11fdf7f2
TL
114 void load_acct_info(const DoutPrefixProvider* dpp, RGWUserInfo& user_info) const override { /* out */
115 return get_decoratee().load_acct_info(dpp, user_info);
7c673cae
FG
116 }
117
11fdf7f2
TL
118 void modify_request_state(const DoutPrefixProvider* dpp, req_state * s) const override { /* in/out */
119 return get_decoratee().modify_request_state(dpp, s);
7c673cae
FG
120 }
121};
122
123
124template <typename T>
125class ThirdPartyAccountApplier : public DecoratedApplier<T> {
20effc67 126 rgw::sal::Store* store;
7c673cae
FG
127 const rgw_user acct_user_override;
128
129public:
130 /* A value representing situations where there is no requested account
131 * override. In other words, acct_user_override will be equal to this
132 * constant where the request isn't a cross-tenant one. */
133 static const rgw_user UNKNOWN_ACCT;
134
135 template <typename U>
20effc67 136 ThirdPartyAccountApplier(rgw::sal::Store* store,
11fdf7f2 137 const rgw_user &acct_user_override,
7c673cae
FG
138 U&& decoratee)
139 : DecoratedApplier<T>(std::move(decoratee)),
20effc67 140 store(store),
7c673cae
FG
141 acct_user_override(acct_user_override) {
142 }
143
144 void to_str(std::ostream& out) const override;
11fdf7f2 145 void load_acct_info(const DoutPrefixProvider* dpp, RGWUserInfo& user_info) const override; /* out */
7c673cae
FG
146};
147
148/* static declaration: UNKNOWN_ACCT will be an empty rgw_user that is a result
149 * of the default construction. */
150template <typename T>
151const rgw_user ThirdPartyAccountApplier<T>::UNKNOWN_ACCT;
152
153template <typename T>
154void ThirdPartyAccountApplier<T>::to_str(std::ostream& out) const
155{
156 out << "rgw::auth::ThirdPartyAccountApplier(" + acct_user_override.to_str() + ")"
157 << " -> ";
158 DecoratedApplier<T>::to_str(out);
159}
160
161template <typename T>
11fdf7f2 162void ThirdPartyAccountApplier<T>::load_acct_info(const DoutPrefixProvider* dpp, RGWUserInfo& user_info) const
7c673cae
FG
163{
164 if (UNKNOWN_ACCT == acct_user_override) {
165 /* There is no override specified by the upper layer. This means that we'll
166 * load the account owned by the authenticated identity (aka auth_user). */
11fdf7f2 167 DecoratedApplier<T>::load_acct_info(dpp, user_info);
7c673cae
FG
168 } else if (DecoratedApplier<T>::is_owner_of(acct_user_override)) {
169 /* The override has been specified but the account belongs to the authenticated
170 * identity. We may safely forward the call to a next stage. */
11fdf7f2 171 DecoratedApplier<T>::load_acct_info(dpp, user_info);
f91f0fd5
TL
172 } else if (this->is_anonymous()) {
173 /* If the user was authed by the anonymous engine then scope the ANON user
174 * to the correct tenant */
175 if (acct_user_override.tenant.empty())
176 user_info.user_id = rgw_user(acct_user_override.id, RGW_USER_ANON_ID);
177 else
178 user_info.user_id = rgw_user(acct_user_override.tenant, RGW_USER_ANON_ID);
7c673cae
FG
179 } else {
180 /* Compatibility mechanism for multi-tenancy. For more details refer to
181 * load_acct_info method of rgw::auth::RemoteApplier. */
20effc67
TL
182 std::unique_ptr<rgw::sal::User> user;
183
7c673cae
FG
184 if (acct_user_override.tenant.empty()) {
185 const rgw_user tenanted_uid(acct_user_override.id, acct_user_override.id);
20effc67 186 user = store->get_user(tenanted_uid);
7c673cae 187
20effc67
TL
188 if (user->load_user(dpp, null_yield) >= 0) {
189 user_info = user->get_info();
7c673cae
FG
190 /* Succeeded. */
191 return;
192 }
193 }
194
20effc67
TL
195 user = store->get_user(acct_user_override);
196 const int ret = user->load_user(dpp, null_yield);
7c673cae
FG
197 if (ret < 0) {
198 /* We aren't trying to recover from ENOENT here. It's supposed that creating
199 * someone else's account isn't a thing we want to support in this filter. */
200 if (ret == -ENOENT) {
201 throw -EACCES;
202 } else {
203 throw ret;
204 }
205 }
20effc67 206 user_info = user->get_info();
7c673cae
FG
207 }
208}
209
210template <typename T> static inline
20effc67 211ThirdPartyAccountApplier<T> add_3rdparty(rgw::sal::Store* store,
11fdf7f2 212 const rgw_user &acct_user_override,
7c673cae 213 T&& t) {
20effc67 214 return ThirdPartyAccountApplier<T>(store, acct_user_override,
7c673cae
FG
215 std::forward<T>(t));
216}
217
218
219template <typename T>
220class SysReqApplier : public DecoratedApplier<T> {
221 CephContext* const cct;
20effc67 222 rgw::sal::Store* store;
7c673cae
FG
223 const RGWHTTPArgs& args;
224 mutable boost::tribool is_system;
225
226public:
227 template <typename U>
228 SysReqApplier(CephContext* const cct,
20effc67 229 rgw::sal::Store* store,
7c673cae
FG
230 const req_state* const s,
231 U&& decoratee)
232 : DecoratedApplier<T>(std::forward<T>(decoratee)),
233 cct(cct),
20effc67 234 store(store),
7c673cae
FG
235 args(s->info.args),
236 is_system(boost::logic::indeterminate) {
237 }
238
239 void to_str(std::ostream& out) const override;
11fdf7f2
TL
240 void load_acct_info(const DoutPrefixProvider* dpp, RGWUserInfo& user_info) const override; /* out */
241 void modify_request_state(const DoutPrefixProvider* dpp, req_state* s) const override; /* in/out */
7c673cae
FG
242};
243
244template <typename T>
245void SysReqApplier<T>::to_str(std::ostream& out) const
246{
247 out << "rgw::auth::SysReqApplier" << " -> ";
248 DecoratedApplier<T>::to_str(out);
249}
250
251template <typename T>
11fdf7f2 252void SysReqApplier<T>::load_acct_info(const DoutPrefixProvider* dpp, RGWUserInfo& user_info) const
7c673cae 253{
11fdf7f2 254 DecoratedApplier<T>::load_acct_info(dpp, user_info);
7c673cae
FG
255 is_system = user_info.system;
256
257 if (is_system) {
11fdf7f2 258 //ldpp_dout(dpp, 20) << "system request" << dendl;
7c673cae
FG
259
260 rgw_user effective_uid(args.sys_get(RGW_SYS_PARAM_PREFIX "uid"));
261 if (! effective_uid.empty()) {
262 /* We aren't writing directly to user_info for consistency and security
263 * reasons. rgw_get_user_info_by_uid doesn't trigger the operator=() but
264 * calls ::decode instead. */
20effc67
TL
265 std::unique_ptr<rgw::sal::User> user = store->get_user(effective_uid);
266 if (user->load_user(dpp, null_yield) < 0) {
11fdf7f2 267 //ldpp_dout(dpp, 0) << "User lookup failed!" << dendl;
7c673cae
FG
268 throw -EACCES;
269 }
20effc67 270 user_info = user->get_info();
7c673cae
FG
271 }
272 }
273}
274
275template <typename T>
11fdf7f2 276void SysReqApplier<T>::modify_request_state(const DoutPrefixProvider* dpp, req_state* const s) const
7c673cae
FG
277{
278 if (boost::logic::indeterminate(is_system)) {
279 RGWUserInfo unused_info;
11fdf7f2 280 load_acct_info(dpp, unused_info);
7c673cae
FG
281 }
282
283 if (is_system) {
284 s->info.args.set_system();
285 s->system_request = true;
286 }
11fdf7f2 287 DecoratedApplier<T>::modify_request_state(dpp, s);
7c673cae
FG
288}
289
290template <typename T> static inline
291SysReqApplier<T> add_sysreq(CephContext* const cct,
20effc67 292 rgw::sal::Store* store,
7c673cae
FG
293 const req_state* const s,
294 T&& t) {
20effc67 295 return SysReqApplier<T>(cct, store, s, std::forward<T>(t));
7c673cae
FG
296}
297
298} /* namespace auth */
299} /* namespace rgw */
300
301#endif /* CEPH_RGW_AUTH_FILTERS_H */