]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_rest_user.cc
import ceph quincy 17.2.6
[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"
20effc67 9#include "rgw_sal.h"
7c673cae
FG
10
11#include "include/str_list.h"
11fdf7f2 12#include "include/ceph_assert.h"
7c673cae 13
9f95a23c
TL
14#include "services/svc_zone.h"
15#include "services/svc_sys_obj.h"
16#include "rgw_zone.h"
17
7c673cae
FG
18#define dout_subsys ceph_subsys_rgw
19
20effc67
TL
20using namespace std;
21
11fdf7f2
TL
22class RGWOp_User_List : public RGWRESTOp {
23
24public:
25 RGWOp_User_List() {}
26
9f95a23c 27 int check_caps(const RGWUserCaps& caps) override {
11fdf7f2
TL
28 return caps.check_cap("users", RGW_CAP_READ);
29 }
30
f67539c2 31 void execute(optional_yield y) override;
11fdf7f2
TL
32
33 const char* name() const override { return "list_user"; }
34};
35
f67539c2 36void RGWOp_User_List::execute(optional_yield y)
11fdf7f2 37{
20effc67 38 RGWUserAdminOpState op_state(store);
11fdf7f2
TL
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;
b3b6e05e 47 op_ret = RGWUserAdminOp_User::list(this, store, op_state, flusher);
11fdf7f2
TL
48}
49
7c673cae
FG
50class RGWOp_User_Info : public RGWRESTOp {
51
52public:
53 RGWOp_User_Info() {}
54
9f95a23c 55 int check_caps(const RGWUserCaps& caps) override {
7c673cae
FG
56 return caps.check_cap("users", RGW_CAP_READ);
57 }
58
f67539c2 59 void execute(optional_yield y) override;
7c673cae 60
11fdf7f2 61 const char* name() const override { return "get_user_info"; }
7c673cae
FG
62};
63
f67539c2 64void RGWOp_User_Info::execute(optional_yield y)
7c673cae 65{
20effc67 66 RGWUserAdminOpState op_state(store);
7c673cae 67
11fdf7f2 68 std::string uid_str, access_key_str;
7c673cae 69 bool fetch_stats;
3efd9988 70 bool sync_stats;
7c673cae
FG
71
72 RESTArgs::get_string(s, "uid", uid_str, &uid_str);
11fdf7f2 73 RESTArgs::get_string(s, "access-key", access_key_str, &access_key_str);
7c673cae
FG
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
11fdf7f2 78 if (uid_str.empty() && access_key_str.empty()){
f67539c2 79 op_ret=-EINVAL;
7c673cae
FG
80 return;
81 }
82
83 rgw_user uid(uid_str);
84
85 RESTArgs::get_bool(s, "stats", false, &fetch_stats);
86
3efd9988
FG
87 RESTArgs::get_bool(s, "sync", false, &sync_stats);
88
7c673cae 89 op_state.set_user_id(uid);
11fdf7f2 90 op_state.set_access_key(access_key_str);
7c673cae 91 op_state.set_fetch_stats(fetch_stats);
3efd9988 92 op_state.set_sync_stats(sync_stats);
7c673cae 93
b3b6e05e 94 op_ret = RGWUserAdminOp_User::info(s, store, op_state, flusher, y);
7c673cae
FG
95}
96
97class RGWOp_User_Create : public RGWRESTOp {
98
99public:
100 RGWOp_User_Create() {}
101
9f95a23c 102 int check_caps(const RGWUserCaps& caps) override {
7c673cae
FG
103 return caps.check_cap("users", RGW_CAP_WRITE);
104 }
105
f67539c2 106 void execute(optional_yield y) override;
7c673cae 107
11fdf7f2 108 const char* name() const override { return "create_user"; }
7c673cae
FG
109};
110
f67539c2 111void RGWOp_User_Create::execute(optional_yield y)
7c673cae
FG
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;
d2e6a577 120 std::string tenant_name;
11fdf7f2 121 std::string op_mask_str;
9f95a23c
TL
122 std::string default_placement_str;
123 std::string placement_tags_str;
7c673cae
FG
124
125 bool gen_key;
126 bool suspended;
127 bool system;
128 bool exclusive;
129
130 int32_t max_buckets;
f6b5b4d7
TL
131 const int32_t default_max_buckets =
132 s->cct->_conf.get_val<int64_t>("rgw_user_max_buckets");
7c673cae 133
20effc67 134 RGWUserAdminOpState op_state(store);
7c673cae
FG
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);
d2e6a577 145 RESTArgs::get_string(s, "tenant", tenant_name, &tenant_name);
7c673cae
FG
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);
11fdf7f2 151 RESTArgs::get_string(s, "op-mask", op_mask_str, &op_mask_str);
9f95a23c
TL
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);
7c673cae 154
9f95a23c 155 if (!s->user->get_info().system && system) {
b3b6e05e 156 ldpp_dout(this, 0) << "cannot set system flag by non-system user" << dendl;
f67539c2 157 op_ret = -EINVAL;
7c673cae
FG
158 return;
159 }
160
d2e6a577
FG
161 if (!tenant_name.empty()) {
162 uid.tenant = tenant_name;
163 }
164
7c673cae
FG
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
11fdf7f2
TL
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) {
b3b6e05e 177 ldpp_dout(this, 0) << "failed to parse op_mask: " << ret << dendl;
f67539c2 178 op_ret = -EINVAL;
11fdf7f2
TL
179 return;
180 }
181 op_state.set_op_mask(op_mask);
182 }
183
7c673cae
FG
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
9f95a23c
TL
194 if (max_buckets != default_max_buckets) {
195 if (max_buckets < 0) {
196 max_buckets = -1;
197 }
7c673cae 198 op_state.set_max_buckets(max_buckets);
9f95a23c 199 }
7c673cae
FG
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
9f95a23c
TL
212 if (!default_placement_str.empty()) {
213 rgw_placement_rule target_rule;
214 target_rule.from_str(default_placement_str);
20effc67 215 if (!store->get_zone()->get_params().valid_placement(target_rule)) {
b3b6e05e 216 ldpp_dout(this, 0) << "NOTICE: invalid dest placement: " << target_rule.to_str() << dendl;
f67539c2 217 op_ret = -EINVAL;
9f95a23c
TL
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
f67539c2 229 bufferlist data;
b3b6e05e 230 op_ret = store->forward_request_to_master(s, s->user.get(), nullptr, data, nullptr, s->info, y);
f67539c2
TL
231 if (op_ret < 0) {
232 ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret << dendl;
233 return;
9f95a23c 234 }
b3b6e05e 235 op_ret = RGWUserAdminOp_User::create(s, store, op_state, flusher, y);
7c673cae
FG
236}
237
238class RGWOp_User_Modify : public RGWRESTOp {
239
240public:
241 RGWOp_User_Modify() {}
242
9f95a23c 243 int check_caps(const RGWUserCaps& caps) override {
7c673cae
FG
244 return caps.check_cap("users", RGW_CAP_WRITE);
245 }
246
f67539c2 247 void execute(optional_yield y) override;
7c673cae 248
11fdf7f2 249 const char* name() const override { return "modify_user"; }
7c673cae
FG
250};
251
f67539c2 252void RGWOp_User_Modify::execute(optional_yield y)
7c673cae
FG
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;
11fdf7f2 260 std::string op_mask_str;
9f95a23c
TL
261 std::string default_placement_str;
262 std::string placement_tags_str;
7c673cae
FG
263
264 bool gen_key;
265 bool suspended;
266 bool system;
28e407b8 267 bool email_set;
94b18763 268 bool quota_set;
7c673cae
FG
269 int32_t max_buckets;
270
20effc67 271 RGWUserAdminOpState op_state(store);
7c673cae
FG
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);
28e407b8 277 RESTArgs::get_string(s, "email", email, &email, &email_set);
7c673cae
FG
278 RESTArgs::get_string(s, "access-key", access_key, &access_key);
279 RESTArgs::get_string(s, "secret-key", secret_key, &secret_key);
7c673cae
FG
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) {
b3b6e05e 291 ldpp_dout(this, 0) << "cannot set system flag by non-system user" << dendl;
f67539c2 292 op_ret = -EINVAL;
7c673cae
FG
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_access_key(access_key);
303 op_state.set_secret_key(secret_key);
304
9f95a23c
TL
305 if (quota_set) {
306 if (max_buckets < 0 ) {
307 max_buckets = -1;
308 }
7c673cae 309 op_state.set_max_buckets(max_buckets);
9f95a23c 310 }
7c673cae
FG
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
9f95a23c
TL
324 if (!op_mask_str.empty()) {
325 uint32_t op_mask;
326 if (rgw_parse_op_type_list(op_mask_str, &op_mask) < 0) {
b3b6e05e 327 ldpp_dout(this, 0) << "failed to parse op_mask" << dendl;
f67539c2 328 op_ret = -EINVAL;
9f95a23c
TL
329 return;
330 }
331 op_state.set_op_mask(op_mask);
332 }
333
7c673cae
FG
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
11fdf7f2
TL
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) {
b3b6e05e 344 ldpp_dout(this, 0) << "failed to parse op_mask: " << ret << dendl;
f67539c2 345 op_ret = -EINVAL;
11fdf7f2
TL
346 return;
347 }
348 op_state.set_op_mask(op_mask);
349 }
350
9f95a23c
TL
351 if (!default_placement_str.empty()) {
352 rgw_placement_rule target_rule;
353 target_rule.from_str(default_placement_str);
20effc67 354 if (!store->get_zone()->get_params().valid_placement(target_rule)) {
b3b6e05e 355 ldpp_dout(this, 0) << "NOTICE: invalid dest placement: " << target_rule.to_str() << dendl;
f67539c2 356 op_ret = -EINVAL;
9f95a23c
TL
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
f67539c2 368 bufferlist data;
b3b6e05e 369 op_ret = store->forward_request_to_master(s, s->user.get(), nullptr, data, nullptr, s->info, y);
f67539c2
TL
370 if (op_ret < 0) {
371 ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret << dendl;
372 return;
9f95a23c 373 }
b3b6e05e 374 op_ret = RGWUserAdminOp_User::modify(s, store, op_state, flusher, y);
7c673cae
FG
375}
376
377class RGWOp_User_Remove : public RGWRESTOp {
378
379public:
380 RGWOp_User_Remove() {}
381
9f95a23c 382 int check_caps(const RGWUserCaps& caps) override {
7c673cae
FG
383 return caps.check_cap("users", RGW_CAP_WRITE);
384 }
385
f67539c2 386 void execute(optional_yield y) override;
7c673cae 387
11fdf7f2 388 const char* name() const override { return "remove_user"; }
7c673cae
FG
389};
390
f67539c2 391void RGWOp_User_Remove::execute(optional_yield y)
7c673cae
FG
392{
393 std::string uid_str;
394 bool purge_data;
395
20effc67 396 RGWUserAdminOpState op_state(store);
7c673cae
FG
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
f67539c2 409 bufferlist data;
b3b6e05e 410 op_ret = store->forward_request_to_master(s, s->user.get(), nullptr, data, nullptr, s->info, y);
f67539c2
TL
411 if (op_ret < 0) {
412 ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret << dendl;
413 return;
9f95a23c 414 }
b3b6e05e 415 op_ret = RGWUserAdminOp_User::remove(s, store, op_state, flusher, s->yield);
7c673cae
FG
416}
417
418class RGWOp_Subuser_Create : public RGWRESTOp {
419
420public:
421 RGWOp_Subuser_Create() {}
422
9f95a23c 423 int check_caps(const RGWUserCaps& caps) override {
7c673cae
FG
424 return caps.check_cap("users", RGW_CAP_WRITE);
425 }
426
f67539c2 427 void execute(optional_yield y) override;
7c673cae 428
11fdf7f2 429 const char* name() const override { return "create_subuser"; }
7c673cae
FG
430};
431
f67539c2 432void RGWOp_Subuser_Create::execute(optional_yield y)
7c673cae
FG
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
20effc67 448 RGWUserAdminOpState op_state(store);
7c673cae
FG
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);
7c673cae
FG
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
f67539c2 484 bufferlist data;
b3b6e05e 485 op_ret = store->forward_request_to_master(s, s->user.get(), nullptr, data, nullptr, s->info, y);
f67539c2
TL
486 if (op_ret < 0) {
487 ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret << dendl;
488 return;
9f95a23c 489 }
b3b6e05e 490 op_ret = RGWUserAdminOp_Subuser::create(s, store, op_state, flusher, y);
7c673cae
FG
491}
492
493class RGWOp_Subuser_Modify : public RGWRESTOp {
494
495public:
496 RGWOp_Subuser_Modify() {}
497
9f95a23c 498 int check_caps(const RGWUserCaps& caps) override {
7c673cae
FG
499 return caps.check_cap("users", RGW_CAP_WRITE);
500 }
501
f67539c2 502 void execute(optional_yield y) override;
7c673cae 503
11fdf7f2 504 const char* name() const override { return "modify_subuser"; }
7c673cae
FG
505};
506
f67539c2 507void RGWOp_Subuser_Modify::execute(optional_yield y)
7c673cae
FG
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
20effc67 515 RGWUserAdminOpState op_state(store);
7c673cae
FG
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);
b32b8144
FG
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();
7c673cae
FG
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
f67539c2 551 bufferlist data;
b3b6e05e 552 op_ret = store->forward_request_to_master(s, s->user.get(), nullptr, data, nullptr, s->info, y);
f67539c2
TL
553 if (op_ret < 0) {
554 ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret << dendl;
555 return;
9f95a23c 556 }
b3b6e05e 557 op_ret = RGWUserAdminOp_Subuser::modify(s, store, op_state, flusher, y);
7c673cae
FG
558}
559
560class RGWOp_Subuser_Remove : public RGWRESTOp {
561
562public:
563 RGWOp_Subuser_Remove() {}
564
9f95a23c 565 int check_caps(const RGWUserCaps& caps) override {
7c673cae
FG
566 return caps.check_cap("users", RGW_CAP_WRITE);
567 }
568
f67539c2 569 void execute(optional_yield y) override;
7c673cae 570
11fdf7f2 571 const char* name() const override { return "remove_subuser"; }
7c673cae
FG
572};
573
f67539c2 574void RGWOp_Subuser_Remove::execute(optional_yield y)
7c673cae
FG
575{
576 std::string uid_str;
577 std::string subuser;
578 bool purge_keys;
579
20effc67 580 RGWUserAdminOpState op_state(store);
7c673cae
FG
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
f67539c2 594 bufferlist data;
b3b6e05e 595 op_ret = store->forward_request_to_master(s, s->user.get(), nullptr, data, nullptr, s->info, y);
f67539c2
TL
596 if (op_ret < 0) {
597 ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret << dendl;
598 return;
9f95a23c 599 }
b3b6e05e 600 op_ret = RGWUserAdminOp_Subuser::remove(s, store, op_state, flusher, y);
7c673cae
FG
601}
602
603class RGWOp_Key_Create : public RGWRESTOp {
604
605public:
606 RGWOp_Key_Create() {}
607
9f95a23c 608 int check_caps(const RGWUserCaps& caps) override {
7c673cae
FG
609 return caps.check_cap("users", RGW_CAP_WRITE);
610 }
611
f67539c2 612 void execute(optional_yield y) override;
7c673cae 613
11fdf7f2 614 const char* name() const override { return "create_access_key"; }
7c673cae
FG
615};
616
f67539c2 617void RGWOp_Key_Create::execute(optional_yield y)
7c673cae
FG
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
20effc67 627 RGWUserAdminOpState op_state(store);
7c673cae
FG
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
b3b6e05e 656 op_ret = RGWUserAdminOp_Key::create(s, store, op_state, flusher, y);
7c673cae
FG
657}
658
659class RGWOp_Key_Remove : public RGWRESTOp {
660
661public:
662 RGWOp_Key_Remove() {}
663
9f95a23c 664 int check_caps(const RGWUserCaps& caps) override {
7c673cae
FG
665 return caps.check_cap("users", RGW_CAP_WRITE);
666 }
667
f67539c2 668 void execute(optional_yield y) override;
7c673cae 669
11fdf7f2 670 const char* name() const override { return "remove_access_key"; }
7c673cae
FG
671};
672
f67539c2 673void RGWOp_Key_Remove::execute(optional_yield y)
7c673cae
FG
674{
675 std::string uid_str;
676 std::string subuser;
677 std::string access_key;
678 std::string key_type_str;
679
20effc67 680 RGWUserAdminOpState op_state(store);
7c673cae
FG
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
b3b6e05e 703 op_ret = RGWUserAdminOp_Key::remove(s, store, op_state, flusher, y);
7c673cae
FG
704}
705
706class RGWOp_Caps_Add : public RGWRESTOp {
707
708public:
709 RGWOp_Caps_Add() {}
710
9f95a23c 711 int check_caps(const RGWUserCaps& caps) override {
7c673cae
FG
712 return caps.check_cap("users", RGW_CAP_WRITE);
713 }
714
f67539c2 715 void execute(optional_yield y) override;
7c673cae 716
11fdf7f2 717 const char* name() const override { return "add_user_caps"; }
7c673cae
FG
718};
719
f67539c2 720void RGWOp_Caps_Add::execute(optional_yield y)
7c673cae
FG
721{
722 std::string uid_str;
723 std::string caps;
724
20effc67 725 RGWUserAdminOpState op_state(store);
7c673cae
FG
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
f67539c2 735 bufferlist data;
b3b6e05e 736 op_ret = store->forward_request_to_master(s, s->user.get(), nullptr, data, nullptr, s->info, y);
f67539c2
TL
737 if (op_ret < 0) {
738 ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret << dendl;
739 return;
9f95a23c 740 }
b3b6e05e 741 op_ret = RGWUserAdminOp_Caps::add(s, store, op_state, flusher, y);
7c673cae
FG
742}
743
744class RGWOp_Caps_Remove : public RGWRESTOp {
745
746public:
747 RGWOp_Caps_Remove() {}
748
9f95a23c 749 int check_caps(const RGWUserCaps& caps) override {
7c673cae
FG
750 return caps.check_cap("users", RGW_CAP_WRITE);
751 }
752
f67539c2 753 void execute(optional_yield y) override;
7c673cae 754
11fdf7f2 755 const char* name() const override { return "remove_user_caps"; }
7c673cae
FG
756};
757
f67539c2 758void RGWOp_Caps_Remove::execute(optional_yield y)
7c673cae
FG
759{
760 std::string uid_str;
761 std::string caps;
762
20effc67 763 RGWUserAdminOpState op_state(store);
7c673cae
FG
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
f67539c2 773 bufferlist data;
b3b6e05e 774 op_ret = store->forward_request_to_master(s, s->user.get(), nullptr, data, nullptr, s->info, y);
f67539c2
TL
775 if (op_ret < 0) {
776 ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret << dendl;
777 return;
9f95a23c 778 }
b3b6e05e 779 op_ret = RGWUserAdminOp_Caps::remove(s, store, op_state, flusher, y);
7c673cae
FG
780}
781
782struct UserQuotas {
783 RGWQuotaInfo bucket_quota;
784 RGWQuotaInfo user_quota;
785
786 UserQuotas() {}
787
f67539c2 788 explicit UserQuotas(RGWUserInfo& info) : bucket_quota(info.bucket_quota),
7c673cae
FG
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
801class RGWOp_Quota_Info : public RGWRESTOp {
802
803public:
804 RGWOp_Quota_Info() {}
805
9f95a23c 806 int check_caps(const RGWUserCaps& caps) override {
7c673cae
FG
807 return caps.check_cap("users", RGW_CAP_READ);
808 }
809
f67539c2 810 void execute(optional_yield y) override;
7c673cae 811
11fdf7f2 812 const char* name() const override { return "get_quota_info"; }
7c673cae
FG
813};
814
815
f67539c2 816void RGWOp_Quota_Info::execute(optional_yield y)
7c673cae 817{
20effc67 818 RGWUserAdminOpState op_state(store);
7c673cae
FG
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()) {
f67539c2 827 op_ret = -EINVAL;
7c673cae
FG
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)) {
f67539c2 838 op_ret = -EINVAL;
7c673cae
FG
839 return;
840 }
841
842 op_state.set_user_id(uid);
843
844 RGWUser user;
b3b6e05e 845 op_ret = user.init(s, store, op_state, y);
f67539c2 846 if (op_ret < 0)
7c673cae
FG
847 return;
848
224ce89b 849 if (!op_state.has_existing_user()) {
f67539c2 850 op_ret = -ERR_NO_SUCH_USER;
224ce89b
WB
851 return;
852 }
853
7c673cae
FG
854 RGWUserInfo info;
855 string err_msg;
f67539c2
TL
856 op_ret = user.info(info, &err_msg);
857 if (op_ret < 0)
7c673cae
FG
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
873class RGWOp_Quota_Set : public RGWRESTOp {
874
875public:
876 RGWOp_Quota_Set() {}
877
9f95a23c 878 int check_caps(const RGWUserCaps& caps) override {
7c673cae
FG
879 return caps.check_cap("users", RGW_CAP_WRITE);
880 }
881
f67539c2 882 void execute(optional_yield y) override;
7c673cae 883
11fdf7f2 884 const char* name() const override { return "set_quota_info"; }
7c673cae
FG
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
f67539c2 935void RGWOp_Quota_Set::execute(optional_yield y)
7c673cae 936{
20effc67 937 RGWUserAdminOpState op_state(store);
7c673cae
FG
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()) {
f67539c2 946 op_ret = -EINVAL;
7c673cae
FG
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)) {
b3b6e05e 957 ldpp_dout(this, 20) << "invalid quota type" << dendl;
f67539c2 958 op_ret = -EINVAL;
7c673cae
FG
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) {
b3b6e05e 972 ldpp_dout(this, 20) << "quota type was not specified, can't set all quotas via http headers" << dendl;
f67539c2 973 op_ret = -EINVAL;
7c673cae
FG
974 return;
975 }
976
977 op_state.set_user_id(uid);
978
979 RGWUser user;
b3b6e05e 980 op_ret = user.init(s, store, op_state, y);
f67539c2 981 if (op_ret < 0) {
b3b6e05e 982 ldpp_dout(this, 20) << "failed initializing user info: " << op_ret << dendl;
7c673cae
FG
983 return;
984 }
985
224ce89b 986 if (!op_state.has_existing_user()) {
f67539c2 987 op_ret = -ERR_NO_SUCH_USER;
224ce89b
WB
988 return;
989 }
990
7c673cae
FG
991#define QUOTA_INPUT_MAX_LEN 1024
992 if (set_all) {
993 UserQuotas quotas;
994
20effc67 995 if ((op_ret = get_json_input(store->ctx(), s, quotas, QUOTA_INPUT_MAX_LEN, NULL)) < 0) {
b3b6e05e 996 ldpp_dout(this, 20) << "failed to retrieve input" << dendl;
7c673cae
FG
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;
20effc67 1007 op_ret = get_json_input(store->ctx(), s, quota, QUOTA_INPUT_MAX_LEN, &empty);
f67539c2 1008 if (op_ret < 0) {
b3b6e05e 1009 ldpp_dout(this, 20) << "failed to retrieve input" << dendl;
7c673cae
FG
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;
f67539c2
TL
1021 op_ret = user.info(info, &err_msg);
1022 if (op_ret < 0) {
b3b6e05e 1023 ldpp_dout(this, 20) << "failed to get user info: " << op_ret << dendl;
7c673cae
FG
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
7c673cae 1033 RESTArgs::get_int64(s, "max-objects", old_quota->max_objects, &quota.max_objects);
f64942e4
AA
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 }
7c673cae
FG
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;
b3b6e05e 1052 op_ret = user.modify(s, op_state, y, &err);
f67539c2 1053 if (op_ret < 0) {
b3b6e05e 1054 ldpp_dout(this, 20) << "failed updating user info: " << op_ret << ": " << err << dendl;
7c673cae
FG
1055 return;
1056 }
1057}
1058
1059RGWOp *RGWHandler_User::op_get()
1060{
1061 if (s->info.args.sub_resource_exists("quota"))
1062 return new RGWOp_Quota_Info;
1063
11fdf7f2
TL
1064 if (s->info.args.sub_resource_exists("list"))
1065 return new RGWOp_User_List;
1066
7c673cae
FG
1067 return new RGWOp_User_Info;
1068}
1069
1070RGWOp *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
1087RGWOp *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
1095RGWOp *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