]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_auth.cc
import 15.2.5
[ceph.git] / ceph / src / rgw / rgw_auth.cc
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#include <array>
5
6#include "rgw_common.h"
7#include "rgw_auth.h"
f64942e4 8#include "rgw_quota.h"
7c673cae
FG
9#include "rgw_user.h"
10#include "rgw_http_client.h"
11#include "rgw_keystone.h"
9f95a23c 12#include "rgw_sal.h"
7c673cae
FG
13
14#include "include/str_list.h"
15
16#define dout_context g_ceph_context
17#define dout_subsys ceph_subsys_rgw
18
19
20namespace rgw {
21namespace auth {
22
23std::unique_ptr<rgw::auth::Identity>
9f95a23c
TL
24transform_old_authinfo(CephContext* const cct,
25 const rgw_user& auth_id,
26 const int perm_mask,
27 const bool is_admin,
28 const uint32_t type)
7c673cae
FG
29{
30 /* This class is not intended for public use. Should be removed altogether
31 * with this function after moving all our APIs to the new authentication
32 * infrastructure. */
33 class DummyIdentityApplier : public rgw::auth::Identity {
34 CephContext* const cct;
35
36 /* For this particular case it's OK to use rgw_user structure to convey
37 * the identity info as this was the policy for doing that before the
38 * new auth. */
39 const rgw_user id;
40 const int perm_mask;
41 const bool is_admin;
11fdf7f2 42 const uint32_t type;
7c673cae
FG
43 public:
44 DummyIdentityApplier(CephContext* const cct,
45 const rgw_user& auth_id,
46 const int perm_mask,
11fdf7f2
TL
47 const bool is_admin,
48 const uint32_t type)
7c673cae
FG
49 : cct(cct),
50 id(auth_id),
51 perm_mask(perm_mask),
11fdf7f2
TL
52 is_admin(is_admin),
53 type(type) {
7c673cae
FG
54 }
55
11fdf7f2 56 uint32_t get_perms_from_aclspec(const DoutPrefixProvider* dpp, const aclspec_t& aclspec) const override {
7c673cae
FG
57 return rgw_perms_from_aclspec_default_strategy(id, aclspec);
58 }
59
60 bool is_admin_of(const rgw_user& acct_id) const override {
61 return is_admin;
62 }
63
64 bool is_owner_of(const rgw_user& acct_id) const override {
65 return id == acct_id;
66 }
67
31f18b77
FG
68 bool is_identity(const idset_t& ids) const override {
69 for (auto& p : ids) {
70 if (p.is_wildcard()) {
71 return true;
72 } else if (p.is_tenant() && p.get_tenant() == id.tenant) {
73 return true;
74 } else if (p.is_user() &&
75 (p.get_tenant() == id.tenant) &&
76 (p.get_id() == id.id)) {
77 return true;
78 }
79 }
80 return false;
81 }
82
7c673cae
FG
83 uint32_t get_perm_mask() const override {
84 return perm_mask;
85 }
86
11fdf7f2
TL
87 uint32_t get_identity_type() const override {
88 return type;
89 }
90
91 string get_acct_name() const override {
92 return {};
93 }
94
f6b5b4d7
TL
95 string get_subuser() const override {
96 return {};
97 }
98
7c673cae
FG
99 void to_str(std::ostream& out) const override {
100 out << "RGWDummyIdentityApplier(auth_id=" << id
101 << ", perm_mask=" << perm_mask
102 << ", is_admin=" << is_admin << ")";
103 }
104 };
105
106 return std::unique_ptr<rgw::auth::Identity>(
9f95a23c
TL
107 new DummyIdentityApplier(cct,
108 auth_id,
109 perm_mask,
110 is_admin,
111 type));
112}
113
114std::unique_ptr<rgw::auth::Identity>
115transform_old_authinfo(const req_state* const s)
116{
117 return transform_old_authinfo(s->cct,
118 s->user->get_id(),
119 s->perm_mask,
7c673cae
FG
120 /* System user has admin permissions by default - it's supposed to pass
121 * through any security check. */
9f95a23c
TL
122 s->system_request,
123 s->user->get_type());
7c673cae
FG
124}
125
126} /* namespace auth */
127} /* namespace rgw */
128
129
130uint32_t rgw_perms_from_aclspec_default_strategy(
131 const rgw_user& uid,
132 const rgw::auth::Identity::aclspec_t& aclspec)
133{
134 dout(5) << "Searching permissions for uid=" << uid << dendl;
135
136 const auto iter = aclspec.find(uid.to_str());
137 if (std::end(aclspec) != iter) {
138 dout(5) << "Found permission: " << iter->second << dendl;
139 return iter->second;
140 }
141
142 dout(5) << "Permissions for user not found" << dendl;
143 return 0;
144}
145
146
147static inline const std::string make_spec_item(const std::string& tenant,
148 const std::string& id)
149{
150 return tenant + ":" + id;
151}
152
153
154static inline std::pair<bool, rgw::auth::Engine::result_t>
155strategy_handle_rejected(rgw::auth::Engine::result_t&& engine_result,
156 const rgw::auth::Strategy::Control policy,
157 rgw::auth::Engine::result_t&& strategy_result)
158{
159 using Control = rgw::auth::Strategy::Control;
160 switch (policy) {
161 case Control::REQUISITE:
162 /* Don't try next. */
163 return std::make_pair(false, std::move(engine_result));
164
165 case Control::SUFFICIENT:
166 /* Don't try next. */
167 return std::make_pair(false, std::move(engine_result));
168
169 case Control::FALLBACK:
170 /* Don't try next. */
171 return std::make_pair(false, std::move(strategy_result));
172
173 default:
174 /* Huh, memory corruption? */
11fdf7f2 175 ceph_abort();
7c673cae
FG
176 }
177}
178
179static inline std::pair<bool, rgw::auth::Engine::result_t>
180strategy_handle_denied(rgw::auth::Engine::result_t&& engine_result,
181 const rgw::auth::Strategy::Control policy,
182 rgw::auth::Engine::result_t&& strategy_result)
183{
184 using Control = rgw::auth::Strategy::Control;
185 switch (policy) {
186 case Control::REQUISITE:
187 /* Don't try next. */
188 return std::make_pair(false, std::move(engine_result));
189
190 case Control::SUFFICIENT:
191 /* Just try next. */
192 return std::make_pair(true, std::move(engine_result));
193
194 case Control::FALLBACK:
195 return std::make_pair(true, std::move(strategy_result));
196
197 default:
198 /* Huh, memory corruption? */
11fdf7f2 199 ceph_abort();
7c673cae
FG
200 }
201}
202
203static inline std::pair<bool, rgw::auth::Engine::result_t>
204strategy_handle_granted(rgw::auth::Engine::result_t&& engine_result,
205 const rgw::auth::Strategy::Control policy,
206 rgw::auth::Engine::result_t&& strategy_result)
207{
208 using Control = rgw::auth::Strategy::Control;
209 switch (policy) {
210 case Control::REQUISITE:
211 /* Try next. */
212 return std::make_pair(true, std::move(engine_result));
213
214 case Control::SUFFICIENT:
215 /* Don't try next. */
216 return std::make_pair(false, std::move(engine_result));
217
218 case Control::FALLBACK:
219 /* Don't try next. */
220 return std::make_pair(false, std::move(engine_result));
221
222 default:
223 /* Huh, memory corruption? */
11fdf7f2 224 ceph_abort();
7c673cae
FG
225 }
226}
227
228rgw::auth::Engine::result_t
11fdf7f2 229rgw::auth::Strategy::authenticate(const DoutPrefixProvider* dpp, const req_state* const s) const
7c673cae
FG
230{
231 result_t strategy_result = result_t::deny();
232
233 for (const stack_item_t& kv : auth_stack) {
234 const rgw::auth::Engine& engine = kv.first;
235 const auto& policy = kv.second;
236
11fdf7f2 237 ldpp_dout(dpp, 20) << get_name() << ": trying " << engine.get_name() << dendl;
7c673cae
FG
238
239 result_t engine_result = result_t::deny();
240 try {
11fdf7f2 241 engine_result = engine.authenticate(dpp, s);
7c673cae
FG
242 } catch (const int err) {
243 engine_result = result_t::deny(err);
244 }
245
246 bool try_next = true;
247 switch (engine_result.get_status()) {
248 case result_t::Status::REJECTED: {
11fdf7f2 249 ldpp_dout(dpp, 20) << engine.get_name() << " rejected with reason="
7c673cae
FG
250 << engine_result.get_reason() << dendl;
251
252 std::tie(try_next, strategy_result) = \
253 strategy_handle_rejected(std::move(engine_result), policy,
254 std::move(strategy_result));
255 break;
256 }
257 case result_t::Status::DENIED: {
11fdf7f2 258 ldpp_dout(dpp, 20) << engine.get_name() << " denied with reason="
7c673cae
FG
259 << engine_result.get_reason() << dendl;
260
261 std::tie(try_next, strategy_result) = \
262 strategy_handle_denied(std::move(engine_result), policy,
263 std::move(strategy_result));
264 break;
265 }
266 case result_t::Status::GRANTED: {
11fdf7f2 267 ldpp_dout(dpp, 20) << engine.get_name() << " granted access" << dendl;
7c673cae
FG
268
269 std::tie(try_next, strategy_result) = \
270 strategy_handle_granted(std::move(engine_result), policy,
271 std::move(strategy_result));
272 break;
273 }
274 default: {
11fdf7f2 275 ceph_abort();
7c673cae
FG
276 }
277 }
278
279 if (! try_next) {
280 break;
281 }
282 }
283
284 return strategy_result;
285}
286
31f18b77 287int
11fdf7f2 288rgw::auth::Strategy::apply(const DoutPrefixProvider *dpp, const rgw::auth::Strategy& auth_strategy,
31f18b77
FG
289 req_state* const s) noexcept
290{
291 try {
11fdf7f2 292 auto result = auth_strategy.authenticate(dpp, s);
31f18b77
FG
293 if (result.get_status() != decltype(result)::Status::GRANTED) {
294 /* Access denied is acknowledged by returning a std::unique_ptr with
295 * nullptr inside. */
11fdf7f2 296 ldpp_dout(dpp, 5) << "Failed the auth strategy, reason="
31f18b77
FG
297 << result.get_reason() << dendl;
298 return result.get_reason();
299 }
300
301 try {
302 rgw::auth::IdentityApplier::aplptr_t applier = result.get_applier();
303 rgw::auth::Completer::cmplptr_t completer = result.get_completer();
304
305 /* Account used by a given RGWOp is decoupled from identity employed
306 * in the authorization phase (RGWOp::verify_permissions). */
9f95a23c 307 applier->load_acct_info(dpp, s->user->get_info());
31f18b77
FG
308 s->perm_mask = applier->get_perm_mask();
309
11fdf7f2 310 /* This is the single place where we pass req_state as a pointer
31f18b77
FG
311 * to non-const and thus its modification is allowed. In the time
312 * of writing only RGWTempURLEngine needed that feature. */
11fdf7f2 313 applier->modify_request_state(dpp, s);
31f18b77 314 if (completer) {
11fdf7f2 315 completer->modify_request_state(dpp, s);
31f18b77
FG
316 }
317
318 s->auth.identity = std::move(applier);
319 s->auth.completer = std::move(completer);
320
321 return 0;
322 } catch (const int err) {
11fdf7f2 323 ldpp_dout(dpp, 5) << "applier throwed err=" << err << dendl;
31f18b77
FG
324 return err;
325 }
326 } catch (const int err) {
11fdf7f2 327 ldpp_dout(dpp, 5) << "auth engine throwed err=" << err << dendl;
31f18b77
FG
328 return err;
329 }
330
331 /* We never should be here. */
332 return -EPERM;
333}
334
7c673cae
FG
335void
336rgw::auth::Strategy::add_engine(const Control ctrl_flag,
337 const Engine& engine) noexcept
338{
339 auth_stack.push_back(std::make_pair(std::cref(engine), ctrl_flag));
340}
341
11fdf7f2
TL
342void rgw::auth::WebIdentityApplier::to_str(std::ostream& out) const
343{
344 out << "rgw::auth::WebIdentityApplier(sub =" << token_claims.sub
345 << ", user_name=" << token_claims.user_name
346 << ", aud =" << token_claims.aud
347 << ", provider_id =" << token_claims.iss << ")";
348}
349
350string rgw::auth::WebIdentityApplier::get_idp_url() const
351{
352 string idp_url = token_claims.iss;
353 auto pos = idp_url.find("http://");
354 if (pos == std::string::npos) {
355 pos = idp_url.find("https://");
356 if (pos != std::string::npos) {
357 idp_url.erase(pos, 8);
358 }
359 } else {
360 idp_url.erase(pos, 7);
361 }
362 return idp_url;
363}
364
365void rgw::auth::WebIdentityApplier::modify_request_state(const DoutPrefixProvider *dpp, req_state* s) const
366{
367 s->info.args.append("sub", token_claims.sub);
368 s->info.args.append("aud", token_claims.aud);
369 s->info.args.append("provider_id", token_claims.iss);
370
371 string idp_url = get_idp_url();
372 string condition = idp_url + ":app_id";
373 s->env.emplace(condition, token_claims.aud);
374}
375
376bool rgw::auth::WebIdentityApplier::is_identity(const idset_t& ids) const
377{
378 if (ids.size() > 1) {
379 return false;
380 }
381
382 for (auto id : ids) {
383 string idp_url = get_idp_url();
384 if (id.is_oidc_provider() && id.get_idp_url() == idp_url) {
385 return true;
386 }
387 }
388 return false;
389}
7c673cae
FG
390
391/* rgw::auth::RemoteAuthApplier */
11fdf7f2 392uint32_t rgw::auth::RemoteApplier::get_perms_from_aclspec(const DoutPrefixProvider* dpp, const aclspec_t& aclspec) const
7c673cae
FG
393{
394 uint32_t perm = 0;
395
396 /* For backward compatibility with ACLOwner. */
397 perm |= rgw_perms_from_aclspec_default_strategy(info.acct_user,
398 aclspec);
399
400 /* We also need to cover cases where rgw_keystone_implicit_tenants
401 * was enabled. */
402 if (info.acct_user.tenant.empty()) {
403 const rgw_user tenanted_acct_user(info.acct_user.id, info.acct_user.id);
404
405 perm |= rgw_perms_from_aclspec_default_strategy(tenanted_acct_user,
406 aclspec);
407 }
408
409 /* Now it's a time for invoking additional strategy that was supplied by
410 * a specific auth engine. */
411 if (extra_acl_strategy) {
412 perm |= extra_acl_strategy(aclspec);
413 }
414
11fdf7f2 415 ldpp_dout(dpp, 20) << "from ACL got perm=" << perm << dendl;
7c673cae
FG
416 return perm;
417}
418
419bool rgw::auth::RemoteApplier::is_admin_of(const rgw_user& uid) const
420{
421 return info.is_admin;
422}
423
424bool rgw::auth::RemoteApplier::is_owner_of(const rgw_user& uid) const
425{
426 if (info.acct_user.tenant.empty()) {
427 const rgw_user tenanted_acct_user(info.acct_user.id, info.acct_user.id);
428
429 if (tenanted_acct_user == uid) {
430 return true;
431 }
432 }
433
434 return info.acct_user == uid;
435}
436
31f18b77
FG
437bool rgw::auth::RemoteApplier::is_identity(const idset_t& ids) const {
438 for (auto& id : ids) {
439 if (id.is_wildcard()) {
440 return true;
441
442 // We also need to cover cases where rgw_keystone_implicit_tenants
443 // was enabled. */
444 } else if (id.is_tenant() &&
445 (info.acct_user.tenant.empty() ?
446 info.acct_user.id :
447 info.acct_user.tenant) == id.get_tenant()) {
448 return true;
449 } else if (id.is_user() &&
450 info.acct_user.id == id.get_id() &&
451 (info.acct_user.tenant.empty() ?
452 info.acct_user.id :
453 info.acct_user.tenant) == id.get_tenant()) {
454 return true;
455 }
456 }
457 return false;
458}
459
7c673cae
FG
460void rgw::auth::RemoteApplier::to_str(std::ostream& out) const
461{
462 out << "rgw::auth::RemoteApplier(acct_user=" << info.acct_user
463 << ", acct_name=" << info.acct_name
464 << ", perm_mask=" << info.perm_mask
465 << ", is_admin=" << info.is_admin << ")";
466}
467
9f95a23c
TL
468void rgw::auth::ImplicitTenants::recompute_value(const ConfigProxy& c)
469{
470 std::string s = c.get_val<std::string>("rgw_keystone_implicit_tenants");
471 int v = 0;
472 if (boost::iequals(s, "both")
473 || boost::iequals(s, "true")
474 || boost::iequals(s, "1")) {
475 v = IMPLICIT_TENANTS_S3|IMPLICIT_TENANTS_SWIFT;
476 } else if (boost::iequals(s, "0")
477 || boost::iequals(s, "none")
478 || boost::iequals(s, "false")) {
479 v = 0;
480 } else if (boost::iequals(s, "s3")) {
481 v = IMPLICIT_TENANTS_S3;
482 } else if (boost::iequals(s, "swift")) {
483 v = IMPLICIT_TENANTS_SWIFT;
484 } else { /* "" (and anything else) */
485 v = IMPLICIT_TENANTS_BAD;
486 // assert(0);
487 }
488 saved = v;
489}
490
491const char **rgw::auth::ImplicitTenants::get_tracked_conf_keys() const
492{
493 static const char *keys[] = {
494 "rgw_keystone_implicit_tenants",
495 nullptr };
496 return keys;
497}
498
499void rgw::auth::ImplicitTenants::handle_conf_change(const ConfigProxy& c,
500 const std::set <std::string> &changed)
501{
502 if (changed.count("rgw_keystone_implicit_tenants")) {
503 recompute_value(c);
504 }
505}
506
11fdf7f2
TL
507void rgw::auth::RemoteApplier::create_account(const DoutPrefixProvider* dpp,
508 const rgw_user& acct_user,
9f95a23c 509 bool implicit_tenant,
7c673cae
FG
510 RGWUserInfo& user_info) const /* out */
511{
512 rgw_user new_acct_user = acct_user;
513
514 if (info.acct_type) {
515 //ldap/keystone for s3 users
516 user_info.type = info.acct_type;
517 }
518
519 /* An upper layer may enforce creating new accounts within their own
520 * tenants. */
9f95a23c 521 if (new_acct_user.tenant.empty() && implicit_tenant) {
7c673cae
FG
522 new_acct_user.tenant = new_acct_user.id;
523 }
524
525 user_info.user_id = new_acct_user;
526 user_info.display_name = info.acct_name;
527
f6b5b4d7
TL
528 user_info.max_buckets =
529 cct->_conf.get_val<int64_t>("rgw_user_max_buckets");
11fdf7f2
TL
530 rgw_apply_default_bucket_quota(user_info.bucket_quota, cct->_conf);
531 rgw_apply_default_user_quota(user_info.user_quota, cct->_conf);
f64942e4 532
9f95a23c
TL
533 int ret = ctl->user->store_info(user_info, null_yield,
534 RGWUserCtl::PutParams().set_exclusive(true));
7c673cae 535 if (ret < 0) {
11fdf7f2 536 ldpp_dout(dpp, 0) << "ERROR: failed to store new user info: user="
7c673cae
FG
537 << user_info.user_id << " ret=" << ret << dendl;
538 throw ret;
539 }
540}
541
542/* TODO(rzarzynski): we need to handle display_name changes. */
11fdf7f2 543void rgw::auth::RemoteApplier::load_acct_info(const DoutPrefixProvider* dpp, RGWUserInfo& user_info) const /* out */
7c673cae
FG
544{
545 /* It's supposed that RGWRemoteAuthApplier tries to load account info
546 * that belongs to the authenticated identity. Another policy may be
547 * applied by using a RGWThirdPartyAccountAuthApplier decorator. */
548 const rgw_user& acct_user = info.acct_user;
9f95a23c
TL
549 auto implicit_value = implicit_tenant_context.get_value();
550 bool implicit_tenant = implicit_value.implicit_tenants_for_(implicit_tenant_bit);
551 bool split_mode = implicit_value.is_split_mode();
7c673cae
FG
552
553 /* Normally, empty "tenant" field of acct_user means the authenticated
554 * identity has the legacy, global tenant. However, due to inclusion
555 * of multi-tenancy, we got some special compatibility kludge for remote
556 * backends like Keystone.
557 * If the global tenant is the requested one, we try the same tenant as
558 * the user name first. If that RGWUserInfo exists, we use it. This way,
559 * migrated OpenStack users can get their namespaced containers and nobody's
560 * the wiser.
561 * If that fails, we look up in the requested (possibly empty) tenant.
562 * If that fails too, we create the account within the global or separated
9f95a23c
TL
563 * namespace depending on rgw_keystone_implicit_tenants.
564 * For compatibility with previous versions of ceph, it is possible
565 * to enable implicit_tenants for only s3 or only swift.
566 * in this mode ("split_mode"), we must constrain the id lookups to
567 * only use the identifier space that would be used if the id were
568 * to be created. */
569
570 if (split_mode && !implicit_tenant)
571 ; /* suppress lookup for id used by "other" protocol */
572 else if (acct_user.tenant.empty()) {
7c673cae
FG
573 const rgw_user tenanted_uid(acct_user.id, acct_user.id);
574
9f95a23c 575 if (ctl->user->get_info_by_uid(tenanted_uid, &user_info, null_yield) >= 0) {
7c673cae
FG
576 /* Succeeded. */
577 return;
578 }
579 }
580
9f95a23c
TL
581 if (split_mode && implicit_tenant)
582 ; /* suppress lookup for id used by "other" protocol */
583 else if (ctl->user->get_info_by_uid(acct_user, &user_info, null_yield) >= 0) {
584 /* Succeeded. */
585 return;
7c673cae
FG
586 }
587
9f95a23c
TL
588 ldpp_dout(dpp, 0) << "NOTICE: couldn't map swift user " << acct_user << dendl;
589 create_account(dpp, acct_user, implicit_tenant, user_info);
590
7c673cae
FG
591 /* Succeeded if we are here (create_account() hasn't throwed). */
592}
593
7c673cae
FG
594/* rgw::auth::LocalApplier */
595/* static declaration */
596const std::string rgw::auth::LocalApplier::NO_SUBUSER;
597
11fdf7f2 598uint32_t rgw::auth::LocalApplier::get_perms_from_aclspec(const DoutPrefixProvider* dpp, const aclspec_t& aclspec) const
7c673cae
FG
599{
600 return rgw_perms_from_aclspec_default_strategy(user_info.user_id, aclspec);
601}
602
603bool rgw::auth::LocalApplier::is_admin_of(const rgw_user& uid) const
604{
605 return user_info.admin || user_info.system;
606}
607
608bool rgw::auth::LocalApplier::is_owner_of(const rgw_user& uid) const
609{
610 return uid == user_info.user_id;
611}
612
31f18b77
FG
613bool rgw::auth::LocalApplier::is_identity(const idset_t& ids) const {
614 for (auto& id : ids) {
615 if (id.is_wildcard()) {
616 return true;
617 } else if (id.is_tenant() &&
618 id.get_tenant() == user_info.user_id.tenant) {
619 return true;
620 } else if (id.is_user() &&
9f95a23c
TL
621 (id.get_tenant() == user_info.user_id.tenant)) {
622 if (id.get_id() == user_info.user_id.id) {
623 return true;
624 }
f6b5b4d7
TL
625 std::string wildcard_subuser = user_info.user_id.id;
626 wildcard_subuser.append(":*");
627 if (wildcard_subuser == id.get_id()) {
628 return true;
629 } else if (subuser != NO_SUBUSER) {
9f95a23c
TL
630 std::string user = user_info.user_id.id;
631 user.append(":");
632 user.append(subuser);
633 if (user == id.get_id()) {
634 return true;
635 }
636 }
31f18b77
FG
637 }
638 }
639 return false;
640}
641
642void rgw::auth::LocalApplier::to_str(std::ostream& out) const {
7c673cae
FG
643 out << "rgw::auth::LocalApplier(acct_user=" << user_info.user_id
644 << ", acct_name=" << user_info.display_name
645 << ", subuser=" << subuser
646 << ", perm_mask=" << get_perm_mask()
647 << ", is_admin=" << static_cast<bool>(user_info.admin) << ")";
648}
649
650uint32_t rgw::auth::LocalApplier::get_perm_mask(const std::string& subuser_name,
651 const RGWUserInfo &uinfo) const
652{
653 if (! subuser_name.empty() && subuser_name != NO_SUBUSER) {
654 const auto iter = uinfo.subusers.find(subuser_name);
655
656 if (iter != std::end(uinfo.subusers)) {
657 return iter->second.perm_mask;
658 } else {
659 /* Subuser specified but not found. */
660 return RGW_PERM_NONE;
661 }
662 } else {
663 /* Due to backward compatibility. */
664 return RGW_PERM_FULL_CONTROL;
665 }
666}
667
11fdf7f2 668void rgw::auth::LocalApplier::load_acct_info(const DoutPrefixProvider* dpp, RGWUserInfo& user_info) const /* out */
7c673cae
FG
669{
670 /* Load the account that belongs to the authenticated identity. An extra call
671 * to RADOS may be safely skipped in this case. */
672 user_info = this->user_info;
673}
674
11fdf7f2
TL
675void rgw::auth::RoleApplier::to_str(std::ostream& out) const {
676 out << "rgw::auth::LocalApplier(role name =" << role_name;
677 for (auto policy : role_policies) {
678 out << ", role policy =" << policy;
679 }
680 out << ")";
681}
682
683bool rgw::auth::RoleApplier::is_identity(const idset_t& ids) const {
684 for (auto& p : ids) {
685 string name;
686 string tenant = p.get_tenant();
687 if (tenant.empty()) {
688 name = p.get_id();
689 } else {
690 name = tenant + "$" + p.get_id();
691 }
692 if (p.is_wildcard()) {
693 return true;
694 } else if (p.is_role() && name == role_name) {
695 return true;
696 }
697 }
698 return false;
699}
700
701void rgw::auth::RoleApplier::load_acct_info(const DoutPrefixProvider* dpp, RGWUserInfo& user_info) const /* out */
702{
703 /* Load the user id */
704 user_info.user_id = this->user_id;
705}
706
707void rgw::auth::RoleApplier::modify_request_state(const DoutPrefixProvider *dpp, req_state* s) const
708{
709 for (auto it : role_policies) {
710 try {
711 bufferlist bl = bufferlist::static_from_string(it);
9f95a23c 712 const rgw::IAM::Policy p(s->cct, s->user->get_tenant(), bl);
11fdf7f2
TL
713 s->iam_user_policies.push_back(std::move(p));
714 } catch (rgw::IAM::PolicyParseException& e) {
715 //Control shouldn't reach here as the policy has already been
716 //verified earlier
717 ldpp_dout(dpp, 20) << "failed to parse policy: " << e.what() << dendl;
718 }
719 }
720}
7c673cae
FG
721
722rgw::auth::Engine::result_t
11fdf7f2 723rgw::auth::AnonymousEngine::authenticate(const DoutPrefixProvider* dpp, const req_state* const s) const
7c673cae
FG
724{
725 if (! is_applicable(s)) {
31f18b77 726 return result_t::deny(-EPERM);
7c673cae
FG
727 } else {
728 RGWUserInfo user_info;
729 rgw_get_anon_user(user_info);
730
d2e6a577
FG
731 auto apl = \
732 apl_factory->create_apl_local(cct, s, user_info,
11fdf7f2
TL
733 rgw::auth::LocalApplier::NO_SUBUSER,
734 boost::none);
7c673cae
FG
735 return result_t::grant(std::move(apl));
736 }
737}