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