storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/web-handlers_test.go (about) 1 /* 2 * MinIO Cloud Storage, (C) 2016, 2017, 2018 MinIO, Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package cmd 18 19 import ( 20 "archive/zip" 21 "bytes" 22 "context" 23 "crypto/md5" 24 "encoding/hex" 25 "encoding/json" 26 "fmt" 27 "io" 28 "io/ioutil" 29 "net/http" 30 "net/http/httptest" 31 "reflect" 32 "strconv" 33 "strings" 34 "testing" 35 36 jwtgo "github.com/dgrijalva/jwt-go" 37 humanize "github.com/dustin/go-humanize" 38 39 xjwt "storj.io/minio/cmd/jwt" 40 "storj.io/minio/pkg/hash" 41 ) 42 43 // Implement a dummy flush writer. 44 type flushWriter struct { 45 io.Writer 46 } 47 48 // Flush writer is a dummy writer compatible with http.Flusher and http.ResponseWriter. 49 func (f *flushWriter) Flush() {} 50 func (f *flushWriter) Write(b []byte) (n int, err error) { return f.Writer.Write(b) } 51 func (f *flushWriter) Header() http.Header { return http.Header{} } 52 func (f *flushWriter) WriteHeader(code int) {} 53 54 func newFlushWriter(writer io.Writer) http.ResponseWriter { 55 return &flushWriter{writer} 56 } 57 58 // Tests private function writeWebErrorResponse. 59 func TestWriteWebErrorResponse(t *testing.T) { 60 var buffer bytes.Buffer 61 testCases := []struct { 62 webErr error 63 apiErrCode APIErrorCode 64 }{ 65 // List of various errors and their corresponding API errors. 66 { 67 webErr: StorageFull{}, 68 apiErrCode: ErrStorageFull, 69 }, 70 { 71 webErr: BucketNotFound{}, 72 apiErrCode: ErrNoSuchBucket, 73 }, 74 { 75 webErr: BucketNameInvalid{}, 76 apiErrCode: ErrInvalidBucketName, 77 }, 78 { 79 webErr: hash.BadDigest{}, 80 apiErrCode: ErrBadDigest, 81 }, 82 { 83 webErr: IncompleteBody{}, 84 apiErrCode: ErrIncompleteBody, 85 }, 86 { 87 webErr: ObjectExistsAsDirectory{}, 88 apiErrCode: ErrObjectExistsAsDirectory, 89 }, 90 { 91 webErr: ObjectNotFound{}, 92 apiErrCode: ErrNoSuchKey, 93 }, 94 { 95 webErr: ObjectNameInvalid{}, 96 apiErrCode: ErrNoSuchKey, 97 }, 98 { 99 webErr: InsufficientWriteQuorum{}, 100 apiErrCode: ErrWriteQuorum, 101 }, 102 { 103 webErr: InsufficientReadQuorum{}, 104 apiErrCode: ErrReadQuorum, 105 }, 106 { 107 webErr: NotImplemented{}, 108 apiErrCode: ErrNotImplemented, 109 }, 110 } 111 112 // Validate all the test cases. 113 for i, testCase := range testCases { 114 writeWebErrorResponse(newFlushWriter(&buffer), testCase.webErr) 115 desc := GetAPIError(testCase.apiErrCode).Description 116 if testCase.apiErrCode == ErrNotImplemented { 117 desc = "Functionality not implemented" 118 } 119 recvDesc := buffer.Bytes() 120 // Check if the written desc is same as the one expected. 121 if !bytes.Equal(recvDesc, []byte(desc)) { 122 t.Errorf("Test %d: Unexpected response, expecting %s, got %s", i+1, desc, buffer.String()) 123 } 124 buffer.Reset() 125 } 126 } 127 128 // Authenticate and get JWT token - will be called before every webrpc handler invocation 129 func getWebRPCToken(apiRouter http.Handler, accessKey, secretKey string) (token string, err error) { 130 return authenticateWeb(accessKey, secretKey) 131 } 132 133 // Wrapper for calling Login Web Handler 134 func TestWebHandlerLogin(t *testing.T) { 135 ExecObjectLayerTest(t, testLoginWebHandler) 136 } 137 138 // testLoginWebHandler - Test login web handler 139 func testLoginWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) { 140 // Register the API end points with Erasure/FS object layer. 141 apiRouter := initTestWebRPCEndPoint(obj) 142 credentials := globalActiveCred 143 144 // test cases with sample input and expected output. 145 testCases := []struct { 146 username string 147 password string 148 success bool 149 }{ 150 {"", "", false}, 151 {"azerty", "foo", false}, 152 {"", "foo", false}, 153 {"azerty", "", false}, 154 {"azerty", "foo", false}, 155 {"azerty", "azerty123", false}, 156 {credentials.AccessKey, credentials.SecretKey, true}, 157 } 158 159 // Iterating over the test cases, calling the function under test and asserting the response. 160 for i, testCase := range testCases { 161 _, err := getWebRPCToken(apiRouter, testCase.username, testCase.password) 162 if err != nil && testCase.success { 163 t.Fatalf("Test %d: Expected to succeed but it failed, %v", i+1, err) 164 } 165 if err == nil && !testCase.success { 166 t.Fatalf("Test %d: Expected to fail but it didn't, %v", i+1, err) 167 } 168 169 } 170 } 171 172 // Wrapper for calling StorageInfo Web Handler 173 func TestWebHandlerStorageInfo(t *testing.T) { 174 ExecObjectLayerTest(t, testStorageInfoWebHandler) 175 } 176 177 // testStorageInfoWebHandler - Test StorageInfo web handler 178 func testStorageInfoWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) { 179 // get random bucket name. 180 // Register the API end points with Erasure/FS object layer. 181 apiRouter := initTestWebRPCEndPoint(obj) 182 credentials := globalActiveCred 183 184 authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey) 185 if err != nil { 186 t.Fatal("Cannot authenticate") 187 } 188 189 rec := httptest.NewRecorder() 190 191 storageInfoRequest := &WebGenericArgs{} 192 storageInfoReply := &StorageInfoRep{} 193 req, err := newTestWebRPCRequest("web.StorageInfo", authorization, storageInfoRequest) 194 if err != nil { 195 t.Fatalf("Failed to create HTTP request: <ERROR> %v", err) 196 } 197 apiRouter.ServeHTTP(rec, req) 198 if rec.Code != http.StatusOK { 199 t.Fatalf("Expected the response status to be 200, but instead found `%d`", rec.Code) 200 } 201 if err = getTestWebRPCResponse(rec, &storageInfoReply); err != nil { 202 t.Fatalf("Failed %v", err) 203 } 204 } 205 206 // Wrapper for calling ServerInfo Web Handler 207 func TestWebHandlerServerInfo(t *testing.T) { 208 ExecObjectLayerTest(t, testServerInfoWebHandler) 209 } 210 211 // testServerInfoWebHandler - Test ServerInfo web handler 212 func testServerInfoWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) { 213 // Register the API end points with Erasure/FS object layer. 214 apiRouter := initTestWebRPCEndPoint(obj) 215 credentials := globalActiveCred 216 217 authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey) 218 if err != nil { 219 t.Fatal("Cannot authenticate") 220 } 221 222 rec := httptest.NewRecorder() 223 224 serverInfoRequest := &WebGenericArgs{} 225 serverInfoReply := &ServerInfoRep{} 226 req, err := newTestWebRPCRequest("web.ServerInfo", authorization, serverInfoRequest) 227 if err != nil { 228 t.Fatalf("Failed to create HTTP request: <ERROR> %v", err) 229 } 230 apiRouter.ServeHTTP(rec, req) 231 if rec.Code != http.StatusOK { 232 t.Fatalf("Expected the response status to be 200, but instead found `%d`", rec.Code) 233 } 234 err = getTestWebRPCResponse(rec, &serverInfoReply) 235 if err != nil { 236 t.Fatalf("Failed, %v", err) 237 } 238 if serverInfoReply.MinioVersion != Version { 239 t.Fatalf("Cannot get minio version from server info handler") 240 } 241 serverInfoReply.MinioGlobalInfo["domains"] = []string(nil) 242 globalInfo := getGlobalInfo() 243 if !reflect.DeepEqual(serverInfoReply.MinioGlobalInfo, globalInfo) { 244 t.Fatalf("Global info did not match got %#v, expected %#v", serverInfoReply.MinioGlobalInfo, globalInfo) 245 } 246 } 247 248 // Wrapper for calling MakeBucket Web Handler 249 func TestWebHandlerMakeBucket(t *testing.T) { 250 ExecObjectLayerTest(t, testMakeBucketWebHandler) 251 } 252 253 // testMakeBucketWebHandler - Test MakeBucket web handler 254 func testMakeBucketWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) { 255 // Register the API end points with Erasure/FS object layer. 256 apiRouter := initTestWebRPCEndPoint(obj) 257 credentials := globalActiveCred 258 259 authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey) 260 if err != nil { 261 t.Fatal("Cannot authenticate") 262 } 263 264 rec := httptest.NewRecorder() 265 266 bucketName := getRandomBucketName() 267 268 testCases := []struct { 269 bucketName string 270 success bool 271 }{ 272 {"", false}, 273 {".", false}, 274 {"ab", false}, 275 {"minio", false}, 276 {minioMetaBucket, false}, 277 {bucketName, true}, 278 } 279 280 for i, testCase := range testCases { 281 makeBucketRequest := MakeBucketArgs{BucketName: testCase.bucketName} 282 makeBucketReply := &WebGenericRep{} 283 req, err := newTestWebRPCRequest("web.MakeBucket", authorization, makeBucketRequest) 284 if err != nil { 285 t.Fatalf("Test %d: Failed to create HTTP request: <ERROR> %v", i+1, err) 286 } 287 apiRouter.ServeHTTP(rec, req) 288 if rec.Code != http.StatusOK { 289 t.Fatalf("Test %d: Expected the response status to be 200, but instead found `%d`", i+1, rec.Code) 290 } 291 err = getTestWebRPCResponse(rec, &makeBucketReply) 292 if testCase.success && err != nil { 293 t.Fatalf("Test %d: Should succeed but it didn't, %v", i+1, err) 294 } 295 if !testCase.success && err == nil { 296 t.Fatalf("Test %d: Should fail but it didn't (%s)", i+1, testCase.bucketName) 297 } 298 } 299 } 300 301 // Wrapper for calling DeleteBucket handler 302 func TestWebHandlerDeleteBucket(t *testing.T) { 303 ExecObjectLayerTest(t, testDeleteBucketWebHandler) 304 } 305 306 // testDeleteBucketWebHandler - Test DeleteBucket web handler 307 func testDeleteBucketWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) { 308 apiRouter := initTestWebRPCEndPoint(obj) 309 310 credentials := globalActiveCred 311 token, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey) 312 if err != nil { 313 t.Fatalf("could not get RPC token, %s", err.Error()) 314 } 315 316 bucketName := getRandomBucketName() 317 var opts ObjectOptions 318 319 err = obj.MakeBucketWithLocation(context.Background(), bucketName, BucketOptions{}) 320 if err != nil { 321 t.Fatalf("failed to create bucket: %s (%s)", err.Error(), instanceType) 322 } 323 324 testCases := []struct { 325 bucketName string 326 // Whether or not to put an object into the bucket. 327 initWithObject bool 328 token string 329 // Expected error (error must only contain this string to pass test) 330 // Empty string = no error 331 expect string 332 }{ 333 {"", false, token, "Bucket Name is invalid. Lowercase letters, period, " + 334 "hyphen, numerals are the only allowed characters and should be minimum " + 335 "3 characters in length."}, 336 {".", false, "auth", "Authentication failed"}, 337 {".", false, token, "Bucket Name . is invalid. Lowercase letters, period, " + 338 "hyphen, numerals are the only allowed characters and should be minimum " + 339 "3 characters in length."}, 340 {"..", false, token, "Bucket Name .. is invalid. Lowercase letters, period, " + 341 "hyphen, numerals are the only allowed characters and should be minimum " + 342 "3 characters in length."}, 343 {"ab", false, token, "Bucket Name ab is invalid. Lowercase letters, period, " + 344 "hyphen, numerals are the only allowed characters and should be minimum " + 345 "3 characters in length."}, 346 {"minio", false, "false token", "Authentication failed"}, 347 {"minio", false, token, "Bucket Name minio is invalid. Lowercase letters, period, " + 348 "hyphen, numerals are the only allowed characters and should be minimum " + 349 "3 characters in length."}, 350 {bucketName, false, token, ""}, 351 {bucketName, true, token, "The bucket you tried to delete is not empty"}, 352 {bucketName, false, "", "JWT token missing"}, 353 } 354 355 for _, test := range testCases { 356 if test.initWithObject { 357 data := bytes.NewBufferString("hello") 358 _, err = obj.PutObject(context.Background(), test.bucketName, "object", mustGetPutObjReader(t, data, int64(data.Len()), "", ""), opts) 359 // _, err = obj.PutObject(test.bucketName, "object", int64(data.Len()), data, nil, "") 360 if err != nil { 361 t.Fatalf("could not put object to %s, %s", test.bucketName, err.Error()) 362 } 363 } 364 365 rec := httptest.NewRecorder() 366 367 makeBucketRequest := MakeBucketArgs{BucketName: test.bucketName} 368 makeBucketReply := &WebGenericRep{} 369 370 req, err := newTestWebRPCRequest("web.DeleteBucket", test.token, makeBucketRequest) 371 if err != nil { 372 t.Errorf("failed to create HTTP request: <ERROR> %v", err) 373 } 374 375 apiRouter.ServeHTTP(rec, req) 376 if rec.Code != http.StatusOK { 377 t.Errorf("expected the response status to be `%d`, but instead found `%d`", http.StatusOK, rec.Code) 378 } 379 err = getTestWebRPCResponse(rec, &makeBucketReply) 380 381 if test.expect != "" { 382 if err == nil { 383 // If we expected an error, but didn't get one. 384 t.Errorf("expected `..%s..` but got nil error", test.expect) 385 } else if !strings.Contains(err.Error(), test.expect) { 386 // If we got an error that wasn't what we expected. 387 t.Errorf("expected `..%s..` but got `%s`", test.expect, err.Error()) 388 } 389 } else if test.expect == "" && err != nil { 390 t.Errorf("expected test success, but got `%s`", err.Error()) 391 } 392 393 // If we created the bucket with an object, now delete the object to cleanup. 394 if test.initWithObject { 395 _, err = obj.DeleteObject(context.Background(), test.bucketName, "object", ObjectOptions{}) 396 if err != nil { 397 t.Fatalf("could not delete object, %s", err.Error()) 398 } 399 } 400 401 // If it did not succeed in deleting the bucket, don't try and recreate it. 402 // Or, it'll fail if there was an object. 403 if err != nil || test.initWithObject { 404 continue 405 } 406 407 err = obj.MakeBucketWithLocation(context.Background(), bucketName, BucketOptions{}) 408 if err != nil { 409 // failed to create new bucket, abort. 410 t.Fatalf("failed to create new bucket (%s): %s", instanceType, err.Error()) 411 } 412 } 413 } 414 415 // Wrapper for calling ListBuckets Web Handler 416 func TestWebHandlerListBuckets(t *testing.T) { 417 ExecObjectLayerTest(t, testListBucketsWebHandler) 418 } 419 420 // testListBucketsHandler - Test ListBuckets web handler 421 func testListBucketsWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) { 422 // Register the API end points with Erasure/FS object layer. 423 apiRouter := initTestWebRPCEndPoint(obj) 424 credentials := globalActiveCred 425 426 authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey) 427 if err != nil { 428 t.Fatal("Cannot authenticate") 429 } 430 431 rec := httptest.NewRecorder() 432 433 bucketName := getRandomBucketName() 434 // Create bucket. 435 err = obj.MakeBucketWithLocation(context.Background(), bucketName, BucketOptions{}) 436 if err != nil { 437 // failed to create newbucket, abort. 438 t.Fatalf("%s : %s", instanceType, err) 439 } 440 441 listBucketsRequest := WebGenericArgs{} 442 listBucketsReply := &ListBucketsRep{} 443 req, err := newTestWebRPCRequest("web.ListBuckets", authorization, listBucketsRequest) 444 if err != nil { 445 t.Fatalf("Failed to create HTTP request: <ERROR> %v", err) 446 } 447 apiRouter.ServeHTTP(rec, req) 448 if rec.Code != http.StatusOK { 449 t.Fatalf("Expected the response status to be 200, but instead found `%d`", rec.Code) 450 } 451 err = getTestWebRPCResponse(rec, &listBucketsReply) 452 if err != nil { 453 t.Fatalf("Failed, %v", err) 454 } 455 if len(listBucketsReply.Buckets) == 0 { 456 t.Fatalf("Cannot find the bucket already created by MakeBucket") 457 } 458 if listBucketsReply.Buckets[0].Name != bucketName { 459 t.Fatalf("Found another bucket %q other than already created by MakeBucket", listBucketsReply.Buckets[0].Name) 460 } 461 } 462 463 // Wrapper for calling ListObjects Web Handler 464 func TestWebHandlerListObjects(t *testing.T) { 465 ExecObjectLayerTest(t, testListObjectsWebHandler) 466 } 467 468 // testListObjectsHandler - Test ListObjects web handler 469 func testListObjectsWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) { 470 // Register the API end points with Erasure/FS object layer. 471 apiRouter := initTestWebRPCEndPoint(obj) 472 credentials := globalActiveCred 473 474 rec := httptest.NewRecorder() 475 476 authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey) 477 if err != nil { 478 t.Fatal("Cannot authenticate") 479 } 480 481 bucketName := getRandomBucketName() 482 objectName := "object" 483 objectSize := 1 * humanize.KiByte 484 485 // Create bucket. 486 err = obj.MakeBucketWithLocation(context.Background(), bucketName, BucketOptions{}) 487 if err != nil { 488 // failed to create newbucket, abort. 489 t.Fatalf("%s : %s", instanceType, err) 490 } 491 492 data := bytes.Repeat([]byte("a"), objectSize) 493 metadata := map[string]string{"etag": "c9a34cfc85d982698c6ac89f76071abd"} 494 _, err = obj.PutObject(context.Background(), bucketName, objectName, mustGetPutObjReader(t, bytes.NewReader(data), int64(len(data)), metadata["etag"], ""), ObjectOptions{UserDefined: metadata}) 495 496 if err != nil { 497 t.Fatalf("Was not able to upload an object, %v", err) 498 } 499 500 test := func(token string) (*ListObjectsRep, error) { 501 listObjectsRequest := ListObjectsArgs{BucketName: bucketName, Prefix: ""} 502 listObjectsReply := &ListObjectsRep{} 503 var req *http.Request 504 req, err = newTestWebRPCRequest("web.ListObjects", token, listObjectsRequest) 505 if err != nil { 506 return nil, err 507 } 508 apiRouter.ServeHTTP(rec, req) 509 if rec.Code != http.StatusOK { 510 return listObjectsReply, fmt.Errorf("Expected the response status to be 200, but instead found `%d`", rec.Code) 511 } 512 err = getTestWebRPCResponse(rec, &listObjectsReply) 513 if err != nil { 514 return listObjectsReply, err 515 } 516 return listObjectsReply, nil 517 } 518 verifyReply := func(reply *ListObjectsRep) { 519 if len(reply.Objects) == 0 { 520 t.Fatalf("Cannot find the object") 521 } 522 if reply.Objects[0].Key != objectName { 523 t.Fatalf("Found another object other than already created by PutObject") 524 } 525 if reply.Objects[0].Size != int64(objectSize) { 526 t.Fatalf("Found a object with the same name but with a different size") 527 } 528 } 529 530 // Authenticated ListObjects should succeed. 531 reply, err := test(authorization) 532 if err != nil { 533 t.Fatal(err) 534 } 535 verifyReply(reply) 536 537 // Unauthenticated ListObjects should fail. 538 _, err = test("") 539 if err == nil { 540 t.Fatalf("Expected error `%s`", err) 541 } 542 } 543 544 // Wrapper for calling RemoveObject Web Handler 545 func TestWebHandlerRemoveObject(t *testing.T) { 546 ExecObjectLayerTest(t, testRemoveObjectWebHandler) 547 } 548 549 // testRemoveObjectWebHandler - Test RemoveObjectObject web handler 550 func testRemoveObjectWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) { 551 // Register the API end points with Erasure/FS object layer. 552 apiRouter := initTestWebRPCEndPoint(obj) 553 credentials := globalActiveCred 554 555 rec := httptest.NewRecorder() 556 authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey) 557 if err != nil { 558 t.Fatal("Cannot authenticate") 559 } 560 561 bucketName := getRandomBucketName() 562 objectName := "object" 563 objectSize := 1 * humanize.KiByte 564 565 // Create bucket. 566 err = obj.MakeBucketWithLocation(context.Background(), bucketName, BucketOptions{}) 567 if err != nil { 568 // failed to create newbucket, abort. 569 t.Fatalf("%s : %s", instanceType, err) 570 } 571 572 data := bytes.Repeat([]byte("a"), objectSize) 573 metadata := map[string]string{"etag": "c9a34cfc85d982698c6ac89f76071abd"} 574 _, err = obj.PutObject(context.Background(), bucketName, objectName, mustGetPutObjReader(t, bytes.NewReader(data), int64(len(data)), metadata["etag"], ""), ObjectOptions{UserDefined: metadata}) 575 if err != nil { 576 t.Fatalf("Was not able to upload an object, %v", err) 577 } 578 579 objectName = "a/object" 580 metadata = map[string]string{"etag": "c9a34cfc85d982698c6ac89f76071abd"} 581 _, err = obj.PutObject(context.Background(), bucketName, objectName, mustGetPutObjReader(t, bytes.NewReader(data), int64(len(data)), metadata["etag"], ""), ObjectOptions{UserDefined: metadata}) 582 if err != nil { 583 t.Fatalf("Was not able to upload an object, %v", err) 584 } 585 586 removeRequest := RemoveObjectArgs{BucketName: bucketName, Objects: []string{"a/", "object"}} 587 removeReply := &WebGenericRep{} 588 req, err := newTestWebRPCRequest("web.RemoveObject", authorization, removeRequest) 589 if err != nil { 590 t.Fatalf("Failed to create HTTP request: <ERROR> %v", err) 591 } 592 apiRouter.ServeHTTP(rec, req) 593 if rec.Code != http.StatusOK { 594 t.Fatalf("Expected the response status to be 200, but instead found `%d`", rec.Code) 595 } 596 err = getTestWebRPCResponse(rec, &removeReply) 597 if err != nil { 598 t.Fatalf("Failed, %v", err) 599 } 600 601 removeRequest = RemoveObjectArgs{BucketName: bucketName, Objects: []string{"a/", "object"}} 602 removeReply = &WebGenericRep{} 603 req, err = newTestWebRPCRequest("web.RemoveObject", authorization, removeRequest) 604 if err != nil { 605 t.Fatalf("Failed to create HTTP request: <ERROR> %v", err) 606 } 607 apiRouter.ServeHTTP(rec, req) 608 if rec.Code != http.StatusOK { 609 t.Fatalf("Expected the response status to be 200, but instead found `%d`", rec.Code) 610 } 611 err = getTestWebRPCResponse(rec, &removeReply) 612 if err != nil { 613 t.Fatalf("Failed, %v", err) 614 } 615 616 removeRequest = RemoveObjectArgs{BucketName: bucketName} 617 removeReply = &WebGenericRep{} 618 req, err = newTestWebRPCRequest("web.RemoveObject", authorization, removeRequest) 619 if err != nil { 620 t.Fatalf("Failed to create HTTP request: <ERROR> %v", err) 621 } 622 apiRouter.ServeHTTP(rec, req) 623 if rec.Code != http.StatusOK { 624 t.Fatalf("Expected the response status to be 200, but instead found `%d`", rec.Code) 625 } 626 b, err := ioutil.ReadAll(rec.Body) 627 if err != nil { 628 t.Fatal(err) 629 } 630 if !bytes.Contains(b, []byte("Invalid arguments specified")) { 631 t.Fatalf("Expected response wrong %s", string(b)) 632 } 633 } 634 635 func TestWebCreateURLToken(t *testing.T) { 636 ExecObjectLayerTest(t, testCreateURLToken) 637 } 638 639 func getTokenString(accessKey, secretKey string) (string, error) { 640 claims := xjwt.NewMapClaims() 641 claims.SetExpiry(UTCNow().Add(defaultJWTExpiry)) 642 claims.SetAccessKey(accessKey) 643 token := jwtgo.NewWithClaims(jwtgo.SigningMethodHS512, claims) 644 return token.SignedString([]byte(secretKey)) 645 } 646 647 func testCreateURLToken(obj ObjectLayer, instanceType string, t TestErrHandler) { 648 apiRouter := initTestWebRPCEndPoint(obj) 649 credentials := globalActiveCred 650 651 authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey) 652 if err != nil { 653 t.Fatal(err) 654 } 655 656 args := WebGenericArgs{} 657 tokenReply := &URLTokenReply{} 658 659 req, err := newTestWebRPCRequest("web.CreateURLToken", authorization, args) 660 if err != nil { 661 t.Fatal(err) 662 } 663 664 rec := httptest.NewRecorder() 665 apiRouter.ServeHTTP(rec, req) 666 667 if rec.Code != http.StatusOK { 668 t.Fatalf("Expected the response status to be 200, but instead found `%d`", rec.Code) 669 } 670 671 err = getTestWebRPCResponse(rec, &tokenReply) 672 if err != nil { 673 t.Fatal(err) 674 } 675 676 // Ensure the token is valid now. It will expire later. 677 if !isAuthTokenValid(tokenReply.Token) { 678 t.Fatalf("token is not valid") 679 } 680 681 // Token is invalid. 682 if isAuthTokenValid("") { 683 t.Fatalf("token shouldn't be valid, but it is") 684 } 685 686 token, err := getTokenString("invalid-access", credentials.SecretKey) 687 if err != nil { 688 t.Fatal(err) 689 } 690 691 // Token has invalid access key. 692 if isAuthTokenValid(token) { 693 t.Fatalf("token shouldn't be valid, but it is") 694 } 695 } 696 697 // Wrapper for calling Upload Handler 698 func TestWebHandlerUpload(t *testing.T) { 699 ExecObjectLayerTest(t, testUploadWebHandler) 700 } 701 702 // testUploadWebHandler - Test Upload web handler 703 func testUploadWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) { 704 // Register the API end points with Erasure/FS object layer. 705 apiRouter := initTestWebRPCEndPoint(obj) 706 credentials := globalActiveCred 707 708 content := []byte("temporary file's content") 709 authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey) 710 if err != nil { 711 t.Fatal("Cannot authenticate") 712 } 713 714 objectName := "test.file" 715 bucketName := getRandomBucketName() 716 717 test := func(token string, sendContentLength bool) int { 718 rec := httptest.NewRecorder() 719 req, rErr := http.NewRequest(http.MethodPut, "/minio/upload/"+bucketName+SlashSeparator+objectName, nil) 720 if rErr != nil { 721 t.Fatalf("Cannot create upload request, %v", rErr) 722 } 723 724 req.Header.Set("x-amz-date", "20160814T114029Z") 725 req.Header.Set("Accept", "*/*") 726 req.Header.Set("User-Agent", "Mozilla") 727 728 req.Body = ioutil.NopCloser(bytes.NewReader(content)) 729 730 if !sendContentLength { 731 req.ContentLength = -1 732 } else { 733 req.ContentLength = int64(len(content)) 734 } 735 736 if token != "" { 737 req.Header.Set("Authorization", "Bearer "+authorization) 738 } 739 apiRouter.ServeHTTP(rec, req) 740 return rec.Code 741 } 742 // Create bucket. 743 err = obj.MakeBucketWithLocation(context.Background(), bucketName, BucketOptions{}) 744 if err != nil { 745 // failed to create newbucket, abort. 746 t.Fatalf("%s : %s", instanceType, err) 747 } 748 749 // Authenticated upload should succeed. 750 code := test(authorization, true) 751 if code != http.StatusOK { 752 t.Fatalf("Expected the response status to be 200, but instead found `%d`", code) 753 } 754 755 var byteBuffer bytes.Buffer 756 err = GetObject(context.Background(), obj, bucketName, objectName, 0, int64(len(content)), &byteBuffer, "", ObjectOptions{}) 757 if err != nil { 758 t.Fatalf("Failed, %v", err) 759 } 760 761 if !bytes.Equal(byteBuffer.Bytes(), content) { 762 t.Fatalf("The upload file is different from the download file") 763 } 764 765 // Authenticated upload without content-length should fail 766 code = test(authorization, false) 767 if code != http.StatusBadRequest { 768 t.Fatalf("Expected the response status to be 200, but instead found `%d`", code) 769 } 770 771 // Unauthenticated upload should fail. 772 code = test("", true) 773 if code != http.StatusForbidden { 774 t.Fatalf("Expected the response status to be 403, but instead found `%d`", code) 775 } 776 777 } 778 779 // Wrapper for calling Download Handler 780 func TestWebHandlerDownload(t *testing.T) { 781 ExecObjectLayerTest(t, testDownloadWebHandler) 782 } 783 784 // testDownloadWebHandler - Test Download web handler 785 func testDownloadWebHandler(obj ObjectLayer, instanceType string, t TestErrHandler) { 786 // Register the API end points with Erasure/FS object layer. 787 apiRouter := initTestWebRPCEndPoint(obj) 788 credentials := globalActiveCred 789 790 authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey) 791 if err != nil { 792 t.Fatal("Cannot authenticate") 793 } 794 795 objectName := "test.file" 796 bucketName := getRandomBucketName() 797 798 test := func(token string) (int, []byte) { 799 rec := httptest.NewRecorder() 800 path := "/minio/download/" + bucketName + SlashSeparator + objectName + "?token=" 801 if token != "" { 802 path = path + token 803 } 804 var req *http.Request 805 req, err = http.NewRequest(http.MethodGet, path, nil) 806 807 if err != nil { 808 t.Fatalf("Cannot create upload request, %v", err) 809 } 810 811 req.Header.Set("User-Agent", "Mozilla") 812 813 apiRouter.ServeHTTP(rec, req) 814 return rec.Code, rec.Body.Bytes() 815 } 816 817 // Create bucket. 818 err = obj.MakeBucketWithLocation(context.Background(), bucketName, BucketOptions{}) 819 if err != nil { 820 // failed to create newbucket, abort. 821 t.Fatalf("%s : %s", instanceType, err) 822 } 823 824 content := []byte("temporary file's content") 825 metadata := map[string]string{"etag": "01ce59706106fe5e02e7f55fffda7f34"} 826 _, err = obj.PutObject(context.Background(), bucketName, objectName, mustGetPutObjReader(t, bytes.NewReader(content), int64(len(content)), metadata["etag"], ""), ObjectOptions{UserDefined: metadata}) 827 if err != nil { 828 t.Fatalf("Was not able to upload an object, %v", err) 829 } 830 831 // Authenticated download should succeed. 832 code, bodyContent := test(authorization) 833 834 if code != http.StatusOK { 835 t.Fatalf("Expected the response status to be 200, but instead found `%d`", code) 836 } 837 838 if !bytes.Equal(bodyContent, content) { 839 t.Fatalf("The downloaded file is corrupted") 840 } 841 842 // Temporary token should succeed. 843 tmpToken, err := authenticateURL(credentials.AccessKey, credentials.SecretKey) 844 if err != nil { 845 t.Fatal(err) 846 } 847 848 code, bodyContent = test(tmpToken) 849 850 if code != http.StatusOK { 851 t.Fatalf("Expected the response status to be 200, but instead found `%d`", code) 852 } 853 854 if !bytes.Equal(bodyContent, content) { 855 t.Fatalf("The downloaded file is corrupted") 856 } 857 858 // Old token should fail. 859 code, bodyContent = test("eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1MDAzMzIwOTUsImlhdCI6MTUwMDMzMjAzNSwic3ViIjoiRFlLSU01VlRZNDBJMVZQSE5VMTkifQ.tXQ45GJc8eOFet_a4VWVyeqJEOPWybotQYNr2zVxBpEOICkGbu_YWGhd9TkLLe1E65oeeiLHPdXSN8CzcbPoRA") 860 if code != http.StatusForbidden { 861 t.Fatalf("Expected the response status to be 403, but instead found `%d`", code) 862 } 863 864 if !bytes.Equal(bodyContent, bytes.NewBufferString("Authentication failed, check your access credentials").Bytes()) { 865 t.Fatalf("Expected authentication error message, got %s", string(bodyContent)) 866 } 867 868 // Unauthenticated download should fail. 869 code, _ = test("") 870 if code != http.StatusForbidden { 871 t.Fatalf("Expected the response status to be 403, but instead found `%d`", code) 872 } 873 } 874 875 // Test web.DownloadZip 876 func TestWebHandlerDownloadZip(t *testing.T) { 877 ExecObjectLayerTest(t, testWebHandlerDownloadZip) 878 } 879 880 func testWebHandlerDownloadZip(obj ObjectLayer, instanceType string, t TestErrHandler) { 881 apiRouter := initTestWebRPCEndPoint(obj) 882 credentials := globalActiveCred 883 var opts ObjectOptions 884 885 authorization, err := authenticateURL(credentials.AccessKey, credentials.SecretKey) 886 if err != nil { 887 t.Fatal("Cannot authenticate") 888 } 889 890 bucket := getRandomBucketName() 891 fileOne := "aaaaaaaaaaaaaa" 892 fileTwo := "bbbbbbbbbbbbbb" 893 fileThree := "cccccccccccccc" 894 895 // Create bucket. 896 err = obj.MakeBucketWithLocation(context.Background(), bucket, BucketOptions{}) 897 if err != nil { 898 // failed to create newbucket, abort. 899 t.Fatalf("%s : %s", instanceType, err) 900 } 901 902 for objName, value := range map[string]string{ 903 "a/one": fileOne, 904 "a/b/two": fileTwo, 905 "a/c/three": fileThree, 906 } { 907 _, err = obj.PutObject(context.Background(), bucket, objName, mustGetPutObjReader(t, strings.NewReader(value), int64(len(value)), "", ""), opts) 908 if err != nil { 909 t.Fatal(err) 910 } 911 } 912 913 test := func(token string) (int, []byte) { 914 rec := httptest.NewRecorder() 915 path := "/minio/zip" + "?token=" 916 if token != "" { 917 path = path + token 918 } 919 args := DownloadZipArgs{ 920 Objects: []string{"one", "b/", "c/"}, 921 Prefix: "a/", 922 BucketName: bucket, 923 } 924 925 var argsData []byte 926 argsData, err = json.Marshal(args) 927 if err != nil { 928 return 0, nil 929 } 930 var req *http.Request 931 req, err = http.NewRequest(http.MethodPost, path, bytes.NewBuffer(argsData)) 932 933 if err != nil { 934 t.Fatalf("Cannot create upload request, %v", err) 935 } 936 937 req.Header.Set("User-Agent", "Mozilla") 938 939 apiRouter.ServeHTTP(rec, req) 940 return rec.Code, rec.Body.Bytes() 941 } 942 code, _ := test("") 943 if code != 403 { 944 t.Fatal("Expected to receive authentication error") 945 } 946 code, data := test(authorization) 947 if code != 200 { 948 t.Fatal("web.DownloadsZip() failed") 949 } 950 reader, err := zip.NewReader(bytes.NewReader(data), int64(len(data))) 951 if err != nil { 952 t.Fatal(err) 953 } 954 h := md5.New() 955 for _, file := range reader.File { 956 fileReader, err := file.Open() 957 if err != nil { 958 t.Fatal(err) 959 } 960 io.Copy(h, fileReader) 961 } 962 // Verify the md5 of the response. 963 if hex.EncodeToString(h.Sum(nil)) != "ac7196449b14bea42775d29e8bb29f50" { 964 t.Fatal("Incorrect zip contents") 965 } 966 } 967 968 // Wrapper for calling PresignedGet handler 969 func TestWebHandlerPresignedGetHandler(t *testing.T) { 970 ExecObjectLayerTest(t, testWebPresignedGetHandler) 971 } 972 973 func testWebPresignedGetHandler(obj ObjectLayer, instanceType string, t TestErrHandler) { 974 // Register the API end points with Erasure/FS object layer. 975 apiRouter := initTestWebRPCEndPoint(obj) 976 credentials := globalActiveCred 977 978 authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey) 979 if err != nil { 980 t.Fatal("Cannot authenticate") 981 } 982 983 rec := httptest.NewRecorder() 984 985 bucketName := getRandomBucketName() 986 objectName := "object" 987 objectSize := 1 * humanize.KiByte 988 989 // Create bucket. 990 err = obj.MakeBucketWithLocation(context.Background(), bucketName, BucketOptions{}) 991 if err != nil { 992 // failed to create newbucket, abort. 993 t.Fatalf("%s : %s", instanceType, err) 994 } 995 996 data := bytes.Repeat([]byte("a"), objectSize) 997 metadata := map[string]string{"etag": "c9a34cfc85d982698c6ac89f76071abd"} 998 _, err = obj.PutObject(context.Background(), bucketName, objectName, mustGetPutObjReader(t, bytes.NewReader(data), int64(len(data)), metadata["etag"], ""), ObjectOptions{UserDefined: metadata}) 999 if err != nil { 1000 t.Fatalf("Was not able to upload an object, %v", err) 1001 } 1002 1003 presignGetReq := PresignedGetArgs{ 1004 HostName: "", 1005 BucketName: bucketName, 1006 ObjectName: objectName, 1007 Expiry: 1000, 1008 } 1009 presignGetRep := &PresignedGetRep{} 1010 req, err := newTestWebRPCRequest("web.PresignedGet", authorization, presignGetReq) 1011 if err != nil { 1012 t.Fatalf("Failed to create HTTP request: <ERROR> %v", err) 1013 } 1014 apiRouter.ServeHTTP(rec, req) 1015 if rec.Code != http.StatusOK { 1016 t.Fatalf("Expected the response status to be 200, but instead found `%d`", rec.Code) 1017 } 1018 err = getTestWebRPCResponse(rec, &presignGetRep) 1019 if err != nil { 1020 t.Fatalf("Failed, %v", err) 1021 } 1022 1023 // Register the API end points with Erasure/FS object layer. 1024 apiRouter = initTestAPIEndPoints(obj, []string{"GetObject"}) 1025 1026 // Initialize a new api recorder. 1027 arec := httptest.NewRecorder() 1028 1029 req, err = newTestRequest(http.MethodGet, presignGetRep.URL, 0, nil) 1030 req.Header.Del("x-amz-content-sha256") 1031 if err != nil { 1032 t.Fatal("Failed to initialized a new request", err) 1033 } 1034 apiRouter.ServeHTTP(arec, req) 1035 if arec.Code != http.StatusOK { 1036 t.Fatalf("Expected the response status to be 200, but instead found `%d`", arec.Code) 1037 } 1038 savedData, err := ioutil.ReadAll(arec.Body) 1039 if err != nil { 1040 t.Fatal("Reading body failed", err) 1041 } 1042 if !bytes.Equal(data, savedData) { 1043 t.Fatal("Read data is not equal was what was expected") 1044 } 1045 1046 // Register the API end points with Erasure/FS object layer. 1047 apiRouter = initTestWebRPCEndPoint(obj) 1048 1049 presignGetReq = PresignedGetArgs{ 1050 HostName: "", 1051 BucketName: "", 1052 ObjectName: "", 1053 } 1054 presignGetRep = &PresignedGetRep{} 1055 req, err = newTestWebRPCRequest("web.PresignedGet", authorization, presignGetReq) 1056 if err != nil { 1057 t.Fatalf("Failed to create HTTP request: <ERROR> %v", err) 1058 } 1059 apiRouter.ServeHTTP(rec, req) 1060 if rec.Code != http.StatusOK { 1061 t.Fatalf("Expected the response status to be 200, but instead found `%d`", rec.Code) 1062 } 1063 err = getTestWebRPCResponse(rec, &presignGetRep) 1064 if err == nil { 1065 t.Fatalf("Failed, %v", err) 1066 } 1067 if err.Error() != "Bucket and Object are mandatory arguments." { 1068 t.Fatalf("Unexpected, expected `Bucket and Object are mandatory arguments`, got %s", err) 1069 } 1070 } 1071 1072 // TestWebCheckAuthorization - Test Authorization for all web handlers 1073 func TestWebCheckAuthorization(t *testing.T) { 1074 ctx, cancel := context.WithCancel(context.Background()) 1075 defer cancel() 1076 1077 // Prepare Erasure backend 1078 obj, fsDirs, err := prepareErasure16(ctx) 1079 if err != nil { 1080 t.Fatalf("Initialization of object layer failed for Erasure setup: %s", err) 1081 } 1082 // Executing the object layer tests for Erasure. 1083 defer removeRoots(fsDirs) 1084 1085 // Register the API end points with Erasure/FS object layer. 1086 apiRouter := initTestWebRPCEndPoint(obj) 1087 1088 // initialize the server and obtain the credentials and root. 1089 // credentials are necessary to sign the HTTP request. 1090 err = newTestConfig(globalMinioDefaultRegion, obj) 1091 if err != nil { 1092 t.Fatal("Init Test config failed", err) 1093 } 1094 1095 rec := httptest.NewRecorder() 1096 1097 // Check if web rpc calls return unauthorized request with an incorrect token 1098 webRPCs := []string{ 1099 "ServerInfo", "StorageInfo", "MakeBucket", 1100 "ListBuckets", "ListObjects", "RemoveObject", 1101 "SetAuth", "GetBucketPolicy", "SetBucketPolicy", 1102 "ListAllBucketPolicies", "PresignedGet", 1103 } 1104 for _, rpcCall := range webRPCs { 1105 reply := &WebGenericRep{} 1106 req, nerr := newTestWebRPCRequest("web."+rpcCall, "Bearer fooauthorization", &WebGenericArgs{}) 1107 if nerr != nil { 1108 t.Fatalf("Test %s: Failed to create HTTP request: <ERROR> %v", rpcCall, nerr) 1109 } 1110 apiRouter.ServeHTTP(rec, req) 1111 if rec.Code != http.StatusOK { 1112 t.Fatalf("Test %s: Expected the response status to be 200, but instead found `%d`", rpcCall, rec.Code) 1113 } 1114 err = getTestWebRPCResponse(rec, &reply) 1115 if err == nil { 1116 t.Fatalf("Test %s: Should fail", rpcCall) 1117 } else { 1118 if !strings.Contains(err.Error(), errAuthentication.Error()) { 1119 t.Fatalf("Test %s: should fail with Unauthorized request. Found error: %v", rpcCall, err) 1120 } 1121 } 1122 } 1123 1124 rec = httptest.NewRecorder() 1125 // Test authorization of web.Download 1126 req, err := http.NewRequest(http.MethodGet, "/minio/download/bucket/object?token=wrongauth", nil) 1127 if err != nil { 1128 t.Fatalf("Cannot create upload request, %v", err) 1129 } 1130 req.Header.Set("User-Agent", "Mozilla") 1131 apiRouter.ServeHTTP(rec, req) 1132 if rec.Code != http.StatusForbidden { 1133 t.Fatalf("Expected the response status to be 403, but instead found `%d`", rec.Code) 1134 } 1135 resp := rec.Body.String() 1136 if !strings.EqualFold(resp, errAuthentication.Error()) { 1137 t.Fatalf("Unexpected error message, expected: %s, found: `%s`", errAuthentication, resp) 1138 } 1139 1140 rec = httptest.NewRecorder() 1141 // Test authorization of web.Upload 1142 content := []byte("temporary file's content") 1143 req, err = http.NewRequest(http.MethodPut, "/minio/upload/bucket/object", nil) 1144 req.Header.Set("Authorization", "Bearer foo-authorization") 1145 req.Header.Set("User-Agent", "Mozilla") 1146 req.Header.Set("Content-Length", strconv.Itoa(len(content))) 1147 req.Header.Set("x-amz-date", "20160814T114029Z") 1148 req.Header.Set("Accept", "*/*") 1149 req.Body = ioutil.NopCloser(bytes.NewReader(content)) 1150 if err != nil { 1151 t.Fatalf("Cannot create upload request, %v", err) 1152 } 1153 apiRouter.ServeHTTP(rec, req) 1154 if rec.Code != http.StatusForbidden { 1155 t.Fatalf("Expected the response status to be 403, but instead found `%d`", rec.Code) 1156 } 1157 resp = rec.Body.String() 1158 if !strings.EqualFold(resp, errAuthentication.Error()) { 1159 t.Fatalf("Unexpected error message, expected: `%s`, found: `%s`", errAuthentication, resp) 1160 } 1161 } 1162 1163 // TestWebObjectLayerFaultyDisks - Test Web RPC responses with faulty disks 1164 func TestWebObjectLayerFaultyDisks(t *testing.T) { 1165 ctx, cancel := context.WithCancel(context.Background()) 1166 defer cancel() 1167 1168 // Prepare Erasure backend 1169 obj, fsDirs, err := prepareErasure16(ctx) 1170 if err != nil { 1171 t.Fatalf("Initialization of object layer failed for Erasure setup: %s", err) 1172 } 1173 // Executing the object layer tests for Erasure. 1174 defer removeRoots(fsDirs) 1175 1176 // initialize the server and obtain the credentials and root. 1177 // credentials are necessary to sign the HTTP request. 1178 err = newTestConfig(globalMinioDefaultRegion, obj) 1179 if err != nil { 1180 t.Fatal("Init Test config failed", err) 1181 } 1182 1183 bucketName := "mybucket" 1184 err = obj.MakeBucketWithLocation(context.Background(), bucketName, BucketOptions{}) 1185 if err != nil { 1186 t.Fatal("Cannot make bucket:", err) 1187 } 1188 1189 // Set faulty disks to Erasure backend 1190 z := obj.(*erasureServerPools) 1191 xl := z.serverPools[0].sets[0] 1192 erasureDisks := xl.getDisks() 1193 z.serverPools[0].erasureDisksMu.Lock() 1194 xl.getDisks = func() []StorageAPI { 1195 for i, d := range erasureDisks { 1196 erasureDisks[i] = newNaughtyDisk(d, nil, errFaultyDisk) 1197 } 1198 return erasureDisks 1199 } 1200 z.serverPools[0].erasureDisksMu.Unlock() 1201 1202 // Initialize web rpc endpoint. 1203 apiRouter := initTestWebRPCEndPoint(obj) 1204 1205 rec := httptest.NewRecorder() 1206 1207 credentials := globalActiveCred 1208 authorization, err := getWebRPCToken(apiRouter, credentials.AccessKey, credentials.SecretKey) 1209 if err != nil { 1210 t.Fatal("Cannot authenticate", err) 1211 } 1212 1213 // Check if web rpc calls return errors with faulty disks. ServerInfo, GenerateAuth, SetAuth, GetAuth are not concerned 1214 // RemoveObject is also not concerned since it always returns success. 1215 webRPCs := []struct { 1216 webRPCName string 1217 ReqArgs interface{} 1218 RepArgs interface{} 1219 }{ 1220 {"MakeBucket", MakeBucketArgs{BucketName: bucketName}, WebGenericRep{}}, 1221 {"ListBuckets", WebGenericArgs{}, ListBucketsRep{}}, 1222 {"ListObjects", ListObjectsArgs{BucketName: bucketName, Prefix: ""}, ListObjectsRep{}}, 1223 {"GetBucketPolicy", GetBucketPolicyArgs{BucketName: bucketName, Prefix: ""}, GetBucketPolicyRep{}}, 1224 {"SetBucketPolicy", SetBucketPolicyWebArgs{BucketName: bucketName, Prefix: "", Policy: "none"}, WebGenericRep{}}, 1225 } 1226 1227 for _, rpcCall := range webRPCs { 1228 args := &rpcCall.ReqArgs 1229 reply := &rpcCall.RepArgs 1230 req, nerr := newTestWebRPCRequest("web."+rpcCall.webRPCName, authorization, args) 1231 if nerr != nil { 1232 t.Fatalf("Test %s: Failed to create HTTP request: <ERROR> %v", rpcCall, nerr) 1233 } 1234 apiRouter.ServeHTTP(rec, req) 1235 if rec.Code != http.StatusOK { 1236 t.Fatalf("Test %s: Expected the response status to be 200, but instead found `%d`", rpcCall, rec.Code) 1237 } 1238 err = getTestWebRPCResponse(rec, &reply) 1239 if err == nil { 1240 t.Errorf("Test %s: Should fail", rpcCall) 1241 } 1242 } 1243 1244 // Test web.StorageInfo 1245 storageInfoRequest := &WebGenericArgs{} 1246 storageInfoReply := &StorageInfoRep{} 1247 req, err := newTestWebRPCRequest("web.StorageInfo", authorization, storageInfoRequest) 1248 if err != nil { 1249 t.Fatalf("Failed to create HTTP request: <ERROR> %v", err) 1250 } 1251 apiRouter.ServeHTTP(rec, req) 1252 if rec.Code != http.StatusOK { 1253 t.Fatalf("Expected the response status to be 200, but instead found `%d`", rec.Code) 1254 } 1255 err = getTestWebRPCResponse(rec, &storageInfoReply) 1256 if err != nil { 1257 t.Fatalf("Failed %v", err) 1258 } 1259 1260 // Test authorization of web.Download 1261 req, err = http.NewRequest(http.MethodGet, "/minio/download/bucket/object?token="+authorization, nil) 1262 if err != nil { 1263 t.Fatalf("Cannot create upload request, %v", err) 1264 } 1265 apiRouter.ServeHTTP(rec, req) 1266 if rec.Code != http.StatusOK { 1267 t.Fatalf("Expected the response status to be 200, but instead found `%d`", rec.Code) 1268 } 1269 1270 // Test authorization of web.Upload 1271 content := []byte("temporary file's content") 1272 req, err = http.NewRequest(http.MethodPut, "/minio/upload/bucket/object", nil) 1273 req.Header.Set("Authorization", "Bearer "+authorization) 1274 req.Header.Set("Content-Length", strconv.Itoa(len(content))) 1275 req.Header.Set("x-amz-date", "20160814T114029Z") 1276 req.Header.Set("Accept", "*/*") 1277 req.Body = ioutil.NopCloser(bytes.NewReader(content)) 1278 if err != nil { 1279 t.Fatalf("Cannot create upload request, %v", err) 1280 } 1281 apiRouter.ServeHTTP(rec, req) 1282 if rec.Code != http.StatusOK { 1283 t.Fatalf("Expected the response status to be 200, but instead found `%d`", rec.Code) 1284 } 1285 }