Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Checksum Work] BlockBlob Client: Transactional/Source Content Validation #21033

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
8b2eb24
Adding test for transactional validation in block blob
siminsavani-msft Apr 19, 2023
af33a48
StageBlockFromURL tests
siminsavani-msft Apr 27, 2023
b461648
Deprecating options in CommitBlockList
siminsavani-msft Apr 27, 2023
818a1f6
CopyFromURL test
siminsavani-msft Apr 27, 2023
34a8a93
Updating checksum behavior
siminsavani-msft Jun 19, 2023
82ae345
Record tests
siminsavani-msft Jun 19, 2023
b7cdc0d
Updated recording
siminsavani-msft Jun 20, 2023
ac461aa
Updated recording again
siminsavani-msft Jun 20, 2023
c67343c
Added error for user gen checksums, tests for UploadStream, UploadBuf…
siminsavani-msft Jun 23, 2023
a1c52f3
Added recorded test
siminsavani-msft Jun 23, 2023
3d6a891
Merge branch 'feature/azblob-stg85/86' into checksum-blockblob
siminsavani-msft Jun 26, 2023
90902a2
Updated CommitBlockList, added tests for CommitBlockList, and added C…
siminsavani-msft Jun 28, 2023
82c5935
Merge branch 'checksum-blockblob' of https://github.com/siminsavani-m…
siminsavani-msft Jun 28, 2023
d252803
Updating UploadStream test
siminsavani-msft Jun 28, 2023
380f947
Recorded test
siminsavani-msft Jun 29, 2023
e0f3df5
Recorded test
siminsavani-msft Jun 30, 2023
fe127ee
Fixing CommitBlockList errors
siminsavani-msft Jul 3, 2023
cceedf7
Fixing linting issues
siminsavani-msft Jul 3, 2023
83d2fe4
Addressing comment + handling CI issues
siminsavani-msft Jul 5, 2023
5e2efb4
Removing TransactionalValidation from CommitBlockList + cleaning up t…
siminsavani-msft Jul 6, 2023
1ffc759
Rerecorded tests
siminsavani-msft Jul 6, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion sdk/storage/azblob/assets.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "go",
"TagPrefix": "go/storage/azblob",
"Tag": "go/storage/azblob_1a8d8f30f5"
"Tag": "go/storage/azblob_23a06ae998"
}
61 changes: 0 additions & 61 deletions sdk/storage/azblob/blob/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,67 +191,6 @@ func waitForCopy(_require *require.Assertions, copyBlobClient *blockblob.Client,
}
}

func (s *BlobUnrecordedTestsSuite) TestCopyBlockBlobFromUrlSourceContentMD5() {
siminsavani-msft marked this conversation as resolved.
Show resolved Hide resolved
_require := require.New(s.T())
testName := s.T().Name()
svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil)
if err != nil {
s.Fail("Unable to fetch service client because " + err.Error())
}

containerName := testcommon.GenerateContainerName(testName)
containerClient := testcommon.CreateNewContainer(context.Background(), _require, containerName, svcClient)
defer testcommon.DeleteContainer(context.Background(), _require, containerClient)

const contentSize = 8 * 1024 // 8 KB
content := make([]byte, contentSize)
contentMD5 := md5.Sum(content)
body := bytes.NewReader(content)

srcBlob := containerClient.NewBlockBlobClient("srcblob")
destBlob := containerClient.NewBlockBlobClient("destblob")

// Prepare source bbClient for copy.
_, err = srcBlob.Upload(context.Background(), streaming.NopCloser(body), nil)
_require.Nil(err)

expiryTime, err := time.Parse(time.UnixDate, "Fri Jun 11 20:00:00 UTC 2049")
_require.Nil(err)

credential, err := testcommon.GetGenericSharedKeyCredential(testcommon.TestAccountDefault)
if err != nil {
s.T().Fatal("Couldn't fetch credential because " + err.Error())
}

// Get source blob url with SAS for StageFromURL.
sasQueryParams, err := sas.AccountSignatureValues{
Protocol: sas.ProtocolHTTPS,
ExpiryTime: expiryTime,
Permissions: to.Ptr(sas.AccountPermissions{Read: true, List: true}).String(),
ResourceTypes: to.Ptr(sas.AccountResourceTypes{Container: true, Object: true}).String(),
}.SignWithSharedKey(credential)
_require.Nil(err)

srcBlobParts, _ := blob.ParseURL(srcBlob.URL())
srcBlobParts.SAS = sasQueryParams
srcBlobURLWithSAS := srcBlobParts.String()

// Invoke CopyFromURL.
sourceContentMD5 := contentMD5[:]
resp, err := destBlob.CopyFromURL(context.Background(), srcBlobURLWithSAS, &blob.CopyFromURLOptions{
SourceContentMD5: sourceContentMD5,
})
_require.Nil(err)
_require.EqualValues(resp.ContentMD5, sourceContentMD5)

// Provide bad MD5 and make sure the copy fails
_, badMD5 := testcommon.GetDataAndReader(testName, 16)
resp, err = destBlob.CopyFromURL(context.Background(), srcBlobURLWithSAS, &blob.CopyFromURLOptions{
SourceContentMD5: badMD5,
})
_require.NotNil(err)
}

func (s *BlobRecordedTestsSuite) TestBlobStartCopyDestEmpty() {
_require := require.New(s.T())
testName := s.T().Name()
Expand Down
1 change: 1 addition & 0 deletions sdk/storage/azblob/bloberror/error_codes.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,4 +153,5 @@ const (
var (
// MissingSharedKeyCredential - Error is returned when SAS URL is being created without SharedKeyCredential.
MissingSharedKeyCredential = errors.New("SAS can only be signed with a SharedKeyCredential")
UnsupportedChecksum = errors.New("for multi-part uploads, user generated checksums cannot be validated")
)
31 changes: 31 additions & 0 deletions sdk/storage/azblob/blockblob/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ import (
"encoding/base64"
"errors"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/bloberror"
"io"
"math"
"os"
"reflect"
"sync"
"time"

Expand Down Expand Up @@ -172,6 +174,13 @@ func (bb *Client) Upload(ctx context.Context, body io.ReadSeekCloser, options *U

opts, httpHeaders, leaseInfo, cpkV, cpkN, accessConditions := options.format()

if options != nil && options.TransactionalValidation != nil {
body, err = options.TransactionalValidation.Apply(body, opts)
if err != nil {
return UploadResponse{}, err
}
}

resp, err := bb.generated().Upload(ctx, count, body, opts, httpHeaders, leaseInfo, cpkV, cpkN, accessConditions)
return resp, err
}
Expand Down Expand Up @@ -260,6 +269,11 @@ func (bb *Client) CommitBlockList(ctx context.Context, base64BlockIDs []string,
ImmutabilityPolicyExpiry: options.ImmutabilityPolicyExpiryTime,
}

// If user attempts to pass in their own checksum, errors out.
if options.TransactionalContentMD5 != nil || options.TransactionalContentCRC64 != nil {
return CommitBlockListResponse{}, bloberror.UnsupportedChecksum
souravgupta-msft marked this conversation as resolved.
Show resolved Hide resolved
}

headers = options.HTTPHeaders
leaseAccess, modifiedAccess = exported.FormatBlobAccessConditions(options.AccessConditions)
cpkInfo = options.CPKInfo
Expand Down Expand Up @@ -506,6 +520,12 @@ func (bb *Client) UploadBuffer(ctx context.Context, buffer []byte, o *UploadBuff
if o != nil {
uploadOptions = *o
}

// If user attempts to pass in their own checksum, errors out.
if uploadOptions.TransactionalValidation != nil && reflect.TypeOf(uploadOptions.TransactionalValidation).Kind() != reflect.Func {
return UploadBufferResponse{}, bloberror.UnsupportedChecksum
}

return bb.uploadFromReader(ctx, bytes.NewReader(buffer), int64(len(buffer)), &uploadOptions)
}

Expand All @@ -519,6 +539,12 @@ func (bb *Client) UploadFile(ctx context.Context, file *os.File, o *UploadFileOp
if o != nil {
uploadOptions = *o
}

// If user attempts to pass in their own checksum, errors out.
if uploadOptions.TransactionalValidation != nil && reflect.TypeOf(uploadOptions.TransactionalValidation).Kind() != reflect.Func {
return UploadFileResponse{}, bloberror.UnsupportedChecksum
}

return bb.uploadFromReader(ctx, file, stat.Size(), &uploadOptions)
}

Expand All @@ -529,6 +555,11 @@ func (bb *Client) UploadStream(ctx context.Context, body io.Reader, o *UploadStr
o = &UploadStreamOptions{}
}

// If user attempts to pass in their own checksum, errors out.
if o.TransactionalValidation != nil && reflect.TypeOf(o.TransactionalValidation).Kind() != reflect.Func {
return UploadStreamResponse{}, bloberror.UnsupportedChecksum
}

result, err := copyFromReader(ctx, body, bb, *o, newMMBPool)
if err != nil {
return CommitBlockListResponse{}, err
Expand Down
Loading