]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_auth.cc
bump version to 18.2.2-pve1
[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>
f91f0fd5 5#include <string>
7c673cae
FG
6
7#include "rgw_common.h"
8#include "rgw_auth.h"
f64942e4 9#include "rgw_quota.h"
7c673cae
FG
10#include "rgw_user.h"
11#include "rgw_http_client.h"
12#include "rgw_keystone.h"
9f95a23c 13#include "rgw_sal.h"
2a845540 14#include "rgw_log.h"
7c673cae
FG
15
16#include "include/str_list.h"
17
18#define dout_context g_ceph_context
19#define dout_subsys ceph_subsys_rgw
20
20effc67 21using namespace std;
7c673cae
FG
22
23namespace rgw {
24namespace auth {
25
26std::unique_ptr<rgw::auth::Identity>
9f95a23c
TL
27transform_old_authinfo(CephContext* const cct,
28 const rgw_user& auth_id,
29 const int perm_mask,
30 const bool is_admin,
31 const uint32_t type)
7c673cae
FG
32{
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
35 * infrastructure. */
36 class DummyIdentityApplier : public rgw::auth::Identity {
37 CephContext* const cct;
38
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
41 * new auth. */
42 const rgw_user id;
43 const int perm_mask;
44 const bool is_admin;
11fdf7f2 45 const uint32_t type;
7c673cae
FG
46 public:
47 DummyIdentityApplier(CephContext* const cct,
48 const rgw_user& auth_id,
49 const int perm_mask,
11fdf7f2
TL
50 const bool is_admin,
51 const uint32_t type)
7c673cae
FG
52 : cct(cct),
53 id(auth_id),
54 perm_mask(perm_mask),
11fdf7f2
TL
55 is_admin(is_admin),
56 type(type) {
7c673cae
FG
57 }
58
11fdf7f2 59 uint32_t get_perms_from_aclspec(const DoutPrefixProvider* dpp, const aclspec_t& aclspec) const override {
b3b6e05e 60 return rgw_perms_from_aclspec_default_strategy(id, aclspec, dpp);
7c673cae
FG
61 }
62
63 bool is_admin_of(const rgw_user& acct_id) const override {
64 return is_admin;
65 }
66
67 bool is_owner_of(const rgw_user& acct_id) const override {
68 return id == acct_id;
69 }
70
31f18b77
FG
71 bool is_identity(const idset_t& ids) const override {
72 for (auto& p : ids) {
73 if (p.is_wildcard()) {
74 return true;
75 } else if (p.is_tenant() && p.get_tenant() == id.tenant) {
76 return true;
77 } else if (p.is_user() &&
78 (p.get_tenant() == id.tenant) &&
79 (p.get_id() == id.id)) {
80 return true;
81 }
82 }
83 return false;
84 }
85
7c673cae
FG
86 uint32_t get_perm_mask() const override {
87 return perm_mask;
88 }
89
11fdf7f2
TL
90 uint32_t get_identity_type() const override {
91 return type;
92 }
93
94 string get_acct_name() const override {
95 return {};
96 }
97
f6b5b4d7
TL
98 string get_subuser() const override {
99 return {};
100 }
101
7c673cae
FG
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 << ")";
106 }
107 };
108
109 return std::unique_ptr<rgw::auth::Identity>(
9f95a23c
TL
110 new DummyIdentityApplier(cct,
111 auth_id,
112 perm_mask,
113 is_admin,
114 type));
115}
116
117std::unique_ptr<rgw::auth::Identity>
118transform_old_authinfo(const req_state* const s)
119{
120 return transform_old_authinfo(s->cct,
121 s->user->get_id(),
122 s->perm_mask,
7c673cae
FG
123 /* System user has admin permissions by default - it's supposed to pass
124 * through any security check. */
9f95a23c
TL
125 s->system_request,
126 s->user->get_type());
7c673cae
FG
127}
128
129} /* namespace auth */
130} /* namespace rgw */
131
132
133uint32_t rgw_perms_from_aclspec_default_strategy(
134 const rgw_user& uid,
b3b6e05e
TL
135 const rgw::auth::Identity::aclspec_t& aclspec,
136 const DoutPrefixProvider *dpp)
7c673cae 137{
b3b6e05e 138 ldpp_dout(dpp, 5) << "Searching permissions for uid=" << uid << dendl;
7c673cae
FG
139
140 const auto iter = aclspec.find(uid.to_str());
141 if (std::end(aclspec) != iter) {
b3b6e05e 142 ldpp_dout(dpp, 5) << "Found permission: " << iter->second << dendl;
7c673cae
FG
143 return iter->second;
144 }
145
b3b6e05e 146 ldpp_dout(dpp, 5) << "Permissions for user not found" << dendl;
7c673cae
FG
147 return 0;
148}
149
150
151static inline const std::string make_spec_item(const std::string& tenant,
152 const std::string& id)
153{
154 return tenant + ":" + id;
155}
156
157
158static inline std::pair<bool, rgw::auth::Engine::result_t>
159strategy_handle_rejected(rgw::auth::Engine::result_t&& engine_result,
160 const rgw::auth::Strategy::Control policy,
161 rgw::auth::Engine::result_t&& strategy_result)
162{
163 using Control = rgw::auth::Strategy::Control;
164 switch (policy) {
165 case Control::REQUISITE:
166 /* Don't try next. */
167 return std::make_pair(false, std::move(engine_result));
168
169 case Control::SUFFICIENT:
170 /* Don't try next. */
171 return std::make_pair(false, std::move(engine_result));
172
173 case Control::FALLBACK:
174 /* Don't try next. */
175 return std::make_pair(false, std::move(strategy_result));
176
177 default:
178 /* Huh, memory corruption? */
11fdf7f2 179 ceph_abort();
7c673cae
FG
180 }
181}
182
183static inline std::pair<bool, rgw::auth::Engine::result_t>
184strategy_handle_denied(rgw::auth::Engine::result_t&& engine_result,
185 const rgw::auth::Strategy::Control policy,
186 rgw::auth::Engine::result_t&& strategy_result)
187{
188 using Control = rgw::auth::Strategy::Control;
189 switch (policy) {
190 case Control::REQUISITE:
191 /* Don't try next. */
192 return std::make_pair(false, std::move(engine_result));
193
194 case Control::SUFFICIENT:
195 /* Just try next. */
196 return std::make_pair(true, std::move(engine_result));
197
198 case Control::FALLBACK:
199 return std::make_pair(true, std::move(strategy_result));
200
201 default:
202 /* Huh, memory corruption? */
11fdf7f2 203 ceph_abort();
7c673cae
FG
204 }
205}
206
207static inline std::pair<bool, rgw::auth::Engine::result_t>
208strategy_handle_granted(rgw::auth::Engine::result_t&& engine_result,
209 const rgw::auth::Strategy::Control policy,
210 rgw::auth::Engine::result_t&& strategy_result)
211{
212 using Control = rgw::auth::Strategy::Control;
213 switch (policy) {
214 case Control::REQUISITE:
215 /* Try next. */
216 return std::make_pair(true, std::move(engine_result));
217
218 case Control::SUFFICIENT:
219 /* Don't try next. */
220 return std::make_pair(false, std::move(engine_result));
221
222 case Control::FALLBACK:
223 /* Don't try next. */
224 return std::make_pair(false, std::move(engine_result));
225
226 default:
227 /* Huh, memory corruption? */
11fdf7f2 228 ceph_abort();
7c673cae
FG
229 }
230}
231
232rgw::auth::Engine::result_t
f67539c2 233rgw::auth::Strategy::authenticate(const DoutPrefixProvider* dpp, const req_state* const s, optional_yield y) const
7c673cae
FG
234{
235 result_t strategy_result = result_t::deny();
236
237 for (const stack_item_t& kv : auth_stack) {
238 const rgw::auth::Engine& engine = kv.first;
239 const auto& policy = kv.second;
240
11fdf7f2 241 ldpp_dout(dpp, 20) << get_name() << ": trying " << engine.get_name() << dendl;
7c673cae
FG
242
243 result_t engine_result = result_t::deny();
244 try {
f67539c2 245 engine_result = engine.authenticate(dpp, s, y);
7c673cae
FG
246 } catch (const int err) {
247 engine_result = result_t::deny(err);
248 }
249
250 bool try_next = true;
251 switch (engine_result.get_status()) {
252 case result_t::Status::REJECTED: {
11fdf7f2 253 ldpp_dout(dpp, 20) << engine.get_name() << " rejected with reason="
7c673cae
FG
254 << engine_result.get_reason() << dendl;
255
256 std::tie(try_next, strategy_result) = \
257 strategy_handle_rejected(std::move(engine_result), policy,
258 std::move(strategy_result));
259 break;
260 }
261 case result_t::Status::DENIED: {
11fdf7f2 262 ldpp_dout(dpp, 20) << engine.get_name() << " denied with reason="
7c673cae
FG
263 << engine_result.get_reason() << dendl;
264
265 std::tie(try_next, strategy_result) = \
266 strategy_handle_denied(std::move(engine_result), policy,
267 std::move(strategy_result));
268 break;
269 }
270 case result_t::Status::GRANTED: {
11fdf7f2 271 ldpp_dout(dpp, 20) << engine.get_name() << " granted access" << dendl;
7c673cae
FG
272
273 std::tie(try_next, strategy_result) = \
274 strategy_handle_granted(std::move(engine_result), policy,
275 std::move(strategy_result));
276 break;
277 }
278 default: {
11fdf7f2 279 ceph_abort();
7c673cae
FG
280 }
281 }
282
283 if (! try_next) {
284 break;
285 }
286 }
287
288 return strategy_result;
289}
290
31f18b77 291int
11fdf7f2 292rgw::auth::Strategy::apply(const DoutPrefixProvider *dpp, const rgw::auth::Strategy& auth_strategy,
f67539c2 293 req_state* const s, optional_yield y) noexcept
31f18b77
FG
294{
295 try {
f67539c2 296 auto result = auth_strategy.authenticate(dpp, s, y);
31f18b77
FG
297 if (result.get_status() != decltype(result)::Status::GRANTED) {
298 /* Access denied is acknowledged by returning a std::unique_ptr with
299 * nullptr inside. */
11fdf7f2 300 ldpp_dout(dpp, 5) << "Failed the auth strategy, reason="
31f18b77
FG
301 << result.get_reason() << dendl;
302 return result.get_reason();
303 }
304
305 try {
306 rgw::auth::IdentityApplier::aplptr_t applier = result.get_applier();
307 rgw::auth::Completer::cmplptr_t completer = result.get_completer();
308
309 /* Account used by a given RGWOp is decoupled from identity employed
310 * in the authorization phase (RGWOp::verify_permissions). */
9f95a23c 311 applier->load_acct_info(dpp, s->user->get_info());
31f18b77
FG
312 s->perm_mask = applier->get_perm_mask();
313
11fdf7f2 314 /* This is the single place where we pass req_state as a pointer
31f18b77
FG
315 * to non-const and thus its modification is allowed. In the time
316 * of writing only RGWTempURLEngine needed that feature. */
11fdf7f2 317 applier->modify_request_state(dpp, s);
31f18b77 318 if (completer) {
11fdf7f2 319 completer->modify_request_state(dpp, s);
31f18b77
FG
320 }
321
322 s->auth.identity = std::move(applier);
323 s->auth.completer = std::move(completer);
324
325 return 0;
326 } catch (const int err) {
11fdf7f2 327 ldpp_dout(dpp, 5) << "applier throwed err=" << err << dendl;
31f18b77 328 return err;
f67539c2
TL
329 } catch (const std::exception& e) {
330 ldpp_dout(dpp, 5) << "applier throwed unexpected err: " << e.what()
331 << dendl;
332 return -EPERM;
31f18b77
FG
333 }
334 } catch (const int err) {
11fdf7f2 335 ldpp_dout(dpp, 5) << "auth engine throwed err=" << err << dendl;
31f18b77 336 return err;
f67539c2
TL
337 } catch (const std::exception& e) {
338 ldpp_dout(dpp, 5) << "auth engine throwed unexpected err: " << e.what()
339 << dendl;
31f18b77
FG
340 }
341
342 /* We never should be here. */
343 return -EPERM;
344}
345
7c673cae
FG
346void
347rgw::auth::Strategy::add_engine(const Control ctrl_flag,
348 const Engine& engine) noexcept
349{
350 auth_stack.push_back(std::make_pair(std::cref(engine), ctrl_flag));
351}
352
11fdf7f2
TL
353void rgw::auth::WebIdentityApplier::to_str(std::ostream& out) const
354{
20effc67
TL
355 out << "rgw::auth::WebIdentityApplier(sub =" << sub
356 << ", user_name=" << user_name
357 << ", provider_id =" << iss << ")";
11fdf7f2
TL
358}
359
360string rgw::auth::WebIdentityApplier::get_idp_url() const
361{
20effc67 362 string idp_url = this->iss;
f91f0fd5 363 idp_url = url_remove_prefix(idp_url);
11fdf7f2
TL
364 return idp_url;
365}
366
f67539c2
TL
367void 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 */
371{
1e59de90 372 std::unique_ptr<rgw::sal::User> user = driver->get_user(acct_user);
20effc67
TL
373 user->get_info().display_name = display_name;
374 user->get_info().type = TYPE_WEB;
375 user->get_info().max_buckets =
f67539c2 376 cct->_conf.get_val<int64_t>("rgw_user_max_buckets");
1e59de90
TL
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);
f67539c2 379
20effc67 380 int ret = user->store_user(dpp, null_yield, true);
f67539c2
TL
381 if (ret < 0) {
382 ldpp_dout(dpp, 0) << "ERROR: failed to store new user info: user="
20effc67 383 << user << " ret=" << ret << dendl;
f67539c2
TL
384 throw ret;
385 }
20effc67 386 user_info = user->get_info();
f67539c2
TL
387}
388
389void rgw::auth::WebIdentityApplier::load_acct_info(const DoutPrefixProvider* dpp, RGWUserInfo& user_info) const {
390 rgw_user federated_user;
20effc67 391 federated_user.id = this->sub;
f67539c2
TL
392 federated_user.tenant = role_tenant;
393 federated_user.ns = "oidc";
394
1e59de90 395 std::unique_ptr<rgw::sal::User> user = driver->get_user(federated_user);
20effc67 396
f67539c2 397 //Check in oidc namespace
20effc67 398 if (user->load_user(dpp, null_yield) >= 0) {
f67539c2 399 /* Succeeded. */
20effc67 400 user_info = user->get_info();
f67539c2
TL
401 return;
402 }
403
20effc67 404 user->clear_ns();
f67539c2 405 //Check for old users which wouldn't have been created in oidc namespace
20effc67 406 if (user->load_user(dpp, null_yield) >= 0) {
f67539c2 407 /* Succeeded. */
20effc67 408 user_info = user->get_info();
f67539c2
TL
409 return;
410 }
411
412 //Check if user_id.buckets already exists, may have been from the time, when shadow users didnt exist
413 RGWStorageStats stats;
20effc67 414 int ret = user->read_stats(dpp, null_yield, &stats);
f67539c2
TL
415 if (ret < 0 && ret != -ENOENT) {
416 ldpp_dout(dpp, 0) << "ERROR: reading stats for the user returned error " << ret << dendl;
417 return;
418 }
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";
423 } else {
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 = "";
427 }
428
429 ldpp_dout(dpp, 0) << "NOTICE: couldn't map oidc federated user " << federated_user << dendl;
20effc67 430 create_account(dpp, federated_user, this->user_name, user_info);
f67539c2
TL
431}
432
11fdf7f2
TL
433void rgw::auth::WebIdentityApplier::modify_request_state(const DoutPrefixProvider *dpp, req_state* s) const
434{
20effc67
TL
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);
11fdf7f2 439
20effc67 440 string condition;
11fdf7f2 441 string idp_url = get_idp_url();
20effc67
TL
442 for (auto& claim : token_claims) {
443 if (claim.first == "aud") {
444 condition.clear();
445 condition = idp_url + ":app_id";
446 s->env.emplace(condition, claim.second);
447 }
448 condition.clear();
449 condition = idp_url + ":" + claim.first;
450 s->env.emplace(condition, claim.second);
451 }
452
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;
461 continue;
462 }
463 if (key.size() > KEY_SIZE || val.size() > VAL_SIZE) {
464 ldpp_dout(dpp, 0) << "ERROR: Invalid tag/value size, hence skipping it" << dendl;
465 continue;
466 }
467 std::string p_key = "aws:PrincipalTag/";
468 p_key.append(key);
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;
471
472 std::string e_key = "aws:RequestTag/";
473 e_key.append(key);
474 s->env.emplace(e_key, val);
475 ldpp_dout(dpp, 10) << "RGW Env Tag Key: " << e_key << " Value: " << val << dendl;
f91f0fd5 476
20effc67
TL
477 s->env.emplace("aws:TagKeys", key);
478 ldpp_dout(dpp, 10) << "aws:TagKeys: " << key << dendl;
f91f0fd5 479
20effc67
TL
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;
482 break;
483 }
484 }
485 }
486
487 if (role_tags) {
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;
493
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;
498 }
499 }
11fdf7f2
TL
500}
501
502bool rgw::auth::WebIdentityApplier::is_identity(const idset_t& ids) const
503{
504 if (ids.size() > 1) {
505 return false;
506 }
507
508 for (auto id : ids) {
509 string idp_url = get_idp_url();
510 if (id.is_oidc_provider() && id.get_idp_url() == idp_url) {
511 return true;
512 }
513 }
514 return false;
515}
7c673cae 516
2a845540
TL
517const std::string rgw::auth::RemoteApplier::AuthInfo::NO_SUBUSER;
518const std::string rgw::auth::RemoteApplier::AuthInfo::NO_ACCESS_KEY;
519
7c673cae 520/* rgw::auth::RemoteAuthApplier */
11fdf7f2 521uint32_t rgw::auth::RemoteApplier::get_perms_from_aclspec(const DoutPrefixProvider* dpp, const aclspec_t& aclspec) const
7c673cae
FG
522{
523 uint32_t perm = 0;
524
525 /* For backward compatibility with ACLOwner. */
526 perm |= rgw_perms_from_aclspec_default_strategy(info.acct_user,
b3b6e05e 527 aclspec, dpp);
7c673cae
FG
528
529 /* We also need to cover cases where rgw_keystone_implicit_tenants
530 * was enabled. */
531 if (info.acct_user.tenant.empty()) {
532 const rgw_user tenanted_acct_user(info.acct_user.id, info.acct_user.id);
533
534 perm |= rgw_perms_from_aclspec_default_strategy(tenanted_acct_user,
b3b6e05e 535 aclspec, dpp);
7c673cae
FG
536 }
537
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);
542 }
543
11fdf7f2 544 ldpp_dout(dpp, 20) << "from ACL got perm=" << perm << dendl;
7c673cae
FG
545 return perm;
546}
547
548bool rgw::auth::RemoteApplier::is_admin_of(const rgw_user& uid) const
549{
550 return info.is_admin;
551}
552
553bool rgw::auth::RemoteApplier::is_owner_of(const rgw_user& uid) const
554{
555 if (info.acct_user.tenant.empty()) {
556 const rgw_user tenanted_acct_user(info.acct_user.id, info.acct_user.id);
557
558 if (tenanted_acct_user == uid) {
559 return true;
560 }
561 }
562
563 return info.acct_user == uid;
564}
565
31f18b77
FG
566bool rgw::auth::RemoteApplier::is_identity(const idset_t& ids) const {
567 for (auto& id : ids) {
568 if (id.is_wildcard()) {
569 return true;
570
571 // We also need to cover cases where rgw_keystone_implicit_tenants
572 // was enabled. */
573 } else if (id.is_tenant() &&
574 (info.acct_user.tenant.empty() ?
575 info.acct_user.id :
576 info.acct_user.tenant) == id.get_tenant()) {
577 return true;
578 } else if (id.is_user() &&
579 info.acct_user.id == id.get_id() &&
580 (info.acct_user.tenant.empty() ?
581 info.acct_user.id :
582 info.acct_user.tenant) == id.get_tenant()) {
583 return true;
584 }
585 }
586 return false;
587}
588
7c673cae
FG
589void rgw::auth::RemoteApplier::to_str(std::ostream& out) const
590{
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 << ")";
595}
596
9f95a23c
TL
597void rgw::auth::ImplicitTenants::recompute_value(const ConfigProxy& c)
598{
599 std::string s = c.get_val<std::string>("rgw_keystone_implicit_tenants");
600 int v = 0;
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")) {
608 v = 0;
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;
615 // assert(0);
616 }
617 saved = v;
618}
619
620const char **rgw::auth::ImplicitTenants::get_tracked_conf_keys() const
621{
622 static const char *keys[] = {
623 "rgw_keystone_implicit_tenants",
624 nullptr };
625 return keys;
626}
627
628void rgw::auth::ImplicitTenants::handle_conf_change(const ConfigProxy& c,
629 const std::set <std::string> &changed)
630{
631 if (changed.count("rgw_keystone_implicit_tenants")) {
632 recompute_value(c);
633 }
634}
635
11fdf7f2
TL
636void rgw::auth::RemoteApplier::create_account(const DoutPrefixProvider* dpp,
637 const rgw_user& acct_user,
9f95a23c 638 bool implicit_tenant,
7c673cae
FG
639 RGWUserInfo& user_info) const /* out */
640{
641 rgw_user new_acct_user = acct_user;
642
7c673cae
FG
643 /* An upper layer may enforce creating new accounts within their own
644 * tenants. */
9f95a23c 645 if (new_acct_user.tenant.empty() && implicit_tenant) {
7c673cae
FG
646 new_acct_user.tenant = new_acct_user.id;
647 }
648
1e59de90 649 std::unique_ptr<rgw::sal::User> user = driver->get_user(new_acct_user);
20effc67
TL
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;
654 }
655 user->get_info().max_buckets =
f6b5b4d7 656 cct->_conf.get_val<int64_t>("rgw_user_max_buckets");
1e59de90
TL
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);
20effc67 659 user_info = user->get_info();
f64942e4 660
20effc67 661 int ret = user->store_user(dpp, null_yield, true);
7c673cae 662 if (ret < 0) {
11fdf7f2 663 ldpp_dout(dpp, 0) << "ERROR: failed to store new user info: user="
20effc67 664 << user << " ret=" << ret << dendl;
7c673cae
FG
665 throw ret;
666 }
667}
668
2a845540
TL
669void rgw::auth::RemoteApplier::write_ops_log_entry(rgw_log_entry& entry) const
670{
671 entry.access_key_id = info.access_key_id;
672 entry.subuser = info.subuser;
673}
674
7c673cae 675/* TODO(rzarzynski): we need to handle display_name changes. */
11fdf7f2 676void rgw::auth::RemoteApplier::load_acct_info(const DoutPrefixProvider* dpp, RGWUserInfo& user_info) const /* out */
7c673cae
FG
677{
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;
9f95a23c
TL
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();
20effc67 685 std::unique_ptr<rgw::sal::User> user;
7c673cae
FG
686
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
694 * the wiser.
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
9f95a23c
TL
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
702 * to be created. */
703
704 if (split_mode && !implicit_tenant)
705 ; /* suppress lookup for id used by "other" protocol */
706 else if (acct_user.tenant.empty()) {
7c673cae 707 const rgw_user tenanted_uid(acct_user.id, acct_user.id);
1e59de90 708 user = driver->get_user(tenanted_uid);
7c673cae 709
20effc67 710 if (user->load_user(dpp, null_yield) >= 0) {
7c673cae 711 /* Succeeded. */
20effc67 712 user_info = user->get_info();
7c673cae
FG
713 return;
714 }
715 }
716
1e59de90 717 user = driver->get_user(acct_user);
20effc67 718
9f95a23c
TL
719 if (split_mode && implicit_tenant)
720 ; /* suppress lookup for id used by "other" protocol */
20effc67
TL
721 else if (user->load_user(dpp, null_yield) >= 0) {
722 /* Succeeded. */
723 user_info = user->get_info();
724 return;
7c673cae
FG
725 }
726
9f95a23c
TL
727 ldpp_dout(dpp, 0) << "NOTICE: couldn't map swift user " << acct_user << dendl;
728 create_account(dpp, acct_user, implicit_tenant, user_info);
729
7c673cae
FG
730 /* Succeeded if we are here (create_account() hasn't throwed). */
731}
732
7c673cae
FG
733/* rgw::auth::LocalApplier */
734/* static declaration */
735const std::string rgw::auth::LocalApplier::NO_SUBUSER;
2a845540 736const std::string rgw::auth::LocalApplier::NO_ACCESS_KEY;
7c673cae 737
11fdf7f2 738uint32_t rgw::auth::LocalApplier::get_perms_from_aclspec(const DoutPrefixProvider* dpp, const aclspec_t& aclspec) const
7c673cae 739{
b3b6e05e 740 return rgw_perms_from_aclspec_default_strategy(user_info.user_id, aclspec, dpp);
7c673cae
FG
741}
742
743bool rgw::auth::LocalApplier::is_admin_of(const rgw_user& uid) const
744{
745 return user_info.admin || user_info.system;
746}
747
748bool rgw::auth::LocalApplier::is_owner_of(const rgw_user& uid) const
749{
750 return uid == user_info.user_id;
751}
752
31f18b77
FG
753bool rgw::auth::LocalApplier::is_identity(const idset_t& ids) const {
754 for (auto& id : ids) {
755 if (id.is_wildcard()) {
756 return true;
757 } else if (id.is_tenant() &&
758 id.get_tenant() == user_info.user_id.tenant) {
759 return true;
760 } else if (id.is_user() &&
9f95a23c
TL
761 (id.get_tenant() == user_info.user_id.tenant)) {
762 if (id.get_id() == user_info.user_id.id) {
763 return true;
764 }
f6b5b4d7
TL
765 std::string wildcard_subuser = user_info.user_id.id;
766 wildcard_subuser.append(":*");
767 if (wildcard_subuser == id.get_id()) {
768 return true;
769 } else if (subuser != NO_SUBUSER) {
9f95a23c
TL
770 std::string user = user_info.user_id.id;
771 user.append(":");
772 user.append(subuser);
773 if (user == id.get_id()) {
774 return true;
775 }
776 }
31f18b77
FG
777 }
778 }
779 return false;
780}
781
782void rgw::auth::LocalApplier::to_str(std::ostream& out) const {
7c673cae
FG
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) << ")";
788}
789
790uint32_t rgw::auth::LocalApplier::get_perm_mask(const std::string& subuser_name,
791 const RGWUserInfo &uinfo) const
792{
793 if (! subuser_name.empty() && subuser_name != NO_SUBUSER) {
794 const auto iter = uinfo.subusers.find(subuser_name);
795
796 if (iter != std::end(uinfo.subusers)) {
797 return iter->second.perm_mask;
798 } else {
799 /* Subuser specified but not found. */
800 return RGW_PERM_NONE;
801 }
802 } else {
803 /* Due to backward compatibility. */
804 return RGW_PERM_FULL_CONTROL;
805 }
806}
807
11fdf7f2 808void rgw::auth::LocalApplier::load_acct_info(const DoutPrefixProvider* dpp, RGWUserInfo& user_info) const /* out */
7c673cae
FG
809{
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;
813}
814
2a845540
TL
815void rgw::auth::LocalApplier::write_ops_log_entry(rgw_log_entry& entry) const
816{
817 entry.access_key_id = access_key_id;
818 entry.subuser = subuser;
819}
820
11fdf7f2 821void rgw::auth::RoleApplier::to_str(std::ostream& out) const {
20effc67 822 out << "rgw::auth::RoleApplier(role name =" << role.name;
f91f0fd5 823 for (auto& policy: role.role_policies) {
11fdf7f2
TL
824 out << ", role policy =" << policy;
825 }
20effc67 826 out << ", token policy =" << token_attrs.token_policy;
11fdf7f2
TL
827 out << ")";
828}
829
830bool rgw::auth::RoleApplier::is_identity(const idset_t& ids) const {
831 for (auto& p : ids) {
11fdf7f2
TL
832 if (p.is_wildcard()) {
833 return true;
f91f0fd5
TL
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) {
838 return true;
839 }
840 } else if (p.is_assumed_role()) {
841 string tenant = p.get_tenant();
20effc67 842 string role_session = role.name + "/" + token_attrs.role_session_name; //role/role-session
f91f0fd5
TL
843 if (role.tenant == tenant && role_session == p.get_role_session()) {
844 return true;
845 }
846 } else {
847 string id = p.get_id();
f67539c2
TL
848 string tenant = p.get_tenant();
849 string oidc_id;
20effc67
TL
850 if (token_attrs.user_id.ns.empty()) {
851 oidc_id = token_attrs.user_id.id;
f67539c2 852 } else {
20effc67 853 oidc_id = token_attrs.user_id.ns + "$" + token_attrs.user_id.id;
f67539c2 854 }
20effc67 855 if (oidc_id == id && token_attrs.user_id.tenant == tenant) {
f91f0fd5
TL
856 return true;
857 }
11fdf7f2
TL
858 }
859 }
860 return false;
861}
862
863void rgw::auth::RoleApplier::load_acct_info(const DoutPrefixProvider* dpp, RGWUserInfo& user_info) const /* out */
864{
865 /* Load the user id */
20effc67 866 user_info.user_id = this->token_attrs.user_id;
11fdf7f2
TL
867}
868
869void rgw::auth::RoleApplier::modify_request_state(const DoutPrefixProvider *dpp, req_state* s) const
870{
f91f0fd5 871 for (auto it: role.role_policies) {
11fdf7f2
TL
872 try {
873 bufferlist bl = bufferlist::static_from_string(it);
1e59de90 874 const rgw::IAM::Policy p(s->cct, role.tenant, bl, false);
11fdf7f2
TL
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
878 //verified earlier
f91f0fd5 879 ldpp_dout(dpp, 20) << "failed to parse role policy: " << e.what() << dendl;
11fdf7f2
TL
880 }
881 }
f91f0fd5 882
20effc67 883 if (!this->token_attrs.token_policy.empty()) {
522d829b 884 try {
20effc67 885 string policy = this->token_attrs.token_policy;
522d829b 886 bufferlist bl = bufferlist::static_from_string(policy);
1e59de90 887 const rgw::IAM::Policy p(s->cct, role.tenant, bl, false);
522d829b
TL
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
891 //verified earlier
892 ldpp_dout(dpp, 20) << "failed to parse token policy: " << e.what() << dendl;
893 }
f91f0fd5
TL
894 }
895
896 string condition = "aws:userid";
20effc67 897 string value = role.id + ":" + token_attrs.role_session_name;
f91f0fd5 898 s->env.emplace(condition, value);
adb31ebb 899
20effc67
TL
900 s->env.emplace("aws:TokenIssueTime", token_attrs.token_issued_at);
901
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;
909 }
f67539c2 910
adb31ebb 911 s->token_claims.emplace_back("sts");
20effc67
TL
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) {
adb31ebb
TL
915 s->token_claims.emplace_back(it);
916 }
11fdf7f2 917}
7c673cae
FG
918
919rgw::auth::Engine::result_t
f67539c2 920rgw::auth::AnonymousEngine::authenticate(const DoutPrefixProvider* dpp, const req_state* const s, optional_yield y) const
7c673cae
FG
921{
922 if (! is_applicable(s)) {
31f18b77 923 return result_t::deny(-EPERM);
7c673cae
FG
924 } else {
925 RGWUserInfo user_info;
926 rgw_get_anon_user(user_info);
927
d2e6a577
FG
928 auto apl = \
929 apl_factory->create_apl_local(cct, s, user_info,
11fdf7f2 930 rgw::auth::LocalApplier::NO_SUBUSER,
2a845540 931 std::nullopt, rgw::auth::LocalApplier::NO_ACCESS_KEY);
7c673cae
FG
932 return result_t::grant(std::move(apl));
933 }
934}