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