diff --git a/cmd/object-handlers_test.go b/cmd/object-handlers_test.go index f046a161e..c6a3d232e 100644 --- a/cmd/object-handlers_test.go +++ b/cmd/object-handlers_test.go @@ -2032,61 +2032,3 @@ func testAPIListObjectPartsHandlerV2(obj ObjectLayer, instanceType, bucketName s signatureMismatchErr.Code, errXML.Code) } } - -// TestAPIListObjectPartsHandler - Tests validate the response of ListObjectParts HTTP handler -// when signature type of the HTTP request is `anonynous/unsigned`. -func TestAPIListObjectPartsHandlerUnknown(t *testing.T) { - ExecObjectLayerAPITest(t, testAPIListObjectPartsHandlerUnknown, - []string{"PutObjectPart", "NewMultipart", "ListObjectParts"}) -} - -func testAPIListObjectPartsHandlerUnknown(obj ObjectLayer, instanceType, bucketName string, apiRouter http.Handler, - credentials credential, t *testing.T) { - testObject := "testobject" - rec := httptest.NewRecorder() - req, err := newTestSignedRequestV4("POST", getNewMultipartURL("", bucketName, testObject), - 0, nil, credentials.AccessKeyID, credentials.SecretAccessKey) - if err != nil { - t.Fatalf("[%s] - Failed to create a signed request to initiate multipart upload for %s/%s: %v", - instanceType, bucketName, testObject, err) - } - apiRouter.ServeHTTP(rec, req) - - // Get uploadID of the mulitpart upload initiated. - var mpartResp InitiateMultipartUploadResponse - mpartRespBytes, err := ioutil.ReadAll(rec.Result().Body) - if err != nil { - t.Fatalf("[%s] Failed to read NewMultipartUpload response %v", instanceType, err) - - } - err = xml.Unmarshal(mpartRespBytes, &mpartResp) - if err != nil { - t.Fatalf("[%s] Failed to unmarshal NewMultipartUpload response %v", instanceType, err) - } - accessDeniedErr := getAPIError(ErrAccessDenied) - unKnownRec := httptest.NewRecorder() - unKnownReq, aErr := newTestRequest("GET", - getListMultipartURLWithParams("", bucketName, testObject, mpartResp.UploadID, "", "", ""), - 0, nil) - if aErr != nil { - t.Fatalf("Test %d %s Failed to create an unKnownymous request to list multipart of an upload for %s/%s: %v", - 1, instanceType, bucketName, testObject, aErr) - } - unKnownReq.Header.Set("Authorization", "nothingElse") - apiRouter.ServeHTTP(unKnownRec, unKnownReq) - unKnownErrBytes, err := ioutil.ReadAll(unKnownRec.Result().Body) - if err != nil { - t.Fatalf("Test %d %s Failed to read error response from list object parts request %s/%s: %v", - 1, instanceType, bucketName, testObject, err) - } - var unKnownErrXML APIErrorResponse - err = xml.Unmarshal(unKnownErrBytes, &unKnownErrXML) - if err != nil { - t.Fatalf("Test %d %s Failed to unmarshal error response from list object parts request %s/%s: %v", - 1, instanceType, bucketName, testObject, err) - } - if accessDeniedErr.Code != unKnownErrXML.Code { - t.Errorf("Test %d %s expected to fail with error %s, but received %s", 1, instanceType, - accessDeniedErr.Code, unKnownErrXML.Code) - } -} diff --git a/cmd/test-utils_test.go b/cmd/test-utils_test.go index cbb151844..5732cef5a 100644 --- a/cmd/test-utils_test.go +++ b/cmd/test-utils_test.go @@ -1461,20 +1461,27 @@ func initAPIHandlerTest(obj ObjectLayer, endPoints []string) (bucketName, rootPa return bucketName, rootPath, apiRouter, nil } -// ExecObjectLayerAPIAnonTest - Helper function to validate object Layer API handler response for anonymous/unsigned HTTP request. +// ExecObjectLayerAPIAnonTest - Helper function to validate object Layer API handler +// response for anonymous/unsigned and unknown signature type HTTP request. + // Here is the brief description of some of the arguments to the function below. // apiRouter - http.Handler with the relevant API endPoint (API endPoint under test) registered. // anonReq - unsigned *http.Request to invoke the handler's response for anonymous requests. // policyFunc - function to return bucketPolicy statement which would permit the anonymous request to be served. // The test works in 2 steps, here is the description of the steps. // STEP 1: Call the handler with the unsigned HTTP request (anonReq), assert for the `ErrAccessDenied` error response. -// STEP 2: Set the policy to allow the unsigned request, use the policyFunc to obtain the relevant statement and call the handler again to verify its success. +// STEP 2: Set the policy to allow the unsigned request, use the policyFunc to obtain the relevant statement and call +// the handler again to verify its success. func ExecObjectLayerAPIAnonTest(t *testing.T, testName, bucketName, objectName, instanceType string, apiRouter http.Handler, anonReq *http.Request, policyFunc func(string, string) policyStatement) { + + anonTestStr := "Anonymous HTTP request test" + unknownSignTestStr := "Unknown HTTP signature test" + // simple function which ends the test by printing the common message which gives the context of the test // and then followed by the the actual error message. - failTest := func(failMsg string) { - t.Fatalf("Minio %s: Anonymous HTTP request test Fail for \"%s\": \n %s.", instanceType, testName, failMsg) + failTest := func(testType, failMsg string) { + t.Fatalf("Minio %s: %s fail for \"%s\": \n %s.", instanceType, testType, testName, failMsg) } // httptest Recorder to capture all the response by the http handler. rec := httptest.NewRecorder() @@ -1482,12 +1489,13 @@ func ExecObjectLayerAPIAnonTest(t *testing.T, testName, bucketName, objectName, // If the body is read in the handler the same request cannot be made use of. buf, err := ioutil.ReadAll(anonReq.Body) if err != nil { - failTest(err.Error()) + failTest(anonTestStr, err.Error()) } // creating 2 read closer (to set as request body) from the body content. readerOne := ioutil.NopCloser(bytes.NewBuffer(buf)) readerTwo := ioutil.NopCloser(bytes.NewBuffer(buf)) + readerThree := ioutil.NopCloser(bytes.NewBuffer(buf)) anonReq.Body = readerOne @@ -1497,7 +1505,7 @@ func ExecObjectLayerAPIAnonTest(t *testing.T, testName, bucketName, objectName, // expected error response when the unsigned HTTP request is not permitted. accesDeniedHTTPStatus := getAPIError(ErrAccessDenied).HTTPStatusCode if rec.Code != accesDeniedHTTPStatus { - failTest(fmt.Sprintf("Object API Nil Test expected to fail with %d, but failed with %d.", accesDeniedHTTPStatus, rec.Code)) + failTest(anonTestStr, fmt.Sprintf("Object API Nil Test expected to fail with %d, but failed with %d.", accesDeniedHTTPStatus, rec.Code)) } // expected error response in bytes when objectLayer is not initialized, or set to `nil`. @@ -1508,11 +1516,11 @@ func ExecObjectLayerAPIAnonTest(t *testing.T, testName, bucketName, objectName, // read the response body. actualContent, err := ioutil.ReadAll(rec.Body) if err != nil { - failTest(fmt.Sprintf("Failed parsing response body: %v", err)) + failTest(anonTestStr, fmt.Sprintf("Failed parsing response body: %v", err)) } // verify whether actual error response (from the response body), matches the expected error response. if !bytes.Equal(expectedErrResponse, actualContent) { - failTest("error response content differs from expected value") + failTest(anonTestStr, "error response content differs from expected value") } } // Set write only policy on bucket to allow anonymous HTTP request for the operation under test. @@ -1544,9 +1552,37 @@ func ExecObjectLayerAPIAnonTest(t *testing.T, testName, bucketName, objectName, // compare the HTTP response status code with the expected one. if rec.Code != expectedHTTPStatus { - failTest(fmt.Sprintf("Expected the anonymous HTTP request to be served after the policy changes\n,Expected response HTTP status code to be %d, got %d.", + failTest(anonTestStr, fmt.Sprintf("Expected the anonymous HTTP request to be served after the policy changes\n,Expected response HTTP status code to be %d, got %d.", expectedHTTPStatus, rec.Code)) } + + // test for unknown auth case. + anonReq.Body = readerThree + // Setting the `Authorization` header to a random value so that the signature falls into unknown auth case. + anonReq.Header.Set("Authorization", "nothingElse") + // initialize new response recorder. + rec = httptest.NewRecorder() + // call the handler using the HTTP Request. + apiRouter.ServeHTTP(rec, anonReq) + // verify the response body for `ErrAccessDenied` message =. + if anonReq.Method != "HEAD" { + // read the response body. + actualContent, err := ioutil.ReadAll(rec.Body) + if err != nil { + failTest(unknownSignTestStr, fmt.Sprintf("Failed parsing response body: %v", err)) + } + // verify whether actual error response (from the response body), matches the expected error response. + if !bytes.Equal(expectedErrResponse, actualContent) { + fmt.Println(string(expectedErrResponse)) + fmt.Println(string(actualContent)) + failTest(unknownSignTestStr, "error response content differs from expected value") + } + } + + if rec.Code != accesDeniedHTTPStatus { + failTest(unknownSignTestStr, fmt.Sprintf("Object API Unknow auth test for \"%s\", expected to fail with %d, but failed with %d.", testName, accesDeniedHTTPStatus, rec.Code)) + } + } // ExecObjectLayerAPINilTest - Sets the object layer to `nil`, and calls rhe registered object layer API endpoint, and assert the error response.