]>
git.proxmox.com Git - ceph.git/blob - 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
7 #include "rgw_common.h"
11 #include "rgw_http_client.h"
12 #include "rgw_keystone.h"
16 #include "include/str_list.h"
18 #define dout_context g_ceph_context
19 #define dout_subsys ceph_subsys_rgw
26 std::unique_ptr
<rgw::auth::Identity
>
27 transform_old_authinfo(CephContext
* const cct
,
28 const rgw_user
& auth_id
,
33 /* This class is not intended for public use. Should be removed altogether
34 * with this function after moving all our APIs to the new authentication
36 class DummyIdentityApplier
: public rgw::auth::Identity
{
37 CephContext
* const cct
;
39 /* For this particular case it's OK to use rgw_user structure to convey
40 * the identity info as this was the policy for doing that before the
47 DummyIdentityApplier(CephContext
* const cct
,
48 const rgw_user
& auth_id
,
59 uint32_t get_perms_from_aclspec(const DoutPrefixProvider
* dpp
, const aclspec_t
& aclspec
) const override
{
60 return rgw_perms_from_aclspec_default_strategy(id
, aclspec
, dpp
);
63 bool is_admin_of(const rgw_user
& acct_id
) const override
{
67 bool is_owner_of(const rgw_user
& acct_id
) const override
{
71 bool is_identity(const idset_t
& ids
) const override
{
73 if (p
.is_wildcard()) {
75 } else if (p
.is_tenant() && p
.get_tenant() == id
.tenant
) {
77 } else if (p
.is_user() &&
78 (p
.get_tenant() == id
.tenant
) &&
79 (p
.get_id() == id
.id
)) {
86 uint32_t get_perm_mask() const override
{
90 uint32_t get_identity_type() const override
{
94 string
get_acct_name() const override
{
98 string
get_subuser() const override
{
102 void to_str(std::ostream
& out
) const override
{
103 out
<< "RGWDummyIdentityApplier(auth_id=" << id
104 << ", perm_mask=" << perm_mask
105 << ", is_admin=" << is_admin
<< ")";
109 return std::unique_ptr
<rgw::auth::Identity
>(
110 new DummyIdentityApplier(cct
,
117 std::unique_ptr
<rgw::auth::Identity
>
118 transform_old_authinfo(const req_state
* const s
)
120 return transform_old_authinfo(s
->cct
,
123 /* System user has admin permissions by default - it's supposed to pass
124 * through any security check. */
126 s
->user
->get_type());
129 } /* namespace auth */
130 } /* namespace rgw */
133 uint32_t rgw_perms_from_aclspec_default_strategy(
135 const rgw::auth::Identity::aclspec_t
& aclspec
,
136 const DoutPrefixProvider
*dpp
)
138 ldpp_dout(dpp
, 5) << "Searching permissions for uid=" << uid
<< dendl
;
140 const auto iter
= aclspec
.find(uid
.to_str());
141 if (std::end(aclspec
) != iter
) {
142 ldpp_dout(dpp
, 5) << "Found permission: " << iter
->second
<< dendl
;
146 ldpp_dout(dpp
, 5) << "Permissions for user not found" << dendl
;
151 static inline const std::string
make_spec_item(const std::string
& tenant
,
152 const std::string
& id
)
154 return tenant
+ ":" + id
;
158 static inline std::pair
<bool, rgw::auth::Engine::result_t
>
159 strategy_handle_rejected(rgw::auth::Engine::result_t
&& engine_result
,
160 const rgw::auth::Strategy::Control policy
,
161 rgw::auth::Engine::result_t
&& strategy_result
)
163 using Control
= rgw::auth::Strategy::Control
;
165 case Control::REQUISITE
:
166 /* Don't try next. */
167 return std::make_pair(false, std::move(engine_result
));
169 case Control::SUFFICIENT
:
170 /* Don't try next. */
171 return std::make_pair(false, std::move(engine_result
));
173 case Control::FALLBACK
:
174 /* Don't try next. */
175 return std::make_pair(false, std::move(strategy_result
));
178 /* Huh, memory corruption? */
183 static inline std::pair
<bool, rgw::auth::Engine::result_t
>
184 strategy_handle_denied(rgw::auth::Engine::result_t
&& engine_result
,
185 const rgw::auth::Strategy::Control policy
,
186 rgw::auth::Engine::result_t
&& strategy_result
)
188 using Control
= rgw::auth::Strategy::Control
;
190 case Control::REQUISITE
:
191 /* Don't try next. */
192 return std::make_pair(false, std::move(engine_result
));
194 case Control::SUFFICIENT
:
196 return std::make_pair(true, std::move(engine_result
));
198 case Control::FALLBACK
:
199 return std::make_pair(true, std::move(strategy_result
));
202 /* Huh, memory corruption? */
207 static inline std::pair
<bool, rgw::auth::Engine::result_t
>
208 strategy_handle_granted(rgw::auth::Engine::result_t
&& engine_result
,
209 const rgw::auth::Strategy::Control policy
,
210 rgw::auth::Engine::result_t
&& strategy_result
)
212 using Control
= rgw::auth::Strategy::Control
;
214 case Control::REQUISITE
:
216 return std::make_pair(true, std::move(engine_result
));
218 case Control::SUFFICIENT
:
219 /* Don't try next. */
220 return std::make_pair(false, std::move(engine_result
));
222 case Control::FALLBACK
:
223 /* Don't try next. */
224 return std::make_pair(false, std::move(engine_result
));
227 /* Huh, memory corruption? */
232 rgw::auth::Engine::result_t
233 rgw::auth::Strategy::authenticate(const DoutPrefixProvider
* dpp
, const req_state
* const s
, optional_yield y
) const
235 result_t strategy_result
= result_t::deny();
237 for (const stack_item_t
& kv
: auth_stack
) {
238 const rgw::auth::Engine
& engine
= kv
.first
;
239 const auto& policy
= kv
.second
;
241 ldpp_dout(dpp
, 20) << get_name() << ": trying " << engine
.get_name() << dendl
;
243 result_t engine_result
= result_t::deny();
245 engine_result
= engine
.authenticate(dpp
, s
, y
);
246 } catch (const int err
) {
247 engine_result
= result_t::deny(err
);
250 bool try_next
= true;
251 switch (engine_result
.get_status()) {
252 case result_t::Status::REJECTED
: {
253 ldpp_dout(dpp
, 20) << engine
.get_name() << " rejected with reason="
254 << engine_result
.get_reason() << dendl
;
256 std::tie(try_next
, strategy_result
) = \
257 strategy_handle_rejected(std::move(engine_result
), policy
,
258 std::move(strategy_result
));
261 case result_t::Status::DENIED
: {
262 ldpp_dout(dpp
, 20) << engine
.get_name() << " denied with reason="
263 << engine_result
.get_reason() << dendl
;
265 std::tie(try_next
, strategy_result
) = \
266 strategy_handle_denied(std::move(engine_result
), policy
,
267 std::move(strategy_result
));
270 case result_t::Status::GRANTED
: {
271 ldpp_dout(dpp
, 20) << engine
.get_name() << " granted access" << dendl
;
273 std::tie(try_next
, strategy_result
) = \
274 strategy_handle_granted(std::move(engine_result
), policy
,
275 std::move(strategy_result
));
288 return strategy_result
;
292 rgw::auth::Strategy::apply(const DoutPrefixProvider
*dpp
, const rgw::auth::Strategy
& auth_strategy
,
293 req_state
* const s
, optional_yield y
) noexcept
296 auto result
= auth_strategy
.authenticate(dpp
, s
, y
);
297 if (result
.get_status() != decltype(result
)::Status::GRANTED
) {
298 /* Access denied is acknowledged by returning a std::unique_ptr with
300 ldpp_dout(dpp
, 5) << "Failed the auth strategy, reason="
301 << result
.get_reason() << dendl
;
302 return result
.get_reason();
306 rgw::auth::IdentityApplier::aplptr_t applier
= result
.get_applier();
307 rgw::auth::Completer::cmplptr_t completer
= result
.get_completer();
309 /* Account used by a given RGWOp is decoupled from identity employed
310 * in the authorization phase (RGWOp::verify_permissions). */
311 applier
->load_acct_info(dpp
, s
->user
->get_info());
312 s
->perm_mask
= applier
->get_perm_mask();
314 /* This is the single place where we pass req_state as a pointer
315 * to non-const and thus its modification is allowed. In the time
316 * of writing only RGWTempURLEngine needed that feature. */
317 applier
->modify_request_state(dpp
, s
);
319 completer
->modify_request_state(dpp
, s
);
322 s
->auth
.identity
= std::move(applier
);
323 s
->auth
.completer
= std::move(completer
);
326 } catch (const int err
) {
327 ldpp_dout(dpp
, 5) << "applier throwed err=" << err
<< dendl
;
329 } catch (const std::exception
& e
) {
330 ldpp_dout(dpp
, 5) << "applier throwed unexpected err: " << e
.what()
334 } catch (const int err
) {
335 ldpp_dout(dpp
, 5) << "auth engine throwed err=" << err
<< dendl
;
337 } catch (const std::exception
& e
) {
338 ldpp_dout(dpp
, 5) << "auth engine throwed unexpected err: " << e
.what()
342 /* We never should be here. */
347 rgw::auth::Strategy::add_engine(const Control ctrl_flag
,
348 const Engine
& engine
) noexcept
350 auth_stack
.push_back(std::make_pair(std::cref(engine
), ctrl_flag
));
353 void rgw::auth::WebIdentityApplier::to_str(std::ostream
& out
) const
355 out
<< "rgw::auth::WebIdentityApplier(sub =" << sub
356 << ", user_name=" << user_name
357 << ", provider_id =" << iss
<< ")";
360 string
rgw::auth::WebIdentityApplier::get_idp_url() const
362 string idp_url
= this->iss
;
363 idp_url
= url_remove_prefix(idp_url
);
367 void rgw::auth::WebIdentityApplier::create_account(const DoutPrefixProvider
* dpp
,
368 const rgw_user
& acct_user
,
369 const string
& display_name
,
370 RGWUserInfo
& user_info
) const /* out */
372 std::unique_ptr
<rgw::sal::User
> user
= driver
->get_user(acct_user
);
373 user
->get_info().display_name
= display_name
;
374 user
->get_info().type
= TYPE_WEB
;
375 user
->get_info().max_buckets
=
376 cct
->_conf
.get_val
<int64_t>("rgw_user_max_buckets");
377 rgw_apply_default_bucket_quota(user
->get_info().quota
.bucket_quota
, cct
->_conf
);
378 rgw_apply_default_user_quota(user
->get_info().quota
.user_quota
, cct
->_conf
);
380 int ret
= user
->store_user(dpp
, null_yield
, true);
382 ldpp_dout(dpp
, 0) << "ERROR: failed to store new user info: user="
383 << user
<< " ret=" << ret
<< dendl
;
386 user_info
= user
->get_info();
389 void rgw::auth::WebIdentityApplier::load_acct_info(const DoutPrefixProvider
* dpp
, RGWUserInfo
& user_info
) const {
390 rgw_user federated_user
;
391 federated_user
.id
= this->sub
;
392 federated_user
.tenant
= role_tenant
;
393 federated_user
.ns
= "oidc";
395 std::unique_ptr
<rgw::sal::User
> user
= driver
->get_user(federated_user
);
397 //Check in oidc namespace
398 if (user
->load_user(dpp
, null_yield
) >= 0) {
400 user_info
= user
->get_info();
405 //Check for old users which wouldn't have been created in oidc namespace
406 if (user
->load_user(dpp
, null_yield
) >= 0) {
408 user_info
= user
->get_info();
412 //Check if user_id.buckets already exists, may have been from the time, when shadow users didnt exist
413 RGWStorageStats stats
;
414 int ret
= user
->read_stats(dpp
, null_yield
, &stats
);
415 if (ret
< 0 && ret
!= -ENOENT
) {
416 ldpp_dout(dpp
, 0) << "ERROR: reading stats for the user returned error " << ret
<< dendl
;
419 if (ret
== -ENOENT
) { /* in case of ENOENT, which means user doesnt have buckets */
420 //In this case user will be created in oidc namespace
421 ldpp_dout(dpp
, 5) << "NOTICE: incoming user has no buckets " << federated_user
<< dendl
;
422 federated_user
.ns
= "oidc";
424 //User already has buckets associated, hence wont be created in oidc namespace.
425 ldpp_dout(dpp
, 5) << "NOTICE: incoming user already has buckets associated " << federated_user
<< ", won't be created in oidc namespace"<< dendl
;
426 federated_user
.ns
= "";
429 ldpp_dout(dpp
, 0) << "NOTICE: couldn't map oidc federated user " << federated_user
<< dendl
;
430 create_account(dpp
, federated_user
, this->user_name
, user_info
);
433 void rgw::auth::WebIdentityApplier::modify_request_state(const DoutPrefixProvider
*dpp
, req_state
* s
) const
435 s
->info
.args
.append("sub", this->sub
);
436 s
->info
.args
.append("aud", this->aud
);
437 s
->info
.args
.append("provider_id", this->iss
);
438 s
->info
.args
.append("client_id", this->client_id
);
441 string idp_url
= get_idp_url();
442 for (auto& claim
: token_claims
) {
443 if (claim
.first
== "aud") {
445 condition
= idp_url
+ ":app_id";
446 s
->env
.emplace(condition
, claim
.second
);
449 condition
= idp_url
+ ":" + claim
.first
;
450 s
->env
.emplace(condition
, claim
.second
);
453 if (principal_tags
) {
454 constexpr size_t KEY_SIZE
= 128, VAL_SIZE
= 256;
455 std::set
<std::pair
<string
, string
>> p_tags
= principal_tags
.get();
456 for (auto& it
: p_tags
) {
457 string key
= it
.first
;
458 string val
= it
.second
;
459 if (key
.find("aws:") == 0 || val
.find("aws:") == 0) {
460 ldpp_dout(dpp
, 0) << "ERROR: Tag/Value can't start with aws:, hence skipping it" << dendl
;
463 if (key
.size() > KEY_SIZE
|| val
.size() > VAL_SIZE
) {
464 ldpp_dout(dpp
, 0) << "ERROR: Invalid tag/value size, hence skipping it" << dendl
;
467 std::string p_key
= "aws:PrincipalTag/";
469 s
->principal_tags
.emplace_back(std::make_pair(p_key
, val
));
470 ldpp_dout(dpp
, 10) << "Principal Tag Key: " << p_key
<< " Value: " << val
<< dendl
;
472 std::string e_key
= "aws:RequestTag/";
474 s
->env
.emplace(e_key
, val
);
475 ldpp_dout(dpp
, 10) << "RGW Env Tag Key: " << e_key
<< " Value: " << val
<< dendl
;
477 s
->env
.emplace("aws:TagKeys", key
);
478 ldpp_dout(dpp
, 10) << "aws:TagKeys: " << key
<< dendl
;
480 if (s
->principal_tags
.size() == 50) {
481 ldpp_dout(dpp
, 0) << "ERROR: Number of tag/value pairs exceeding 50, hence skipping the rest" << dendl
;
488 for (auto& it
: role_tags
.get()) {
489 std::string p_key
= "aws:PrincipalTag/";
490 p_key
.append(it
.first
);
491 s
->principal_tags
.emplace_back(std::make_pair(p_key
, it
.second
));
492 ldpp_dout(dpp
, 10) << "Principal Tag Key: " << p_key
<< " Value: " << it
.second
<< dendl
;
494 std::string e_key
= "iam:ResourceTag/";
495 e_key
.append(it
.first
);
496 s
->env
.emplace(e_key
, it
.second
);
497 ldpp_dout(dpp
, 10) << "RGW Env Tag Key: " << e_key
<< " Value: " << it
.second
<< dendl
;
502 bool rgw::auth::WebIdentityApplier::is_identity(const idset_t
& ids
) const
504 if (ids
.size() > 1) {
508 for (auto id
: ids
) {
509 string idp_url
= get_idp_url();
510 if (id
.is_oidc_provider() && id
.get_idp_url() == idp_url
) {
517 const std::string
rgw::auth::RemoteApplier::AuthInfo::NO_SUBUSER
;
518 const std::string
rgw::auth::RemoteApplier::AuthInfo::NO_ACCESS_KEY
;
520 /* rgw::auth::RemoteAuthApplier */
521 uint32_t rgw::auth::RemoteApplier::get_perms_from_aclspec(const DoutPrefixProvider
* dpp
, const aclspec_t
& aclspec
) const
525 /* For backward compatibility with ACLOwner. */
526 perm
|= rgw_perms_from_aclspec_default_strategy(info
.acct_user
,
529 /* We also need to cover cases where rgw_keystone_implicit_tenants
531 if (info
.acct_user
.tenant
.empty()) {
532 const rgw_user
tenanted_acct_user(info
.acct_user
.id
, info
.acct_user
.id
);
534 perm
|= rgw_perms_from_aclspec_default_strategy(tenanted_acct_user
,
538 /* Now it's a time for invoking additional strategy that was supplied by
539 * a specific auth engine. */
540 if (extra_acl_strategy
) {
541 perm
|= extra_acl_strategy(aclspec
);
544 ldpp_dout(dpp
, 20) << "from ACL got perm=" << perm
<< dendl
;
548 bool rgw::auth::RemoteApplier::is_admin_of(const rgw_user
& uid
) const
550 return info
.is_admin
;
553 bool rgw::auth::RemoteApplier::is_owner_of(const rgw_user
& uid
) const
555 if (info
.acct_user
.tenant
.empty()) {
556 const rgw_user
tenanted_acct_user(info
.acct_user
.id
, info
.acct_user
.id
);
558 if (tenanted_acct_user
== uid
) {
563 return info
.acct_user
== uid
;
566 bool rgw::auth::RemoteApplier::is_identity(const idset_t
& ids
) const {
567 for (auto& id
: ids
) {
568 if (id
.is_wildcard()) {
571 // We also need to cover cases where rgw_keystone_implicit_tenants
573 } else if (id
.is_tenant() &&
574 (info
.acct_user
.tenant
.empty() ?
576 info
.acct_user
.tenant
) == id
.get_tenant()) {
578 } else if (id
.is_user() &&
579 info
.acct_user
.id
== id
.get_id() &&
580 (info
.acct_user
.tenant
.empty() ?
582 info
.acct_user
.tenant
) == id
.get_tenant()) {
589 void rgw::auth::RemoteApplier::to_str(std::ostream
& out
) const
591 out
<< "rgw::auth::RemoteApplier(acct_user=" << info
.acct_user
592 << ", acct_name=" << info
.acct_name
593 << ", perm_mask=" << info
.perm_mask
594 << ", is_admin=" << info
.is_admin
<< ")";
597 void rgw::auth::ImplicitTenants::recompute_value(const ConfigProxy
& c
)
599 std::string s
= c
.get_val
<std::string
>("rgw_keystone_implicit_tenants");
601 if (boost::iequals(s
, "both")
602 || boost::iequals(s
, "true")
603 || boost::iequals(s
, "1")) {
604 v
= IMPLICIT_TENANTS_S3
|IMPLICIT_TENANTS_SWIFT
;
605 } else if (boost::iequals(s
, "0")
606 || boost::iequals(s
, "none")
607 || boost::iequals(s
, "false")) {
609 } else if (boost::iequals(s
, "s3")) {
610 v
= IMPLICIT_TENANTS_S3
;
611 } else if (boost::iequals(s
, "swift")) {
612 v
= IMPLICIT_TENANTS_SWIFT
;
613 } else { /* "" (and anything else) */
614 v
= IMPLICIT_TENANTS_BAD
;
620 const char **rgw::auth::ImplicitTenants::get_tracked_conf_keys() const
622 static const char *keys
[] = {
623 "rgw_keystone_implicit_tenants",
628 void rgw::auth::ImplicitTenants::handle_conf_change(const ConfigProxy
& c
,
629 const std::set
<std::string
> &changed
)
631 if (changed
.count("rgw_keystone_implicit_tenants")) {
636 void rgw::auth::RemoteApplier::create_account(const DoutPrefixProvider
* dpp
,
637 const rgw_user
& acct_user
,
638 bool implicit_tenant
,
639 RGWUserInfo
& user_info
) const /* out */
641 rgw_user new_acct_user
= acct_user
;
643 /* An upper layer may enforce creating new accounts within their own
645 if (new_acct_user
.tenant
.empty() && implicit_tenant
) {
646 new_acct_user
.tenant
= new_acct_user
.id
;
649 std::unique_ptr
<rgw::sal::User
> user
= driver
->get_user(new_acct_user
);
650 user
->get_info().display_name
= info
.acct_name
;
651 if (info
.acct_type
) {
652 //ldap/keystone for s3 users
653 user
->get_info().type
= info
.acct_type
;
655 user
->get_info().max_buckets
=
656 cct
->_conf
.get_val
<int64_t>("rgw_user_max_buckets");
657 rgw_apply_default_bucket_quota(user
->get_info().quota
.bucket_quota
, cct
->_conf
);
658 rgw_apply_default_user_quota(user
->get_info().quota
.user_quota
, cct
->_conf
);
659 user_info
= user
->get_info();
661 int ret
= user
->store_user(dpp
, null_yield
, true);
663 ldpp_dout(dpp
, 0) << "ERROR: failed to store new user info: user="
664 << user
<< " ret=" << ret
<< dendl
;
669 void rgw::auth::RemoteApplier::write_ops_log_entry(rgw_log_entry
& entry
) const
671 entry
.access_key_id
= info
.access_key_id
;
672 entry
.subuser
= info
.subuser
;
675 /* TODO(rzarzynski): we need to handle display_name changes. */
676 void rgw::auth::RemoteApplier::load_acct_info(const DoutPrefixProvider
* dpp
, RGWUserInfo
& user_info
) const /* out */
678 /* It's supposed that RGWRemoteAuthApplier tries to load account info
679 * that belongs to the authenticated identity. Another policy may be
680 * applied by using a RGWThirdPartyAccountAuthApplier decorator. */
681 const rgw_user
& acct_user
= info
.acct_user
;
682 auto implicit_value
= implicit_tenant_context
.get_value();
683 bool implicit_tenant
= implicit_value
.implicit_tenants_for_(implicit_tenant_bit
);
684 bool split_mode
= implicit_value
.is_split_mode();
685 std::unique_ptr
<rgw::sal::User
> user
;
687 /* Normally, empty "tenant" field of acct_user means the authenticated
688 * identity has the legacy, global tenant. However, due to inclusion
689 * of multi-tenancy, we got some special compatibility kludge for remote
690 * backends like Keystone.
691 * If the global tenant is the requested one, we try the same tenant as
692 * the user name first. If that RGWUserInfo exists, we use it. This way,
693 * migrated OpenStack users can get their namespaced containers and nobody's
695 * If that fails, we look up in the requested (possibly empty) tenant.
696 * If that fails too, we create the account within the global or separated
697 * namespace depending on rgw_keystone_implicit_tenants.
698 * For compatibility with previous versions of ceph, it is possible
699 * to enable implicit_tenants for only s3 or only swift.
700 * in this mode ("split_mode"), we must constrain the id lookups to
701 * only use the identifier space that would be used if the id were
704 if (split_mode
&& !implicit_tenant
)
705 ; /* suppress lookup for id used by "other" protocol */
706 else if (acct_user
.tenant
.empty()) {
707 const rgw_user
tenanted_uid(acct_user
.id
, acct_user
.id
);
708 user
= driver
->get_user(tenanted_uid
);
710 if (user
->load_user(dpp
, null_yield
) >= 0) {
712 user_info
= user
->get_info();
717 user
= driver
->get_user(acct_user
);
719 if (split_mode
&& implicit_tenant
)
720 ; /* suppress lookup for id used by "other" protocol */
721 else if (user
->load_user(dpp
, null_yield
) >= 0) {
723 user_info
= user
->get_info();
727 ldpp_dout(dpp
, 0) << "NOTICE: couldn't map swift user " << acct_user
<< dendl
;
728 create_account(dpp
, acct_user
, implicit_tenant
, user_info
);
730 /* Succeeded if we are here (create_account() hasn't throwed). */
733 /* rgw::auth::LocalApplier */
734 /* static declaration */
735 const std::string
rgw::auth::LocalApplier::NO_SUBUSER
;
736 const std::string
rgw::auth::LocalApplier::NO_ACCESS_KEY
;
738 uint32_t rgw::auth::LocalApplier::get_perms_from_aclspec(const DoutPrefixProvider
* dpp
, const aclspec_t
& aclspec
) const
740 return rgw_perms_from_aclspec_default_strategy(user_info
.user_id
, aclspec
, dpp
);
743 bool rgw::auth::LocalApplier::is_admin_of(const rgw_user
& uid
) const
745 return user_info
.admin
|| user_info
.system
;
748 bool rgw::auth::LocalApplier::is_owner_of(const rgw_user
& uid
) const
750 return uid
== user_info
.user_id
;
753 bool rgw::auth::LocalApplier::is_identity(const idset_t
& ids
) const {
754 for (auto& id
: ids
) {
755 if (id
.is_wildcard()) {
757 } else if (id
.is_tenant() &&
758 id
.get_tenant() == user_info
.user_id
.tenant
) {
760 } else if (id
.is_user() &&
761 (id
.get_tenant() == user_info
.user_id
.tenant
)) {
762 if (id
.get_id() == user_info
.user_id
.id
) {
765 std::string wildcard_subuser
= user_info
.user_id
.id
;
766 wildcard_subuser
.append(":*");
767 if (wildcard_subuser
== id
.get_id()) {
769 } else if (subuser
!= NO_SUBUSER
) {
770 std::string user
= user_info
.user_id
.id
;
772 user
.append(subuser
);
773 if (user
== id
.get_id()) {
782 void rgw::auth::LocalApplier::to_str(std::ostream
& out
) const {
783 out
<< "rgw::auth::LocalApplier(acct_user=" << user_info
.user_id
784 << ", acct_name=" << user_info
.display_name
785 << ", subuser=" << subuser
786 << ", perm_mask=" << get_perm_mask()
787 << ", is_admin=" << static_cast<bool>(user_info
.admin
) << ")";
790 uint32_t rgw::auth::LocalApplier::get_perm_mask(const std::string
& subuser_name
,
791 const RGWUserInfo
&uinfo
) const
793 if (! subuser_name
.empty() && subuser_name
!= NO_SUBUSER
) {
794 const auto iter
= uinfo
.subusers
.find(subuser_name
);
796 if (iter
!= std::end(uinfo
.subusers
)) {
797 return iter
->second
.perm_mask
;
799 /* Subuser specified but not found. */
800 return RGW_PERM_NONE
;
803 /* Due to backward compatibility. */
804 return RGW_PERM_FULL_CONTROL
;
808 void rgw::auth::LocalApplier::load_acct_info(const DoutPrefixProvider
* dpp
, RGWUserInfo
& user_info
) const /* out */
810 /* Load the account that belongs to the authenticated identity. An extra call
811 * to RADOS may be safely skipped in this case. */
812 user_info
= this->user_info
;
815 void rgw::auth::LocalApplier::write_ops_log_entry(rgw_log_entry
& entry
) const
817 entry
.access_key_id
= access_key_id
;
818 entry
.subuser
= subuser
;
821 void rgw::auth::RoleApplier::to_str(std::ostream
& out
) const {
822 out
<< "rgw::auth::RoleApplier(role name =" << role
.name
;
823 for (auto& policy
: role
.role_policies
) {
824 out
<< ", role policy =" << policy
;
826 out
<< ", token policy =" << token_attrs
.token_policy
;
830 bool rgw::auth::RoleApplier::is_identity(const idset_t
& ids
) const {
831 for (auto& p
: ids
) {
832 if (p
.is_wildcard()) {
834 } else if (p
.is_role()) {
835 string name
= p
.get_id();
836 string tenant
= p
.get_tenant();
837 if (name
== role
.name
&& tenant
== role
.tenant
) {
840 } else if (p
.is_assumed_role()) {
841 string tenant
= p
.get_tenant();
842 string role_session
= role
.name
+ "/" + token_attrs
.role_session_name
; //role/role-session
843 if (role
.tenant
== tenant
&& role_session
== p
.get_role_session()) {
847 string id
= p
.get_id();
848 string tenant
= p
.get_tenant();
850 if (token_attrs
.user_id
.ns
.empty()) {
851 oidc_id
= token_attrs
.user_id
.id
;
853 oidc_id
= token_attrs
.user_id
.ns
+ "$" + token_attrs
.user_id
.id
;
855 if (oidc_id
== id
&& token_attrs
.user_id
.tenant
== tenant
) {
863 void rgw::auth::RoleApplier::load_acct_info(const DoutPrefixProvider
* dpp
, RGWUserInfo
& user_info
) const /* out */
865 /* Load the user id */
866 user_info
.user_id
= this->token_attrs
.user_id
;
869 void rgw::auth::RoleApplier::modify_request_state(const DoutPrefixProvider
*dpp
, req_state
* s
) const
871 for (auto it
: role
.role_policies
) {
873 bufferlist bl
= bufferlist::static_from_string(it
);
874 const rgw::IAM::Policy
p(s
->cct
, role
.tenant
, bl
, false);
875 s
->iam_user_policies
.push_back(std::move(p
));
876 } catch (rgw::IAM::PolicyParseException
& e
) {
877 //Control shouldn't reach here as the policy has already been
879 ldpp_dout(dpp
, 20) << "failed to parse role policy: " << e
.what() << dendl
;
883 if (!this->token_attrs
.token_policy
.empty()) {
885 string policy
= this->token_attrs
.token_policy
;
886 bufferlist bl
= bufferlist::static_from_string(policy
);
887 const rgw::IAM::Policy
p(s
->cct
, role
.tenant
, bl
, false);
888 s
->session_policies
.push_back(std::move(p
));
889 } catch (rgw::IAM::PolicyParseException
& e
) {
890 //Control shouldn't reach here as the policy has already been
892 ldpp_dout(dpp
, 20) << "failed to parse token policy: " << e
.what() << dendl
;
896 string condition
= "aws:userid";
897 string value
= role
.id
+ ":" + token_attrs
.role_session_name
;
898 s
->env
.emplace(condition
, value
);
900 s
->env
.emplace("aws:TokenIssueTime", token_attrs
.token_issued_at
);
902 for (auto& m
: token_attrs
.principal_tags
) {
903 s
->env
.emplace(m
.first
, m
.second
);
904 ldpp_dout(dpp
, 10) << "Principal Tag Key: " << m
.first
<< " Value: " << m
.second
<< dendl
;
905 std::size_t pos
= m
.first
.find('/');
906 string key
= m
.first
.substr(pos
+ 1);
907 s
->env
.emplace("aws:TagKeys", key
);
908 ldpp_dout(dpp
, 10) << "aws:TagKeys: " << key
<< dendl
;
911 s
->token_claims
.emplace_back("sts");
912 s
->token_claims
.emplace_back("role_name:" + role
.tenant
+ "$" + role
.name
);
913 s
->token_claims
.emplace_back("role_session:" + token_attrs
.role_session_name
);
914 for (auto& it
: token_attrs
.token_claims
) {
915 s
->token_claims
.emplace_back(it
);
919 rgw::auth::Engine::result_t
920 rgw::auth::AnonymousEngine::authenticate(const DoutPrefixProvider
* dpp
, const req_state
* const s
, optional_yield y
) const
922 if (! is_applicable(s
)) {
923 return result_t::deny(-EPERM
);
925 RGWUserInfo user_info
;
926 rgw_get_anon_user(user_info
);
929 apl_factory
->create_apl_local(cct
, s
, user_info
,
930 rgw::auth::LocalApplier::NO_SUBUSER
,
931 std::nullopt
, rgw::auth::LocalApplier::NO_ACCESS_KEY
);
932 return result_t::grant(std::move(apl
));