google-cloud-storage 1.26.1 → 1.29.1
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.
- checksums.yaml +4 -4
- data/AUTHENTICATION.md +8 -2
- data/CHANGELOG.md +59 -0
- data/TROUBLESHOOTING.md +2 -8
- data/lib/google-cloud-storage.rb +1 -0
- data/lib/google/cloud/storage.rb +2 -1
- data/lib/google/cloud/storage/bucket.rb +251 -60
- data/lib/google/cloud/storage/bucket/lifecycle.rb +160 -26
- data/lib/google/cloud/storage/errors.rb +7 -2
- data/lib/google/cloud/storage/file.rb +114 -34
- data/lib/google/cloud/storage/file/signer_v2.rb +21 -12
- data/lib/google/cloud/storage/file/signer_v4.rb +38 -20
- data/lib/google/cloud/storage/project.rb +84 -30
- data/lib/google/cloud/storage/service.rb +4 -3
- data/lib/google/cloud/storage/version.rb +1 -1
- metadata +3 -3
@@ -77,13 +77,21 @@ module Google
|
|
77
77
|
end
|
78
78
|
|
79
79
|
def determine_signing_key options = {}
|
80
|
-
options[:signing_key] || options[:private_key] ||
|
81
|
-
|
80
|
+
signing_key = options[:signing_key] || options[:private_key] ||
|
81
|
+
options[:signer] || @service.credentials.signing_key
|
82
|
+
raise SignedUrlUnavailable, error_msg("signing_key (private_key, signer)") unless signing_key
|
83
|
+
signing_key
|
82
84
|
end
|
83
85
|
|
84
86
|
def determine_issuer options = {}
|
85
|
-
options[:issuer] || options[:client_email] ||
|
86
|
-
|
87
|
+
issuer = options[:issuer] || options[:client_email] || @service.credentials.issuer
|
88
|
+
raise SignedUrlUnavailable, error_msg("issuer (client_email)") unless issuer
|
89
|
+
issuer
|
90
|
+
end
|
91
|
+
|
92
|
+
def error_msg attr_name
|
93
|
+
"Service account credentials '#{attr_name}' is missing. To generate service account credentials " \
|
94
|
+
"see https://cloud.google.com/iam/docs/service-accounts"
|
87
95
|
end
|
88
96
|
|
89
97
|
def post_object options
|
@@ -99,8 +107,6 @@ module Google
|
|
99
107
|
i = determine_issuer options
|
100
108
|
s = determine_signing_key options
|
101
109
|
|
102
|
-
raise SignedUrlUnavailable unless i && s
|
103
|
-
|
104
110
|
policy_str = p.to_json
|
105
111
|
policy = Base64.strict_encode64(policy_str).delete "\n"
|
106
112
|
|
@@ -119,18 +125,21 @@ module Google
|
|
119
125
|
i = determine_issuer options
|
120
126
|
s = determine_signing_key options
|
121
127
|
|
122
|
-
raise SignedUrlUnavailable unless i && s
|
123
|
-
|
124
128
|
sig = generate_signature s, signature_str(options)
|
125
129
|
generate_signed_url i, sig, options[:expires], options[:query]
|
126
130
|
end
|
127
131
|
|
128
132
|
def generate_signature signing_key, secret
|
129
|
-
|
130
|
-
|
133
|
+
unencoded_signature = ""
|
134
|
+
if signing_key.is_a? Proc
|
135
|
+
unencoded_signature = signing_key.call secret
|
136
|
+
else
|
137
|
+
unless signing_key.respond_to? :sign
|
138
|
+
signing_key = OpenSSL::PKey::RSA.new signing_key
|
139
|
+
end
|
140
|
+
unencoded_signature = signing_key.sign OpenSSL::Digest::SHA256.new, secret
|
131
141
|
end
|
132
|
-
|
133
|
-
Base64.strict_encode64(signature).delete "\n"
|
142
|
+
Base64.strict_encode64(unencoded_signature).delete "\n"
|
134
143
|
end
|
135
144
|
|
136
145
|
def generate_signed_url issuer, signed_string, expires, query
|
@@ -43,6 +43,7 @@ module Google
|
|
43
43
|
client_email: nil,
|
44
44
|
signing_key: nil,
|
45
45
|
private_key: nil,
|
46
|
+
signer: nil,
|
46
47
|
expires: nil,
|
47
48
|
fields: nil,
|
48
49
|
conditions: nil,
|
@@ -50,8 +51,7 @@ module Google
|
|
50
51
|
virtual_hosted_style: nil,
|
51
52
|
bucket_bound_hostname: nil
|
52
53
|
i = determine_issuer issuer, client_email
|
53
|
-
s = determine_signing_key signing_key, private_key
|
54
|
-
raise SignedUrlUnavailable unless i && s
|
54
|
+
s = determine_signing_key signing_key, private_key, signer
|
55
55
|
|
56
56
|
now = Time.now.utc
|
57
57
|
base_fields = required_fields i, now
|
@@ -82,12 +82,13 @@ module Google
|
|
82
82
|
client_email: nil,
|
83
83
|
signing_key: nil,
|
84
84
|
private_key: nil,
|
85
|
+
signer: nil,
|
85
86
|
query: nil,
|
86
87
|
scheme: "https",
|
87
88
|
virtual_hosted_style: nil,
|
88
89
|
bucket_bound_hostname: nil
|
89
90
|
raise ArgumentError, "method is required" unless method
|
90
|
-
issuer, signer = issuer_and_signer issuer, client_email, signing_key, private_key
|
91
|
+
issuer, signer = issuer_and_signer issuer, client_email, signing_key, private_key, signer
|
91
92
|
datetime_now = Time.now.utc
|
92
93
|
goog_date = datetime_now.strftime "%Y%m%dT%H%M%SZ"
|
93
94
|
datestamp = datetime_now.strftime "%Y%m%d"
|
@@ -192,28 +193,40 @@ module Google
|
|
192
193
|
def determine_issuer issuer, client_email
|
193
194
|
# Parse the Service Account and get client id and private key
|
194
195
|
issuer = issuer || client_email || @service.credentials.issuer
|
195
|
-
raise SignedUrlUnavailable, "issuer (client_email)
|
196
|
+
raise SignedUrlUnavailable, error_msg("issuer (client_email)") unless issuer
|
196
197
|
issuer
|
197
198
|
end
|
198
199
|
|
199
|
-
def determine_signing_key signing_key, private_key
|
200
|
-
signing_key = signing_key || private_key || @service.credentials.signing_key
|
201
|
-
raise SignedUrlUnavailable, "signing_key (private_key)
|
200
|
+
def determine_signing_key signing_key, private_key, signer
|
201
|
+
signing_key = signing_key || private_key || signer || @service.credentials.signing_key
|
202
|
+
raise SignedUrlUnavailable, error_msg("signing_key (private_key, signer)") unless signing_key
|
202
203
|
signing_key
|
203
204
|
end
|
204
205
|
|
206
|
+
def error_msg attr_name
|
207
|
+
"Service account credentials '#{attr_name}' is missing. To generate service account credentials " \
|
208
|
+
"see https://cloud.google.com/iam/docs/service-accounts"
|
209
|
+
end
|
210
|
+
|
205
211
|
def service_account_signer signer
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
212
|
+
if signer.is_a? Proc
|
213
|
+
lambda do |string_to_sign|
|
214
|
+
sig = signer.call string_to_sign
|
215
|
+
sig.unpack("H*").first
|
216
|
+
end
|
217
|
+
else
|
218
|
+
signer = OpenSSL::PKey::RSA.new signer unless signer.respond_to? :sign
|
219
|
+
# Sign string to sign
|
220
|
+
lambda do |string_to_sign|
|
221
|
+
sig = signer.sign OpenSSL::Digest::SHA256.new, string_to_sign
|
222
|
+
sig.unpack("H*").first
|
223
|
+
end
|
211
224
|
end
|
212
225
|
end
|
213
226
|
|
214
|
-
def issuer_and_signer issuer, client_email, signing_key, private_key
|
227
|
+
def issuer_and_signer issuer, client_email, signing_key, private_key, signer
|
215
228
|
issuer = determine_issuer issuer, client_email
|
216
|
-
signing_key = determine_signing_key signing_key, private_key
|
229
|
+
signing_key = determine_signing_key signing_key, private_key, signer
|
217
230
|
signer = service_account_signer signing_key
|
218
231
|
[issuer, signer]
|
219
232
|
end
|
@@ -260,7 +273,7 @@ module Google
|
|
260
273
|
# Only the characters in the regex set [A-Za-z0-9.~_-] must be left un-escaped; all others must be
|
261
274
|
# percent-encoded using %XX UTF-8 style.
|
262
275
|
def escape_query_param str
|
263
|
-
CGI.escape(str.to_s).gsub("%7E", "~")
|
276
|
+
CGI.escape(str.to_s).gsub("%7E", "~").gsub "+", "%20"
|
264
277
|
end
|
265
278
|
|
266
279
|
def host_name virtual_hosted_style, bucket_bound_hostname
|
@@ -274,7 +287,7 @@ module Google
|
|
274
287
|
path = []
|
275
288
|
path << "/#{@bucket_name}" if path_style
|
276
289
|
path << "/#{String(@file_name)}" if @file_name && !@file_name.empty?
|
277
|
-
CGI.escape(path.join).gsub
|
290
|
+
CGI.escape(path.join).gsub("%2F", "/").gsub "+", "%20"
|
278
291
|
end
|
279
292
|
|
280
293
|
##
|
@@ -337,11 +350,16 @@ module Google
|
|
337
350
|
end
|
338
351
|
|
339
352
|
def generate_signature signing_key, data
|
340
|
-
|
341
|
-
|
353
|
+
packed_signature = nil
|
354
|
+
if signing_key.is_a? Proc
|
355
|
+
packed_signature = signing_key.call data
|
356
|
+
else
|
357
|
+
unless signing_key.respond_to? :sign
|
358
|
+
signing_key = OpenSSL::PKey::RSA.new signing_key
|
359
|
+
end
|
360
|
+
packed_signature = signing_key.sign OpenSSL::Digest::SHA256.new, data
|
342
361
|
end
|
343
|
-
|
344
|
-
signature.unpack("H*").first.force_encoding "utf-8"
|
362
|
+
packed_signature.unpack("H*").first.force_encoding "utf-8"
|
345
363
|
end
|
346
364
|
end
|
347
365
|
end
|
@@ -483,7 +483,7 @@ module Google
|
|
483
483
|
# A {SignedUrlUnavailable} is raised if the service account credentials
|
484
484
|
# are missing. Service account credentials are acquired by following the
|
485
485
|
# steps in [Service Account Authentication](
|
486
|
-
# https://cloud.google.com/
|
486
|
+
# https://cloud.google.com/iam/docs/service-accounts).
|
487
487
|
#
|
488
488
|
# @see https://cloud.google.com/storage/docs/access-control/signed-urls
|
489
489
|
# Signed URLs guide
|
@@ -511,10 +511,22 @@ module Google
|
|
511
511
|
# use the signed URL.
|
512
512
|
# @param [String] issuer Service Account's Client Email.
|
513
513
|
# @param [String] client_email Service Account's Client Email.
|
514
|
-
# @param [OpenSSL::PKey::RSA, String] signing_key Service Account's
|
515
|
-
# Private Key
|
516
|
-
#
|
517
|
-
#
|
514
|
+
# @param [OpenSSL::PKey::RSA, String, Proc] signing_key Service Account's
|
515
|
+
# Private Key or a Proc that accepts a single String parameter and returns a
|
516
|
+
# RSA SHA256 signature using a valid Google Service Account Private Key.
|
517
|
+
# @param [OpenSSL::PKey::RSA, String, Proc] private_key Service Account's
|
518
|
+
# Private Key or a Proc that accepts a single String parameter and returns a
|
519
|
+
# RSA SHA256 signature using a valid Google Service Account Private Key.
|
520
|
+
# @param [OpenSSL::PKey::RSA, String, Proc] signer Service Account's
|
521
|
+
# Private Key or a Proc that accepts a single String parameter and returns a
|
522
|
+
# RSA SHA256 signature using a valid Google Service Account Private Key.
|
523
|
+
#
|
524
|
+
# When using this method in environments such as GAE Flexible Environment,
|
525
|
+
# GKE, or Cloud Functions where the private key is unavailable, it may be
|
526
|
+
# necessary to provide a Proc (or lambda) via the signer parameter. This
|
527
|
+
# Proc should return a signature created using a RPC call to the
|
528
|
+
# [Service Account Credentials signBlob](https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/signBlob)
|
529
|
+
# method as shown in the example below.
|
518
530
|
# @param [Hash] query Query string parameters to include in the signed
|
519
531
|
# URL. The given parameters are not verified by the signature.
|
520
532
|
#
|
@@ -540,7 +552,12 @@ module Google
|
|
540
552
|
# to create. Must be one of `:v2` or `:v4`. The default value is
|
541
553
|
# `:v2`.
|
542
554
|
#
|
543
|
-
# @return [String]
|
555
|
+
# @return [String] The signed URL.
|
556
|
+
#
|
557
|
+
# @raise [SignedUrlUnavailable] If the service account credentials
|
558
|
+
# are missing. Service account credentials are acquired by following the
|
559
|
+
# steps in [Service Account Authentication](
|
560
|
+
# https://cloud.google.com/iam/docs/service-accounts).
|
544
561
|
#
|
545
562
|
# @example
|
546
563
|
# require "google/cloud/storage"
|
@@ -575,6 +592,41 @@ module Google
|
|
575
592
|
# issuer: issuer_email,
|
576
593
|
# signing_key: key
|
577
594
|
#
|
595
|
+
# @example Using Cloud IAMCredentials signBlob to create the signature:
|
596
|
+
# require "google/cloud/storage"
|
597
|
+
# require "google/apis/iamcredentials_v1"
|
598
|
+
# require "googleauth"
|
599
|
+
#
|
600
|
+
# # Issuer is the service account email that the Signed URL will be signed with
|
601
|
+
# # and any permission granted in the Signed URL must be granted to the
|
602
|
+
# # Google Service Account.
|
603
|
+
# issuer = "service-account@project-id.iam.gserviceaccount.com"
|
604
|
+
#
|
605
|
+
# # Create a lambda that accepts the string_to_sign
|
606
|
+
# signer = lambda do |string_to_sign|
|
607
|
+
# IAMCredentials = Google::Apis::IamcredentialsV1
|
608
|
+
# iam_client = IAMCredentials::IAMCredentialsService.new
|
609
|
+
#
|
610
|
+
# # Get the environment configured authorization
|
611
|
+
# scopes = ["https://www.googleapis.com/auth/iam"]
|
612
|
+
# iam_client.authorization = Google::Auth.get_application_default scopes
|
613
|
+
#
|
614
|
+
# request = {
|
615
|
+
# "payload": string_to_sign,
|
616
|
+
# }
|
617
|
+
# resource = "projects/-/serviceAccounts/#{issuer}"
|
618
|
+
# response = iam_client.sign_service_account_blob resource, request, {}
|
619
|
+
# response.signed_blob
|
620
|
+
# end
|
621
|
+
#
|
622
|
+
# storage = Google::Cloud::Storage.new
|
623
|
+
#
|
624
|
+
# bucket_name = "my-todo-app"
|
625
|
+
# file_path = "avatars/heidi/400x400.png"
|
626
|
+
# url = storage.signed_url bucket_name, file_path,
|
627
|
+
# method: "GET", issuer: issuer,
|
628
|
+
# signer: signer
|
629
|
+
#
|
578
630
|
# @example Using the `headers` option:
|
579
631
|
# require "google/cloud/storage"
|
580
632
|
#
|
@@ -616,6 +668,7 @@ module Google
|
|
616
668
|
client_email: nil,
|
617
669
|
signing_key: nil,
|
618
670
|
private_key: nil,
|
671
|
+
signer: nil,
|
619
672
|
query: nil,
|
620
673
|
scheme: "HTTPS",
|
621
674
|
virtual_hosted_style: nil,
|
@@ -624,31 +677,32 @@ module Google
|
|
624
677
|
version ||= :v2
|
625
678
|
case version.to_sym
|
626
679
|
when :v2
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
680
|
+
sign = File::SignerV2.new bucket, path, service
|
681
|
+
sign.signed_url method: method,
|
682
|
+
expires: expires,
|
683
|
+
headers: headers,
|
684
|
+
content_type: content_type,
|
685
|
+
content_md5: content_md5,
|
686
|
+
issuer: issuer,
|
687
|
+
client_email: client_email,
|
688
|
+
signing_key: signing_key,
|
689
|
+
private_key: private_key,
|
690
|
+
signer: signer,
|
691
|
+
query: query
|
639
692
|
when :v4
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
693
|
+
sign = File::SignerV4.new bucket, path, service
|
694
|
+
sign.signed_url method: method,
|
695
|
+
expires: expires,
|
696
|
+
headers: headers,
|
697
|
+
issuer: issuer,
|
698
|
+
client_email: client_email,
|
699
|
+
signing_key: signing_key,
|
700
|
+
private_key: private_key,
|
701
|
+
signer: signer,
|
702
|
+
query: query,
|
703
|
+
scheme: scheme,
|
704
|
+
virtual_hosted_style: virtual_hosted_style,
|
705
|
+
bucket_bound_hostname: bucket_bound_hostname
|
652
706
|
else
|
653
707
|
raise ArgumentError, "version '#{version}' not supported"
|
654
708
|
end
|
@@ -39,7 +39,7 @@ module Google
|
|
39
39
|
##
|
40
40
|
# Creates a new Service instance.
|
41
41
|
def initialize project, credentials,
|
42
|
-
retries: nil, timeout: nil, host: nil
|
42
|
+
retries: nil, timeout: nil, host: nil, quota_project: nil
|
43
43
|
@project = project
|
44
44
|
@credentials = credentials
|
45
45
|
@service = API::StorageService.new
|
@@ -55,6 +55,7 @@ module Google
|
|
55
55
|
@service.request_options.header["x-goog-api-client"] = \
|
56
56
|
"gl-ruby/#{RUBY_VERSION} gccl/#{Google::Cloud::Storage::VERSION}"
|
57
57
|
@service.request_options.header["Accept-Encoding"] = "gzip"
|
58
|
+
@service.request_options.quota_project = quota_project if quota_project
|
58
59
|
@service.authorization = @credentials.client if @credentials
|
59
60
|
@service.root_url = host if host
|
60
61
|
end
|
@@ -292,12 +293,12 @@ module Google
|
|
292
293
|
def insert_file bucket_name, source, path = nil, acl: nil,
|
293
294
|
cache_control: nil, content_disposition: nil,
|
294
295
|
content_encoding: nil, content_language: nil,
|
295
|
-
content_type: nil, crc32c: nil, md5: nil, metadata: nil,
|
296
|
+
content_type: nil, custom_time: nil, crc32c: nil, md5: nil, metadata: nil,
|
296
297
|
storage_class: nil, key: nil, kms_key: nil,
|
297
298
|
temporary_hold: nil, event_based_hold: nil,
|
298
299
|
user_project: nil
|
299
300
|
params =
|
300
|
-
{ cache_control: cache_control, content_type: content_type,
|
301
|
+
{ cache_control: cache_control, content_type: content_type, custom_time: custom_time,
|
301
302
|
content_disposition: content_disposition, md5_hash: md5,
|
302
303
|
content_encoding: content_encoding, crc32c: crc32c,
|
303
304
|
content_language: content_language, metadata: metadata,
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: google-cloud-storage
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.29.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Moore
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2020-05
|
12
|
+
date: 2020-10-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: google-cloud-core
|
@@ -298,7 +298,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
298
298
|
- !ruby/object:Gem::Version
|
299
299
|
version: '0'
|
300
300
|
requirements: []
|
301
|
-
rubygems_version: 3.
|
301
|
+
rubygems_version: 3.1.4
|
302
302
|
signing_key:
|
303
303
|
specification_version: 4
|
304
304
|
summary: API Client library for Google Cloud Storage
|