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