aws-sdk-s3 1.48.0 → 1.114.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +903 -0
  3. data/LICENSE.txt +202 -0
  4. data/VERSION +1 -0
  5. data/lib/aws-sdk-s3/arn/access_point_arn.rb +69 -0
  6. data/lib/aws-sdk-s3/arn/multi_region_access_point_arn.rb +68 -0
  7. data/lib/aws-sdk-s3/arn/object_lambda_arn.rb +69 -0
  8. data/lib/aws-sdk-s3/arn/outpost_access_point_arn.rb +74 -0
  9. data/lib/aws-sdk-s3/bucket.rb +375 -82
  10. data/lib/aws-sdk-s3/bucket_acl.rb +55 -15
  11. data/lib/aws-sdk-s3/bucket_cors.rb +67 -14
  12. data/lib/aws-sdk-s3/bucket_lifecycle.rb +54 -16
  13. data/lib/aws-sdk-s3/bucket_lifecycle_configuration.rb +56 -16
  14. data/lib/aws-sdk-s3/bucket_logging.rb +52 -13
  15. data/lib/aws-sdk-s3/bucket_notification.rb +43 -17
  16. data/lib/aws-sdk-s3/bucket_policy.rb +51 -13
  17. data/lib/aws-sdk-s3/bucket_region_cache.rb +2 -0
  18. data/lib/aws-sdk-s3/bucket_request_payment.rb +51 -12
  19. data/lib/aws-sdk-s3/bucket_tagging.rb +59 -14
  20. data/lib/aws-sdk-s3/bucket_versioning.rb +118 -12
  21. data/lib/aws-sdk-s3/bucket_website.rb +66 -17
  22. data/lib/aws-sdk-s3/client.rb +8996 -758
  23. data/lib/aws-sdk-s3/client_api.rb +778 -2
  24. data/lib/aws-sdk-s3/customizations/bucket.rb +59 -16
  25. data/lib/aws-sdk-s3/customizations/multipart_upload.rb +2 -0
  26. data/lib/aws-sdk-s3/customizations/object.rb +200 -62
  27. data/lib/aws-sdk-s3/customizations/object_summary.rb +5 -0
  28. data/lib/aws-sdk-s3/customizations/types/list_object_versions_output.rb +2 -0
  29. data/lib/aws-sdk-s3/customizations.rb +4 -1
  30. data/lib/aws-sdk-s3/encryption/client.rb +22 -5
  31. data/lib/aws-sdk-s3/encryption/decrypt_handler.rb +71 -29
  32. data/lib/aws-sdk-s3/encryption/default_cipher_provider.rb +43 -5
  33. data/lib/aws-sdk-s3/encryption/default_key_provider.rb +2 -0
  34. data/lib/aws-sdk-s3/encryption/encrypt_handler.rb +13 -2
  35. data/lib/aws-sdk-s3/encryption/errors.rb +2 -0
  36. data/lib/aws-sdk-s3/encryption/io_auth_decrypter.rb +2 -0
  37. data/lib/aws-sdk-s3/encryption/io_decrypter.rb +11 -3
  38. data/lib/aws-sdk-s3/encryption/io_encrypter.rb +2 -0
  39. data/lib/aws-sdk-s3/encryption/key_provider.rb +2 -0
  40. data/lib/aws-sdk-s3/encryption/kms_cipher_provider.rb +34 -3
  41. data/lib/aws-sdk-s3/encryption/materials.rb +8 -6
  42. data/lib/aws-sdk-s3/encryption/utils.rb +25 -0
  43. data/lib/aws-sdk-s3/encryption.rb +4 -0
  44. data/lib/aws-sdk-s3/encryptionV2/client.rb +566 -0
  45. data/lib/aws-sdk-s3/encryptionV2/decrypt_handler.rb +222 -0
  46. data/lib/aws-sdk-s3/encryptionV2/default_cipher_provider.rb +170 -0
  47. data/lib/aws-sdk-s3/encryptionV2/default_key_provider.rb +40 -0
  48. data/lib/aws-sdk-s3/encryptionV2/encrypt_handler.rb +65 -0
  49. data/lib/aws-sdk-s3/encryptionV2/errors.rb +37 -0
  50. data/lib/aws-sdk-s3/encryptionV2/io_auth_decrypter.rb +58 -0
  51. data/lib/aws-sdk-s3/encryptionV2/io_decrypter.rb +37 -0
  52. data/lib/aws-sdk-s3/encryptionV2/io_encrypter.rb +73 -0
  53. data/lib/aws-sdk-s3/encryptionV2/key_provider.rb +31 -0
  54. data/lib/aws-sdk-s3/encryptionV2/kms_cipher_provider.rb +169 -0
  55. data/lib/aws-sdk-s3/encryptionV2/materials.rb +60 -0
  56. data/lib/aws-sdk-s3/encryptionV2/utils.rb +103 -0
  57. data/lib/aws-sdk-s3/encryption_v2.rb +23 -0
  58. data/lib/aws-sdk-s3/errors.rb +123 -1
  59. data/lib/aws-sdk-s3/event_streams.rb +8 -1
  60. data/lib/aws-sdk-s3/file_downloader.rb +17 -10
  61. data/lib/aws-sdk-s3/file_part.rb +11 -6
  62. data/lib/aws-sdk-s3/file_uploader.rb +33 -14
  63. data/lib/aws-sdk-s3/legacy_signer.rb +17 -25
  64. data/lib/aws-sdk-s3/multipart_file_uploader.rb +78 -19
  65. data/lib/aws-sdk-s3/multipart_stream_uploader.rb +18 -7
  66. data/lib/aws-sdk-s3/multipart_upload.rb +178 -29
  67. data/lib/aws-sdk-s3/multipart_upload_error.rb +2 -0
  68. data/lib/aws-sdk-s3/multipart_upload_part.rb +233 -42
  69. data/lib/aws-sdk-s3/object.rb +846 -179
  70. data/lib/aws-sdk-s3/object_acl.rb +79 -21
  71. data/lib/aws-sdk-s3/object_copier.rb +2 -0
  72. data/lib/aws-sdk-s3/object_multipart_copier.rb +2 -0
  73. data/lib/aws-sdk-s3/object_summary.rb +613 -162
  74. data/lib/aws-sdk-s3/object_version.rb +162 -71
  75. data/lib/aws-sdk-s3/plugins/accelerate.rb +38 -38
  76. data/lib/aws-sdk-s3/plugins/arn.rb +254 -0
  77. data/lib/aws-sdk-s3/plugins/bucket_dns.rb +8 -8
  78. data/lib/aws-sdk-s3/plugins/bucket_name_restrictions.rb +25 -3
  79. data/lib/aws-sdk-s3/plugins/dualstack.rb +38 -33
  80. data/lib/aws-sdk-s3/plugins/expect_100_continue.rb +4 -4
  81. data/lib/aws-sdk-s3/plugins/get_bucket_location_fix.rb +3 -1
  82. data/lib/aws-sdk-s3/plugins/http_200_errors.rb +11 -3
  83. data/lib/aws-sdk-s3/plugins/iad_regional_endpoint.rb +73 -0
  84. data/lib/aws-sdk-s3/plugins/location_constraint.rb +2 -0
  85. data/lib/aws-sdk-s3/plugins/md5s.rb +34 -30
  86. data/lib/aws-sdk-s3/plugins/object_lambda_endpoint.rb +25 -0
  87. data/lib/aws-sdk-s3/plugins/redirects.rb +2 -0
  88. data/lib/aws-sdk-s3/plugins/s3_host_id.rb +2 -0
  89. data/lib/aws-sdk-s3/plugins/s3_signer.rb +94 -36
  90. data/lib/aws-sdk-s3/plugins/skip_whole_multipart_get_checksums.rb +31 -0
  91. data/lib/aws-sdk-s3/plugins/sse_cpk.rb +3 -1
  92. data/lib/aws-sdk-s3/plugins/streaming_retry.rb +139 -0
  93. data/lib/aws-sdk-s3/plugins/url_encoded_keys.rb +2 -0
  94. data/lib/aws-sdk-s3/presigned_post.rb +110 -51
  95. data/lib/aws-sdk-s3/presigner.rb +133 -45
  96. data/lib/aws-sdk-s3/resource.rb +43 -7
  97. data/lib/aws-sdk-s3/types.rb +8445 -1136
  98. data/lib/aws-sdk-s3/waiters.rb +67 -1
  99. data/lib/aws-sdk-s3.rb +12 -6
  100. 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 See {PresignedPost#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 See {PresignedPost#acl_starts_with}.
189
- # @option options [String] :cache_control See {PresignedPost#cache_control}.
190
- # @option options [String] :cache_control_starts_with See {PresignedPost#cache_control_starts_with}.
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 See {PresignedPost#content_type_starts_with}.
193
- # @option options [String] :content_disposition See {PresignedPost#content_disposition}.
194
- # @option options [String] :content_disposition_starts_with See {PresignedPost#content_disposition_starts_with}.
195
- # @option options [String] :content_encoding See {PresignedPost#content_encoding}.
196
- # @option options [String] :content_encoding_starts_with See {PresignedPost#content_encoding_starts_with}.
197
- # @option options [String] :expires See {PresignedPost#expires}.
198
- # @option options [String] :expires_starts_with See {PresignedPost#expires_starts_with}.
199
- # @option options [Range<Integer>] :content_length_range See {PresignedPost#content_length_range}.
200
- # @option options [String] :success_action_redirect See {PresignedPost#success_action_redirect}.
201
- # @option options [String] :success_action_redirect_starts_with See {PresignedPost#success_action_redirect_starts_with}.
202
- # @option options [String] :success_action_status See {PresignedPost#success_action_status}.
203
- # @option options [String] :storage_class See {PresignedPost#storage_class}.
204
- # @option options [String] :website_redirect_location See {PresignedPost#website_redirect_location}.
205
- # @option options [Hash<String,String>] :metadata See {PresignedPost#metadata}.
206
- # @option options [Hash<String,String>] :metadata_starts_with See {PresignedPost#metadata_starts_with}.
207
- # @option options [String] :server_side_encryption See {PresignedPost#server_side_encryption}.
208
- # @option options [String] :server_side_encryption_aws_kms_key_id See {PresignedPost#server_side_encryption_aws_kms_key_id}.
209
- # @option options [String] :server_side_encryption_customer_algorithm See {PresignedPost#server_side_encryption_customer_algorithm}.
210
- # @option options [String] :server_side_encryption_customer_key See {PresignedPost#server_side_encryption_customer_key}.
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 send("#{option_name}", option_value)
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("%Y%m%dT%H%M%SZ")
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
- define_method("#{field}") do |value|
261
- with(field_name, value)
262
- end
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
- if options[:starts_with]
265
- define_method("#{field}_starts_with") do |value|
266
- starts_with(field_name, value)
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. Use can use `${filename}`
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
- def key(key)
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
- def key_starts_with(prefix)
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
- def expires(time)
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
- def expires_starts_with(prefix)
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
- def content_length_range(byte_range)
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
- def metadata(hash)
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
- def metadata_starts_with(hash)
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(:server_side_encryption_aws_kms_key_id, 'x-amz-server-side-encryption-aws-kms-key-id')
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(:server_side_encryption_customer_algorithm, 'x-amz-server-side-encryption-customer-algorithm')
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
- def server_side_encryption_customer_key(value)
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
- def server_side_encryption_customer_key_starts_with(prefix)
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 = "key required; you must provide a key via :key, "
575
- msg << ":key_starts_with, or :allow_any => ['key']"
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
- url.host = @bucket_name + '.' + url.host
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 = '/' + @bucket_name
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("AWS4" + k_secret, datetime[0,8])
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')
@@ -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
- def presigned_url(method, params = {})
77
- if params[:key].nil? or params[:key] == ''
78
- raise ArgumentError, ":key must not be blank"
79
- end
80
- virtual_host = !!params.delete(:virtual_host)
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
- whitelisted_headers = params.delete(:whitelist_headers) || []
83
- unsigned_headers = BLACKLISTED_HEADERS - whitelisted_headers
84
- scheme = http_scheme(params, virtual_host)
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(req, expires_in(params), scheme, time, unsigned_headers)
90
- req.send_request.data
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
- private
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, virtual_host)
96
- if params.delete(:secure) == false || virtual_host
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
- msg = "expires_in value of #{expires_in} exceeds one-week maximum"
107
- raise ArgumentError, msg
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
- uri.scheme = 'http'
122
- uri.port = 80
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(req, expires_in, scheme, time, unsigned_headers)
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.keys.each do |key|
150
- if key.match(/^x-amz/i)
151
- value = Aws::Sigv4::Signer.uri_escape(http_req.headers.delete(key))
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
- end
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
@@ -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/master/CONTRIBUTING.md
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: "EU", # accepts EU, eu-west-1, us-west-1, us-west-2, ap-south-1, ap-southeast-1, ap-southeast-2, ap-northeast-1, sa-east-1, cn-north-1, eu-central-1
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, overwrite, and delete any object in the
53
- # bucket.
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 Amazon S3 object lock to be enabled for the
58
- # new bucket.
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
- resp = @client.create_bucket(options)
97
+ @client.create_bucket(options)
62
98
  Bucket.new(
63
99
  name: options[:bucket],
64
100
  client: @client