aboutsummaryrefslogtreecommitdiff
path: root/vendor/cloud.google.com/go/storage/storage.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/cloud.google.com/go/storage/storage.go')
-rw-r--r--vendor/cloud.google.com/go/storage/storage.go105
1 files changed, 79 insertions, 26 deletions
diff --git a/vendor/cloud.google.com/go/storage/storage.go b/vendor/cloud.google.com/go/storage/storage.go
index 9dccf5a..bafb136 100644
--- a/vendor/cloud.google.com/go/storage/storage.go
+++ b/vendor/cloud.google.com/go/storage/storage.go
@@ -272,12 +272,13 @@ func SignedURL(bucket, name string, opts *SignedURLOptions) (string, error) {
// ObjectHandle provides operations on an object in a Google Cloud Storage bucket.
// Use BucketHandle.Object to get a handle.
type ObjectHandle struct {
- c *Client
- bucket string
- object string
- acl ACLHandle
- gen int64 // a negative value indicates latest
- conds *Conditions
+ c *Client
+ bucket string
+ object string
+ acl ACLHandle
+ gen int64 // a negative value indicates latest
+ conds *Conditions
+ encryptionKey []byte // AES-256 key
}
// ACL provides access to the object's access control list.
@@ -309,6 +310,17 @@ func (o *ObjectHandle) If(conds Conditions) *ObjectHandle {
return &o2
}
+// Key returns a new ObjectHandle that uses the supplied encryption
+// key to encrypt and decrypt the object's contents.
+//
+// Encryption key must be a 32-byte AES-256 key.
+// See https://cloud.google.com/storage/docs/encryption for details.
+func (o *ObjectHandle) Key(encryptionKey []byte) *ObjectHandle {
+ o2 := *o
+ o2.encryptionKey = encryptionKey
+ return &o2
+}
+
// Attrs returns meta information about the object.
// ErrObjectNotExist will be returned if the object is not found.
func (o *ObjectHandle) Attrs(ctx context.Context) (*ObjectAttrs, error) {
@@ -319,6 +331,9 @@ func (o *ObjectHandle) Attrs(ctx context.Context) (*ObjectAttrs, error) {
if err := applyConds("Attrs", o.gen, o.conds, call); err != nil {
return nil, err
}
+ if err := setEncryptionHeaders(call.Header(), o.encryptionKey, false); err != nil {
+ return nil, err
+ }
var obj *raw.Object
var err error
err = runWithRetry(ctx, func() error { obj, err = call.Do(); return err })
@@ -389,6 +404,9 @@ func (o *ObjectHandle) Update(ctx context.Context, uattrs ObjectAttrsToUpdate) (
if err := applyConds("Update", o.gen, o.conds, call); err != nil {
return nil, err
}
+ if err := setEncryptionHeaders(call.Header(), o.encryptionKey, false); err != nil {
+ return nil, err
+ }
var obj *raw.Object
var err error
err = runWithRetry(ctx, func() error { obj, err = call.Do(); return err })
@@ -486,6 +504,9 @@ func (o *ObjectHandle) NewRangeReader(ctx context.Context, offset, length int64)
} else if length > 0 {
req.Header.Set("Range", fmt.Sprintf("bytes=%d-%d", offset, offset+length-1))
}
+ if err := setEncryptionHeaders(req.Header, o.encryptionKey, false); err != nil {
+ return nil, err
+ }
var res *http.Response
err = runWithRetry(ctx, func() error { res, err = o.c.hc.Do(req); return err })
if err != nil {
@@ -616,7 +637,7 @@ func toRawObjectACL(oldACL []ACLRule) []*raw.ObjectAccessControl {
}
// toRawObject copies the editable attributes from o to the raw library's Object type.
-func (o ObjectAttrs) toRawObject(bucket string) *raw.Object {
+func (o *ObjectAttrs) toRawObject(bucket string) *raw.Object {
acl := toRawObjectACL(o.ACL)
return &raw.Object{
Bucket: bucket,
@@ -716,6 +737,13 @@ type ObjectAttrs struct {
// metadata does not change this property. This field is read-only.
Updated time.Time
+ // CustomerKeySHA256 is the base64-encoded SHA-256 hash of the
+ // customer-supplied encryption key for the object. It is empty if there is
+ // no customer-supplied encryption key.
+ // See // https://cloud.google.com/storage/docs/encryption for more about
+ // encryption in Google Cloud Storage.
+ CustomerKeySHA256 string
+
// Prefix is set only for ObjectAttrs which represent synthetic "directory
// entries" when iterating over buckets using Query.Delimiter. See
// ObjectIterator.Next. When set, no other fields in ObjectAttrs will be
@@ -754,26 +782,31 @@ func newObject(o *raw.Object) *ObjectAttrs {
if err == nil && len(d) == 4 {
crc32c = uint32(d[0])<<24 + uint32(d[1])<<16 + uint32(d[2])<<8 + uint32(d[3])
}
+ var sha256 string
+ if o.CustomerEncryption != nil {
+ sha256 = o.CustomerEncryption.KeySha256
+ }
return &ObjectAttrs{
- Bucket: o.Bucket,
- Name: o.Name,
- ContentType: o.ContentType,
- ContentLanguage: o.ContentLanguage,
- CacheControl: o.CacheControl,
- ACL: acl,
- Owner: owner,
- ContentEncoding: o.ContentEncoding,
- Size: int64(o.Size),
- MD5: md5,
- CRC32C: crc32c,
- MediaLink: o.MediaLink,
- Metadata: o.Metadata,
- Generation: o.Generation,
- MetaGeneration: o.Metageneration,
- StorageClass: o.StorageClass,
- Created: convertTime(o.TimeCreated),
- Deleted: convertTime(o.TimeDeleted),
- Updated: convertTime(o.Updated),
+ Bucket: o.Bucket,
+ Name: o.Name,
+ ContentType: o.ContentType,
+ ContentLanguage: o.ContentLanguage,
+ CacheControl: o.CacheControl,
+ ACL: acl,
+ Owner: owner,
+ ContentEncoding: o.ContentEncoding,
+ Size: int64(o.Size),
+ MD5: md5,
+ CRC32C: crc32c,
+ MediaLink: o.MediaLink,
+ Metadata: o.Metadata,
+ Generation: o.Generation,
+ MetaGeneration: o.Metageneration,
+ StorageClass: o.StorageClass,
+ CustomerKeySHA256: sha256,
+ Created: convertTime(o.TimeCreated),
+ Deleted: convertTime(o.TimeDeleted),
+ Updated: convertTime(o.Updated),
}
}
@@ -1018,4 +1051,24 @@ func (c composeSourceObj) IfGenerationMatch(gen int64) {
}
}
+func setEncryptionHeaders(headers http.Header, key []byte, copySource bool) error {
+ if key == nil {
+ return nil
+ }
+ // TODO(jbd): Ask the API team to return a more user-friendly error
+ // and avoid doing this check at the client level.
+ if len(key) != 32 {
+ return errors.New("storage: not a 32-byte AES-256 key")
+ }
+ var cs string
+ if copySource {
+ cs = "copy-source-"
+ }
+ headers.Set("x-goog-"+cs+"encryption-algorithm", "AES256")
+ headers.Set("x-goog-"+cs+"encryption-key", base64.StdEncoding.EncodeToString(key))
+ keyHash := sha256.Sum256(key)
+ headers.Set("x-goog-"+cs+"encryption-key-sha256", base64.StdEncoding.EncodeToString(keyHash[:]))
+ return nil
+}
+
// TODO(jbd): Add storage.objects.watch.