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