storage.go 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123
  1. // Copyright 2014 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package storage
  15. import (
  16. "bytes"
  17. "context"
  18. "crypto"
  19. "crypto/rand"
  20. "crypto/rsa"
  21. "crypto/sha256"
  22. "crypto/x509"
  23. "encoding/base64"
  24. "encoding/pem"
  25. "errors"
  26. "fmt"
  27. "io"
  28. "net/http"
  29. "net/url"
  30. "reflect"
  31. "regexp"
  32. "sort"
  33. "strconv"
  34. "strings"
  35. "time"
  36. "unicode/utf8"
  37. "cloud.google.com/go/internal/optional"
  38. "cloud.google.com/go/internal/trace"
  39. "cloud.google.com/go/internal/version"
  40. "google.golang.org/api/googleapi"
  41. "google.golang.org/api/option"
  42. raw "google.golang.org/api/storage/v1"
  43. htransport "google.golang.org/api/transport/http"
  44. )
  45. var (
  46. // ErrBucketNotExist indicates that the bucket does not exist.
  47. ErrBucketNotExist = errors.New("storage: bucket doesn't exist")
  48. // ErrObjectNotExist indicates that the object does not exist.
  49. ErrObjectNotExist = errors.New("storage: object doesn't exist")
  50. )
  51. const userAgent = "gcloud-golang-storage/20151204"
  52. const (
  53. // ScopeFullControl grants permissions to manage your
  54. // data and permissions in Google Cloud Storage.
  55. ScopeFullControl = raw.DevstorageFullControlScope
  56. // ScopeReadOnly grants permissions to
  57. // view your data in Google Cloud Storage.
  58. ScopeReadOnly = raw.DevstorageReadOnlyScope
  59. // ScopeReadWrite grants permissions to manage your
  60. // data in Google Cloud Storage.
  61. ScopeReadWrite = raw.DevstorageReadWriteScope
  62. )
  63. var xGoogHeader = fmt.Sprintf("gl-go/%s gccl/%s", version.Go(), version.Repo)
  64. func setClientHeader(headers http.Header) {
  65. headers.Set("x-goog-api-client", xGoogHeader)
  66. }
  67. // Client is a client for interacting with Google Cloud Storage.
  68. //
  69. // Clients should be reused instead of created as needed.
  70. // The methods of Client are safe for concurrent use by multiple goroutines.
  71. type Client struct {
  72. hc *http.Client
  73. raw *raw.Service
  74. }
  75. // NewClient creates a new Google Cloud Storage client.
  76. // The default scope is ScopeFullControl. To use a different scope, like ScopeReadOnly, use option.WithScopes.
  77. func NewClient(ctx context.Context, opts ...option.ClientOption) (*Client, error) {
  78. o := []option.ClientOption{
  79. option.WithScopes(ScopeFullControl),
  80. option.WithUserAgent(userAgent),
  81. }
  82. opts = append(o, opts...)
  83. hc, ep, err := htransport.NewClient(ctx, opts...)
  84. if err != nil {
  85. return nil, fmt.Errorf("dialing: %v", err)
  86. }
  87. rawService, err := raw.New(hc)
  88. if err != nil {
  89. return nil, fmt.Errorf("storage client: %v", err)
  90. }
  91. if ep != "" {
  92. rawService.BasePath = ep
  93. }
  94. return &Client{
  95. hc: hc,
  96. raw: rawService,
  97. }, nil
  98. }
  99. // Close closes the Client.
  100. //
  101. // Close need not be called at program exit.
  102. func (c *Client) Close() error {
  103. // Set fields to nil so that subsequent uses will panic.
  104. c.hc = nil
  105. c.raw = nil
  106. return nil
  107. }
  108. // SignedURLOptions allows you to restrict the access to the signed URL.
  109. type SignedURLOptions struct {
  110. // GoogleAccessID represents the authorizer of the signed URL generation.
  111. // It is typically the Google service account client email address from
  112. // the Google Developers Console in the form of "xxx@developer.gserviceaccount.com".
  113. // Required.
  114. GoogleAccessID string
  115. // PrivateKey is the Google service account private key. It is obtainable
  116. // from the Google Developers Console.
  117. // At https://console.developers.google.com/project/<your-project-id>/apiui/credential,
  118. // create a service account client ID or reuse one of your existing service account
  119. // credentials. Click on the "Generate new P12 key" to generate and download
  120. // a new private key. Once you download the P12 file, use the following command
  121. // to convert it into a PEM file.
  122. //
  123. // $ openssl pkcs12 -in key.p12 -passin pass:notasecret -out key.pem -nodes
  124. //
  125. // Provide the contents of the PEM file as a byte slice.
  126. // Exactly one of PrivateKey or SignBytes must be non-nil.
  127. PrivateKey []byte
  128. // SignBytes is a function for implementing custom signing.
  129. // If your application is running on Google App Engine, you can use appengine's internal signing function:
  130. // ctx := appengine.NewContext(request)
  131. // acc, _ := appengine.ServiceAccount(ctx)
  132. // url, err := SignedURL("bucket", "object", &SignedURLOptions{
  133. // GoogleAccessID: acc,
  134. // SignBytes: func(b []byte) ([]byte, error) {
  135. // _, signedBytes, err := appengine.SignBytes(ctx, b)
  136. // return signedBytes, err
  137. // },
  138. // // etc.
  139. // })
  140. //
  141. // Exactly one of PrivateKey or SignBytes must be non-nil.
  142. SignBytes func([]byte) ([]byte, error)
  143. // Method is the HTTP method to be used with the signed URL.
  144. // Signed URLs can be used with GET, HEAD, PUT, and DELETE requests.
  145. // Required.
  146. Method string
  147. // Expires is the expiration time on the signed URL. It must be
  148. // a datetime in the future.
  149. // Required.
  150. Expires time.Time
  151. // ContentType is the content type header the client must provide
  152. // to use the generated signed URL.
  153. // Optional.
  154. ContentType string
  155. // Headers is a list of extension headers the client must provide
  156. // in order to use the generated signed URL.
  157. // Optional.
  158. Headers []string
  159. // MD5 is the base64 encoded MD5 checksum of the file.
  160. // If provided, the client should provide the exact value on the request
  161. // header in order to use the signed URL.
  162. // Optional.
  163. MD5 string
  164. }
  165. var (
  166. canonicalHeaderRegexp = regexp.MustCompile(`(?i)^(x-goog-[^:]+):(.*)?$`)
  167. excludedCanonicalHeaders = map[string]bool{
  168. "x-goog-encryption-key": true,
  169. "x-goog-encryption-key-sha256": true,
  170. }
  171. )
  172. // sanitizeHeaders applies the specifications for canonical extension headers at
  173. // https://cloud.google.com/storage/docs/access-control/signed-urls#about-canonical-extension-headers.
  174. func sanitizeHeaders(hdrs []string) []string {
  175. headerMap := map[string][]string{}
  176. for _, hdr := range hdrs {
  177. // No leading or trailing whitespaces.
  178. sanitizedHeader := strings.TrimSpace(hdr)
  179. // Only keep canonical headers, discard any others.
  180. headerMatches := canonicalHeaderRegexp.FindStringSubmatch(sanitizedHeader)
  181. if len(headerMatches) == 0 {
  182. continue
  183. }
  184. header := strings.ToLower(strings.TrimSpace(headerMatches[1]))
  185. if excludedCanonicalHeaders[headerMatches[1]] {
  186. // Do not keep any deliberately excluded canonical headers when signing.
  187. continue
  188. }
  189. value := strings.TrimSpace(headerMatches[2])
  190. if len(value) > 0 {
  191. // Remove duplicate headers by appending the values of duplicates
  192. // in their order of appearance.
  193. headerMap[header] = append(headerMap[header], value)
  194. }
  195. }
  196. var sanitizedHeaders []string
  197. for header, values := range headerMap {
  198. // There should be no spaces around the colon separating the
  199. // header name from the header value or around the values
  200. // themselves. The values should be separated by commas.
  201. // NOTE: The semantics for headers without a value are not clear.
  202. // However from specifications these should be edge-cases
  203. // anyway and we should assume that there will be no
  204. // canonical headers using empty values. Any such headers
  205. // are discarded at the regexp stage above.
  206. sanitizedHeaders = append(
  207. sanitizedHeaders,
  208. fmt.Sprintf("%s:%s", header, strings.Join(values, ",")),
  209. )
  210. }
  211. sort.Strings(sanitizedHeaders)
  212. return sanitizedHeaders
  213. }
  214. // SignedURL returns a URL for the specified object. Signed URLs allow
  215. // the users access to a restricted resource for a limited time without having a
  216. // Google account or signing in. For more information about the signed
  217. // URLs, see https://cloud.google.com/storage/docs/accesscontrol#Signed-URLs.
  218. func SignedURL(bucket, name string, opts *SignedURLOptions) (string, error) {
  219. if opts == nil {
  220. return "", errors.New("storage: missing required SignedURLOptions")
  221. }
  222. if opts.GoogleAccessID == "" {
  223. return "", errors.New("storage: missing required GoogleAccessID")
  224. }
  225. if (opts.PrivateKey == nil) == (opts.SignBytes == nil) {
  226. return "", errors.New("storage: exactly one of PrivateKey or SignedBytes must be set")
  227. }
  228. if opts.Method == "" {
  229. return "", errors.New("storage: missing required method option")
  230. }
  231. if opts.Expires.IsZero() {
  232. return "", errors.New("storage: missing required expires option")
  233. }
  234. if opts.MD5 != "" {
  235. md5, err := base64.StdEncoding.DecodeString(opts.MD5)
  236. if err != nil || len(md5) != 16 {
  237. return "", errors.New("storage: invalid MD5 checksum")
  238. }
  239. }
  240. opts.Headers = sanitizeHeaders(opts.Headers)
  241. signBytes := opts.SignBytes
  242. if opts.PrivateKey != nil {
  243. key, err := parseKey(opts.PrivateKey)
  244. if err != nil {
  245. return "", err
  246. }
  247. signBytes = func(b []byte) ([]byte, error) {
  248. sum := sha256.Sum256(b)
  249. return rsa.SignPKCS1v15(
  250. rand.Reader,
  251. key,
  252. crypto.SHA256,
  253. sum[:],
  254. )
  255. }
  256. }
  257. u := &url.URL{
  258. Path: fmt.Sprintf("/%s/%s", bucket, name),
  259. }
  260. buf := &bytes.Buffer{}
  261. fmt.Fprintf(buf, "%s\n", opts.Method)
  262. fmt.Fprintf(buf, "%s\n", opts.MD5)
  263. fmt.Fprintf(buf, "%s\n", opts.ContentType)
  264. fmt.Fprintf(buf, "%d\n", opts.Expires.Unix())
  265. if len(opts.Headers) > 0 {
  266. fmt.Fprintf(buf, "%s\n", strings.Join(opts.Headers, "\n"))
  267. }
  268. fmt.Fprintf(buf, "%s", u.String())
  269. b, err := signBytes(buf.Bytes())
  270. if err != nil {
  271. return "", err
  272. }
  273. encoded := base64.StdEncoding.EncodeToString(b)
  274. u.Scheme = "https"
  275. u.Host = "storage.googleapis.com"
  276. q := u.Query()
  277. q.Set("GoogleAccessId", opts.GoogleAccessID)
  278. q.Set("Expires", fmt.Sprintf("%d", opts.Expires.Unix()))
  279. q.Set("Signature", string(encoded))
  280. u.RawQuery = q.Encode()
  281. return u.String(), nil
  282. }
  283. // ObjectHandle provides operations on an object in a Google Cloud Storage bucket.
  284. // Use BucketHandle.Object to get a handle.
  285. type ObjectHandle struct {
  286. c *Client
  287. bucket string
  288. object string
  289. acl ACLHandle
  290. gen int64 // a negative value indicates latest
  291. conds *Conditions
  292. encryptionKey []byte // AES-256 key
  293. userProject string // for requester-pays buckets
  294. readCompressed bool // Accept-Encoding: gzip
  295. }
  296. // ACL provides access to the object's access control list.
  297. // This controls who can read and write this object.
  298. // This call does not perform any network operations.
  299. func (o *ObjectHandle) ACL() *ACLHandle {
  300. return &o.acl
  301. }
  302. // Generation returns a new ObjectHandle that operates on a specific generation
  303. // of the object.
  304. // By default, the handle operates on the latest generation. Not
  305. // all operations work when given a specific generation; check the API
  306. // endpoints at https://cloud.google.com/storage/docs/json_api/ for details.
  307. func (o *ObjectHandle) Generation(gen int64) *ObjectHandle {
  308. o2 := *o
  309. o2.gen = gen
  310. return &o2
  311. }
  312. // If returns a new ObjectHandle that applies a set of preconditions.
  313. // Preconditions already set on the ObjectHandle are ignored.
  314. // Operations on the new handle will return an error if the preconditions are not
  315. // satisfied. See https://cloud.google.com/storage/docs/generations-preconditions
  316. // for more details.
  317. func (o *ObjectHandle) If(conds Conditions) *ObjectHandle {
  318. o2 := *o
  319. o2.conds = &conds
  320. return &o2
  321. }
  322. // Key returns a new ObjectHandle that uses the supplied encryption
  323. // key to encrypt and decrypt the object's contents.
  324. //
  325. // Encryption key must be a 32-byte AES-256 key.
  326. // See https://cloud.google.com/storage/docs/encryption for details.
  327. func (o *ObjectHandle) Key(encryptionKey []byte) *ObjectHandle {
  328. o2 := *o
  329. o2.encryptionKey = encryptionKey
  330. return &o2
  331. }
  332. // Attrs returns meta information about the object.
  333. // ErrObjectNotExist will be returned if the object is not found.
  334. func (o *ObjectHandle) Attrs(ctx context.Context) (attrs *ObjectAttrs, err error) {
  335. ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Object.Attrs")
  336. defer func() { trace.EndSpan(ctx, err) }()
  337. if err := o.validate(); err != nil {
  338. return nil, err
  339. }
  340. call := o.c.raw.Objects.Get(o.bucket, o.object).Projection("full").Context(ctx)
  341. if err := applyConds("Attrs", o.gen, o.conds, call); err != nil {
  342. return nil, err
  343. }
  344. if o.userProject != "" {
  345. call.UserProject(o.userProject)
  346. }
  347. if err := setEncryptionHeaders(call.Header(), o.encryptionKey, false); err != nil {
  348. return nil, err
  349. }
  350. var obj *raw.Object
  351. setClientHeader(call.Header())
  352. err = runWithRetry(ctx, func() error { obj, err = call.Do(); return err })
  353. if e, ok := err.(*googleapi.Error); ok && e.Code == http.StatusNotFound {
  354. return nil, ErrObjectNotExist
  355. }
  356. if err != nil {
  357. return nil, err
  358. }
  359. return newObject(obj), nil
  360. }
  361. // Update updates an object with the provided attributes.
  362. // All zero-value attributes are ignored.
  363. // ErrObjectNotExist will be returned if the object is not found.
  364. func (o *ObjectHandle) Update(ctx context.Context, uattrs ObjectAttrsToUpdate) (oa *ObjectAttrs, err error) {
  365. ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Object.Update")
  366. defer func() { trace.EndSpan(ctx, err) }()
  367. if err := o.validate(); err != nil {
  368. return nil, err
  369. }
  370. var attrs ObjectAttrs
  371. // Lists of fields to send, and set to null, in the JSON.
  372. var forceSendFields, nullFields []string
  373. if uattrs.ContentType != nil {
  374. attrs.ContentType = optional.ToString(uattrs.ContentType)
  375. // For ContentType, sending the empty string is a no-op.
  376. // Instead we send a null.
  377. if attrs.ContentType == "" {
  378. nullFields = append(nullFields, "ContentType")
  379. } else {
  380. forceSendFields = append(forceSendFields, "ContentType")
  381. }
  382. }
  383. if uattrs.ContentLanguage != nil {
  384. attrs.ContentLanguage = optional.ToString(uattrs.ContentLanguage)
  385. // For ContentLanguage it's an error to send the empty string.
  386. // Instead we send a null.
  387. if attrs.ContentLanguage == "" {
  388. nullFields = append(nullFields, "ContentLanguage")
  389. } else {
  390. forceSendFields = append(forceSendFields, "ContentLanguage")
  391. }
  392. }
  393. if uattrs.ContentEncoding != nil {
  394. attrs.ContentEncoding = optional.ToString(uattrs.ContentEncoding)
  395. forceSendFields = append(forceSendFields, "ContentEncoding")
  396. }
  397. if uattrs.ContentDisposition != nil {
  398. attrs.ContentDisposition = optional.ToString(uattrs.ContentDisposition)
  399. forceSendFields = append(forceSendFields, "ContentDisposition")
  400. }
  401. if uattrs.CacheControl != nil {
  402. attrs.CacheControl = optional.ToString(uattrs.CacheControl)
  403. forceSendFields = append(forceSendFields, "CacheControl")
  404. }
  405. if uattrs.EventBasedHold != nil {
  406. attrs.EventBasedHold = optional.ToBool(uattrs.EventBasedHold)
  407. forceSendFields = append(forceSendFields, "EventBasedHold")
  408. }
  409. if uattrs.TemporaryHold != nil {
  410. attrs.TemporaryHold = optional.ToBool(uattrs.TemporaryHold)
  411. forceSendFields = append(forceSendFields, "TemporaryHold")
  412. }
  413. if uattrs.Metadata != nil {
  414. attrs.Metadata = uattrs.Metadata
  415. if len(attrs.Metadata) == 0 {
  416. // Sending the empty map is a no-op. We send null instead.
  417. nullFields = append(nullFields, "Metadata")
  418. } else {
  419. forceSendFields = append(forceSendFields, "Metadata")
  420. }
  421. }
  422. if uattrs.ACL != nil {
  423. attrs.ACL = uattrs.ACL
  424. // It's an error to attempt to delete the ACL, so
  425. // we don't append to nullFields here.
  426. forceSendFields = append(forceSendFields, "Acl")
  427. }
  428. rawObj := attrs.toRawObject(o.bucket)
  429. rawObj.ForceSendFields = forceSendFields
  430. rawObj.NullFields = nullFields
  431. call := o.c.raw.Objects.Patch(o.bucket, o.object, rawObj).Projection("full").Context(ctx)
  432. if err := applyConds("Update", o.gen, o.conds, call); err != nil {
  433. return nil, err
  434. }
  435. if o.userProject != "" {
  436. call.UserProject(o.userProject)
  437. }
  438. if uattrs.PredefinedACL != "" {
  439. call.PredefinedAcl(uattrs.PredefinedACL)
  440. }
  441. if err := setEncryptionHeaders(call.Header(), o.encryptionKey, false); err != nil {
  442. return nil, err
  443. }
  444. var obj *raw.Object
  445. setClientHeader(call.Header())
  446. err = runWithRetry(ctx, func() error { obj, err = call.Do(); return err })
  447. if e, ok := err.(*googleapi.Error); ok && e.Code == http.StatusNotFound {
  448. return nil, ErrObjectNotExist
  449. }
  450. if err != nil {
  451. return nil, err
  452. }
  453. return newObject(obj), nil
  454. }
  455. // BucketName returns the name of the bucket.
  456. func (o *ObjectHandle) BucketName() string {
  457. return o.bucket
  458. }
  459. // ObjectName returns the name of the object.
  460. func (o *ObjectHandle) ObjectName() string {
  461. return o.object
  462. }
  463. // ObjectAttrsToUpdate is used to update the attributes of an object.
  464. // Only fields set to non-nil values will be updated.
  465. // Set a field to its zero value to delete it.
  466. //
  467. // For example, to change ContentType and delete ContentEncoding and
  468. // Metadata, use
  469. // ObjectAttrsToUpdate{
  470. // ContentType: "text/html",
  471. // ContentEncoding: "",
  472. // Metadata: map[string]string{},
  473. // }
  474. type ObjectAttrsToUpdate struct {
  475. EventBasedHold optional.Bool
  476. TemporaryHold optional.Bool
  477. ContentType optional.String
  478. ContentLanguage optional.String
  479. ContentEncoding optional.String
  480. ContentDisposition optional.String
  481. CacheControl optional.String
  482. Metadata map[string]string // set to map[string]string{} to delete
  483. ACL []ACLRule
  484. // If not empty, applies a predefined set of access controls. ACL must be nil.
  485. // See https://cloud.google.com/storage/docs/json_api/v1/objects/patch.
  486. PredefinedACL string
  487. }
  488. // Delete deletes the single specified object.
  489. func (o *ObjectHandle) Delete(ctx context.Context) error {
  490. if err := o.validate(); err != nil {
  491. return err
  492. }
  493. call := o.c.raw.Objects.Delete(o.bucket, o.object).Context(ctx)
  494. if err := applyConds("Delete", o.gen, o.conds, call); err != nil {
  495. return err
  496. }
  497. if o.userProject != "" {
  498. call.UserProject(o.userProject)
  499. }
  500. // Encryption doesn't apply to Delete.
  501. setClientHeader(call.Header())
  502. err := runWithRetry(ctx, func() error { return call.Do() })
  503. switch e := err.(type) {
  504. case nil:
  505. return nil
  506. case *googleapi.Error:
  507. if e.Code == http.StatusNotFound {
  508. return ErrObjectNotExist
  509. }
  510. }
  511. return err
  512. }
  513. // ReadCompressed when true causes the read to happen without decompressing.
  514. func (o *ObjectHandle) ReadCompressed(compressed bool) *ObjectHandle {
  515. o2 := *o
  516. o2.readCompressed = compressed
  517. return &o2
  518. }
  519. // NewWriter returns a storage Writer that writes to the GCS object
  520. // associated with this ObjectHandle.
  521. //
  522. // A new object will be created unless an object with this name already exists.
  523. // Otherwise any previous object with the same name will be replaced.
  524. // The object will not be available (and any previous object will remain)
  525. // until Close has been called.
  526. //
  527. // Attributes can be set on the object by modifying the returned Writer's
  528. // ObjectAttrs field before the first call to Write. If no ContentType
  529. // attribute is specified, the content type will be automatically sniffed
  530. // using net/http.DetectContentType.
  531. //
  532. // It is the caller's responsibility to call Close when writing is done. To
  533. // stop writing without saving the data, cancel the context.
  534. func (o *ObjectHandle) NewWriter(ctx context.Context) *Writer {
  535. return &Writer{
  536. ctx: ctx,
  537. o: o,
  538. donec: make(chan struct{}),
  539. ObjectAttrs: ObjectAttrs{Name: o.object},
  540. ChunkSize: googleapi.DefaultUploadChunkSize,
  541. }
  542. }
  543. func (o *ObjectHandle) validate() error {
  544. if o.bucket == "" {
  545. return errors.New("storage: bucket name is empty")
  546. }
  547. if o.object == "" {
  548. return errors.New("storage: object name is empty")
  549. }
  550. if !utf8.ValidString(o.object) {
  551. return fmt.Errorf("storage: object name %q is not valid UTF-8", o.object)
  552. }
  553. return nil
  554. }
  555. // parseKey converts the binary contents of a private key file to an
  556. // *rsa.PrivateKey. It detects whether the private key is in a PEM container or
  557. // not. If so, it extracts the private key from PEM container before
  558. // conversion. It only supports PEM containers with no passphrase.
  559. func parseKey(key []byte) (*rsa.PrivateKey, error) {
  560. if block, _ := pem.Decode(key); block != nil {
  561. key = block.Bytes
  562. }
  563. parsedKey, err := x509.ParsePKCS8PrivateKey(key)
  564. if err != nil {
  565. parsedKey, err = x509.ParsePKCS1PrivateKey(key)
  566. if err != nil {
  567. return nil, err
  568. }
  569. }
  570. parsed, ok := parsedKey.(*rsa.PrivateKey)
  571. if !ok {
  572. return nil, errors.New("oauth2: private key is invalid")
  573. }
  574. return parsed, nil
  575. }
  576. // toRawObject copies the editable attributes from o to the raw library's Object type.
  577. func (o *ObjectAttrs) toRawObject(bucket string) *raw.Object {
  578. var ret string
  579. if !o.RetentionExpirationTime.IsZero() {
  580. ret = o.RetentionExpirationTime.Format(time.RFC3339)
  581. }
  582. return &raw.Object{
  583. Bucket: bucket,
  584. Name: o.Name,
  585. EventBasedHold: o.EventBasedHold,
  586. TemporaryHold: o.TemporaryHold,
  587. RetentionExpirationTime: ret,
  588. ContentType: o.ContentType,
  589. ContentEncoding: o.ContentEncoding,
  590. ContentLanguage: o.ContentLanguage,
  591. CacheControl: o.CacheControl,
  592. ContentDisposition: o.ContentDisposition,
  593. StorageClass: o.StorageClass,
  594. Acl: toRawObjectACL(o.ACL),
  595. Metadata: o.Metadata,
  596. }
  597. }
  598. // ObjectAttrs represents the metadata for a Google Cloud Storage (GCS) object.
  599. type ObjectAttrs struct {
  600. // Bucket is the name of the bucket containing this GCS object.
  601. // This field is read-only.
  602. Bucket string
  603. // Name is the name of the object within the bucket.
  604. // This field is read-only.
  605. Name string
  606. // ContentType is the MIME type of the object's content.
  607. ContentType string
  608. // ContentLanguage is the content language of the object's content.
  609. ContentLanguage string
  610. // CacheControl is the Cache-Control header to be sent in the response
  611. // headers when serving the object data.
  612. CacheControl string
  613. // EventBasedHold specifies whether an object is under event-based hold. New
  614. // objects created in a bucket whose DefaultEventBasedHold is set will
  615. // default to that value.
  616. EventBasedHold bool
  617. // TemporaryHold specifies whether an object is under temporary hold. While
  618. // this flag is set to true, the object is protected against deletion and
  619. // overwrites.
  620. TemporaryHold bool
  621. // RetentionExpirationTime is a server-determined value that specifies the
  622. // earliest time that the object's retention period expires.
  623. // This is a read-only field.
  624. RetentionExpirationTime time.Time
  625. // ACL is the list of access control rules for the object.
  626. ACL []ACLRule
  627. // If not empty, applies a predefined set of access controls. It should be set
  628. // only when writing, copying or composing an object. When copying or composing,
  629. // it acts as the destinationPredefinedAcl parameter.
  630. // PredefinedACL is always empty for ObjectAttrs returned from the service.
  631. // See https://cloud.google.com/storage/docs/json_api/v1/objects/insert
  632. // for valid values.
  633. PredefinedACL string
  634. // Owner is the owner of the object. This field is read-only.
  635. //
  636. // If non-zero, it is in the form of "user-<userId>".
  637. Owner string
  638. // Size is the length of the object's content. This field is read-only.
  639. Size int64
  640. // ContentEncoding is the encoding of the object's content.
  641. ContentEncoding string
  642. // ContentDisposition is the optional Content-Disposition header of the object
  643. // sent in the response headers.
  644. ContentDisposition string
  645. // MD5 is the MD5 hash of the object's content. This field is read-only,
  646. // except when used from a Writer. If set on a Writer, the uploaded
  647. // data is rejected if its MD5 hash does not match this field.
  648. MD5 []byte
  649. // CRC32C is the CRC32 checksum of the object's content using
  650. // the Castagnoli93 polynomial. This field is read-only, except when
  651. // used from a Writer. If set on a Writer and Writer.SendCRC32C
  652. // is true, the uploaded data is rejected if its CRC32c hash does not
  653. // match this field.
  654. CRC32C uint32
  655. // MediaLink is an URL to the object's content. This field is read-only.
  656. MediaLink string
  657. // Metadata represents user-provided metadata, in key/value pairs.
  658. // It can be nil if no metadata is provided.
  659. Metadata map[string]string
  660. // Generation is the generation number of the object's content.
  661. // This field is read-only.
  662. Generation int64
  663. // Metageneration is the version of the metadata for this
  664. // object at this generation. This field is used for preconditions
  665. // and for detecting changes in metadata. A metageneration number
  666. // is only meaningful in the context of a particular generation
  667. // of a particular object. This field is read-only.
  668. Metageneration int64
  669. // StorageClass is the storage class of the object.
  670. // This value defines how objects in the bucket are stored and
  671. // determines the SLA and the cost of storage. Typical values are
  672. // "MULTI_REGIONAL", "REGIONAL", "NEARLINE", "COLDLINE", "STANDARD"
  673. // and "DURABLE_REDUCED_AVAILABILITY".
  674. // It defaults to "STANDARD", which is equivalent to "MULTI_REGIONAL"
  675. // or "REGIONAL" depending on the bucket's location settings.
  676. StorageClass string
  677. // Created is the time the object was created. This field is read-only.
  678. Created time.Time
  679. // Deleted is the time the object was deleted.
  680. // If not deleted, it is the zero value. This field is read-only.
  681. Deleted time.Time
  682. // Updated is the creation or modification time of the object.
  683. // For buckets with versioning enabled, changing an object's
  684. // metadata does not change this property. This field is read-only.
  685. Updated time.Time
  686. // CustomerKeySHA256 is the base64-encoded SHA-256 hash of the
  687. // customer-supplied encryption key for the object. It is empty if there is
  688. // no customer-supplied encryption key.
  689. // See // https://cloud.google.com/storage/docs/encryption for more about
  690. // encryption in Google Cloud Storage.
  691. CustomerKeySHA256 string
  692. // Cloud KMS key name, in the form
  693. // projects/P/locations/L/keyRings/R/cryptoKeys/K, used to encrypt this object,
  694. // if the object is encrypted by such a key.
  695. //
  696. // Providing both a KMSKeyName and a customer-supplied encryption key (via
  697. // ObjectHandle.Key) will result in an error when writing an object.
  698. KMSKeyName string
  699. // Prefix is set only for ObjectAttrs which represent synthetic "directory
  700. // entries" when iterating over buckets using Query.Delimiter. See
  701. // ObjectIterator.Next. When set, no other fields in ObjectAttrs will be
  702. // populated.
  703. Prefix string
  704. }
  705. // convertTime converts a time in RFC3339 format to time.Time.
  706. // If any error occurs in parsing, the zero-value time.Time is silently returned.
  707. func convertTime(t string) time.Time {
  708. var r time.Time
  709. if t != "" {
  710. r, _ = time.Parse(time.RFC3339, t)
  711. }
  712. return r
  713. }
  714. func newObject(o *raw.Object) *ObjectAttrs {
  715. if o == nil {
  716. return nil
  717. }
  718. owner := ""
  719. if o.Owner != nil {
  720. owner = o.Owner.Entity
  721. }
  722. md5, _ := base64.StdEncoding.DecodeString(o.Md5Hash)
  723. crc32c, _ := decodeUint32(o.Crc32c)
  724. var sha256 string
  725. if o.CustomerEncryption != nil {
  726. sha256 = o.CustomerEncryption.KeySha256
  727. }
  728. return &ObjectAttrs{
  729. Bucket: o.Bucket,
  730. Name: o.Name,
  731. ContentType: o.ContentType,
  732. ContentLanguage: o.ContentLanguage,
  733. CacheControl: o.CacheControl,
  734. EventBasedHold: o.EventBasedHold,
  735. TemporaryHold: o.TemporaryHold,
  736. RetentionExpirationTime: convertTime(o.RetentionExpirationTime),
  737. ACL: toObjectACLRules(o.Acl),
  738. Owner: owner,
  739. ContentEncoding: o.ContentEncoding,
  740. ContentDisposition: o.ContentDisposition,
  741. Size: int64(o.Size),
  742. MD5: md5,
  743. CRC32C: crc32c,
  744. MediaLink: o.MediaLink,
  745. Metadata: o.Metadata,
  746. Generation: o.Generation,
  747. Metageneration: o.Metageneration,
  748. StorageClass: o.StorageClass,
  749. CustomerKeySHA256: sha256,
  750. KMSKeyName: o.KmsKeyName,
  751. Created: convertTime(o.TimeCreated),
  752. Deleted: convertTime(o.TimeDeleted),
  753. Updated: convertTime(o.Updated),
  754. }
  755. }
  756. // Decode a uint32 encoded in Base64 in big-endian byte order.
  757. func decodeUint32(b64 string) (uint32, error) {
  758. d, err := base64.StdEncoding.DecodeString(b64)
  759. if err != nil {
  760. return 0, err
  761. }
  762. if len(d) != 4 {
  763. return 0, fmt.Errorf("storage: %q does not encode a 32-bit value", d)
  764. }
  765. return uint32(d[0])<<24 + uint32(d[1])<<16 + uint32(d[2])<<8 + uint32(d[3]), nil
  766. }
  767. // Encode a uint32 as Base64 in big-endian byte order.
  768. func encodeUint32(u uint32) string {
  769. b := []byte{byte(u >> 24), byte(u >> 16), byte(u >> 8), byte(u)}
  770. return base64.StdEncoding.EncodeToString(b)
  771. }
  772. // Query represents a query to filter objects from a bucket.
  773. type Query struct {
  774. // Delimiter returns results in a directory-like fashion.
  775. // Results will contain only objects whose names, aside from the
  776. // prefix, do not contain delimiter. Objects whose names,
  777. // aside from the prefix, contain delimiter will have their name,
  778. // truncated after the delimiter, returned in prefixes.
  779. // Duplicate prefixes are omitted.
  780. // Optional.
  781. Delimiter string
  782. // Prefix is the prefix filter to query objects
  783. // whose names begin with this prefix.
  784. // Optional.
  785. Prefix string
  786. // Versions indicates whether multiple versions of the same
  787. // object will be included in the results.
  788. Versions bool
  789. }
  790. // contentTyper implements ContentTyper to enable an
  791. // io.ReadCloser to specify its MIME type.
  792. type contentTyper struct {
  793. io.Reader
  794. t string
  795. }
  796. func (c *contentTyper) ContentType() string {
  797. return c.t
  798. }
  799. // Conditions constrain methods to act on specific generations of
  800. // objects.
  801. //
  802. // The zero value is an empty set of constraints. Not all conditions or
  803. // combinations of conditions are applicable to all methods.
  804. // See https://cloud.google.com/storage/docs/generations-preconditions
  805. // for details on how these operate.
  806. type Conditions struct {
  807. // Generation constraints.
  808. // At most one of the following can be set to a non-zero value.
  809. // GenerationMatch specifies that the object must have the given generation
  810. // for the operation to occur.
  811. // If GenerationMatch is zero, it has no effect.
  812. // Use DoesNotExist to specify that the object does not exist in the bucket.
  813. GenerationMatch int64
  814. // GenerationNotMatch specifies that the object must not have the given
  815. // generation for the operation to occur.
  816. // If GenerationNotMatch is zero, it has no effect.
  817. GenerationNotMatch int64
  818. // DoesNotExist specifies that the object must not exist in the bucket for
  819. // the operation to occur.
  820. // If DoesNotExist is false, it has no effect.
  821. DoesNotExist bool
  822. // Metadata generation constraints.
  823. // At most one of the following can be set to a non-zero value.
  824. // MetagenerationMatch specifies that the object must have the given
  825. // metageneration for the operation to occur.
  826. // If MetagenerationMatch is zero, it has no effect.
  827. MetagenerationMatch int64
  828. // MetagenerationNotMatch specifies that the object must not have the given
  829. // metageneration for the operation to occur.
  830. // If MetagenerationNotMatch is zero, it has no effect.
  831. MetagenerationNotMatch int64
  832. }
  833. func (c *Conditions) validate(method string) error {
  834. if *c == (Conditions{}) {
  835. return fmt.Errorf("storage: %s: empty conditions", method)
  836. }
  837. if !c.isGenerationValid() {
  838. return fmt.Errorf("storage: %s: multiple conditions specified for generation", method)
  839. }
  840. if !c.isMetagenerationValid() {
  841. return fmt.Errorf("storage: %s: multiple conditions specified for metageneration", method)
  842. }
  843. return nil
  844. }
  845. func (c *Conditions) isGenerationValid() bool {
  846. n := 0
  847. if c.GenerationMatch != 0 {
  848. n++
  849. }
  850. if c.GenerationNotMatch != 0 {
  851. n++
  852. }
  853. if c.DoesNotExist {
  854. n++
  855. }
  856. return n <= 1
  857. }
  858. func (c *Conditions) isMetagenerationValid() bool {
  859. return c.MetagenerationMatch == 0 || c.MetagenerationNotMatch == 0
  860. }
  861. // applyConds modifies the provided call using the conditions in conds.
  862. // call is something that quacks like a *raw.WhateverCall.
  863. func applyConds(method string, gen int64, conds *Conditions, call interface{}) error {
  864. cval := reflect.ValueOf(call)
  865. if gen >= 0 {
  866. if !setConditionField(cval, "Generation", gen) {
  867. return fmt.Errorf("storage: %s: generation not supported", method)
  868. }
  869. }
  870. if conds == nil {
  871. return nil
  872. }
  873. if err := conds.validate(method); err != nil {
  874. return err
  875. }
  876. switch {
  877. case conds.GenerationMatch != 0:
  878. if !setConditionField(cval, "IfGenerationMatch", conds.GenerationMatch) {
  879. return fmt.Errorf("storage: %s: ifGenerationMatch not supported", method)
  880. }
  881. case conds.GenerationNotMatch != 0:
  882. if !setConditionField(cval, "IfGenerationNotMatch", conds.GenerationNotMatch) {
  883. return fmt.Errorf("storage: %s: ifGenerationNotMatch not supported", method)
  884. }
  885. case conds.DoesNotExist:
  886. if !setConditionField(cval, "IfGenerationMatch", int64(0)) {
  887. return fmt.Errorf("storage: %s: DoesNotExist not supported", method)
  888. }
  889. }
  890. switch {
  891. case conds.MetagenerationMatch != 0:
  892. if !setConditionField(cval, "IfMetagenerationMatch", conds.MetagenerationMatch) {
  893. return fmt.Errorf("storage: %s: ifMetagenerationMatch not supported", method)
  894. }
  895. case conds.MetagenerationNotMatch != 0:
  896. if !setConditionField(cval, "IfMetagenerationNotMatch", conds.MetagenerationNotMatch) {
  897. return fmt.Errorf("storage: %s: ifMetagenerationNotMatch not supported", method)
  898. }
  899. }
  900. return nil
  901. }
  902. func applySourceConds(gen int64, conds *Conditions, call *raw.ObjectsRewriteCall) error {
  903. if gen >= 0 {
  904. call.SourceGeneration(gen)
  905. }
  906. if conds == nil {
  907. return nil
  908. }
  909. if err := conds.validate("CopyTo source"); err != nil {
  910. return err
  911. }
  912. switch {
  913. case conds.GenerationMatch != 0:
  914. call.IfSourceGenerationMatch(conds.GenerationMatch)
  915. case conds.GenerationNotMatch != 0:
  916. call.IfSourceGenerationNotMatch(conds.GenerationNotMatch)
  917. case conds.DoesNotExist:
  918. call.IfSourceGenerationMatch(0)
  919. }
  920. switch {
  921. case conds.MetagenerationMatch != 0:
  922. call.IfSourceMetagenerationMatch(conds.MetagenerationMatch)
  923. case conds.MetagenerationNotMatch != 0:
  924. call.IfSourceMetagenerationNotMatch(conds.MetagenerationNotMatch)
  925. }
  926. return nil
  927. }
  928. // setConditionField sets a field on a *raw.WhateverCall.
  929. // We can't use anonymous interfaces because the return type is
  930. // different, since the field setters are builders.
  931. func setConditionField(call reflect.Value, name string, value interface{}) bool {
  932. m := call.MethodByName(name)
  933. if !m.IsValid() {
  934. return false
  935. }
  936. m.Call([]reflect.Value{reflect.ValueOf(value)})
  937. return true
  938. }
  939. // conditionsQuery returns the generation and conditions as a URL query
  940. // string suitable for URL.RawQuery. It assumes that the conditions
  941. // have been validated.
  942. func conditionsQuery(gen int64, conds *Conditions) string {
  943. // URL escapes are elided because integer strings are URL-safe.
  944. var buf []byte
  945. appendParam := func(s string, n int64) {
  946. if len(buf) > 0 {
  947. buf = append(buf, '&')
  948. }
  949. buf = append(buf, s...)
  950. buf = strconv.AppendInt(buf, n, 10)
  951. }
  952. if gen >= 0 {
  953. appendParam("generation=", gen)
  954. }
  955. if conds == nil {
  956. return string(buf)
  957. }
  958. switch {
  959. case conds.GenerationMatch != 0:
  960. appendParam("ifGenerationMatch=", conds.GenerationMatch)
  961. case conds.GenerationNotMatch != 0:
  962. appendParam("ifGenerationNotMatch=", conds.GenerationNotMatch)
  963. case conds.DoesNotExist:
  964. appendParam("ifGenerationMatch=", 0)
  965. }
  966. switch {
  967. case conds.MetagenerationMatch != 0:
  968. appendParam("ifMetagenerationMatch=", conds.MetagenerationMatch)
  969. case conds.MetagenerationNotMatch != 0:
  970. appendParam("ifMetagenerationNotMatch=", conds.MetagenerationNotMatch)
  971. }
  972. return string(buf)
  973. }
  974. // composeSourceObj wraps a *raw.ComposeRequestSourceObjects, but adds the methods
  975. // that modifyCall searches for by name.
  976. type composeSourceObj struct {
  977. src *raw.ComposeRequestSourceObjects
  978. }
  979. func (c composeSourceObj) Generation(gen int64) {
  980. c.src.Generation = gen
  981. }
  982. func (c composeSourceObj) IfGenerationMatch(gen int64) {
  983. // It's safe to overwrite ObjectPreconditions, since its only field is
  984. // IfGenerationMatch.
  985. c.src.ObjectPreconditions = &raw.ComposeRequestSourceObjectsObjectPreconditions{
  986. IfGenerationMatch: gen,
  987. }
  988. }
  989. func setEncryptionHeaders(headers http.Header, key []byte, copySource bool) error {
  990. if key == nil {
  991. return nil
  992. }
  993. // TODO(jbd): Ask the API team to return a more user-friendly error
  994. // and avoid doing this check at the client level.
  995. if len(key) != 32 {
  996. return errors.New("storage: not a 32-byte AES-256 key")
  997. }
  998. var cs string
  999. if copySource {
  1000. cs = "copy-source-"
  1001. }
  1002. headers.Set("x-goog-"+cs+"encryption-algorithm", "AES256")
  1003. headers.Set("x-goog-"+cs+"encryption-key", base64.StdEncoding.EncodeToString(key))
  1004. keyHash := sha256.Sum256(key)
  1005. headers.Set("x-goog-"+cs+"encryption-key-sha256", base64.StdEncoding.EncodeToString(keyHash[:]))
  1006. return nil
  1007. }
  1008. // ServiceAccount fetches the email address of the given project's Google Cloud Storage service account.
  1009. func (c *Client) ServiceAccount(ctx context.Context, projectID string) (string, error) {
  1010. r := c.raw.Projects.ServiceAccount.Get(projectID)
  1011. res, err := r.Context(ctx).Do()
  1012. if err != nil {
  1013. return "", err
  1014. }
  1015. return res.EmailAddress, nil
  1016. }