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