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