]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_auth.h
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / rgw / rgw_auth.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 3
1e59de90 4#pragma once
7c673cae
FG
5
6#include <functional>
20effc67 7#include <optional>
7c673cae
FG
8#include <ostream>
9#include <type_traits>
10#include <system_error>
11#include <utility>
12
13#include "rgw_common.h"
11fdf7f2 14#include "rgw_web_idp.h"
7c673cae
FG
15
16#define RGW_USER_ANON_ID "anonymous"
17
9f95a23c 18class RGWCtl;
2a845540 19struct rgw_log_entry;
1e59de90 20struct req_state;
9f95a23c 21
7c673cae
FG
22namespace rgw {
23namespace auth {
24
25using Exception = std::system_error;
26
27
28/* Load information about identity that will be used by RGWOp to authorize
29 * any operation that comes from an authenticated user. */
30class Identity {
31public:
32 typedef std::map<std::string, int> aclspec_t;
31f18b77 33 using idset_t = boost::container::flat_set<Principal>;
7c673cae
FG
34
35 virtual ~Identity() = default;
36
37 /* Translate the ACL provided in @aclspec into concrete permission set that
38 * can be used during the authorization phase (RGWOp::verify_permission).
39 * On error throws rgw::auth::Exception storing the reason.
40 *
41 * NOTE: an implementation is responsible for giving the real semantic to
42 * the items in @aclspec. That is, their meaning may depend on particular
43 * applier that is being used. */
11fdf7f2 44 virtual uint32_t get_perms_from_aclspec(const DoutPrefixProvider* dpp, const aclspec_t& aclspec) const = 0;
7c673cae
FG
45
46 /* Verify whether a given identity *can be treated as* an admin of rgw_user
47 * (account in Swift's terminology) specified in @uid. On error throws
48 * rgw::auth::Exception storing the reason. */
49 virtual bool is_admin_of(const rgw_user& uid) const = 0;
50
51 /* Verify whether a given identity *is* the owner of the rgw_user (account
52 * in the Swift's terminology) specified in @uid. On internal error throws
53 * rgw::auth::Exception storing the reason. */
54 virtual bool is_owner_of(const rgw_user& uid) const = 0;
55
56 /* Return the permission mask that is used to narrow down the set of
57 * operations allowed for a given identity. This method reflects the idea
58 * of subuser tied to RGWUserInfo. On error throws rgw::auth::Exception
59 * with the reason. */
60 virtual uint32_t get_perm_mask() const = 0;
61
f91f0fd5 62 virtual bool is_anonymous() const {
7c673cae
FG
63 /* If the identity owns the anonymous account (rgw_user), it's considered
64 * the anonymous identity. On error throws rgw::auth::Exception storing
65 * the reason. */
66 return is_owner_of(rgw_user(RGW_USER_ANON_ID));
67 }
68
69 virtual void to_str(std::ostream& out) const = 0;
31f18b77
FG
70
71 /* Verify whether a given identity corresponds to an identity in the
72 provided set */
73 virtual bool is_identity(const idset_t& ids) const = 0;
11fdf7f2
TL
74
75 /* Identity Type: RGW/ LDAP/ Keystone */
76 virtual uint32_t get_identity_type() const = 0;
77
78 /* Name of Account */
20effc67 79 virtual std::string get_acct_name() const = 0;
f6b5b4d7
TL
80
81 /* Subuser of Account */
20effc67 82 virtual std::string get_subuser() const = 0;
f67539c2 83
20effc67 84 virtual std::string get_role_tenant() const { return ""; }
2a845540
TL
85
86 /* write any auth-specific fields that are safe to expose in the ops log */
87 virtual void write_ops_log_entry(rgw_log_entry& entry) const {};
7c673cae
FG
88};
89
90inline std::ostream& operator<<(std::ostream& out,
91 const rgw::auth::Identity& id) {
92 id.to_str(out);
93 return out;
94}
95
96
9f95a23c
TL
97std::unique_ptr<rgw::auth::Identity>
98transform_old_authinfo(CephContext* const cct,
99 const rgw_user& auth_id,
100 const int perm_mask,
101 const bool is_admin,
102 const uint32_t type);
7c673cae
FG
103std::unique_ptr<Identity> transform_old_authinfo(const req_state* const s);
104
105
106/* Interface for classes applying changes to request state/RADOS store
107 * imposed by a particular rgw::auth::Engine.
108 *
109 * In contrast to rgw::auth::Engine, implementations of this interface
9f95a23c 110 * are allowed to handle req_state or RGWUserCtl in the read-write manner.
7c673cae
FG
111 *
112 * It's expected that most (if not all) of implementations will also
113 * conform to rgw::auth::Identity interface to provide authorization
114 * policy (ACLs, account's ownership and entitlement). */
115class IdentityApplier : public Identity {
116public:
117 typedef std::unique_ptr<IdentityApplier> aplptr_t;
118
119 virtual ~IdentityApplier() {};
120
121 /* Fill provided RGWUserInfo with information about the account that
122 * RGWOp will operate on. Errors are handled solely through exceptions.
123 *
124 * XXX: be aware that the "account" term refers to rgw_user. The naming
125 * is legacy. */
11fdf7f2 126 virtual void load_acct_info(const DoutPrefixProvider* dpp, RGWUserInfo& user_info) const = 0; /* out */
7c673cae
FG
127
128 /* Apply any changes to request state. This method will be most useful for
31f18b77 129 * TempURL of Swift API. */
11fdf7f2 130 virtual void modify_request_state(const DoutPrefixProvider* dpp, req_state* s) const {} /* in/out */
7c673cae
FG
131};
132
133
134/* Interface class for completing the two-step authentication process.
135 * Completer provides the second step - the complete() method that should
136 * be called after Engine::authenticate() but before *committing* results
137 * of an RGWOp (or sending a response in the case of non-mutating ops).
138 *
139 * The motivation driving the interface is to address those authentication
140 * schemas that require message integrity verification *without* in-memory
141 * data buffering. Typical examples are AWS Auth v4 and the auth mechanism
142 * of browser uploads facilities both in S3 and Swift APIs (see RGWPostObj).
143 * The workflow of request from the authentication point-of-view does look
144 * like following one:
145 * A. authenticate (Engine::authenticate),
146 * B. authorize (see RGWOp::verify_permissions),
147 * C. execute-prepare (init potential data modifications),
148 * D. authenticate-complete - (Completer::complete),
149 * E. execute-commit - commit the modifications from point C. */
150class Completer {
151public:
31f18b77
FG
152 /* It's expected that Completers would tend to implement many interfaces
153 * and be used not only in req_state::auth::completer. Ref counting their
11fdf7f2 154 * instances would be helpful. */
31f18b77 155 typedef std::shared_ptr<Completer> cmplptr_t;
7c673cae
FG
156
157 virtual ~Completer() = default;
158
159 /* Complete the authentication process. Return boolean indicating whether
160 * the completion succeeded. On error throws rgw::auth::Exception storing
161 * the reason. */
162 virtual bool complete() = 0;
31f18b77
FG
163
164 /* Apply any changes to request state. The initial use case was injecting
165 * the AWSv4 filter over rgw::io::RestfulClient in req_state. */
11fdf7f2 166 virtual void modify_request_state(const DoutPrefixProvider* dpp, req_state* s) = 0; /* in/out */
7c673cae
FG
167};
168
169
170/* Interface class for authentication backends (auth engines) in RadosGW.
171 *
172 * An engine is supposed only to authenticate (not authorize!) requests
173 * basing on their req_state and - if access has been granted - provide
174 * an upper layer with:
175 * - rgw::auth::IdentityApplier to commit all changes to the request state as
176 * well as to the RADOS store (creating an account, synchronizing
177 * user-related information with external databases and so on).
178 * - rgw::auth::Completer (optionally) to finish the authentication
179 * of the request. Typical use case is verifying message integrity
180 * in AWS Auth v4 and browser uploads (RGWPostObj).
181 *
182 * Both of them are supposed to be wrapped in Engine::AuthResult.
183 *
184 * The authentication process consists of two steps:
185 * - Engine::authenticate() which should be called before *initiating*
186 * any modifications to RADOS store that are related to an operation
187 * a client wants to perform (RGWOp::execute).
188 * - Completer::complete() supposed to be called, if completer has been
189 * returned, after the authenticate() step but before *committing*
190 * those modifications or sending a response (RGWOp::complete).
191 *
192 * An engine outlives both Applier and Completer. It's intended to live
193 * since RadosGW's initialization and handle multiple requests till
194 * a reconfiguration.
195 *
196 * Auth engine MUST NOT make any changes to req_state nor RADOS store.
197 * This is solely an Applier's responsibility!
198 *
199 * Separation between authentication and global state modification has
200 * been introduced because many auth engines are orthogonal to appliers
201 * and thus they can be decoupled. Additional motivation is to clearly
202 * distinguish all portions of code modifying data structures. */
203class Engine {
204public:
205 virtual ~Engine() = default;
206
207 class AuthResult {
208 struct rejection_mark_t {};
209 bool is_rejected = false;
210 int reason = 0;
211
212 std::pair<IdentityApplier::aplptr_t, Completer::cmplptr_t> result_pair;
213
11fdf7f2 214 explicit AuthResult(const int reason)
7c673cae
FG
215 : reason(reason) {
216 }
217
218 AuthResult(rejection_mark_t&&, const int reason)
219 : is_rejected(true),
220 reason(reason) {
221 }
222
223 /* Allow only the reasonable combintations - returning just Completer
224 * without accompanying IdentityApplier is strictly prohibited! */
11fdf7f2 225 explicit AuthResult(IdentityApplier::aplptr_t&& applier)
7c673cae
FG
226 : result_pair(std::move(applier), nullptr) {
227 }
228
229 AuthResult(IdentityApplier::aplptr_t&& applier,
230 Completer::cmplptr_t&& completer)
231 : result_pair(std::move(applier), std::move(completer)) {
232 }
233
234 public:
235 enum class Status {
236 /* Engine doesn't grant the access but also doesn't reject it. */
237 DENIED,
238
11fdf7f2 239 /* Engine successfully authenicated requester. */
7c673cae
FG
240 GRANTED,
241
242 /* Engine strictly indicates that a request should be rejected
243 * without trying any further engine. */
244 REJECTED
245 };
246
247 Status get_status() const {
248 if (is_rejected) {
249 return Status::REJECTED;
250 } else if (! result_pair.first) {
251 return Status::DENIED;
252 } else {
253 return Status::GRANTED;
254 }
255 }
256
257 int get_reason() const {
258 return reason;
259 }
260
261 IdentityApplier::aplptr_t get_applier() {
262 return std::move(result_pair.first);
263 }
264
265 Completer::cmplptr_t&& get_completer() {
266 return std::move(result_pair.second);
267 }
268
269 static AuthResult reject(const int reason = -EACCES) {
270 return AuthResult(rejection_mark_t(), reason);
271 }
272
273 static AuthResult deny(const int reason = -EACCES) {
274 return AuthResult(reason);
275 }
276
277 static AuthResult grant(IdentityApplier::aplptr_t&& applier) {
278 return AuthResult(std::move(applier));
279 }
280
281 static AuthResult grant(IdentityApplier::aplptr_t&& applier,
282 Completer::cmplptr_t&& completer) {
283 return AuthResult(std::move(applier), std::move(completer));
284 }
285 };
286
287 using result_t = AuthResult;
288
289 /* Get name of the auth engine. */
290 virtual const char* get_name() const noexcept = 0;
291
292 /* Throwing method for identity verification. When the check is positive
293 * an implementation should return Engine::result_t containing:
294 * - a non-null pointer to an object conforming the Applier interface.
295 * Otherwise, the authentication is treated as failed.
296 * - a (potentially null) pointer to an object conforming the Completer
297 * interface.
298 *
299 * On error throws rgw::auth::Exception containing the reason. */
f67539c2 300 virtual result_t authenticate(const DoutPrefixProvider* dpp, const req_state* s, optional_yield y) const = 0;
7c673cae
FG
301};
302
303
304/* Interface for extracting a token basing from data carried by req_state. */
305class TokenExtractor {
306public:
307 virtual ~TokenExtractor() = default;
308 virtual std::string get_token(const req_state* s) const = 0;
309};
310
311
312/* Abstract class for stacking sub-engines to expose them as a single
313 * Engine. It is responsible for ordering its sub-engines and managing
314 * fall-backs between them. Derivatee is supposed to encapsulate engine
315 * instances and add them using the add_engine() method in the order it
316 * wants to be tried during the call to authenticate().
317 *
318 * Each new Strategy should be exposed to StrategyRegistry for handling
319 * the dynamic reconfiguration. */
320class Strategy : public Engine {
321public:
322 /* Specifiers controlling what happens when an associated engine fails.
323 * The names and semantic has been borrowed mostly from libpam. */
324 enum class Control {
325 /* Failure of an engine injected with the REQUISITE specifier aborts
326 * the strategy's authentication process immediately. No other engine
327 * will be tried. */
328 REQUISITE,
329
330 /* Success of an engine injected with the SUFFICIENT specifier ends
331 * strategy's authentication process successfully. However, denying
332 * doesn't abort it -- there will be fall-back to following engine
333 * if the one that failed wasn't the last one. */
334 SUFFICIENT,
335
336 /* Like SUFFICIENT with the exception that on failure the reason code
337 * is not overridden. Instead, it's taken directly from the last tried
338 * non-FALLBACK engine. If there was no previous non-FALLBACK engine
339 * in a Strategy, then the result_t::deny(reason = -EACCES) is used. */
340 FALLBACK,
341 };
342
f67539c2 343 Engine::result_t authenticate(const DoutPrefixProvider* dpp, const req_state* s, optional_yield y) const override final;
7c673cae
FG
344
345 bool is_empty() const {
346 return auth_stack.empty();
347 }
348
f67539c2 349 static int apply(const DoutPrefixProvider* dpp, const Strategy& auth_strategy, req_state* s, optional_yield y) noexcept;
31f18b77 350
7c673cae
FG
351private:
352 /* Using the reference wrapper here to explicitly point out we are not
353 * interested in storing nulls while preserving the dynamic polymorphism. */
354 using stack_item_t = std::pair<std::reference_wrapper<const Engine>,
355 Control>;
356 std::vector<stack_item_t> auth_stack;
357
358protected:
359 void add_engine(Control ctrl_flag, const Engine& engine) noexcept;
360};
361
362
363/* A class aggregating the knowledge about all Strategies in RadosGW. It is
364 * responsible for handling the dynamic reconfiguration on e.g. realm update.
365 * The definition is in rgw/rgw_auth_registry.h,
366 *
367 * Each new Strategy should be exposed to it. */
368class StrategyRegistry;
369
11fdf7f2 370class WebIdentityApplier : public IdentityApplier {
20effc67
TL
371 std::string sub;
372 std::string iss;
373 std::string aud;
374 std::string client_id;
375 std::string user_name;
11fdf7f2
TL
376protected:
377 CephContext* const cct;
1e59de90 378 rgw::sal::Driver* driver;
20effc67
TL
379 std::string role_session;
380 std::string role_tenant;
381 std::unordered_multimap<std::string, std::string> token_claims;
382 boost::optional<std::multimap<std::string,std::string>> role_tags;
383 boost::optional<std::set<std::pair<std::string, std::string>>> principal_tags;
11fdf7f2 384
20effc67 385 std::string get_idp_url() const;
11fdf7f2 386
f67539c2
TL
387 void create_account(const DoutPrefixProvider* dpp,
388 const rgw_user& acct_user,
20effc67 389 const std::string& display_name,
f67539c2 390 RGWUserInfo& user_info) const; /* out */
28e407b8 391public:
11fdf7f2 392 WebIdentityApplier( CephContext* const cct,
1e59de90 393 rgw::sal::Driver* driver,
20effc67
TL
394 const std::string& role_session,
395 const std::string& role_tenant,
396 const std::unordered_multimap<std::string, std::string>& token_claims,
397 boost::optional<std::multimap<std::string,std::string>> role_tags,
398 boost::optional<std::set<std::pair<std::string, std::string>>> principal_tags)
399 : cct(cct),
1e59de90 400 driver(driver),
f91f0fd5 401 role_session(role_session),
f67539c2 402 role_tenant(role_tenant),
20effc67
TL
403 token_claims(token_claims),
404 role_tags(role_tags),
405 principal_tags(principal_tags) {
406 const auto& sub = token_claims.find("sub");
407 if(sub != token_claims.end()) {
408 this->sub = sub->second;
409 }
410
411 const auto& iss = token_claims.find("iss");
412 if(iss != token_claims.end()) {
413 this->iss = iss->second;
414 }
415
416 const auto& aud = token_claims.find("aud");
417 if(aud != token_claims.end()) {
418 this->aud = aud->second;
419 }
420
421 const auto& client_id = token_claims.find("client_id");
422 if(client_id != token_claims.end()) {
423 this->client_id = client_id->second;
424 } else {
425 const auto& azp = token_claims.find("azp");
426 if (azp != token_claims.end()) {
427 this->client_id = azp->second;
428 }
429 }
430
431 const auto& user_name = token_claims.find("username");
432 if(user_name != token_claims.end()) {
433 this->user_name = user_name->second;
434 } else {
435 const auto& given_username = token_claims.find("given_username");
436 if (given_username != token_claims.end()) {
437 this->user_name = given_username->second;
438 }
439 }
28e407b8 440 }
28e407b8 441
11fdf7f2
TL
442 void modify_request_state(const DoutPrefixProvider *dpp, req_state* s) const override;
443
444 uint32_t get_perms_from_aclspec(const DoutPrefixProvider* dpp, const aclspec_t& aclspec) const override {
445 return RGW_PERM_NONE;
446 }
447
448 bool is_admin_of(const rgw_user& uid) const override {
449 return false;
450 }
451
452 bool is_owner_of(const rgw_user& uid) const override {
20effc67 453 if (uid.id == this->sub && uid.tenant == role_tenant && uid.ns == "oidc") {
f67539c2
TL
454 return true;
455 }
11fdf7f2
TL
456 return false;
457 }
458
459 uint32_t get_perm_mask() const override {
460 return RGW_PERM_NONE;
461 }
462
463 void to_str(std::ostream& out) const override;
464
465 bool is_identity(const idset_t& ids) const override;
466
f67539c2
TL
467 void load_acct_info(const DoutPrefixProvider* dpp, RGWUserInfo& user_info) const override;
468
11fdf7f2
TL
469 uint32_t get_identity_type() const override {
470 return TYPE_WEB;
471 }
472
20effc67
TL
473 std::string get_acct_name() const override {
474 return this->user_name;
11fdf7f2
TL
475 }
476
20effc67 477 std::string get_subuser() const override {
f6b5b4d7
TL
478 return {};
479 }
480
11fdf7f2
TL
481 struct Factory {
482 virtual ~Factory() {}
483
484 virtual aplptr_t create_apl_web_identity( CephContext* cct,
485 const req_state* s,
20effc67
TL
486 const std::string& role_session,
487 const std::string& role_tenant,
488 const std::unordered_multimap<std::string, std::string>& token,
489 boost::optional<std::multimap<std::string, std::string>>,
490 boost::optional<std::set<std::pair<std::string, std::string>>> principal_tags) const = 0;
11fdf7f2
TL
491 };
492};
28e407b8 493
9f95a23c
TL
494class ImplicitTenants: public md_config_obs_t {
495public:
496 enum implicit_tenant_flag_bits {IMPLICIT_TENANTS_SWIFT=1,
497 IMPLICIT_TENANTS_S3=2, IMPLICIT_TENANTS_BAD = -1, };
498private:
499 int saved;
500 void recompute_value(const ConfigProxy& );
501 class ImplicitTenantValue {
502 friend class ImplicitTenants;
503 int v;
504 ImplicitTenantValue(int v) : v(v) {};
505 public:
506 bool inline is_split_mode()
507 {
508 assert(v != IMPLICIT_TENANTS_BAD);
509 return v == IMPLICIT_TENANTS_SWIFT || v == IMPLICIT_TENANTS_S3;
510 }
511 bool inline implicit_tenants_for_(const implicit_tenant_flag_bits bit)
512 {
513 assert(v != IMPLICIT_TENANTS_BAD);
514 return static_cast<bool>(v&bit);
515 }
516 };
517public:
518 ImplicitTenants(const ConfigProxy& c) { recompute_value(c);}
1e59de90 519 ImplicitTenantValue get_value() const {
9f95a23c
TL
520 return ImplicitTenantValue(saved);
521 }
522private:
523 const char** get_tracked_conf_keys() const override;
524 void handle_conf_change(const ConfigProxy& conf,
525 const std::set <std::string> &changed) override;
526};
527
528std::tuple<bool,bool> implicit_tenants_enabled_for_swift(CephContext * const cct);
529std::tuple<bool,bool> implicit_tenants_enabled_for_s3(CephContext * const cct);
530
7c673cae
FG
531/* rgw::auth::RemoteApplier targets those authentication engines which don't
532 * need to ask the RADOS store while performing the auth process. Instead,
533 * they obtain credentials from an external source like Keystone or LDAP.
534 *
535 * As the authenticated user may not have an account yet, RGWRemoteAuthApplier
536 * must be able to create it basing on data passed by an auth engine. Those
537 * data will be used to fill RGWUserInfo structure. */
538class RemoteApplier : public IdentityApplier {
539public:
540 class AuthInfo {
541 friend class RemoteApplier;
542 protected:
543 const rgw_user acct_user;
544 const std::string acct_name;
545 const uint32_t perm_mask;
546 const bool is_admin;
547 const uint32_t acct_type;
2a845540
TL
548 const std::string access_key_id;
549 const std::string subuser;
7c673cae
FG
550
551 public:
552 enum class acct_privilege_t {
553 IS_ADMIN_ACCT,
554 IS_PLAIN_ACCT
555 };
556
2a845540
TL
557 static const std::string NO_SUBUSER;
558 static const std::string NO_ACCESS_KEY;
559
7c673cae
FG
560 AuthInfo(const rgw_user& acct_user,
561 const std::string& acct_name,
562 const uint32_t perm_mask,
563 const acct_privilege_t level,
2a845540
TL
564 const std::string access_key_id,
565 const std::string subuser,
7c673cae
FG
566 const uint32_t acct_type=TYPE_NONE)
567 : acct_user(acct_user),
568 acct_name(acct_name),
569 perm_mask(perm_mask),
570 is_admin(acct_privilege_t::IS_ADMIN_ACCT == level),
2a845540
TL
571 acct_type(acct_type),
572 access_key_id(access_key_id),
573 subuser(subuser) {
7c673cae
FG
574 }
575 };
576
577 using aclspec_t = rgw::auth::Identity::aclspec_t;
578 typedef std::function<uint32_t(const aclspec_t&)> acl_strategy_t;
579
580protected:
581 CephContext* const cct;
582
583 /* Read-write is intensional here due to RGWUserInfo creation process. */
1e59de90 584 rgw::sal::Driver* driver;
7c673cae
FG
585
586 /* Supplemental strategy for extracting permissions from ACLs. Its results
587 * will be combined (ORed) with a default strategy that is responsible for
588 * handling backward compatibility. */
589 const acl_strategy_t extra_acl_strategy;
590
591 const AuthInfo info;
1e59de90 592 const rgw::auth::ImplicitTenants& implicit_tenant_context;
9f95a23c 593 const rgw::auth::ImplicitTenants::implicit_tenant_flag_bits implicit_tenant_bit;
7c673cae 594
11fdf7f2
TL
595 virtual void create_account(const DoutPrefixProvider* dpp,
596 const rgw_user& acct_user,
9f95a23c 597 bool implicit_tenant,
7c673cae
FG
598 RGWUserInfo& user_info) const; /* out */
599
600public:
601 RemoteApplier(CephContext* const cct,
1e59de90 602 rgw::sal::Driver* driver,
7c673cae
FG
603 acl_strategy_t&& extra_acl_strategy,
604 const AuthInfo& info,
1e59de90 605 const rgw::auth::ImplicitTenants& implicit_tenant_context,
9f95a23c 606 rgw::auth::ImplicitTenants::implicit_tenant_flag_bits implicit_tenant_bit)
7c673cae 607 : cct(cct),
1e59de90 608 driver(driver),
7c673cae
FG
609 extra_acl_strategy(std::move(extra_acl_strategy)),
610 info(info),
9f95a23c
TL
611 implicit_tenant_context(implicit_tenant_context),
612 implicit_tenant_bit(implicit_tenant_bit) {
7c673cae
FG
613 }
614
11fdf7f2 615 uint32_t get_perms_from_aclspec(const DoutPrefixProvider* dpp, const aclspec_t& aclspec) const override;
7c673cae
FG
616 bool is_admin_of(const rgw_user& uid) const override;
617 bool is_owner_of(const rgw_user& uid) const override;
31f18b77
FG
618 bool is_identity(const idset_t& ids) const override;
619
7c673cae
FG
620 uint32_t get_perm_mask() const override { return info.perm_mask; }
621 void to_str(std::ostream& out) const override;
11fdf7f2 622 void load_acct_info(const DoutPrefixProvider* dpp, RGWUserInfo& user_info) const override; /* out */
2a845540 623 void write_ops_log_entry(rgw_log_entry& entry) const override;
11fdf7f2 624 uint32_t get_identity_type() const override { return info.acct_type; }
20effc67
TL
625 std::string get_acct_name() const override { return info.acct_name; }
626 std::string get_subuser() const override { return {}; }
7c673cae
FG
627
628 struct Factory {
629 virtual ~Factory() {}
630 /* Providing r-value reference here is required intensionally. Callee is
631 * thus disallowed to handle std::function in a way that could inhibit
632 * the move behaviour (like forgetting about std::moving a l-value). */
633 virtual aplptr_t create_apl_remote(CephContext* cct,
634 const req_state* s,
635 acl_strategy_t&& extra_acl_strategy,
11fdf7f2 636 const AuthInfo &info) const = 0;
7c673cae
FG
637 };
638};
639
640
641/* rgw::auth::LocalApplier targets those auth engines that base on the data
642 * enclosed in the RGWUserInfo control structure. As a side effect of doing
643 * the authentication process, they must have it loaded. Leveraging this is
644 * a way to avoid unnecessary calls to underlying RADOS store. */
645class LocalApplier : public IdentityApplier {
646 using aclspec_t = rgw::auth::Identity::aclspec_t;
647
648protected:
649 const RGWUserInfo user_info;
650 const std::string subuser;
11fdf7f2 651 uint32_t perm_mask;
2a845540 652 const std::string access_key_id;
7c673cae
FG
653
654 uint32_t get_perm_mask(const std::string& subuser_name,
655 const RGWUserInfo &uinfo) const;
656
657public:
658 static const std::string NO_SUBUSER;
2a845540 659 static const std::string NO_ACCESS_KEY;
7c673cae
FG
660
661 LocalApplier(CephContext* const cct,
662 const RGWUserInfo& user_info,
11fdf7f2 663 std::string subuser,
2a845540
TL
664 const std::optional<uint32_t>& perm_mask,
665 const std::string access_key_id)
7c673cae 666 : user_info(user_info),
20effc67 667 subuser(std::move(subuser)),
2a845540
TL
668 perm_mask(perm_mask.value_or(RGW_PERM_INVALID)),
669 access_key_id(access_key_id) {
7c673cae
FG
670 }
671
672
11fdf7f2 673 uint32_t get_perms_from_aclspec(const DoutPrefixProvider* dpp, const aclspec_t& aclspec) const override;
7c673cae
FG
674 bool is_admin_of(const rgw_user& uid) const override;
675 bool is_owner_of(const rgw_user& uid) const override;
31f18b77 676 bool is_identity(const idset_t& ids) const override;
7c673cae 677 uint32_t get_perm_mask() const override {
11fdf7f2
TL
678 if (this->perm_mask == RGW_PERM_INVALID) {
679 return get_perm_mask(subuser, user_info);
680 } else {
681 return this->perm_mask;
682 }
7c673cae
FG
683 }
684 void to_str(std::ostream& out) const override;
11fdf7f2
TL
685 void load_acct_info(const DoutPrefixProvider* dpp, RGWUserInfo& user_info) const override; /* out */
686 uint32_t get_identity_type() const override { return TYPE_RGW; }
20effc67
TL
687 std::string get_acct_name() const override { return {}; }
688 std::string get_subuser() const override { return subuser; }
2a845540 689 void write_ops_log_entry(rgw_log_entry& entry) const override;
7c673cae
FG
690
691 struct Factory {
692 virtual ~Factory() {}
693 virtual aplptr_t create_apl_local(CephContext* cct,
694 const req_state* s,
695 const RGWUserInfo& user_info,
11fdf7f2 696 const std::string& subuser,
2a845540
TL
697 const std::optional<uint32_t>& perm_mask,
698 const std::string& access_key_id) const = 0;
7c673cae
FG
699 };
700};
701
11fdf7f2 702class RoleApplier : public IdentityApplier {
f91f0fd5
TL
703public:
704 struct Role {
20effc67
TL
705 std::string id;
706 std::string name;
707 std::string tenant;
708 std::vector<std::string> role_policies;
709 };
710 struct TokenAttrs {
711 rgw_user user_id;
712 std::string token_policy;
713 std::string role_session_name;
714 std::vector<std::string> token_claims;
715 std::string token_issued_at;
716 std::vector<std::pair<std::string, std::string>> principal_tags;
717 };
11fdf7f2 718protected:
20effc67
TL
719 Role role;
720 TokenAttrs token_attrs;
11fdf7f2
TL
721
722public:
723
724 RoleApplier(CephContext* const cct,
f91f0fd5 725 const Role& role,
20effc67 726 const TokenAttrs& token_attrs)
f91f0fd5 727 : role(role),
20effc67 728 token_attrs(token_attrs) {}
11fdf7f2
TL
729
730 uint32_t get_perms_from_aclspec(const DoutPrefixProvider* dpp, const aclspec_t& aclspec) const override {
731 return 0;
732 }
733 bool is_admin_of(const rgw_user& uid) const override {
734 return false;
735 }
736 bool is_owner_of(const rgw_user& uid) const override {
20effc67 737 return (this->token_attrs.user_id.id == uid.id && this->token_attrs.user_id.tenant == uid.tenant && this->token_attrs.user_id.ns == uid.ns);
11fdf7f2
TL
738 }
739 bool is_identity(const idset_t& ids) const override;
740 uint32_t get_perm_mask() const override {
20effc67 741 return RGW_PERM_NONE;
11fdf7f2
TL
742 }
743 void to_str(std::ostream& out) const override;
744 void load_acct_info(const DoutPrefixProvider* dpp, RGWUserInfo& user_info) const override; /* out */
745 uint32_t get_identity_type() const override { return TYPE_ROLE; }
20effc67
TL
746 std::string get_acct_name() const override { return {}; }
747 std::string get_subuser() const override { return {}; }
11fdf7f2 748 void modify_request_state(const DoutPrefixProvider* dpp, req_state* s) const override;
20effc67 749 std::string get_role_tenant() const override { return role.tenant; }
11fdf7f2
TL
750
751 struct Factory {
752 virtual ~Factory() {}
753 virtual aplptr_t create_apl_role( CephContext* cct,
754 const req_state* s,
f67539c2 755 const rgw::auth::RoleApplier::Role& role,
20effc67 756 const rgw::auth::RoleApplier::TokenAttrs& token_attrs) const = 0;
11fdf7f2
TL
757 };
758};
7c673cae
FG
759
760/* The anonymous abstract engine. */
761class AnonymousEngine : public Engine {
762 CephContext* const cct;
763 const rgw::auth::LocalApplier::Factory* const apl_factory;
764
765public:
766 AnonymousEngine(CephContext* const cct,
767 const rgw::auth::LocalApplier::Factory* const apl_factory)
768 : cct(cct),
769 apl_factory(apl_factory) {
770 }
771
772 const char* get_name() const noexcept override {
773 return "rgw::auth::AnonymousEngine";
774 }
775
f67539c2 776 Engine::result_t authenticate(const DoutPrefixProvider* dpp, const req_state* s, optional_yield y) const override final;
7c673cae
FG
777
778protected:
779 virtual bool is_applicable(const req_state*) const noexcept {
780 return true;
781 }
782};
783
784} /* namespace auth */
785} /* namespace rgw */
786
787
788uint32_t rgw_perms_from_aclspec_default_strategy(
789 const rgw_user& uid,
b3b6e05e
TL
790 const rgw::auth::Identity::aclspec_t& aclspec,
791 const DoutPrefixProvider *dpp);