]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_rest_s3.h
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / rgw / rgw_rest_s3.h
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3
4#ifndef CEPH_RGW_REST_S3_H
5
6#define CEPH_RGW_REST_S3_H
7#define TIME_BUF_SIZE 128
8
9#include <mutex>
10
31f18b77
FG
11#include <boost/utility/string_view.hpp>
12#include <boost/container/static_vector.hpp>
13
31f18b77 14#include "common/sstring.hh"
7c673cae
FG
15#include "rgw_op.h"
16#include "rgw_rest.h"
17#include "rgw_http_errors.h"
18#include "rgw_acl_s3.h"
19#include "rgw_policy_s3.h"
20#include "rgw_lc_s3.h"
21#include "rgw_keystone.h"
22#include "rgw_rest_conn.h"
23#include "rgw_ldap.h"
7c673cae
FG
24
25#include "rgw_token.h"
11fdf7f2 26#include "include/ceph_assert.h"
7c673cae
FG
27
28#include "rgw_auth.h"
29#include "rgw_auth_filters.h"
11fdf7f2 30#include "rgw_sts.h"
7c673cae 31
31f18b77
FG
32struct rgw_http_error {
33 int http_ret;
34 const char *s3_code;
35};
36
37void rgw_get_errno_s3(struct rgw_http_error *e, int err_no);
7c673cae
FG
38
39class RGWGetObj_ObjStore_S3 : public RGWGetObj_ObjStore
40{
41protected:
42 // Serving a custom error page from an object is really a 200 response with
43 // just the status line altered.
44 int custom_http_ret = 0;
45 std::map<std::string, std::string> crypt_http_responses;
46public:
47 RGWGetObj_ObjStore_S3() {}
48 ~RGWGetObj_ObjStore_S3() override {}
49
50 int get_params() override;
51 int send_response_data_error() override;
52 int send_response_data(bufferlist& bl, off_t ofs, off_t len) override;
53 void set_custom_http_response(int http_ret) { custom_http_ret = http_ret; }
11fdf7f2
TL
54 int get_decrypt_filter(std::unique_ptr<RGWGetObj_Filter>* filter,
55 RGWGetObj_Filter* cb,
7c673cae
FG
56 bufferlist* manifest_bl) override;
57};
58
224ce89b
WB
59class RGWGetObjTags_ObjStore_S3 : public RGWGetObjTags_ObjStore
60{
61 bufferlist tags_bl;
62public:
63 RGWGetObjTags_ObjStore_S3() {}
64 ~RGWGetObjTags_ObjStore_S3() {}
65
66 void send_response_data(bufferlist &bl) override;
67};
68
69class RGWPutObjTags_ObjStore_S3 : public RGWPutObjTags_ObjStore
70{
71public:
72 RGWPutObjTags_ObjStore_S3() {}
73 ~RGWPutObjTags_ObjStore_S3() {}
74
75 int get_params() override;
76 void send_response() override;
77};
78
79class RGWDeleteObjTags_ObjStore_S3 : public RGWDeleteObjTags
80{
81public:
82 ~RGWDeleteObjTags_ObjStore_S3() override {}
83 void send_response() override;
84};
85
7c673cae
FG
86class RGWListBuckets_ObjStore_S3 : public RGWListBuckets_ObjStore {
87public:
88 RGWListBuckets_ObjStore_S3() {}
89 ~RGWListBuckets_ObjStore_S3() override {}
90
91 int get_params() override {
92 limit = -1; /* no limit */
93 return 0;
94 }
95 void send_response_begin(bool has_buckets) override;
96 void send_response_data(RGWUserBuckets& buckets) override;
97 void send_response_end() override;
98};
99
100class RGWGetUsage_ObjStore_S3 : public RGWGetUsage_ObjStore {
101public:
102 RGWGetUsage_ObjStore_S3() {}
103 ~RGWGetUsage_ObjStore_S3() override {}
104
105 int get_params() override ;
106 void send_response() override;
107};
108
109class RGWListBucket_ObjStore_S3 : public RGWListBucket_ObjStore {
110 bool objs_container;
111public:
112 RGWListBucket_ObjStore_S3() : objs_container(false) {
113 default_max = 1000;
114 }
115 ~RGWListBucket_ObjStore_S3() override {}
116
117 int get_params() override;
118 void send_response() override;
119 void send_versioned_response();
120};
121
122class RGWGetBucketLogging_ObjStore_S3 : public RGWGetBucketLogging {
123public:
124 RGWGetBucketLogging_ObjStore_S3() {}
125 ~RGWGetBucketLogging_ObjStore_S3() override {}
126
127 void send_response() override;
128};
129
130class RGWGetBucketLocation_ObjStore_S3 : public RGWGetBucketLocation {
131public:
132 RGWGetBucketLocation_ObjStore_S3() {}
133 ~RGWGetBucketLocation_ObjStore_S3() override {}
134
135 void send_response() override;
136};
137
138class RGWGetBucketVersioning_ObjStore_S3 : public RGWGetBucketVersioning {
139public:
140 RGWGetBucketVersioning_ObjStore_S3() {}
141 ~RGWGetBucketVersioning_ObjStore_S3() override {}
142
143 void send_response() override;
144};
145
146class RGWSetBucketVersioning_ObjStore_S3 : public RGWSetBucketVersioning {
147public:
148 RGWSetBucketVersioning_ObjStore_S3() {}
149 ~RGWSetBucketVersioning_ObjStore_S3() override {}
150
151 int get_params() override;
152 void send_response() override;
153};
154
155class RGWGetBucketWebsite_ObjStore_S3 : public RGWGetBucketWebsite {
156public:
157 RGWGetBucketWebsite_ObjStore_S3() {}
158 ~RGWGetBucketWebsite_ObjStore_S3() override {}
159
160 void send_response() override;
161};
162
163class RGWSetBucketWebsite_ObjStore_S3 : public RGWSetBucketWebsite {
164public:
165 RGWSetBucketWebsite_ObjStore_S3() {}
166 ~RGWSetBucketWebsite_ObjStore_S3() override {}
167
168 int get_params() override;
169 void send_response() override;
170};
171
172class RGWDeleteBucketWebsite_ObjStore_S3 : public RGWDeleteBucketWebsite {
173public:
174 RGWDeleteBucketWebsite_ObjStore_S3() {}
175 ~RGWDeleteBucketWebsite_ObjStore_S3() override {}
176
177 void send_response() override;
178};
179
180class RGWStatBucket_ObjStore_S3 : public RGWStatBucket_ObjStore {
181public:
182 RGWStatBucket_ObjStore_S3() {}
183 ~RGWStatBucket_ObjStore_S3() override {}
184
185 void send_response() override;
186};
187
188class RGWCreateBucket_ObjStore_S3 : public RGWCreateBucket_ObjStore {
189public:
190 RGWCreateBucket_ObjStore_S3() {}
191 ~RGWCreateBucket_ObjStore_S3() override {}
192
193 int get_params() override;
194 void send_response() override;
195};
196
197class RGWDeleteBucket_ObjStore_S3 : public RGWDeleteBucket_ObjStore {
198public:
199 RGWDeleteBucket_ObjStore_S3() {}
200 ~RGWDeleteBucket_ObjStore_S3() override {}
201
202 void send_response() override;
203};
204
205class RGWPutObj_ObjStore_S3 : public RGWPutObj_ObjStore {
206private:
207 std::map<std::string, std::string> crypt_http_responses;
208
209public:
210 RGWPutObj_ObjStore_S3() {}
211 ~RGWPutObj_ObjStore_S3() override {}
212
213 int get_params() override;
214 int get_data(bufferlist& bl) override;
215 void send_response() override;
216
11fdf7f2
TL
217 int get_encrypt_filter(std::unique_ptr<rgw::putobj::DataProcessor> *filter,
218 rgw::putobj::DataProcessor *cb) override;
219 int get_decrypt_filter(std::unique_ptr<RGWGetObj_Filter>* filter,
220 RGWGetObj_Filter* cb,
7c673cae
FG
221 map<string, bufferlist>& attrs,
222 bufferlist* manifest_bl) override;
223};
224
225class RGWPostObj_ObjStore_S3 : public RGWPostObj_ObjStore {
226 parts_collection_t parts;
227 std::string filename;
228 std::string content_type;
229 RGWPolicyEnv env;
230 RGWPolicy post_policy;
231 map<string, string> crypt_http_responses;
232
233 const rgw::auth::StrategyRegistry* auth_registry_ptr = nullptr;
234
235 int get_policy();
224ce89b 236 int get_tags();
7c673cae
FG
237 void rebuild_key(string& key);
238
239 std::string get_current_filename() const override;
240 std::string get_current_content_type() const override;
241
242public:
243 RGWPostObj_ObjStore_S3() {}
244 ~RGWPostObj_ObjStore_S3() override {}
245
11fdf7f2 246 int verify_requester(const rgw::auth::StrategyRegistry& auth_registry) override {
7c673cae
FG
247 auth_registry_ptr = &auth_registry;
248 return RGWPostObj_ObjStore::verify_requester(auth_registry);
249 }
250
251 int get_params() override;
252 int complete_get_params();
253
254 void send_response() override;
255 int get_data(ceph::bufferlist& bl, bool& again) override;
11fdf7f2
TL
256 int get_encrypt_filter(std::unique_ptr<rgw::putobj::DataProcessor> *filter,
257 rgw::putobj::DataProcessor *cb) override;
7c673cae
FG
258};
259
260class RGWDeleteObj_ObjStore_S3 : public RGWDeleteObj_ObjStore {
261public:
262 RGWDeleteObj_ObjStore_S3() {}
263 ~RGWDeleteObj_ObjStore_S3() override {}
264
265 int get_params() override;
266 void send_response() override;
267};
268
269class RGWCopyObj_ObjStore_S3 : public RGWCopyObj_ObjStore {
270 bool sent_header;
271public:
272 RGWCopyObj_ObjStore_S3() : sent_header(false) {}
273 ~RGWCopyObj_ObjStore_S3() override {}
274
275 int init_dest_policy() override;
276 int get_params() override;
11fdf7f2 277 int check_storage_class(const rgw_placement_rule& src_placement);
7c673cae
FG
278 void send_partial_response(off_t ofs) override;
279 void send_response() override;
280};
281
282class RGWGetACLs_ObjStore_S3 : public RGWGetACLs_ObjStore {
283public:
284 RGWGetACLs_ObjStore_S3() {}
285 ~RGWGetACLs_ObjStore_S3() override {}
286
287 void send_response() override;
288};
289
290class RGWPutACLs_ObjStore_S3 : public RGWPutACLs_ObjStore {
291public:
292 RGWPutACLs_ObjStore_S3() {}
293 ~RGWPutACLs_ObjStore_S3() override {}
294
295 int get_policy_from_state(RGWRados *store, struct req_state *s, stringstream& ss) override;
296 void send_response() override;
297 int get_params() override;
298};
299
300class RGWGetLC_ObjStore_S3 : public RGWGetLC_ObjStore {
301protected:
11fdf7f2 302 RGWLifecycleConfiguration_S3 config;
7c673cae
FG
303public:
304 RGWGetLC_ObjStore_S3() {}
305 ~RGWGetLC_ObjStore_S3() override {}
306 void execute() override;
307
308 void send_response() override;
309};
310
311class RGWPutLC_ObjStore_S3 : public RGWPutLC_ObjStore {
312public:
313 RGWPutLC_ObjStore_S3() {}
314 ~RGWPutLC_ObjStore_S3() override {}
315
316 void send_response() override;
317};
318
319class RGWDeleteLC_ObjStore_S3 : public RGWDeleteLC_ObjStore {
320public:
321 RGWDeleteLC_ObjStore_S3() {}
322 ~RGWDeleteLC_ObjStore_S3() override {}
323
324 void send_response() override;
325};
326
327class RGWGetCORS_ObjStore_S3 : public RGWGetCORS_ObjStore {
328public:
329 RGWGetCORS_ObjStore_S3() {}
330 ~RGWGetCORS_ObjStore_S3() override {}
331
332 void send_response() override;
333};
334
335class RGWPutCORS_ObjStore_S3 : public RGWPutCORS_ObjStore {
336public:
337 RGWPutCORS_ObjStore_S3() {}
338 ~RGWPutCORS_ObjStore_S3() override {}
339
340 int get_params() override;
341 void send_response() override;
342};
343
344class RGWDeleteCORS_ObjStore_S3 : public RGWDeleteCORS_ObjStore {
345public:
346 RGWDeleteCORS_ObjStore_S3() {}
347 ~RGWDeleteCORS_ObjStore_S3() override {}
348
349 void send_response() override;
350};
351
352class RGWOptionsCORS_ObjStore_S3 : public RGWOptionsCORS_ObjStore {
353public:
354 RGWOptionsCORS_ObjStore_S3() {}
355 ~RGWOptionsCORS_ObjStore_S3() override {}
356
357 void send_response() override;
358};
359
360class RGWGetRequestPayment_ObjStore_S3 : public RGWGetRequestPayment {
361public:
362 RGWGetRequestPayment_ObjStore_S3() {}
363 ~RGWGetRequestPayment_ObjStore_S3() override {}
364
365 void send_response() override;
366};
367
368class RGWSetRequestPayment_ObjStore_S3 : public RGWSetRequestPayment {
369public:
370 RGWSetRequestPayment_ObjStore_S3() {}
371 ~RGWSetRequestPayment_ObjStore_S3() override {}
372
373 int get_params() override;
374 void send_response() override;
375};
376
377class RGWInitMultipart_ObjStore_S3 : public RGWInitMultipart_ObjStore {
378private:
379 std::map<std::string, std::string> crypt_http_responses;
380public:
381 RGWInitMultipart_ObjStore_S3() {}
382 ~RGWInitMultipart_ObjStore_S3() override {}
383
384 int get_params() override;
385 void send_response() override;
386 int prepare_encryption(map<string, bufferlist>& attrs) override;
387};
388
389class RGWCompleteMultipart_ObjStore_S3 : public RGWCompleteMultipart_ObjStore {
390public:
391 RGWCompleteMultipart_ObjStore_S3() {}
392 ~RGWCompleteMultipart_ObjStore_S3() override {}
393
394 int get_params() override;
395 void send_response() override;
396};
397
398class RGWAbortMultipart_ObjStore_S3 : public RGWAbortMultipart_ObjStore {
399public:
400 RGWAbortMultipart_ObjStore_S3() {}
401 ~RGWAbortMultipart_ObjStore_S3() override {}
402
403 void send_response() override;
404};
405
406class RGWListMultipart_ObjStore_S3 : public RGWListMultipart_ObjStore {
407public:
408 RGWListMultipart_ObjStore_S3() {}
409 ~RGWListMultipart_ObjStore_S3() override {}
410
411 void send_response() override;
412};
413
414class RGWListBucketMultiparts_ObjStore_S3 : public RGWListBucketMultiparts_ObjStore {
415public:
416 RGWListBucketMultiparts_ObjStore_S3() {
417 default_max = 1000;
418 }
419 ~RGWListBucketMultiparts_ObjStore_S3() override {}
420
421 void send_response() override;
422};
423
424class RGWDeleteMultiObj_ObjStore_S3 : public RGWDeleteMultiObj_ObjStore {
425public:
426 RGWDeleteMultiObj_ObjStore_S3() {}
427 ~RGWDeleteMultiObj_ObjStore_S3() override {}
428
429 int get_params() override;
430 void send_status() override;
431 void begin_response() override;
432 void send_partial_response(rgw_obj_key& key, bool delete_marker,
433 const string& marker_version_id, int ret) override;
434 void end_response() override;
435};
436
437class RGWGetObjLayout_ObjStore_S3 : public RGWGetObjLayout {
438public:
439 RGWGetObjLayout_ObjStore_S3() {}
440 ~RGWGetObjLayout_ObjStore_S3() {}
441
11fdf7f2 442 void send_response() override;
7c673cae
FG
443};
444
31f18b77
FG
445class RGWConfigBucketMetaSearch_ObjStore_S3 : public RGWConfigBucketMetaSearch {
446public:
447 RGWConfigBucketMetaSearch_ObjStore_S3() {}
448 ~RGWConfigBucketMetaSearch_ObjStore_S3() {}
449
450 int get_params() override;
451 void send_response() override;
452};
453
454class RGWGetBucketMetaSearch_ObjStore_S3 : public RGWGetBucketMetaSearch {
455public:
456 RGWGetBucketMetaSearch_ObjStore_S3() {}
457 ~RGWGetBucketMetaSearch_ObjStore_S3() {}
458
459 void send_response() override;
460};
461
462class RGWDelBucketMetaSearch_ObjStore_S3 : public RGWDelBucketMetaSearch {
463public:
464 RGWDelBucketMetaSearch_ObjStore_S3() {}
465 ~RGWDelBucketMetaSearch_ObjStore_S3() {}
466
467 void send_response() override;
468};
7c673cae
FG
469
470class RGW_Auth_S3 {
7c673cae 471public:
11fdf7f2
TL
472 static int authorize(const DoutPrefixProvider *dpp,
473 RGWRados *store,
7c673cae
FG
474 const rgw::auth::StrategyRegistry& auth_registry,
475 struct req_state *s);
7c673cae
FG
476};
477
478class RGWHandler_Auth_S3 : public RGWHandler_REST {
479 friend class RGWRESTMgr_S3;
480
481 const rgw::auth::StrategyRegistry& auth_registry;
482
483public:
11fdf7f2 484 explicit RGWHandler_Auth_S3(const rgw::auth::StrategyRegistry& auth_registry)
7c673cae
FG
485 : RGWHandler_REST(),
486 auth_registry(auth_registry) {
487 }
488 ~RGWHandler_Auth_S3() override = default;
489
490 static int validate_bucket_name(const string& bucket);
491 static int validate_object_name(const string& bucket);
492
493 int init(RGWRados *store,
494 struct req_state *s,
495 rgw::io::BasicClient *cio) override;
11fdf7f2
TL
496 int authorize(const DoutPrefixProvider *dpp) override {
497 return RGW_Auth_S3::authorize(dpp, store, auth_registry, s);
7c673cae
FG
498 }
499 int postauth_init() override { return 0; }
500};
501
502class RGWHandler_REST_S3 : public RGWHandler_REST {
503 friend class RGWRESTMgr_S3;
11fdf7f2 504protected:
7c673cae
FG
505 const rgw::auth::StrategyRegistry& auth_registry;
506public:
507 static int init_from_header(struct req_state *s, int default_formatter, bool configurable_format);
508
11fdf7f2 509 explicit RGWHandler_REST_S3(const rgw::auth::StrategyRegistry& auth_registry)
7c673cae
FG
510 : RGWHandler_REST(),
511 auth_registry(auth_registry) {
11fdf7f2 512 }
7c673cae
FG
513 ~RGWHandler_REST_S3() override = default;
514
515 int init(RGWRados *store,
516 struct req_state *s,
517 rgw::io::BasicClient *cio) override;
11fdf7f2 518 int authorize(const DoutPrefixProvider *dpp) override;
7c673cae
FG
519 int postauth_init() override;
520};
521
522class RGWHandler_REST_Service_S3 : public RGWHandler_REST_S3 {
523protected:
11fdf7f2 524 bool isSTSenabled;
7c673cae
FG
525 bool is_usage_op() {
526 return s->info.args.exists("usage");
527 }
528 RGWOp *op_get() override;
529 RGWOp *op_head() override;
530 RGWOp *op_post() override;
531public:
11fdf7f2
TL
532 RGWHandler_REST_Service_S3(const rgw::auth::StrategyRegistry& auth_registry,
533 bool isSTSenabled) :
534 RGWHandler_REST_S3(auth_registry), isSTSenabled(isSTSenabled) {}
7c673cae
FG
535 ~RGWHandler_REST_Service_S3() override = default;
536};
537
538class RGWHandler_REST_Bucket_S3 : public RGWHandler_REST_S3 {
539protected:
540 bool is_acl_op() {
541 return s->info.args.exists("acl");
542 }
543 bool is_cors_op() {
544 return s->info.args.exists("cors");
545 }
546 bool is_lc_op() {
547 return s->info.args.exists("lifecycle");
548 }
549 bool is_obj_update_op() override {
550 return is_acl_op() || is_cors_op();
551 }
552 bool is_request_payment_op() {
553 return s->info.args.exists("requestPayment");
554 }
31f18b77
FG
555 bool is_policy_op() {
556 return s->info.args.exists("policy");
557 }
7c673cae
FG
558 RGWOp *get_obj_op(bool get_data);
559
560 RGWOp *op_get() override;
561 RGWOp *op_head() override;
562 RGWOp *op_put() override;
563 RGWOp *op_delete() override;
564 RGWOp *op_post() override;
565 RGWOp *op_options() override;
566public:
567 using RGWHandler_REST_S3::RGWHandler_REST_S3;
568 ~RGWHandler_REST_Bucket_S3() override = default;
569};
570
571class RGWHandler_REST_Obj_S3 : public RGWHandler_REST_S3 {
572protected:
573 bool is_acl_op() {
574 return s->info.args.exists("acl");
575 }
224ce89b
WB
576 bool is_tagging_op() {
577 return s->info.args.exists("tagging");
578 }
7c673cae 579 bool is_obj_update_op() override {
224ce89b 580 return is_acl_op() || is_tagging_op() ;
7c673cae
FG
581 }
582 RGWOp *get_obj_op(bool get_data);
583
584 RGWOp *op_get() override;
585 RGWOp *op_head() override;
586 RGWOp *op_put() override;
587 RGWOp *op_delete() override;
588 RGWOp *op_post() override;
589 RGWOp *op_options() override;
590public:
591 using RGWHandler_REST_S3::RGWHandler_REST_S3;
592 ~RGWHandler_REST_Obj_S3() override = default;
593};
594
595class RGWRESTMgr_S3 : public RGWRESTMgr {
596private:
597 bool enable_s3website;
11fdf7f2 598 bool enable_sts;
7c673cae 599public:
11fdf7f2
TL
600 explicit RGWRESTMgr_S3(bool enable_s3website = false, bool enable_sts = false)
601 : enable_s3website(enable_s3website),
602 enable_sts(enable_sts) {
7c673cae
FG
603 }
604
605 ~RGWRESTMgr_S3() override = default;
606
607 RGWHandler_REST *get_handler(struct req_state* s,
608 const rgw::auth::StrategyRegistry& auth_registry,
609 const std::string& frontend_prefix) override;
610};
611
612class RGWHandler_REST_Obj_S3Website;
613
614static inline bool looks_like_ip_address(const char *bucket)
615{
616 int num_periods = 0;
617 bool expect_period = false;
618 for (const char *b = bucket; *b; ++b) {
619 if (*b == '.') {
620 if (!expect_period)
621 return false;
622 ++num_periods;
623 if (num_periods > 3)
624 return false;
625 expect_period = false;
626 }
627 else if (isdigit(*b)) {
628 expect_period = true;
629 }
630 else {
631 return false;
632 }
633 }
634 return (num_periods == 3);
635}
636
637static inline int valid_s3_object_name(const string& name) {
638 if (name.size() > 1024) {
639 return -ERR_INVALID_OBJECT_NAME;
640 }
641 if (check_utf8(name.c_str(), name.size())) {
642 return -ERR_INVALID_OBJECT_NAME;
643 }
644 return 0;
645}
646
647static inline int valid_s3_bucket_name(const string& name, bool relaxed=false)
648{
649 // This function enforces Amazon's spec for bucket names.
650 // (The requirements, not the recommendations.)
651 int len = name.size();
652 if (len < 3) {
653 // Name too short
654 return -ERR_INVALID_BUCKET_NAME;
655 } else if (len > 255) {
656 // Name too long
657 return -ERR_INVALID_BUCKET_NAME;
658 }
659
660 // bucket names must start with a number, letter, or underscore
661 if (!(isalpha(name[0]) || isdigit(name[0]))) {
662 if (!relaxed)
663 return -ERR_INVALID_BUCKET_NAME;
664 else if (!(name[0] == '_' || name[0] == '.' || name[0] == '-'))
665 return -ERR_INVALID_BUCKET_NAME;
666 }
667
668 for (const char *s = name.c_str(); *s; ++s) {
669 char c = *s;
670 if (isdigit(c) || (c == '.'))
671 continue;
672 if (isalpha(c))
673 continue;
674 if ((c == '-') || (c == '_'))
675 continue;
676 // Invalid character
677 return -ERR_INVALID_BUCKET_NAME;
678 }
679
680 if (looks_like_ip_address(name.c_str()))
681 return -ERR_INVALID_BUCKET_NAME;
682
683 return 0;
684}
685
686
687namespace rgw {
688namespace auth {
689namespace s3 {
690
31f18b77 691class AWSEngine : public rgw::auth::Engine {
7c673cae 692public:
31f18b77
FG
693 class VersionAbstractor {
694 static constexpr size_t DIGEST_SIZE_V2 = CEPH_CRYPTO_HMACSHA1_DIGESTSIZE;
695 static constexpr size_t DIGEST_SIZE_V4 = CEPH_CRYPTO_HMACSHA256_DIGESTSIZE;
696
697 /* Knowing the signature max size allows us to employ the sstring, and thus
698 * avoid dynamic allocations. The multiplier comes from representing digest
699 * in the base64-encoded form. */
700 static constexpr size_t SIGNATURE_MAX_SIZE = \
11fdf7f2 701 std::max(DIGEST_SIZE_V2, DIGEST_SIZE_V4) * 2 + sizeof('\0');
31f18b77 702
7c673cae 703 public:
31f18b77 704 virtual ~VersionAbstractor() {};
7c673cae 705
31f18b77
FG
706 using access_key_id_t = boost::string_view;
707 using client_signature_t = boost::string_view;
11fdf7f2 708 using session_token_t = boost::string_view;
31f18b77 709 using server_signature_t = basic_sstring<char, uint16_t, SIGNATURE_MAX_SIZE>;
7c673cae
FG
710 using string_to_sign_t = std::string;
711
31f18b77
FG
712 /* Transformation for crafting the AWS signature at server side which is
713 * used later to compare with the user-provided one. The methodology for
714 * doing that depends on AWS auth version. */
715 using signature_factory_t = \
716 std::function<server_signature_t(CephContext* cct,
717 const std::string& secret_key,
718 const string_to_sign_t& string_to_sign)>;
719
720 /* Return an instance of Completer for verifying the payload's fingerprint
721 * if necessary. Otherwise caller gets nullptr. Caller may provide secret
722 * key */
723 using completer_factory_t = \
724 std::function<rgw::auth::Completer::cmplptr_t(
725 const boost::optional<std::string>& secret_key)>;
726
224ce89b
WB
727 struct auth_data_t {
728 access_key_id_t access_key_id;
729 client_signature_t client_signature;
11fdf7f2 730 session_token_t session_token;
224ce89b
WB
731 string_to_sign_t string_to_sign;
732 signature_factory_t signature_factory;
733 completer_factory_t completer_factory;
734 };
735
736 virtual auth_data_t get_auth_data(const req_state* s) const = 0;
7c673cae
FG
737 };
738
739protected:
740 CephContext* cct;
31f18b77 741 const VersionAbstractor& ver_abstractor;
7c673cae 742
31f18b77 743 AWSEngine(CephContext* const cct, const VersionAbstractor& ver_abstractor)
7c673cae 744 : cct(cct),
31f18b77 745 ver_abstractor(ver_abstractor) {
7c673cae
FG
746 }
747
748 using result_t = rgw::auth::Engine::result_t;
31f18b77
FG
749 using string_to_sign_t = VersionAbstractor::string_to_sign_t;
750 using signature_factory_t = VersionAbstractor::signature_factory_t;
751 using completer_factory_t = VersionAbstractor::completer_factory_t;
752
753 /* TODO(rzarzynski): clean up. We've too many input parameter hee. Also
754 * the signature get_auth_data() of VersionAbstractor is too complicated.
755 * Replace these thing with a simple, dedicated structure. */
11fdf7f2
TL
756 virtual result_t authenticate(const DoutPrefixProvider* dpp,
757 const boost::string_view& access_key_id,
31f18b77 758 const boost::string_view& signature,
11fdf7f2 759 const boost::string_view& session_token,
31f18b77
FG
760 const string_to_sign_t& string_to_sign,
761 const signature_factory_t& signature_factory,
762 const completer_factory_t& completer_factory,
7c673cae
FG
763 const req_state* s) const = 0;
764
765public:
11fdf7f2 766 result_t authenticate(const DoutPrefixProvider* dpp, const req_state* const s) const final;
7c673cae
FG
767};
768
31f18b77
FG
769
770class AWSGeneralAbstractor : public AWSEngine::VersionAbstractor {
7c673cae
FG
771 CephContext* const cct;
772
31f18b77
FG
773 virtual boost::optional<std::string>
774 get_v4_canonical_headers(const req_info& info,
775 const boost::string_view& signedheaders,
776 const bool using_qs) const;
777
224ce89b 778 auth_data_t get_auth_data_v2(const req_state* s) const;
11fdf7f2 779 auth_data_t get_auth_data_v4(const req_state* s, const bool using_qs) const;
31f18b77 780
7c673cae 781public:
11fdf7f2 782 explicit AWSGeneralAbstractor(CephContext* const cct)
7c673cae
FG
783 : cct(cct) {
784 }
785
224ce89b 786 auth_data_t get_auth_data(const req_state* s) const override;
7c673cae
FG
787};
788
31f18b77
FG
789class AWSGeneralBoto2Abstractor : public AWSGeneralAbstractor {
790 boost::optional<std::string>
791 get_v4_canonical_headers(const req_info& info,
792 const boost::string_view& signedheaders,
793 const bool using_qs) const override;
794
795public:
796 using AWSGeneralAbstractor::AWSGeneralAbstractor;
797};
7c673cae 798
31f18b77 799class AWSBrowserUploadAbstractor : public AWSEngine::VersionAbstractor {
7c673cae
FG
800 static std::string to_string(ceph::bufferlist bl) {
801 return std::string(bl.c_str(),
802 static_cast<std::string::size_type>(bl.length()));
803 }
804
31f18b77
FG
805 auth_data_t get_auth_data_v2(const req_state* s) const;
806 auth_data_t get_auth_data_v4(const req_state* s) const;
807
7c673cae 808public:
11fdf7f2 809 explicit AWSBrowserUploadAbstractor(CephContext*) {
7c673cae
FG
810 }
811
224ce89b 812 auth_data_t get_auth_data(const req_state* s) const override;
7c673cae
FG
813};
814
815
31f18b77 816class LDAPEngine : public AWSEngine {
7c673cae
FG
817 static rgw::LDAPHelper* ldh;
818 static std::mutex mtx;
819
820 static void init(CephContext* const cct);
821
822 using acl_strategy_t = rgw::auth::RemoteApplier::acl_strategy_t;
823 using auth_info_t = rgw::auth::RemoteApplier::AuthInfo;
824 using result_t = rgw::auth::Engine::result_t;
825
826protected:
827 RGWRados* const store;
828 const rgw::auth::RemoteApplier::Factory* const apl_factory;
829
830 acl_strategy_t get_acl_strategy() const;
831 auth_info_t get_creds_info(const rgw::RGWToken& token) const noexcept;
832
11fdf7f2
TL
833 result_t authenticate(const DoutPrefixProvider* dpp,
834 const boost::string_view& access_key_id,
31f18b77 835 const boost::string_view& signature,
11fdf7f2 836 const boost::string_view& session_token,
31f18b77
FG
837 const string_to_sign_t& string_to_sign,
838 const signature_factory_t&,
839 const completer_factory_t& completer_factory,
7c673cae
FG
840 const req_state* s) const override;
841public:
842 LDAPEngine(CephContext* const cct,
843 RGWRados* const store,
31f18b77 844 const VersionAbstractor& ver_abstractor,
7c673cae 845 const rgw::auth::RemoteApplier::Factory* const apl_factory)
31f18b77 846 : AWSEngine(cct, ver_abstractor),
7c673cae
FG
847 store(store),
848 apl_factory(apl_factory) {
849 init(cct);
850 }
851
31f18b77 852 using AWSEngine::authenticate;
7c673cae
FG
853
854 const char* get_name() const noexcept override {
855 return "rgw::auth::s3::LDAPEngine";
856 }
a8e16298
TL
857
858 static bool valid();
11fdf7f2 859 static void shutdown();
7c673cae
FG
860};
861
31f18b77 862class LocalEngine : public AWSEngine {
7c673cae
FG
863 RGWRados* const store;
864 const rgw::auth::LocalApplier::Factory* const apl_factory;
865
11fdf7f2
TL
866 result_t authenticate(const DoutPrefixProvider* dpp,
867 const boost::string_view& access_key_id,
31f18b77 868 const boost::string_view& signature,
11fdf7f2 869 const boost::string_view& session_token,
31f18b77
FG
870 const string_to_sign_t& string_to_sign,
871 const signature_factory_t& signature_factory,
872 const completer_factory_t& completer_factory,
7c673cae
FG
873 const req_state* s) const override;
874public:
31f18b77
FG
875 LocalEngine(CephContext* const cct,
876 RGWRados* const store,
877 const VersionAbstractor& ver_abstractor,
878 const rgw::auth::LocalApplier::Factory* const apl_factory)
879 : AWSEngine(cct, ver_abstractor),
7c673cae
FG
880 store(store),
881 apl_factory(apl_factory) {
882 }
883
31f18b77 884 using AWSEngine::authenticate;
7c673cae
FG
885
886 const char* get_name() const noexcept override {
31f18b77 887 return "rgw::auth::s3::LocalEngine";
7c673cae
FG
888 }
889};
890
11fdf7f2
TL
891class STSEngine : public AWSEngine {
892 RGWRados* const store;
893 const rgw::auth::LocalApplier::Factory* const local_apl_factory;
894 const rgw::auth::RemoteApplier::Factory* const remote_apl_factory;
895 const rgw::auth::RoleApplier::Factory* const role_apl_factory;
896
897 using acl_strategy_t = rgw::auth::RemoteApplier::acl_strategy_t;
898 using auth_info_t = rgw::auth::RemoteApplier::AuthInfo;
899
900 acl_strategy_t get_acl_strategy() const { return nullptr; };
901 auth_info_t get_creds_info(const STS::SessionToken& token) const noexcept;
902
903 int get_session_token(const boost::string_view& session_token,
904 STS::SessionToken& token) const;
905
906 result_t authenticate(const DoutPrefixProvider* dpp,
907 const boost::string_view& access_key_id,
908 const boost::string_view& signature,
909 const boost::string_view& session_token,
910 const string_to_sign_t& string_to_sign,
911 const signature_factory_t& signature_factory,
912 const completer_factory_t& completer_factory,
913 const req_state* s) const override;
914public:
915 STSEngine(CephContext* const cct,
916 RGWRados* const store,
917 const VersionAbstractor& ver_abstractor,
918 const rgw::auth::LocalApplier::Factory* const local_apl_factory,
919 const rgw::auth::RemoteApplier::Factory* const remote_apl_factory,
920 const rgw::auth::RoleApplier::Factory* const role_apl_factory)
921 : AWSEngine(cct, ver_abstractor),
922 store(store),
923 local_apl_factory(local_apl_factory),
924 remote_apl_factory(remote_apl_factory),
925 role_apl_factory(role_apl_factory) {
926 }
927
928 using AWSEngine::authenticate;
929
930 const char* get_name() const noexcept override {
931 return "rgw::auth::s3::STSEngine";
932 }
933};
7c673cae 934
d2e6a577
FG
935class S3AnonymousEngine : public rgw::auth::AnonymousEngine {
936 bool is_applicable(const req_state* s) const noexcept override;
937
938public:
939 /* Let's reuse the parent class' constructor. */
940 using rgw::auth::AnonymousEngine::AnonymousEngine;
941
942 const char* get_name() const noexcept override {
943 return "rgw::auth::s3::S3AnonymousEngine";
944 }
945};
946
947
7c673cae
FG
948class S3AuthFactory : public rgw::auth::RemoteApplier::Factory,
949 public rgw::auth::LocalApplier::Factory {
950 typedef rgw::auth::IdentityApplier::aplptr_t aplptr_t;
951 RGWRados* const store;
952
953public:
11fdf7f2
TL
954 explicit S3AuthFactory(RGWRados* const store)
955 : store(store) {
7c673cae
FG
956 }
957
958 aplptr_t create_apl_remote(CephContext* const cct,
959 const req_state* const s,
960 rgw::auth::RemoteApplier::acl_strategy_t&& acl_alg,
11fdf7f2 961 const rgw::auth::RemoteApplier::AuthInfo &info
7c673cae
FG
962 ) const override {
963 return aplptr_t(
964 new rgw::auth::RemoteApplier(cct, store, std::move(acl_alg), info,
11fdf7f2 965 cct->_conf->rgw_keystone_implicit_tenants));
7c673cae
FG
966 }
967
968 aplptr_t create_apl_local(CephContext* const cct,
969 const req_state* const s,
970 const RGWUserInfo& user_info,
11fdf7f2
TL
971 const std::string& subuser,
972 const boost::optional<uint32_t>& perm_mask) const override {
7c673cae 973 return aplptr_t(
11fdf7f2 974 new rgw::auth::LocalApplier(cct, user_info, subuser, perm_mask));
7c673cae
FG
975 }
976};
977
978
979} /* namespace s3 */
980} /* namespace auth */
981} /* namespace rgw */
982
983
984#endif /* CEPH_RGW_REST_S3_H */