fix: avoid double body reads in SelectObject call (#9638)

Bonus fix handle encryption headers in response
properly for both notification and response to
the client.
master
Harshavardhana 5 years ago committed by GitHub
parent 3202f78f0f
commit d31eaddba3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 40
      cmd/object-handlers.go

@ -173,11 +173,13 @@ func (api objectAPIHandlers) SelectObjectContentHandler(w http.ResponseWriter, r
if api.CacheAPI() != nil { if api.CacheAPI() != nil {
getObjectNInfo = api.CacheAPI().GetObjectNInfo getObjectNInfo = api.CacheAPI().GetObjectNInfo
} }
getObject := func(offset, length int64) (rc io.ReadCloser, err error) { getObject := func(offset, length int64) (rc io.ReadCloser, err error) {
isSuffixLength := false isSuffixLength := false
if offset < 0 { if offset < 0 {
isSuffixLength = true isSuffixLength = true
} }
rs := &HTTPRangeSpec{ rs := &HTTPRangeSpec{
IsSuffixLength: isSuffixLength, IsSuffixLength: isSuffixLength,
Start: offset, Start: offset,
@ -193,6 +195,20 @@ func (api objectAPIHandlers) SelectObjectContentHandler(w http.ResponseWriter, r
return return
} }
// filter object lock metadata if permission does not permit
getRetPerms := checkRequestAuthType(ctx, r, policy.GetObjectRetentionAction, bucket, object)
legalHoldPerms := checkRequestAuthType(ctx, r, policy.GetObjectLegalHoldAction, bucket, object)
// filter object lock metadata if permission does not permit
objInfo.UserDefined = objectlock.FilterObjectLockMetadata(objInfo.UserDefined, getRetPerms != ErrNone, legalHoldPerms != ErrNone)
if objectAPI.IsEncryptionSupported() {
if _, err = DecryptObjectInfo(&objInfo, r.Header); err != nil {
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r))
return
}
}
s3Select, err := s3select.NewS3Select(r.Body) s3Select, err := s3select.NewS3Select(r.Body)
if err != nil { if err != nil {
if serr, ok := err.(s3select.SelectError); ok { if serr, ok := err.(s3select.SelectError); ok {
@ -212,12 +228,6 @@ func (api objectAPIHandlers) SelectObjectContentHandler(w http.ResponseWriter, r
return return
} }
getRetPerms := checkRequestAuthType(ctx, r, policy.GetObjectRetentionAction, bucket, object)
legalHoldPerms := checkRequestAuthType(ctx, r, policy.GetObjectLegalHoldAction, bucket, object)
// filter object lock metadata if permission does not permit
objInfo.UserDefined = objectlock.FilterObjectLockMetadata(objInfo.UserDefined, getRetPerms != ErrNone, legalHoldPerms != ErrNone)
if err = s3Select.Open(getObject); err != nil { if err = s3Select.Open(getObject); err != nil {
if serr, ok := err.(s3select.SelectError); ok { if serr, ok := err.(s3select.SelectError); ok {
encodedErrorResponse := encodeResponse(APIErrorResponse{ encodedErrorResponse := encodeResponse(APIErrorResponse{
@ -236,6 +246,24 @@ func (api objectAPIHandlers) SelectObjectContentHandler(w http.ResponseWriter, r
return return
} }
// Set encryption response headers
if objectAPI.IsEncryptionSupported() {
if crypto.IsEncrypted(objInfo.UserDefined) {
switch {
case crypto.S3.IsEncrypted(objInfo.UserDefined):
w.Header().Set(crypto.SSEHeader, crypto.SSEAlgorithmAES256)
case crypto.SSEC.IsEncrypted(objInfo.UserDefined):
// Validate the SSE-C Key set in the header.
if _, err = crypto.SSEC.UnsealObjectKey(r.Header, objInfo.UserDefined, bucket, object); err != nil {
writeErrorResponseHeadersOnly(w, toAPIError(ctx, err))
return
}
w.Header().Set(crypto.SSECAlgorithm, r.Header.Get(crypto.SSECAlgorithm))
w.Header().Set(crypto.SSECKeyMD5, r.Header.Get(crypto.SSECKeyMD5))
}
}
}
s3Select.Evaluate(w) s3Select.Evaluate(w)
s3Select.Close() s3Select.Close()

Loading…
Cancel
Save