handler/PUT: Handle signature verification through a custom reader. (#2066)

Change brings in a new signVerifyReader which provides a io.Reader
compatible reader, additionally implements Verify() function.

Verify() function validates the signature present in the incoming
request. This approach is choosen to avoid complexities involved
in using io.Pipe().

Thanks to Krishna for his inputs on this.

Fixes #2058
Fixes #2054
Fixes #2087
This commit is contained in:
Harshavardhana
2016-07-05 01:04:50 -07:00
committed by Anand Babu (AB) Periasamy
parent 0540863663
commit 8a028a9efb
18 changed files with 380 additions and 518 deletions

View File

@@ -779,6 +779,66 @@ func (s *TestSuiteCommon) TestListBuckets(c *C) {
c.Assert(err, IsNil)
}
// This tests validate if PUT handler can successfully detect signature mismatch.
func (s *TestSuiteCommon) TestValidateSignature(c *C) {
// generate a random bucket name.
bucketName := getRandomBucketName()
// HTTP request to create the bucket.
request, err := newTestRequest("PUT", getMakeBucketURL(s.endPoint, bucketName),
0, nil, s.accessKey, s.secretKey)
c.Assert(err, IsNil)
client := http.Client{}
// Execute the HTTP request to create bucket.
response, err := client.Do(request)
c.Assert(err, IsNil)
c.Assert(response.StatusCode, Equals, http.StatusOK)
objName := "test-object"
// Body is on purpose set to nil so that we get payload generated for empty bytes.
// Create new HTTP request with incorrect secretKey to generate an incorrect signature.
secretKey := s.secretKey + "a"
request, err = newTestRequest("PUT", getPutObjectURL(s.endPoint, bucketName, objName), 0, nil, s.accessKey, secretKey)
c.Assert(err, IsNil)
response, err = client.Do(request)
c.Assert(err, IsNil)
verifyError(c, response, "SignatureDoesNotMatch", "The request signature we calculated does not match the signature you provided. Check your key and signing method.", http.StatusForbidden)
}
// This tests validate if PUT handler can successfully detect SHA256 mismatch.
func (s *TestSuiteCommon) TestSHA256Mismatch(c *C) {
// generate a random bucket name.
bucketName := getRandomBucketName()
// HTTP request to create the bucket.
request, err := newTestRequest("PUT", getMakeBucketURL(s.endPoint, bucketName),
0, nil, s.accessKey, s.secretKey)
c.Assert(err, IsNil)
client := http.Client{}
// Execute the HTTP request to create bucket.
response, err := client.Do(request)
c.Assert(err, IsNil)
c.Assert(response.StatusCode, Equals, http.StatusOK)
objName := "test-object"
// Body is on purpose set to nil so that we get payload generated for empty bytes.
// Create new HTTP request with incorrect secretKey to generate an incorrect signature.
secretKey := s.secretKey + "a"
request, err = newTestRequest("PUT", getPutObjectURL(s.endPoint, bucketName, objName), 0, nil, s.accessKey, secretKey)
c.Assert(request.Header.Get("x-amz-content-sha256"), Equals, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
// Set the body to generate signature mismatch.
request.Body = ioutil.NopCloser(bytes.NewReader([]byte("Hello, World")))
c.Assert(err, IsNil)
// execute the HTTP request.
response, err = client.Do(request)
c.Assert(err, IsNil)
verifyError(c, response, "XAmzContentSHA256Mismatch", "The provided 'x-amz-content-sha256' header does not match what was computed.", http.StatusBadRequest)
}
// TestNotBeAbleToCreateObjectInNonexistentBucket - Validates the error response
// on an attempt to upload an object into a non-existent bucket.
func (s *TestSuiteCommon) TestPutObjectLongName(c *C) {
@@ -790,11 +850,11 @@ func (s *TestSuiteCommon) TestPutObjectLongName(c *C) {
c.Assert(err, IsNil)
client := http.Client{}
// execute the HTTP request to create bucket.
// Execute the HTTP request to create bucket.
response, err := client.Do(request)
c.Assert(err, IsNil)
c.Assert(response.StatusCode, Equals, http.StatusOK)
// content for the object to be uploaded.
// Content for the object to be uploaded.
buffer := bytes.NewReader([]byte("hello world"))
// make long object name.
longObjName := fmt.Sprintf("%0255d/%0255d/%0255d", 1, 1, 1)
@@ -808,6 +868,7 @@ func (s *TestSuiteCommon) TestPutObjectLongName(c *C) {
c.Assert(response.StatusCode, Equals, http.StatusOK)
// make long object name.
longObjName = fmt.Sprintf("%0256d", 1)
buffer = bytes.NewReader([]byte("hello world"))
request, err = newTestRequest("PUT", getPutObjectURL(s.endPoint, bucketName, longObjName),
int64(buffer.Len()), buffer, s.accessKey, s.secretKey)
c.Assert(err, IsNil)
@@ -1916,7 +1977,7 @@ func (s *TestSuiteCommon) TestObjectValidMD5(c *C) {
client = http.Client{}
response, err = client.Do(request)
c.Assert(err, IsNil)
// exepcting a successful upload.
// expecting a successful upload.
c.Assert(response.StatusCode, Equals, http.StatusOK)
objectName = "test-2-object"
buffer1 = bytes.NewReader(data)
@@ -1925,7 +1986,8 @@ func (s *TestSuiteCommon) TestObjectValidMD5(c *C) {
int64(buffer1.Len()), buffer1, s.accessKey, s.secretKey)
c.Assert(err, IsNil)
// set Content-Md5 to invalid value.
request.Header.Set("Content-Md5", "WvLTlMrX9NpYDQlEIFlnDw==")
request.Header.Set("Content-Md5", "kvLTlMrX9NpYDQlEIFlnDA==")
// expecting a failure during upload.
client = http.Client{}
response, err = client.Do(request)
c.Assert(err, IsNil)