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