mirror of
https://github.com/minio/minio.git
synced 2024-12-24 06:05:55 -05:00
Add padding to compressed+encrypted files (#15282)
Add up to 256 bytes of padding for compressed+encrypted files. This will obscure the obvious cases of extremely compressible content and leave a similar output size for a very wide variety of inputs. This does *not* mean the compression ratio doesn't leak information about the content, but the outcome space is much smaller, so often *less* information is leaked.
This commit is contained in:
parent
697c9973a7
commit
0149382cdc
@ -865,7 +865,7 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := crypto.IsRequested(r.Header); !objectAPI.IsEncryptionSupported() && ok {
|
if crypto.Requested(r.Header) && !objectAPI.IsEncryptionSupported() {
|
||||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL)
|
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -1041,7 +1041,7 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if objectAPI.IsEncryptionSupported() {
|
if objectAPI.IsEncryptionSupported() {
|
||||||
if _, ok := crypto.IsRequested(formValues); ok && !HasSuffix(object, SlashSeparator) { // handle SSE requests
|
if crypto.Requested(formValues) && !HasSuffix(object, SlashSeparator) { // handle SSE requests
|
||||||
if crypto.SSECopy.IsRequested(r.Header) {
|
if crypto.SSECopy.IsRequested(r.Header) {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, errInvalidEncryptionParameters), r.URL)
|
writeErrorResponse(ctx, w, toAPIError(ctx, errInvalidEncryptionParameters), r.URL)
|
||||||
return
|
return
|
||||||
|
@ -976,14 +976,7 @@ func (er erasureObjects) putObject(ctx context.Context, bucket string, object st
|
|||||||
switch size := data.Size(); {
|
switch size := data.Size(); {
|
||||||
case size == 0:
|
case size == 0:
|
||||||
buffer = make([]byte, 1) // Allocate atleast a byte to reach EOF
|
buffer = make([]byte, 1) // Allocate atleast a byte to reach EOF
|
||||||
case size == -1:
|
case size >= fi.Erasure.BlockSize || size == -1:
|
||||||
if size := data.ActualSize(); size > 0 && size < fi.Erasure.BlockSize {
|
|
||||||
buffer = make([]byte, data.ActualSize()+256, data.ActualSize()*2+512)
|
|
||||||
} else {
|
|
||||||
buffer = er.bp.Get()
|
|
||||||
defer er.bp.Put(buffer)
|
|
||||||
}
|
|
||||||
case size >= fi.Erasure.BlockSize:
|
|
||||||
buffer = er.bp.Get()
|
buffer = er.bp.Get()
|
||||||
defer er.bp.Put(buffer)
|
defer er.bp.Put(buffer)
|
||||||
case size < fi.Erasure.BlockSize:
|
case size < fi.Erasure.BlockSize:
|
||||||
|
@ -74,6 +74,10 @@ const (
|
|||||||
compReadAheadBuffers = 5
|
compReadAheadBuffers = 5
|
||||||
// Size of each buffer.
|
// Size of each buffer.
|
||||||
compReadAheadBufSize = 1 << 20
|
compReadAheadBufSize = 1 << 20
|
||||||
|
// Pad Encrypted+Compressed files to a multiple of this.
|
||||||
|
compPadEncrypted = 256
|
||||||
|
// Disable compressed file indices below this size
|
||||||
|
compMinIndexSize = 8 << 20
|
||||||
)
|
)
|
||||||
|
|
||||||
// isMinioBucket returns true if given bucket is a MinIO internal
|
// isMinioBucket returns true if given bucket is a MinIO internal
|
||||||
@ -436,8 +440,7 @@ func isCompressible(header http.Header, object string) bool {
|
|||||||
cfg := globalCompressConfig
|
cfg := globalCompressConfig
|
||||||
globalCompressConfigMu.Unlock()
|
globalCompressConfigMu.Unlock()
|
||||||
|
|
||||||
_, ok := crypto.IsRequested(header)
|
if !cfg.Enabled || (crypto.Requested(header) && !cfg.AllowEncrypted) || excludeForCompression(header, object, cfg) {
|
||||||
if !cfg.Enabled || (ok && !cfg.AllowEncrypted) || excludeForCompression(header, object, cfg) {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -985,10 +988,17 @@ func init() {
|
|||||||
// input 'on' is always recommended such that this function works
|
// input 'on' is always recommended such that this function works
|
||||||
// properly, because we do not wish to create an object even if
|
// properly, because we do not wish to create an object even if
|
||||||
// client closed the stream prematurely.
|
// client closed the stream prematurely.
|
||||||
func newS2CompressReader(r io.Reader, on int64) (rc io.ReadCloser, idx func() []byte) {
|
func newS2CompressReader(r io.Reader, on int64, encrypted bool) (rc io.ReadCloser, idx func() []byte) {
|
||||||
pr, pw := io.Pipe()
|
pr, pw := io.Pipe()
|
||||||
// Copy input to compressor
|
// Copy input to compressor
|
||||||
comp := s2.NewWriter(pw, compressOpts...)
|
opts := compressOpts
|
||||||
|
if encrypted {
|
||||||
|
// The values used for padding are not a security concern,
|
||||||
|
// but we choose pseudo-random numbers instead of just zeros.
|
||||||
|
rng := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
|
opts = append([]s2.WriterOption{s2.WriterPadding(compPadEncrypted), s2.WriterPaddingSrc(rng)}, compressOpts...)
|
||||||
|
}
|
||||||
|
comp := s2.NewWriter(pw, opts...)
|
||||||
indexCh := make(chan []byte, 1)
|
indexCh := make(chan []byte, 1)
|
||||||
go func() {
|
go func() {
|
||||||
defer close(indexCh)
|
defer close(indexCh)
|
||||||
@ -1006,8 +1016,8 @@ func newS2CompressReader(r io.Reader, on int64) (rc io.ReadCloser, idx func() []
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Close the stream.
|
// Close the stream.
|
||||||
// If more than 8MB was written, generate index.
|
// If more than compMinIndexSize was written, generate index.
|
||||||
if cn > 8<<20 {
|
if cn > compMinIndexSize {
|
||||||
idx, err := comp.CloseIndex()
|
idx, err := comp.CloseIndex()
|
||||||
idx = s2.RemoveIndexHeaders(idx)
|
idx = s2.RemoveIndexHeaders(idx)
|
||||||
indexCh <- idx
|
indexCh <- idx
|
||||||
@ -1048,7 +1058,7 @@ func compressSelfTest() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const skip = 2<<20 + 511
|
const skip = 2<<20 + 511
|
||||||
r, _ := newS2CompressReader(bytes.NewBuffer(data), int64(len(data)))
|
r, _ := newS2CompressReader(bytes.NewBuffer(data), int64(len(data)), true)
|
||||||
b, err := io.ReadAll(r)
|
b, err := io.ReadAll(r)
|
||||||
failOnErr(err)
|
failOnErr(err)
|
||||||
failOnErr(r.Close())
|
failOnErr(r.Close())
|
||||||
|
@ -624,7 +624,7 @@ func TestS2CompressReader(t *testing.T) {
|
|||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
buf := make([]byte, 100) // make small buffer to ensure multiple reads are required for large case
|
buf := make([]byte, 100) // make small buffer to ensure multiple reads are required for large case
|
||||||
|
|
||||||
r, idxCB := newS2CompressReader(bytes.NewReader(tt.data), int64(len(tt.data)))
|
r, idxCB := newS2CompressReader(bytes.NewReader(tt.data), int64(len(tt.data)), false)
|
||||||
defer r.Close()
|
defer r.Close()
|
||||||
|
|
||||||
var rdrBuf bytes.Buffer
|
var rdrBuf bytes.Buffer
|
||||||
|
@ -119,7 +119,7 @@ func (api objectAPIHandlers) SelectObjectContentHandler(w http.ResponseWriter, r
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := crypto.IsRequested(r.Header); ok && !objectAPI.IsEncryptionSupported() {
|
if crypto.Requested(r.Header) && !objectAPI.IsEncryptionSupported() {
|
||||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrBadRequest), r.URL)
|
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrBadRequest), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -330,7 +330,7 @@ func (api objectAPIHandlers) getObjectHandler(ctx context.Context, objectAPI Obj
|
|||||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrBadRequest), r.URL)
|
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrBadRequest), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if _, ok := crypto.IsRequested(r.Header); !objectAPI.IsEncryptionSupported() && ok {
|
if crypto.Requested(r.Header) && !objectAPI.IsEncryptionSupported() {
|
||||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrBadRequest), r.URL)
|
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrBadRequest), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -611,7 +611,7 @@ func (api objectAPIHandlers) headObjectHandler(ctx context.Context, objectAPI Ob
|
|||||||
writeErrorResponseHeadersOnly(w, errorCodes.ToAPIErr(ErrBadRequest))
|
writeErrorResponseHeadersOnly(w, errorCodes.ToAPIErr(ErrBadRequest))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if _, ok := crypto.IsRequested(r.Header); !objectAPI.IsEncryptionSupported() && ok {
|
if crypto.Requested(r.Header) && !objectAPI.IsEncryptionSupported() {
|
||||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrBadRequest), r.URL)
|
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrBadRequest), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -951,7 +951,7 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := crypto.IsRequested(r.Header); ok {
|
if crypto.Requested(r.Header) {
|
||||||
if globalIsGateway {
|
if globalIsGateway {
|
||||||
if crypto.SSEC.IsRequested(r.Header) && !objectAPI.IsEncryptionSupported() {
|
if crypto.SSEC.IsRequested(r.Header) && !objectAPI.IsEncryptionSupported() {
|
||||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL)
|
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL)
|
||||||
@ -1151,7 +1151,7 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if either the source is encrypted or the destination will be encrypted.
|
// Check if either the source is encrypted or the destination will be encrypted.
|
||||||
_, objectEncryption := crypto.IsRequested(r.Header)
|
objectEncryption := crypto.Requested(r.Header)
|
||||||
objectEncryption = objectEncryption || crypto.IsSourceEncrypted(srcInfo.UserDefined)
|
objectEncryption = objectEncryption || crypto.IsSourceEncrypted(srcInfo.UserDefined)
|
||||||
|
|
||||||
var compressMetadata map[string]string
|
var compressMetadata map[string]string
|
||||||
@ -1168,7 +1168,8 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re
|
|||||||
compressMetadata[ReservedMetadataPrefix+"actual-size"] = strconv.FormatInt(actualSize, 10)
|
compressMetadata[ReservedMetadataPrefix+"actual-size"] = strconv.FormatInt(actualSize, 10)
|
||||||
|
|
||||||
reader = etag.NewReader(reader, nil)
|
reader = etag.NewReader(reader, nil)
|
||||||
s2c, cb := newS2CompressReader(reader, actualSize)
|
wantEncryption := objectAPI.IsEncryptionSupported() && crypto.Requested(r.Header)
|
||||||
|
s2c, cb := newS2CompressReader(reader, actualSize, wantEncryption)
|
||||||
dstOpts.IndexCB = cb
|
dstOpts.IndexCB = cb
|
||||||
defer s2c.Close()
|
defer s2c.Close()
|
||||||
reader = etag.Wrap(s2c, reader)
|
reader = etag.Wrap(s2c, reader)
|
||||||
@ -1573,7 +1574,7 @@ func (api objectAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Req
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := crypto.IsRequested(r.Header); ok {
|
if crypto.Requested(r.Header) {
|
||||||
if globalIsGateway {
|
if globalIsGateway {
|
||||||
if crypto.SSEC.IsRequested(r.Header) && !objectAPI.IsEncryptionSupported() {
|
if crypto.SSEC.IsRequested(r.Header) && !objectAPI.IsEncryptionSupported() {
|
||||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL)
|
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL)
|
||||||
@ -1737,7 +1738,8 @@ func (api objectAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Req
|
|||||||
|
|
||||||
// Set compression metrics.
|
// Set compression metrics.
|
||||||
var s2c io.ReadCloser
|
var s2c io.ReadCloser
|
||||||
s2c, idxCb = newS2CompressReader(actualReader, actualSize)
|
wantEncryption := objectAPI.IsEncryptionSupported() && crypto.Requested(r.Header)
|
||||||
|
s2c, idxCb = newS2CompressReader(actualReader, actualSize, wantEncryption)
|
||||||
defer s2c.Close()
|
defer s2c.Close()
|
||||||
|
|
||||||
reader = etag.Wrap(s2c, actualReader)
|
reader = etag.Wrap(s2c, actualReader)
|
||||||
@ -1796,7 +1798,7 @@ func (api objectAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Req
|
|||||||
}
|
}
|
||||||
var objectEncryptionKey crypto.ObjectKey
|
var objectEncryptionKey crypto.ObjectKey
|
||||||
if objectAPI.IsEncryptionSupported() {
|
if objectAPI.IsEncryptionSupported() {
|
||||||
if _, ok := crypto.IsRequested(r.Header); ok && !HasSuffix(object, SlashSeparator) { // handle SSE requests
|
if crypto.Requested(r.Header) && !HasSuffix(object, SlashSeparator) { // handle SSE requests
|
||||||
if crypto.SSECopy.IsRequested(r.Header) {
|
if crypto.SSECopy.IsRequested(r.Header) {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, errInvalidEncryptionParameters), r.URL)
|
writeErrorResponse(ctx, w, toAPIError(ctx, errInvalidEncryptionParameters), r.URL)
|
||||||
return
|
return
|
||||||
@ -1929,7 +1931,7 @@ func (api objectAPIHandlers) PutObjectExtractHandler(w http.ResponseWriter, r *h
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := crypto.IsRequested(r.Header); ok {
|
if crypto.Requested(r.Header) {
|
||||||
if globalIsGateway {
|
if globalIsGateway {
|
||||||
if crypto.SSEC.IsRequested(r.Header) && !objectAPI.IsEncryptionSupported() {
|
if crypto.SSEC.IsRequested(r.Header) && !objectAPI.IsEncryptionSupported() {
|
||||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL)
|
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL)
|
||||||
@ -2088,7 +2090,8 @@ func (api objectAPIHandlers) PutObjectExtractHandler(w http.ResponseWriter, r *h
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set compression metrics.
|
// Set compression metrics.
|
||||||
s2c, cb := newS2CompressReader(actualReader, actualSize)
|
wantEncryption := objectAPI.IsEncryptionSupported() && crypto.Requested(r.Header)
|
||||||
|
s2c, cb := newS2CompressReader(actualReader, actualSize, wantEncryption)
|
||||||
defer s2c.Close()
|
defer s2c.Close()
|
||||||
idxCb = cb
|
idxCb = cb
|
||||||
reader = etag.Wrap(s2c, actualReader)
|
reader = etag.Wrap(s2c, actualReader)
|
||||||
@ -2144,7 +2147,7 @@ func (api objectAPIHandlers) PutObjectExtractHandler(w http.ResponseWriter, r *h
|
|||||||
|
|
||||||
var objectEncryptionKey crypto.ObjectKey
|
var objectEncryptionKey crypto.ObjectKey
|
||||||
if objectAPI.IsEncryptionSupported() {
|
if objectAPI.IsEncryptionSupported() {
|
||||||
if _, ok := crypto.IsRequested(r.Header); ok && !HasSuffix(object, SlashSeparator) { // handle SSE requests
|
if crypto.Requested(r.Header) && !HasSuffix(object, SlashSeparator) { // handle SSE requests
|
||||||
if crypto.SSECopy.IsRequested(r.Header) {
|
if crypto.SSECopy.IsRequested(r.Header) {
|
||||||
return errInvalidEncryptionParameters
|
return errInvalidEncryptionParameters
|
||||||
}
|
}
|
||||||
@ -2234,7 +2237,7 @@ func (api objectAPIHandlers) NewMultipartUploadHandler(w http.ResponseWriter, r
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := crypto.IsRequested(r.Header); ok {
|
if crypto.Requested(r.Header) {
|
||||||
if globalIsGateway {
|
if globalIsGateway {
|
||||||
if crypto.SSEC.IsRequested(r.Header) && !objectAPI.IsEncryptionSupported() {
|
if crypto.SSEC.IsRequested(r.Header) && !objectAPI.IsEncryptionSupported() {
|
||||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL)
|
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL)
|
||||||
@ -2279,7 +2282,7 @@ func (api objectAPIHandlers) NewMultipartUploadHandler(w http.ResponseWriter, r
|
|||||||
encMetadata := map[string]string{}
|
encMetadata := map[string]string{}
|
||||||
|
|
||||||
if objectAPI.IsEncryptionSupported() {
|
if objectAPI.IsEncryptionSupported() {
|
||||||
if _, ok := crypto.IsRequested(r.Header); ok {
|
if crypto.Requested(r.Header) {
|
||||||
if err = setEncryptionMetadata(r, bucket, object, encMetadata); err != nil {
|
if err = setEncryptionMetadata(r, bucket, object, encMetadata); err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
@ -2377,7 +2380,7 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := crypto.IsRequested(r.Header); !objectAPI.IsEncryptionSupported() && ok {
|
if crypto.Requested(r.Header) && !objectAPI.IsEncryptionSupported() {
|
||||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL)
|
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -2594,7 +2597,8 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt
|
|||||||
// Compress only if the compression is enabled during initial multipart.
|
// Compress only if the compression is enabled during initial multipart.
|
||||||
var idxCb func() []byte
|
var idxCb func() []byte
|
||||||
if isCompressed {
|
if isCompressed {
|
||||||
s2c, cb := newS2CompressReader(reader, actualPartSize)
|
wantEncryption := objectAPI.IsEncryptionSupported() && crypto.Requested(r.Header)
|
||||||
|
s2c, cb := newS2CompressReader(reader, actualPartSize, wantEncryption)
|
||||||
idxCb = cb
|
idxCb = cb
|
||||||
defer s2c.Close()
|
defer s2c.Close()
|
||||||
reader = etag.Wrap(s2c, reader)
|
reader = etag.Wrap(s2c, reader)
|
||||||
@ -2709,7 +2713,7 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := crypto.IsRequested(r.Header); ok {
|
if crypto.Requested(r.Header) {
|
||||||
if globalIsGateway {
|
if globalIsGateway {
|
||||||
if crypto.SSEC.IsRequested(r.Header) && !objectAPI.IsEncryptionSupported() {
|
if crypto.SSEC.IsRequested(r.Header) && !objectAPI.IsEncryptionSupported() {
|
||||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL)
|
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrNotImplemented), r.URL)
|
||||||
@ -2857,7 +2861,8 @@ func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set compression metrics.
|
// Set compression metrics.
|
||||||
s2c, cb := newS2CompressReader(actualReader, actualSize)
|
wantEncryption := objectAPI.IsEncryptionSupported() && crypto.Requested(r.Header)
|
||||||
|
s2c, cb := newS2CompressReader(actualReader, actualSize, wantEncryption)
|
||||||
idxCb = cb
|
idxCb = cb
|
||||||
defer s2c.Close()
|
defer s2c.Close()
|
||||||
reader = etag.Wrap(s2c, actualReader)
|
reader = etag.Wrap(s2c, actualReader)
|
||||||
|
@ -66,7 +66,7 @@ func (api objectAPIHandlers) getObjectInArchiveFileHandler(ctx context.Context,
|
|||||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrBadRequest), r.URL)
|
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrBadRequest), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if _, ok := crypto.IsRequested(r.Header); !objectAPI.IsEncryptionSupported() && ok {
|
if crypto.Requested(r.Header) && !objectAPI.IsEncryptionSupported() {
|
||||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrBadRequest), r.URL)
|
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrBadRequest), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -357,7 +357,7 @@ func (api objectAPIHandlers) headObjectInArchiveFileHandler(ctx context.Context,
|
|||||||
writeErrorResponseHeadersOnly(w, errorCodes.ToAPIErr(ErrBadRequest))
|
writeErrorResponseHeadersOnly(w, errorCodes.ToAPIErr(ErrBadRequest))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if _, ok := crypto.IsRequested(r.Header); !objectAPI.IsEncryptionSupported() && ok {
|
if crypto.Requested(r.Header) && !objectAPI.IsEncryptionSupported() {
|
||||||
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrBadRequest), r.URL)
|
writeErrorResponse(ctx, w, errorCodes.ToAPIErr(ErrBadRequest), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -128,7 +128,7 @@ type ApplyOptions struct {
|
|||||||
// set minimal SSE-KMS headers if autoEncrypt is true and the BucketSSEConfig
|
// set minimal SSE-KMS headers if autoEncrypt is true and the BucketSSEConfig
|
||||||
// is nil.
|
// is nil.
|
||||||
func (b *BucketSSEConfig) Apply(headers http.Header, opts ApplyOptions) {
|
func (b *BucketSSEConfig) Apply(headers http.Header, opts ApplyOptions) {
|
||||||
if _, ok := crypto.IsRequested(headers); ok {
|
if crypto.Requested(headers) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if b == nil {
|
if b == nil {
|
||||||
|
@ -29,6 +29,10 @@ import (
|
|||||||
func TestIsRequested(t *testing.T) {
|
func TestIsRequested(t *testing.T) {
|
||||||
for i, test := range kmsIsRequestedTests {
|
for i, test := range kmsIsRequestedTests {
|
||||||
_, got := IsRequested(test.Header)
|
_, got := IsRequested(test.Header)
|
||||||
|
if Requested(test.Header) != got {
|
||||||
|
// Test if result matches.
|
||||||
|
t.Errorf("Requested mismatch, want %v, got %v", Requested(test.Header), got)
|
||||||
|
}
|
||||||
got = got && S3KMS.IsRequested(test.Header)
|
got = got && S3KMS.IsRequested(test.Header)
|
||||||
if got != test.Expected {
|
if got != test.Expected {
|
||||||
t.Errorf("SSE-KMS: Test %d: Wanted %v but got %v", i, test.Expected, got)
|
t.Errorf("SSE-KMS: Test %d: Wanted %v but got %v", i, test.Expected, got)
|
||||||
@ -36,6 +40,10 @@ func TestIsRequested(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for i, test := range s3IsRequestedTests {
|
for i, test := range s3IsRequestedTests {
|
||||||
_, got := IsRequested(test.Header)
|
_, got := IsRequested(test.Header)
|
||||||
|
if Requested(test.Header) != got {
|
||||||
|
// Test if result matches.
|
||||||
|
t.Errorf("Requested mismatch, want %v, got %v", Requested(test.Header), got)
|
||||||
|
}
|
||||||
got = got && S3.IsRequested(test.Header)
|
got = got && S3.IsRequested(test.Header)
|
||||||
if got != test.Expected {
|
if got != test.Expected {
|
||||||
t.Errorf("SSE-S3: Test %d: Wanted %v but got %v", i, test.Expected, got)
|
t.Errorf("SSE-S3: Test %d: Wanted %v but got %v", i, test.Expected, got)
|
||||||
@ -43,6 +51,10 @@ func TestIsRequested(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for i, test := range ssecIsRequestedTests {
|
for i, test := range ssecIsRequestedTests {
|
||||||
_, got := IsRequested(test.Header)
|
_, got := IsRequested(test.Header)
|
||||||
|
if Requested(test.Header) != got {
|
||||||
|
// Test if result matches.
|
||||||
|
t.Errorf("Requested mismatch, want %v, got %v", Requested(test.Header), got)
|
||||||
|
}
|
||||||
got = got && SSEC.IsRequested(test.Header)
|
got = got && SSEC.IsRequested(test.Header)
|
||||||
if got != test.Expected {
|
if got != test.Expected {
|
||||||
t.Errorf("SSE-C: Test %d: Wanted %v but got %v", i, test.Expected, got)
|
t.Errorf("SSE-C: Test %d: Wanted %v but got %v", i, test.Expected, got)
|
||||||
|
@ -71,6 +71,11 @@ func IsRequested(h http.Header) (Type, bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Requested returns whether any type of encryption is requested.
|
||||||
|
func Requested(h http.Header) bool {
|
||||||
|
return S3.IsRequested(h) || S3KMS.IsRequested(h) || SSEC.IsRequested(h)
|
||||||
|
}
|
||||||
|
|
||||||
// UnsealObjectKey extracts and decrypts the sealed object key
|
// UnsealObjectKey extracts and decrypts the sealed object key
|
||||||
// from the metadata using the SSE-Copy client key of the HTTP headers
|
// from the metadata using the SSE-Copy client key of the HTTP headers
|
||||||
// and returns the decrypted object key.
|
// and returns the decrypted object key.
|
||||||
|
Loading…
Reference in New Issue
Block a user