]>
Commit | Line | Data |
---|---|---|
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 |
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); | |
7c673cae FG |
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; } | |
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 |
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 | ||
7c673cae FG |
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 | bool objs_container; | |
111 | public: | |
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 | ||
122 | class RGWGetBucketLogging_ObjStore_S3 : public RGWGetBucketLogging { | |
123 | public: | |
124 | RGWGetBucketLogging_ObjStore_S3() {} | |
125 | ~RGWGetBucketLogging_ObjStore_S3() override {} | |
126 | ||
127 | void send_response() override; | |
128 | }; | |
129 | ||
130 | class RGWGetBucketLocation_ObjStore_S3 : public RGWGetBucketLocation { | |
131 | public: | |
132 | RGWGetBucketLocation_ObjStore_S3() {} | |
133 | ~RGWGetBucketLocation_ObjStore_S3() override {} | |
134 | ||
135 | void send_response() override; | |
136 | }; | |
137 | ||
138 | class RGWGetBucketVersioning_ObjStore_S3 : public RGWGetBucketVersioning { | |
139 | public: | |
140 | RGWGetBucketVersioning_ObjStore_S3() {} | |
141 | ~RGWGetBucketVersioning_ObjStore_S3() override {} | |
142 | ||
143 | void send_response() override; | |
144 | }; | |
145 | ||
146 | class RGWSetBucketVersioning_ObjStore_S3 : public RGWSetBucketVersioning { | |
147 | public: | |
148 | RGWSetBucketVersioning_ObjStore_S3() {} | |
149 | ~RGWSetBucketVersioning_ObjStore_S3() override {} | |
150 | ||
151 | int get_params() override; | |
152 | void send_response() override; | |
153 | }; | |
154 | ||
155 | class RGWGetBucketWebsite_ObjStore_S3 : public RGWGetBucketWebsite { | |
156 | public: | |
157 | RGWGetBucketWebsite_ObjStore_S3() {} | |
158 | ~RGWGetBucketWebsite_ObjStore_S3() override {} | |
159 | ||
160 | void send_response() override; | |
161 | }; | |
162 | ||
163 | class RGWSetBucketWebsite_ObjStore_S3 : public RGWSetBucketWebsite { | |
164 | public: | |
165 | RGWSetBucketWebsite_ObjStore_S3() {} | |
166 | ~RGWSetBucketWebsite_ObjStore_S3() override {} | |
167 | ||
168 | int get_params() override; | |
169 | void send_response() override; | |
170 | }; | |
171 | ||
172 | class RGWDeleteBucketWebsite_ObjStore_S3 : public RGWDeleteBucketWebsite { | |
173 | public: | |
174 | RGWDeleteBucketWebsite_ObjStore_S3() {} | |
175 | ~RGWDeleteBucketWebsite_ObjStore_S3() override {} | |
176 | ||
177 | void send_response() override; | |
178 | }; | |
179 | ||
180 | class RGWStatBucket_ObjStore_S3 : public RGWStatBucket_ObjStore { | |
181 | public: | |
182 | RGWStatBucket_ObjStore_S3() {} | |
183 | ~RGWStatBucket_ObjStore_S3() override {} | |
184 | ||
185 | void send_response() override; | |
186 | }; | |
187 | ||
188 | class RGWCreateBucket_ObjStore_S3 : public RGWCreateBucket_ObjStore { | |
189 | public: | |
190 | RGWCreateBucket_ObjStore_S3() {} | |
191 | ~RGWCreateBucket_ObjStore_S3() override {} | |
192 | ||
193 | int get_params() override; | |
194 | void send_response() override; | |
195 | }; | |
196 | ||
197 | class RGWDeleteBucket_ObjStore_S3 : public RGWDeleteBucket_ObjStore { | |
198 | public: | |
199 | RGWDeleteBucket_ObjStore_S3() {} | |
200 | ~RGWDeleteBucket_ObjStore_S3() override {} | |
201 | ||
202 | void send_response() override; | |
203 | }; | |
204 | ||
205 | class RGWPutObj_ObjStore_S3 : public RGWPutObj_ObjStore { | |
206 | private: | |
207 | std::map<std::string, std::string> crypt_http_responses; | |
208 | ||
209 | public: | |
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 | ||
225 | class 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 | ||
242 | public: | |
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 | ||
260 | class RGWDeleteObj_ObjStore_S3 : public RGWDeleteObj_ObjStore { | |
261 | public: | |
262 | RGWDeleteObj_ObjStore_S3() {} | |
263 | ~RGWDeleteObj_ObjStore_S3() override {} | |
264 | ||
265 | int get_params() override; | |
266 | void send_response() override; | |
267 | }; | |
268 | ||
269 | class RGWCopyObj_ObjStore_S3 : public RGWCopyObj_ObjStore { | |
270 | bool sent_header; | |
271 | public: | |
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 | ||
282 | class RGWGetACLs_ObjStore_S3 : public RGWGetACLs_ObjStore { | |
283 | public: | |
284 | RGWGetACLs_ObjStore_S3() {} | |
285 | ~RGWGetACLs_ObjStore_S3() override {} | |
286 | ||
287 | void send_response() override; | |
288 | }; | |
289 | ||
290 | class RGWPutACLs_ObjStore_S3 : public RGWPutACLs_ObjStore { | |
291 | public: | |
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 | ||
300 | class RGWGetLC_ObjStore_S3 : public RGWGetLC_ObjStore { | |
301 | protected: | |
11fdf7f2 | 302 | RGWLifecycleConfiguration_S3 config; |
7c673cae FG |
303 | public: |
304 | RGWGetLC_ObjStore_S3() {} | |
305 | ~RGWGetLC_ObjStore_S3() override {} | |
306 | void execute() override; | |
307 | ||
308 | void send_response() override; | |
309 | }; | |
310 | ||
311 | class RGWPutLC_ObjStore_S3 : public RGWPutLC_ObjStore { | |
312 | public: | |
313 | RGWPutLC_ObjStore_S3() {} | |
314 | ~RGWPutLC_ObjStore_S3() override {} | |
315 | ||
316 | void send_response() override; | |
317 | }; | |
318 | ||
319 | class RGWDeleteLC_ObjStore_S3 : public RGWDeleteLC_ObjStore { | |
320 | public: | |
321 | RGWDeleteLC_ObjStore_S3() {} | |
322 | ~RGWDeleteLC_ObjStore_S3() override {} | |
323 | ||
324 | void send_response() override; | |
325 | }; | |
326 | ||
327 | class RGWGetCORS_ObjStore_S3 : public RGWGetCORS_ObjStore { | |
328 | public: | |
329 | RGWGetCORS_ObjStore_S3() {} | |
330 | ~RGWGetCORS_ObjStore_S3() override {} | |
331 | ||
332 | void send_response() override; | |
333 | }; | |
334 | ||
335 | class RGWPutCORS_ObjStore_S3 : public RGWPutCORS_ObjStore { | |
336 | public: | |
337 | RGWPutCORS_ObjStore_S3() {} | |
338 | ~RGWPutCORS_ObjStore_S3() override {} | |
339 | ||
340 | int get_params() override; | |
341 | void send_response() override; | |
342 | }; | |
343 | ||
344 | class RGWDeleteCORS_ObjStore_S3 : public RGWDeleteCORS_ObjStore { | |
345 | public: | |
346 | RGWDeleteCORS_ObjStore_S3() {} | |
347 | ~RGWDeleteCORS_ObjStore_S3() override {} | |
348 | ||
349 | void send_response() override; | |
350 | }; | |
351 | ||
352 | class RGWOptionsCORS_ObjStore_S3 : public RGWOptionsCORS_ObjStore { | |
353 | public: | |
354 | RGWOptionsCORS_ObjStore_S3() {} | |
355 | ~RGWOptionsCORS_ObjStore_S3() override {} | |
356 | ||
357 | void send_response() override; | |
358 | }; | |
359 | ||
360 | class RGWGetRequestPayment_ObjStore_S3 : public RGWGetRequestPayment { | |
361 | public: | |
362 | RGWGetRequestPayment_ObjStore_S3() {} | |
363 | ~RGWGetRequestPayment_ObjStore_S3() override {} | |
364 | ||
365 | void send_response() override; | |
366 | }; | |
367 | ||
368 | class RGWSetRequestPayment_ObjStore_S3 : public RGWSetRequestPayment { | |
369 | public: | |
370 | RGWSetRequestPayment_ObjStore_S3() {} | |
371 | ~RGWSetRequestPayment_ObjStore_S3() override {} | |
372 | ||
373 | int get_params() override; | |
374 | void send_response() override; | |
375 | }; | |
376 | ||
377 | class RGWInitMultipart_ObjStore_S3 : public RGWInitMultipart_ObjStore { | |
378 | private: | |
379 | std::map<std::string, std::string> crypt_http_responses; | |
380 | public: | |
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 | ||
389 | class RGWCompleteMultipart_ObjStore_S3 : public RGWCompleteMultipart_ObjStore { | |
390 | public: | |
391 | RGWCompleteMultipart_ObjStore_S3() {} | |
392 | ~RGWCompleteMultipart_ObjStore_S3() override {} | |
393 | ||
394 | int get_params() override; | |
395 | void send_response() override; | |
396 | }; | |
397 | ||
398 | class RGWAbortMultipart_ObjStore_S3 : public RGWAbortMultipart_ObjStore { | |
399 | public: | |
400 | RGWAbortMultipart_ObjStore_S3() {} | |
401 | ~RGWAbortMultipart_ObjStore_S3() override {} | |
402 | ||
403 | void send_response() override; | |
404 | }; | |
405 | ||
406 | class RGWListMultipart_ObjStore_S3 : public RGWListMultipart_ObjStore { | |
407 | public: | |
408 | RGWListMultipart_ObjStore_S3() {} | |
409 | ~RGWListMultipart_ObjStore_S3() override {} | |
410 | ||
411 | void send_response() override; | |
412 | }; | |
413 | ||
414 | class RGWListBucketMultiparts_ObjStore_S3 : public RGWListBucketMultiparts_ObjStore { | |
415 | public: | |
416 | RGWListBucketMultiparts_ObjStore_S3() { | |
417 | default_max = 1000; | |
418 | } | |
419 | ~RGWListBucketMultiparts_ObjStore_S3() override {} | |
420 | ||
421 | void send_response() override; | |
422 | }; | |
423 | ||
424 | class RGWDeleteMultiObj_ObjStore_S3 : public RGWDeleteMultiObj_ObjStore { | |
425 | public: | |
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 | ||
437 | class RGWGetObjLayout_ObjStore_S3 : public RGWGetObjLayout { | |
438 | public: | |
439 | RGWGetObjLayout_ObjStore_S3() {} | |
440 | ~RGWGetObjLayout_ObjStore_S3() {} | |
441 | ||
11fdf7f2 | 442 | void send_response() override; |
7c673cae FG |
443 | }; |
444 | ||
31f18b77 FG |
445 | class RGWConfigBucketMetaSearch_ObjStore_S3 : public RGWConfigBucketMetaSearch { |
446 | public: | |
447 | RGWConfigBucketMetaSearch_ObjStore_S3() {} | |
448 | ~RGWConfigBucketMetaSearch_ObjStore_S3() {} | |
449 | ||
450 | int get_params() override; | |
451 | void send_response() override; | |
452 | }; | |
453 | ||
454 | class RGWGetBucketMetaSearch_ObjStore_S3 : public RGWGetBucketMetaSearch { | |
455 | public: | |
456 | RGWGetBucketMetaSearch_ObjStore_S3() {} | |
457 | ~RGWGetBucketMetaSearch_ObjStore_S3() {} | |
458 | ||
459 | void send_response() override; | |
460 | }; | |
461 | ||
462 | class RGWDelBucketMetaSearch_ObjStore_S3 : public RGWDelBucketMetaSearch { | |
463 | public: | |
464 | RGWDelBucketMetaSearch_ObjStore_S3() {} | |
465 | ~RGWDelBucketMetaSearch_ObjStore_S3() {} | |
466 | ||
467 | void send_response() override; | |
468 | }; | |
7c673cae FG |
469 | |
470 | class RGW_Auth_S3 { | |
7c673cae | 471 | public: |
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 | ||
478 | class RGWHandler_Auth_S3 : public RGWHandler_REST { | |
479 | friend class RGWRESTMgr_S3; | |
480 | ||
481 | const rgw::auth::StrategyRegistry& auth_registry; | |
482 | ||
483 | public: | |
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 | ||
502 | class RGWHandler_REST_S3 : public RGWHandler_REST { | |
503 | friend class RGWRESTMgr_S3; | |
11fdf7f2 | 504 | protected: |
7c673cae FG |
505 | const rgw::auth::StrategyRegistry& auth_registry; |
506 | public: | |
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 | ||
522 | class RGWHandler_REST_Service_S3 : public RGWHandler_REST_S3 { | |
523 | protected: | |
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; | |
531 | public: | |
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 | ||
538 | class RGWHandler_REST_Bucket_S3 : public RGWHandler_REST_S3 { | |
539 | protected: | |
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; | |
566 | public: | |
567 | using RGWHandler_REST_S3::RGWHandler_REST_S3; | |
568 | ~RGWHandler_REST_Bucket_S3() override = default; | |
569 | }; | |
570 | ||
571 | class RGWHandler_REST_Obj_S3 : public RGWHandler_REST_S3 { | |
572 | protected: | |
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; | |
590 | public: | |
591 | using RGWHandler_REST_S3::RGWHandler_REST_S3; | |
592 | ~RGWHandler_REST_Obj_S3() override = default; | |
593 | }; | |
594 | ||
595 | class RGWRESTMgr_S3 : public RGWRESTMgr { | |
596 | private: | |
597 | bool enable_s3website; | |
11fdf7f2 | 598 | bool enable_sts; |
7c673cae | 599 | public: |
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 | ||
612 | class RGWHandler_REST_Obj_S3Website; | |
613 | ||
614 | static 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 | ||
637 | static 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 | ||
647 | static 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 | ||
687 | namespace rgw { | |
688 | namespace auth { | |
689 | namespace s3 { | |
690 | ||
31f18b77 | 691 | class AWSEngine : public rgw::auth::Engine { |
7c673cae | 692 | public: |
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 | ||
739 | protected: | |
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 | ||
765 | public: | |
11fdf7f2 | 766 | result_t authenticate(const DoutPrefixProvider* dpp, const req_state* const s) const final; |
7c673cae FG |
767 | }; |
768 | ||
31f18b77 FG |
769 | |
770 | class 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 | 781 | public: |
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 |
789 | class 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 | ||
795 | public: | |
796 | using AWSGeneralAbstractor::AWSGeneralAbstractor; | |
797 | }; | |
7c673cae | 798 | |
31f18b77 | 799 | class 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 | 808 | public: |
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 | 816 | class 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 | ||
826 | protected: | |
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; |
841 | public: | |
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 | 862 | class 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; |
874 | public: | |
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 |
891 | class 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; | |
914 | public: | |
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 |
935 | class S3AnonymousEngine : public rgw::auth::AnonymousEngine { |
936 | bool is_applicable(const req_state* s) const noexcept override; | |
937 | ||
938 | public: | |
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 |
948 | class 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 | ||
953 | public: | |
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 */ |