mirror of
https://github.com/minio/minio.git
synced 2025-05-23 02:21:51 -04:00
azure/s3 gateways: Pass ETag during GET call to avoid data corruption (#11024)
Both Azure & S3 gateways call for object information before returning the stream of the object, however, the object content/length could be modified meanwhile, which means it can return a corrupted object. Use ETag to ensure that the object was not modified during the GET call
This commit is contained in:
parent
970ddb424b
commit
cffdb01279
@ -812,7 +812,7 @@ func (a *azureObjects) GetObjectNInfo(ctx context.Context, bucket, object string
|
|||||||
|
|
||||||
pr, pw := io.Pipe()
|
pr, pw := io.Pipe()
|
||||||
go func() {
|
go func() {
|
||||||
err := a.GetObject(ctx, bucket, object, startOffset, length, pw, objInfo.ETag, opts)
|
err := a.GetObject(ctx, bucket, object, startOffset, length, pw, objInfo.InnerETag, opts)
|
||||||
pw.CloseWithError(err)
|
pw.CloseWithError(err)
|
||||||
}()
|
}()
|
||||||
// Setup cleanup function to cause the above go-routine to
|
// Setup cleanup function to cause the above go-routine to
|
||||||
@ -833,8 +833,13 @@ func (a *azureObjects) GetObject(ctx context.Context, bucket, object string, sta
|
|||||||
return azureToObjectError(minio.InvalidRange{}, bucket, object)
|
return azureToObjectError(minio.InvalidRange{}, bucket, object)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
accessCond := azblob.BlobAccessConditions{}
|
||||||
|
if etag != "" {
|
||||||
|
accessCond.ModifiedAccessConditions.IfMatch = azblob.ETag(etag)
|
||||||
|
}
|
||||||
|
|
||||||
blobURL := a.client.NewContainerURL(bucket).NewBlobURL(object)
|
blobURL := a.client.NewContainerURL(bucket).NewBlobURL(object)
|
||||||
blob, err := blobURL.Download(ctx, startOffset, length, azblob.BlobAccessConditions{}, false)
|
blob, err := blobURL.Download(ctx, startOffset, length, accessCond, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return azureToObjectError(err, bucket, object)
|
return azureToObjectError(err, bucket, object)
|
||||||
}
|
}
|
||||||
@ -855,6 +860,8 @@ func (a *azureObjects) GetObjectInfo(ctx context.Context, bucket, object string,
|
|||||||
return objInfo, azureToObjectError(err, bucket, object)
|
return objInfo, azureToObjectError(err, bucket, object)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
realETag := string(blob.ETag())
|
||||||
|
|
||||||
// Populate correct ETag's if possible, this code primarily exists
|
// Populate correct ETag's if possible, this code primarily exists
|
||||||
// because AWS S3 indicates that
|
// because AWS S3 indicates that
|
||||||
//
|
//
|
||||||
@ -866,7 +873,7 @@ func (a *azureObjects) GetObjectInfo(ctx context.Context, bucket, object string,
|
|||||||
//
|
//
|
||||||
// Some applications depend on this behavior refer https://github.com/minio/minio/issues/6550
|
// Some applications depend on this behavior refer https://github.com/minio/minio/issues/6550
|
||||||
// So we handle it here and make this consistent.
|
// So we handle it here and make this consistent.
|
||||||
etag := minio.ToS3ETag(string(blob.ETag()))
|
etag := minio.ToS3ETag(realETag)
|
||||||
metadata := blob.NewMetadata()
|
metadata := blob.NewMetadata()
|
||||||
contentMD5 := blob.ContentMD5()
|
contentMD5 := blob.ContentMD5()
|
||||||
switch {
|
switch {
|
||||||
@ -881,6 +888,7 @@ func (a *azureObjects) GetObjectInfo(ctx context.Context, bucket, object string,
|
|||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
UserDefined: azurePropertiesToS3Meta(metadata, blob.NewHTTPHeaders(), blob.ContentLength()),
|
UserDefined: azurePropertiesToS3Meta(metadata, blob.NewHTTPHeaders(), blob.ContentLength()),
|
||||||
ETag: etag,
|
ETag: etag,
|
||||||
|
InnerETag: realETag,
|
||||||
ModTime: blob.LastModified(),
|
ModTime: blob.LastModified(),
|
||||||
Name: object,
|
Name: object,
|
||||||
Size: blob.ContentLength(),
|
Size: blob.ContentLength(),
|
||||||
|
@ -431,6 +431,11 @@ func (l *s3Objects) GetObject(ctx context.Context, bucket string, key string, st
|
|||||||
return minio.ErrorRespToObjectError(err, bucket, key)
|
return minio.ErrorRespToObjectError(err, bucket, key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if etag != "" {
|
||||||
|
opts.SetMatchETag(etag)
|
||||||
|
}
|
||||||
|
|
||||||
object, _, _, err := l.Client.GetObject(ctx, bucket, key, opts)
|
object, _, _, err := l.Client.GetObject(ctx, bucket, key, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return minio.ErrorRespToObjectError(err, bucket, key)
|
return minio.ErrorRespToObjectError(err, bucket, key)
|
||||||
|
@ -168,6 +168,9 @@ type ObjectInfo struct {
|
|||||||
// Hex encoded unique entity tag of the object.
|
// Hex encoded unique entity tag of the object.
|
||||||
ETag string
|
ETag string
|
||||||
|
|
||||||
|
// The ETag stored in the gateway backend
|
||||||
|
InnerETag string
|
||||||
|
|
||||||
// Version ID of this object.
|
// Version ID of this object.
|
||||||
VersionID string
|
VersionID string
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user