aws-sdk-s3 1.81.1 → 1.82.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -12,13 +12,12 @@ module Aws
12
12
  # Define a new initialize method that extracts out a bucket ARN.
13
13
  define_method(:initialize) do |*args|
14
14
  old_initialize.bind(self).call(*args)
15
- bucket_name, region, arn = Plugins::BucketARN.resolve_arn!(
15
+ resolved_region, arn = Plugins::ARN.resolve_arn!(
16
16
  name,
17
17
  client.config.region,
18
18
  client.config.s3_use_arn_region
19
19
  )
20
- @name = bucket_name
21
- @client.config.region = region
20
+ @resolved_region = resolved_region
22
21
  @arn = arn
23
22
  end
24
23
 
@@ -102,7 +101,11 @@ module Aws
102
101
  if options[:virtual_host]
103
102
  "http://#{name}"
104
103
  elsif @arn
105
- Plugins::BucketARN.resolve_url!(URI.parse(s3_bucket_url), @arn).to_s
104
+ Plugins::ARN.resolve_url!(
105
+ client.config.endpoint.dup,
106
+ @arn,
107
+ @resolved_region
108
+ ).to_s
106
109
  else
107
110
  s3_bucket_url
108
111
  end
@@ -241,9 +241,9 @@ module Aws::S3
241
241
  # Resource Name (ARN) of the object as accessed through the access
242
242
  # point, in the format
243
243
  # `arn:aws:s3:<Region>:<account-id>:accesspoint/<access-point-name>/object/<key>`.
244
- # For example, to copy the object `reports/january.pdf` through the
245
- # access point `my-access-point` owned by account `123456789012` in
246
- # Region `us-west-2`, use the URL encoding of
244
+ # For example, to copy the object `reports/january.pdf` through access
245
+ # point `my-access-point` owned by account `123456789012` in Region
246
+ # `us-west-2`, use the URL encoding of
247
247
  # `arn:aws:s3:us-west-2:123456789012:accesspoint/my-access-point/object/reports/january.pdf`.
248
248
  # The value must be URL encoded.
249
249
  #
@@ -252,6 +252,15 @@ module Aws::S3
252
252
  #
253
253
  # </note>
254
254
  #
255
+ # Alternatively, for objects accessed through Amazon S3 on Outposts,
256
+ # specify the ARN of the object as accessed in the format
257
+ # `arn:aws:s3-outposts:<Region>:<account-id>:outpost/<outpost-id>/object/<key>`.
258
+ # For example, to copy the object `reports/january.pdf` through
259
+ # outpost `my-outpost` owned by account `123456789012` in Region
260
+ # `us-west-2`, use the URL encoding of
261
+ # `arn:aws:s3-outposts:us-west-2:123456789012:outpost/my-outpost/object/reports/january.pdf`.
262
+ # The value must be URL encoded.
263
+ #
255
264
  # To copy a specific version of an object, append
256
265
  # `?versionId=<version-id>` to the value (for example,
257
266
  # `awsexamplebucket/reports/january.pdf?versionId=QUpfdndhfd8438MNFDN93jdnJFkdmqnh893`).
@@ -530,7 +530,7 @@ module Aws::S3
530
530
  # metadata_directive: "COPY", # accepts COPY, REPLACE
531
531
  # tagging_directive: "COPY", # accepts COPY, REPLACE
532
532
  # server_side_encryption: "AES256", # accepts AES256, aws:kms
533
- # storage_class: "STANDARD", # accepts STANDARD, REDUCED_REDUNDANCY, STANDARD_IA, ONEZONE_IA, INTELLIGENT_TIERING, GLACIER, DEEP_ARCHIVE
533
+ # storage_class: "STANDARD", # accepts STANDARD, REDUCED_REDUNDANCY, STANDARD_IA, ONEZONE_IA, INTELLIGENT_TIERING, GLACIER, DEEP_ARCHIVE, OUTPOSTS
534
534
  # website_redirect_location: "WebsiteRedirectLocation",
535
535
  # sse_customer_algorithm: "SSECustomerAlgorithm",
536
536
  # sse_customer_key: "SSECustomerKey",
@@ -590,6 +590,15 @@ module Aws::S3
590
590
  #
591
591
  # </note>
592
592
  #
593
+ # Alternatively, for objects accessed through Amazon S3 on Outposts,
594
+ # specify the ARN of the object as accessed in the format
595
+ # `arn:aws:s3-outposts:<Region>:<account-id>:outpost/<outpost-id>/object/<key>`.
596
+ # For example, to copy the object `reports/january.pdf` through
597
+ # outpost `my-outpost` owned by account `123456789012` in Region
598
+ # `us-west-2`, use the URL encoding of
599
+ # `arn:aws:s3-outposts:us-west-2:123456789012:outpost/my-outpost/object/reports/january.pdf`.
600
+ # The value must be URL encoded.
601
+ #
593
602
  # To copy a specific version of an object, append
594
603
  # `?versionId=<version-id>` to the value (for example,
595
604
  # `awsexamplebucket/reports/january.pdf?versionId=QUpfdndhfd8438MNFDN93jdnJFkdmqnh893`).
@@ -881,7 +890,7 @@ module Aws::S3
881
890
  # "MetadataKey" => "MetadataValue",
882
891
  # },
883
892
  # server_side_encryption: "AES256", # accepts AES256, aws:kms
884
- # storage_class: "STANDARD", # accepts STANDARD, REDUCED_REDUNDANCY, STANDARD_IA, ONEZONE_IA, INTELLIGENT_TIERING, GLACIER, DEEP_ARCHIVE
893
+ # storage_class: "STANDARD", # accepts STANDARD, REDUCED_REDUNDANCY, STANDARD_IA, ONEZONE_IA, INTELLIGENT_TIERING, GLACIER, DEEP_ARCHIVE, OUTPOSTS
885
894
  # website_redirect_location: "WebsiteRedirectLocation",
886
895
  # sse_customer_algorithm: "SSECustomerAlgorithm",
887
896
  # sse_customer_key: "SSECustomerKey",
@@ -1021,7 +1030,7 @@ module Aws::S3
1021
1030
  # "MetadataKey" => "MetadataValue",
1022
1031
  # },
1023
1032
  # server_side_encryption: "AES256", # accepts AES256, aws:kms
1024
- # storage_class: "STANDARD", # accepts STANDARD, REDUCED_REDUNDANCY, STANDARD_IA, ONEZONE_IA, INTELLIGENT_TIERING, GLACIER, DEEP_ARCHIVE
1033
+ # storage_class: "STANDARD", # accepts STANDARD, REDUCED_REDUNDANCY, STANDARD_IA, ONEZONE_IA, INTELLIGENT_TIERING, GLACIER, DEEP_ARCHIVE, OUTPOSTS
1025
1034
  # website_redirect_location: "WebsiteRedirectLocation",
1026
1035
  # sse_customer_algorithm: "SSECustomerAlgorithm",
1027
1036
  # sse_customer_key: "SSECustomerKey",
@@ -1298,7 +1307,7 @@ module Aws::S3
1298
1307
  # value: "MetadataValue",
1299
1308
  # },
1300
1309
  # ],
1301
- # storage_class: "STANDARD", # accepts STANDARD, REDUCED_REDUNDANCY, STANDARD_IA, ONEZONE_IA, INTELLIGENT_TIERING, GLACIER, DEEP_ARCHIVE
1310
+ # storage_class: "STANDARD", # accepts STANDARD, REDUCED_REDUNDANCY, STANDARD_IA, ONEZONE_IA, INTELLIGENT_TIERING, GLACIER, DEEP_ARCHIVE, OUTPOSTS
1302
1311
  # },
1303
1312
  # },
1304
1313
  # },
@@ -295,7 +295,7 @@ module Aws::S3
295
295
  # metadata_directive: "COPY", # accepts COPY, REPLACE
296
296
  # tagging_directive: "COPY", # accepts COPY, REPLACE
297
297
  # server_side_encryption: "AES256", # accepts AES256, aws:kms
298
- # storage_class: "STANDARD", # accepts STANDARD, REDUCED_REDUNDANCY, STANDARD_IA, ONEZONE_IA, INTELLIGENT_TIERING, GLACIER, DEEP_ARCHIVE
298
+ # storage_class: "STANDARD", # accepts STANDARD, REDUCED_REDUNDANCY, STANDARD_IA, ONEZONE_IA, INTELLIGENT_TIERING, GLACIER, DEEP_ARCHIVE, OUTPOSTS
299
299
  # website_redirect_location: "WebsiteRedirectLocation",
300
300
  # sse_customer_algorithm: "SSECustomerAlgorithm",
301
301
  # sse_customer_key: "SSECustomerKey",
@@ -355,6 +355,15 @@ module Aws::S3
355
355
  #
356
356
  # </note>
357
357
  #
358
+ # Alternatively, for objects accessed through Amazon S3 on Outposts,
359
+ # specify the ARN of the object as accessed in the format
360
+ # `arn:aws:s3-outposts:<Region>:<account-id>:outpost/<outpost-id>/object/<key>`.
361
+ # For example, to copy the object `reports/january.pdf` through
362
+ # outpost `my-outpost` owned by account `123456789012` in Region
363
+ # `us-west-2`, use the URL encoding of
364
+ # `arn:aws:s3-outposts:us-west-2:123456789012:outpost/my-outpost/object/reports/january.pdf`.
365
+ # The value must be URL encoded.
366
+ #
358
367
  # To copy a specific version of an object, append
359
368
  # `?versionId=<version-id>` to the value (for example,
360
369
  # `awsexamplebucket/reports/january.pdf?versionId=QUpfdndhfd8438MNFDN93jdnJFkdmqnh893`).
@@ -646,7 +655,7 @@ module Aws::S3
646
655
  # "MetadataKey" => "MetadataValue",
647
656
  # },
648
657
  # server_side_encryption: "AES256", # accepts AES256, aws:kms
649
- # storage_class: "STANDARD", # accepts STANDARD, REDUCED_REDUNDANCY, STANDARD_IA, ONEZONE_IA, INTELLIGENT_TIERING, GLACIER, DEEP_ARCHIVE
658
+ # storage_class: "STANDARD", # accepts STANDARD, REDUCED_REDUNDANCY, STANDARD_IA, ONEZONE_IA, INTELLIGENT_TIERING, GLACIER, DEEP_ARCHIVE, OUTPOSTS
650
659
  # website_redirect_location: "WebsiteRedirectLocation",
651
660
  # sse_customer_algorithm: "SSECustomerAlgorithm",
652
661
  # sse_customer_key: "SSECustomerKey",
@@ -786,7 +795,7 @@ module Aws::S3
786
795
  # "MetadataKey" => "MetadataValue",
787
796
  # },
788
797
  # server_side_encryption: "AES256", # accepts AES256, aws:kms
789
- # storage_class: "STANDARD", # accepts STANDARD, REDUCED_REDUNDANCY, STANDARD_IA, ONEZONE_IA, INTELLIGENT_TIERING, GLACIER, DEEP_ARCHIVE
798
+ # storage_class: "STANDARD", # accepts STANDARD, REDUCED_REDUNDANCY, STANDARD_IA, ONEZONE_IA, INTELLIGENT_TIERING, GLACIER, DEEP_ARCHIVE, OUTPOSTS
790
799
  # website_redirect_location: "WebsiteRedirectLocation",
791
800
  # sse_customer_algorithm: "SSECustomerAlgorithm",
792
801
  # sse_customer_key: "SSECustomerKey",
@@ -1063,7 +1072,7 @@ module Aws::S3
1063
1072
  # value: "MetadataValue",
1064
1073
  # },
1065
1074
  # ],
1066
- # storage_class: "STANDARD", # accepts STANDARD, REDUCED_REDUNDANCY, STANDARD_IA, ONEZONE_IA, INTELLIGENT_TIERING, GLACIER, DEEP_ARCHIVE
1075
+ # storage_class: "STANDARD", # accepts STANDARD, REDUCED_REDUNDANCY, STANDARD_IA, ONEZONE_IA, INTELLIGENT_TIERING, GLACIER, DEEP_ARCHIVE, OUTPOSTS
1067
1076
  # },
1068
1077
  # },
1069
1078
  # },
@@ -0,0 +1,187 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../arn/access_point_arn'
4
+ require_relative '../arn/outpost_access_point_arn'
5
+
6
+ module Aws
7
+ module S3
8
+ module Plugins
9
+ # When an accesspoint ARN is provided for :bucket in S3 operations, this
10
+ # plugin resolves the request endpoint from the ARN when possible.
11
+ # @api private
12
+ class ARN < Seahorse::Client::Plugin
13
+ option(
14
+ :s3_use_arn_region,
15
+ default: true,
16
+ doc_type: 'Boolean',
17
+ docstring: <<-DOCS) do |cfg|
18
+ For S3 ARNs passed into the `:bucket` parameter, this option will
19
+ use the region in the ARN, allowing for cross-region requests to
20
+ be made. Set to `false` to use the client's region instead.
21
+ DOCS
22
+ resolve_s3_use_arn_region(cfg)
23
+ end
24
+
25
+ def add_handlers(handlers, _config)
26
+ handlers.add(Handler)
27
+ end
28
+
29
+ class Handler < Seahorse::Client::Handler
30
+ def call(context)
31
+ bucket_member = _bucket_member(context.operation.input.shape)
32
+ if bucket_member && (bucket = context.params[bucket_member])
33
+ resolved_region, arn = ARN.resolve_arn!(
34
+ bucket,
35
+ context.config.region,
36
+ context.config.s3_use_arn_region
37
+ )
38
+ if arn
39
+ validate_config!(context, arn)
40
+
41
+ ARN.resolve_url!(
42
+ context.http_request.endpoint,
43
+ arn,
44
+ resolved_region,
45
+ extract_dualstack_config!(context)
46
+ )
47
+ end
48
+ end
49
+ @handler.call(context)
50
+ end
51
+
52
+ private
53
+
54
+ def _bucket_member(input)
55
+ input.members.each do |member, ref|
56
+ return member if ref.shape.name == 'BucketName'
57
+ end
58
+ nil
59
+ end
60
+
61
+ # other plugins use dualstack so disable it when we're done
62
+ def extract_dualstack_config!(context)
63
+ dualstack = context[:use_dualstack_endpoint]
64
+ context[:use_dualstack_endpoint] = false if dualstack
65
+ dualstack
66
+ end
67
+
68
+ 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
+ if context.config.force_path_style
76
+ raise ArgumentError,
77
+ 'Cannot provide both an Access Point ARN and setting '\
78
+ ':force_path_style to true.'
79
+ end
80
+
81
+ if context.config.use_accelerate_endpoint
82
+ raise ArgumentError,
83
+ 'Cannot provide both an Access Point ARN and setting '\
84
+ ':use_accelerate_endpoint to true.'
85
+ end
86
+
87
+ if !arn.support_dualstack? && context[:use_dualstack_endpoint]
88
+ raise ArgumentError,
89
+ 'Cannot provide both an Outpost Access Point ARN and '\
90
+ 'setting :use_dualstack_endpoint to true.'
91
+ end
92
+ end
93
+ end
94
+
95
+ class << self
96
+ # @api private
97
+ def resolve_arn!(member_value, region, use_arn_region)
98
+ if Aws::ARNParser.arn?(member_value)
99
+ 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
109
+ s3_arn.validate_arn!
110
+ validate_region_config!(s3_arn, region, use_arn_region)
111
+ region = s3_arn.region if use_arn_region
112
+ [region, s3_arn]
113
+ else
114
+ [region]
115
+ end
116
+ end
117
+
118
+ # @api private
119
+ def resolve_url!(url, arn, region, dualstack = false)
120
+ url.host = arn.host_url(region, dualstack)
121
+ url.path = url_path(url.path, arn)
122
+ url
123
+ end
124
+
125
+ private
126
+
127
+ def resolve_s3_use_arn_region(cfg)
128
+ value = ENV['AWS_S3_USE_ARN_REGION'] ||
129
+ Aws.shared_config.s3_use_arn_region(profile: cfg.profile) ||
130
+ 'true'
131
+ value = Aws::Util.str_2_bool(value)
132
+ # Raise if provided value is not true or false
133
+ if value.nil?
134
+ raise ArgumentError,
135
+ 'Must provide either `true` or `false` for '\
136
+ 's3_use_arn_region profile option or for '\
137
+ "ENV['AWS_S3_USE_ARN_REGION']"
138
+ end
139
+ value
140
+ end
141
+
142
+ # Remove ARN from the path since it was substituted already
143
+ # This only works because accesspoints care about the URL
144
+ def url_path(path, arn)
145
+ path = path.sub("/#{Seahorse::Util.uri_escape(arn.to_s)}", '')
146
+ .sub("/#{arn}", '')
147
+ "/#{path}" unless path =~ /^\//
148
+ path
149
+ end
150
+
151
+ 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', '')
172
+ end
173
+ if use_arn_region &&
174
+ !Aws::Partitions.partition(arn.partition).region?(region)
175
+ raise Aws::Errors::InvalidARNPartitionError
176
+ end
177
+
178
+ if !use_arn_region && region != arn.region
179
+ raise Aws::Errors::InvalidARNRegionError
180
+ end
181
+ end
182
+ end
183
+ end
184
+ end
185
+ end
186
+ end
187
+ end
@@ -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
@@ -12,12 +12,14 @@ module Aws
12
12
 
13
13
  option(:sigv4_signer) do |cfg|
14
14
  S3Signer.build_v4_signer(
15
+ service: 's3',
15
16
  region: cfg.sigv4_region,
16
17
  credentials: cfg.credentials
17
18
  )
18
19
  end
19
20
 
20
21
  option(:sigv4_region) do |cfg|
22
+ # S3 removes core's signature_v4 plugin that checks for this
21
23
  raise Aws::Errors::MissingRegionError if cfg.region.nil?
22
24
 
23
25
  Aws::Partitions::EndpointProvider.signing_region(cfg.region, 's3')
@@ -67,11 +69,26 @@ module Aws
67
69
  if context[:cached_sigv4_region] &&
68
70
  context[:cached_sigv4_region] != context.config.sigv4_signer.region
69
71
  S3Signer.build_v4_signer(
72
+ service: 's3',
70
73
  region: context[:cached_sigv4_region],
71
74
  credentials: context.config.credentials
72
75
  )
73
76
  else
74
- context.config.sigv4_signer
77
+ resolved_region, arn = ARN.resolve_arn!(
78
+ context.params[:bucket],
79
+ context.config.sigv4_signer.region,
80
+ context.config.s3_use_arn_region
81
+ )
82
+
83
+ if arn
84
+ S3Signer.build_v4_signer(
85
+ service: arn.respond_to?(:outpost_id) ? 's3-outposts' : 's3',
86
+ region: resolved_region,
87
+ credentials: context.config.credentials
88
+ )
89
+ else
90
+ context.config.sigv4_signer
91
+ end
75
92
  end
76
93
  end
77
94
  end
@@ -90,7 +107,9 @@ module Aws
90
107
  def check_for_cached_region(context, bucket)
91
108
  cached_region = S3::BUCKET_REGIONS[bucket]
92
109
  if cached_region && cached_region != context.config.region
93
- context.http_request.endpoint.host = S3Signer.new_hostname(context, cached_region)
110
+ context.http_request.endpoint.host = S3Signer.new_hostname(
111
+ context, cached_region
112
+ )
94
113
  context[:cached_sigv4_region] = cached_region
95
114
  end
96
115
  end
@@ -150,11 +169,14 @@ module Aws
150
169
 
151
170
  def resign_with_new_region(context, actual_region)
152
171
  context.http_response.body.truncate(0)
153
- context.http_request.endpoint.host = S3Signer.new_hostname(context, actual_region)
172
+ context.http_request.endpoint.host = S3Signer.new_hostname(
173
+ context, actual_region
174
+ )
154
175
  context.metadata[:redirect_region] = actual_region
155
176
  Aws::Plugins::SignatureV4.apply_signature(
156
177
  context: context,
157
178
  signer: S3Signer.build_v4_signer(
179
+ service: 's3',
158
180
  region: actual_region,
159
181
  credentials: context.config.credentials
160
182
  )
@@ -189,7 +211,7 @@ module Aws
189
211
  # @api private
190
212
  def build_v4_signer(options = {})
191
213
  Aws::Sigv4::Signer.new(
192
- service: 's3',
214
+ service: options[:service],
193
215
  region: options[:region],
194
216
  credentials_provider: options[:credentials],
195
217
  uri_escape_path: false,
@@ -200,7 +222,7 @@ module Aws
200
222
  def new_hostname(context, region)
201
223
  # Check to see if the bucket is actually an ARN and resolve it
202
224
  # Otherwise it will retry with the ARN as the bucket name.
203
- resolved_bucket, resolved_region, arn = BucketARN.resolve_arn!(
225
+ resolved_region, arn = ARN.resolve_arn!(
204
226
  context.params[:bucket],
205
227
  region,
206
228
  context.config.s3_use_arn_region
@@ -210,9 +232,9 @@ module Aws
210
232
  )
211
233
 
212
234
  if arn
213
- BucketARN.resolve_url!(uri, arn).host
235
+ ARN.resolve_url!(uri, arn).host
214
236
  else
215
- resolved_bucket + '.' + uri.host
237
+ "#{context.params[:bucket]}.#{uri.host}"
216
238
  end
217
239
  end
218
240
  end