8 #include "common/ceph_crypto.h"
11 #define S3_BUCKET_NAME "s3testgw.fcgi"
12 #define SWIFT_BUCKET_NAME "swift3testgw.fcgi"
14 ((g_test->get_key_type() == KEY_TYPE_S3)?(string("/" S3_BUCKET_NAME)):(string("/swift/v1/" SWIFT_BUCKET_NAME)))
15 #include <gtest/gtest.h>
16 #include "common/code_environment.h"
17 #include "common/ceph_argparse.h"
18 #include "common/Finisher.h"
19 #include "global/global_init.h"
20 #include "rgw/rgw_cors.h"
21 #include "rgw/rgw_cors_s3.h"
25 #define CURL_VERBOSE 0
26 #define HTTP_RESPONSE_STR "RespCode"
27 #define CEPH_CRYPTO_HMACSHA1_DIGESTSIZE 20
29 extern "C" int ceph_armor(char *dst
, const char *dst_end
,
30 const char *src
, const char *end
);
32 KEY_TYPE_UNDEFINED
= 0,
37 static void print_usage(char *exec
){
38 cout
<< "Usage: " << exec
<< " <Options>\n";
40 "-g <gw-ip> - The ip address of the gateway\n"
41 "-p <gw-port> - The port number of the gateway\n"
42 "-k <SWIFT|S3> - The key type, either SWIFT or S3\n"
43 "-s3 <AWSAccessKeyId:SecretAccessKeyID> - Only, if the key type is S3, gives S3 credentials\n"
44 "-swift <Auth-Token> - Only if the key type is SWIFT, and gives the SWIFT credentials\n";
46 class test_cors_helper
{
52 map
<string
, string
> response
;
53 list
<string
> extra_hdrs
;
58 test_cors_helper() : curl_inst(NULL
), resp_data(NULL
), resp_code(0), kt(KEY_TYPE_UNDEFINED
){
59 curl_global_init(CURL_GLOBAL_ALL
);
62 curl_global_cleanup();
64 int send_request(string method
, string uri
,
65 size_t (*function
)(void *,size_t,size_t,void *) = 0,
66 void *ud
= 0, size_t length
= 0);
67 int extract_input(unsigned argc
, char *argv
[]);
68 string
& get_response(string hdr
){
71 void set_extra_header(string hdr
){
72 extra_hdrs
.push_back(hdr
);
74 void set_response(char *val
);
75 void set_response_data(char *data
, size_t len
){
76 if(resp_data
) delete resp_data
;
77 resp_data
= new string(data
, len
);
78 /*cout << resp_data->c_str() << "\n";*/
80 const string
*get_response_data(){return resp_data
;}
81 unsigned get_resp_code(){return resp_code
;}
82 key_type
get_key_type(){return kt
;}
85 int test_cors_helper::extract_input(unsigned argc
, char *argv
[]){
86 #define ERR_CHECK_NEXT_PARAM(o) \
87 if((loop + 1) >= argc)return -1; \
88 else o = argv[loop+1];
90 for(unsigned loop
= 1;loop
< argc
; loop
+= 2){
91 if(strcmp(argv
[loop
], "-g") == 0){
92 ERR_CHECK_NEXT_PARAM(host
);
93 }else if(strcmp(argv
[loop
], "-k") == 0){
95 ERR_CHECK_NEXT_PARAM(type
);
96 if(type
.compare("S3") == 0)kt
= KEY_TYPE_S3
;
97 else if(type
.compare("SWIFT") == 0)kt
= KEY_TYPE_SWIFT
;
98 }else if(strcmp(argv
[loop
],"-s3") == 0){
99 ERR_CHECK_NEXT_PARAM(creds
);
100 }else if(strcmp(argv
[loop
],"-swift") == 0){
101 ERR_CHECK_NEXT_PARAM(creds
);
102 }else if(strcmp(argv
[loop
],"-p") == 0){
103 ERR_CHECK_NEXT_PARAM(port
);
106 if(host
.empty() || creds
.empty())
111 void test_cors_helper::set_response(char *r
){
113 size_t off
= sr
.find(": ");
114 if(off
!= string::npos
){
115 h
.assign(sr
, 0, off
);
116 v
.assign(sr
, off
+ 2, sr
.find("\r\n") - (off
+2));
118 /*Could be the status code*/
119 if(sr
.find("HTTP/") != string::npos
){
120 h
.assign(HTTP_RESPONSE_STR
);
122 v
.assign(sr
, off
+ 1, sr
.find("\r\n") - (off
+ 1));
123 resp_code
= atoi((v
.substr(0, 3)).c_str());
129 size_t write_header(void *ptr
, size_t size
, size_t nmemb
, void *ud
){
130 test_cors_helper
*h
= static_cast<test_cors_helper
*>(ud
);
131 h
->set_response((char *)ptr
);
135 size_t write_data(void *ptr
, size_t size
, size_t nmemb
, void *ud
){
136 test_cors_helper
*h
= static_cast<test_cors_helper
*>(ud
);
137 h
->set_response_data((char *)ptr
, size
*nmemb
);
140 static inline void buf_to_hex(const unsigned char *buf
, int len
, char *str
)
144 for (i
= 0; i
< len
; i
++) {
145 sprintf(&str
[i
*2], "%02x", (int)buf
[i
]);
149 static void calc_hmac_sha1(const char *key
, int key_len
,
150 const char *msg
, int msg_len
, char *dest
)
151 /* destination should be CEPH_CRYPTO_HMACSHA1_DIGESTSIZE bytes long */
153 ceph::crypto::HMACSHA1
hmac((const unsigned char *)key
, key_len
);
154 hmac
.Update((const unsigned char *)msg
, msg_len
);
155 hmac
.Final((unsigned char *)dest
);
157 char hex_str
[(CEPH_CRYPTO_HMACSHA1_DIGESTSIZE
* 2) + 1];
158 buf_to_hex((unsigned char *)dest
, CEPH_CRYPTO_HMACSHA1_DIGESTSIZE
, hex_str
);
161 static int get_s3_auth(const string
&method
, string creds
, const string
&date
, const string
&res
, string
& out
){
162 string aid
, secret
, auth_hdr
;
163 size_t off
= creds
.find(":");
165 if(off
!= string::npos
){
166 aid
.assign(creds
, 0, off
);
167 secret
.assign(creds
, off
+ 1, string::npos
);
169 /*sprintf(auth_hdr, "%s\n\n\n%s\n%s", req_type, date, res);*/
170 char hmac_sha1
[CEPH_CRYPTO_HMACSHA1_DIGESTSIZE
];
171 char b64
[65]; /* 64 is really enough */
172 auth_hdr
.append(method
+ string("\n\n\n") + date
+ string("\n") + res
);
173 calc_hmac_sha1(secret
.c_str(), secret
.length(), auth_hdr
.c_str(), auth_hdr
.length(), hmac_sha1
);
174 int ret
= ceph_armor(b64
, b64
+ 64, hmac_sha1
,
175 hmac_sha1
+ CEPH_CRYPTO_HMACSHA1_DIGESTSIZE
);
177 cout
<< "ceph_armor failed\n";
181 out
.append(aid
+ string(":") + b64
);
186 void get_date(string
& d
){
190 char *days
[] = {(char *)"Sun", (char *)"Mon", (char *)"Tue",
191 (char *)"Wed", (char *)"Thu", (char *)"Fri",
193 char *months
[] = {(char *)"Jan", (char *)"Feb", (char *)"Mar",
194 (char *)"Apr", (char *)"May", (char *)"Jun",
195 (char *)"Jul",(char *) "Aug", (char *)"Sep",
196 (char *)"Oct", (char *)"Nov", (char *)"Dec"};
197 gettimeofday(&tv
, NULL
);
198 gmtime_r(&tv
.tv_sec
, &tm
);
199 sprintf(date
, "%s, %d %s %d %d:%d:%d GMT",
201 tm
.tm_mday
, months
[tm
.tm_mon
],
203 tm
.tm_hour
, tm
.tm_min
, 0 /*tm.tm_sec*/);
207 int test_cors_helper::send_request(string method
, string res
,
208 size_t (*read_function
)( void *,size_t,size_t,void *),
213 url
.append(string("http://") + host
);
214 if(port
.length() > 0)url
.append(string(":") + port
);
216 curl_inst
= curl_easy_init();
218 curl_easy_setopt(curl_inst
, CURLOPT_URL
, url
.c_str());
219 curl_easy_setopt(curl_inst
, CURLOPT_CUSTOMREQUEST
, method
.c_str());
220 curl_easy_setopt(curl_inst
, CURLOPT_VERBOSE
, CURL_VERBOSE
);
221 curl_easy_setopt(curl_inst
, CURLOPT_HEADERFUNCTION
, write_header
);
222 curl_easy_setopt(curl_inst
, CURLOPT_WRITEHEADER
, (void *)this);
223 curl_easy_setopt(curl_inst
, CURLOPT_WRITEFUNCTION
, write_data
);
224 curl_easy_setopt(curl_inst
, CURLOPT_WRITEDATA
, (void *)this);
226 curl_easy_setopt(curl_inst
, CURLOPT_READFUNCTION
, read_function
);
227 curl_easy_setopt(curl_inst
, CURLOPT_READDATA
, (void *)ud
);
228 curl_easy_setopt(curl_inst
, CURLOPT_UPLOAD
, 1L);
229 curl_easy_setopt(curl_inst
, CURLOPT_INFILESIZE_LARGE
, (curl_off_t
)length
);
234 http_date
.append(string("Date: ") + date
);
235 if(kt
== KEY_TYPE_S3
){
237 if(get_s3_auth(method
, creds
, date
, res
, s3auth
) < 0)return -1;
238 auth
.append(string("Authorization: AWS ") + s3auth
);
239 } else if(kt
== KEY_TYPE_SWIFT
){
240 auth
.append(string("X-Auth-Token: ") + creds
);
242 cout
<< "Unknown state (" << kt
<< ")\n";
246 struct curl_slist
*slist
= NULL
;
247 slist
= curl_slist_append(slist
, auth
.c_str());
248 slist
= curl_slist_append(slist
, http_date
.c_str());
249 for(list
<string
>::iterator it
= extra_hdrs
.begin();
250 it
!= extra_hdrs
.end(); ++it
){
251 slist
= curl_slist_append(slist
, (*it
).c_str());
254 curl_slist_append(slist
, "Expect:");
255 curl_easy_setopt(curl_inst
, CURLOPT_HTTPHEADER
, slist
);
257 response
.erase(response
.begin(), response
.end());
258 extra_hdrs
.erase(extra_hdrs
.begin(), extra_hdrs
.end());
259 CURLcode res
= curl_easy_perform(curl_inst
);
261 cout
<< "Curl perform failed for " << url
<< ", res: " <<
262 curl_easy_strerror(res
) << "\n";
265 curl_slist_free_all(slist
);
267 curl_easy_cleanup(curl_inst
);
271 test_cors_helper
*g_test
;
274 static int create_bucket(void){
275 if(g_test
->get_key_type() == KEY_TYPE_S3
){
276 g_test
->send_request(string("PUT"), string("/" S3_BUCKET_NAME
));
277 if(g_test
->get_resp_code() != 200U){
278 cout
<< "Error creating bucket, http code " << g_test
->get_resp_code();
281 }else if(g_test
->get_key_type() == KEY_TYPE_SWIFT
){
282 g_test
->send_request(string("PUT"), string("/swift/v1/" SWIFT_BUCKET_NAME
));
283 if(g_test
->get_resp_code() != 201U){
284 cout
<< "Error creating bucket, http code " << g_test
->get_resp_code();
291 static int delete_bucket(void){
292 if(g_test
->get_key_type() == KEY_TYPE_S3
){
293 g_test
->send_request(string("DELETE"), string("/" S3_BUCKET_NAME
));
294 if(g_test
->get_resp_code() != 204U){
295 cout
<< "Error deleting bucket, http code " << g_test
->get_resp_code();
298 }else if(g_test
->get_key_type() == KEY_TYPE_SWIFT
){
299 g_test
->send_request(string("DELETE"), string("/swift/v1/" SWIFT_BUCKET_NAME
));
300 if(g_test
->get_resp_code() != 204U){
301 cout
<< "Error deleting bucket, http code " << g_test
->get_resp_code();
308 RGWCORSRule
*xml_to_cors_rule(string s
){
309 RGWCORSConfiguration_S3
*cors_config
;
310 RGWCORSXMLParser_S3
parser(g_ceph_context
);
311 const string
*data
= g_test
->get_response_data();
312 if (!parser
.init()) {
315 if (!parser
.parse(data
->c_str(), data
->length(), 1)) {
318 cors_config
= (RGWCORSConfiguration_S3
*)parser
.find_first("CORSConfiguration");
322 return cors_config
->host_name_rule(s
.c_str());
325 size_t cors_read_xml(void *ptr
, size_t s
, size_t n
, void *ud
){
326 stringstream
*ss
= (stringstream
*)ud
;
327 size_t len
= ss
->str().length();
329 cout
<< "Cannot copy xml data, as len is not enough\n";
332 memcpy(ptr
, (void *)ss
->str().c_str(), len
);
336 void send_cors(set
<string
> o
, set
<string
> h
,
337 list
<string
> e
, uint8_t flags
,
339 if(g_test
->get_key_type() == KEY_TYPE_S3
){
340 RGWCORSRule
rule(o
, h
, e
, flags
, max_age
);
341 RGWCORSConfiguration config
;
342 config
.stack_rule(rule
);
344 RGWCORSConfiguration_S3
*s3
;
345 s3
= static_cast<RGWCORSConfiguration_S3
*>(&config
);
348 g_test
->send_request(string("PUT"), string("/" S3_BUCKET_NAME
"?cors"), cors_read_xml
,
349 (void *)&ss
, ss
.str().length());
350 }else if(g_test
->get_key_type() == KEY_TYPE_SWIFT
){
351 set
<string
>::iterator it
;
353 for(it
= o
.begin(); it
!= o
.end(); ++it
){
354 if(a_o
.length() > 0)a_o
.append(" ");
357 g_test
->set_extra_header(string("X-Container-Meta-Access-Control-Allow-Origin: ") + a_o
);
361 for(it
= h
.begin(); it
!= h
.end(); ++it
){
362 if(a_h
.length() > 0)a_h
.append(" ");
365 g_test
->set_extra_header(string("X-Container-Meta-Access-Control-Allow-Headers: ") + a_h
);
369 for(list
<string
>::iterator lit
= e
.begin(); lit
!= e
.end(); ++lit
){
370 if(e_h
.length() > 0)e_h
.append(" ");
373 g_test
->set_extra_header(string("X-Container-Meta-Access-Control-Expose-Headers: ") + e_h
);
375 if(max_age
!= CORS_MAX_AGE_INVALID
){
377 sprintf(age
, "%u", max_age
);
378 g_test
->set_extra_header(string("X-Container-Meta-Access-Control-Max-Age: ") + string(age
));
380 //const char *data = "1";
383 g_test
->send_request(string("POST"), string("/swift/v1/" SWIFT_BUCKET_NAME
), cors_read_xml
,
388 TEST(TestCORS
, getcors_firsttime
){
389 if(g_test
->get_key_type() == KEY_TYPE_SWIFT
)return;
390 ASSERT_EQ(0, create_bucket());
391 g_test
->send_request(string("GET"), string("/" S3_BUCKET_NAME
"?cors"));
392 EXPECT_EQ(404U, g_test
->get_resp_code());
393 ASSERT_EQ(0, delete_bucket());
396 TEST(TestCORS
, putcors_firsttime
){
397 ASSERT_EQ(0, create_bucket());
398 set
<string
> origins
, h
;
401 origins
.insert(origins
.end(), "example.com");
402 uint8_t flags
= RGW_CORS_GET
| RGW_CORS_PUT
;
404 send_cors(origins
, h
, e
, flags
, CORS_MAX_AGE_INVALID
);
405 EXPECT_EQ(((g_test
->get_key_type() == KEY_TYPE_SWIFT
)?202U:200U), g_test
->get_resp_code());
407 /*Now get the CORS and check if its fine*/
408 if(g_test
->get_key_type() == KEY_TYPE_S3
){
409 g_test
->send_request(string("GET"), string("/" S3_BUCKET_NAME
"?cors"));
410 EXPECT_EQ(200U, g_test
->get_resp_code());
412 RGWCORSRule
*r
= xml_to_cors_rule(string("example.com"));
413 EXPECT_TRUE(r
!= NULL
);
416 EXPECT_TRUE((r
->get_allowed_methods() & (RGW_CORS_GET
| RGW_CORS_PUT
))
417 == (RGW_CORS_GET
| RGW_CORS_PUT
));
419 ASSERT_EQ(0, delete_bucket());
422 TEST(TestCORS
, putcors_invalid_hostname
){
423 ASSERT_EQ(0, create_bucket());
424 set
<string
> origins
, h
;
427 origins
.insert(origins
.end(), "*.example.*");
428 uint8_t flags
= RGW_CORS_GET
| RGW_CORS_PUT
;
429 send_cors(origins
, h
, e
, flags
, CORS_MAX_AGE_INVALID
);
430 EXPECT_EQ((400U), g_test
->get_resp_code());
431 origins
.erase(origins
.begin(), origins
.end());
433 if((g_test
->get_key_type() != KEY_TYPE_SWIFT
)){
434 origins
.insert(origins
.end(), "");
435 send_cors(origins
, h
, e
, flags
, CORS_MAX_AGE_INVALID
);
436 EXPECT_EQ((400U), g_test
->get_resp_code());
437 origins
.erase(origins
.begin(), origins
.end());
439 ASSERT_EQ(0, delete_bucket());
442 TEST(TestCORS
, putcors_invalid_headers
){
443 ASSERT_EQ(0, create_bucket());
444 set
<string
> origins
, h
;
447 origins
.insert(origins
.end(), "www.example.com");
448 h
.insert(h
.end(), "*-Header-*");
449 uint8_t flags
= RGW_CORS_GET
| RGW_CORS_PUT
;
450 send_cors(origins
, h
, e
, flags
, CORS_MAX_AGE_INVALID
);
451 EXPECT_EQ((400U), g_test
->get_resp_code());
452 h
.erase(h
.begin(), h
.end());
454 if((g_test
->get_key_type() != KEY_TYPE_SWIFT
)){
455 h
.insert(h
.end(), "");
456 flags
= RGW_CORS_GET
| RGW_CORS_PUT
;
457 send_cors(origins
, h
, e
, flags
, CORS_MAX_AGE_INVALID
);
458 EXPECT_EQ((400U), g_test
->get_resp_code());
459 h
.erase(h
.begin(), h
.end());
461 ASSERT_EQ(0, delete_bucket());
464 TEST(TestCORS
, optionscors_test_options_1
){
465 ASSERT_EQ(0, create_bucket());
466 set
<string
> origins
, h
;
469 origins
.insert(origins
.end(), "*.example.com");
470 uint8_t flags
= RGW_CORS_GET
| RGW_CORS_PUT
;
472 send_cors(origins
, h
, e
, flags
, CORS_MAX_AGE_INVALID
);
473 EXPECT_EQ(((g_test
->get_key_type() == KEY_TYPE_SWIFT
)?202U:200U), g_test
->get_resp_code());
475 g_test
->set_extra_header(string("Origin: a.example.com"));
476 g_test
->set_extra_header(string("Access-Control-Request-Method: GET"));
477 g_test
->set_extra_header(string("Access-Control-Allow-Headers: SomeHeader"));
478 g_test
->send_request(string("OPTIONS"), BUCKET_URL
);
479 EXPECT_EQ(200U, g_test
->get_resp_code());
480 if(g_test
->get_resp_code() == 200){
481 string s
= g_test
->get_response(string("Access-Control-Allow-Origin"));
482 EXPECT_EQ(0, s
.compare("a.example.com"));
483 s
= g_test
->get_response(string("Access-Control-Allow-Methods"));
484 EXPECT_EQ(0, s
.compare("GET"));
485 s
= g_test
->get_response(string("Access-Control-Allow-Headers"));
486 EXPECT_EQ(0U, s
.length());
487 s
= g_test
->get_response(string("Access-Control-Max-Age"));
488 EXPECT_EQ(0U, s
.length());
489 s
= g_test
->get_response(string("Access-Control-Expose-Headers"));
490 EXPECT_EQ(0U, s
.length());
493 ASSERT_EQ(0, delete_bucket());
496 TEST(TestCORS
, optionscors_test_options_2
){
497 ASSERT_EQ(0, create_bucket());
498 set
<string
> origins
, h
;
501 origins
.insert(origins
.end(), "*.example.com");
502 uint8_t flags
= RGW_CORS_GET
| RGW_CORS_PUT
| RGW_CORS_DELETE
| RGW_CORS_HEAD
;
504 send_cors(origins
, h
, e
, flags
, CORS_MAX_AGE_INVALID
);
505 EXPECT_EQ(((g_test
->get_key_type() == KEY_TYPE_SWIFT
)?202U:200U), g_test
->get_resp_code());
507 g_test
->set_extra_header(string("Origin: a.example.com"));
508 g_test
->set_extra_header(string("Access-Control-Request-Method: HEAD"));
509 g_test
->send_request(string("OPTIONS"), BUCKET_URL
);
510 EXPECT_EQ(200U, g_test
->get_resp_code());
511 if(g_test
->get_resp_code() == 200){
512 string s
= g_test
->get_response(string("Access-Control-Allow-Origin"));
513 EXPECT_EQ(0, s
.compare("a.example.com"));
514 s
= g_test
->get_response(string("Access-Control-Allow-Methods"));
515 EXPECT_EQ(0, s
.compare("HEAD"));
518 g_test
->set_extra_header(string("Origin: foo.bar.example.com"));
519 g_test
->set_extra_header(string("Access-Control-Request-Method: HEAD"));
520 g_test
->send_request(string("OPTIONS"), BUCKET_URL
);
521 EXPECT_EQ(200U, g_test
->get_resp_code());
522 if(g_test
->get_resp_code() == 200){
523 string s
= g_test
->get_response(string("Access-Control-Allow-Origin"));
524 EXPECT_EQ(0, s
.compare("foo.bar.example.com"));
525 s
= g_test
->get_response(string("Access-Control-Allow-Methods"));
526 EXPECT_EQ(0, s
.compare("HEAD"));
528 ASSERT_EQ(0, delete_bucket());
531 TEST(TestCORS
, optionscors_test_options_3
){
532 ASSERT_EQ(0, create_bucket());
533 set
<string
> origins
, h
;
536 origins
.insert(origins
.end(), "*");
537 uint8_t flags
= RGW_CORS_GET
| RGW_CORS_PUT
| RGW_CORS_DELETE
| RGW_CORS_HEAD
;
539 send_cors(origins
, h
, e
, flags
, CORS_MAX_AGE_INVALID
);
540 EXPECT_EQ(((g_test
->get_key_type() == KEY_TYPE_SWIFT
)?202U:200U), g_test
->get_resp_code());
542 /*Check for HEAD in Access-Control-Allow-Methods*/
543 g_test
->set_extra_header(string("Origin: a.example.com"));
544 g_test
->set_extra_header(string("Access-Control-Request-Method: HEAD"));
545 g_test
->send_request(string("OPTIONS"), BUCKET_URL
);
546 EXPECT_EQ(200U, g_test
->get_resp_code());
547 if(g_test
->get_resp_code() == 200){
548 string s
= g_test
->get_response(string("Access-Control-Allow-Origin"));
549 EXPECT_EQ(0, s
.compare("a.example.com"));
550 s
= g_test
->get_response(string("Access-Control-Allow-Methods"));
551 EXPECT_EQ(0, s
.compare("HEAD"));
554 /*Check for DELETE in Access-Control-Allow-Methods*/
555 g_test
->set_extra_header(string("Origin: foo.bar"));
556 g_test
->set_extra_header(string("Access-Control-Request-Method: DELETE"));
557 g_test
->send_request(string("OPTIONS"), BUCKET_URL
);
558 EXPECT_EQ(200U, g_test
->get_resp_code());
559 if(g_test
->get_resp_code() == 200){
560 string s
= g_test
->get_response(string("Access-Control-Allow-Origin"));
561 EXPECT_EQ(0, s
.compare("foo.bar"));
562 s
= g_test
->get_response(string("Access-Control-Allow-Methods"));
563 EXPECT_EQ(0, s
.compare("DELETE"));
566 /*Check for PUT in Access-Control-Allow-Methods*/
567 g_test
->set_extra_header(string("Origin: foo.bar"));
568 g_test
->set_extra_header(string("Access-Control-Request-Method: PUT"));
569 g_test
->send_request(string("OPTIONS"), BUCKET_URL
);
570 EXPECT_EQ(200U, g_test
->get_resp_code());
571 if(g_test
->get_resp_code() == 200){
572 string s
= g_test
->get_response(string("Access-Control-Allow-Origin"));
573 EXPECT_EQ(0, s
.compare("foo.bar"));
574 s
= g_test
->get_response(string("Access-Control-Allow-Methods"));
575 EXPECT_EQ(0, s
.compare("PUT"));
578 /*Check for POST in Access-Control-Allow-Methods*/
579 g_test
->set_extra_header(string("Origin: foo.bar"));
580 g_test
->set_extra_header(string("Access-Control-Request-Method: POST"));
581 g_test
->send_request(string("OPTIONS"), BUCKET_URL
);
582 EXPECT_EQ(200U, g_test
->get_resp_code());
583 if(g_test
->get_resp_code() == 200){
584 string s
= g_test
->get_response(string("Access-Control-Allow-Origin"));
585 EXPECT_EQ(0, s
.compare("foo.bar"));
586 if(g_test
->get_key_type() == KEY_TYPE_S3
){
587 s
= g_test
->get_response(string("Access-Control-Allow-Methods"));
588 EXPECT_EQ(0U, s
.length());
590 s
= g_test
->get_response(string("Access-Control-Allow-Methods"));
591 EXPECT_EQ(0, s
.compare("POST"));
594 ASSERT_EQ(0, delete_bucket());
597 TEST(TestCORS
, optionscors_test_options_4
){
598 ASSERT_EQ(0, create_bucket());
599 set
<string
> origins
, h
;
602 origins
.insert(origins
.end(), "example.com");
603 h
.insert(h
.end(), "Header1");
604 h
.insert(h
.end(), "Header2");
605 h
.insert(h
.end(), "*");
606 uint8_t flags
= RGW_CORS_GET
| RGW_CORS_PUT
;
608 send_cors(origins
, h
, e
, flags
, CORS_MAX_AGE_INVALID
);
609 EXPECT_EQ(((g_test
->get_key_type() == KEY_TYPE_SWIFT
)?202U:200U), g_test
->get_resp_code());
611 g_test
->set_extra_header(string("Origin: example.com"));
612 g_test
->set_extra_header(string("Access-Control-Request-Method: GET"));
613 g_test
->send_request(string("OPTIONS"), BUCKET_URL
);
614 EXPECT_EQ(200U, g_test
->get_resp_code());
615 if(g_test
->get_resp_code() == 200){
616 string s
= g_test
->get_response(string("Access-Control-Allow-Origin"));
617 EXPECT_EQ(0, s
.compare("example.com"));
618 s
= g_test
->get_response(string("Access-Control-Allow-Methods"));
619 EXPECT_EQ(0, s
.compare("GET"));
620 s
= g_test
->get_response(string("Access-Control-Allow-Headers"));
621 EXPECT_EQ(0U, s
.length());
623 g_test
->set_extra_header(string("Origin: example.com"));
624 g_test
->set_extra_header(string("Access-Control-Request-Method: GET"));
625 g_test
->set_extra_header(string("Access-Control-Allow-Headers: Header1"));
626 g_test
->send_request(string("OPTIONS"), BUCKET_URL
);
627 EXPECT_EQ(200U, g_test
->get_resp_code());
628 if(g_test
->get_resp_code() == 200){
629 string s
= g_test
->get_response(string("Access-Control-Allow-Origin"));
630 EXPECT_EQ(0, s
.compare("example.com"));
631 s
= g_test
->get_response(string("Access-Control-Allow-Methods"));
632 EXPECT_EQ(0, s
.compare("GET"));
633 s
= g_test
->get_response(string("Access-Control-Allow-Headers"));
634 EXPECT_EQ(0, s
.compare("Header1"));
636 g_test
->set_extra_header(string("Origin: example.com"));
637 g_test
->set_extra_header(string("Access-Control-Request-Method: GET"));
638 g_test
->set_extra_header(string("Access-Control-Allow-Headers: Header2"));
639 g_test
->send_request(string("OPTIONS"), BUCKET_URL
);
640 EXPECT_EQ(200U, g_test
->get_resp_code());
641 if(g_test
->get_resp_code() == 200){
642 string s
= g_test
->get_response(string("Access-Control-Allow-Origin"));
643 EXPECT_EQ(0, s
.compare("example.com"));
644 s
= g_test
->get_response(string("Access-Control-Allow-Methods"));
645 EXPECT_EQ(0, s
.compare("GET"));
646 s
= g_test
->get_response(string("Access-Control-Allow-Headers"));
647 EXPECT_EQ(0, s
.compare("Header2"));
649 g_test
->set_extra_header(string("Origin: example.com"));
650 g_test
->set_extra_header(string("Access-Control-Request-Method: GET"));
651 g_test
->set_extra_header(string("Access-Control-Allow-Headers: Header2, Header1"));
652 g_test
->send_request(string("OPTIONS"), BUCKET_URL
);
653 EXPECT_EQ(200U, g_test
->get_resp_code());
654 if(g_test
->get_resp_code() == 200){
655 string s
= g_test
->get_response(string("Access-Control-Allow-Origin"));
656 EXPECT_EQ(0, s
.compare("example.com"));
657 s
= g_test
->get_response(string("Access-Control-Allow-Methods"));
658 EXPECT_EQ(0, s
.compare("GET"));
659 s
= g_test
->get_response(string("Access-Control-Allow-Headers"));
660 EXPECT_EQ(0, s
.compare("Header2,Header1"));
662 g_test
->set_extra_header(string("Origin: example.com"));
663 g_test
->set_extra_header(string("Access-Control-Request-Method: GET"));
664 g_test
->set_extra_header(string("Access-Control-Allow-Headers: Header1, Header2"));
665 g_test
->send_request(string("OPTIONS"), BUCKET_URL
);
666 EXPECT_EQ(200U, g_test
->get_resp_code());
667 if(g_test
->get_resp_code() == 200){
668 string s
= g_test
->get_response(string("Access-Control-Allow-Origin"));
669 EXPECT_EQ(0, s
.compare("example.com"));
670 s
= g_test
->get_response(string("Access-Control-Allow-Methods"));
671 EXPECT_EQ(0, s
.compare("GET"));
672 s
= g_test
->get_response(string("Access-Control-Allow-Headers"));
673 EXPECT_EQ(0, s
.compare("Header1,Header2"));
675 g_test
->set_extra_header(string("Origin: example.com"));
676 g_test
->set_extra_header(string("Access-Control-Request-Method: GET"));
677 g_test
->set_extra_header(string("Access-Control-Allow-Headers: Header1, Header2, Header3"));
678 g_test
->send_request(string("OPTIONS"), BUCKET_URL
);
679 EXPECT_EQ(200U, g_test
->get_resp_code());
680 if(g_test
->get_resp_code() == 200){
681 string s
= g_test
->get_response(string("Access-Control-Allow-Origin"));
682 EXPECT_EQ(0, s
.compare("example.com"));
683 s
= g_test
->get_response(string("Access-Control-Allow-Methods"));
684 EXPECT_EQ(0, s
.compare("GET"));
685 s
= g_test
->get_response(string("Access-Control-Allow-Headers"));
686 EXPECT_EQ(0, s
.compare("Header1,Header2,Header3"));
688 ASSERT_EQ(0, delete_bucket());
691 TEST(TestCORS
, optionscors_test_options_5
){
692 ASSERT_EQ(0, create_bucket());
693 set
<string
> origins
, h
;
696 origins
.insert(origins
.end(), "example.com");
697 e
.insert(e
.end(), "Expose1");
698 e
.insert(e
.end(), "Expose2");
699 uint8_t flags
= RGW_CORS_GET
| RGW_CORS_PUT
;
701 send_cors(origins
, h
, e
, flags
, CORS_MAX_AGE_INVALID
);
702 EXPECT_EQ(((g_test
->get_key_type() == KEY_TYPE_SWIFT
)?202U:200U), g_test
->get_resp_code());
704 g_test
->set_extra_header(string("Origin: example.com"));
705 g_test
->set_extra_header(string("Access-Control-Request-Method: GET"));
706 g_test
->send_request(string("OPTIONS"), BUCKET_URL
);
707 EXPECT_EQ(200U, g_test
->get_resp_code());
708 if(g_test
->get_resp_code() == 200){
709 string s
= g_test
->get_response(string("Access-Control-Allow-Origin"));
710 EXPECT_EQ(0, s
.compare("example.com"));
711 s
= g_test
->get_response(string("Access-Control-Allow-Methods"));
712 EXPECT_EQ(0, s
.compare("GET"));
713 s
= g_test
->get_response(string("Access-Control-Expose-Headers"));
714 EXPECT_EQ(0, s
.compare("Expose1,Expose2"));
716 ASSERT_EQ(0, delete_bucket());
719 TEST(TestCORS
, optionscors_test_options_6
){
720 ASSERT_EQ(0, create_bucket());
721 set
<string
> origins
, h
;
723 unsigned err
= (g_test
->get_key_type() == KEY_TYPE_SWIFT
)?401U:403U;
725 origins
.insert(origins
.end(), "http://www.example.com");
726 uint8_t flags
= RGW_CORS_GET
| RGW_CORS_PUT
;
728 send_cors(origins
, h
, e
, flags
, CORS_MAX_AGE_INVALID
);
729 EXPECT_EQ(((g_test
->get_key_type() == KEY_TYPE_SWIFT
)?202U:200U), g_test
->get_resp_code());
731 g_test
->set_extra_header(string("Origin: example.com"));
732 g_test
->set_extra_header(string("Access-Control-Request-Method: GET"));
733 g_test
->send_request(string("OPTIONS"), BUCKET_URL
);
734 EXPECT_EQ(err
, g_test
->get_resp_code());
736 g_test
->set_extra_header(string("Origin: http://example.com"));
737 g_test
->set_extra_header(string("Access-Control-Request-Method: GET"));
738 g_test
->send_request(string("OPTIONS"), BUCKET_URL
);
739 EXPECT_EQ(err
, g_test
->get_resp_code());
741 g_test
->set_extra_header(string("Origin: www.example.com"));
742 g_test
->set_extra_header(string("Access-Control-Request-Method: GET"));
743 g_test
->send_request(string("OPTIONS"), BUCKET_URL
);
744 EXPECT_EQ(err
, g_test
->get_resp_code());
746 g_test
->set_extra_header(string("Origin: http://www.example.com"));
747 g_test
->set_extra_header(string("Access-Control-Request-Method: GET"));
748 g_test
->send_request(string("OPTIONS"), BUCKET_URL
);
749 EXPECT_EQ(200U, g_test
->get_resp_code());
751 origins
.erase(origins
.begin(), origins
.end());
752 origins
.insert(origins
.end(), "*.example.com");
753 send_cors(origins
, h
, e
, flags
, CORS_MAX_AGE_INVALID
);
754 EXPECT_EQ(((g_test
->get_key_type() == KEY_TYPE_SWIFT
)?202U:200U), g_test
->get_resp_code());
756 g_test
->set_extra_header(string("Origin: .example.com"));
757 g_test
->set_extra_header(string("Access-Control-Request-Method: GET"));
758 g_test
->send_request(string("OPTIONS"), BUCKET_URL
);
759 EXPECT_EQ(200U, g_test
->get_resp_code());
761 g_test
->set_extra_header(string("Origin: http://example.com"));
762 g_test
->set_extra_header(string("Access-Control-Request-Method: GET"));
763 g_test
->send_request(string("OPTIONS"), BUCKET_URL
);
764 EXPECT_EQ(err
, g_test
->get_resp_code());
766 g_test
->set_extra_header(string("Origin: www.example.com"));
767 g_test
->set_extra_header(string("Access-Control-Request-Method: GET"));
768 g_test
->send_request(string("OPTIONS"), BUCKET_URL
);
769 EXPECT_EQ(200U, g_test
->get_resp_code());
771 g_test
->set_extra_header(string("Origin: http://www.example.com"));
772 g_test
->set_extra_header(string("Access-Control-Request-Method: GET"));
773 g_test
->send_request(string("OPTIONS"), BUCKET_URL
);
774 EXPECT_EQ(200U, g_test
->get_resp_code());
776 g_test
->set_extra_header(string("Origin: https://www.example.com"));
777 g_test
->set_extra_header(string("Access-Control-Request-Method: GET"));
778 g_test
->send_request(string("OPTIONS"), BUCKET_URL
);
779 EXPECT_EQ(200U, g_test
->get_resp_code());
781 origins
.erase(origins
.begin(), origins
.end());
782 origins
.insert(origins
.end(), "https://example*.com");
783 send_cors(origins
, h
, e
, flags
, CORS_MAX_AGE_INVALID
);
784 EXPECT_EQ(((g_test
->get_key_type() == KEY_TYPE_SWIFT
)?202U:200U), g_test
->get_resp_code());
786 g_test
->set_extra_header(string("Origin: https://example.com"));
787 g_test
->set_extra_header(string("Access-Control-Request-Method: GET"));
788 g_test
->send_request(string("OPTIONS"), BUCKET_URL
);
789 EXPECT_EQ(200U, g_test
->get_resp_code());
791 g_test
->set_extra_header(string("Origin: http://example.com"));
792 g_test
->set_extra_header(string("Access-Control-Request-Method: GET"));
793 g_test
->send_request(string("OPTIONS"), BUCKET_URL
);
794 EXPECT_EQ(err
, g_test
->get_resp_code());
796 g_test
->set_extra_header(string("Origin: www.example.com"));
797 g_test
->set_extra_header(string("Access-Control-Request-Method: GET"));
798 g_test
->send_request(string("OPTIONS"), BUCKET_URL
);
799 EXPECT_EQ(err
, g_test
->get_resp_code());
801 g_test
->set_extra_header(string("Origin: https://example.a.b.com"));
802 g_test
->set_extra_header(string("Access-Control-Request-Method: GET"));
803 g_test
->send_request(string("OPTIONS"), BUCKET_URL
);
804 EXPECT_EQ(200U, g_test
->get_resp_code());
806 ASSERT_EQ(0, delete_bucket());
809 TEST(TestCORS
, optionscors_test_options_7
){
810 ASSERT_EQ(0, create_bucket());
811 set
<string
> origins
, h
;
814 origins
.insert(origins
.end(), "example.com");
815 h
.insert(h
.end(), "Header*");
816 h
.insert(h
.end(), "Hdr-*-Length");
817 h
.insert(h
.end(), "*-Length");
818 h
.insert(h
.end(), "foo*foo");
819 uint8_t flags
= RGW_CORS_GET
| RGW_CORS_PUT
;
821 send_cors(origins
, h
, e
, flags
, CORS_MAX_AGE_INVALID
);
822 EXPECT_EQ(((g_test
->get_key_type() == KEY_TYPE_SWIFT
)?202U:200U), g_test
->get_resp_code());
824 g_test
->set_extra_header(string("Origin: example.com"));
825 g_test
->set_extra_header(string("Access-Control-Request-Method: GET"));
826 g_test
->set_extra_header(string("Access-Control-Allow-Headers: Header1, Header2, Header3, "
827 "Hdr--Length, Hdr-1-Length, Header-Length, Content-Length, foofoofoo"));
828 g_test
->send_request(string("OPTIONS"), BUCKET_URL
);
829 EXPECT_EQ(200U, g_test
->get_resp_code());
830 if(g_test
->get_resp_code() == 200){
831 string s
= g_test
->get_response(string("Access-Control-Allow-Origin"));
832 EXPECT_EQ(0, s
.compare("example.com"));
833 s
= g_test
->get_response(string("Access-Control-Allow-Methods"));
834 EXPECT_EQ(0, s
.compare("GET"));
835 s
= g_test
->get_response(string("Access-Control-Allow-Headers"));
836 EXPECT_EQ(0, s
.compare("Header1,Header2,Header3,"
837 "Hdr--Length,Hdr-1-Length,Header-Length,Content-Length,foofoofoo"));
839 ASSERT_EQ(0, delete_bucket());
842 TEST(TestCORS
, deletecors_firsttime
){
843 if(g_test
->get_key_type() == KEY_TYPE_SWIFT
)return;
844 ASSERT_EQ(0, create_bucket());
845 g_test
->send_request("DELETE", "/" S3_BUCKET_NAME
"?cors");
846 EXPECT_EQ(204U, g_test
->get_resp_code());
847 ASSERT_EQ(0, delete_bucket());
850 TEST(TestCORS
, deletecors_test
){
851 set
<string
> origins
, h
;
853 if(g_test
->get_key_type() == KEY_TYPE_SWIFT
)return;
854 ASSERT_EQ(0, create_bucket());
855 origins
.insert(origins
.end(), "example.com");
856 uint8_t flags
= RGW_CORS_GET
| RGW_CORS_PUT
;
858 send_cors(origins
, h
, e
, flags
, CORS_MAX_AGE_INVALID
);
859 EXPECT_EQ(((g_test
->get_key_type() == KEY_TYPE_SWIFT
)?202U:200U), g_test
->get_resp_code());
861 g_test
->send_request("GET", "/" S3_BUCKET_NAME
"?cors");
862 EXPECT_EQ(200U, g_test
->get_resp_code());
863 g_test
->send_request("DELETE", "/" S3_BUCKET_NAME
"?cors");
864 EXPECT_EQ(204U, g_test
->get_resp_code());
865 g_test
->send_request("GET", "/" S3_BUCKET_NAME
"?cors");
866 EXPECT_EQ(404U, g_test
->get_resp_code());
867 ASSERT_EQ(0, delete_bucket());
870 int main(int argc
, char *argv
[]){
871 vector
<const char*> args
;
872 argv_to_vec(argc
, (const char **)argv
, args
);
874 auto cct
= global_init(NULL
, args
, CEPH_ENTITY_TYPE_CLIENT
,
875 CODE_ENVIRONMENT_UTILITY
,
876 CINIT_FLAG_NO_DEFAULT_CONFIG_FILE
);
877 common_init_finish(g_ceph_context
);
878 g_test
= new test_cors_helper();
879 finisher
= new Finisher(g_ceph_context
);
881 ::testing::InitGoogleTest(&argc
, argv
);
885 if(g_test
->extract_input((unsigned)argc
, argv
) < 0){
886 print_usage(argv
[0]);
890 int r
= RUN_ALL_TESTS();
892 cout
<< "There are failures in the test case\n";