aws-sdk-s3 1.80.0 → 1.114.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 (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 +34 -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 +3 -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