google-cloud-storage 1.18.1 → 1.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/AUTHENTICATION.md +17 -30
  3. data/CHANGELOG.md +312 -0
  4. data/CONTRIBUTING.md +4 -5
  5. data/LOGGING.md +1 -1
  6. data/OVERVIEW.md +37 -5
  7. data/TROUBLESHOOTING.md +2 -8
  8. data/lib/google/cloud/storage/bucket/acl.rb +40 -40
  9. data/lib/google/cloud/storage/bucket/cors.rb +4 -1
  10. data/lib/google/cloud/storage/bucket/lifecycle.rb +259 -44
  11. data/lib/google/cloud/storage/bucket/list.rb +3 -3
  12. data/lib/google/cloud/storage/bucket.rb +1096 -172
  13. data/lib/google/cloud/storage/convert.rb +4 -3
  14. data/lib/google/cloud/storage/credentials.rb +16 -14
  15. data/lib/google/cloud/storage/errors.rb +7 -2
  16. data/lib/google/cloud/storage/file/acl.rb +181 -20
  17. data/lib/google/cloud/storage/file/list.rb +10 -8
  18. data/lib/google/cloud/storage/file/signer_v2.rb +36 -18
  19. data/lib/google/cloud/storage/file/signer_v4.rb +249 -61
  20. data/lib/google/cloud/storage/file/verifier.rb +2 -2
  21. data/lib/google/cloud/storage/file.rb +450 -84
  22. data/lib/google/cloud/storage/hmac_key/list.rb +182 -0
  23. data/lib/google/cloud/storage/hmac_key.rb +316 -0
  24. data/lib/google/cloud/storage/policy/binding.rb +246 -0
  25. data/lib/google/cloud/storage/policy/bindings.rb +196 -0
  26. data/lib/google/cloud/storage/policy/condition.rb +138 -0
  27. data/lib/google/cloud/storage/policy.rb +277 -24
  28. data/lib/google/cloud/storage/post_object.rb +20 -2
  29. data/lib/google/cloud/storage/project.rb +249 -50
  30. data/lib/google/cloud/storage/service.rb +479 -288
  31. data/lib/google/cloud/storage/version.rb +1 -1
  32. data/lib/google/cloud/storage.rb +86 -16
  33. data/lib/google-cloud-storage.rb +54 -7
  34. metadata +74 -27
@@ -15,6 +15,7 @@
15
15
 
16
16
  require "google/cloud/errors"
17
17
  require "google/apis/storage_v1"
18
+ require "google/cloud/storage/policy/bindings"
18
19
 
19
20
  module Google
20
21
  module Cloud
@@ -22,7 +23,9 @@ module Google
22
23
  ##
23
24
  # # Policy
24
25
  #
25
- # Represents a Cloud IAM Policy for the Cloud Storage service.
26
+ # An abstract Cloud IAM Policy for the Cloud Storage service. See concrete
27
+ # subclasses {Google::Cloud::Storage::PolicyV1} and
28
+ # {Google::Cloud::Storage::PolicyV3}.
26
29
  #
27
30
  # A common pattern for updating a resource's metadata, such as its Policy,
28
31
  # is to read the current data from the service, update the data locally,
@@ -49,8 +52,45 @@ module Google
49
52
  # @attr [String] etag Used to verify whether the policy has changed since
50
53
  # the last request. The policy will be written only if the `etag` values
51
54
  # match.
52
- # @attr [Hash{String => Array<String>}] roles The bindings that associate
53
- # roles with an array of members. See [Understanding
55
+ # @attr [Integer] version The syntax schema version of the policy. Each version
56
+ # of the policy contains a specific syntax schema that can be used by bindings.
57
+ # The newer version may contain role bindings with the newer syntax schema
58
+ # that is unsupported by earlier versions. This field is not intended to
59
+ # be used for any purposes other than policy syntax schema control.
60
+ #
61
+ # The following policy versions are valid:
62
+ #
63
+ # * 1 - The first version of Cloud IAM policy schema. Supports binding one
64
+ # role to one or more members. Does not support conditional bindings.
65
+ # * 3 - Introduces the condition field in the role binding, which further
66
+ # constrains the role binding via context-based and attribute-based rules.
67
+ # See [Understanding policies](https://cloud.google.com/iam/docs/policies)
68
+ # and [Overview of Cloud IAM Conditions](https://cloud.google.com/iam/docs/conditions-overview)
69
+ # for more information.
70
+ #
71
+ class Policy
72
+ attr_reader :etag
73
+ attr_reader :version
74
+
75
+ ##
76
+ # @private Creates a Policy object.
77
+ def initialize etag, version
78
+ @etag = etag
79
+ @version = version
80
+ end
81
+ end
82
+
83
+ ##
84
+ # A subclass of {Google::Cloud::Storage::Policy} that supports access to {#roles}
85
+ # and related helpers. Attempts to call {#bindings} and {#version=} will
86
+ # raise a runtime error. To update the Policy version and add bindings with a newer
87
+ # syntax, use {Google::Cloud::Storage::PolicyV3} instead by calling
88
+ # {Google::Cloud::Storage::Bucket#policy} with `requested_policy_version: 3`. To
89
+ # obtain instances of this class, call {Google::Cloud::Storage::Bucket#policy}
90
+ # without the `requested_policy_version` keyword argument.
91
+ #
92
+ # @attr [Hash] roles Returns the version 1 bindings (no conditions) as a hash that
93
+ # associates roles with arrays of members. See [Understanding
54
94
  # Roles](https://cloud.google.com/iam/docs/understanding-roles) for a
55
95
  # listing of primitive and curated roles. See [Buckets:
56
96
  # setIamPolicy](https://cloud.google.com/storage/docs/json_api/v1/buckets/setIamPolicy)
@@ -60,22 +100,22 @@ module Google
60
100
  # require "google/cloud/storage"
61
101
  #
62
102
  # storage = Google::Cloud::Storage.new
63
- #
64
- # bucket = storage.bucket "my-todo-app"
103
+ # bucket = storage.bucket "my-bucket"
65
104
  #
66
105
  # bucket.policy do |p|
106
+ # p.version # the value is 1
67
107
  # p.remove "roles/storage.admin", "user:owner@example.com"
68
108
  # p.add "roles/storage.admin", "user:newowner@example.com"
69
109
  # p.roles["roles/storage.objectViewer"] = ["allUsers"]
70
110
  # end
71
111
  #
72
- class Policy
73
- attr_reader :etag, :roles
112
+ class PolicyV1 < Policy
113
+ attr_reader :roles
74
114
 
75
115
  ##
76
- # @private Creates a Policy object.
77
- def initialize etag, roles
78
- @etag = etag
116
+ # @private Creates a PolicyV1 object.
117
+ def initialize etag, version, roles
118
+ super etag, version
79
119
  @roles = roles
80
120
  end
81
121
 
@@ -97,7 +137,7 @@ module Google
97
137
  #
98
138
  # storage = Google::Cloud::Storage.new
99
139
  #
100
- # bucket = storage.bucket "my-todo-app"
140
+ # bucket = storage.bucket "my-bucket"
101
141
  #
102
142
  # bucket.policy do |p|
103
143
  # p.add "roles/storage.admin", "user:newowner@example.com"
@@ -125,7 +165,7 @@ module Google
125
165
  #
126
166
  # storage = Google::Cloud::Storage.new
127
167
  #
128
- # bucket = storage.bucket "my-todo-app"
168
+ # bucket = storage.bucket "my-bucket"
129
169
  #
130
170
  # bucket.policy do |p|
131
171
  # p.remove "roles/storage.admin", "user:owner@example.com"
@@ -151,7 +191,7 @@ module Google
151
191
  #
152
192
  # storage = Google::Cloud::Storage.new
153
193
  #
154
- # bucket = storage.bucket "my-todo-app"
194
+ # bucket = storage.bucket "my-bucket"
155
195
  #
156
196
  # bucket.policy do |p|
157
197
  # p.role("roles/storage.admin") << "user:owner@example.com"
@@ -170,28 +210,41 @@ module Google
170
210
  # @return [Policy]
171
211
  #
172
212
  def deep_dup
173
- warn "DEPRECATED: Storage::Policy#deep_dup"
213
+ warn "DEPRECATED: Storage::PolicyV1#deep_dup"
174
214
  dup.tap do |p|
175
- roles_dup = p.roles.each_with_object({}) do |(k, v), memo|
176
- memo[k] = v.dup rescue value
215
+ roles_dup = p.roles.transform_values do |v|
216
+ v.dup rescue value
177
217
  end
178
218
  p.instance_variable_set :@roles, roles_dup
179
219
  end
180
220
  end
181
221
 
222
+ ##
223
+ # @private Illegal operation in PolicyV1. Use {#roles} instead.
224
+ #
225
+ # @raise [RuntimeError] If called on this class.
226
+ #
227
+ def bindings
228
+ raise "Illegal operation unless using PolicyV3. Use #roles instead."
229
+ end
230
+
231
+ ##
232
+ # @private Illegal operation in PolicyV1. Use {Google::Cloud::Storage::PolicyV3#version=} instead.
233
+ #
234
+ # @raise [RuntimeError] If called on this class.
235
+ #
236
+ def version=(*)
237
+ raise "Illegal operation unless using PolicyV3."
238
+ end
239
+
182
240
  ##
183
241
  # @private Convert the Policy to a
184
242
  # Google::Apis::StorageV1::Policy.
185
243
  def to_gapi
186
244
  Google::Apis::StorageV1::Policy.new(
187
245
  etag: etag,
188
- bindings: roles.keys.map do |role_name|
189
- next if roles[role_name].empty?
190
- Google::Apis::StorageV1::Policy::Binding.new(
191
- role: role_name,
192
- members: roles[role_name].uniq
193
- )
194
- end
246
+ version: version,
247
+ bindings: roles_to_gapi
195
248
  )
196
249
  end
197
250
 
@@ -202,7 +255,207 @@ module Google
202
255
  roles = Array(gapi.bindings).each_with_object({}) do |binding, memo|
203
256
  memo[binding.role] = binding.members.to_a
204
257
  end
205
- new gapi.etag, roles
258
+ new gapi.etag, gapi.version, roles
259
+ end
260
+
261
+ protected
262
+
263
+ def roles_to_gapi
264
+ roles.keys.map do |role_name|
265
+ next if roles[role_name].empty?
266
+ Google::Apis::StorageV1::Policy::Binding.new(
267
+ role: role_name,
268
+ members: roles[role_name].uniq
269
+ )
270
+ end
271
+ end
272
+ end
273
+
274
+ ##
275
+ # A subclass of {Google::Cloud::Storage::Policy} that supports access to {#bindings}
276
+ # and {version=}. Attempts to call {#roles} and relate helpers will raise a runtime
277
+ # error. This class may be used to update the Policy version and add bindings with a newer
278
+ # syntax. To obtain instances of this class, call {Google::Cloud::Storage::Bucket#policy}
279
+ # with `requested_policy_version: 3`.
280
+ #
281
+ # @attr [Bindings] bindings Returns the Policy's bindings object that associate roles with
282
+ # an array of members. Conditions can be configured on the {Binding} object. See
283
+ # [Understanding Roles](https://cloud.google.com/iam/docs/understanding-roles) for a
284
+ # listing of primitive and curated roles. See [Buckets:
285
+ # setIamPolicy](https://cloud.google.com/storage/docs/json_api/v1/buckets/setIamPolicy)
286
+ # for a listing of values and patterns for members.
287
+ #
288
+ # @example Updating Policy version 1 to version 3:
289
+ # require "google/cloud/storage"
290
+ #
291
+ # storage = Google::Cloud::Storage.new
292
+ # bucket = storage.bucket "my-bucket"
293
+ #
294
+ # bucket.uniform_bucket_level_access = true
295
+ #
296
+ # bucket.policy requested_policy_version: 3 do |p|
297
+ # p.version # the value is 1
298
+ # p.version = 3
299
+ #
300
+ # expr = "resource.name.startsWith(\"projects/_/buckets/bucket-name/objects/prefix-a-\")"
301
+ # p.bindings.insert({
302
+ # role: "roles/storage.admin",
303
+ # members: ["user:owner@example.com"],
304
+ # condition: {
305
+ # title: "my-condition",
306
+ # description: "description of condition",
307
+ # expression: expr
308
+ # }
309
+ # })
310
+ # end
311
+ #
312
+ # @example Using Policy version 3:
313
+ # require "google/cloud/storage"
314
+ #
315
+ # storage = Google::Cloud::Storage.new
316
+ # bucket = storage.bucket "my-bucket"
317
+ #
318
+ # bucket.uniform_bucket_level_access? # true
319
+ #
320
+ # bucket.policy requested_policy_version: 3 do |p|
321
+ # p.version = 3 # Must be explicitly set to opt-in to support for conditions.
322
+ #
323
+ # expr = "resource.name.startsWith(\"projects/_/buckets/bucket-name/objects/prefix-a-\")"
324
+ # p.bindings.insert({
325
+ # role: "roles/storage.admin",
326
+ # members: ["user:owner@example.com"],
327
+ # condition: {
328
+ # title: "my-condition",
329
+ # description: "description of condition",
330
+ # expression: expr
331
+ # }
332
+ # })
333
+ # end
334
+ #
335
+ class PolicyV3 < Policy
336
+ attr_reader :bindings
337
+
338
+ ##
339
+ # @private Creates a PolicyV3 object.
340
+ def initialize etag, version, bindings
341
+ super etag, version
342
+ @bindings = Bindings.new
343
+ @bindings.insert(*bindings)
344
+ end
345
+
346
+ ##
347
+ # Updates the syntax schema version of the policy. Each version of the
348
+ # policy contains a specific syntax schema that can be used by bindings.
349
+ # The newer version may contain role bindings with the newer syntax schema
350
+ # that is unsupported by earlier versions. This field is not intended to
351
+ # be used for any purposes other than policy syntax schema control.
352
+ #
353
+ # The following policy versions are valid:
354
+ #
355
+ # * 1 - The first version of Cloud IAM policy schema. Supports binding one
356
+ # role to one or more members. Does not support conditional bindings.
357
+ # * 3 - Introduces the condition field in the role binding, which further
358
+ # constrains the role binding via context-based and attribute-based rules.
359
+ # See [Understanding policies](https://cloud.google.com/iam/docs/policies)
360
+ # and [Overview of Cloud IAM Conditions](https://cloud.google.com/iam/docs/conditions-overview)
361
+ # for more information.
362
+ #
363
+ # @param [Integer] new_version The syntax schema version of the policy.
364
+ #
365
+ # @see https://cloud.google.com/iam/docs/policies#versions Policy versions
366
+ #
367
+ # @example Updating Policy version 1 to version 3:
368
+ # require "google/cloud/storage"
369
+ #
370
+ # storage = Google::Cloud::Storage.new
371
+ # bucket = storage.bucket "my-bucket"
372
+ #
373
+ # bucket.uniform_bucket_level_access = true
374
+ #
375
+ # bucket.policy requested_policy_version: 3 do |p|
376
+ # p.version # the value is 1
377
+ # p.version = 3
378
+ #
379
+ # expr = "resource.name.startsWith(\"projects/_/buckets/bucket-name/objects/prefix-a-\")"
380
+ # p.bindings.insert({
381
+ # role: "roles/storage.admin",
382
+ # members: ["user:owner@example.com"],
383
+ # condition: {
384
+ # title: "my-condition",
385
+ # description: "description of condition",
386
+ # expression: expr
387
+ # }
388
+ # })
389
+ # end
390
+ #
391
+ def version= new_version
392
+ if new_version < version
393
+ raise "new_version (#{new_version}) cannot be less than the current version (#{version})."
394
+ end
395
+ @version = new_version
396
+ end
397
+
398
+ ##
399
+ # @private Illegal operation in PolicyV3. Use {#bindings} instead.
400
+ #
401
+ # @raise [RuntimeError] If called on this class.
402
+ #
403
+ def roles
404
+ raise "Illegal operation when using PolicyV1. Use Policy#bindings instead."
405
+ end
406
+
407
+ ##
408
+ # @private Illegal operation in PolicyV3. Use {#bindings} instead.
409
+ #
410
+ # @raise [RuntimeError] If called on this class.
411
+ #
412
+ def add(*)
413
+ raise "Illegal operation when using PolicyV1. Use Policy#bindings instead."
414
+ end
415
+
416
+ ##
417
+ # @private Illegal operation in PolicyV3. Use {#bindings} instead.
418
+ #
419
+ # @raise [RuntimeError] If called on this class.
420
+ #
421
+ def remove(*)
422
+ raise "Illegal operation when using PolicyV1. Use Policy#bindings instead."
423
+ end
424
+
425
+ ##
426
+ # @private Illegal operation in PolicyV3. Use {#bindings} instead.
427
+ #
428
+ # @raise [RuntimeError] If called on this class.
429
+ #
430
+ def role(*)
431
+ raise "Illegal operation when using PolicyV1. Use Policy#bindings instead."
432
+ end
433
+
434
+ ##
435
+ # @private Illegal operation in PolicyV3. Deprecated in PolicyV1.
436
+ #
437
+ # @raise [RuntimeError] If called on this class.
438
+ #
439
+ def deep_dup
440
+ raise "Illegal operation when using PolicyV3. Deprecated in PolicyV1."
441
+ end
442
+
443
+ ##
444
+ # @private Convert the PolicyV3 to a
445
+ # Google::Apis::StorageV1::Policy.
446
+ def to_gapi
447
+ Google::Apis::StorageV1::Policy.new(
448
+ etag: etag,
449
+ version: version,
450
+ bindings: bindings.to_gapi
451
+ )
452
+ end
453
+
454
+ ##
455
+ # @private New Policy from a
456
+ # Google::Apis::StorageV1::Policy object.
457
+ def self.from_gapi gapi
458
+ new gapi.etag, gapi.version, Array(gapi.bindings).map(&:to_h)
206
459
  end
207
460
  end
208
461
  end
@@ -27,7 +27,7 @@ module Google
27
27
  # form. Each key/value pair should be set as an input tag's name and
28
28
  # value.
29
29
  #
30
- # @example
30
+ # @example Using Bucket#post_object (V2):
31
31
  # require "google/cloud/storage"
32
32
  #
33
33
  # storage = Google::Cloud::Storage.new
@@ -41,8 +41,26 @@ module Google
41
41
  # post.fields[:signature] #=> "ABC...XYZ="
42
42
  # post.fields[:policy] #=> "ABC...XYZ="
43
43
  #
44
+ # @example Using Bucket#generate_signed_post_policy_v4 (V4):
45
+ # require "google/cloud/storage"
46
+ #
47
+ # storage = Google::Cloud::Storage.new
48
+ #
49
+ # bucket = storage.bucket "my-todo-app"
50
+ # conditions = [["starts-with","$acl","public"]]
51
+ # post = bucket.generate_signed_post_policy_v4 "avatars/heidi/400x400.png", expires: 10, conditions: conditions
52
+ #
53
+ # post.url #=> "https://storage.googleapis.com/my-todo-app/"
54
+ # post.fields["key"] #=> "my-todo-app/avatars/heidi/400x400.png"
55
+ # post.fields["policy"] #=> "ABC...XYZ"
56
+ # post.fields["x-goog-algorithm"] #=> "GOOG4-RSA-SHA256"
57
+ # post.fields["x-goog-credential"] #=> "cred@pid.iam.gserviceaccount.com/20200123/auto/storage/goog4_request"
58
+ # post.fields["x-goog-date"] #=> "20200128T000000Z"
59
+ # post.fields["x-goog-signature"] #=> "4893a0e...cd82"
60
+ #
44
61
  class PostObject
45
- attr_reader :url, :fields
62
+ attr_reader :url
63
+ attr_reader :fields
46
64
 
47
65
  # @private
48
66
  def initialize url, fields