signature: Fix signature handling of parallel requests.

Signature struct should be immutable, this fixes an issue
with AWS cli not being able to do multipart put operations.
This commit is contained in:
Harshavardhana 2016-03-02 11:22:58 -08:00
parent b37fbabe7f
commit 17d145df3a
3 changed files with 42 additions and 34 deletions

View file

@ -242,6 +242,7 @@ func (api storageAPI) PutBucketHandler(w http.ResponseWriter, r *http.Request) {
// Set http request for signature.
auth := api.Signature.SetHTTPRequestToVerify(r)
if isRequestPresignedSignatureV4(r) {
ok, err := auth.DoesPresignedSignatureMatch()
if err != nil {
@ -355,10 +356,10 @@ func (api storageAPI) PostPolicyBucketHandler(w http.ResponseWriter, r *http.Req
var ok bool
// Set http request for signature.
api.Signature.SetHTTPRequestToVerify(r)
auth := api.Signature.SetHTTPRequestToVerify(r)
// Verify policy signature.
ok, err = api.Signature.DoesPolicySignatureMatch(formValues)
ok, err = auth.DoesPolicySignatureMatch(formValues)
if err != nil {
errorIf(err.Trace(), "Unable to verify signature.", nil)
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)

View file

@ -441,9 +441,12 @@ func (api storageAPI) PutObjectHandler(w http.ResponseWriter, r *http.Request) {
// Set http request for signature.
auth := api.Signature.SetHTTPRequestToVerify(r)
var metadata fs.ObjectMetadata
var err *probe.Error
// For presigned requests verify them right here.
if isRequestPresignedSignatureV4(r) {
ok, err := auth.DoesPresignedSignatureMatch()
var ok bool
ok, err = auth.DoesPresignedSignatureMatch()
if err != nil {
errorIf(err.Trace(r.URL.String()), "Presigned signature verification failed.", nil)
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
@ -453,11 +456,12 @@ func (api storageAPI) PutObjectHandler(w http.ResponseWriter, r *http.Request) {
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
return
}
auth = nil
// Create presigned object.
metadata, err = api.Filesystem.CreateObject(bucket, object, md5, size, r.Body, nil)
} else {
// Create object.
metadata, err = api.Filesystem.CreateObject(bucket, object, md5, size, r.Body, &auth)
}
// Create object.
metadata, err := api.Filesystem.CreateObject(bucket, object, md5, size, r.Body, auth)
if err != nil {
errorIf(err.Trace(), "CreateObject failed.", nil)
switch err.ToGoError().(type) {
@ -573,21 +577,21 @@ func (api storageAPI) PutObjectPartHandler(w http.ResponseWriter, r *http.Reques
uploadID := r.URL.Query().Get("uploadId")
partIDString := r.URL.Query().Get("partNumber")
var partID int
{
var err error
partID, err = strconv.Atoi(partIDString)
if err != nil {
writeErrorResponse(w, r, InvalidPart, r.URL.Path)
return
}
partID, e := strconv.Atoi(partIDString)
if e != nil {
writeErrorResponse(w, r, InvalidPart, r.URL.Path)
return
}
// Set http request for signature.
auth := api.Signature.SetHTTPRequestToVerify(r)
var partMD5 string
var err *probe.Error
// For presigned requests verify right here.
if isRequestPresignedSignatureV4(r) {
ok, err := auth.DoesPresignedSignatureMatch()
var ok bool
ok, err = auth.DoesPresignedSignatureMatch()
if err != nil {
errorIf(err.Trace(r.URL.String()), "Presigned signature verification failed.", nil)
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
@ -597,12 +601,10 @@ func (api storageAPI) PutObjectPartHandler(w http.ResponseWriter, r *http.Reques
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
return
}
// Signature verified, set this to nil payload verification
// not necessary.
auth = nil
partMD5, err = api.Filesystem.CreateObjectPart(bucket, object, uploadID, md5, partID, size, r.Body, nil)
} else {
partMD5, err = api.Filesystem.CreateObjectPart(bucket, object, uploadID, md5, partID, size, r.Body, &auth)
}
calculatedMD5, err := api.Filesystem.CreateObjectPart(bucket, object, uploadID, md5, partID, size, r.Body, auth)
if err != nil {
errorIf(err.Trace(), "CreateObjectPart failed.", nil)
switch err.ToGoError().(type) {
@ -623,8 +625,8 @@ func (api storageAPI) PutObjectPartHandler(w http.ResponseWriter, r *http.Reques
}
return
}
if calculatedMD5 != "" {
w.Header().Set("ETag", "\""+calculatedMD5+"\"")
if partMD5 != "" {
w.Header().Set("ETag", "\""+partMD5+"\"")
}
writeSuccessResponse(w, nil)
}
@ -741,11 +743,18 @@ func (api storageAPI) CompleteMultipartUploadHandler(w http.ResponseWriter, r *h
}
}
// Extract object resources.
objectResourcesMetadata := getObjectResources(r.URL.Query())
// Set http request for signature.
auth := api.Signature.SetHTTPRequestToVerify(r)
var metadata fs.ObjectMetadata
var err *probe.Error
// For presigned requests verify right here.
if isRequestPresignedSignatureV4(r) {
ok, err := auth.DoesPresignedSignatureMatch()
var ok bool
ok, err = auth.DoesPresignedSignatureMatch()
if err != nil {
errorIf(err.Trace(r.URL.String()), "Presigned signature verification failed.", nil)
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
@ -755,14 +764,12 @@ func (api storageAPI) CompleteMultipartUploadHandler(w http.ResponseWriter, r *h
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
return
}
auth = nil
// Complete multipart upload presigned.
metadata, err = api.Filesystem.CompleteMultipartUpload(bucket, object, objectResourcesMetadata.UploadID, r.Body, nil)
} else {
// Complete multipart upload.
metadata, err = api.Filesystem.CompleteMultipartUpload(bucket, object, objectResourcesMetadata.UploadID, r.Body, &auth)
}
// Extract object resources.
objectResourcesMetadata := getObjectResources(r.URL.Query())
// Complete multipart upload.
metadata, err := api.Filesystem.CompleteMultipartUpload(bucket, object, objectResourcesMetadata.UploadID, r.Body, api.Signature)
if err != nil {
errorIf(err.Trace(), "CompleteMultipartUpload failed.", nil)
switch err.ToGoError().(type) {

View file

@ -74,13 +74,13 @@ func New(accessKeyID, secretAccessKey, region string) (*Sign, *probe.Error) {
}
// SetHTTPRequestToVerify - sets the http request which needs to be verified.
func (s *Sign) SetHTTPRequestToVerify(r *http.Request) *Sign {
func (s *Sign) SetHTTPRequestToVerify(r *http.Request) Sign {
// Do not set http request if its 'nil'.
if r == nil {
return s
return *s
}
s.httpRequest = r
return s
return *s
}
// getCanonicalHeaders generate a list of request headers with their values