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