]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_rest_user.cc
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / rgw / rgw_rest_user.cc
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 #include "common/ceph_json.h"
5
6 #include "rgw_op.h"
7 #include "rgw_user.h"
8 #include "rgw_rest_user.h"
9 #include "rgw_sal_rados.h"
10
11 #include "include/str_list.h"
12 #include "include/ceph_assert.h"
13
14 #include "services/svc_zone.h"
15 #include "services/svc_sys_obj.h"
16 #include "rgw_zone.h"
17
18 #define dout_subsys ceph_subsys_rgw
19
20 class RGWOp_User_List : public RGWRESTOp {
21
22 public:
23 RGWOp_User_List() {}
24
25 int check_caps(const RGWUserCaps& caps) override {
26 return caps.check_cap("users", RGW_CAP_READ);
27 }
28
29 void execute(optional_yield y) override;
30
31 const char* name() const override { return "list_user"; }
32 };
33
34 void RGWOp_User_List::execute(optional_yield y)
35 {
36 RGWUserAdminOpState op_state;
37
38 uint32_t max_entries;
39 std::string marker;
40 RESTArgs::get_uint32(s, "max-entries", 1000, &max_entries);
41 RESTArgs::get_string(s, "marker", marker, &marker);
42
43 op_state.max_entries = max_entries;
44 op_state.marker = marker;
45 op_ret = RGWUserAdminOp_User::list(store, op_state, flusher);
46 }
47
48 class RGWOp_User_Info : public RGWRESTOp {
49
50 public:
51 RGWOp_User_Info() {}
52
53 int check_caps(const RGWUserCaps& caps) override {
54 return caps.check_cap("users", RGW_CAP_READ);
55 }
56
57 void execute(optional_yield y) override;
58
59 const char* name() const override { return "get_user_info"; }
60 };
61
62 void RGWOp_User_Info::execute(optional_yield y)
63 {
64 RGWUserAdminOpState op_state;
65
66 std::string uid_str, access_key_str;
67 bool fetch_stats;
68 bool sync_stats;
69
70 RESTArgs::get_string(s, "uid", uid_str, &uid_str);
71 RESTArgs::get_string(s, "access-key", access_key_str, &access_key_str);
72
73 // if uid was not supplied in rest argument, error out now, otherwise we'll
74 // end up initializing anonymous user, for which keys.init will eventually
75 // return -EACESS
76 if (uid_str.empty() && access_key_str.empty()){
77 op_ret=-EINVAL;
78 return;
79 }
80
81 rgw_user uid(uid_str);
82
83 RESTArgs::get_bool(s, "stats", false, &fetch_stats);
84
85 RESTArgs::get_bool(s, "sync", false, &sync_stats);
86
87 op_state.set_user_id(uid);
88 op_state.set_access_key(access_key_str);
89 op_state.set_fetch_stats(fetch_stats);
90 op_state.set_sync_stats(sync_stats);
91
92 op_ret = RGWUserAdminOp_User::info(store, op_state, flusher, y);
93 }
94
95 class RGWOp_User_Create : public RGWRESTOp {
96
97 public:
98 RGWOp_User_Create() {}
99
100 int check_caps(const RGWUserCaps& caps) override {
101 return caps.check_cap("users", RGW_CAP_WRITE);
102 }
103
104 void execute(optional_yield y) override;
105
106 const char* name() const override { return "create_user"; }
107 };
108
109 void RGWOp_User_Create::execute(optional_yield y)
110 {
111 std::string uid_str;
112 std::string display_name;
113 std::string email;
114 std::string access_key;
115 std::string secret_key;
116 std::string key_type_str;
117 std::string caps;
118 std::string tenant_name;
119 std::string op_mask_str;
120 std::string default_placement_str;
121 std::string placement_tags_str;
122
123 bool gen_key;
124 bool suspended;
125 bool system;
126 bool exclusive;
127
128 int32_t max_buckets;
129 const int32_t default_max_buckets =
130 s->cct->_conf.get_val<int64_t>("rgw_user_max_buckets");
131
132 RGWUserAdminOpState op_state;
133
134 RESTArgs::get_string(s, "uid", uid_str, &uid_str);
135 rgw_user uid(uid_str);
136
137 RESTArgs::get_string(s, "display-name", display_name, &display_name);
138 RESTArgs::get_string(s, "email", email, &email);
139 RESTArgs::get_string(s, "access-key", access_key, &access_key);
140 RESTArgs::get_string(s, "secret-key", secret_key, &secret_key);
141 RESTArgs::get_string(s, "key-type", key_type_str, &key_type_str);
142 RESTArgs::get_string(s, "user-caps", caps, &caps);
143 RESTArgs::get_string(s, "tenant", tenant_name, &tenant_name);
144 RESTArgs::get_bool(s, "generate-key", true, &gen_key);
145 RESTArgs::get_bool(s, "suspended", false, &suspended);
146 RESTArgs::get_int32(s, "max-buckets", default_max_buckets, &max_buckets);
147 RESTArgs::get_bool(s, "system", false, &system);
148 RESTArgs::get_bool(s, "exclusive", false, &exclusive);
149 RESTArgs::get_string(s, "op-mask", op_mask_str, &op_mask_str);
150 RESTArgs::get_string(s, "default-placement", default_placement_str, &default_placement_str);
151 RESTArgs::get_string(s, "placement-tags", placement_tags_str, &placement_tags_str);
152
153 if (!s->user->get_info().system && system) {
154 ldout(s->cct, 0) << "cannot set system flag by non-system user" << dendl;
155 op_ret = -EINVAL;
156 return;
157 }
158
159 if (!tenant_name.empty()) {
160 uid.tenant = tenant_name;
161 }
162
163 // TODO: validate required args are passed in. (for eg. uid and display_name here)
164 op_state.set_user_id(uid);
165 op_state.set_display_name(display_name);
166 op_state.set_user_email(email);
167 op_state.set_caps(caps);
168 op_state.set_access_key(access_key);
169 op_state.set_secret_key(secret_key);
170
171 if (!op_mask_str.empty()) {
172 uint32_t op_mask;
173 int ret = rgw_parse_op_type_list(op_mask_str, &op_mask);
174 if (ret < 0) {
175 ldout(s->cct, 0) << "failed to parse op_mask: " << ret << dendl;
176 op_ret = -EINVAL;
177 return;
178 }
179 op_state.set_op_mask(op_mask);
180 }
181
182 if (!key_type_str.empty()) {
183 int32_t key_type = KEY_TYPE_UNDEFINED;
184 if (key_type_str.compare("swift") == 0)
185 key_type = KEY_TYPE_SWIFT;
186 else if (key_type_str.compare("s3") == 0)
187 key_type = KEY_TYPE_S3;
188
189 op_state.set_key_type(key_type);
190 }
191
192 if (max_buckets != default_max_buckets) {
193 if (max_buckets < 0) {
194 max_buckets = -1;
195 }
196 op_state.set_max_buckets(max_buckets);
197 }
198 if (s->info.args.exists("suspended"))
199 op_state.set_suspension(suspended);
200
201 if (s->info.args.exists("system"))
202 op_state.set_system(system);
203
204 if (s->info.args.exists("exclusive"))
205 op_state.set_exclusive(exclusive);
206
207 if (gen_key)
208 op_state.set_generate_key();
209
210 if (!default_placement_str.empty()) {
211 rgw_placement_rule target_rule;
212 target_rule.from_str(default_placement_str);
213 if (!store->svc()->zone->get_zone_params().valid_placement(target_rule)) {
214 ldout(s->cct, 0) << "NOTICE: invalid dest placement: " << target_rule.to_str() << dendl;
215 op_ret = -EINVAL;
216 return;
217 }
218 op_state.set_default_placement(target_rule);
219 }
220
221 if (!placement_tags_str.empty()) {
222 list<string> placement_tags_list;
223 get_str_list(placement_tags_str, ",", placement_tags_list);
224 op_state.set_placement_tags(placement_tags_list);
225 }
226
227 bufferlist data;
228 op_ret = store->forward_request_to_master(s->user.get(), nullptr, data, nullptr, s->info, y);
229 if (op_ret < 0) {
230 ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret << dendl;
231 return;
232 }
233 op_ret = RGWUserAdminOp_User::create(store, op_state, flusher, y);
234 }
235
236 class RGWOp_User_Modify : public RGWRESTOp {
237
238 public:
239 RGWOp_User_Modify() {}
240
241 int check_caps(const RGWUserCaps& caps) override {
242 return caps.check_cap("users", RGW_CAP_WRITE);
243 }
244
245 void execute(optional_yield y) override;
246
247 const char* name() const override { return "modify_user"; }
248 };
249
250 void RGWOp_User_Modify::execute(optional_yield y)
251 {
252 std::string uid_str;
253 std::string display_name;
254 std::string email;
255 std::string access_key;
256 std::string secret_key;
257 std::string key_type_str;
258 std::string caps;
259 std::string op_mask_str;
260 std::string default_placement_str;
261 std::string placement_tags_str;
262
263 bool gen_key;
264 bool suspended;
265 bool system;
266 bool email_set;
267 bool quota_set;
268 int32_t max_buckets;
269
270 RGWUserAdminOpState op_state;
271
272 RESTArgs::get_string(s, "uid", uid_str, &uid_str);
273 rgw_user uid(uid_str);
274
275 RESTArgs::get_string(s, "display-name", display_name, &display_name);
276 RESTArgs::get_string(s, "email", email, &email, &email_set);
277 RESTArgs::get_string(s, "access-key", access_key, &access_key);
278 RESTArgs::get_string(s, "secret-key", secret_key, &secret_key);
279 RESTArgs::get_string(s, "user-caps", caps, &caps);
280 RESTArgs::get_bool(s, "generate-key", false, &gen_key);
281 RESTArgs::get_bool(s, "suspended", false, &suspended);
282 RESTArgs::get_int32(s, "max-buckets", RGW_DEFAULT_MAX_BUCKETS, &max_buckets, &quota_set);
283 RESTArgs::get_string(s, "key-type", key_type_str, &key_type_str);
284
285 RESTArgs::get_bool(s, "system", false, &system);
286 RESTArgs::get_string(s, "op-mask", op_mask_str, &op_mask_str);
287 RESTArgs::get_string(s, "default-placement", default_placement_str, &default_placement_str);
288 RESTArgs::get_string(s, "placement-tags", placement_tags_str, &placement_tags_str);
289
290 if (!s->user->get_info().system && system) {
291 ldout(s->cct, 0) << "cannot set system flag by non-system user" << dendl;
292 op_ret = -EINVAL;
293 return;
294 }
295
296 op_state.set_user_id(uid);
297 op_state.set_display_name(display_name);
298
299 if (email_set)
300 op_state.set_user_email(email);
301
302 op_state.set_caps(caps);
303 op_state.set_access_key(access_key);
304 op_state.set_secret_key(secret_key);
305
306 if (quota_set) {
307 if (max_buckets < 0 ) {
308 max_buckets = -1;
309 }
310 op_state.set_max_buckets(max_buckets);
311 }
312 if (gen_key)
313 op_state.set_generate_key();
314
315 if (!key_type_str.empty()) {
316 int32_t key_type = KEY_TYPE_UNDEFINED;
317 if (key_type_str.compare("swift") == 0)
318 key_type = KEY_TYPE_SWIFT;
319 else if (key_type_str.compare("s3") == 0)
320 key_type = KEY_TYPE_S3;
321
322 op_state.set_key_type(key_type);
323 }
324
325 if (!op_mask_str.empty()) {
326 uint32_t op_mask;
327 if (rgw_parse_op_type_list(op_mask_str, &op_mask) < 0) {
328 ldout(s->cct, 0) << "failed to parse op_mask" << dendl;
329 op_ret = -EINVAL;
330 return;
331 }
332 op_state.set_op_mask(op_mask);
333 }
334
335 if (s->info.args.exists("suspended"))
336 op_state.set_suspension(suspended);
337
338 if (s->info.args.exists("system"))
339 op_state.set_system(system);
340
341 if (!op_mask_str.empty()) {
342 uint32_t op_mask;
343 int ret = rgw_parse_op_type_list(op_mask_str, &op_mask);
344 if (ret < 0) {
345 ldout(s->cct, 0) << "failed to parse op_mask: " << ret << dendl;
346 op_ret = -EINVAL;
347 return;
348 }
349 op_state.set_op_mask(op_mask);
350 }
351
352 if (!default_placement_str.empty()) {
353 rgw_placement_rule target_rule;
354 target_rule.from_str(default_placement_str);
355 if (!store->svc()->zone->get_zone_params().valid_placement(target_rule)) {
356 ldout(s->cct, 0) << "NOTICE: invalid dest placement: " << target_rule.to_str() << dendl;
357 op_ret = -EINVAL;
358 return;
359 }
360 op_state.set_default_placement(target_rule);
361 }
362
363 if (!placement_tags_str.empty()) {
364 list<string> placement_tags_list;
365 get_str_list(placement_tags_str, ",", placement_tags_list);
366 op_state.set_placement_tags(placement_tags_list);
367 }
368
369 bufferlist data;
370 op_ret = store->forward_request_to_master(s->user.get(), nullptr, data, nullptr, s->info, y);
371 if (op_ret < 0) {
372 ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret << dendl;
373 return;
374 }
375 op_ret = RGWUserAdminOp_User::modify(store, op_state, flusher, y);
376 }
377
378 class RGWOp_User_Remove : public RGWRESTOp {
379
380 public:
381 RGWOp_User_Remove() {}
382
383 int check_caps(const RGWUserCaps& caps) override {
384 return caps.check_cap("users", RGW_CAP_WRITE);
385 }
386
387 void execute(optional_yield y) override;
388
389 const char* name() const override { return "remove_user"; }
390 };
391
392 void RGWOp_User_Remove::execute(optional_yield y)
393 {
394 std::string uid_str;
395 bool purge_data;
396
397 RGWUserAdminOpState op_state;
398
399 RESTArgs::get_string(s, "uid", uid_str, &uid_str);
400 rgw_user uid(uid_str);
401
402 RESTArgs::get_bool(s, "purge-data", false, &purge_data);
403
404 // FIXME: no double checking
405 if (!uid.empty())
406 op_state.set_user_id(uid);
407
408 op_state.set_purge_data(purge_data);
409
410 bufferlist data;
411 op_ret = store->forward_request_to_master(s->user.get(), nullptr, data, nullptr, s->info, y);
412 if (op_ret < 0) {
413 ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret << dendl;
414 return;
415 }
416 op_ret = RGWUserAdminOp_User::remove(store, op_state, flusher, s->yield);
417 }
418
419 class RGWOp_Subuser_Create : public RGWRESTOp {
420
421 public:
422 RGWOp_Subuser_Create() {}
423
424 int check_caps(const RGWUserCaps& caps) override {
425 return caps.check_cap("users", RGW_CAP_WRITE);
426 }
427
428 void execute(optional_yield y) override;
429
430 const char* name() const override { return "create_subuser"; }
431 };
432
433 void RGWOp_Subuser_Create::execute(optional_yield y)
434 {
435 std::string uid_str;
436 std::string subuser;
437 std::string secret_key;
438 std::string access_key;
439 std::string perm_str;
440 std::string key_type_str;
441
442 bool gen_subuser = false; // FIXME placeholder
443 bool gen_secret;
444 bool gen_access;
445
446 uint32_t perm_mask = 0;
447 int32_t key_type = KEY_TYPE_SWIFT;
448
449 RGWUserAdminOpState op_state;
450
451 RESTArgs::get_string(s, "uid", uid_str, &uid_str);
452 rgw_user uid(uid_str);
453
454 RESTArgs::get_string(s, "subuser", subuser, &subuser);
455 RESTArgs::get_string(s, "access-key", access_key, &access_key);
456 RESTArgs::get_string(s, "secret-key", secret_key, &secret_key);
457 RESTArgs::get_string(s, "access", perm_str, &perm_str);
458 RESTArgs::get_string(s, "key-type", key_type_str, &key_type_str);
459 //RESTArgs::get_bool(s, "generate-subuser", false, &gen_subuser);
460 RESTArgs::get_bool(s, "generate-secret", false, &gen_secret);
461 RESTArgs::get_bool(s, "gen-access-key", false, &gen_access);
462
463 perm_mask = rgw_str_to_perm(perm_str.c_str());
464 op_state.set_perm(perm_mask);
465
466 op_state.set_user_id(uid);
467 op_state.set_subuser(subuser);
468 op_state.set_access_key(access_key);
469 op_state.set_secret_key(secret_key);
470 op_state.set_generate_subuser(gen_subuser);
471
472 if (gen_access)
473 op_state.set_gen_access();
474
475 if (gen_secret)
476 op_state.set_gen_secret();
477
478 if (!key_type_str.empty()) {
479 if (key_type_str.compare("swift") == 0)
480 key_type = KEY_TYPE_SWIFT;
481 else if (key_type_str.compare("s3") == 0)
482 key_type = KEY_TYPE_S3;
483 }
484 op_state.set_key_type(key_type);
485
486 bufferlist data;
487 op_ret = store->forward_request_to_master(s->user.get(), nullptr, data, nullptr, s->info, y);
488 if (op_ret < 0) {
489 ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret << dendl;
490 return;
491 }
492 op_ret = RGWUserAdminOp_Subuser::create(store, op_state, flusher, y);
493 }
494
495 class RGWOp_Subuser_Modify : public RGWRESTOp {
496
497 public:
498 RGWOp_Subuser_Modify() {}
499
500 int check_caps(const RGWUserCaps& caps) override {
501 return caps.check_cap("users", RGW_CAP_WRITE);
502 }
503
504 void execute(optional_yield y) override;
505
506 const char* name() const override { return "modify_subuser"; }
507 };
508
509 void RGWOp_Subuser_Modify::execute(optional_yield y)
510 {
511 std::string uid_str;
512 std::string subuser;
513 std::string secret_key;
514 std::string key_type_str;
515 std::string perm_str;
516
517 RGWUserAdminOpState op_state;
518
519 uint32_t perm_mask;
520 int32_t key_type = KEY_TYPE_SWIFT;
521
522 bool gen_secret;
523
524 RESTArgs::get_string(s, "uid", uid_str, &uid_str);
525 rgw_user uid(uid_str);
526
527 RESTArgs::get_string(s, "subuser", subuser, &subuser);
528 RESTArgs::get_string(s, "secret-key", secret_key, &secret_key);
529 RESTArgs::get_string(s, "access", perm_str, &perm_str);
530 RESTArgs::get_string(s, "key-type", key_type_str, &key_type_str);
531 RESTArgs::get_bool(s, "generate-secret", false, &gen_secret);
532
533 perm_mask = rgw_str_to_perm(perm_str.c_str());
534 op_state.set_perm(perm_mask);
535
536 op_state.set_user_id(uid);
537 op_state.set_subuser(subuser);
538
539 if (!secret_key.empty())
540 op_state.set_secret_key(secret_key);
541
542 if (gen_secret)
543 op_state.set_gen_secret();
544
545 if (!key_type_str.empty()) {
546 if (key_type_str.compare("swift") == 0)
547 key_type = KEY_TYPE_SWIFT;
548 else if (key_type_str.compare("s3") == 0)
549 key_type = KEY_TYPE_S3;
550 }
551 op_state.set_key_type(key_type);
552
553 bufferlist data;
554 op_ret = store->forward_request_to_master(s->user.get(), nullptr, data, nullptr, s->info, y);
555 if (op_ret < 0) {
556 ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret << dendl;
557 return;
558 }
559 op_ret = RGWUserAdminOp_Subuser::modify(store, op_state, flusher, y);
560 }
561
562 class RGWOp_Subuser_Remove : public RGWRESTOp {
563
564 public:
565 RGWOp_Subuser_Remove() {}
566
567 int check_caps(const RGWUserCaps& caps) override {
568 return caps.check_cap("users", RGW_CAP_WRITE);
569 }
570
571 void execute(optional_yield y) override;
572
573 const char* name() const override { return "remove_subuser"; }
574 };
575
576 void RGWOp_Subuser_Remove::execute(optional_yield y)
577 {
578 std::string uid_str;
579 std::string subuser;
580 bool purge_keys;
581
582 RGWUserAdminOpState op_state;
583
584 RESTArgs::get_string(s, "uid", uid_str, &uid_str);
585 rgw_user uid(uid_str);
586
587 RESTArgs::get_string(s, "subuser", subuser, &subuser);
588 RESTArgs::get_bool(s, "purge-keys", true, &purge_keys);
589
590 op_state.set_user_id(uid);
591 op_state.set_subuser(subuser);
592
593 if (purge_keys)
594 op_state.set_purge_keys();
595
596 bufferlist data;
597 op_ret = store->forward_request_to_master(s->user.get(), nullptr, data, nullptr, s->info, y);
598 if (op_ret < 0) {
599 ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret << dendl;
600 return;
601 }
602 op_ret = RGWUserAdminOp_Subuser::remove(store, op_state, flusher, y);
603 }
604
605 class RGWOp_Key_Create : public RGWRESTOp {
606
607 public:
608 RGWOp_Key_Create() {}
609
610 int check_caps(const RGWUserCaps& caps) override {
611 return caps.check_cap("users", RGW_CAP_WRITE);
612 }
613
614 void execute(optional_yield y) override;
615
616 const char* name() const override { return "create_access_key"; }
617 };
618
619 void RGWOp_Key_Create::execute(optional_yield y)
620 {
621 std::string uid_str;
622 std::string subuser;
623 std::string access_key;
624 std::string secret_key;
625 std::string key_type_str;
626
627 bool gen_key;
628
629 RGWUserAdminOpState op_state;
630
631 RESTArgs::get_string(s, "uid", uid_str, &uid_str);
632 rgw_user uid(uid_str);
633
634 RESTArgs::get_string(s, "subuser", subuser, &subuser);
635 RESTArgs::get_string(s, "access-key", access_key, &access_key);
636 RESTArgs::get_string(s, "secret-key", secret_key, &secret_key);
637 RESTArgs::get_string(s, "key-type", key_type_str, &key_type_str);
638 RESTArgs::get_bool(s, "generate-key", true, &gen_key);
639
640 op_state.set_user_id(uid);
641 op_state.set_subuser(subuser);
642 op_state.set_access_key(access_key);
643 op_state.set_secret_key(secret_key);
644
645 if (gen_key)
646 op_state.set_generate_key();
647
648 if (!key_type_str.empty()) {
649 int32_t key_type = KEY_TYPE_UNDEFINED;
650 if (key_type_str.compare("swift") == 0)
651 key_type = KEY_TYPE_SWIFT;
652 else if (key_type_str.compare("s3") == 0)
653 key_type = KEY_TYPE_S3;
654
655 op_state.set_key_type(key_type);
656 }
657
658 op_ret = RGWUserAdminOp_Key::create(store, op_state, flusher, y);
659 }
660
661 class RGWOp_Key_Remove : public RGWRESTOp {
662
663 public:
664 RGWOp_Key_Remove() {}
665
666 int check_caps(const RGWUserCaps& caps) override {
667 return caps.check_cap("users", RGW_CAP_WRITE);
668 }
669
670 void execute(optional_yield y) override;
671
672 const char* name() const override { return "remove_access_key"; }
673 };
674
675 void RGWOp_Key_Remove::execute(optional_yield y)
676 {
677 std::string uid_str;
678 std::string subuser;
679 std::string access_key;
680 std::string key_type_str;
681
682 RGWUserAdminOpState op_state;
683
684 RESTArgs::get_string(s, "uid", uid_str, &uid_str);
685 rgw_user uid(uid_str);
686
687 RESTArgs::get_string(s, "subuser", subuser, &subuser);
688 RESTArgs::get_string(s, "access-key", access_key, &access_key);
689 RESTArgs::get_string(s, "key-type", key_type_str, &key_type_str);
690
691 op_state.set_user_id(uid);
692 op_state.set_subuser(subuser);
693 op_state.set_access_key(access_key);
694
695 if (!key_type_str.empty()) {
696 int32_t key_type = KEY_TYPE_UNDEFINED;
697 if (key_type_str.compare("swift") == 0)
698 key_type = KEY_TYPE_SWIFT;
699 else if (key_type_str.compare("s3") == 0)
700 key_type = KEY_TYPE_S3;
701
702 op_state.set_key_type(key_type);
703 }
704
705 op_ret = RGWUserAdminOp_Key::remove(store, op_state, flusher, y);
706 }
707
708 class RGWOp_Caps_Add : public RGWRESTOp {
709
710 public:
711 RGWOp_Caps_Add() {}
712
713 int check_caps(const RGWUserCaps& caps) override {
714 return caps.check_cap("users", RGW_CAP_WRITE);
715 }
716
717 void execute(optional_yield y) override;
718
719 const char* name() const override { return "add_user_caps"; }
720 };
721
722 void RGWOp_Caps_Add::execute(optional_yield y)
723 {
724 std::string uid_str;
725 std::string caps;
726
727 RGWUserAdminOpState op_state;
728
729 RESTArgs::get_string(s, "uid", uid_str, &uid_str);
730 rgw_user uid(uid_str);
731
732 RESTArgs::get_string(s, "user-caps", caps, &caps);
733
734 op_state.set_user_id(uid);
735 op_state.set_caps(caps);
736
737 bufferlist data;
738 op_ret = store->forward_request_to_master(s->user.get(), nullptr, data, nullptr, s->info, y);
739 if (op_ret < 0) {
740 ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret << dendl;
741 return;
742 }
743 op_ret = RGWUserAdminOp_Caps::add(store, op_state, flusher, y);
744 }
745
746 class RGWOp_Caps_Remove : public RGWRESTOp {
747
748 public:
749 RGWOp_Caps_Remove() {}
750
751 int check_caps(const RGWUserCaps& caps) override {
752 return caps.check_cap("users", RGW_CAP_WRITE);
753 }
754
755 void execute(optional_yield y) override;
756
757 const char* name() const override { return "remove_user_caps"; }
758 };
759
760 void RGWOp_Caps_Remove::execute(optional_yield y)
761 {
762 std::string uid_str;
763 std::string caps;
764
765 RGWUserAdminOpState op_state;
766
767 RESTArgs::get_string(s, "uid", uid_str, &uid_str);
768 rgw_user uid(uid_str);
769
770 RESTArgs::get_string(s, "user-caps", caps, &caps);
771
772 op_state.set_user_id(uid);
773 op_state.set_caps(caps);
774
775 bufferlist data;
776 op_ret = store->forward_request_to_master(s->user.get(), nullptr, data, nullptr, s->info, y);
777 if (op_ret < 0) {
778 ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret << dendl;
779 return;
780 }
781 op_ret = RGWUserAdminOp_Caps::remove(store, op_state, flusher, y);
782 }
783
784 struct UserQuotas {
785 RGWQuotaInfo bucket_quota;
786 RGWQuotaInfo user_quota;
787
788 UserQuotas() {}
789
790 explicit UserQuotas(RGWUserInfo& info) : bucket_quota(info.bucket_quota),
791 user_quota(info.user_quota) {}
792
793 void dump(Formatter *f) const {
794 encode_json("bucket_quota", bucket_quota, f);
795 encode_json("user_quota", user_quota, f);
796 }
797 void decode_json(JSONObj *obj) {
798 JSONDecoder::decode_json("bucket_quota", bucket_quota, obj);
799 JSONDecoder::decode_json("user_quota", user_quota, obj);
800 }
801 };
802
803 class RGWOp_Quota_Info : public RGWRESTOp {
804
805 public:
806 RGWOp_Quota_Info() {}
807
808 int check_caps(const RGWUserCaps& caps) override {
809 return caps.check_cap("users", RGW_CAP_READ);
810 }
811
812 void execute(optional_yield y) override;
813
814 const char* name() const override { return "get_quota_info"; }
815 };
816
817
818 void RGWOp_Quota_Info::execute(optional_yield y)
819 {
820 RGWUserAdminOpState op_state;
821
822 std::string uid_str;
823 std::string quota_type;
824
825 RESTArgs::get_string(s, "uid", uid_str, &uid_str);
826 RESTArgs::get_string(s, "quota-type", quota_type, &quota_type);
827
828 if (uid_str.empty()) {
829 op_ret = -EINVAL;
830 return;
831 }
832
833 rgw_user uid(uid_str);
834
835 bool show_all = quota_type.empty();
836 bool show_bucket = show_all || (quota_type == "bucket");
837 bool show_user = show_all || (quota_type == "user");
838
839 if (!(show_all || show_bucket || show_user)) {
840 op_ret = -EINVAL;
841 return;
842 }
843
844 op_state.set_user_id(uid);
845
846 RGWUser user;
847 op_ret = user.init(store, op_state, y);
848 if (op_ret < 0)
849 return;
850
851 if (!op_state.has_existing_user()) {
852 op_ret = -ERR_NO_SUCH_USER;
853 return;
854 }
855
856 RGWUserInfo info;
857 string err_msg;
858 op_ret = user.info(info, &err_msg);
859 if (op_ret < 0)
860 return;
861
862 flusher.start(0);
863 if (show_all) {
864 UserQuotas quotas(info);
865 encode_json("quota", quotas, s->formatter);
866 } else if (show_user) {
867 encode_json("user_quota", info.user_quota, s->formatter);
868 } else {
869 encode_json("bucket_quota", info.bucket_quota, s->formatter);
870 }
871
872 flusher.flush();
873 }
874
875 class RGWOp_Quota_Set : public RGWRESTOp {
876
877 public:
878 RGWOp_Quota_Set() {}
879
880 int check_caps(const RGWUserCaps& caps) override {
881 return caps.check_cap("users", RGW_CAP_WRITE);
882 }
883
884 void execute(optional_yield y) override;
885
886 const char* name() const override { return "set_quota_info"; }
887 };
888
889 /**
890 * set quota
891 *
892 * two different ways to set the quota info: as json struct in the message body or via http params.
893 *
894 * as json:
895 *
896 * PUT /admin/user?uid=<uid>[&quota-type=<type>]
897 *
898 * whereas quota-type is optional and is either user, or bucket
899 *
900 * if quota-type is not specified then we expect to get a structure that contains both quotas,
901 * otherwise we'll only get the relevant configuration.
902 *
903 * E.g., if quota type not specified:
904 * {
905 * "user_quota" : {
906 * "max_size_kb" : 4096,
907 * "max_objects" : -1,
908 * "enabled" : false
909 * },
910 * "bucket_quota" : {
911 * "max_size_kb" : 1024,
912 * "max_objects" : -1,
913 * "enabled" : true
914 * }
915 * }
916 *
917 *
918 * or if quota type is specified:
919 * {
920 * "max_size_kb" : 4096,
921 * "max_objects" : -1,
922 * "enabled" : false
923 * }
924 *
925 * Another option is not to pass any body and set the following http params:
926 *
927 *
928 * max-size-kb=<size>
929 * max-objects=<max objects>
930 * enabled[={true,false}]
931 *
932 * all params are optionals and default to the current settings. With this type of configuration the
933 * quota-type param is mandatory.
934 *
935 */
936
937 void RGWOp_Quota_Set::execute(optional_yield y)
938 {
939 RGWUserAdminOpState op_state;
940
941 std::string uid_str;
942 std::string quota_type;
943
944 RESTArgs::get_string(s, "uid", uid_str, &uid_str);
945 RESTArgs::get_string(s, "quota-type", quota_type, &quota_type);
946
947 if (uid_str.empty()) {
948 op_ret = -EINVAL;
949 return;
950 }
951
952 rgw_user uid(uid_str);
953
954 bool set_all = quota_type.empty();
955 bool set_bucket = set_all || (quota_type == "bucket");
956 bool set_user = set_all || (quota_type == "user");
957
958 if (!(set_all || set_bucket || set_user)) {
959 ldout(store->ctx(), 20) << "invalid quota type" << dendl;
960 op_ret = -EINVAL;
961 return;
962 }
963
964 bool use_http_params;
965
966 if (s->content_length > 0) {
967 use_http_params = false;
968 } else {
969 const char *encoding = s->info.env->get("HTTP_TRANSFER_ENCODING");
970 use_http_params = (!encoding || strcmp(encoding, "chunked") != 0);
971 }
972
973 if (use_http_params && set_all) {
974 ldout(store->ctx(), 20) << "quota type was not specified, can't set all quotas via http headers" << dendl;
975 op_ret = -EINVAL;
976 return;
977 }
978
979 op_state.set_user_id(uid);
980
981 RGWUser user;
982 op_ret = user.init(store, op_state, y);
983 if (op_ret < 0) {
984 ldout(store->ctx(), 20) << "failed initializing user info: " << op_ret << dendl;
985 return;
986 }
987
988 if (!op_state.has_existing_user()) {
989 op_ret = -ERR_NO_SUCH_USER;
990 return;
991 }
992
993 #define QUOTA_INPUT_MAX_LEN 1024
994 if (set_all) {
995 UserQuotas quotas;
996
997 if ((op_ret = rgw_rest_get_json_input(store->ctx(), s, quotas, QUOTA_INPUT_MAX_LEN, NULL)) < 0) {
998 ldout(store->ctx(), 20) << "failed to retrieve input" << dendl;
999 return;
1000 }
1001
1002 op_state.set_user_quota(quotas.user_quota);
1003 op_state.set_bucket_quota(quotas.bucket_quota);
1004 } else {
1005 RGWQuotaInfo quota;
1006
1007 if (!use_http_params) {
1008 bool empty;
1009 op_ret = rgw_rest_get_json_input(store->ctx(), s, quota, QUOTA_INPUT_MAX_LEN, &empty);
1010 if (op_ret < 0) {
1011 ldout(store->ctx(), 20) << "failed to retrieve input" << dendl;
1012 if (!empty)
1013 return;
1014
1015 /* was probably chunked input, but no content provided, configure via http params */
1016 use_http_params = true;
1017 }
1018 }
1019
1020 if (use_http_params) {
1021 RGWUserInfo info;
1022 string err_msg;
1023 op_ret = user.info(info, &err_msg);
1024 if (op_ret < 0) {
1025 ldout(store->ctx(), 20) << "failed to get user info: " << op_ret << dendl;
1026 return;
1027 }
1028 RGWQuotaInfo *old_quota;
1029 if (set_user) {
1030 old_quota = &info.user_quota;
1031 } else {
1032 old_quota = &info.bucket_quota;
1033 }
1034
1035 RESTArgs::get_int64(s, "max-objects", old_quota->max_objects, &quota.max_objects);
1036 RESTArgs::get_int64(s, "max-size", old_quota->max_size, &quota.max_size);
1037 int64_t max_size_kb;
1038 bool has_max_size_kb = false;
1039 RESTArgs::get_int64(s, "max-size-kb", 0, &max_size_kb, &has_max_size_kb);
1040 if (has_max_size_kb) {
1041 quota.max_size = max_size_kb * 1024;
1042 }
1043 RESTArgs::get_bool(s, "enabled", old_quota->enabled, &quota.enabled);
1044 }
1045
1046 if (set_user) {
1047 op_state.set_user_quota(quota);
1048 } else {
1049 op_state.set_bucket_quota(quota);
1050 }
1051 }
1052
1053 string err;
1054 op_ret = user.modify(op_state, y, &err);
1055 if (op_ret < 0) {
1056 ldout(store->ctx(), 20) << "failed updating user info: " << op_ret << ": " << err << dendl;
1057 return;
1058 }
1059 }
1060
1061 RGWOp *RGWHandler_User::op_get()
1062 {
1063 if (s->info.args.sub_resource_exists("quota"))
1064 return new RGWOp_Quota_Info;
1065
1066 if (s->info.args.sub_resource_exists("list"))
1067 return new RGWOp_User_List;
1068
1069 return new RGWOp_User_Info;
1070 }
1071
1072 RGWOp *RGWHandler_User::op_put()
1073 {
1074 if (s->info.args.sub_resource_exists("subuser"))
1075 return new RGWOp_Subuser_Create;
1076
1077 if (s->info.args.sub_resource_exists("key"))
1078 return new RGWOp_Key_Create;
1079
1080 if (s->info.args.sub_resource_exists("caps"))
1081 return new RGWOp_Caps_Add;
1082
1083 if (s->info.args.sub_resource_exists("quota"))
1084 return new RGWOp_Quota_Set;
1085
1086 return new RGWOp_User_Create;
1087 }
1088
1089 RGWOp *RGWHandler_User::op_post()
1090 {
1091 if (s->info.args.sub_resource_exists("subuser"))
1092 return new RGWOp_Subuser_Modify;
1093
1094 return new RGWOp_User_Modify;
1095 }
1096
1097 RGWOp *RGWHandler_User::op_delete()
1098 {
1099 if (s->info.args.sub_resource_exists("subuser"))
1100 return new RGWOp_Subuser_Remove;
1101
1102 if (s->info.args.sub_resource_exists("key"))
1103 return new RGWOp_Key_Remove;
1104
1105 if (s->info.args.sub_resource_exists("caps"))
1106 return new RGWOp_Caps_Remove;
1107
1108 return new RGWOp_User_Remove;
1109 }
1110