aws-sdk-s3 1.81.1 → 1.114.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  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 +172 -46
  10. data/lib/aws-sdk-s3/bucket_acl.rb +28 -6
  11. data/lib/aws-sdk-s3/bucket_cors.rb +29 -9
  12. data/lib/aws-sdk-s3/bucket_lifecycle.rb +30 -9
  13. data/lib/aws-sdk-s3/bucket_lifecycle_configuration.rb +31 -9
  14. data/lib/aws-sdk-s3/bucket_logging.rb +25 -6
  15. data/lib/aws-sdk-s3/bucket_notification.rb +21 -9
  16. data/lib/aws-sdk-s3/bucket_policy.rb +27 -7
  17. data/lib/aws-sdk-s3/bucket_request_payment.rb +27 -8
  18. data/lib/aws-sdk-s3/bucket_tagging.rb +27 -7
  19. data/lib/aws-sdk-s3/bucket_versioning.rb +70 -10
  20. data/lib/aws-sdk-s3/bucket_website.rb +27 -7
  21. data/lib/aws-sdk-s3/client.rb +4415 -1650
  22. data/lib/aws-sdk-s3/client_api.rb +661 -41
  23. data/lib/aws-sdk-s3/customizations/bucket.rb +15 -7
  24. data/lib/aws-sdk-s3/customizations/object.rb +120 -21
  25. data/lib/aws-sdk-s3/customizations.rb +1 -1
  26. data/lib/aws-sdk-s3/encryption/client.rb +1 -1
  27. data/lib/aws-sdk-s3/encryption/decrypt_handler.rb +0 -4
  28. data/lib/aws-sdk-s3/encryptionV2/client.rb +1 -1
  29. data/lib/aws-sdk-s3/encryptionV2/decrypt_handler.rb +0 -4
  30. data/lib/aws-sdk-s3/encryptionV2/default_cipher_provider.rb +3 -3
  31. data/lib/aws-sdk-s3/encryptionV2/encrypt_handler.rb +0 -4
  32. data/lib/aws-sdk-s3/errors.rb +22 -1
  33. data/lib/aws-sdk-s3/event_streams.rb +1 -1
  34. data/lib/aws-sdk-s3/file_downloader.rb +7 -2
  35. data/lib/aws-sdk-s3/file_uploader.rb +9 -4
  36. data/lib/aws-sdk-s3/legacy_signer.rb +15 -25
  37. data/lib/aws-sdk-s3/multipart_file_uploader.rb +26 -7
  38. data/lib/aws-sdk-s3/multipart_upload.rb +133 -19
  39. data/lib/aws-sdk-s3/multipart_upload_part.rb +152 -23
  40. data/lib/aws-sdk-s3/object.rb +501 -126
  41. data/lib/aws-sdk-s3/object_acl.rb +39 -9
  42. data/lib/aws-sdk-s3/object_summary.rb +330 -110
  43. data/lib/aws-sdk-s3/object_version.rb +80 -49
  44. data/lib/aws-sdk-s3/plugins/accelerate.rb +13 -4
  45. data/lib/aws-sdk-s3/plugins/arn.rb +254 -0
  46. data/lib/aws-sdk-s3/plugins/bucket_dns.rb +1 -3
  47. data/lib/aws-sdk-s3/plugins/bucket_name_restrictions.rb +1 -1
  48. data/lib/aws-sdk-s3/plugins/dualstack.rb +33 -32
  49. data/lib/aws-sdk-s3/plugins/expect_100_continue.rb +2 -1
  50. data/lib/aws-sdk-s3/plugins/get_bucket_location_fix.rb +1 -1
  51. data/lib/aws-sdk-s3/plugins/iad_regional_endpoint.rb +18 -7
  52. data/lib/aws-sdk-s3/plugins/md5s.rb +5 -3
  53. data/lib/aws-sdk-s3/plugins/object_lambda_endpoint.rb +25 -0
  54. data/lib/aws-sdk-s3/plugins/s3_signer.rb +66 -17
  55. data/lib/aws-sdk-s3/plugins/skip_whole_multipart_get_checksums.rb +31 -0
  56. data/lib/aws-sdk-s3/plugins/streaming_retry.rb +23 -2
  57. data/lib/aws-sdk-s3/presigned_post.rb +38 -19
  58. data/lib/aws-sdk-s3/presigner.rb +33 -17
  59. data/lib/aws-sdk-s3/resource.rb +23 -3
  60. data/lib/aws-sdk-s3/types.rb +4792 -1089
  61. data/lib/aws-sdk-s3/waiters.rb +1 -1
  62. data/lib/aws-sdk-s3.rb +2 -2
  63. metadata +21 -13
  64. data/lib/aws-sdk-s3/plugins/bucket_arn.rb +0 -212
@@ -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,29 +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]().
407
- #
408
- # <note markdown="1"> Amazon S3 doesn't support retrieving multiple ranges of data per
409
- # `GET` request.
410
- #
411
- # </note>
415
+ # Because `HeadObject` returns only the metadata for an object, this
416
+ # parameter has no effect.
412
417
  # @option options [String] :sse_customer_algorithm
413
418
  # Specifies the algorithm to use to when encrypting the object (for
414
419
  # example, AES256).
@@ -425,9 +430,9 @@ module Aws::S3
425
430
  # @option options [String] :request_payer
426
431
  # Confirms that the requester knows that they will be charged for the
427
432
  # request. Bucket owners need not specify this parameter in their
428
- # requests. For information about downloading objects from requester
429
- # pays buckets, see [Downloading Objects in Requestor Pays Buckets][1]
430
- # 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*.
431
436
  #
432
437
  #
433
438
  #
@@ -438,9 +443,16 @@ module Aws::S3
438
443
  # for the part specified. Useful querying about the size of the part and
439
444
  # the number of parts in this object.
440
445
  # @option options [String] :expected_bucket_owner
441
- # The account id of the expected bucket owner. If the bucket is owned by
442
- # a different account, the request will fail with an HTTP `403 (Access
443
- # 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.
444
456
  # @return [Types::HeadObjectOutput]
445
457
  def head(options = {})
446
458
  options = options.merge(
@@ -520,6 +532,7 @@ module Aws::S3
520
532
  # request_payer: "requester", # accepts requester
521
533
  # bypass_governance_retention: false,
522
534
  # expected_bucket_owner: "AccountId",
535
+ # checksum_algorithm: "CRC32", # accepts CRC32, CRC32C, SHA1, SHA256
523
536
  # })
524
537
  # @param options ({})
525
538
  # @option options [String] :mfa
@@ -530,21 +543,39 @@ module Aws::S3
530
543
  # @option options [String] :request_payer
531
544
  # Confirms that the requester knows that they will be charged for the
532
545
  # request. Bucket owners need not specify this parameter in their
533
- # requests. For information about downloading objects from requester
534
- # pays buckets, see [Downloading Objects in Requestor Pays Buckets][1]
535
- # 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*.
536
549
  #
537
550
  #
538
551
  #
539
552
  # [1]: https://docs.aws.amazon.com/AmazonS3/latest/dev/ObjectsinRequesterPaysBuckets.html
540
553
  # @option options [Boolean] :bypass_governance_retention
541
554
  # Specifies whether you want to delete this object even if it has a
542
- # Governance-type Object Lock in place. You must have sufficient
543
- # permissions to perform this operation.
555
+ # Governance-type Object Lock in place. To use this header, you must
556
+ # have the `s3:BypassGovernanceRetention` permission.
544
557
  # @option options [String] :expected_bucket_owner
545
- # The account id of the expected bucket owner. If the bucket is owned by
546
- # a different account, the request will fail with an HTTP `403 (Access
547
- # 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
548
579
  # @return [void]
549
580
  def batch_delete!(options = {})
550
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
@@ -0,0 +1,254 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../arn/access_point_arn'
4
+ require_relative '../arn/object_lambda_arn'
5
+ require_relative '../arn/outpost_access_point_arn'
6
+ require_relative '../arn/multi_region_access_point_arn'
7
+
8
+ module Aws
9
+ module S3
10
+ module Plugins
11
+ # When an accesspoint ARN is provided for :bucket in S3 operations, this
12
+ # plugin resolves the request endpoint from the ARN when possible.
13
+ # @api private
14
+ class ARN < Seahorse::Client::Plugin
15
+ option(
16
+ :s3_use_arn_region,
17
+ default: true,
18
+ doc_type: 'Boolean',
19
+ docstring: <<-DOCS) do |cfg|
20
+ For S3 ARNs passed into the `:bucket` parameter, this option will
21
+ use the region in the ARN, allowing for cross-region requests to
22
+ be made. Set to `false` to use the client's region instead.
23
+ DOCS
24
+ resolve_s3_use_arn_region(cfg)
25
+ end
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
42
+ def add_handlers(handlers, _config)
43
+ handlers.add(ARNHandler, step: :validate, priority: 75)
44
+ handlers.add(UrlHandler)
45
+ end
46
+
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
69
+ def call(context)
70
+ bucket_member = _bucket_member(context.operation.input.shape)
71
+ if bucket_member && (bucket = context.params[bucket_member])
72
+ resolved_region, arn = ARN.resolve_arn!(
73
+ bucket,
74
+ context.config.region,
75
+ context.config.s3_use_arn_region
76
+ )
77
+ if arn
78
+ validate_config!(context, arn)
79
+
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
+ }
86
+ end
87
+ end
88
+ @handler.call(context)
89
+ end
90
+
91
+ private
92
+
93
+ def _bucket_member(input)
94
+ input.members.each do |member, ref|
95
+ return member if ref.shape.name == 'BucketName'
96
+ end
97
+ nil
98
+ end
99
+
100
+ # other plugins use dualstack so disable it when we're done
101
+ def extract_dualstack_config!(context)
102
+ dualstack = context[:use_dualstack_endpoint]
103
+ context[:use_dualstack_endpoint] = false if dualstack
104
+ dualstack
105
+ end
106
+
107
+ def validate_config!(context, arn)
108
+ if context.config.force_path_style
109
+ raise ArgumentError,
110
+ 'Cannot provide an Access Point ARN when '\
111
+ '`:force_path_style` is set to true.'
112
+ end
113
+
114
+ if context.config.use_accelerate_endpoint
115
+ raise ArgumentError,
116
+ 'Cannot provide an Access Point ARN when '\
117
+ '`:use_accelerate_endpoint` is set to true.'
118
+ end
119
+
120
+ if !arn.support_dualstack? && context[:use_dualstack_endpoint]
121
+ raise ArgumentError,
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.'
137
+ end
138
+ end
139
+ end
140
+
141
+ class << self
142
+ # @api private
143
+ def resolve_arn!(member_value, region, use_arn_region)
144
+ if Aws::ARNParser.arn?(member_value)
145
+ arn = Aws::ARNParser.parse(member_value)
146
+ s3_arn = resolve_arn_type!(arn)
147
+ s3_arn.validate_arn!
148
+ validate_region_config!(s3_arn, region, use_arn_region)
149
+ region = s3_arn.region if use_arn_region
150
+ [region, s3_arn]
151
+ else
152
+ [region]
153
+ end
154
+ end
155
+
156
+ # @api private
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)
160
+ url.path = url_path(url.path, arn)
161
+ url
162
+ end
163
+
164
+ private
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
+
183
+ def resolve_s3_use_arn_region(cfg)
184
+ value = ENV['AWS_S3_USE_ARN_REGION'] ||
185
+ Aws.shared_config.s3_use_arn_region(profile: cfg.profile) ||
186
+ 'true'
187
+ value = Aws::Util.str_2_bool(value)
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
204
+ if value.nil?
205
+ raise ArgumentError,
206
+ 'Must provide either `true` or `false` for '\
207
+ 's3_use_arn_region profile option or for '\
208
+ "ENV['AWS_S3_USE_ARN_REGION']"
209
+ end
210
+ value
211
+ end
212
+
213
+ # Remove ARN from the path because we've already set the new host
214
+ def url_path(path, arn)
215
+ path = path.sub("/#{Seahorse::Util.uri_escape(arn.to_s)}", '')
216
+ .sub("/#{arn}", '')
217
+ "/#{path}" unless path =~ /^\//
218
+ path
219
+ end
220
+
221
+ def validate_region_config!(arn, region, use_arn_region)
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.'
227
+ end
228
+ # These "regions" are in the AWS partition
229
+ # Cannot use ARN region unless it's the same partition
230
+ unless arn.partition == 'aws'
231
+ raise Aws::Errors::InvalidARNPartitionError
232
+ end
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
247
+ end
248
+ end
249
+ end
250
+ end
251
+ end
252
+ end
253
+ end
254
+ 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
@@ -73,8 +73,6 @@ request URI and never moved to the host as a sub-domain.
73
73
  end
74
74
  end
75
75
 
76
- # Checks for a valid RFC-3986 host name
77
- # @see https://tools.ietf.org/html/rfc3986#section-3.2.2
78
76
  # @param [String] bucket_name
79
77
  # @return [Boolean]
80
78
  def valid_subdomain?(bucket_name)
@@ -13,7 +13,7 @@ module Aws
13
13
  def call(context)
14
14
  bucket_member = _bucket_member(context.operation.input.shape)
15
15
  if bucket_member && (bucket = context.params[bucket_member])
16
- _resolved_bucket, _resolved_region, arn = BucketARN.resolve_arn!(
16
+ _resolved_region, arn = ARN.resolve_arn!(
17
17
  bucket,
18
18
  context.config.region,
19
19
  context.config.s3_use_arn_region
@@ -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