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.
master
Harshavardhana 9 years ago
parent b37fbabe7f
commit 17d145df3a
  1. 5
      bucket-handlers.go
  2. 61
      object-handlers.go
  3. 6
      pkg/s3/signature4/v4-signature.go

@ -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)

@ -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. // Create object.
metadata, err := api.Filesystem.CreateObject(bucket, object, md5, size, r.Body, auth) 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
partID, err = strconv.Atoi(partIDString)
if err != nil {
writeErrorResponse(w, r, InvalidPart, r.URL.Path) writeErrorResponse(w, r, InvalidPart, r.URL.Path)
return 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 {
// Extract object resources.
objectResourcesMetadata := getObjectResources(r.URL.Query())
// Complete multipart upload. // Complete multipart upload.
metadata, err := api.Filesystem.CompleteMultipartUpload(bucket, object, objectResourcesMetadata.UploadID, r.Body, api.Signature) metadata, err = api.Filesystem.CompleteMultipartUpload(bucket, object, objectResourcesMetadata.UploadID, r.Body, &auth)
}
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) {

@ -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

Loading…
Cancel
Save