]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/test_rgw_admin_meta.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / test / test_rgw_admin_meta.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14 #include <iostream>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <errno.h>
19 #include <sys/wait.h>
20 #include <unistd.h>
21 #include <fstream>
22 #include <map>
23 #include <list>
24 extern "C"{
25 #include <curl/curl.h>
26 }
27 #include "common/ceph_crypto.h"
28 #include "include/str_list.h"
29 #include "common/ceph_json.h"
30 #include "common/code_environment.h"
31 #include "common/ceph_argparse.h"
32 #include "common/Finisher.h"
33 #include "global/global_init.h"
34 #include "rgw_common.h"
35 #include "rgw_rados.h"
36 #include <gtest/gtest.h>
37
38 using namespace std;
39
40 #define CURL_VERBOSE 0
41 #define HTTP_RESPONSE_STR "RespCode"
42 #define CEPH_CRYPTO_HMACSHA1_DIGESTSIZE 20
43 #define RGW_ADMIN_RESP_PATH "/tmp/.test_rgw_admin_resp"
44 #define CEPH_UID "ceph"
45
46 static string uid = CEPH_UID;
47 static string display_name = "CEPH";
48 static string meta_caps = "metadata";
49
50 extern "C" int ceph_armor(char *dst, const char *dst_end,
51 const char *src, const char *end);
52 static void print_usage(char *exec){
53 cout << "Usage: " << exec << " <Options>\n";
54 cout << "Options:\n"
55 "-g <gw-ip> - The ip address of the gateway\n"
56 "-p <gw-port> - The port number of the gateway\n"
57 "-c <ceph.conf> - Absolute path of ceph config file\n"
58 "-rgw-admin <path/to/radosgw-admin> - radosgw-admin absolute path\n";
59 }
60
61 namespace admin_meta {
62 class test_helper {
63 private:
64 string host;
65 string port;
66 string creds;
67 string rgw_admin_path;
68 string conf_path;
69 CURL *curl_inst;
70 map<string, string> response;
71 list<string> extra_hdrs;
72 string *resp_data;
73 unsigned resp_code;
74 public:
75 test_helper() : curl_inst(0), resp_data(NULL), resp_code(0) {
76 curl_global_init(CURL_GLOBAL_ALL);
77 }
78 ~test_helper(){
79 curl_global_cleanup();
80 }
81 int send_request(string method, string uri,
82 size_t (*function)(void *,size_t,size_t,void *) = 0,
83 void *ud = 0, size_t length = 0);
84 int extract_input(int argc, char *argv[]);
85 string& get_response(string hdr){
86 return response[hdr];
87 }
88 void set_extra_header(string hdr){
89 extra_hdrs.push_back(hdr);
90 }
91 void set_response(char *val);
92 void set_response_data(char *data, size_t len){
93 if(resp_data) delete resp_data;
94 resp_data = new string(data, len);
95 }
96 string& get_rgw_admin_path() {
97 return rgw_admin_path;
98 }
99 string& get_ceph_conf_path() {
100 return conf_path;
101 }
102 void set_creds(string& c) {
103 creds = c;
104 }
105 const string *get_response_data(){return resp_data;}
106 unsigned get_resp_code(){return resp_code;}
107 };
108
109 int test_helper::extract_input(int argc, char *argv[]){
110 #define ERR_CHECK_NEXT_PARAM(o) \
111 if(((int)loop + 1) >= argc)return -1; \
112 else o = argv[loop+1];
113
114 for(unsigned loop = 1;loop < (unsigned)argc; loop += 2){
115 if(strcmp(argv[loop], "-g") == 0){
116 ERR_CHECK_NEXT_PARAM(host);
117 }else if(strcmp(argv[loop],"-p") == 0){
118 ERR_CHECK_NEXT_PARAM(port);
119 }else if(strcmp(argv[loop], "-c") == 0){
120 ERR_CHECK_NEXT_PARAM(conf_path);
121 }else if(strcmp(argv[loop], "-rgw-admin") == 0){
122 ERR_CHECK_NEXT_PARAM(rgw_admin_path);
123 }else return -1;
124 }
125 if(host.empty() || rgw_admin_path.empty())
126 return -1;
127 return 0;
128 }
129
130 void test_helper::set_response(char *r){
131 string sr(r), h, v;
132 size_t off = sr.find(": ");
133 if(off != string::npos){
134 h.assign(sr, 0, off);
135 v.assign(sr, off + 2, sr.find("\r\n") - (off+2));
136 }else{
137 /*Could be the status code*/
138 if(sr.find("HTTP/") != string::npos){
139 h.assign(HTTP_RESPONSE_STR);
140 off = sr.find(" ");
141 v.assign(sr, off + 1, sr.find("\r\n") - (off + 1));
142 resp_code = atoi((v.substr(0, 3)).c_str());
143 }
144 }
145 response[h] = v;
146 }
147
148 size_t write_header(void *ptr, size_t size, size_t nmemb, void *ud){
149 test_helper *h = static_cast<test_helper *>(ud);
150 h->set_response((char *)ptr);
151 return size*nmemb;
152 }
153
154 size_t write_data(void *ptr, size_t size, size_t nmemb, void *ud){
155 test_helper *h = static_cast<test_helper *>(ud);
156 h->set_response_data((char *)ptr, size*nmemb);
157 return size*nmemb;
158 }
159
160 static inline void buf_to_hex(const unsigned char *buf, int len, char *str)
161 {
162 int i;
163 str[0] = '\0';
164 for (i = 0; i < len; i++) {
165 sprintf(&str[i*2], "%02x", (int)buf[i]);
166 }
167 }
168
169 static void calc_hmac_sha1(const char *key, int key_len,
170 const char *msg, int msg_len, char *dest)
171 /* destination should be CEPH_CRYPTO_HMACSHA1_DIGESTSIZE bytes long */
172 {
173 ceph::crypto::HMACSHA1 hmac((const unsigned char *)key, key_len);
174 hmac.Update((const unsigned char *)msg, msg_len);
175 hmac.Final((unsigned char *)dest);
176
177 char hex_str[(CEPH_CRYPTO_HMACSHA1_DIGESTSIZE * 2) + 1];
178 admin_meta::buf_to_hex((unsigned char *)dest, CEPH_CRYPTO_HMACSHA1_DIGESTSIZE, hex_str);
179 }
180
181 static int get_s3_auth(const string &method, string creds, const string &date, string res, string& out){
182 string aid, secret, auth_hdr;
183 string tmp_res;
184 size_t off = creds.find(":");
185 out = "";
186 if(off != string::npos){
187 aid.assign(creds, 0, off);
188 secret.assign(creds, off + 1, string::npos);
189
190 /*sprintf(auth_hdr, "%s\n\n\n%s\n%s", req_type, date, res);*/
191 char hmac_sha1[CEPH_CRYPTO_HMACSHA1_DIGESTSIZE];
192 char b64[65]; /* 64 is really enough */
193 size_t off = res.find("?");
194 if(off == string::npos)
195 tmp_res = res;
196 else
197 tmp_res.assign(res, 0, off);
198 auth_hdr.append(method + string("\n\n\n") + date + string("\n") + tmp_res);
199 admin_meta::calc_hmac_sha1(secret.c_str(), secret.length(),
200 auth_hdr.c_str(), auth_hdr.length(), hmac_sha1);
201 int ret = ceph_armor(b64, b64 + 64, hmac_sha1,
202 hmac_sha1 + CEPH_CRYPTO_HMACSHA1_DIGESTSIZE);
203 if (ret < 0) {
204 cout << "ceph_armor failed\n";
205 return -1;
206 }
207 b64[ret] = 0;
208 out.append(aid + string(":") + b64);
209 }else return -1;
210 return 0;
211 }
212
213 void get_date(string& d){
214 struct timeval tv;
215 char date[64];
216 struct tm tm;
217 char *days[] = {(char *)"Sun", (char *)"Mon", (char *)"Tue",
218 (char *)"Wed", (char *)"Thu", (char *)"Fri",
219 (char *)"Sat"};
220 char *months[] = {(char *)"Jan", (char *)"Feb", (char *)"Mar",
221 (char *)"Apr", (char *)"May", (char *)"Jun",
222 (char *)"Jul",(char *) "Aug", (char *)"Sep",
223 (char *)"Oct", (char *)"Nov", (char *)"Dec"};
224 gettimeofday(&tv, NULL);
225 gmtime_r(&tv.tv_sec, &tm);
226 sprintf(date, "%s, %d %s %d %d:%d:%d GMT",
227 days[tm.tm_wday],
228 tm.tm_mday, months[tm.tm_mon],
229 tm.tm_year + 1900,
230 tm.tm_hour, tm.tm_min, 0 /*tm.tm_sec*/);
231 d = date;
232 }
233
234 int test_helper::send_request(string method, string res,
235 size_t (*read_function)( void *,size_t,size_t,void *),
236 void *ud,
237 size_t length){
238 string url;
239 string auth, date;
240 url.append(string("http://") + host);
241 if(port.length() > 0)url.append(string(":") + port);
242 url.append(res);
243 curl_inst = curl_easy_init();
244 if(curl_inst){
245 curl_easy_setopt(curl_inst, CURLOPT_URL, url.c_str());
246 curl_easy_setopt(curl_inst, CURLOPT_CUSTOMREQUEST, method.c_str());
247 curl_easy_setopt(curl_inst, CURLOPT_VERBOSE, CURL_VERBOSE);
248 curl_easy_setopt(curl_inst, CURLOPT_HEADERFUNCTION, admin_meta::write_header);
249 curl_easy_setopt(curl_inst, CURLOPT_WRITEHEADER, (void *)this);
250 curl_easy_setopt(curl_inst, CURLOPT_WRITEFUNCTION, admin_meta::write_data);
251 curl_easy_setopt(curl_inst, CURLOPT_WRITEDATA, (void *)this);
252 if(read_function){
253 curl_easy_setopt(curl_inst, CURLOPT_READFUNCTION, read_function);
254 curl_easy_setopt(curl_inst, CURLOPT_READDATA, (void *)ud);
255 curl_easy_setopt(curl_inst, CURLOPT_UPLOAD, 1L);
256 curl_easy_setopt(curl_inst, CURLOPT_INFILESIZE_LARGE, (curl_off_t)length);
257 }
258
259 get_date(date);
260 string http_date;
261 http_date.append(string("Date: ") + date);
262
263 string s3auth;
264 if (admin_meta::get_s3_auth(method, creds, date, res, s3auth) < 0)
265 return -1;
266 auth.append(string("Authorization: AWS ") + s3auth);
267
268 struct curl_slist *slist = NULL;
269 slist = curl_slist_append(slist, auth.c_str());
270 slist = curl_slist_append(slist, http_date.c_str());
271 for(list<string>::iterator it = extra_hdrs.begin();
272 it != extra_hdrs.end(); ++it){
273 slist = curl_slist_append(slist, (*it).c_str());
274 }
275 if(read_function)
276 curl_slist_append(slist, "Expect:");
277 curl_easy_setopt(curl_inst, CURLOPT_HTTPHEADER, slist);
278
279 response.erase(response.begin(), response.end());
280 extra_hdrs.erase(extra_hdrs.begin(), extra_hdrs.end());
281 CURLcode res = curl_easy_perform(curl_inst);
282 if(res != CURLE_OK){
283 cout << "Curl perform failed for " << url << ", res: " <<
284 curl_easy_strerror(res) << "\n";
285 return -1;
286 }
287 curl_slist_free_all(slist);
288 }
289 curl_easy_cleanup(curl_inst);
290 return 0;
291 }
292 };
293
294 admin_meta::test_helper *g_test;
295 Finisher *finisher;
296
297 int run_rgw_admin(string& cmd, string& resp) {
298 pid_t pid;
299 pid = fork();
300 if (pid == 0) {
301 /* child */
302 list<string> l;
303 get_str_list(cmd, " \t", l);
304 char *argv[l.size()];
305 unsigned loop = 1;
306
307 argv[0] = (char *)"radosgw-admin";
308 for (list<string>::iterator it = l.begin();
309 it != l.end(); ++it) {
310 argv[loop++] = (char *)(*it).c_str();
311 }
312 argv[loop] = NULL;
313 if (!freopen(RGW_ADMIN_RESP_PATH, "w+", stdout)) {
314 cout << "Unable to open stdout file" << std::endl;
315 }
316 execv((g_test->get_rgw_admin_path()).c_str(), argv);
317 } else if (pid > 0) {
318 int status;
319 waitpid(pid, &status, 0);
320 if (WIFEXITED(status)) {
321 if(WEXITSTATUS(status) != 0) {
322 cout << "Child exited with status " << WEXITSTATUS(status) << std::endl;
323 return -1;
324 }
325 }
326 ifstream in;
327 struct stat st;
328
329 if (stat(RGW_ADMIN_RESP_PATH, &st) < 0) {
330 cout << "Error stating the admin response file, errno " << errno << std::endl;
331 return -1;
332 } else {
333 char *data = (char *)malloc(st.st_size + 1);
334 in.open(RGW_ADMIN_RESP_PATH);
335 in.read(data, st.st_size);
336 in.close();
337 data[st.st_size] = 0;
338 resp = data;
339 free(data);
340 unlink(RGW_ADMIN_RESP_PATH);
341 /* cout << "radosgw-admin " << cmd << ": " << resp << std::endl;*/
342 }
343 } else
344 return -1;
345 return 0;
346 }
347
348 int get_creds(string& json, string& creds) {
349 JSONParser parser;
350 if(!parser.parse(json.c_str(), json.length())) {
351 cout << "Error parsing create user response" << std::endl;
352 return -1;
353 }
354
355 RGWUserInfo info;
356 decode_json_obj(info, &parser);
357 creds = "";
358 for(map<string, RGWAccessKey>::iterator it = info.access_keys.begin();
359 it != info.access_keys.end(); ++it) {
360 RGWAccessKey _k = it->second;
361 /*cout << "accesskeys [ " << it->first << " ] = " <<
362 "{ " << _k.id << ", " << _k.key << ", " << _k.subuser << "}" << std::endl;*/
363 creds.append(it->first + string(":") + _k.key);
364 break;
365 }
366 return 0;
367 }
368
369 int user_create(string& uid, string& display_name, bool set_creds = true) {
370 stringstream ss;
371 string creds;
372 ss << "-c " << g_test->get_ceph_conf_path() << " user create --uid=" << uid
373 << " --display-name=" << display_name;
374
375 string out;
376 string cmd = ss.str();
377 if(run_rgw_admin(cmd, out) != 0) {
378 cout << "Error creating user" << std::endl;
379 return -1;
380 }
381 get_creds(out, creds);
382 if(set_creds)
383 g_test->set_creds(creds);
384 return 0;
385 }
386
387 int user_info(string& uid, string& display_name, RGWUserInfo& uinfo) {
388 stringstream ss;
389 ss << "-c " << g_test->get_ceph_conf_path() << " user info --uid=" << uid
390 << " --display-name=" << display_name;
391
392 string out;
393 string cmd = ss.str();
394 if(run_rgw_admin(cmd, out) != 0) {
395 cout << "Error reading user information" << std::endl;
396 return -1;
397 }
398 JSONParser parser;
399 if(!parser.parse(out.c_str(), out.length())) {
400 cout << "Error parsing create user response" << std::endl;
401 return -1;
402 }
403 decode_json_obj(uinfo, &parser);
404 return 0;
405 }
406
407 int user_rm(string& uid, string& display_name) {
408 stringstream ss;
409 ss << "-c " << g_test->get_ceph_conf_path() << " user rm --uid=" << uid
410 << " --display-name=" << display_name;
411
412 string out;
413 string cmd = ss.str();
414 if(run_rgw_admin(cmd, out) != 0) {
415 cout << "Error removing user" << std::endl;
416 return -1;
417 }
418 return 0;
419 }
420
421 int meta_caps_add(const char *perm) {
422 stringstream ss;
423
424 ss << "-c " << g_test->get_ceph_conf_path() << " caps add --caps=" <<
425 meta_caps << "=" << perm << " --uid=" << uid;
426 string out;
427 string cmd = ss.str();
428 if(run_rgw_admin(cmd, out) != 0) {
429 cout << "Error creating user" << std::endl;
430 return -1;
431 }
432 return 0;
433 }
434
435 int meta_caps_rm(const char *perm) {
436 stringstream ss;
437
438 ss << "-c " << g_test->get_ceph_conf_path() << " caps rm --caps=" <<
439 meta_caps << "=" << perm << " --uid=" << uid;
440 string out;
441 string cmd = ss.str();
442 if(run_rgw_admin(cmd, out) != 0) {
443 cout << "Error creating user" << std::endl;
444 return -1;
445 }
446 return 0;
447 }
448
449 int compare_access_keys(RGWAccessKey& k1, RGWAccessKey& k2) {
450 if (k1.id.compare(k2.id) != 0)
451 return -1;
452 if (k1.key.compare(k2.key) != 0)
453 return -1;
454 if (k1.subuser.compare(k2.subuser) != 0)
455 return -1;
456
457 return 0;
458 }
459
460 int compare_user_info(RGWUserInfo& i1, RGWUserInfo& i2) {
461 int rv;
462
463 if ((rv = i1.user_id.compare(i2.user_id)) != 0)
464 return rv;
465 if ((rv = i1.display_name.compare(i2.display_name)) != 0)
466 return rv;
467 if ((rv = i1.user_email.compare(i2.user_email)) != 0)
468 return rv;
469 if (i1.access_keys.size() != i2.access_keys.size())
470 return -1;
471 for (map<string, RGWAccessKey>::iterator it = i1.access_keys.begin();
472 it != i1.access_keys.end(); ++it) {
473 RGWAccessKey k1, k2;
474 k1 = it->second;
475 if (i2.access_keys.count(it->first) == 0)
476 return -1;
477 k2 = i2.access_keys[it->first];
478 if (compare_access_keys(k1, k2) != 0)
479 return -1;
480 }
481 if (i1.swift_keys.size() != i2.swift_keys.size())
482 return -1;
483 for (map<string, RGWAccessKey>::iterator it = i1.swift_keys.begin();
484 it != i1.swift_keys.end(); ++it) {
485 RGWAccessKey k1, k2;
486 k1 = it->second;
487 if (i2.swift_keys.count(it->first) == 0)
488 return -1;
489 k2 = i2.swift_keys[it->first];
490 if (compare_access_keys(k1, k2) != 0)
491 return -1;
492 }
493 if (i1.subusers.size() != i2.subusers.size())
494 return -1;
495 for (map<string, RGWSubUser>::iterator it = i1.subusers.begin();
496 it != i1.subusers.end(); ++it) {
497 RGWSubUser k1, k2;
498 k1 = it->second;
499 if (!i2.subusers.count(it->first))
500 return -1;
501 k2 = i2.subusers[it->first];
502 if (k1.name.compare(k2.name) != 0)
503 return -1;
504 if (k1.perm_mask != k2.perm_mask)
505 return -1;
506 }
507 if (i1.suspended != i2.suspended)
508 return -1;
509 if (i1.max_buckets != i2.max_buckets)
510 return -1;
511 uint32_t p1, p2;
512 p1 = p2 = RGW_CAP_ALL;
513 if (i1.caps.check_cap(meta_caps, p1) != 0)
514 return -1;
515 if (i2.caps.check_cap(meta_caps, p2) != 0)
516 return -1;
517 return 0;
518 }
519
520 size_t read_dummy_post(void *ptr, size_t s, size_t n, void *ud) {
521 int dummy = 0;
522 memcpy(ptr, &dummy, sizeof(dummy));
523 return sizeof(dummy);
524 }
525
526
527 int parse_json_resp(JSONParser &parser) {
528 string *resp;
529 resp = (string *)g_test->get_response_data();
530 if(!resp)
531 return -1;
532 if(!parser.parse(resp->c_str(), resp->length())) {
533 cout << "Error parsing create user response" << std::endl;
534 return -1;
535 }
536 return 0;
537 }
538
539 size_t meta_read_json(void *ptr, size_t s, size_t n, void *ud){
540 stringstream *ss = (stringstream *)ud;
541 size_t len = ss->str().length();
542 if(s*n < len){
543 cout << "Cannot copy json data, as len is not enough\n";
544 return 0;
545 }
546 memcpy(ptr, (void *)ss->str().c_str(), len);
547 return len;
548 }
549
550 TEST(TestRGWAdmin, meta_list){
551 JSONParser parser;
552 bool found = false;
553 const char *perm = "*";
554
555 ASSERT_EQ(0, user_create(uid, display_name));
556 ASSERT_EQ(0, meta_caps_add(perm));
557
558 /*Check the sections*/
559 g_test->send_request(string("GET"), string("/admin/metadata/"));
560 EXPECT_EQ(200U, g_test->get_resp_code());
561
562 ASSERT_TRUE(parse_json_resp(parser) == 0);
563 EXPECT_TRUE(parser.is_array());
564
565 vector<string> l;
566 l = parser.get_array_elements();
567 for(vector<string>::iterator it = l.begin();
568 it != l.end(); ++it) {
569 if((*it).compare("\"user\"") == 0) {
570 found = true;
571 break;
572 }
573 }
574 EXPECT_TRUE(found);
575
576 /*Check with a wrong section*/
577 g_test->send_request(string("GET"), string("/admin/metadata/users"));
578 EXPECT_EQ(404U, g_test->get_resp_code());
579
580 /*Check the list of keys*/
581 g_test->send_request(string("GET"), string("/admin/metadata/user"));
582 EXPECT_EQ(200U, g_test->get_resp_code());
583
584 ASSERT_TRUE(parse_json_resp(parser) == 0);
585 EXPECT_TRUE(parser.is_array());
586
587 l = parser.get_array_elements();
588 EXPECT_EQ(1U, l.size());
589 for(vector<string>::iterator it = l.begin();
590 it != l.end(); ++it) {
591 if((*it).compare(string("\"") + uid + string("\"")) == 0) {
592 found = true;
593 break;
594 }
595 }
596 EXPECT_TRUE(found);
597
598 /*Check with second user*/
599 string uid2 = "ceph1", display_name2 = "CEPH1";
600 ASSERT_EQ(0, user_create(uid2, display_name2, false));
601 /*Check the list of keys*/
602 g_test->send_request(string("GET"), string("/admin/metadata/user"));
603 EXPECT_EQ(200U, g_test->get_resp_code());
604
605 ASSERT_TRUE(parse_json_resp(parser) == 0);
606 EXPECT_TRUE(parser.is_array());
607
608 l = parser.get_array_elements();
609 EXPECT_EQ(2U, l.size());
610 bool found2 = false;
611 for(vector<string>::iterator it = l.begin();
612 it != l.end(); ++it) {
613 if((*it).compare(string("\"") + uid + string("\"")) == 0) {
614 found = true;
615 }
616 if((*it).compare(string("\"") + uid2 + string("\"")) == 0) {
617 found2 = true;
618 }
619 }
620 EXPECT_TRUE(found && found2);
621 ASSERT_EQ(0, user_rm(uid2, display_name2));
622
623 /*Remove the metadata caps*/
624 int rv = meta_caps_rm(perm);
625 EXPECT_EQ(0, rv);
626
627 if(rv == 0) {
628 g_test->send_request(string("GET"), string("/admin/metadata/"));
629 EXPECT_EQ(403U, g_test->get_resp_code());
630
631 g_test->send_request(string("GET"), string("/admin/metadata/user"));
632 EXPECT_EQ(403U, g_test->get_resp_code());
633 }
634 ASSERT_EQ(0, user_rm(uid, display_name));
635 }
636
637 TEST(TestRGWAdmin, meta_get){
638 JSONParser parser;
639 const char *perm = "*";
640 RGWUserInfo info;
641
642 ASSERT_EQ(0, user_create(uid, display_name));
643 ASSERT_EQ(0, meta_caps_add(perm));
644
645 ASSERT_EQ(0, user_info(uid, display_name, info));
646
647 g_test->send_request(string("GET"), string("/admin/metadata/user?key=test"));
648 EXPECT_EQ(404U, g_test->get_resp_code());
649
650 g_test->send_request(string("GET"), (string("/admin/metadata/user?key=") + uid));
651 EXPECT_EQ(200U, g_test->get_resp_code());
652
653 ASSERT_TRUE(parse_json_resp(parser) == 0);
654 RGWObjVersionTracker objv_tracker;
655 string metadata_key;
656
657 obj_version *objv = &objv_tracker.read_version;
658
659 JSONDecoder::decode_json("key", metadata_key, &parser);
660 JSONDecoder::decode_json("ver", *objv, &parser);
661 JSONObj *jo = parser.find_obj("data");
662 ASSERT_TRUE(jo);
663 string exp_meta_key = "user:";
664 exp_meta_key.append(uid);
665 EXPECT_TRUE(metadata_key.compare(exp_meta_key) == 0);
666
667 RGWUserInfo obt_info;
668 decode_json_obj(obt_info, jo);
669
670 EXPECT_TRUE(compare_user_info(info, obt_info) == 0);
671
672 /*Make a modification and check if its reflected*/
673 ASSERT_EQ(0, meta_caps_rm(perm));
674 perm = "read";
675 ASSERT_EQ(0, meta_caps_add(perm));
676
677 JSONParser parser1;
678 g_test->send_request(string("GET"), (string("/admin/metadata/user?key=") + uid));
679 EXPECT_EQ(200U, g_test->get_resp_code());
680
681 ASSERT_TRUE(parse_json_resp(parser1) == 0);
682
683 RGWObjVersionTracker objv_tracker1;
684 obj_version *objv1 = &objv_tracker1.read_version;
685
686 JSONDecoder::decode_json("key", metadata_key, &parser1);
687 JSONDecoder::decode_json("ver", *objv1, &parser1);
688 jo = parser1.find_obj("data");
689 ASSERT_TRUE(jo);
690
691 decode_json_obj(obt_info, jo);
692 uint32_t p1, p2;
693 p1 = RGW_CAP_ALL;
694 p2 = RGW_CAP_READ;
695 EXPECT_TRUE (info.caps.check_cap(meta_caps, p1) == 0);
696 EXPECT_TRUE (obt_info.caps.check_cap(meta_caps, p2) == 0);
697 p2 = RGW_CAP_WRITE;
698 EXPECT_TRUE (obt_info.caps.check_cap(meta_caps, p2) != 0);
699
700 /*Version and tag infromation*/
701 EXPECT_TRUE(objv1->ver > objv->ver);
702 EXPECT_EQ(objv1->tag, objv->tag);
703
704 int rv = meta_caps_rm(perm);
705 EXPECT_EQ(0, rv);
706
707 if(rv == 0) {
708 g_test->send_request(string("GET"), (string("/admin/metadata/user?key=") + uid));
709 EXPECT_EQ(403U, g_test->get_resp_code());
710 }
711 ASSERT_EQ(0, user_rm(uid, display_name));
712 }
713
714 TEST(TestRGWAdmin, meta_put){
715 JSONParser parser;
716 const char *perm = "*";
717 RGWUserInfo info;
718
719 ASSERT_EQ(0, user_create(uid, display_name));
720 ASSERT_EQ(0, meta_caps_add(perm));
721
722 g_test->send_request(string("GET"), (string("/admin/metadata/user?key=") + uid));
723 EXPECT_EQ(200U, g_test->get_resp_code());
724
725 ASSERT_TRUE(parse_json_resp(parser) == 0);
726 RGWObjVersionTracker objv_tracker;
727 string metadata_key;
728
729 obj_version *objv = &objv_tracker.read_version;
730
731 JSONDecoder::decode_json("key", metadata_key, &parser);
732 JSONDecoder::decode_json("ver", *objv, &parser);
733 JSONObj *jo = parser.find_obj("data");
734 ASSERT_TRUE(jo);
735 string exp_meta_key = "user:";
736 exp_meta_key.append(uid);
737 EXPECT_TRUE(metadata_key.compare(exp_meta_key) == 0);
738
739 RGWUserInfo obt_info;
740 decode_json_obj(obt_info, jo);
741
742 /*Change the cap and PUT */
743 RGWUserCaps caps;
744 string new_cap;
745 Formatter *f = new JSONFormatter();
746
747 new_cap = meta_caps + string("=write");
748 caps.add_from_string(new_cap);
749 obt_info.caps = caps;
750 f->open_object_section("metadata_info");
751 ::encode_json("key", metadata_key, f);
752 ::encode_json("ver", *objv, f);
753 ::encode_json("data", obt_info, f);
754 f->close_section();
755 std::stringstream ss;
756 f->flush(ss);
757
758 g_test->send_request(string("PUT"), (string("/admin/metadata/user?key=") + uid),
759 meta_read_json,
760 (void *)&ss, ss.str().length());
761 EXPECT_EQ(200U, g_test->get_resp_code());
762
763 ASSERT_EQ(0, user_info(uid, display_name, obt_info));
764 uint32_t cp;
765 cp = RGW_CAP_WRITE;
766 EXPECT_TRUE (obt_info.caps.check_cap(meta_caps, cp) == 0);
767 cp = RGW_CAP_READ;
768 EXPECT_TRUE (obt_info.caps.check_cap(meta_caps, cp) != 0);
769
770 int rv = meta_caps_rm("write");
771 EXPECT_EQ(0, rv);
772 if(rv == 0) {
773 g_test->send_request(string("PUT"), (string("/admin/metadata/user?key=") + uid));
774 EXPECT_EQ(403U, g_test->get_resp_code());
775 }
776 ASSERT_EQ(0, user_rm(uid, display_name));
777 }
778
779 TEST(TestRGWAdmin, meta_lock_unlock) {
780 const char *perm = "*";
781 string rest_req;
782
783 ASSERT_EQ(0, user_create(uid, display_name));
784 ASSERT_EQ(0, meta_caps_add(perm));
785
786 rest_req = "/admin/metadata/user?key=" CEPH_UID "&lock&length=3";
787 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
788 EXPECT_EQ(400U, g_test->get_resp_code()); /*Bad request*/
789
790 rest_req = "/admin/metadata/user?lock&length=3&lock_id=ceph";
791 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
792 EXPECT_EQ(400U, g_test->get_resp_code()); /*Bad request*/
793
794 rest_req = "/admin/metadata/user?key=" CEPH_UID "&unlock";
795 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
796 EXPECT_EQ(400U, g_test->get_resp_code()); /*Bad request*/
797
798 rest_req = "/admin/metadata/user?unlock&lock_id=ceph";
799 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
800 EXPECT_EQ(400U, g_test->get_resp_code()); /*Bad request*/
801
802 rest_req = "/admin/metadata/user?key=" CEPH_UID "&lock&length=3&lock_id=ceph";
803 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
804 EXPECT_EQ(200U, g_test->get_resp_code());
805
806 rest_req = "/admin/metadata/user?key=" CEPH_UID "&unlock&lock_id=ceph";
807 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
808 EXPECT_EQ(200U, g_test->get_resp_code());
809
810 rest_req = "/admin/metadata/user?key=" CEPH_UID "&lock&length=3&lock_id=ceph1";
811 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
812 EXPECT_EQ(200U, g_test->get_resp_code());
813
814 rest_req = "/admin/metadata/user?key=" CEPH_UID "&unlock&lock_id=ceph1";
815 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
816 EXPECT_EQ(200U, g_test->get_resp_code());
817
818 rest_req = "/admin/metadata/user?key=" CEPH_UID "&lock&length=3&lock_id=ceph";
819 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
820 EXPECT_EQ(200U, g_test->get_resp_code());
821 utime_t sleep_time(3, 0);
822
823 rest_req = "/admin/metadata/user?key=" CEPH_UID "&lock&length=3&lock_id=ceph1";
824 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
825 EXPECT_EQ(500U, g_test->get_resp_code());
826
827 rest_req = "/admin/metadata/user?key=" CEPH_UID "&lock&length=3&lock_id=ceph";
828 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
829 EXPECT_EQ(409U, g_test->get_resp_code());
830 sleep_time.sleep();
831
832 rest_req = "/admin/metadata/user?key=" CEPH_UID "&lock&length=3&lock_id=ceph1";
833 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
834 EXPECT_EQ(200U, g_test->get_resp_code());
835
836 rest_req = "/admin/metadata/user?key=" CEPH_UID "&unlock&lock_id=ceph1";
837 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
838 EXPECT_EQ(200U, g_test->get_resp_code());
839
840 ASSERT_EQ(0, meta_caps_rm(perm));
841 perm = "read";
842 ASSERT_EQ(0, meta_caps_add(perm));
843 rest_req = "/admin/metadata/user?key=" CEPH_UID "&lock&length=3&lock_id=ceph";
844 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
845 EXPECT_EQ(403U, g_test->get_resp_code());
846
847 rest_req = "/admin/metadata/user?key=" CEPH_UID "&unlock&lock_id=ceph";
848 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
849 EXPECT_EQ(403U, g_test->get_resp_code());
850
851 ASSERT_EQ(0, meta_caps_rm(perm));
852 perm = "write";
853 ASSERT_EQ(0, meta_caps_add(perm));
854 rest_req = "/admin/metadata/user?key=" CEPH_UID "&lock&length=3&lock_id=ceph";
855 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
856 EXPECT_EQ(200U, g_test->get_resp_code());
857
858 rest_req = "/admin/metadata/user?key=" CEPH_UID "&unlock&lock_id=ceph";
859 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
860 EXPECT_EQ(200U, g_test->get_resp_code());
861
862 ASSERT_EQ(0, meta_caps_rm(perm));
863 rest_req = "/admin/metadata/user?key=" CEPH_UID "&lock&length=3&lock_id=ceph";
864 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
865 EXPECT_EQ(403U, g_test->get_resp_code());
866
867 rest_req = "/admin/metadata/user?key=" CEPH_UID "&unlock&lock_id=ceph";
868 g_test->send_request(string("POST"), rest_req, read_dummy_post, NULL, sizeof(int));
869 EXPECT_EQ(403U, g_test->get_resp_code());
870
871 ASSERT_EQ(0, user_rm(uid, display_name));
872 }
873
874 TEST(TestRGWAdmin, meta_delete){
875 JSONParser parser;
876 const char *perm = "*";
877 RGWUserInfo info;
878
879 ASSERT_EQ(0, user_create(uid, display_name));
880 ASSERT_EQ(0, meta_caps_add(perm));
881
882 g_test->send_request(string("DELETE"), (string("/admin/metadata/user?key=") + uid));
883 EXPECT_EQ(200U, g_test->get_resp_code());
884
885 ASSERT_TRUE(user_info(uid, display_name, info) != 0);
886
887 ASSERT_EQ(0, user_create(uid, display_name));
888 perm = "read";
889 ASSERT_EQ(0, meta_caps_add(perm));
890
891 g_test->send_request(string("DELETE"), (string("/admin/metadata/user?key=") + uid));
892 EXPECT_EQ(403U, g_test->get_resp_code());
893 ASSERT_EQ(0, user_rm(uid, display_name));
894 }
895
896 int main(int argc, char *argv[]){
897 auto args = argv_to_vec(argc, argv);
898
899 auto cct = global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT,
900 CODE_ENVIRONMENT_UTILITY,
901 CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
902 common_init_finish(g_ceph_context);
903 g_test = new admin_meta::test_helper();
904 finisher = new Finisher(g_ceph_context);
905 #ifdef GTEST
906 ::testing::InitGoogleTest(&argc, argv);
907 #endif
908 finisher->start();
909
910 if(g_test->extract_input(argc, argv) < 0){
911 print_usage(argv[0]);
912 return -1;
913 }
914 #ifdef GTEST
915 int r = RUN_ALL_TESTS();
916 if (r >= 0) {
917 cout << "There are no failures in the test case\n";
918 } else {
919 cout << "There are some failures\n";
920 }
921 #endif
922 finisher->stop();
923 return 0;
924 }