add Crypto UserAgent and versionid
This commit is contained in:
@@ -71,6 +71,7 @@ func (s *CryptoObjectService) Put(ctx context.Context, name string, r io.Reader,
|
||||
opt.XOptionHeader.Add(COSClientSideEncryptionUnencryptedContentLength, strconv.FormatInt(opt.ContentLength, 10))
|
||||
opt.ContentLength = cc.GetEncryptedLen(opt.ContentLength)
|
||||
}
|
||||
opt.XOptionHeader.Add(UserAgent, s.cryptoClient.userAgent)
|
||||
addCryptoHeaders(opt.XOptionHeader, cc.GetCipherData())
|
||||
|
||||
return s.ObjectService.Put(ctx, name, reader, opt)
|
||||
@@ -96,14 +97,14 @@ func (s *CryptoObjectService) PutFromFile(ctx context.Context, name, filePath st
|
||||
return
|
||||
}
|
||||
|
||||
func (s *CryptoObjectService) Get(ctx context.Context, name string, opt *cos.ObjectGetOptions) (*cos.Response, error) {
|
||||
meta, err := s.ObjectService.Head(ctx, name, nil)
|
||||
func (s *CryptoObjectService) Get(ctx context.Context, name string, opt *cos.ObjectGetOptions, id ...string) (*cos.Response, error) {
|
||||
meta, err := s.ObjectService.Head(ctx, name, nil, id...)
|
||||
if err != nil {
|
||||
return meta, err
|
||||
}
|
||||
_isEncrypted := isEncrypted(&meta.Header)
|
||||
if !_isEncrypted {
|
||||
return s.ObjectService.Get(ctx, name, opt)
|
||||
return s.ObjectService.Get(ctx, name, opt, id...)
|
||||
}
|
||||
|
||||
envelope := getEnvelopeFromHeader(&meta.Header)
|
||||
@@ -120,6 +121,10 @@ func (s *CryptoObjectService) Get(ctx context.Context, name string, opt *cos.Obj
|
||||
return nil, fmt.Errorf("get content cipher from envelope failed: %v, object:%v", err, name)
|
||||
}
|
||||
|
||||
opt = cos.CloneObjectGetOptions(opt)
|
||||
if opt.XOptionHeader == nil {
|
||||
opt.XOptionHeader = &http.Header{}
|
||||
}
|
||||
optRange, err := cos.GetRangeOptions(opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -132,7 +137,6 @@ func (s *CryptoObjectService) Get(ctx context.Context, name string, opt *cos.Obj
|
||||
discardAlignLen = optRange.Start - adjustStart
|
||||
if discardAlignLen > 0 {
|
||||
optRange.Start = adjustStart
|
||||
opt = cos.CloneObjectGetOptions(opt)
|
||||
opt.Range = cos.FormatRangeOptions(optRange)
|
||||
}
|
||||
|
||||
@@ -143,7 +147,8 @@ func (s *CryptoObjectService) Get(ctx context.Context, name string, opt *cos.Obj
|
||||
return nil, fmt.Errorf("ContentCipher Clone failed:%v, bject:%v", err, name)
|
||||
}
|
||||
}
|
||||
resp, err := s.ObjectService.Get(ctx, name, opt)
|
||||
opt.XOptionHeader.Add(UserAgent, s.cryptoClient.userAgent)
|
||||
resp, err := s.ObjectService.Get(ctx, name, opt, id...)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
@@ -161,8 +166,8 @@ func (s *CryptoObjectService) Get(ctx context.Context, name string, opt *cos.Obj
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func (s *CryptoObjectService) GetToFile(ctx context.Context, name, localpath string, opt *cos.ObjectGetOptions) (*cos.Response, error) {
|
||||
resp, err := s.Get(ctx, name, opt)
|
||||
func (s *CryptoObjectService) GetToFile(ctx context.Context, name, localpath string, opt *cos.ObjectGetOptions, id ...string) (*cos.Response, error) {
|
||||
resp, err := s.Get(ctx, name, opt, id...)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ func (s *CryptoObjectService) InitiateMultipartUpload(ctx context.Context, name
|
||||
opt.XOptionHeader.Add(COSClientSideEncryptionDataSize, strconv.FormatInt(cryptoCtx.DataSize, 10))
|
||||
}
|
||||
opt.XOptionHeader.Add(COSClientSideEncryptionPartSize, strconv.FormatInt(cryptoCtx.PartSize, 10))
|
||||
opt.XOptionHeader.Add(UserAgent, s.cryptoClient.userAgent)
|
||||
addCryptoHeaders(opt.XOptionHeader, contentCipher.GetCipherData())
|
||||
|
||||
return s.ObjectService.InitiateMultipartUpload(ctx, name, opt)
|
||||
@@ -54,6 +55,10 @@ func (s *CryptoObjectService) UploadPart(ctx context.Context, name, uploadID str
|
||||
return nil, fmt.Errorf("CryptoContext's PartSize is zero")
|
||||
}
|
||||
opt = cos.CloneObjectUploadPartOptions(opt)
|
||||
if opt.XOptionHeader == nil {
|
||||
opt.XOptionHeader = &http.Header{}
|
||||
}
|
||||
opt.XOptionHeader.Add(UserAgent, s.cryptoClient.userAgent)
|
||||
if cryptoCtx.ContentCipher == nil {
|
||||
return nil, fmt.Errorf("ContentCipher is nil, Please call the InitiateMultipartUpload")
|
||||
}
|
||||
@@ -77,3 +82,16 @@ func (s *CryptoObjectService) UploadPart(ctx context.Context, name, uploadID str
|
||||
}
|
||||
return s.ObjectService.UploadPart(ctx, name, uploadID, partNumber, reader, opt)
|
||||
}
|
||||
|
||||
func (s *CryptoObjectService) CompleteMultipartUpload(ctx context.Context, name, uploadID string, opt *cos.CompleteMultipartUploadOptions) (*cos.CompleteMultipartUploadResult, *cos.Response, error) {
|
||||
opt = cos.CloneCompleteMultipartUploadOptions(opt)
|
||||
if opt.XOptionHeader == nil {
|
||||
opt.XOptionHeader = &http.Header{}
|
||||
}
|
||||
opt.XOptionHeader.Add(UserAgent, s.cryptoClient.userAgent)
|
||||
return s.ObjectService.CompleteMultipartUpload(ctx, name, uploadID, opt)
|
||||
}
|
||||
|
||||
func (s *CryptoObjectService) CopyPart(ctx context.Context, name, uploadID string, partNumber int, sourceURL string, opt *cos.ObjectCopyPartOptions) (*cos.CopyPartResult, *cos.Response, error) {
|
||||
return nil, nil, fmt.Errorf("CryptoObjectService doesn't support CopyPart")
|
||||
}
|
||||
|
||||
@@ -120,6 +120,45 @@ func (s *CosTestSuite) TestPutGetDeleteObject_Normal_10MB() {
|
||||
assert.Nil(s.T(), err, "DeleteObject Failed")
|
||||
}
|
||||
|
||||
func (s *CosTestSuite) TestPutGetDeleteObject_VersionID() {
|
||||
name := "test/objectPut" + time.Now().Format(time.RFC3339)
|
||||
originData := make([]byte, 1024*1024*10+1)
|
||||
_, err := rand.Read(originData)
|
||||
f := bytes.NewReader(originData)
|
||||
|
||||
opt := &cos.BucketPutVersionOptions{
|
||||
Status: "Enabled",
|
||||
}
|
||||
_, err = s.CClient.Bucket.PutVersioning(context.Background(), opt)
|
||||
assert.Nil(s.T(), err, "PutVersioning Failed")
|
||||
time.Sleep(3 * time.Second)
|
||||
|
||||
// 加密存储
|
||||
resp, err := s.CClient.Object.Put(context.Background(), name, f, nil)
|
||||
assert.Nil(s.T(), err, "PutObject Failed")
|
||||
versionId := resp.Header.Get("x-cos-version-id")
|
||||
|
||||
_, err = s.CClient.Object.Delete(context.Background(), name)
|
||||
assert.Nil(s.T(), err, "DeleteObject Failed")
|
||||
|
||||
// 解密读取
|
||||
resp, err = s.CClient.Object.Get(context.Background(), name, nil, versionId)
|
||||
assert.Nil(s.T(), err, "GetObject Failed")
|
||||
defer resp.Body.Close()
|
||||
decryptedData, _ := ioutil.ReadAll(resp.Body)
|
||||
assert.Equal(s.T(), bytes.Compare(originData, decryptedData), 0, "decryptData != originData")
|
||||
|
||||
delopt := &cos.ObjectDeleteOptions{
|
||||
VersionId: versionId,
|
||||
}
|
||||
_, err = s.CClient.Object.Delete(context.Background(), name, delopt)
|
||||
assert.Nil(s.T(), err, "DeleteObject Failed")
|
||||
|
||||
opt.Status = "Suspended"
|
||||
_, err = s.CClient.Bucket.PutVersioning(context.Background(), opt)
|
||||
assert.Nil(s.T(), err, "PutVersioning Failed")
|
||||
}
|
||||
|
||||
func (s *CosTestSuite) TestPutGetDeleteObject_ZeroFile() {
|
||||
name := "test/objectPut" + time.Now().Format(time.RFC3339)
|
||||
// 加密存储
|
||||
@@ -377,6 +416,122 @@ func (s *CosTestSuite) TestPutGetDeleteObject_WithListenerAndRange() {
|
||||
assert.Nil(s.T(), err, "DeleteObject Failed")
|
||||
}
|
||||
|
||||
func (s *CosTestSuite) TestPutGetDeleteObject_Copy() {
|
||||
name := "test/objectPut" + time.Now().Format(time.RFC3339)
|
||||
contentLength := 1024*1024*10 + 1
|
||||
originData := make([]byte, contentLength)
|
||||
_, err := rand.Read(originData)
|
||||
f := bytes.NewReader(originData)
|
||||
|
||||
// 加密存储
|
||||
popt := &cos.ObjectPutOptions{
|
||||
nil,
|
||||
&cos.ObjectPutHeaderOptions{
|
||||
Listener: &cos.DefaultProgressListener{},
|
||||
},
|
||||
}
|
||||
resp, err := s.CClient.Object.Put(context.Background(), name, f, popt)
|
||||
assert.Nil(s.T(), err, "PutObject Failed")
|
||||
encryptedDataCRC := resp.Header.Get("x-cos-hash-crc64ecma")
|
||||
time.Sleep(3 * time.Second)
|
||||
sourceURL := fmt.Sprintf("%s/%s", s.CClient.BaseURL.BucketURL.Host, name)
|
||||
{
|
||||
// x-cos-metadata-directive必须为Copy,否则丢失加密信息,无法解密
|
||||
dest := "test/ObjectCopy1" + time.Now().Format(time.RFC3339)
|
||||
res, _, err := s.CClient.Object.Copy(context.Background(), dest, sourceURL, nil)
|
||||
assert.Nil(s.T(), err, "ObjectCopy Failed")
|
||||
assert.Equal(s.T(), encryptedDataCRC, res.CRC64, "CRC isn't consistent, return:%v, want:%v", res.CRC64, encryptedDataCRC)
|
||||
|
||||
// Range解密读取
|
||||
for i := 0; i < 3; i++ {
|
||||
math_rand.Seed(time.Now().UnixNano())
|
||||
rangeStart := math_rand.Intn(contentLength)
|
||||
rangeEnd := rangeStart + math_rand.Intn(contentLength-rangeStart)
|
||||
if rangeEnd == rangeStart || rangeStart >= contentLength-1 {
|
||||
continue
|
||||
}
|
||||
opt := &cos.ObjectGetOptions{
|
||||
Range: fmt.Sprintf("bytes=%v-%v", rangeStart, rangeEnd),
|
||||
Listener: &cos.DefaultProgressListener{},
|
||||
}
|
||||
resp, err := s.CClient.Object.Get(context.Background(), dest, opt)
|
||||
assert.Nil(s.T(), err, "GetObject Failed")
|
||||
defer resp.Body.Close()
|
||||
decryptedData, _ := ioutil.ReadAll(resp.Body)
|
||||
assert.Equal(s.T(), bytes.Compare(originData[rangeStart:rangeEnd+1], decryptedData), 0, "decryptData != originData")
|
||||
}
|
||||
// 解密读取
|
||||
resp, err := s.CClient.Object.Get(context.Background(), dest, nil)
|
||||
assert.Nil(s.T(), err, "GetObject Failed")
|
||||
defer resp.Body.Close()
|
||||
decryptedData, _ := ioutil.ReadAll(resp.Body)
|
||||
assert.Equal(s.T(), bytes.Compare(originData, decryptedData), 0, "decryptData != originData")
|
||||
|
||||
_, err = s.CClient.Object.Delete(context.Background(), dest)
|
||||
assert.Nil(s.T(), err, "DeleteObject Failed")
|
||||
}
|
||||
{
|
||||
// x-cos-metadata-directive必须为Copy,否则丢失加密信息,无法解密
|
||||
opt := &cos.ObjectCopyOptions{
|
||||
&cos.ObjectCopyHeaderOptions{
|
||||
XCosMetadataDirective: "Replaced",
|
||||
},
|
||||
nil,
|
||||
}
|
||||
dest := "test/ObjectCopy2" + time.Now().Format(time.RFC3339)
|
||||
res, _, err := s.CClient.Object.Copy(context.Background(), dest, sourceURL, opt)
|
||||
assert.Nil(s.T(), err, "ObjectCopy Failed")
|
||||
assert.Equal(s.T(), encryptedDataCRC, res.CRC64, "CRC isn't consistent, return:%v, want:%v", res.CRC64, encryptedDataCRC)
|
||||
|
||||
// 解密读取
|
||||
resp, err := s.CClient.Object.Get(context.Background(), dest, nil)
|
||||
assert.Nil(s.T(), err, "GetObject Failed")
|
||||
defer resp.Body.Close()
|
||||
decryptedData, _ := ioutil.ReadAll(resp.Body)
|
||||
assert.NotEqual(s.T(), bytes.Compare(originData, decryptedData), 0, "decryptData != originData")
|
||||
|
||||
_, err = s.CClient.Object.Delete(context.Background(), dest)
|
||||
assert.Nil(s.T(), err, "DeleteObject Failed")
|
||||
}
|
||||
{
|
||||
// MultiCopy若是分块拷贝,则无法拷贝元数据
|
||||
dest := "test/ObjectCopy3" + time.Now().Format(time.RFC3339)
|
||||
res, _, err := s.CClient.Object.MultiCopy(context.Background(), dest, sourceURL, nil)
|
||||
assert.Nil(s.T(), err, "ObjectMultiCopy Failed")
|
||||
assert.Equal(s.T(), encryptedDataCRC, res.CRC64, "CRC isn't consistent, return:%v, want:%v", res.CRC64, encryptedDataCRC)
|
||||
// Range解密读取
|
||||
for i := 0; i < 3; i++ {
|
||||
math_rand.Seed(time.Now().UnixNano())
|
||||
rangeStart := math_rand.Intn(contentLength)
|
||||
rangeEnd := rangeStart + math_rand.Intn(contentLength-rangeStart)
|
||||
if rangeEnd == rangeStart || rangeStart >= contentLength-1 {
|
||||
continue
|
||||
}
|
||||
opt := &cos.ObjectGetOptions{
|
||||
Range: fmt.Sprintf("bytes=%v-%v", rangeStart, rangeEnd),
|
||||
Listener: &cos.DefaultProgressListener{},
|
||||
}
|
||||
resp, err := s.CClient.Object.Get(context.Background(), dest, opt)
|
||||
assert.Nil(s.T(), err, "GetObject Failed")
|
||||
defer resp.Body.Close()
|
||||
decryptedData, _ := ioutil.ReadAll(resp.Body)
|
||||
assert.Equal(s.T(), bytes.Compare(originData[rangeStart:rangeEnd+1], decryptedData), 0, "decryptData != originData")
|
||||
}
|
||||
// 解密读取
|
||||
resp, err := s.CClient.Object.Get(context.Background(), dest, nil)
|
||||
assert.Nil(s.T(), err, "GetObject Failed")
|
||||
defer resp.Body.Close()
|
||||
decryptedData, _ := ioutil.ReadAll(resp.Body)
|
||||
assert.Equal(s.T(), bytes.Compare(originData, decryptedData), 0, "decryptData != originData")
|
||||
|
||||
_, err = s.CClient.Object.Delete(context.Background(), dest)
|
||||
assert.Nil(s.T(), err, "DeleteObject Failed")
|
||||
}
|
||||
|
||||
_, err = s.CClient.Object.Delete(context.Background(), name)
|
||||
assert.Nil(s.T(), err, "DeleteObject Failed")
|
||||
}
|
||||
|
||||
func TestCosTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(CosTestSuite))
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ const (
|
||||
COSClientSideEncryptionUnencryptedContentMD5 = "x-cos-meta-client-side-encryption-unencrypted-content-md5"
|
||||
COSClientSideEncryptionDataSize = "x-cos-meta-client-side-encryption-data-size"
|
||||
COSClientSideEncryptionPartSize = "x-cos-meta-client-side-encryption-part-size"
|
||||
COSClientUserAgent = "User-Agent"
|
||||
UserAgent = "User-Agent"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
Reference in New Issue
Block a user