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. // Set http request for signature.
auth := api.Signature.SetHTTPRequestToVerify(r) auth := api.Signature.SetHTTPRequestToVerify(r)
if isRequestPresignedSignatureV4(r) { if isRequestPresignedSignatureV4(r) {
ok, err := auth.DoesPresignedSignatureMatch() ok, err := auth.DoesPresignedSignatureMatch()
if err != nil { if err != nil {
@ -355,10 +356,10 @@ func (api storageAPI) PostPolicyBucketHandler(w http.ResponseWriter, r *http.Req
var ok bool var ok bool
// Set http request for signature. // Set http request for signature.
api.Signature.SetHTTPRequestToVerify(r) auth := api.Signature.SetHTTPRequestToVerify(r)
// Verify policy signature. // Verify policy signature.
ok, err = api.Signature.DoesPolicySignatureMatch(formValues) ok, err = auth.DoesPolicySignatureMatch(formValues)
if err != nil { if err != nil {
errorIf(err.Trace(), "Unable to verify signature.", nil) errorIf(err.Trace(), "Unable to verify signature.", nil)
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path) 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. // Set http request for signature.
auth := api.Signature.SetHTTPRequestToVerify(r) auth := api.Signature.SetHTTPRequestToVerify(r)
var metadata fs.ObjectMetadata
var err *probe.Error
// For presigned requests verify them right here. // For presigned requests verify them right here.
if isRequestPresignedSignatureV4(r) { if isRequestPresignedSignatureV4(r) {
ok, err := auth.DoesPresignedSignatureMatch() var ok bool
ok, err = auth.DoesPresignedSignatureMatch()
if err != nil { if err != nil {
errorIf(err.Trace(r.URL.String()), "Presigned signature verification failed.", nil) errorIf(err.Trace(r.URL.String()), "Presigned signature verification failed.", nil)
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path) 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) writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
return 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 { if err != nil {
errorIf(err.Trace(), "CreateObject failed.", nil) errorIf(err.Trace(), "CreateObject failed.", nil)
switch err.ToGoError().(type) { switch err.ToGoError().(type) {
@ -573,21 +577,21 @@ func (api storageAPI) PutObjectPartHandler(w http.ResponseWriter, r *http.Reques
uploadID := r.URL.Query().Get("uploadId") uploadID := r.URL.Query().Get("uploadId")
partIDString := r.URL.Query().Get("partNumber") partIDString := r.URL.Query().Get("partNumber")
var partID int partID, e := strconv.Atoi(partIDString)
{ if e != nil {
var err error writeErrorResponse(w, r, InvalidPart, r.URL.Path)
partID, err = strconv.Atoi(partIDString) return
if err != nil {
writeErrorResponse(w, r, InvalidPart, r.URL.Path)
return
}
} }
// Set http request for signature. // Set http request for signature.
auth := api.Signature.SetHTTPRequestToVerify(r) auth := api.Signature.SetHTTPRequestToVerify(r)
var partMD5 string
var err *probe.Error
// For presigned requests verify right here. // For presigned requests verify right here.
if isRequestPresignedSignatureV4(r) { if isRequestPresignedSignatureV4(r) {
ok, err := auth.DoesPresignedSignatureMatch() var ok bool
ok, err = auth.DoesPresignedSignatureMatch()
if err != nil { if err != nil {
errorIf(err.Trace(r.URL.String()), "Presigned signature verification failed.", nil) errorIf(err.Trace(r.URL.String()), "Presigned signature verification failed.", nil)
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path) 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) writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
return return
} }
// Signature verified, set this to nil payload verification partMD5, err = api.Filesystem.CreateObjectPart(bucket, object, uploadID, md5, partID, size, r.Body, nil)
// not necessary. } else {
auth = nil 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 { if err != nil {
errorIf(err.Trace(), "CreateObjectPart failed.", nil) errorIf(err.Trace(), "CreateObjectPart failed.", nil)
switch err.ToGoError().(type) { switch err.ToGoError().(type) {
@ -623,8 +625,8 @@ func (api storageAPI) PutObjectPartHandler(w http.ResponseWriter, r *http.Reques
} }
return return
} }
if calculatedMD5 != "" { if partMD5 != "" {
w.Header().Set("ETag", "\""+calculatedMD5+"\"") w.Header().Set("ETag", "\""+partMD5+"\"")
} }
writeSuccessResponse(w, nil) 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. // Set http request for signature.
auth := api.Signature.SetHTTPRequestToVerify(r) auth := api.Signature.SetHTTPRequestToVerify(r)
var metadata fs.ObjectMetadata
var err *probe.Error
// For presigned requests verify right here. // For presigned requests verify right here.
if isRequestPresignedSignatureV4(r) { if isRequestPresignedSignatureV4(r) {
ok, err := auth.DoesPresignedSignatureMatch() var ok bool
ok, err = auth.DoesPresignedSignatureMatch()
if err != nil { if err != nil {
errorIf(err.Trace(r.URL.String()), "Presigned signature verification failed.", nil) errorIf(err.Trace(r.URL.String()), "Presigned signature verification failed.", nil)
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path) 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) writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
return 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 { if err != nil {
errorIf(err.Trace(), "CompleteMultipartUpload failed.", nil) errorIf(err.Trace(), "CompleteMultipartUpload failed.", nil)
switch err.ToGoError().(type) { 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. // 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'. // Do not set http request if its 'nil'.
if r == nil { if r == nil {
return s return *s
} }
s.httpRequest = r s.httpRequest = r
return s return *s
} }
// getCanonicalHeaders generate a list of request headers with their values // getCanonicalHeaders generate a list of request headers with their values