mirror of
https://github.com/minio/minio.git
synced 2024-12-23 21:55:53 -05:00
feat: Encrypt s3zip file index (#16179)
This commit is contained in:
parent
12fd6678ee
commit
ebe395788b
@ -1083,6 +1083,44 @@ func (o *ObjectInfo) metadataDecrypter() objectMetaDecryptFn {
|
||||
}
|
||||
}
|
||||
|
||||
// metadataEncryptFn provides an encryption function for metadata.
|
||||
// Will return nil, nil if unencrypted.
|
||||
func (o *ObjectInfo) metadataEncryptFn(headers http.Header) (objectMetaEncryptFn, error) {
|
||||
kind, _ := crypto.IsEncrypted(o.UserDefined)
|
||||
switch kind {
|
||||
case crypto.SSEC:
|
||||
if crypto.SSECopy.IsRequested(headers) {
|
||||
key, err := crypto.SSECopy.ParseHTTP(headers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
objectEncryptionKey, err := decryptObjectMeta(key[:], o.Bucket, o.Name, o.UserDefined)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(objectEncryptionKey) == 32 {
|
||||
var key crypto.ObjectKey
|
||||
copy(key[:], objectEncryptionKey)
|
||||
return metadataEncrypter(key), nil
|
||||
}
|
||||
return nil, errors.New("metadataEncryptFn: unexpected key size")
|
||||
}
|
||||
case crypto.S3, crypto.S3KMS:
|
||||
objectEncryptionKey, err := decryptObjectMeta(nil, o.Bucket, o.Name, o.UserDefined)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(objectEncryptionKey) == 32 {
|
||||
var key crypto.ObjectKey
|
||||
copy(key[:], objectEncryptionKey)
|
||||
return metadataEncrypter(key), nil
|
||||
}
|
||||
return nil, errors.New("metadataEncryptFn: unexpected key size")
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// decryptChecksums will attempt to decode checksums and return it/them if set.
|
||||
func (o *ObjectInfo) decryptChecksums() map[string]string {
|
||||
data := o.Checksum
|
||||
|
@ -26,6 +26,7 @@ import (
|
||||
"github.com/minio/madmin-go/v2"
|
||||
"github.com/minio/minio/internal/bucket/replication"
|
||||
"github.com/minio/minio/internal/hash"
|
||||
"github.com/minio/minio/internal/logger"
|
||||
)
|
||||
|
||||
// BackendType - represents different backend types.
|
||||
@ -181,8 +182,9 @@ type ObjectInfo struct {
|
||||
Checksum []byte
|
||||
}
|
||||
|
||||
// ArchiveInfo returns any saved zip archive meta information
|
||||
func (o ObjectInfo) ArchiveInfo() []byte {
|
||||
// ArchiveInfo returns any saved zip archive meta information.
|
||||
// It will be decrypted if needed.
|
||||
func (o *ObjectInfo) ArchiveInfo() []byte {
|
||||
if len(o.UserDefined) == 0 {
|
||||
return nil
|
||||
}
|
||||
@ -190,11 +192,20 @@ func (o ObjectInfo) ArchiveInfo() []byte {
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return []byte(z)
|
||||
data := []byte(z)
|
||||
if v, ok := o.UserDefined[archiveTypeMetadataKey]; ok && v == archiveTypeEnc {
|
||||
decrypted, err := o.metadataDecrypter()(archiveTypeEnc, data)
|
||||
if err != nil {
|
||||
logger.LogIf(GlobalContext, err)
|
||||
return nil
|
||||
}
|
||||
data = decrypted
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
// Clone - Returns a cloned copy of current objectInfo
|
||||
func (o ObjectInfo) Clone() (cinfo ObjectInfo) {
|
||||
func (o *ObjectInfo) Clone() (cinfo ObjectInfo) {
|
||||
cinfo = ObjectInfo{
|
||||
Bucket: o.Bucket,
|
||||
Name: o.Name,
|
||||
|
@ -676,6 +676,11 @@ func (api objectAPIHandlers) CompleteMultipartUploadHandler(w http.ResponseWrite
|
||||
}
|
||||
}
|
||||
|
||||
opts.EncryptFn, err = objInfo.metadataEncryptFn(r.Header)
|
||||
if err != nil {
|
||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||
return
|
||||
}
|
||||
if r.Header.Get(xMinIOExtract) == "true" && strings.HasSuffix(object, archiveExt) {
|
||||
opts := ObjectOptions{VersionID: objInfo.VersionID, MTime: objInfo.ModTime}
|
||||
if _, err := updateObjectMetadataWithZipInfo(ctx, objectAPI, bucket, object, opts); err != nil {
|
||||
|
@ -38,6 +38,7 @@ import (
|
||||
|
||||
const (
|
||||
archiveType = "zip"
|
||||
archiveTypeEnc = "zip-enc"
|
||||
archiveExt = "." + archiveType // ".zip"
|
||||
archiveSeparator = "/"
|
||||
archivePattern = archiveExt + archiveSeparator // ".zip/"
|
||||
@ -152,6 +153,12 @@ func (api objectAPIHandlers) getObjectInArchiveFileHandler(ctx context.Context,
|
||||
|
||||
zipInfo := zipObjInfo.ArchiveInfo()
|
||||
if len(zipInfo) == 0 {
|
||||
opts.EncryptFn, err = zipObjInfo.metadataEncryptFn(r.Header)
|
||||
if err != nil {
|
||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||
return
|
||||
}
|
||||
|
||||
zipInfo, err = updateObjectMetadataWithZipInfo(ctx, objectAPI, bucket, zipPath, opts)
|
||||
}
|
||||
if err != nil {
|
||||
@ -451,6 +458,11 @@ func (api objectAPIHandlers) headObjectInArchiveFileHandler(ctx context.Context,
|
||||
|
||||
zipInfo := zipObjInfo.ArchiveInfo()
|
||||
if len(zipInfo) == 0 {
|
||||
opts.EncryptFn, err = zipObjInfo.metadataEncryptFn(r.Header)
|
||||
if err != nil {
|
||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||
return
|
||||
}
|
||||
zipInfo, err = updateObjectMetadataWithZipInfo(ctx, objectAPI, bucket, zipPath, opts)
|
||||
}
|
||||
if err != nil {
|
||||
@ -491,7 +503,8 @@ func (api objectAPIHandlers) headObjectInArchiveFileHandler(ctx context.Context,
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
// Update the passed zip object metadata with the zip contents info, file name, modtime, size, etc..
|
||||
// Update the passed zip object metadata with the zip contents info, file name, modtime, size, etc.
|
||||
// The returned zip index will de decrypted.
|
||||
func updateObjectMetadataWithZipInfo(ctx context.Context, objectAPI ObjectLayer, bucket, object string, opts ObjectOptions) ([]byte, error) {
|
||||
files, srcInfo, err := getFilesListFromZIPObject(ctx, objectAPI, bucket, object, opts)
|
||||
if err != nil {
|
||||
@ -502,14 +515,18 @@ func updateObjectMetadataWithZipInfo(ctx context.Context, objectAPI ObjectLayer,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
srcInfo.UserDefined[archiveTypeMetadataKey] = archiveType
|
||||
at := archiveType
|
||||
zipInfoStr := string(zipInfo)
|
||||
if opts.EncryptFn != nil {
|
||||
at = archiveTypeEnc
|
||||
zipInfoStr = string(opts.EncryptFn(archiveTypeEnc, zipInfo))
|
||||
}
|
||||
srcInfo.UserDefined[archiveTypeMetadataKey] = at
|
||||
popts := ObjectOptions{
|
||||
MTime: srcInfo.ModTime,
|
||||
VersionID: srcInfo.VersionID,
|
||||
EvalMetadataFn: func(oi *ObjectInfo) error {
|
||||
oi.UserDefined[archiveTypeMetadataKey] = archiveType
|
||||
oi.UserDefined[archiveTypeMetadataKey] = at
|
||||
oi.UserDefined[archiveInfoMetadataKey] = zipInfoStr
|
||||
return nil
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user