aws-sdk-s3 1.86.2 → 1.116.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +913 -0
  3. data/LICENSE.txt +202 -0
  4. data/VERSION +1 -0
  5. data/lib/aws-sdk-s3/arn/access_point_arn.rb +19 -12
  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 +15 -12
  9. data/lib/aws-sdk-s3/bucket.rb +145 -47
  10. data/lib/aws-sdk-s3/bucket_acl.rb +27 -8
  11. data/lib/aws-sdk-s3/bucket_cors.rb +28 -11
  12. data/lib/aws-sdk-s3/bucket_lifecycle.rb +30 -11
  13. data/lib/aws-sdk-s3/bucket_lifecycle_configuration.rb +31 -9
  14. data/lib/aws-sdk-s3/bucket_logging.rb +24 -8
  15. data/lib/aws-sdk-s3/bucket_notification.rb +21 -9
  16. data/lib/aws-sdk-s3/bucket_policy.rb +26 -9
  17. data/lib/aws-sdk-s3/bucket_request_payment.rb +26 -10
  18. data/lib/aws-sdk-s3/bucket_tagging.rb +26 -9
  19. data/lib/aws-sdk-s3/bucket_versioning.rb +67 -16
  20. data/lib/aws-sdk-s3/bucket_website.rb +26 -9
  21. data/lib/aws-sdk-s3/client.rb +3633 -1862
  22. data/lib/aws-sdk-s3/client_api.rb +546 -116
  23. data/lib/aws-sdk-s3/customizations/bucket.rb +8 -3
  24. data/lib/aws-sdk-s3/customizations/object.rb +116 -18
  25. data/lib/aws-sdk-s3/encryption/client.rb +1 -1
  26. data/lib/aws-sdk-s3/encryption/decrypt_handler.rb +0 -4
  27. data/lib/aws-sdk-s3/encryptionV2/client.rb +1 -1
  28. data/lib/aws-sdk-s3/encryptionV2/decrypt_handler.rb +0 -4
  29. data/lib/aws-sdk-s3/encryptionV2/default_cipher_provider.rb +3 -3
  30. data/lib/aws-sdk-s3/encryptionV2/encrypt_handler.rb +0 -4
  31. data/lib/aws-sdk-s3/errors.rb +1 -1
  32. data/lib/aws-sdk-s3/event_streams.rb +1 -1
  33. data/lib/aws-sdk-s3/file_downloader.rb +7 -2
  34. data/lib/aws-sdk-s3/file_uploader.rb +8 -3
  35. data/lib/aws-sdk-s3/multipart_file_uploader.rb +26 -7
  36. data/lib/aws-sdk-s3/multipart_upload.rb +133 -19
  37. data/lib/aws-sdk-s3/multipart_upload_part.rb +141 -21
  38. data/lib/aws-sdk-s3/object.rb +391 -130
  39. data/lib/aws-sdk-s3/object_acl.rb +30 -11
  40. data/lib/aws-sdk-s3/object_summary.rb +243 -115
  41. data/lib/aws-sdk-s3/object_version.rb +80 -53
  42. data/lib/aws-sdk-s3/plugins/accelerate.rb +13 -4
  43. data/lib/aws-sdk-s3/plugins/arn.rb +125 -58
  44. data/lib/aws-sdk-s3/plugins/bucket_dns.rb +1 -1
  45. data/lib/aws-sdk-s3/plugins/dualstack.rb +33 -32
  46. data/lib/aws-sdk-s3/plugins/expect_100_continue.rb +2 -1
  47. data/lib/aws-sdk-s3/plugins/get_bucket_location_fix.rb +1 -1
  48. data/lib/aws-sdk-s3/plugins/iad_regional_endpoint.rb +17 -11
  49. data/lib/aws-sdk-s3/plugins/md5s.rb +5 -3
  50. data/lib/aws-sdk-s3/plugins/object_lambda_endpoint.rb +25 -0
  51. data/lib/aws-sdk-s3/plugins/s3_signer.rb +55 -28
  52. data/lib/aws-sdk-s3/plugins/skip_whole_multipart_get_checksums.rb +31 -0
  53. data/lib/aws-sdk-s3/plugins/streaming_retry.rb +23 -2
  54. data/lib/aws-sdk-s3/presigned_post.rb +38 -19
  55. data/lib/aws-sdk-s3/presigner.rb +33 -30
  56. data/lib/aws-sdk-s3/resource.rb +24 -4
  57. data/lib/aws-sdk-s3/types.rb +3777 -1306
  58. data/lib/aws-sdk-s3/waiters.rb +1 -1
  59. data/lib/aws-sdk-s3.rb +2 -2
  60. metadata +20 -14
@@ -3,7 +3,7 @@
3
3
  # WARNING ABOUT GENERATED CODE
4
4
  #
5
5
  # This file is generated. See the contributing guide for more information:
6
- # https://github.com/aws/aws-sdk-ruby/blob/master/CONTRIBUTING.md
6
+ # https://github.com/aws/aws-sdk-ruby/blob/version-3/CONTRIBUTING.md
7
7
  #
8
8
  # WARNING ABOUT GENERATED CODE
9
9
 
@@ -56,6 +56,12 @@ module Aws::S3
56
56
  data[:etag]
57
57
  end
58
58
 
59
+ # The algorithm that was used to create a checksum of the object.
60
+ # @return [Array<String>]
61
+ def checksum_algorithm
62
+ data[:checksum_algorithm]
63
+ end
64
+
59
65
  # Size in bytes of the object.
60
66
  # @return [Integer]
61
67
  def size
@@ -245,20 +251,21 @@ module Aws::S3
245
251
  # @option options [String] :request_payer
246
252
  # Confirms that the requester knows that they will be charged for the
247
253
  # request. Bucket owners need not specify this parameter in their
248
- # requests. For information about downloading objects from requester
249
- # pays buckets, see [Downloading Objects in Requestor Pays Buckets][1]
250
- # in the *Amazon S3 Developer Guide*.
254
+ # requests. For information about downloading objects from Requester
255
+ # Pays buckets, see [Downloading Objects in Requester Pays Buckets][1]
256
+ # in the *Amazon S3 User Guide*.
251
257
  #
252
258
  #
253
259
  #
254
260
  # [1]: https://docs.aws.amazon.com/AmazonS3/latest/dev/ObjectsinRequesterPaysBuckets.html
255
261
  # @option options [Boolean] :bypass_governance_retention
256
262
  # Indicates whether S3 Object Lock should bypass Governance-mode
257
- # restrictions to process this operation.
263
+ # restrictions to process this operation. To use this header, you must
264
+ # have the `s3:BypassGovernanceRetention` permission.
258
265
  # @option options [String] :expected_bucket_owner
259
- # The account id of the expected bucket owner. If the bucket is owned by
260
- # a different account, the request will fail with an HTTP `403 (Access
261
- # Denied)` error.
266
+ # The account ID of the expected bucket owner. If the bucket is owned by
267
+ # a different account, the request fails with the HTTP status code `403
268
+ # Forbidden` (access denied).
262
269
  # @return [Types::DeleteObjectOutput]
263
270
  def delete(options = {})
264
271
  options = options.merge(
@@ -290,20 +297,21 @@ module Aws::S3
290
297
  # request_payer: "requester", # accepts requester
291
298
  # part_number: 1,
292
299
  # expected_bucket_owner: "AccountId",
300
+ # checksum_mode: "ENABLED", # accepts ENABLED
293
301
  # })
294
302
  # @param [Hash] options ({})
295
303
  # @option options [String] :if_match
296
304
  # Return the object only if its entity tag (ETag) is the same as the one
297
- # specified, otherwise return a 412 (precondition failed).
305
+ # specified; otherwise, return a 412 (precondition failed) error.
298
306
  # @option options [Time,DateTime,Date,Integer,String] :if_modified_since
299
307
  # Return the object only if it has been modified since the specified
300
- # time, otherwise return a 304 (not modified).
308
+ # time; otherwise, return a 304 (not modified) error.
301
309
  # @option options [String] :if_none_match
302
310
  # Return the object only if its entity tag (ETag) is different from the
303
- # one specified, otherwise return a 304 (not modified).
311
+ # one specified; otherwise, return a 304 (not modified) error.
304
312
  # @option options [Time,DateTime,Date,Integer,String] :if_unmodified_since
305
313
  # Return the object only if it has not been modified since the specified
306
- # time, otherwise return a 412 (precondition failed).
314
+ # time; otherwise, return a 412 (precondition failed) error.
307
315
  # @option options [String] :range
308
316
  # Downloads the specified range bytes of an object. For more information
309
317
  # about the HTTP Range header, see
@@ -330,13 +338,13 @@ module Aws::S3
330
338
  # @option options [Time,DateTime,Date,Integer,String] :response_expires
331
339
  # Sets the `Expires` header of the response.
332
340
  # @option options [String] :sse_customer_algorithm
333
- # Specifies the algorithm to use to when encrypting the object (for
341
+ # Specifies the algorithm to use to when decrypting the object (for
334
342
  # example, AES256).
335
343
  # @option options [String] :sse_customer_key
336
- # Specifies the customer-provided encryption key for Amazon S3 to use in
337
- # encrypting data. This value is used to store the object and then it is
338
- # discarded; Amazon S3 does not store the encryption key. The key must
339
- # be appropriate for use with the algorithm specified in the
344
+ # Specifies the customer-provided encryption key for Amazon S3 used to
345
+ # encrypt the data. This value is used to decrypt the object when
346
+ # recovering it and must match the one used when storing the data. The
347
+ # key must be appropriate for use with the algorithm specified in the
340
348
  # `x-amz-server-side-encryption-customer-algorithm` header.
341
349
  # @option options [String] :sse_customer_key_md5
342
350
  # Specifies the 128-bit MD5 digest of the encryption key according to
@@ -345,9 +353,9 @@ module Aws::S3
345
353
  # @option options [String] :request_payer
346
354
  # Confirms that the requester knows that they will be charged for the
347
355
  # request. Bucket owners need not specify this parameter in their
348
- # requests. For information about downloading objects from requester
349
- # pays buckets, see [Downloading Objects in Requestor Pays Buckets][1]
350
- # in the *Amazon S3 Developer Guide*.
356
+ # requests. For information about downloading objects from Requester
357
+ # Pays buckets, see [Downloading Objects in Requester Pays Buckets][1]
358
+ # in the *Amazon S3 User Guide*.
351
359
  #
352
360
  #
353
361
  #
@@ -358,9 +366,11 @@ module Aws::S3
358
366
  # for the part specified. Useful for downloading just a part of an
359
367
  # object.
360
368
  # @option options [String] :expected_bucket_owner
361
- # The account id of the expected bucket owner. If the bucket is owned by
362
- # a different account, the request will fail with an HTTP `403 (Access
363
- # Denied)` error.
369
+ # The account ID of the expected bucket owner. If the bucket is owned by
370
+ # a different account, the request fails with the HTTP status code `403
371
+ # Forbidden` (access denied).
372
+ # @option options [String] :checksum_mode
373
+ # To retrieve the checksum, this mode must be enabled.
364
374
  # @return [Types::GetObjectOutput]
365
375
  def get(options = {}, &block)
366
376
  options = options.merge(
@@ -386,33 +396,24 @@ module Aws::S3
386
396
  # request_payer: "requester", # accepts requester
387
397
  # part_number: 1,
388
398
  # expected_bucket_owner: "AccountId",
399
+ # checksum_mode: "ENABLED", # accepts ENABLED
389
400
  # })
390
401
  # @param [Hash] options ({})
391
402
  # @option options [String] :if_match
392
403
  # Return the object only if its entity tag (ETag) is the same as the one
393
- # specified, otherwise return a 412 (precondition failed).
404
+ # specified; otherwise, return a 412 (precondition failed) error.
394
405
  # @option options [Time,DateTime,Date,Integer,String] :if_modified_since
395
406
  # Return the object only if it has been modified since the specified
396
- # time, otherwise return a 304 (not modified).
407
+ # time; otherwise, return a 304 (not modified) error.
397
408
  # @option options [String] :if_none_match
398
409
  # Return the object only if its entity tag (ETag) is different from the
399
- # one specified, otherwise return a 304 (not modified).
410
+ # one specified; otherwise, return a 304 (not modified) error.
400
411
  # @option options [Time,DateTime,Date,Integer,String] :if_unmodified_since
401
412
  # Return the object only if it has not been modified since the specified
402
- # time, otherwise return a 412 (precondition failed).
413
+ # time; otherwise, return a 412 (precondition failed) error.
403
414
  # @option options [String] :range
404
- # Downloads the specified range bytes of an object. For more information
405
- # about the HTTP Range header, see
406
- # [http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35][1].
407
- #
408
- # <note markdown="1"> Amazon S3 doesn't support retrieving multiple ranges of data per
409
- # `GET` request.
410
- #
411
- # </note>
412
- #
413
- #
414
- #
415
- # [1]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35
415
+ # Because `HeadObject` returns only the metadata for an object, this
416
+ # parameter has no effect.
416
417
  # @option options [String] :sse_customer_algorithm
417
418
  # Specifies the algorithm to use to when encrypting the object (for
418
419
  # example, AES256).
@@ -429,9 +430,9 @@ module Aws::S3
429
430
  # @option options [String] :request_payer
430
431
  # Confirms that the requester knows that they will be charged for the
431
432
  # request. Bucket owners need not specify this parameter in their
432
- # requests. For information about downloading objects from requester
433
- # pays buckets, see [Downloading Objects in Requestor Pays Buckets][1]
434
- # in the *Amazon S3 Developer Guide*.
433
+ # requests. For information about downloading objects from Requester
434
+ # Pays buckets, see [Downloading Objects in Requester Pays Buckets][1]
435
+ # in the *Amazon S3 User Guide*.
435
436
  #
436
437
  #
437
438
  #
@@ -442,9 +443,16 @@ module Aws::S3
442
443
  # for the part specified. Useful querying about the size of the part and
443
444
  # the number of parts in this object.
444
445
  # @option options [String] :expected_bucket_owner
445
- # The account id of the expected bucket owner. If the bucket is owned by
446
- # a different account, the request will fail with an HTTP `403 (Access
447
- # Denied)` error.
446
+ # The account ID of the expected bucket owner. If the bucket is owned by
447
+ # a different account, the request fails with the HTTP status code `403
448
+ # Forbidden` (access denied).
449
+ # @option options [String] :checksum_mode
450
+ # To retrieve the checksum, this parameter must be enabled.
451
+ #
452
+ # In addition, if you enable `ChecksumMode` and the object is encrypted
453
+ # with Amazon Web Services Key Management Service (Amazon Web Services
454
+ # KMS), you must have permission to use the `kms:Decrypt` action for the
455
+ # request to succeed.
448
456
  # @return [Types::HeadObjectOutput]
449
457
  def head(options = {})
450
458
  options = options.merge(
@@ -524,6 +532,7 @@ module Aws::S3
524
532
  # request_payer: "requester", # accepts requester
525
533
  # bypass_governance_retention: false,
526
534
  # expected_bucket_owner: "AccountId",
535
+ # checksum_algorithm: "CRC32", # accepts CRC32, CRC32C, SHA1, SHA256
527
536
  # })
528
537
  # @param options ({})
529
538
  # @option options [String] :mfa
@@ -534,21 +543,39 @@ module Aws::S3
534
543
  # @option options [String] :request_payer
535
544
  # Confirms that the requester knows that they will be charged for the
536
545
  # request. Bucket owners need not specify this parameter in their
537
- # requests. For information about downloading objects from requester
538
- # pays buckets, see [Downloading Objects in Requestor Pays Buckets][1]
539
- # in the *Amazon S3 Developer Guide*.
546
+ # requests. For information about downloading objects from Requester
547
+ # Pays buckets, see [Downloading Objects in Requester Pays Buckets][1]
548
+ # in the *Amazon S3 User Guide*.
540
549
  #
541
550
  #
542
551
  #
543
552
  # [1]: https://docs.aws.amazon.com/AmazonS3/latest/dev/ObjectsinRequesterPaysBuckets.html
544
553
  # @option options [Boolean] :bypass_governance_retention
545
554
  # Specifies whether you want to delete this object even if it has a
546
- # Governance-type Object Lock in place. You must have sufficient
547
- # permissions to perform this operation.
555
+ # Governance-type Object Lock in place. To use this header, you must
556
+ # have the `s3:BypassGovernanceRetention` permission.
548
557
  # @option options [String] :expected_bucket_owner
549
- # The account id of the expected bucket owner. If the bucket is owned by
550
- # a different account, the request will fail with an HTTP `403 (Access
551
- # Denied)` error.
558
+ # The account ID of the expected bucket owner. If the bucket is owned by
559
+ # a different account, the request fails with the HTTP status code `403
560
+ # Forbidden` (access denied).
561
+ # @option options [String] :checksum_algorithm
562
+ # Indicates the algorithm used to create the checksum for the object
563
+ # when using the SDK. This header will not provide any additional
564
+ # functionality if not using the SDK. When sending this header, there
565
+ # must be a corresponding `x-amz-checksum` or `x-amz-trailer` header
566
+ # sent. Otherwise, Amazon S3 fails the request with the HTTP status code
567
+ # `400 Bad Request`. For more information, see [Checking object
568
+ # integrity][1] in the *Amazon S3 User Guide*.
569
+ #
570
+ # If you provide an individual checksum, Amazon S3 ignores any provided
571
+ # `ChecksumAlgorithm` parameter.
572
+ #
573
+ # This checksum algorithm must be the same for all parts and it match
574
+ # the checksum value supplied in the `CreateMultipartUpload` request.
575
+ #
576
+ #
577
+ #
578
+ # [1]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html
552
579
  # @return [void]
553
580
  def batch_delete!(options = {})
554
581
  batch_enum.each do |batch|
@@ -29,7 +29,7 @@ each bucket. [Go here for more information](http://docs.aws.amazon.com/AmazonS3/
29
29
  OptionHandler, step: :initialize, operations: operations
30
30
  )
31
31
  handlers.add(
32
- AccelerateHandler, step: :build, priority: 0, operations: operations
32
+ AccelerateHandler, step: :build, priority: 11, operations: operations
33
33
  )
34
34
  end
35
35
 
@@ -40,8 +40,17 @@ each bucket. [Go here for more information](http://docs.aws.amazon.com/AmazonS3/
40
40
  if context.params.is_a?(Hash)
41
41
  accelerate = context.params.delete(:use_accelerate_endpoint)
42
42
  end
43
- if accelerate.nil?
44
- accelerate = context.config.use_accelerate_endpoint
43
+ accelerate = context.config.use_accelerate_endpoint if accelerate.nil?
44
+ # Raise if :endpoint and accelerate are both provided
45
+ if accelerate && !context.config.regional_endpoint
46
+ raise ArgumentError,
47
+ 'Cannot use both :use_accelerate_endpoint and :endpoint'
48
+ end
49
+ # Raise if :use_fips_endpoint and accelerate are both provided
50
+ if accelerate && context.config.use_fips_endpoint
51
+ raise ArgumentError,
52
+ 'Cannot use both :use_accelerate_endpoint and '\
53
+ ':use_fips_endpoint'
45
54
  end
46
55
  context[:use_accelerate_endpoint] = accelerate
47
56
  @handler.call(context)
@@ -51,7 +60,7 @@ each bucket. [Go here for more information](http://docs.aws.amazon.com/AmazonS3/
51
60
  # @api private
52
61
  class AccelerateHandler < Seahorse::Client::Handler
53
62
  def call(context)
54
- if context[:use_accelerate_endpoint]
63
+ if context.config.regional_endpoint && context[:use_accelerate_endpoint]
55
64
  dualstack = !!context[:use_dualstack_endpoint]
56
65
  use_accelerate_endpoint(context, dualstack)
57
66
  end
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative '../arn/access_point_arn'
4
+ require_relative '../arn/object_lambda_arn'
4
5
  require_relative '../arn/outpost_access_point_arn'
6
+ require_relative '../arn/multi_region_access_point_arn'
5
7
 
6
8
  module Aws
7
9
  module S3
@@ -22,11 +24,48 @@ be made. Set to `false` to use the client's region instead.
22
24
  resolve_s3_use_arn_region(cfg)
23
25
  end
24
26
 
27
+ option(
28
+ :s3_disable_multiregion_access_points,
29
+ default: false,
30
+ doc_type: 'Boolean',
31
+ docstring: <<-DOCS) do |cfg|
32
+ When set to `false` this will option will raise errors when multi-region
33
+ access point ARNs are used. Multi-region access points can potentially
34
+ result in cross region requests.
35
+ DOCS
36
+ resolve_s3_disable_multiregion_access_points(cfg)
37
+ end
38
+
39
+ # param validator is validate:50
40
+ # endpoint is build:90 (populates the URI for the first time)
41
+ # endpoint pattern is build:10
25
42
  def add_handlers(handlers, _config)
26
- handlers.add(Handler)
43
+ handlers.add(ARNHandler, step: :validate, priority: 75)
44
+ handlers.add(UrlHandler)
27
45
  end
28
46
 
29
- class Handler < Seahorse::Client::Handler
47
+ # After extracting out any ARN input, resolve a new URL with it.
48
+ class UrlHandler < Seahorse::Client::Handler
49
+ def call(context)
50
+ if context.metadata[:s3_arn]
51
+ ARN.resolve_url!(
52
+ context.http_request.endpoint,
53
+ context.metadata[:s3_arn][:arn],
54
+ context.metadata[:s3_arn][:resolved_region],
55
+ context.metadata[:s3_arn][:fips],
56
+ context.metadata[:s3_arn][:dualstack],
57
+ # if regional_endpoint is false, a custom endpoint was provided
58
+ # in this case, we want to prefix the endpoint using the ARN
59
+ !context.config.regional_endpoint
60
+ )
61
+ end
62
+ @handler.call(context)
63
+ end
64
+ end
65
+
66
+ # This plugin will extract out any ARN input and set context for other
67
+ # plugins to use without having to translate the ARN again.
68
+ class ARNHandler < Seahorse::Client::Handler
30
69
  def call(context)
31
70
  bucket_member = _bucket_member(context.operation.input.shape)
32
71
  if bucket_member && (bucket = context.params[bucket_member])
@@ -38,12 +77,12 @@ be made. Set to `false` to use the client's region instead.
38
77
  if arn
39
78
  validate_config!(context, arn)
40
79
 
41
- ARN.resolve_url!(
42
- context.http_request.endpoint,
43
- arn,
44
- resolved_region,
45
- extract_dualstack_config!(context)
46
- )
80
+ context.metadata[:s3_arn] = {
81
+ arn: arn,
82
+ resolved_region: resolved_region,
83
+ fips: context.config.use_fips_endpoint,
84
+ dualstack: extract_dualstack_config!(context)
85
+ }
47
86
  end
48
87
  end
49
88
  @handler.call(context)
@@ -66,28 +105,35 @@ be made. Set to `false` to use the client's region instead.
66
105
  end
67
106
 
68
107
  def validate_config!(context, arn)
69
- unless context.config.regional_endpoint
70
- raise ArgumentError,
71
- 'Cannot provide both an Access Point ARN and setting '\
72
- ':endpoint.'
73
- end
74
-
75
108
  if context.config.force_path_style
76
109
  raise ArgumentError,
77
- 'Cannot provide both an Access Point ARN and setting '\
78
- ':force_path_style to true.'
110
+ 'Cannot provide an Access Point ARN when '\
111
+ '`:force_path_style` is set to true.'
79
112
  end
80
113
 
81
114
  if context.config.use_accelerate_endpoint
82
115
  raise ArgumentError,
83
- 'Cannot provide both an Access Point ARN and setting '\
84
- ':use_accelerate_endpoint to true.'
116
+ 'Cannot provide an Access Point ARN when '\
117
+ '`:use_accelerate_endpoint` is set to true.'
85
118
  end
86
119
 
87
120
  if !arn.support_dualstack? && context[:use_dualstack_endpoint]
88
121
  raise ArgumentError,
89
- 'Cannot provide both an Outpost Access Point ARN and '\
90
- 'setting :use_dualstack_endpoint to true.'
122
+ 'Cannot provide an Outpost Access Point, Object Lambda, '\
123
+ 'or Multi-region Access Point ARN'\
124
+ ' when `:use_dualstack_endpoint` is set to true.'
125
+ end
126
+
127
+ if arn.region.empty? && context.config.s3_disable_multiregion_access_points
128
+ raise ArgumentError,
129
+ 'Cannot provide a Multi-region Access Point ARN with '\
130
+ '`:s3_disable_multiregion_access_points` set to true'
131
+ end
132
+
133
+ if context.config.use_fips_endpoint && !arn.support_fips?
134
+ raise ArgumentError,
135
+ 'FIPS client regions are not supported for this type '\
136
+ 'of ARN.'
91
137
  end
92
138
  end
93
139
  end
@@ -97,15 +143,7 @@ be made. Set to `false` to use the client's region instead.
97
143
  def resolve_arn!(member_value, region, use_arn_region)
98
144
  if Aws::ARNParser.arn?(member_value)
99
145
  arn = Aws::ARNParser.parse(member_value)
100
- if arn.resource.start_with?('accesspoint')
101
- s3_arn = Aws::S3::AccessPointARN.new(arn.to_h)
102
- elsif arn.resource.start_with?('outpost')
103
- s3_arn = Aws::S3::OutpostAccessPointARN.new(arn.to_h)
104
- else
105
- raise ArgumentError,
106
- 'Only Access Point and Outpost Access Point type ARNs '\
107
- 'are currently supported.'
108
- end
146
+ s3_arn = resolve_arn_type!(arn)
109
147
  s3_arn.validate_arn!
110
148
  validate_region_config!(s3_arn, region, use_arn_region)
111
149
  region = s3_arn.region if use_arn_region
@@ -116,20 +154,53 @@ be made. Set to `false` to use the client's region instead.
116
154
  end
117
155
 
118
156
  # @api private
119
- def resolve_url!(url, arn, region, dualstack = false)
120
- url.host = arn.host_url(region, dualstack)
157
+ def resolve_url!(url, arn, region, fips = false, dualstack = false, has_custom_endpoint = false)
158
+ custom_endpoint = url.host if has_custom_endpoint
159
+ url.host = arn.host_url(region, fips, dualstack, custom_endpoint)
121
160
  url.path = url_path(url.path, arn)
122
161
  url
123
162
  end
124
163
 
125
164
  private
126
165
 
166
+ def resolve_arn_type!(arn)
167
+ case arn.service
168
+ when 's3'
169
+ arn.region.empty? ?
170
+ Aws::S3::MultiRegionAccessPointARN.new(arn.to_h) :
171
+ Aws::S3::AccessPointARN.new(arn.to_h)
172
+ when 's3-outposts'
173
+ Aws::S3::OutpostAccessPointARN.new(arn.to_h)
174
+ when 's3-object-lambda'
175
+ Aws::S3::ObjectLambdaARN.new(arn.to_h)
176
+ else
177
+ raise ArgumentError,
178
+ 'Only Access Point, Outposts, and Object Lambdas ARNs '\
179
+ 'are currently supported.'
180
+ end
181
+ end
182
+
127
183
  def resolve_s3_use_arn_region(cfg)
128
184
  value = ENV['AWS_S3_USE_ARN_REGION'] ||
129
185
  Aws.shared_config.s3_use_arn_region(profile: cfg.profile) ||
130
186
  'true'
131
187
  value = Aws::Util.str_2_bool(value)
132
188
  # Raise if provided value is not true or false
189
+ if value.nil?
190
+ raise ArgumentError,
191
+ 'Must provide either `true` or `false` for the '\
192
+ '`s3_use_arn_region` profile option or for '\
193
+ "ENV['AWS_S3_USE_ARN_REGION']."
194
+ end
195
+ value
196
+ end
197
+
198
+ def resolve_s3_disable_multiregion_access_points(cfg)
199
+ value = ENV['AWS_S3_DISABLE_MULTIREGION_ACCESS_POINTS'] ||
200
+ Aws.shared_config.s3_disable_multiregion_access_points(profile: cfg.profile) ||
201
+ 'false'
202
+ value = Aws::Util.str_2_bool(value)
203
+ # Raise if provided value is not true or false
133
204
  if value.nil?
134
205
  raise ArgumentError,
135
206
  'Must provide either `true` or `false` for '\
@@ -139,8 +210,7 @@ be made. Set to `false` to use the client's region instead.
139
210
  value
140
211
  end
141
212
 
142
- # Remove ARN from the path since it was substituted already
143
- # This only works because accesspoints care about the URL
213
+ # Remove ARN from the path because we've already set the new host
144
214
  def url_path(path, arn)
145
215
  path = path.sub("/#{Seahorse::Util.uri_escape(arn.to_s)}", '')
146
216
  .sub("/#{arn}", '')
@@ -149,34 +219,31 @@ be made. Set to `false` to use the client's region instead.
149
219
  end
150
220
 
151
221
  def validate_region_config!(arn, region, use_arn_region)
152
- fips = arn.support_fips?
153
-
154
- # s3-external-1 is specific just to s3 and not part of partitions
155
- # aws-global is a partition region
156
- unless arn.partition == 'aws' &&
157
- (region == 's3-external-1' || region == 'aws-global')
158
- if !fips && arn.region.include?('fips')
159
- raise ArgumentError,
160
- 'FIPS region ARNs are not supported for this type of ARN.'
161
- end
162
-
163
- if !fips && !use_arn_region && region.include?('fips')
164
- raise ArgumentError,
165
- 'FIPS client regions are not supported for this type of '\
166
- 'ARN without s3_use_arn_region.'
167
- end
168
-
169
- # if it's a fips region, attempt to normalize it
170
- if fips || use_arn_region
171
- region = region.gsub('fips-', '').gsub('-fips', '')
222
+ if ['s3-external-1', 'aws-global'].include?(region)
223
+ # These "regions" are not regional endpoints
224
+ unless use_arn_region
225
+ raise Aws::Errors::InvalidARNRegionError,
226
+ 'Configured client region is not a regional endpoint.'
172
227
  end
173
- if use_arn_region &&
174
- !Aws::Partitions.partition(arn.partition).region?(region)
228
+ # These "regions" are in the AWS partition
229
+ # Cannot use ARN region unless it's the same partition
230
+ unless arn.partition == 'aws'
175
231
  raise Aws::Errors::InvalidARNPartitionError
176
232
  end
177
-
178
- if !use_arn_region && region != arn.region
179
- raise Aws::Errors::InvalidARNRegionError
233
+ else
234
+ # use_arn_region does not apply to MRAP (global) arns
235
+ unless arn.region.empty?
236
+ # Raise if the ARN and client regions are in different partitions
237
+ if use_arn_region &&
238
+ !Aws::Partitions.partition(arn.partition).region?(region)
239
+ raise Aws::Errors::InvalidARNPartitionError
240
+ end
241
+
242
+ # Raise if regions mismatch
243
+ # Either when it's a fips client or not using the ARN region
244
+ if !use_arn_region && region != arn.region
245
+ raise Aws::Errors::InvalidARNRegionError
246
+ end
180
247
  end
181
248
  end
182
249
  end
@@ -24,7 +24,7 @@ request URI and never moved to the host as a sub-domain.
24
24
  DOCS
25
25
 
26
26
  def add_handlers(handlers, config)
27
- handlers.add(Handler) unless config.force_path_style
27
+ handlers.add(Handler, priority: 48) unless config.force_path_style
28
28
  end
29
29
 
30
30
  # @api private
@@ -5,27 +5,24 @@ module Aws
5
5
  module Plugins
6
6
  # @api private
7
7
  class Dualstack < Seahorse::Client::Plugin
8
-
9
- option(:use_dualstack_endpoint,
10
- default: false,
11
- doc_type: 'Boolean',
12
- docstring: <<-DOCS)
13
- When set to `true`, IPv6-compatible bucket endpoints will be used
14
- for all operations.
15
- DOCS
16
-
17
8
  def add_handlers(handlers, config)
18
9
  handlers.add(OptionHandler, step: :initialize)
19
- handlers.add(DualstackHandler, step: :build, priority: 0)
10
+ handlers.add(DualstackHandler, step: :build, priority: 49)
20
11
  end
21
12
 
22
13
  # @api private
23
14
  class OptionHandler < Seahorse::Client::Handler
24
15
  def call(context)
16
+ # Support client configuration and per-operation configuration
25
17
  if context.params.is_a?(Hash)
26
18
  dualstack = context.params.delete(:use_dualstack_endpoint)
27
19
  end
28
20
  dualstack = context.config.use_dualstack_endpoint if dualstack.nil?
21
+ # Raise if :endpoint and dualstack are both provided
22
+ if dualstack && !context.config.regional_endpoint
23
+ raise ArgumentError,
24
+ 'Cannot use both :use_dualstack_endpoint and :endpoint'
25
+ end
29
26
  context[:use_dualstack_endpoint] = dualstack
30
27
  @handler.call(context)
31
28
  end
@@ -34,37 +31,41 @@ for all operations.
34
31
  # @api private
35
32
  class DualstackHandler < Seahorse::Client::Handler
36
33
  def call(context)
37
- apply_dualstack_endpoint(context) if use_dualstack_endpoint?(context)
34
+ # only rewrite the endpoint if it's not a custom endpoint
35
+ # accelerate/ARN already handle dualstack cases, so ignore these
36
+ # check to see if dualstack is on but configured off via operation
37
+ if context.config.regional_endpoint &&
38
+ use_dualstack_endpoint?(context)
39
+ apply_dualstack_endpoint(context)
40
+ end
38
41
  @handler.call(context)
39
42
  end
40
43
 
41
44
  private
42
- def apply_dualstack_endpoint(context)
43
- bucket_name = context.params[:bucket]
44
- region = context.config.region
45
- context.config.force_path_style
46
- dns_suffix = Aws::Partitions::EndpointProvider.dns_suffix_for(region)
47
45
 
48
- if use_bucket_dns?(bucket_name, context)
49
- host = "#{bucket_name}.s3.dualstack.#{region}.#{dns_suffix}"
50
- else
51
- host = "s3.dualstack.#{region}.#{dns_suffix}"
52
- end
46
+ def apply_dualstack_endpoint(context)
47
+ new_endpoint = Aws::Partitions::EndpointProvider.resolve(
48
+ context.config.region,
49
+ 's3',
50
+ 'regional',
51
+ {
52
+ dualstack: context[:use_dualstack_endpoint],
53
+ fips: context.config.use_fips_endpoint
54
+ }
55
+ )
53
56
  endpoint = URI.parse(context.http_request.endpoint.to_s)
54
- endpoint.scheme = context.http_request.endpoint.scheme
55
- endpoint.port = context.http_request.endpoint.port
56
- endpoint.host = host
57
- context.http_request.endpoint = endpoint.to_s
58
- end
59
-
60
- def use_bucket_dns?(bucket_name, context)
61
- ssl = context.http_request.endpoint.scheme == "https"
62
- bucket_name && BucketDns.dns_compatible?(bucket_name, ssl) &&
63
- !context.config.force_path_style
57
+ endpoint.host = URI.parse(new_endpoint).host
58
+ context.http_request.endpoint = endpoint
64
59
  end
65
60
 
66
61
  def use_dualstack_endpoint?(context)
67
- context[:use_dualstack_endpoint] && !context[:use_accelerate_endpoint]
62
+ # case when dualstack is turned off via operation
63
+ (context[:use_dualstack_endpoint] ||
64
+ context.config.use_dualstack_endpoint) &&
65
+ # accelerate plugin already applies dualstack
66
+ !context[:use_accelerate_endpoint] &&
67
+ # arns handle dualstack
68
+ !context.metadata[:s3_arn]
68
69
  end
69
70
  end
70
71