]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_rest.h
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / rgw / rgw_rest.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_H
5 #define CEPH_RGW_REST_H
6
7 #define TIME_BUF_SIZE 128
8
9 #include <boost/utility/string_ref.hpp>
10 #include <boost/container/flat_set.hpp>
11 #include "common/sstring.hh"
12 #include "common/ceph_json.h"
13 #include "include/assert.h" /* needed because of common/ceph_json.h */
14 #include "rgw_op.h"
15 #include "rgw_formats.h"
16 #include "rgw_client_io.h"
17
18 extern std::map<std::string, std::string> rgw_to_http_attrs;
19
20 extern string camelcase_dash_http_attr(const string& orig);
21 extern string lowercase_dash_http_attr(const string& orig);
22
23 extern void rgw_rest_init(CephContext *cct, RGWRados *store, RGWZoneGroup& zone_group);
24
25 extern void rgw_flush_formatter_and_reset(struct req_state *s,
26 ceph::Formatter *formatter);
27
28 extern void rgw_flush_formatter(struct req_state *s,
29 ceph::Formatter *formatter);
30
31 extern int rgw_rest_read_all_input(struct req_state *s, char **data, int *plen,
32 uint64_t max_len, bool allow_chunked=true);
33
34 template <class T>
35 int rgw_rest_get_json_input(CephContext *cct, req_state *s, T& out,
36 uint64_t max_len, bool *empty)
37 {
38 int rv, data_len;
39 char *data;
40
41 if (empty)
42 *empty = false;
43
44 if ((rv = rgw_rest_read_all_input(s, &data, &data_len, max_len)) < 0) {
45 return rv;
46 }
47
48 if (!data_len) {
49 if (empty) {
50 *empty = true;
51 }
52
53 return -EINVAL;
54 }
55
56 JSONParser parser;
57
58 if (!parser.parse(data, data_len)) {
59 free(data);
60 return -EINVAL;
61 }
62
63 free(data);
64
65 try {
66 decode_json_obj(out, &parser);
67 } catch (JSONDecoder::err& e) {
68 return -EINVAL;
69 }
70
71 return 0;
72 }
73
74 template <class T>
75 int rgw_rest_get_json_input_keep_data(CephContext *cct, req_state *s, T& out, uint64_t max_len, char **pdata, int *len)
76 {
77 int rv, data_len;
78 char *data;
79
80 if ((rv = rgw_rest_read_all_input(s, &data, &data_len, max_len)) < 0) {
81 return rv;
82 }
83
84 if (!data_len) {
85 return -EINVAL;
86 }
87
88 *len = data_len;
89
90 JSONParser parser;
91
92 if (!parser.parse(data, data_len)) {
93 free(data);
94 return -EINVAL;
95 }
96
97 try {
98 decode_json_obj(out, &parser);
99 } catch (JSONDecoder::err& e) {
100 free(data);
101 return -EINVAL;
102 }
103
104 *pdata = data;
105 return 0;
106 }
107
108 class RESTArgs {
109 public:
110 static int get_string(struct req_state *s, const string& name,
111 const string& def_val, string *val,
112 bool *existed = NULL);
113 static int get_uint64(struct req_state *s, const string& name,
114 uint64_t def_val, uint64_t *val, bool *existed = NULL);
115 static int get_int64(struct req_state *s, const string& name,
116 int64_t def_val, int64_t *val, bool *existed = NULL);
117 static int get_uint32(struct req_state *s, const string& name,
118 uint32_t def_val, uint32_t *val, bool *existed = NULL);
119 static int get_int32(struct req_state *s, const string& name,
120 int32_t def_val, int32_t *val, bool *existed = NULL);
121 static int get_time(struct req_state *s, const string& name,
122 const utime_t& def_val, utime_t *val,
123 bool *existed = NULL);
124 static int get_epoch(struct req_state *s, const string& name,
125 uint64_t def_val, uint64_t *epoch,
126 bool *existed = NULL);
127 static int get_bool(struct req_state *s, const string& name, bool def_val,
128 bool *val, bool *existed = NULL);
129 };
130
131 class RGWRESTFlusher : public RGWFormatterFlusher {
132 struct req_state *s;
133 RGWOp *op;
134 protected:
135 void do_flush() override;
136 void do_start(int ret) override;
137 public:
138 RGWRESTFlusher(struct req_state *_s, RGWOp *_op) :
139 RGWFormatterFlusher(_s->formatter), s(_s), op(_op) {}
140 RGWRESTFlusher() : RGWFormatterFlusher(NULL), s(NULL), op(NULL) {}
141
142 void init(struct req_state *_s, RGWOp *_op) {
143 s = _s;
144 op = _op;
145 set_formatter(s->formatter);
146 }
147 };
148
149 class RGWGetObj_ObjStore : public RGWGetObj
150 {
151 protected:
152 bool sent_header;
153 public:
154 RGWGetObj_ObjStore() : sent_header(false) {}
155
156 void init(RGWRados *store, struct req_state *s, RGWHandler *h) override {
157 RGWGetObj::init(store, s, h);
158 sent_header = false;
159 }
160
161 int get_params() override;
162 };
163
164 class RGWListBuckets_ObjStore : public RGWListBuckets {
165 public:
166 RGWListBuckets_ObjStore() {}
167 ~RGWListBuckets_ObjStore() override {}
168 };
169
170 class RGWGetUsage_ObjStore : public RGWGetUsage {
171 public:
172 RGWGetUsage_ObjStore() {}
173 ~RGWGetUsage_ObjStore() override {}
174 };
175
176 class RGWListBucket_ObjStore : public RGWListBucket {
177 public:
178 RGWListBucket_ObjStore() {}
179 ~RGWListBucket_ObjStore() override {}
180 };
181
182 class RGWStatAccount_ObjStore : public RGWStatAccount {
183 public:
184 RGWStatAccount_ObjStore() {}
185 ~RGWStatAccount_ObjStore() override {}
186 };
187
188 class RGWStatBucket_ObjStore : public RGWStatBucket {
189 public:
190 RGWStatBucket_ObjStore() {}
191 ~RGWStatBucket_ObjStore() override {}
192 };
193
194 class RGWCreateBucket_ObjStore : public RGWCreateBucket {
195 public:
196 RGWCreateBucket_ObjStore() {}
197 ~RGWCreateBucket_ObjStore() override {}
198 };
199
200 class RGWDeleteBucket_ObjStore : public RGWDeleteBucket {
201 public:
202 RGWDeleteBucket_ObjStore() {}
203 ~RGWDeleteBucket_ObjStore() override {}
204 };
205
206 class RGWPutObj_ObjStore : public RGWPutObj
207 {
208 public:
209 RGWPutObj_ObjStore() {}
210 ~RGWPutObj_ObjStore() override {}
211
212 int verify_params() override;
213 int get_params() override;
214 int get_data(bufferlist& bl) override;
215
216 int get_padding_last_aws4_chunk_encoded(bufferlist &bl, uint64_t chunk_size);
217 };
218
219 class RGWPostObj_ObjStore : public RGWPostObj
220 {
221 std::string boundary;
222
223 public:
224 struct post_part_field {
225 std::string val;
226 std::map<std::string, std::string> params;
227 };
228
229 struct post_form_part {
230 std::string name;
231 std::map<std::string, post_part_field, ltstr_nocase> fields;
232 ceph::bufferlist data;
233 };
234
235 protected:
236 using parts_collection_t = \
237 std::map<std::string, post_form_part, const ltstr_nocase>;
238
239 std::string err_msg;
240 ceph::bufferlist in_data;
241
242 int read_with_boundary(ceph::bufferlist& bl,
243 uint64_t max,
244 bool check_eol,
245 bool& reached_boundary,
246 bool& done);
247
248 int read_line(ceph::bufferlist& bl,
249 uint64_t max,
250 bool& reached_boundary,
251 bool& done);
252
253 int read_data(ceph::bufferlist& bl,
254 uint64_t max,
255 bool& reached_boundary,
256 bool& done);
257
258 int read_form_part_header(struct post_form_part *part, bool& done);
259
260 int get_params() override;
261
262 static int parse_part_field(const std::string& line,
263 std::string& field_name, /* out */
264 post_part_field& field); /* out */
265
266 static void parse_boundary_params(const std::string& params_str,
267 std::string& first,
268 std::map<std::string, std::string>& params);
269
270 static bool part_str(parts_collection_t& parts,
271 const std::string& name,
272 std::string *val);
273
274 static std::string get_part_str(parts_collection_t& parts,
275 const std::string& name,
276 const std::string& def_val = std::string());
277
278 static bool part_bl(parts_collection_t& parts,
279 const std::string& name,
280 ceph::bufferlist *pbl);
281
282 public:
283 RGWPostObj_ObjStore() {}
284 ~RGWPostObj_ObjStore() override {}
285
286 int verify_params() override;
287 };
288
289
290 class RGWPutMetadataAccount_ObjStore : public RGWPutMetadataAccount
291 {
292 public:
293 RGWPutMetadataAccount_ObjStore() {}
294 ~RGWPutMetadataAccount_ObjStore() override {}
295 };
296
297 class RGWPutMetadataBucket_ObjStore : public RGWPutMetadataBucket
298 {
299 public:
300 RGWPutMetadataBucket_ObjStore() {}
301 ~RGWPutMetadataBucket_ObjStore() override {}
302 };
303
304 class RGWPutMetadataObject_ObjStore : public RGWPutMetadataObject
305 {
306 public:
307 RGWPutMetadataObject_ObjStore() {}
308 ~RGWPutMetadataObject_ObjStore() override {}
309 };
310
311 class RGWDeleteObj_ObjStore : public RGWDeleteObj {
312 public:
313 RGWDeleteObj_ObjStore() {}
314 ~RGWDeleteObj_ObjStore() override {}
315 };
316
317 class RGWGetCrossDomainPolicy_ObjStore : public RGWGetCrossDomainPolicy {
318 public:
319 RGWGetCrossDomainPolicy_ObjStore() = default;
320 ~RGWGetCrossDomainPolicy_ObjStore() override = default;
321 };
322
323 class RGWGetHealthCheck_ObjStore : public RGWGetHealthCheck {
324 public:
325 RGWGetHealthCheck_ObjStore() = default;
326 ~RGWGetHealthCheck_ObjStore() override = default;
327 };
328
329 class RGWCopyObj_ObjStore : public RGWCopyObj {
330 public:
331 RGWCopyObj_ObjStore() {}
332 ~RGWCopyObj_ObjStore() override {}
333 };
334
335 class RGWGetACLs_ObjStore : public RGWGetACLs {
336 public:
337 RGWGetACLs_ObjStore() {}
338 ~RGWGetACLs_ObjStore() override {}
339 };
340
341 class RGWPutACLs_ObjStore : public RGWPutACLs {
342 public:
343 RGWPutACLs_ObjStore() {}
344 ~RGWPutACLs_ObjStore() override {}
345
346 int get_params() override;
347 };
348
349 class RGWGetLC_ObjStore : public RGWGetLC {
350 public:
351 RGWGetLC_ObjStore() {}
352 ~RGWGetLC_ObjStore() override {}
353 };
354
355 class RGWPutLC_ObjStore : public RGWPutLC {
356 public:
357 RGWPutLC_ObjStore() {}
358 ~RGWPutLC_ObjStore() override {}
359
360 int get_params() override;
361 };
362
363 class RGWDeleteLC_ObjStore : public RGWDeleteLC {
364 public:
365 RGWDeleteLC_ObjStore() {}
366 ~RGWDeleteLC_ObjStore() override {}
367
368 };
369
370 class RGWGetCORS_ObjStore : public RGWGetCORS {
371 public:
372 RGWGetCORS_ObjStore() {}
373 ~RGWGetCORS_ObjStore() override {}
374 };
375
376 class RGWPutCORS_ObjStore : public RGWPutCORS {
377 public:
378 RGWPutCORS_ObjStore() {}
379 ~RGWPutCORS_ObjStore() override {}
380 };
381
382 class RGWDeleteCORS_ObjStore : public RGWDeleteCORS {
383 public:
384 RGWDeleteCORS_ObjStore() {}
385 ~RGWDeleteCORS_ObjStore() override {}
386 };
387
388 class RGWOptionsCORS_ObjStore : public RGWOptionsCORS {
389 public:
390 RGWOptionsCORS_ObjStore() {}
391 ~RGWOptionsCORS_ObjStore() override {}
392 };
393
394 class RGWInitMultipart_ObjStore : public RGWInitMultipart {
395 public:
396 RGWInitMultipart_ObjStore() {}
397 ~RGWInitMultipart_ObjStore() override {}
398 };
399
400 class RGWCompleteMultipart_ObjStore : public RGWCompleteMultipart {
401 public:
402 RGWCompleteMultipart_ObjStore() {}
403 ~RGWCompleteMultipart_ObjStore() override {}
404
405 int get_params() override;
406 };
407
408 class RGWAbortMultipart_ObjStore : public RGWAbortMultipart {
409 public:
410 RGWAbortMultipart_ObjStore() {}
411 ~RGWAbortMultipart_ObjStore() override {}
412 };
413
414 class RGWListMultipart_ObjStore : public RGWListMultipart {
415 public:
416 RGWListMultipart_ObjStore() {}
417 ~RGWListMultipart_ObjStore() override {}
418
419 int get_params() override;
420 };
421
422 class RGWListBucketMultiparts_ObjStore : public RGWListBucketMultiparts {
423 public:
424 RGWListBucketMultiparts_ObjStore() {}
425 ~RGWListBucketMultiparts_ObjStore() override {}
426
427 int get_params() override;
428 };
429
430 class RGWBulkDelete_ObjStore : public RGWBulkDelete {
431 public:
432 RGWBulkDelete_ObjStore() {}
433 ~RGWBulkDelete_ObjStore() override {}
434 };
435
436 class RGWBulkUploadOp_ObjStore : public RGWBulkUploadOp {
437 public:
438 RGWBulkUploadOp_ObjStore() = default;
439 ~RGWBulkUploadOp_ObjStore() = default;
440 };
441
442 class RGWDeleteMultiObj_ObjStore : public RGWDeleteMultiObj {
443 public:
444 RGWDeleteMultiObj_ObjStore() {}
445 ~RGWDeleteMultiObj_ObjStore() override {}
446
447 int get_params() override;
448 };
449
450 class RGWInfo_ObjStore : public RGWInfo {
451 public:
452 RGWInfo_ObjStore() = default;
453 ~RGWInfo_ObjStore() override = default;
454 };
455
456 class RGWRESTOp : public RGWOp {
457 protected:
458 int http_ret;
459 RGWRESTFlusher flusher;
460 public:
461 RGWRESTOp() : http_ret(0) {}
462 void init(RGWRados *store, struct req_state *s,
463 RGWHandler *dialect_handler) override {
464 RGWOp::init(store, s, dialect_handler);
465 flusher.init(s, this);
466 }
467 void send_response() override;
468 virtual int check_caps(RGWUserCaps& caps)
469 { return -EPERM; } /* should to be implemented! */
470 int verify_permission() override;
471 };
472
473 class RGWHandler_REST : public RGWHandler {
474 protected:
475
476 virtual bool is_obj_update_op() { return false; }
477 virtual RGWOp *op_get() { return NULL; }
478 virtual RGWOp *op_put() { return NULL; }
479 virtual RGWOp *op_delete() { return NULL; }
480 virtual RGWOp *op_head() { return NULL; }
481 virtual RGWOp *op_post() { return NULL; }
482 virtual RGWOp *op_copy() { return NULL; }
483 virtual RGWOp *op_options() { return NULL; }
484
485 static int allocate_formatter(struct req_state *s, int default_formatter,
486 bool configurable);
487 public:
488 static constexpr int MAX_BUCKET_NAME_LEN = 255;
489 static constexpr int MAX_OBJ_NAME_LEN = 1024;
490
491 RGWHandler_REST() {}
492 ~RGWHandler_REST() override {}
493
494 static int validate_tenant_name(const string& bucket);
495 static int validate_bucket_name(const string& bucket);
496 static int validate_object_name(const string& object);
497
498 int init_permissions(RGWOp* op) override;
499 int read_permissions(RGWOp* op) override;
500
501 virtual RGWOp* get_op(RGWRados* store);
502 virtual void put_op(RGWOp* op);
503 };
504
505 class RGWHandler_REST_SWIFT;
506 class RGWHandler_SWIFT_Auth;
507 class RGWHandler_REST_S3;
508
509 namespace rgw {
510 namespace auth {
511
512 class StrategyRegistry;
513
514 }
515 }
516
517 class RGWRESTMgr {
518 bool should_log;
519
520 protected:
521 std::map<std::string, RGWRESTMgr*> resource_mgrs;
522 std::multimap<size_t, std::string> resources_by_size;
523 RGWRESTMgr* default_mgr;
524
525 virtual RGWRESTMgr* get_resource_mgr(struct req_state* s,
526 const std::string& uri,
527 std::string* out_uri);
528
529 virtual RGWRESTMgr* get_resource_mgr_as_default(struct req_state* const s,
530 const std::string& uri,
531 std::string* our_uri) {
532 return this;
533 }
534
535 public:
536 RGWRESTMgr()
537 : should_log(false),
538 default_mgr(nullptr) {
539 }
540 virtual ~RGWRESTMgr();
541
542 void register_resource(std::string resource, RGWRESTMgr* mgr);
543 void register_default_mgr(RGWRESTMgr* mgr);
544
545 virtual RGWRESTMgr* get_manager(struct req_state* const s,
546 /* Prefix to be concatenated with @uri
547 * during the lookup. */
548 const std::string& frontend_prefix,
549 const std::string& uri,
550 std::string* out_uri) final {
551 return get_resource_mgr(s, frontend_prefix + uri, out_uri);
552 }
553
554 virtual RGWHandler_REST* get_handler(
555 struct req_state* const s,
556 const rgw::auth::StrategyRegistry& auth_registry,
557 const std::string& frontend_prefix
558 ) {
559 return nullptr;
560 }
561
562 virtual void put_handler(RGWHandler_REST* const handler) {
563 delete handler;
564 }
565
566 void set_logging(bool _should_log) {
567 should_log = _should_log;
568 }
569
570 bool get_logging() const {
571 return should_log;
572 }
573 };
574
575 class RGWLibIO;
576 class RGWRestfulIO;
577
578 class RGWREST {
579 using x_header = basic_sstring<char, uint16_t, 32>;
580 boost::container::flat_set<x_header> x_headers;
581 RGWRESTMgr mgr;
582
583 static int preprocess(struct req_state *s, rgw::io::BasicClient* rio);
584 public:
585 RGWREST() {}
586 RGWHandler_REST *get_handler(RGWRados *store,
587 struct req_state *s,
588 const rgw::auth::StrategyRegistry& auth_registry,
589 const std::string& frontend_prefix,
590 RGWRestfulIO *rio,
591 RGWRESTMgr **pmgr,
592 int *init_error);
593 #if 0
594 RGWHandler *get_handler(RGWRados *store, struct req_state *s,
595 RGWLibIO *io, RGWRESTMgr **pmgr,
596 int *init_error);
597 #endif
598
599 void put_handler(RGWHandler_REST *handler) {
600 mgr.put_handler(handler);
601 }
602
603 void register_resource(string resource, RGWRESTMgr *m,
604 bool register_empty = false) {
605 if (!register_empty && resource.empty())
606 return;
607
608 mgr.register_resource(resource, m);
609 }
610
611 void register_default_mgr(RGWRESTMgr *m) {
612 mgr.register_default_mgr(m);
613 }
614
615 void register_x_headers(const std::string& headers);
616
617 bool log_x_headers(void) {
618 return (x_headers.size() > 0);
619 }
620
621 bool log_x_header(const std::string& header) {
622 return (x_headers.find(header) != x_headers.end());
623 }
624 };
625
626 static constexpr int64_t NO_CONTENT_LENGTH = -1;
627 static constexpr int64_t CHUNKED_TRANSFER_ENCODING = -2;
628
629 extern void set_req_state_err(struct rgw_err &err, int err_no, int prot_flags);
630 extern void set_req_state_err(struct req_state *s, int err_no);
631 extern void dump_errno(int http_ret, string& out);
632 extern void dump_errno(const struct rgw_err &err, string& out);
633 extern void dump_errno(struct req_state *s);
634 extern void dump_errno(struct req_state *s, int http_ret);
635 extern void end_header(struct req_state *s,
636 RGWOp* op = nullptr,
637 const char *content_type = nullptr,
638 const int64_t proposed_content_length =
639 NO_CONTENT_LENGTH,
640 bool force_content_type = false,
641 bool force_no_error = false);
642 extern void dump_start(struct req_state *s);
643 extern void list_all_buckets_start(struct req_state *s);
644 extern void dump_owner(struct req_state *s, const rgw_user& id, string& name,
645 const char *section = NULL);
646 extern void dump_header(struct req_state* s,
647 const boost::string_ref& name,
648 const boost::string_ref& val);
649 extern void dump_header(struct req_state* s,
650 const boost::string_ref& name,
651 ceph::buffer::list& bl);
652 extern void dump_header(struct req_state* s,
653 const boost::string_ref& name,
654 long long val);
655 extern void dump_header(struct req_state* s,
656 const boost::string_ref& name,
657 const utime_t& val);
658 template <class... Args>
659 static inline void dump_header_prefixed(struct req_state* s,
660 const boost::string_ref& name_prefix,
661 const boost::string_ref& name,
662 Args&&... args) {
663 char full_name_buf[name_prefix.size() + name.size() + 1];
664 const auto len = snprintf(full_name_buf, sizeof(full_name_buf), "%.*s%.*s",
665 static_cast<int>(name_prefix.length()),
666 name_prefix.data(),
667 static_cast<int>(name.length()),
668 name.data());
669 boost::string_ref full_name(full_name_buf, len);
670 return dump_header(s, std::move(full_name), std::forward<Args>(args)...);
671 }
672
673 template <class... Args>
674 static inline void dump_header_quoted(struct req_state* s,
675 const boost::string_ref& name,
676 const boost::string_ref& val) {
677 /* We need two extra bytes for quotes. */
678 char qvalbuf[val.size() + 2 + 1];
679 const auto len = snprintf(qvalbuf, sizeof(qvalbuf), "\"%.*s\"",
680 static_cast<int>(val.length()), val.data());
681 return dump_header(s, name, boost::string_ref(qvalbuf, len));
682 }
683
684 template <class ValueT>
685 static inline void dump_header_if_nonempty(struct req_state* s,
686 const boost::string_ref& name,
687 const ValueT& value) {
688 if (name.length() > 0 && value.length() > 0) {
689 return dump_header(s, name, value);
690 }
691 }
692
693 extern void dump_content_length(struct req_state *s, uint64_t len);
694 extern void dump_etag(struct req_state *s,
695 const boost::string_ref& etag,
696 bool quoted = false);
697 extern void dump_etag(struct req_state *s,
698 ceph::buffer::list& bl_etag,
699 bool quoted = false);
700 extern void dump_epoch_header(struct req_state *s, const char *name, real_time t);
701 extern void dump_time_header(struct req_state *s, const char *name, real_time t);
702 extern void dump_last_modified(struct req_state *s, real_time t);
703 extern void abort_early(struct req_state* s, RGWOp* op, int err,
704 RGWHandler* handler);
705 extern void dump_range(struct req_state* s, uint64_t ofs, uint64_t end,
706 uint64_t total_size);
707 extern void dump_continue(struct req_state *s);
708 extern void list_all_buckets_end(struct req_state *s);
709 extern void dump_time(struct req_state *s, const char *name, real_time *t);
710 extern std::string dump_time_to_str(const real_time& t);
711 extern void dump_bucket_from_state(struct req_state *s);
712 extern void dump_uri_from_state(struct req_state *s);
713 extern void dump_redirect(struct req_state *s, const string& redirect);
714 extern bool is_valid_url(const char *url);
715 extern void dump_access_control(struct req_state *s, const char *origin,
716 const char *meth,
717 const char *hdr, const char *exp_hdr,
718 uint32_t max_age);
719 extern void dump_access_control(req_state *s, RGWOp *op);
720
721 extern int dump_body(struct req_state* s, const char* buf, size_t len);
722 extern int dump_body(struct req_state* s, /* const */ ceph::buffer::list& bl);
723 extern int dump_body(struct req_state* s, const std::string& str);
724
725 extern int recv_body(struct req_state* s, char* buf, size_t max);
726
727 #endif /* CEPH_RGW_REST_H */