]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_rest_sts.cc
import ceph pacific 16.2.5
[ceph.git] / ceph / src / rgw / rgw_rest_sts.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 #include <vector>
4 #include <string>
5 #include <array>
6 #include <string_view>
7 #include <sstream>
8 #include <memory>
9
10 #include <boost/algorithm/string/predicate.hpp>
11 #include <boost/format.hpp>
12 #include <boost/optional.hpp>
13 #include <boost/utility/in_place_factory.hpp>
14 #include <boost/tokenizer.hpp>
15
16
17
18 #include "ceph_ver.h"
19 #include "common/Formatter.h"
20 #include "common/utf8.h"
21 #include "common/ceph_json.h"
22
23 #include "rgw_rest.h"
24 #include "rgw_auth.h"
25 #include "rgw_auth_registry.h"
26 #include "jwt-cpp/jwt.h"
27 #include "rgw_rest_sts.h"
28
29 #include "rgw_formats.h"
30 #include "rgw_client_io.h"
31
32 #include "rgw_request.h"
33 #include "rgw_process.h"
34 #include "rgw_iam_policy.h"
35 #include "rgw_iam_policy_keywords.h"
36
37 #include "rgw_sts.h"
38 #include "rgw_rest_oidc_provider.h"
39
40
41 #define dout_context g_ceph_context
42 #define dout_subsys ceph_subsys_rgw
43
44 namespace rgw::auth::sts {
45
46 bool
47 WebTokenEngine::is_applicable(const std::string& token) const noexcept
48 {
49 return ! token.empty();
50 }
51
52 std::string
53 WebTokenEngine::get_role_tenant(const string& role_arn) const
54 {
55 string tenant;
56 auto r_arn = rgw::ARN::parse(role_arn);
57 if (r_arn) {
58 tenant = r_arn->account;
59 }
60 return tenant;
61 }
62
63 boost::optional<RGWOIDCProvider>
64 WebTokenEngine::get_provider(const DoutPrefixProvider *dpp, const string& role_arn, const string& iss) const
65 {
66 string tenant = get_role_tenant(role_arn);
67
68 string idp_url = iss;
69 auto pos = idp_url.find("http://");
70 if (pos == std::string::npos) {
71 pos = idp_url.find("https://");
72 if (pos != std::string::npos) {
73 idp_url.erase(pos, 8);
74 } else {
75 pos = idp_url.find("www.");
76 if (pos != std::string::npos) {
77 idp_url.erase(pos, 4);
78 }
79 }
80 } else {
81 idp_url.erase(pos, 7);
82 }
83 auto provider_arn = rgw::ARN(idp_url, "oidc-provider", tenant);
84 string p_arn = provider_arn.to_string();
85 RGWOIDCProvider provider(cct, ctl, p_arn, tenant);
86 auto ret = provider.get(dpp);
87 if (ret < 0) {
88 return boost::none;
89 }
90 return provider;
91 }
92
93 bool
94 WebTokenEngine::is_client_id_valid(vector<string>& client_ids, const string& client_id) const
95 {
96 for (auto it : client_ids) {
97 if (it == client_id) {
98 return true;
99 }
100 }
101 return false;
102 }
103
104 bool
105 WebTokenEngine::is_cert_valid(const vector<string>& thumbprints, const string& cert) const
106 {
107 //calculate thumbprint of cert
108 std::unique_ptr<BIO, decltype(&BIO_free_all)> certbio(BIO_new_mem_buf(cert.data(), cert.size()), BIO_free_all);
109 std::unique_ptr<BIO, decltype(&BIO_free_all)> keybio(BIO_new(BIO_s_mem()), BIO_free_all);
110 string pw="";
111 std::unique_ptr<X509, decltype(&X509_free)> x_509cert(PEM_read_bio_X509(certbio.get(), nullptr, nullptr, const_cast<char*>(pw.c_str())), X509_free);
112 const EVP_MD* fprint_type = EVP_sha1();
113 unsigned int fprint_size;
114 unsigned char fprint[EVP_MAX_MD_SIZE];
115
116 if (!X509_digest(x_509cert.get(), fprint_type, fprint, &fprint_size)) {
117 return false;
118 }
119 stringstream ss;
120 for (unsigned int i = 0; i < fprint_size; i++) {
121 ss << std::setfill('0') << std::setw(2) << std::hex << (0xFF & (unsigned int)fprint[i]);
122 }
123 std::string digest = ss.str();
124
125 for (auto& it : thumbprints) {
126 if (boost::iequals(it,digest)) {
127 return true;
128 }
129 }
130 return false;
131 }
132
133 //Offline validation of incoming Web Token which is a signed JWT (JSON Web Token)
134 boost::optional<WebTokenEngine::token_t>
135 WebTokenEngine::get_from_jwt(const DoutPrefixProvider* dpp, const std::string& token, const req_state* const s,
136 optional_yield y) const
137 {
138 WebTokenEngine::token_t t;
139 try {
140 const auto& decoded = jwt::decode(token);
141
142 auto& payload = decoded.get_payload();
143 ldpp_dout(dpp, 20) << " payload = " << payload << dendl;
144 if (decoded.has_issuer()) {
145 t.iss = decoded.get_issuer();
146 }
147 if (decoded.has_audience()) {
148 auto aud = decoded.get_audience();
149 t.aud = *(aud.begin());
150 }
151 if (decoded.has_subject()) {
152 t.sub = decoded.get_subject();
153 }
154 if (decoded.has_payload_claim("client_id")) {
155 t.client_id = decoded.get_payload_claim("client_id").as_string();
156 }
157 if (t.client_id.empty() && decoded.has_payload_claim("clientId")) {
158 t.client_id = decoded.get_payload_claim("clientId").as_string();
159 }
160 string role_arn = s->info.args.get("RoleArn");
161 auto provider = get_provider(dpp, role_arn, t.iss);
162 if (! provider) {
163 ldpp_dout(dpp, 0) << "Couldn't get oidc provider info using input iss" << t.iss << dendl;
164 throw -EACCES;
165 }
166 vector<string> client_ids = provider->get_client_ids();
167 vector<string> thumbprints = provider->get_thumbprints();
168 if (! client_ids.empty()) {
169 if (! is_client_id_valid(client_ids, t.client_id) && ! is_client_id_valid(client_ids, t.aud)) {
170 ldpp_dout(dpp, 0) << "Client id in token doesn't match with that registered with oidc provider" << dendl;
171 throw -EACCES;
172 }
173 }
174 //Validate signature
175 if (decoded.has_algorithm()) {
176 auto& algorithm = decoded.get_algorithm();
177 try {
178 validate_signature(dpp, decoded, algorithm, t.iss, thumbprints, y);
179 } catch (...) {
180 throw -EACCES;
181 }
182 } else {
183 return boost::none;
184 }
185 } catch (int error) {
186 if (error == -EACCES) {
187 throw -EACCES;
188 }
189 ldpp_dout(dpp, 5) << "Invalid JWT token" << dendl;
190 return boost::none;
191 }
192 catch (...) {
193 ldpp_dout(dpp, 5) << "Invalid JWT token" << dendl;
194 return boost::none;
195 }
196 return t;
197 }
198
199 void
200 WebTokenEngine::validate_signature(const DoutPrefixProvider* dpp, const jwt::decoded_jwt& decoded, const string& algorithm, const string& iss, const vector<string>& thumbprints, optional_yield y) const
201 {
202 if (algorithm != "HS256" && algorithm != "HS384" && algorithm != "HS512") {
203 // Get certificate
204 string cert_url = iss + "/protocol/openid-connect/certs";
205 bufferlist cert_resp;
206 RGWHTTPTransceiver cert_req(cct, "GET", cert_url, &cert_resp);
207 //Headers
208 cert_req.append_header("Content-Type", "application/x-www-form-urlencoded");
209
210 int res = cert_req.process(y);
211 if (res < 0) {
212 ldpp_dout(dpp, 10) << "HTTP request res: " << res << dendl;
213 throw -EINVAL;
214 }
215 //Debug only
216 ldpp_dout(dpp, 20) << "HTTP status: " << cert_req.get_http_status() << dendl;
217 ldpp_dout(dpp, 20) << "JSON Response is: " << cert_resp.c_str() << dendl;
218
219 JSONParser parser;
220 if (parser.parse(cert_resp.c_str(), cert_resp.length())) {
221 JSONObj::data_val val;
222 if (parser.get_data("keys", &val)) {
223 if (val.str[0] == '[') {
224 val.str.erase(0, 1);
225 }
226 if (val.str[val.str.size() - 1] == ']') {
227 val.str = val.str.erase(val.str.size() - 1, 1);
228 }
229 if (parser.parse(val.str.c_str(), val.str.size())) {
230 vector<string> x5c;
231 if (JSONDecoder::decode_json("x5c", x5c, &parser)) {
232 string cert;
233 bool found_valid_cert = false;
234 for (auto& it : x5c) {
235 cert = "-----BEGIN CERTIFICATE-----\n" + it + "\n-----END CERTIFICATE-----";
236 ldpp_dout(dpp, 20) << "Certificate is: " << cert.c_str() << dendl;
237 if (is_cert_valid(thumbprints, cert)) {
238 found_valid_cert = true;
239 break;
240 }
241 found_valid_cert = true;
242 }
243 if (! found_valid_cert) {
244 ldpp_dout(dpp, 0) << "Cert doesn't match that with the thumbprints registered with oidc provider: " << cert.c_str() << dendl;
245 throw -EINVAL;
246 }
247 try {
248 //verify method takes care of expired tokens also
249 if (algorithm == "RS256") {
250 auto verifier = jwt::verify()
251 .allow_algorithm(jwt::algorithm::rs256{cert});
252
253 verifier.verify(decoded);
254 } else if (algorithm == "RS384") {
255 auto verifier = jwt::verify()
256 .allow_algorithm(jwt::algorithm::rs384{cert});
257
258 verifier.verify(decoded);
259 } else if (algorithm == "RS512") {
260 auto verifier = jwt::verify()
261 .allow_algorithm(jwt::algorithm::rs512{cert});
262
263 verifier.verify(decoded);
264 } else if (algorithm == "ES256") {
265 auto verifier = jwt::verify()
266 .allow_algorithm(jwt::algorithm::es256{cert});
267
268 verifier.verify(decoded);
269 } else if (algorithm == "ES384") {
270 auto verifier = jwt::verify()
271 .allow_algorithm(jwt::algorithm::es384{cert});
272
273 verifier.verify(decoded);
274 } else if (algorithm == "ES512") {
275 auto verifier = jwt::verify()
276 .allow_algorithm(jwt::algorithm::es512{cert});
277
278 verifier.verify(decoded);
279 } else if (algorithm == "PS256") {
280 auto verifier = jwt::verify()
281 .allow_algorithm(jwt::algorithm::ps256{cert});
282
283 verifier.verify(decoded);
284 } else if (algorithm == "PS384") {
285 auto verifier = jwt::verify()
286 .allow_algorithm(jwt::algorithm::ps384{cert});
287
288 verifier.verify(decoded);
289 } else if (algorithm == "PS512") {
290 auto verifier = jwt::verify()
291 .allow_algorithm(jwt::algorithm::ps512{cert});
292
293 verifier.verify(decoded);
294 }
295 } catch (std::runtime_error& e) {
296 ldpp_dout(dpp, 0) << "Signature validation failed: " << e.what() << dendl;
297 throw;
298 }
299 catch (...) {
300 ldpp_dout(dpp, 0) << "Signature validation failed" << dendl;
301 throw;
302 }
303 } else {
304 ldpp_dout(dpp, 0) << "x5c not present" << dendl;
305 throw -EINVAL;
306 }
307 } else {
308 ldpp_dout(dpp, 0) << "Malformed JSON object for keys" << dendl;
309 throw -EINVAL;
310 }
311 } else {
312 ldpp_dout(dpp, 0) << "keys not present in JSON" << dendl;
313 throw -EINVAL;
314 } //if-else get-data
315 } else {
316 ldpp_dout(dpp, 0) << "Malformed json returned while fetching cert" << dendl;
317 throw -EINVAL;
318 } //if-else parser cert_resp
319 } else {
320 ldpp_dout(dpp, 0) << "JWT signed by HMAC algos are currently not supported" << dendl;
321 throw -EINVAL;
322 }
323 }
324
325 WebTokenEngine::result_t
326 WebTokenEngine::authenticate( const DoutPrefixProvider* dpp,
327 const std::string& token,
328 const req_state* const s,
329 optional_yield y) const
330 {
331 boost::optional<WebTokenEngine::token_t> t;
332
333 if (! is_applicable(token)) {
334 return result_t::deny();
335 }
336
337 try {
338 t = get_from_jwt(dpp, token, s, y);
339 }
340 catch (...) {
341 return result_t::deny(-EACCES);
342 }
343
344 if (t) {
345 string role_session = s->info.args.get("RoleSessionName");
346 if (role_session.empty()) {
347 ldpp_dout(dpp, 0) << "Role Session Name is empty " << dendl;
348 return result_t::deny(-EACCES);
349 }
350 string role_arn = s->info.args.get("RoleArn");
351 string role_tenant = get_role_tenant(role_arn);
352 auto apl = apl_factory->create_apl_web_identity(cct, s, role_session, role_tenant, *t);
353 return result_t::grant(std::move(apl));
354 }
355 return result_t::deny(-EACCES);
356 }
357
358 } // namespace rgw::auth::sts
359
360 int RGWREST_STS::verify_permission(optional_yield y)
361 {
362 STS::STSService _sts(s->cct, store, s->user->get_id(), s->auth.identity.get());
363 sts = std::move(_sts);
364
365 string rArn = s->info.args.get("RoleArn");
366 const auto& [ret, role] = sts.getRoleInfo(s, rArn, y);
367 if (ret < 0) {
368 ldpp_dout(this, 0) << "failed to get role info using role arn: " << rArn << dendl;
369 return ret;
370 }
371 string policy = role.get_assume_role_policy();
372 buffer::list bl = buffer::list::static_from_string(policy);
373
374 //Parse the policy
375 //TODO - This step should be part of Role Creation
376 try {
377 const rgw::IAM::Policy p(s->cct, s->user->get_tenant(), bl);
378 //Check if the input role arn is there as one of the Principals in the policy,
379 // If yes, then return 0, else -EPERM
380 auto p_res = p.eval_principal(s->env, *s->auth.identity);
381 if (p_res == rgw::IAM::Effect::Deny) {
382 ldpp_dout(this, 0) << "evaluating principal returned deny" << dendl;
383 return -EPERM;
384 }
385 auto c_res = p.eval_conditions(s->env);
386 if (c_res == rgw::IAM::Effect::Deny) {
387 ldpp_dout(this, 0) << "evaluating condition returned deny" << dendl;
388 return -EPERM;
389 }
390 } catch (rgw::IAM::PolicyParseException& e) {
391 ldpp_dout(this, 0) << "failed to parse policy: " << e.what() << dendl;
392 return -EPERM;
393 }
394
395 return 0;
396 }
397
398 void RGWREST_STS::send_response()
399 {
400 if (op_ret) {
401 set_req_state_err(s, op_ret);
402 }
403 dump_errno(s);
404 end_header(s);
405 }
406
407 int RGWSTSGetSessionToken::verify_permission(optional_yield y)
408 {
409 rgw::Partition partition = rgw::Partition::aws;
410 rgw::Service service = rgw::Service::s3;
411 if (!verify_user_permission(this,
412 s,
413 rgw::ARN(partition, service, "", s->user->get_tenant(), ""),
414 rgw::IAM::stsGetSessionToken)) {
415 ldpp_dout(this, 0) << "User does not have permssion to perform GetSessionToken" << dendl;
416 return -EACCES;
417 }
418
419 return 0;
420 }
421
422 int RGWSTSGetSessionToken::get_params()
423 {
424 duration = s->info.args.get("DurationSeconds");
425 serialNumber = s->info.args.get("SerialNumber");
426 tokenCode = s->info.args.get("TokenCode");
427
428 if (! duration.empty()) {
429 string err;
430 uint64_t duration_in_secs = strict_strtoll(duration.c_str(), 10, &err);
431 if (!err.empty()) {
432 ldpp_dout(this, 0) << "Invalid value of input duration: " << duration << dendl;
433 return -EINVAL;
434 }
435
436 if (duration_in_secs < STS::GetSessionTokenRequest::getMinDuration() ||
437 duration_in_secs > s->cct->_conf->rgw_sts_max_session_duration) {
438 ldpp_dout(this, 0) << "Invalid duration in secs: " << duration_in_secs << dendl;
439 return -EINVAL;
440 }
441 }
442
443 return 0;
444 }
445
446 void RGWSTSGetSessionToken::execute(optional_yield y)
447 {
448 if (op_ret = get_params(); op_ret < 0) {
449 return;
450 }
451
452 STS::STSService sts(s->cct, store, s->user->get_id(), s->auth.identity.get());
453
454 STS::GetSessionTokenRequest req(duration, serialNumber, tokenCode);
455 const auto& [ret, creds] = sts.getSessionToken(req);
456 op_ret = std::move(ret);
457 //Dump the output
458 if (op_ret == 0) {
459 s->formatter->open_object_section("GetSessionTokenResponse");
460 s->formatter->open_object_section("GetSessionTokenResult");
461 s->formatter->open_object_section("Credentials");
462 creds.dump(s->formatter);
463 s->formatter->close_section();
464 s->formatter->close_section();
465 s->formatter->close_section();
466 }
467 }
468
469 int RGWSTSAssumeRoleWithWebIdentity::get_params()
470 {
471 duration = s->info.args.get("DurationSeconds");
472 providerId = s->info.args.get("ProviderId");
473 policy = s->info.args.get("Policy");
474 roleArn = s->info.args.get("RoleArn");
475 roleSessionName = s->info.args.get("RoleSessionName");
476 iss = s->info.args.get("provider_id");
477 sub = s->info.args.get("sub");
478 aud = s->info.args.get("aud");
479
480 if (roleArn.empty() || roleSessionName.empty() || sub.empty() || aud.empty()) {
481 ldpp_dout(this, 0) << "ERROR: one of role arn or role session name or token is empty" << dendl;
482 return -EINVAL;
483 }
484
485 if (! policy.empty()) {
486 bufferlist bl = bufferlist::static_from_string(policy);
487 try {
488 const rgw::IAM::Policy p(s->cct, s->user->get_tenant(), bl);
489 }
490 catch (rgw::IAM::PolicyParseException& e) {
491 ldpp_dout(this, 20) << "failed to parse policy: " << e.what() << "policy" << policy << dendl;
492 return -ERR_MALFORMED_DOC;
493 }
494 }
495
496 return 0;
497 }
498
499 void RGWSTSAssumeRoleWithWebIdentity::execute(optional_yield y)
500 {
501 if (op_ret = get_params(); op_ret < 0) {
502 return;
503 }
504
505 STS::AssumeRoleWithWebIdentityRequest req(s->cct, duration, providerId, policy, roleArn,
506 roleSessionName, iss, sub, aud);
507 STS::AssumeRoleWithWebIdentityResponse response = sts.assumeRoleWithWebIdentity(req);
508 op_ret = std::move(response.assumeRoleResp.retCode);
509
510 //Dump the output
511 if (op_ret == 0) {
512 s->formatter->open_object_section("AssumeRoleWithWebIdentityResponse");
513 s->formatter->open_object_section("AssumeRoleWithWebIdentityResult");
514 encode_json("SubjectFromWebIdentityToken", response.sub , s->formatter);
515 encode_json("Audience", response.aud , s->formatter);
516 s->formatter->open_object_section("AssumedRoleUser");
517 response.assumeRoleResp.user.dump(s->formatter);
518 s->formatter->close_section();
519 s->formatter->open_object_section("Credentials");
520 response.assumeRoleResp.creds.dump(s->formatter);
521 s->formatter->close_section();
522 encode_json("Provider", response.providerId , s->formatter);
523 encode_json("PackedPolicySize", response.assumeRoleResp.packedPolicySize , s->formatter);
524 s->formatter->close_section();
525 s->formatter->close_section();
526 }
527 }
528
529 int RGWSTSAssumeRole::get_params()
530 {
531 duration = s->info.args.get("DurationSeconds");
532 externalId = s->info.args.get("ExternalId");
533 policy = s->info.args.get("Policy");
534 roleArn = s->info.args.get("RoleArn");
535 roleSessionName = s->info.args.get("RoleSessionName");
536 serialNumber = s->info.args.get("SerialNumber");
537 tokenCode = s->info.args.get("TokenCode");
538
539 if (roleArn.empty() || roleSessionName.empty()) {
540 ldpp_dout(this, 0) << "ERROR: one of role arn or role session name is empty" << dendl;
541 return -EINVAL;
542 }
543
544 if (! policy.empty()) {
545 bufferlist bl = bufferlist::static_from_string(policy);
546 try {
547 const rgw::IAM::Policy p(s->cct, s->user->get_tenant(), bl);
548 }
549 catch (rgw::IAM::PolicyParseException& e) {
550 ldpp_dout(this, 0) << "failed to parse policy: " << e.what() << "policy" << policy << dendl;
551 return -ERR_MALFORMED_DOC;
552 }
553 }
554
555 return 0;
556 }
557
558 void RGWSTSAssumeRole::execute(optional_yield y)
559 {
560 if (op_ret = get_params(); op_ret < 0) {
561 return;
562 }
563
564 STS::AssumeRoleRequest req(s->cct, duration, externalId, policy, roleArn,
565 roleSessionName, serialNumber, tokenCode);
566 STS::AssumeRoleResponse response = sts.assumeRole(s, req, y);
567 op_ret = std::move(response.retCode);
568 //Dump the output
569 if (op_ret == 0) {
570 s->formatter->open_object_section("AssumeRoleResponse");
571 s->formatter->open_object_section("AssumeRoleResult");
572 s->formatter->open_object_section("Credentials");
573 response.creds.dump(s->formatter);
574 s->formatter->close_section();
575 s->formatter->open_object_section("AssumedRoleUser");
576 response.user.dump(s->formatter);
577 s->formatter->close_section();
578 encode_json("PackedPolicySize", response.packedPolicySize , s->formatter);
579 s->formatter->close_section();
580 s->formatter->close_section();
581 }
582 }
583
584 int RGW_Auth_STS::authorize(const DoutPrefixProvider *dpp,
585 rgw::sal::RGWRadosStore *store,
586 const rgw::auth::StrategyRegistry& auth_registry,
587 struct req_state *s, optional_yield y)
588 {
589 return rgw::auth::Strategy::apply(dpp, auth_registry.get_sts(), s, y);
590 }
591
592 void RGWHandler_REST_STS::rgw_sts_parse_input()
593 {
594 if (post_body.size() > 0) {
595 ldpp_dout(s, 10) << "Content of POST: " << post_body << dendl;
596
597 if (post_body.find("Action") != string::npos) {
598 boost::char_separator<char> sep("&");
599 boost::tokenizer<boost::char_separator<char>> tokens(post_body, sep);
600 for (const auto& t : tokens) {
601 auto pos = t.find("=");
602 if (pos != string::npos) {
603 s->info.args.append(t.substr(0,pos),
604 url_decode(t.substr(pos+1, t.size() -1)));
605 }
606 }
607 }
608 }
609 auto payload_hash = rgw::auth::s3::calc_v4_payload_hash(post_body);
610 s->info.args.append("PayloadHash", payload_hash);
611 }
612
613 RGWOp *RGWHandler_REST_STS::op_post()
614 {
615 rgw_sts_parse_input();
616
617 if (s->info.args.exists("Action")) {
618 string action = s->info.args.get("Action");
619 if (action == "AssumeRole") {
620 return new RGWSTSAssumeRole;
621 } else if (action == "GetSessionToken") {
622 return new RGWSTSGetSessionToken;
623 } else if (action == "AssumeRoleWithWebIdentity") {
624 return new RGWSTSAssumeRoleWithWebIdentity;
625 }
626 }
627
628 return nullptr;
629 }
630
631 int RGWHandler_REST_STS::init(rgw::sal::RGWRadosStore *store,
632 struct req_state *s,
633 rgw::io::BasicClient *cio)
634 {
635 s->dialect = "sts";
636
637 if (int ret = RGWHandler_REST_STS::init_from_header(s, RGW_FORMAT_XML, true); ret < 0) {
638 ldpp_dout(s, 10) << "init_from_header returned err=" << ret << dendl;
639 return ret;
640 }
641
642 return RGWHandler_REST::init(store, s, cio);
643 }
644
645 int RGWHandler_REST_STS::authorize(const DoutPrefixProvider* dpp, optional_yield y)
646 {
647 if (s->info.args.exists("Action") && s->info.args.get("Action") == "AssumeRoleWithWebIdentity") {
648 return RGW_Auth_STS::authorize(dpp, store, auth_registry, s, y);
649 }
650 return RGW_Auth_S3::authorize(dpp, store, auth_registry, s, y);
651 }
652
653 int RGWHandler_REST_STS::init_from_header(struct req_state* s,
654 int default_formatter,
655 bool configurable_format)
656 {
657 string req;
658 string first;
659
660 s->prot_flags = RGW_REST_STS;
661
662 const char *p, *req_name;
663 if (req_name = s->relative_uri.c_str(); *req_name == '?') {
664 p = req_name;
665 } else {
666 p = s->info.request_params.c_str();
667 }
668
669 s->info.args.set(p);
670 s->info.args.parse(s);
671
672 /* must be called after the args parsing */
673 if (int ret = allocate_formatter(s, default_formatter, configurable_format); ret < 0)
674 return ret;
675
676 if (*req_name != '/')
677 return 0;
678
679 req_name++;
680
681 if (!*req_name)
682 return 0;
683
684 req = req_name;
685 int pos = req.find('/');
686 if (pos >= 0) {
687 first = req.substr(0, pos);
688 } else {
689 first = req;
690 }
691
692 return 0;
693 }
694
695 RGWHandler_REST*
696 RGWRESTMgr_STS::get_handler(rgw::sal::RGWRadosStore *store,
697 struct req_state* const s,
698 const rgw::auth::StrategyRegistry& auth_registry,
699 const std::string& frontend_prefix)
700 {
701 return new RGWHandler_REST_STS(auth_registry);
702 }