From 73ef85bc5db590c22689e11be20737a3dd88168f Mon Sep 17 00:00:00 2001 From: Niall Sheridan Date: Wed, 28 Dec 2016 21:18:36 +0000 Subject: Update dependencies --- vendor/cloud.google.com/go/internal/retry.go | 55 ++++++++++++++ vendor/cloud.google.com/go/storage/bucket.go | 3 + vendor/cloud.google.com/go/storage/copy.go | 16 ++++ vendor/cloud.google.com/go/storage/doc.go | 2 +- vendor/cloud.google.com/go/storage/invoke.go | 19 ++--- vendor/cloud.google.com/go/storage/storage.go | 105 +++++++++++++++++++------- vendor/cloud.google.com/go/storage/writer.go | 6 +- 7 files changed, 167 insertions(+), 39 deletions(-) create mode 100644 vendor/cloud.google.com/go/internal/retry.go (limited to 'vendor/cloud.google.com') diff --git a/vendor/cloud.google.com/go/internal/retry.go b/vendor/cloud.google.com/go/internal/retry.go new file mode 100644 index 0000000..79995be --- /dev/null +++ b/vendor/cloud.google.com/go/internal/retry.go @@ -0,0 +1,55 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package internal + +import ( + "fmt" + "time" + + gax "github.com/googleapis/gax-go" + + "golang.org/x/net/context" +) + +// Retry calls the supplied function f repeatedly according to the provided +// backoff parameters. It returns when one of the following occurs: +// When f's first return value is true, Retry immediately returns with f's second +// return value. +// When the provided context is done, Retry returns with ctx.Err(). +func Retry(ctx context.Context, bo gax.Backoff, f func() (stop bool, err error)) error { + return retry(ctx, bo, f, gax.Sleep) +} + +func retry(ctx context.Context, bo gax.Backoff, f func() (stop bool, err error), + sleep func(context.Context, time.Duration) error) error { + var lastErr error + for { + stop, err := f() + if stop { + return err + } + // Remember the last "real" error from f. + if err != nil && err != context.Canceled && err != context.DeadlineExceeded { + lastErr = err + } + p := bo.Pause() + if cerr := sleep(ctx, p); cerr != nil { + if lastErr != nil { + return fmt.Errorf("%v; last function err: %v", cerr, lastErr) + } + return cerr + } + } +} diff --git a/vendor/cloud.google.com/go/storage/bucket.go b/vendor/cloud.google.com/go/storage/bucket.go index a2be0f4..f87fe33 100644 --- a/vendor/cloud.google.com/go/storage/bucket.go +++ b/vendor/cloud.google.com/go/storage/bucket.go @@ -246,6 +246,9 @@ func (it *ObjectIterator) fetch(pageSize int, pageToken string) (string, error) return err }) if err != nil { + if e, ok := err.(*googleapi.Error); ok && e.Code == http.StatusNotFound { + err = ErrBucketNotExist + } return "", err } for _, item := range resp.Items { diff --git a/vendor/cloud.google.com/go/storage/copy.go b/vendor/cloud.google.com/go/storage/copy.go index 6adb566..1f28455 100644 --- a/vendor/cloud.google.com/go/storage/copy.go +++ b/vendor/cloud.google.com/go/storage/copy.go @@ -110,6 +110,12 @@ func (c *Copier) callRewrite(ctx context.Context, src *ObjectHandle, rawObj *raw if err := applySourceConds(c.src.gen, c.src.conds, call); err != nil { return nil, err } + if err := setEncryptionHeaders(call.Header(), c.dst.encryptionKey, false); err != nil { + return nil, err + } + if err := setEncryptionHeaders(call.Header(), c.src.encryptionKey, true); err != nil { + return nil, err + } var res *raw.RewriteResponse var err error err = runWithRetry(ctx, func() error { res, err = call.Do(); return err }) @@ -123,6 +129,10 @@ func (c *Copier) callRewrite(ctx context.Context, src *ObjectHandle, rawObj *raw // ComposerFrom creates a Composer that can compose srcs into dst. // You can immediately call Run on the returned Composer, or you can // configure it first. +// +// The encryption key for the destination object will be used to decrypt all +// source objects and encrypt the destination object. It is an error +// to specify an encryption key for any of the source objects. func (dst *ObjectHandle) ComposerFrom(srcs ...*ObjectHandle) *Composer { return &Composer{dst: dst, srcs: srcs} } @@ -158,6 +168,9 @@ func (c *Composer) Run(ctx context.Context) (*ObjectAttrs, error) { if src.bucket != c.dst.bucket { return nil, fmt.Errorf("storage: all source objects must be in bucket %q, found %q", c.dst.bucket, src.bucket) } + if src.encryptionKey != nil { + return nil, fmt.Errorf("storage: compose source %s.%s must not have encryption key", src.bucket, src.object) + } srcObj := &raw.ComposeRequestSourceObjects{ Name: src.object, } @@ -171,6 +184,9 @@ func (c *Composer) Run(ctx context.Context) (*ObjectAttrs, error) { if err := applyConds("ComposeFrom destination", c.dst.gen, c.dst.conds, call); err != nil { return nil, err } + if err := setEncryptionHeaders(call.Header(), c.dst.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 }) diff --git a/vendor/cloud.google.com/go/storage/doc.go b/vendor/cloud.google.com/go/storage/doc.go index c23f2c8..cf6496b 100644 --- a/vendor/cloud.google.com/go/storage/doc.go +++ b/vendor/cloud.google.com/go/storage/doc.go @@ -23,7 +23,7 @@ All of the methods of this package use exponential backoff to retry calls that fail with certain errors, as described in https://cloud.google.com/storage/docs/exponential-backoff. -Note: This package is experimental and may make backwards-incompatible changes. +Note: This package is in beta. Some backwards-incompatible changes may occur. Creating a Client diff --git a/vendor/cloud.google.com/go/storage/invoke.go b/vendor/cloud.google.com/go/storage/invoke.go index 03b98f4..e8fc924 100644 --- a/vendor/cloud.google.com/go/storage/invoke.go +++ b/vendor/cloud.google.com/go/storage/invoke.go @@ -15,6 +15,7 @@ package storage import ( + "cloud.google.com/go/internal" gax "github.com/googleapis/gax-go" "golang.org/x/net/context" "google.golang.org/api/googleapi" @@ -23,24 +24,20 @@ import ( // runWithRetry calls the function until it returns nil or a non-retryable error, or // the context is done. func runWithRetry(ctx context.Context, call func() error) error { - var backoff gax.Backoff // use defaults for gax exponential backoff - for { - err := call() + return internal.Retry(ctx, gax.Backoff{}, func() (stop bool, err error) { + err = call() if err == nil { - return nil + return true, nil } e, ok := err.(*googleapi.Error) if !ok { - return err + return true, err } // Retry on 429 and 5xx, according to // https://cloud.google.com/storage/docs/exponential-backoff. if e.Code == 429 || (e.Code >= 500 && e.Code < 600) { - if err := gax.Sleep(ctx, backoff.Pause()); err != nil { - return err - } - continue + return false, nil } - return err - } + return true, err + }) } 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. diff --git a/vendor/cloud.google.com/go/storage/writer.go b/vendor/cloud.google.com/go/storage/writer.go index 8f98156..64d7543 100644 --- a/vendor/cloud.google.com/go/storage/writer.go +++ b/vendor/cloud.google.com/go/storage/writer.go @@ -85,7 +85,11 @@ func (w *Writer) open() error { Media(pr, mediaOpts...). Projection("full"). Context(w.ctx) - + if err := setEncryptionHeaders(call.Header(), w.o.encryptionKey, false); err != nil { + w.err = err + pr.CloseWithError(w.err) + return + } var resp *raw.Object err := applyConds("NewWriter", w.o.gen, w.o.conds, call) if err == nil { -- cgit v1.2.3