google-cloud-storage 1.18.1 → 1.44.0

Sign up to get free protection for your applications and to get access to all the features.
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