aws-sdk-s3 1.48.0 → 1.113.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +888 -0
- data/LICENSE.txt +202 -0
- data/VERSION +1 -0
- data/lib/aws-sdk-s3/arn/access_point_arn.rb +69 -0
- data/lib/aws-sdk-s3/arn/multi_region_access_point_arn.rb +68 -0
- data/lib/aws-sdk-s3/arn/object_lambda_arn.rb +69 -0
- data/lib/aws-sdk-s3/arn/outpost_access_point_arn.rb +74 -0
- data/lib/aws-sdk-s3/bucket.rb +375 -82
- data/lib/aws-sdk-s3/bucket_acl.rb +55 -15
- data/lib/aws-sdk-s3/bucket_cors.rb +67 -14
- data/lib/aws-sdk-s3/bucket_lifecycle.rb +54 -16
- data/lib/aws-sdk-s3/bucket_lifecycle_configuration.rb +56 -16
- data/lib/aws-sdk-s3/bucket_logging.rb +52 -13
- data/lib/aws-sdk-s3/bucket_notification.rb +43 -17
- data/lib/aws-sdk-s3/bucket_policy.rb +51 -13
- data/lib/aws-sdk-s3/bucket_region_cache.rb +2 -0
- data/lib/aws-sdk-s3/bucket_request_payment.rb +51 -12
- data/lib/aws-sdk-s3/bucket_tagging.rb +59 -14
- data/lib/aws-sdk-s3/bucket_versioning.rb +118 -12
- data/lib/aws-sdk-s3/bucket_website.rb +66 -17
- data/lib/aws-sdk-s3/client.rb +8973 -740
- data/lib/aws-sdk-s3/client_api.rb +778 -2
- data/lib/aws-sdk-s3/customizations/bucket.rb +59 -16
- data/lib/aws-sdk-s3/customizations/multipart_upload.rb +2 -0
- data/lib/aws-sdk-s3/customizations/object.rb +200 -62
- data/lib/aws-sdk-s3/customizations/object_summary.rb +5 -0
- data/lib/aws-sdk-s3/customizations/types/list_object_versions_output.rb +2 -0
- data/lib/aws-sdk-s3/customizations.rb +4 -1
- data/lib/aws-sdk-s3/encryption/client.rb +22 -5
- data/lib/aws-sdk-s3/encryption/decrypt_handler.rb +71 -29
- data/lib/aws-sdk-s3/encryption/default_cipher_provider.rb +43 -5
- data/lib/aws-sdk-s3/encryption/default_key_provider.rb +2 -0
- data/lib/aws-sdk-s3/encryption/encrypt_handler.rb +13 -2
- data/lib/aws-sdk-s3/encryption/errors.rb +2 -0
- data/lib/aws-sdk-s3/encryption/io_auth_decrypter.rb +2 -0
- data/lib/aws-sdk-s3/encryption/io_decrypter.rb +11 -3
- data/lib/aws-sdk-s3/encryption/io_encrypter.rb +2 -0
- data/lib/aws-sdk-s3/encryption/key_provider.rb +2 -0
- data/lib/aws-sdk-s3/encryption/kms_cipher_provider.rb +34 -3
- data/lib/aws-sdk-s3/encryption/materials.rb +8 -6
- data/lib/aws-sdk-s3/encryption/utils.rb +25 -0
- data/lib/aws-sdk-s3/encryption.rb +4 -0
- data/lib/aws-sdk-s3/encryptionV2/client.rb +566 -0
- data/lib/aws-sdk-s3/encryptionV2/decrypt_handler.rb +222 -0
- data/lib/aws-sdk-s3/encryptionV2/default_cipher_provider.rb +170 -0
- data/lib/aws-sdk-s3/encryptionV2/default_key_provider.rb +40 -0
- data/lib/aws-sdk-s3/encryptionV2/encrypt_handler.rb +65 -0
- data/lib/aws-sdk-s3/encryptionV2/errors.rb +37 -0
- data/lib/aws-sdk-s3/encryptionV2/io_auth_decrypter.rb +58 -0
- data/lib/aws-sdk-s3/encryptionV2/io_decrypter.rb +37 -0
- data/lib/aws-sdk-s3/encryptionV2/io_encrypter.rb +73 -0
- data/lib/aws-sdk-s3/encryptionV2/key_provider.rb +31 -0
- data/lib/aws-sdk-s3/encryptionV2/kms_cipher_provider.rb +169 -0
- data/lib/aws-sdk-s3/encryptionV2/materials.rb +60 -0
- data/lib/aws-sdk-s3/encryptionV2/utils.rb +103 -0
- data/lib/aws-sdk-s3/encryption_v2.rb +23 -0
- data/lib/aws-sdk-s3/errors.rb +123 -1
- data/lib/aws-sdk-s3/event_streams.rb +8 -1
- data/lib/aws-sdk-s3/file_downloader.rb +17 -10
- data/lib/aws-sdk-s3/file_part.rb +11 -6
- data/lib/aws-sdk-s3/file_uploader.rb +33 -14
- data/lib/aws-sdk-s3/legacy_signer.rb +17 -25
- data/lib/aws-sdk-s3/multipart_file_uploader.rb +78 -19
- data/lib/aws-sdk-s3/multipart_stream_uploader.rb +18 -7
- data/lib/aws-sdk-s3/multipart_upload.rb +178 -29
- data/lib/aws-sdk-s3/multipart_upload_error.rb +2 -0
- data/lib/aws-sdk-s3/multipart_upload_part.rb +233 -42
- data/lib/aws-sdk-s3/object.rb +846 -179
- data/lib/aws-sdk-s3/object_acl.rb +79 -21
- data/lib/aws-sdk-s3/object_copier.rb +2 -0
- data/lib/aws-sdk-s3/object_multipart_copier.rb +2 -0
- data/lib/aws-sdk-s3/object_summary.rb +611 -162
- data/lib/aws-sdk-s3/object_version.rb +162 -71
- data/lib/aws-sdk-s3/plugins/accelerate.rb +38 -38
- data/lib/aws-sdk-s3/plugins/arn.rb +254 -0
- data/lib/aws-sdk-s3/plugins/bucket_dns.rb +8 -8
- data/lib/aws-sdk-s3/plugins/bucket_name_restrictions.rb +25 -3
- data/lib/aws-sdk-s3/plugins/dualstack.rb +38 -33
- data/lib/aws-sdk-s3/plugins/expect_100_continue.rb +4 -4
- data/lib/aws-sdk-s3/plugins/get_bucket_location_fix.rb +3 -1
- data/lib/aws-sdk-s3/plugins/http_200_errors.rb +11 -3
- data/lib/aws-sdk-s3/plugins/iad_regional_endpoint.rb +73 -0
- data/lib/aws-sdk-s3/plugins/location_constraint.rb +2 -0
- data/lib/aws-sdk-s3/plugins/md5s.rb +34 -30
- data/lib/aws-sdk-s3/plugins/object_lambda_endpoint.rb +25 -0
- data/lib/aws-sdk-s3/plugins/redirects.rb +2 -0
- data/lib/aws-sdk-s3/plugins/s3_host_id.rb +2 -0
- data/lib/aws-sdk-s3/plugins/s3_signer.rb +89 -36
- data/lib/aws-sdk-s3/plugins/skip_whole_multipart_get_checksums.rb +31 -0
- data/lib/aws-sdk-s3/plugins/sse_cpk.rb +3 -1
- data/lib/aws-sdk-s3/plugins/streaming_retry.rb +118 -0
- data/lib/aws-sdk-s3/plugins/url_encoded_keys.rb +2 -0
- data/lib/aws-sdk-s3/presigned_post.rb +110 -51
- data/lib/aws-sdk-s3/presigner.rb +133 -45
- data/lib/aws-sdk-s3/resource.rb +43 -7
- data/lib/aws-sdk-s3/types.rb +8437 -1132
- data/lib/aws-sdk-s3/waiters.rb +67 -1
- data/lib/aws-sdk-s3.rb +12 -6
- metadata +37 -12
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'openssl'
|
2
4
|
require 'base64'
|
3
5
|
|
@@ -96,7 +98,7 @@ module Aws
|
|
96
98
|
# or call the associated method.
|
97
99
|
#
|
98
100
|
# ```ruby
|
99
|
-
# post = Aws::S3::PresignedPost.new(creds, region, bucket)
|
101
|
+
# post = Aws::S3::PresignedPost.new(creds, region, bucket)
|
100
102
|
# post.content_type('text/plain')
|
101
103
|
# ```
|
102
104
|
#
|
@@ -174,44 +176,76 @@ module Aws
|
|
174
176
|
# ```
|
175
177
|
#
|
176
178
|
class PresignedPost
|
179
|
+
@@allowed_fields = []
|
177
180
|
|
178
181
|
# @param [Credentials] credentials Security credentials for signing
|
179
182
|
# the post policy.
|
180
183
|
# @param [String] bucket_region Region of the target bucket.
|
181
184
|
# @param [String] bucket_name Name of the target bucket.
|
185
|
+
# @option options [Boolean] :use_accelerate_endpoint (false) When `true`,
|
186
|
+
# PresignedPost will attempt to use accelerated endpoint.
|
187
|
+
# @option options [String] :url See {PresignedPost#url}.
|
188
|
+
# @option options [Sting, Array<String>] :allow_any
|
189
|
+
# See {PresignedPost#allow_any}.
|
182
190
|
# @option options [Time] :signature_expiration Specify when the signature on
|
183
191
|
# the post will expire. Defaults to one hour from creation of the
|
184
192
|
# presigned post. May not exceed one week from creation time.
|
185
193
|
# @option options [String] :key See {PresignedPost#key}.
|
186
|
-
# @option options [String] :key_starts_with
|
194
|
+
# @option options [String] :key_starts_with
|
195
|
+
# See {PresignedPost#key_starts_with}.
|
187
196
|
# @option options [String] :acl See {PresignedPost#acl}.
|
188
|
-
# @option options [String] :acl_starts_with
|
189
|
-
#
|
190
|
-
# @option options [String] :
|
197
|
+
# @option options [String] :acl_starts_with
|
198
|
+
# See {PresignedPost#acl_starts_with}.
|
199
|
+
# @option options [String] :cache_control
|
200
|
+
# See {PresignedPost#cache_control}.
|
201
|
+
# @option options [String] :cache_control_starts_with
|
202
|
+
# See {PresignedPost#cache_control_starts_with}.
|
191
203
|
# @option options [String] :content_type See {PresignedPost#content_type}.
|
192
|
-
# @option options [String] :content_type_starts_with
|
193
|
-
#
|
194
|
-
# @option options [String] :
|
195
|
-
#
|
196
|
-
# @option options [String] :
|
197
|
-
#
|
198
|
-
# @option options [String] :
|
199
|
-
#
|
200
|
-
# @option options [String] :
|
201
|
-
#
|
202
|
-
# @option options [
|
203
|
-
# @option options [String] :
|
204
|
-
#
|
205
|
-
# @option options [
|
206
|
-
#
|
207
|
-
# @option options [String] :
|
208
|
-
#
|
209
|
-
# @option options [String] :
|
210
|
-
#
|
204
|
+
# @option options [String] :content_type_starts_with
|
205
|
+
# See {PresignedPost#content_type_starts_with}.
|
206
|
+
# @option options [String] :content_disposition
|
207
|
+
# See {PresignedPost#content_disposition}.
|
208
|
+
# @option options [String] :content_disposition_starts_with
|
209
|
+
# See {PresignedPost#content_disposition_starts_with}.
|
210
|
+
# @option options [String] :content_encoding
|
211
|
+
# See {PresignedPost#content_encoding}.
|
212
|
+
# @option options [String] :content_encoding_starts_with
|
213
|
+
# See {PresignedPost#content_encoding_starts_with}.
|
214
|
+
# @option options [Time] :expires See {PresignedPost#expires}.
|
215
|
+
# @option options [String] :expires_starts_with
|
216
|
+
# See {PresignedPost#expires_starts_with}.
|
217
|
+
# @option options [Range<Integer>] :content_length_range
|
218
|
+
# See {PresignedPost#content_length_range}.
|
219
|
+
# @option options [String] :success_action_redirect
|
220
|
+
# See {PresignedPost#success_action_redirect}.
|
221
|
+
# @option options [String] :success_action_redirect_starts_with
|
222
|
+
# See {PresignedPost#success_action_redirect_starts_with}.
|
223
|
+
# @option options [String] :success_action_status
|
224
|
+
# See {PresignedPost#success_action_status}.
|
225
|
+
# @option options [String] :storage_class
|
226
|
+
# See {PresignedPost#storage_class}.
|
227
|
+
# @option options [String] :website_redirect_location
|
228
|
+
# See {PresignedPost#website_redirect_location}.
|
229
|
+
# @option options [Hash<String,String>] :metadata
|
230
|
+
# See {PresignedPost#metadata}.
|
231
|
+
# @option options [Hash<String,String>] :metadata_starts_with
|
232
|
+
# See {PresignedPost#metadata_starts_with}.
|
233
|
+
# @option options [String] :server_side_encryption
|
234
|
+
# See {PresignedPost#server_side_encryption}.
|
235
|
+
# @option options [String] :server_side_encryption_aws_kms_key_id
|
236
|
+
# See {PresignedPost#server_side_encryption_aws_kms_key_id}.
|
237
|
+
# @option options [String] :server_side_encryption_customer_algorithm
|
238
|
+
# See {PresignedPost#server_side_encryption_customer_algorithm}.
|
239
|
+
# @option options [String] :server_side_encryption_customer_key
|
240
|
+
# See {PresignedPost#server_side_encryption_customer_key}.
|
241
|
+
# @option options [String] :server_side_encryption_customer_key_starts_with
|
242
|
+
# See {PresignedPost#server_side_encryption_customer_key_starts_with}.
|
211
243
|
def initialize(credentials, bucket_region, bucket_name, options = {})
|
212
244
|
@credentials = credentials.credentials
|
213
245
|
@bucket_region = bucket_region
|
214
246
|
@bucket_name = bucket_name
|
247
|
+
@accelerate = !!options.delete(:use_accelerate_endpoint)
|
248
|
+
options.delete(:url) if @accelerate # resource methods pass url
|
215
249
|
@url = options.delete(:url) || bucket_url
|
216
250
|
@fields = {}
|
217
251
|
@key_set = false
|
@@ -221,7 +255,12 @@ module Aws
|
|
221
255
|
case option_name
|
222
256
|
when :allow_any then allow_any(option_value)
|
223
257
|
when :signature_expiration then @signature_expiration = option_value
|
224
|
-
else
|
258
|
+
else
|
259
|
+
if @@allowed_fields.include?(option_name)
|
260
|
+
send("#{option_name}", option_value)
|
261
|
+
else
|
262
|
+
raise ArgumentError, "Unsupported option: #{option_name}"
|
263
|
+
end
|
225
264
|
end
|
226
265
|
end
|
227
266
|
end
|
@@ -234,7 +273,7 @@ module Aws
|
|
234
273
|
# as hidden input fields.
|
235
274
|
def fields
|
236
275
|
check_required_values!
|
237
|
-
datetime = Time.now.utc.strftime(
|
276
|
+
datetime = Time.now.utc.strftime('%Y%m%dT%H%M%SZ')
|
238
277
|
fields = @fields.dup
|
239
278
|
fields.update('policy' => policy(datetime))
|
240
279
|
fields.update(signature_fields(datetime))
|
@@ -253,24 +292,30 @@ module Aws
|
|
253
292
|
end
|
254
293
|
|
255
294
|
# @api private
|
256
|
-
def self.define_field(field, *args)
|
295
|
+
def self.define_field(field, *args, &block)
|
296
|
+
@@allowed_fields << field
|
257
297
|
options = args.last.is_a?(Hash) ? args.pop : {}
|
258
298
|
field_name = args.last || field.to_s
|
259
299
|
|
260
|
-
|
261
|
-
|
262
|
-
|
300
|
+
if block_given?
|
301
|
+
define_method("#{field}", block)
|
302
|
+
else
|
303
|
+
define_method("#{field}") do |value|
|
304
|
+
with(field_name, value)
|
305
|
+
end
|
263
306
|
|
264
|
-
|
265
|
-
|
266
|
-
|
307
|
+
if options[:starts_with]
|
308
|
+
@@allowed_fields << "#{field}_starts_with".to_sym
|
309
|
+
define_method("#{field}_starts_with") do |value|
|
310
|
+
starts_with(field_name, value)
|
311
|
+
end
|
267
312
|
end
|
268
313
|
end
|
269
314
|
end
|
270
315
|
|
271
316
|
# @!group Fields
|
272
317
|
|
273
|
-
# The key to use for the uploaded object.
|
318
|
+
# The key to use for the uploaded object. You can use `${filename}`
|
274
319
|
# as a variable in the key. This will be replaced with the name
|
275
320
|
# of the file as provided by the user.
|
276
321
|
#
|
@@ -281,7 +326,7 @@ module Aws
|
|
281
326
|
# @param [String] key
|
282
327
|
# @see http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html)
|
283
328
|
# @return [self]
|
284
|
-
|
329
|
+
define_field(:key) do |key|
|
285
330
|
@key_set = true
|
286
331
|
with('key', key)
|
287
332
|
end
|
@@ -290,7 +335,7 @@ module Aws
|
|
290
335
|
# @param [String] prefix
|
291
336
|
# @see #key
|
292
337
|
# @return [self]
|
293
|
-
|
338
|
+
define_field(:key_starts_with) do |prefix|
|
294
339
|
@key_set = true
|
295
340
|
starts_with('key', prefix)
|
296
341
|
end
|
@@ -373,21 +418,21 @@ module Aws
|
|
373
418
|
# @param [Time] time
|
374
419
|
# @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.21
|
375
420
|
# @return [self]
|
376
|
-
|
421
|
+
define_field(:expires) do |time|
|
377
422
|
with('Expires', time.httpdate)
|
378
423
|
end
|
379
424
|
|
380
425
|
# @param [String] prefix
|
381
426
|
# @see #expires
|
382
427
|
# @return [self]
|
383
|
-
|
428
|
+
define_field(:expires_starts_with) do |prefix|
|
384
429
|
starts_with('Expires', prefix)
|
385
430
|
end
|
386
431
|
|
387
432
|
# The minimum and maximum allowable size for the uploaded content.
|
388
433
|
# @param [Range<Integer>] byte_range
|
389
434
|
# @return [self]
|
390
|
-
|
435
|
+
define_field(:content_length_range) do |byte_range|
|
391
436
|
min = byte_range.begin
|
392
437
|
max = byte_range.end
|
393
438
|
max -= 1 if byte_range.exclude_end?
|
@@ -466,7 +511,7 @@ module Aws
|
|
466
511
|
# prefixed with "x-amz-meta-".
|
467
512
|
# @param [Hash<String,String>] hash
|
468
513
|
# @return [self]
|
469
|
-
|
514
|
+
define_field(:metadata) do |hash|
|
470
515
|
hash.each do |key, value|
|
471
516
|
with("x-amz-meta-#{key}", value)
|
472
517
|
end
|
@@ -477,7 +522,7 @@ module Aws
|
|
477
522
|
# @param [Hash<String,String>] hash
|
478
523
|
# @see #metadata
|
479
524
|
# @return [self]
|
480
|
-
|
525
|
+
define_field(:metadata_starts_with) do |hash|
|
481
526
|
hash.each do |key, value|
|
482
527
|
starts_with("x-amz-meta-#{key}", value)
|
483
528
|
end
|
@@ -505,7 +550,10 @@ module Aws
|
|
505
550
|
# (KMS) master encryption key to use for the object.
|
506
551
|
# @param [String] value
|
507
552
|
# @return [self]
|
508
|
-
define_field(
|
553
|
+
define_field(
|
554
|
+
:server_side_encryption_aws_kms_key_id,
|
555
|
+
'x-amz-server-side-encryption-aws-kms-key-id'
|
556
|
+
)
|
509
557
|
|
510
558
|
# @!endgroup
|
511
559
|
|
@@ -518,7 +566,10 @@ module Aws
|
|
518
566
|
# @param [String] value
|
519
567
|
# @see #server_side_encryption_customer_key
|
520
568
|
# @return [self]
|
521
|
-
define_field(
|
569
|
+
define_field(
|
570
|
+
:server_side_encryption_customer_algorithm,
|
571
|
+
'x-amz-server-side-encryption-customer-algorithm'
|
572
|
+
)
|
522
573
|
|
523
574
|
# Specifies the customer-provided encryption key for Amazon S3 to use
|
524
575
|
# in encrypting data. This value is used to store the object and then
|
@@ -529,7 +580,7 @@ module Aws
|
|
529
580
|
# @param [String] value
|
530
581
|
# @see #server_side_encryption_customer_algorithm
|
531
582
|
# @return [self]
|
532
|
-
|
583
|
+
define_field(:server_side_encryption_customer_key) do |value|
|
533
584
|
field_name = 'x-amz-server-side-encryption-customer-key'
|
534
585
|
with(field_name, base64(value))
|
535
586
|
with(field_name + '-MD5', base64(OpenSSL::Digest::MD5.digest(value)))
|
@@ -538,7 +589,7 @@ module Aws
|
|
538
589
|
# @param [String] prefix
|
539
590
|
# @see #server_side_encryption_customer_key
|
540
591
|
# @return [self]
|
541
|
-
|
592
|
+
define_field(:server_side_encryption_customer_key_starts_with) do |prefix|
|
542
593
|
field_name = 'x-amz-server-side-encryption-customer-key'
|
543
594
|
starts_with(field_name, prefix)
|
544
595
|
end
|
@@ -571,8 +622,8 @@ module Aws
|
|
571
622
|
|
572
623
|
def check_required_values!
|
573
624
|
unless @key_set
|
574
|
-
msg =
|
575
|
-
|
625
|
+
msg = 'key required; you must provide a key via :key, '\
|
626
|
+
":key_starts_with, or :allow_any => ['key']"
|
576
627
|
raise msg
|
577
628
|
end
|
578
629
|
end
|
@@ -580,10 +631,18 @@ module Aws
|
|
580
631
|
def bucket_url
|
581
632
|
url = Aws::Partitions::EndpointProvider.resolve(@bucket_region, 's3')
|
582
633
|
url = URI.parse(url)
|
583
|
-
if Plugins::BucketDns.dns_compatible?(@bucket_name, true)
|
584
|
-
|
634
|
+
if Plugins::BucketDns.dns_compatible?(@bucket_name, _ssl = true)
|
635
|
+
if @accelerate
|
636
|
+
url.host = "#{@bucket_name}.s3-accelerate.amazonaws.com"
|
637
|
+
else
|
638
|
+
url.host = "#{@bucket_name}.#{url.host}"
|
639
|
+
end
|
585
640
|
else
|
586
|
-
url.path =
|
641
|
+
url.path = "/#{@bucket_name}"
|
642
|
+
end
|
643
|
+
if @bucket_region == 'us-east-1'
|
644
|
+
# keep legacy behavior by default
|
645
|
+
url.host = Plugins::IADRegionalEndpoint.legacy_host(url.host)
|
587
646
|
end
|
588
647
|
url.to_s
|
589
648
|
end
|
@@ -613,7 +672,7 @@ module Aws
|
|
613
672
|
|
614
673
|
def signature(datetime, string_to_sign)
|
615
674
|
k_secret = @credentials.secret_access_key
|
616
|
-
k_date = hmac(
|
675
|
+
k_date = hmac('AWS4' + k_secret, datetime[0,8])
|
617
676
|
k_region = hmac(k_date, @bucket_region)
|
618
677
|
k_service = hmac(k_region, 's3')
|
619
678
|
k_credentials = hmac(k_service, 'aws4_request')
|
data/lib/aws-sdk-s3/presigner.rb
CHANGED
@@ -1,23 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Aws
|
2
4
|
module S3
|
3
|
-
|
4
|
-
# Allows you to create presigned URLs for S3 operations.
|
5
|
-
#
|
6
|
-
# Example Use:
|
7
|
-
#
|
8
|
-
# signer = Aws::S3::Presigner.new
|
9
|
-
# url = signer.presigned_url(:get_object, bucket: "bucket", key: "key")
|
10
|
-
#
|
11
5
|
class Presigner
|
12
|
-
|
13
6
|
# @api private
|
14
7
|
ONE_WEEK = 60 * 60 * 24 * 7
|
15
8
|
|
16
9
|
# @api private
|
17
10
|
FIFTEEN_MINUTES = 60 * 15
|
18
11
|
|
12
|
+
# @api private
|
19
13
|
BLACKLISTED_HEADERS = [
|
20
14
|
'accept',
|
15
|
+
'amz-sdk-request',
|
21
16
|
'cache-control',
|
22
17
|
'content-length', # due to a ELB bug
|
23
18
|
'expect',
|
@@ -41,6 +36,59 @@ module Aws
|
|
41
36
|
@client = options[:client] || Aws::S3::Client.new
|
42
37
|
end
|
43
38
|
|
39
|
+
# Create presigned URLs for S3 operations.
|
40
|
+
#
|
41
|
+
# @example
|
42
|
+
# signer = Aws::S3::Presigner.new
|
43
|
+
# url = signer.presigned_url(:get_object, bucket: "bucket", key: "key")
|
44
|
+
#
|
45
|
+
# @param [Symbol] method Symbolized method name of the operation you want
|
46
|
+
# to presign.
|
47
|
+
#
|
48
|
+
# @option params [Integer] :expires_in (900) The number of seconds
|
49
|
+
# before the presigned URL expires. Defaults to 15 minutes. As signature
|
50
|
+
# version 4 has a maximum expiry time of one week for presigned URLs,
|
51
|
+
# attempts to set this value to greater than one week (604800) will
|
52
|
+
# raise an exception.
|
53
|
+
#
|
54
|
+
# @option params [Time] :time (Time.now) The starting time for when the
|
55
|
+
# presigned url becomes active.
|
56
|
+
#
|
57
|
+
# @option params [Boolean] :secure (true) When `false`, a HTTP URL
|
58
|
+
# is returned instead of the default HTTPS URL.
|
59
|
+
#
|
60
|
+
# @option params [Boolean] :virtual_host (false) When `true`, the
|
61
|
+
# bucket name will be used as the hostname.
|
62
|
+
#
|
63
|
+
# @option params [Boolean] :use_accelerate_endpoint (false) When `true`,
|
64
|
+
# Presigner will attempt to use accelerated endpoint.
|
65
|
+
#
|
66
|
+
# @option params [Array<String>] :whitelist_headers ([]) Additional
|
67
|
+
# headers to be included for the signed request. Certain headers beyond
|
68
|
+
# the authorization header could, in theory, be changed for various
|
69
|
+
# reasons (including but not limited to proxies) while in transit and
|
70
|
+
# after signing. This would lead to signature errors being returned,
|
71
|
+
# despite no actual problems with signing. (see BLACKLISTED_HEADERS)
|
72
|
+
#
|
73
|
+
# @raise [ArgumentError] Raises an ArgumentError if `:expires_in`
|
74
|
+
# exceeds one week.
|
75
|
+
#
|
76
|
+
# @return [String] a presigned url
|
77
|
+
def presigned_url(method, params = {})
|
78
|
+
url, _headers = _presigned_request(method, params)
|
79
|
+
url
|
80
|
+
end
|
81
|
+
|
82
|
+
# Allows you to create presigned URL requests for S3 operations. This
|
83
|
+
# method returns a tuple containing the URL and the signed X-amz-* headers
|
84
|
+
# to be used with the presigned url.
|
85
|
+
#
|
86
|
+
# @example
|
87
|
+
# signer = Aws::S3::Presigner.new
|
88
|
+
# url, headers = signer.presigned_request(
|
89
|
+
# :get_object, bucket: "bucket", key: "key"
|
90
|
+
# )
|
91
|
+
#
|
44
92
|
# @param [Symbol] method Symbolized method name of the operation you want
|
45
93
|
# to presign.
|
46
94
|
#
|
@@ -73,27 +121,38 @@ module Aws
|
|
73
121
|
# @raise [ArgumentError] Raises an ArgumentError if `:expires_in`
|
74
122
|
# exceeds one week.
|
75
123
|
#
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
124
|
+
# @return [String, Hash] A tuple with a presigned URL and headers that
|
125
|
+
# should be included with the request.
|
126
|
+
def presigned_request(method, params = {})
|
127
|
+
_presigned_request(method, params, false)
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
|
132
|
+
def _presigned_request(method, params, hoist = true)
|
133
|
+
virtual_host = params.delete(:virtual_host)
|
81
134
|
time = params.delete(:time)
|
82
|
-
|
83
|
-
|
84
|
-
|
135
|
+
unsigned_headers = unsigned_headers(params)
|
136
|
+
scheme = http_scheme(params)
|
137
|
+
expires_in = expires_in(params)
|
85
138
|
|
86
139
|
req = @client.build_request(method, params)
|
87
140
|
use_bucket_as_hostname(req) if virtual_host
|
141
|
+
handle_presigned_url_context(req)
|
88
142
|
|
89
|
-
sign_but_dont_send(
|
90
|
-
|
143
|
+
x_amz_headers = sign_but_dont_send(
|
144
|
+
req, expires_in, scheme, time, unsigned_headers, hoist
|
145
|
+
)
|
146
|
+
[req.send_request.data, x_amz_headers]
|
91
147
|
end
|
92
148
|
|
93
|
-
|
149
|
+
def unsigned_headers(params)
|
150
|
+
whitelist_headers = params.delete(:whitelist_headers) || []
|
151
|
+
BLACKLISTED_HEADERS - whitelist_headers
|
152
|
+
end
|
94
153
|
|
95
|
-
def http_scheme(params
|
96
|
-
if params.delete(:secure) == false
|
154
|
+
def http_scheme(params)
|
155
|
+
if params.delete(:secure) == false
|
97
156
|
'http'
|
98
157
|
else
|
99
158
|
@client.config.endpoint.scheme
|
@@ -103,8 +162,11 @@ module Aws
|
|
103
162
|
def expires_in(params)
|
104
163
|
if (expires_in = params.delete(:expires_in))
|
105
164
|
if expires_in > ONE_WEEK
|
106
|
-
|
107
|
-
|
165
|
+
raise ArgumentError,
|
166
|
+
"expires_in value of #{expires_in} exceeds one-week maximum."
|
167
|
+
elsif expires_in <= 0
|
168
|
+
raise ArgumentError,
|
169
|
+
"expires_in value of #{expires_in} cannot be 0 or less."
|
108
170
|
end
|
109
171
|
expires_in
|
110
172
|
else
|
@@ -118,25 +180,34 @@ module Aws
|
|
118
180
|
uri = context.http_request.endpoint
|
119
181
|
uri.host = context.params[:bucket]
|
120
182
|
uri.path.sub!("/#{context.params[:bucket]}", '')
|
121
|
-
|
122
|
-
|
183
|
+
@handler.call(context)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
# Used for excluding presigned_urls from API request count.
|
188
|
+
#
|
189
|
+
# Store context information as early as possible, to allow
|
190
|
+
# handlers to perform decisions based on this flag if need.
|
191
|
+
def handle_presigned_url_context(req)
|
192
|
+
req.handle(step: :initialize, priority: 98) do |context|
|
193
|
+
context[:presigned_url] = true
|
123
194
|
@handler.call(context)
|
124
195
|
end
|
125
196
|
end
|
126
197
|
|
127
198
|
# @param [Seahorse::Client::Request] req
|
128
|
-
def sign_but_dont_send(
|
199
|
+
def sign_but_dont_send(
|
200
|
+
req, expires_in, scheme, time, unsigned_headers, hoist = true
|
201
|
+
)
|
202
|
+
x_amz_headers = {}
|
203
|
+
|
129
204
|
http_req = req.context.http_request
|
130
205
|
|
131
206
|
req.handlers.remove(Aws::S3::Plugins::S3Signer::LegacyHandler)
|
132
207
|
req.handlers.remove(Aws::S3::Plugins::S3Signer::V4Handler)
|
133
208
|
req.handlers.remove(Seahorse::Client::Plugins::ContentLength::Handler)
|
134
209
|
|
135
|
-
signer = build_signer(req.context.config, unsigned_headers)
|
136
|
-
|
137
|
-
req.context[:presigned_url] = true
|
138
210
|
req.handle(step: :send) do |context|
|
139
|
-
|
140
211
|
if scheme != http_req.endpoint.scheme
|
141
212
|
endpoint = http_req.endpoint.dup
|
142
213
|
endpoint.scheme = scheme
|
@@ -144,17 +215,42 @@ module Aws
|
|
144
215
|
http_req.endpoint = URI.parse(endpoint.to_s)
|
145
216
|
end
|
146
217
|
|
147
|
-
# hoist x-amz-* headers to the querystring
|
148
218
|
query = http_req.endpoint.query ? http_req.endpoint.query.split('&') : []
|
149
|
-
http_req.headers.
|
150
|
-
|
151
|
-
|
219
|
+
http_req.headers.each do |key, value|
|
220
|
+
next unless key =~ /^x-amz/i
|
221
|
+
|
222
|
+
if hoist
|
223
|
+
value = Aws::Sigv4::Signer.uri_escape(value)
|
152
224
|
key = Aws::Sigv4::Signer.uri_escape(key)
|
225
|
+
# hoist x-amz-* headers to the querystring
|
226
|
+
http_req.headers.delete(key)
|
153
227
|
query << "#{key}=#{value}"
|
228
|
+
else
|
229
|
+
x_amz_headers[key] = value
|
154
230
|
end
|
155
231
|
end
|
156
232
|
http_req.endpoint.query = query.join('&') unless query.empty?
|
157
233
|
|
234
|
+
signing_algorithm = :sigv4
|
235
|
+
|
236
|
+
# If it's an ARN, get the resolved region and service
|
237
|
+
if (arn = context.metadata[:s3_arn])
|
238
|
+
region = arn[:resolved_region]
|
239
|
+
service = arn[:arn].service
|
240
|
+
region = arn[:arn].is_a?(MultiRegionAccessPointARN) ? '*': arn[:resolved_region]
|
241
|
+
signing_algorithm = arn[:arn].is_a?(MultiRegionAccessPointARN) ? :sigv4a : :sigv4
|
242
|
+
end
|
243
|
+
|
244
|
+
signer = Aws::Sigv4::Signer.new(
|
245
|
+
service: service || 's3',
|
246
|
+
region: region || context.config.region,
|
247
|
+
signing_algorithm: signing_algorithm,
|
248
|
+
credentials_provider: context.config.credentials,
|
249
|
+
unsigned_headers: unsigned_headers,
|
250
|
+
apply_checksum_header: false,
|
251
|
+
uri_escape_path: false
|
252
|
+
)
|
253
|
+
|
158
254
|
url = signer.presign_url(
|
159
255
|
http_method: http_req.http_method,
|
160
256
|
url: http_req.endpoint,
|
@@ -166,16 +262,8 @@ module Aws
|
|
166
262
|
|
167
263
|
Seahorse::Client::Response.new(context: context, data: url)
|
168
264
|
end
|
169
|
-
|
170
|
-
|
171
|
-
def build_signer(cfg, unsigned_headers)
|
172
|
-
Aws::Sigv4::Signer.new(
|
173
|
-
service: 's3',
|
174
|
-
region: cfg.region,
|
175
|
-
credentials_provider: cfg.credentials,
|
176
|
-
unsigned_headers: unsigned_headers,
|
177
|
-
uri_escape_path: false
|
178
|
-
)
|
265
|
+
# Return the headers
|
266
|
+
x_amz_headers
|
179
267
|
end
|
180
268
|
end
|
181
269
|
end
|
data/lib/aws-sdk-s3/resource.rb
CHANGED
@@ -1,11 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# WARNING ABOUT GENERATED CODE
|
2
4
|
#
|
3
5
|
# This file is generated. See the contributing guide for more information:
|
4
|
-
# https://github.com/aws/aws-sdk-ruby/blob/
|
6
|
+
# https://github.com/aws/aws-sdk-ruby/blob/version-3/CONTRIBUTING.md
|
5
7
|
#
|
6
8
|
# WARNING ABOUT GENERATED CODE
|
7
9
|
|
8
10
|
module Aws::S3
|
11
|
+
|
12
|
+
# This class provides a resource oriented interface for S3.
|
13
|
+
# To create a resource object:
|
14
|
+
#
|
15
|
+
# resource = Aws::S3::Resource.new(region: 'us-west-2')
|
16
|
+
#
|
17
|
+
# You can supply a client object with custom configuration that will be used for all resource operations.
|
18
|
+
# If you do not pass `:client`, a default client will be constructed.
|
19
|
+
#
|
20
|
+
# client = Aws::S3::Client.new(region: 'us-west-2')
|
21
|
+
# resource = Aws::S3::Resource.new(client: client)
|
22
|
+
#
|
9
23
|
class Resource
|
10
24
|
|
11
25
|
# @param options ({})
|
@@ -27,7 +41,7 @@ module Aws::S3
|
|
27
41
|
# acl: "private", # accepts private, public-read, public-read-write, authenticated-read
|
28
42
|
# bucket: "BucketName", # required
|
29
43
|
# create_bucket_configuration: {
|
30
|
-
# location_constraint: "
|
44
|
+
# location_constraint: "af-south-1", # accepts af-south-1, ap-east-1, ap-northeast-1, ap-northeast-2, ap-northeast-3, ap-south-1, ap-southeast-1, ap-southeast-2, ca-central-1, cn-north-1, cn-northwest-1, EU, eu-central-1, eu-north-1, eu-south-1, eu-west-1, eu-west-2, eu-west-3, me-south-1, sa-east-1, us-east-2, us-gov-east-1, us-gov-west-1, us-west-1, us-west-2
|
31
45
|
# },
|
32
46
|
# grant_full_control: "GrantFullControl",
|
33
47
|
# grant_read: "GrantRead",
|
@@ -35,12 +49,15 @@ module Aws::S3
|
|
35
49
|
# grant_write: "GrantWrite",
|
36
50
|
# grant_write_acp: "GrantWriteACP",
|
37
51
|
# object_lock_enabled_for_bucket: false,
|
52
|
+
# object_ownership: "BucketOwnerPreferred", # accepts BucketOwnerPreferred, ObjectWriter, BucketOwnerEnforced
|
38
53
|
# })
|
39
54
|
# @param [Hash] options ({})
|
40
55
|
# @option options [String] :acl
|
41
56
|
# The canned ACL to apply to the bucket.
|
42
57
|
# @option options [required, String] :bucket
|
58
|
+
# The name of the bucket to create.
|
43
59
|
# @option options [Types::CreateBucketConfiguration] :create_bucket_configuration
|
60
|
+
# The configuration information for the bucket.
|
44
61
|
# @option options [String] :grant_full_control
|
45
62
|
# Allows grantee the read, write, read ACP, and write ACP permissions on
|
46
63
|
# the bucket.
|
@@ -49,16 +66,35 @@ module Aws::S3
|
|
49
66
|
# @option options [String] :grant_read_acp
|
50
67
|
# Allows grantee to read the bucket ACL.
|
51
68
|
# @option options [String] :grant_write
|
52
|
-
# Allows grantee to create
|
53
|
-
#
|
69
|
+
# Allows grantee to create new objects in the bucket.
|
70
|
+
#
|
71
|
+
# For the bucket and object owners of existing objects, also allows
|
72
|
+
# deletions and overwrites of those objects.
|
54
73
|
# @option options [String] :grant_write_acp
|
55
74
|
# Allows grantee to write the ACL for the applicable bucket.
|
56
75
|
# @option options [Boolean] :object_lock_enabled_for_bucket
|
57
|
-
# Specifies whether you want
|
58
|
-
#
|
76
|
+
# Specifies whether you want S3 Object Lock to be enabled for the new
|
77
|
+
# bucket.
|
78
|
+
# @option options [String] :object_ownership
|
79
|
+
# The container element for object ownership for a bucket's ownership
|
80
|
+
# controls.
|
81
|
+
#
|
82
|
+
# BucketOwnerPreferred - Objects uploaded to the bucket change ownership
|
83
|
+
# to the bucket owner if the objects are uploaded with the
|
84
|
+
# `bucket-owner-full-control` canned ACL.
|
85
|
+
#
|
86
|
+
# ObjectWriter - The uploading account will own the object if the object
|
87
|
+
# is uploaded with the `bucket-owner-full-control` canned ACL.
|
88
|
+
#
|
89
|
+
# BucketOwnerEnforced - Access control lists (ACLs) are disabled and no
|
90
|
+
# longer affect permissions. The bucket owner automatically owns and has
|
91
|
+
# full control over every object in the bucket. The bucket only accepts
|
92
|
+
# PUT requests that don't specify an ACL or bucket owner full control
|
93
|
+
# ACLs, such as the `bucket-owner-full-control` canned ACL or an
|
94
|
+
# equivalent form of this ACL expressed in the XML format.
|
59
95
|
# @return [Bucket]
|
60
96
|
def create_bucket(options = {})
|
61
|
-
|
97
|
+
@client.create_bucket(options)
|
62
98
|
Bucket.new(
|
63
99
|
name: options[:bucket],
|
64
100
|
client: @client
|