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