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
@@ -15,7 +15,8 @@ module Aws
15
15
  class Handler < Seahorse::Client::Handler
16
16
 
17
17
  def call(context)
18
- if context.http_request.body && context.http_request.body.size > 0
18
+ body = context.http_request.body
19
+ if body.respond_to?(:size) && body.size > 0
19
20
  context.http_request.headers['expect'] = '100-continue'
20
21
  end
21
22
  @handler.call(context)
@@ -11,7 +11,7 @@ module Aws
11
11
  @handler.call(context).on(200) do |response|
12
12
  response.data = S3::Types::GetBucketLocationOutput.new
13
13
  xml = context.http_response.body_contents
14
- matches = xml.match(/>(.+?)<\/LocationConstraint>/)
14
+ matches = xml.match(/<LocationConstraint.*?>(.+?)<\/LocationConstraint>/)
15
15
  response.data[:location_constraint] = matches ? matches[1] : ''
16
16
  end
17
17
  end
@@ -10,14 +10,15 @@ module Aws
10
10
  default: 'legacy',
11
11
  doc_type: String,
12
12
  docstring: <<-DOCS) do |cfg|
13
- Passing in `regional` to enable regional endpoint for S3's `us-east-1`
14
- region. Defaults to `legacy` mode using global endpoint.
13
+ Pass in `regional` to enable the `us-east-1` regional endpoint.
14
+ Defaults to `legacy` mode which uses the global endpoint.
15
15
  DOCS
16
16
  resolve_iad_regional_endpoint(cfg)
17
17
  end
18
18
 
19
19
  def add_handlers(handlers, config)
20
- if config.region == 'us-east-1'
20
+ # only modify non-custom endpoints
21
+ if config.regional_endpoint && config.region == 'us-east-1'
21
22
  handlers.add(Handler)
22
23
  end
23
24
  end
@@ -26,10 +27,14 @@ region. Defaults to `legacy` mode using global endpoint.
26
27
  class Handler < Seahorse::Client::Handler
27
28
 
28
29
  def call(context)
29
- # keep legacy global endpoint pattern by default
30
- if context.config.s3_us_east_1_regional_endpoint == 'legacy'
31
- context.http_request.endpoint.host = IADRegionalEndpoint.legacy_host(
32
- context.http_request.endpoint.host)
30
+ # WriteGetObjectResponse does not have a global endpoint
31
+ # ARNs are regionalized, so don't touch those either.
32
+ if context.operation.name != 'WriteGetObjectResponse' &&
33
+ context.config.s3_us_east_1_regional_endpoint == 'legacy' &&
34
+ !context.metadata[:s3_arn]
35
+ host = context.http_request.endpoint.host
36
+ legacy_host = IADRegionalEndpoint.legacy_host(host)
37
+ context.http_request.endpoint.host = legacy_host
33
38
  end
34
39
  @handler.call(context)
35
40
  end
@@ -43,8 +48,14 @@ region. Defaults to `legacy` mode using global endpoint.
43
48
  private
44
49
 
45
50
  def self.resolve_iad_regional_endpoint(cfg)
51
+ default_mode_value =
52
+ if cfg.respond_to?(:defaults_mode_config_resolver)
53
+ cfg.defaults_mode_config_resolver.resolve(:s3_us_east_1_regional_endpoint)
54
+ end
55
+
46
56
  mode = ENV['AWS_S3_US_EAST_1_REGIONAL_ENDPOINT'] ||
47
57
  Aws.shared_config.s3_us_east_1_regional_endpoint(profile: cfg.profile) ||
58
+ default_mode_value ||
48
59
  'legacy'
49
60
  mode = mode.downcase
50
61
  unless %w(legacy regional).include?(mode)
@@ -22,9 +22,11 @@ module Aws
22
22
  CHUNK_SIZE = 1 * 1024 * 1024 # one MB
23
23
 
24
24
  def call(context)
25
- body = context.http_request.body
26
- if body.size > 0
27
- context.http_request.headers['Content-Md5'] ||= md5(body)
25
+ if !context[:checksum_algorithms] # skip in favor of flexible checksum
26
+ body = context.http_request.body
27
+ if body.respond_to?(:size) && body.size > 0
28
+ context.http_request.headers['Content-Md5'] ||= md5(body)
29
+ end
28
30
  end
29
31
  @handler.call(context)
30
32
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module S3
5
+ module Plugins
6
+ # WriteGetObjectResponse is called from Lambda after a data transform.
7
+ # If there is no custom endpoint, we change the endpoint from s3 to
8
+ # s3-object-lambda just for this operation.
9
+ class ObjectLambdaEndpoint < Seahorse::Client::Plugin
10
+ class Handler < Seahorse::Client::Handler
11
+ def call(context)
12
+ if context.config.regional_endpoint
13
+ host = context.http_request.endpoint.host
14
+ host = host.sub('s3.', 's3-object-lambda.')
15
+ context.http_request.endpoint.host = host
16
+ end
17
+ @handler.call(context)
18
+ end
19
+ end
20
+
21
+ handler(Handler, operations: [:write_get_object_response])
22
+ end
23
+ end
24
+ end
25
+ end
@@ -12,15 +12,19 @@ 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
- Aws::Partitions::EndpointProvider.signing_region(cfg.region, 's3')
25
+ Aws::Partitions::EndpointProvider.signing_region(
26
+ cfg.region, 's3'
27
+ )
24
28
  end
25
29
 
26
30
  def add_handlers(handlers, cfg)
@@ -67,9 +71,30 @@ module Aws
67
71
  if context[:cached_sigv4_region] &&
68
72
  context[:cached_sigv4_region] != context.config.sigv4_signer.region
69
73
  S3Signer.build_v4_signer(
74
+ service: 's3',
70
75
  region: context[:cached_sigv4_region],
71
76
  credentials: context.config.credentials
72
77
  )
78
+ elsif (arn = context.metadata[:s3_arn])
79
+ if arn[:arn].is_a?(MultiRegionAccessPointARN)
80
+ signing_region = '*'
81
+ signing_algorithm = :sigv4a
82
+ else
83
+ signing_region = arn[:resolved_region]
84
+ signing_algorithm = :sigv4
85
+ end
86
+ S3Signer.build_v4_signer(
87
+ service: arn[:arn].service,
88
+ signing_algorithm: signing_algorithm,
89
+ region: signing_region,
90
+ credentials: context.config.credentials
91
+ )
92
+ elsif context.operation.name == 'WriteGetObjectResponse'
93
+ S3Signer.build_v4_signer(
94
+ service: 's3-object-lambda',
95
+ region: context.config.sigv4_region,
96
+ credentials: context.config.credentials
97
+ )
73
98
  else
74
99
  context.config.sigv4_signer
75
100
  end
@@ -90,7 +115,9 @@ module Aws
90
115
  def check_for_cached_region(context, bucket)
91
116
  cached_region = S3::BUCKET_REGIONS[bucket]
92
117
  if cached_region && cached_region != context.config.region
93
- context.http_request.endpoint.host = S3Signer.new_hostname(context, cached_region)
118
+ context.http_request.endpoint.host = S3Signer.new_hostname(
119
+ context, cached_region
120
+ )
94
121
  context[:cached_sigv4_region] = cached_region
95
122
  end
96
123
  end
@@ -111,7 +138,8 @@ module Aws
111
138
  def handle_region_errors(response)
112
139
  if wrong_sigv4_region?(response) &&
113
140
  !fips_region?(response) &&
114
- !custom_endpoint?(response)
141
+ !custom_endpoint?(response) &&
142
+ !expired_credentials?(response)
115
143
  get_region_and_retry(response.context)
116
144
  else
117
145
  response
@@ -135,9 +163,18 @@ module Aws
135
163
  resp.context.http_request.endpoint.host.include?('fips')
136
164
  end
137
165
 
166
+ def expired_credentials?(resp)
167
+ resp.context.http_response.body_contents.match(/<Code>ExpiredToken<\/Code>/)
168
+ end
169
+
138
170
  def custom_endpoint?(resp)
139
171
  resolved_suffix = Aws::Partitions::EndpointProvider.dns_suffix_for(
140
- resp.context.config.region
172
+ resp.context.config.region,
173
+ 's3',
174
+ {
175
+ dualstack: resp.context[:use_dualstack_endpoint],
176
+ fips: resp.context.config.use_fips_endpoint
177
+ }
141
178
  )
142
179
  !resp.context.http_request.endpoint.hostname.include?(resolved_suffix)
143
180
  end
@@ -150,11 +187,18 @@ module Aws
150
187
 
151
188
  def resign_with_new_region(context, actual_region)
152
189
  context.http_response.body.truncate(0)
153
- context.http_request.endpoint.host = S3Signer.new_hostname(context, actual_region)
190
+ context.http_request.endpoint.host = S3Signer.new_hostname(
191
+ context, actual_region
192
+ )
154
193
  context.metadata[:redirect_region] = actual_region
194
+ # if it's an ARN, use the service in the ARN
195
+ if (arn = context.metadata[:s3_arn])
196
+ service = arn[:arn].service
197
+ end
155
198
  Aws::Plugins::SignatureV4.apply_signature(
156
199
  context: context,
157
200
  signer: S3Signer.build_v4_signer(
201
+ service: service || 's3',
158
202
  region: actual_region,
159
203
  credentials: context.config.credentials
160
204
  )
@@ -189,30 +233,35 @@ module Aws
189
233
  # @api private
190
234
  def build_v4_signer(options = {})
191
235
  Aws::Sigv4::Signer.new(
192
- service: 's3',
236
+ service: options[:service],
193
237
  region: options[:region],
194
238
  credentials_provider: options[:credentials],
239
+ signing_algorithm: options.fetch(:signing_algorithm, :sigv4),
195
240
  uri_escape_path: false,
196
241
  unsigned_headers: ['content-length', 'x-amzn-trace-id']
197
242
  )
198
243
  end
199
244
 
245
+ # Check to see if the bucket is actually an ARN
246
+ # Otherwise it will retry with the ARN as the bucket name.
200
247
  def new_hostname(context, region)
201
- # Check to see if the bucket is actually an ARN and resolve it
202
- # Otherwise it will retry with the ARN as the bucket name.
203
- resolved_bucket, resolved_region, arn = BucketARN.resolve_arn!(
204
- context.params[:bucket],
205
- region,
206
- context.config.s3_use_arn_region
207
- )
208
248
  uri = URI.parse(
209
- Aws::Partitions::EndpointProvider.resolve(resolved_region, 's3')
249
+ Aws::Partitions::EndpointProvider.resolve(
250
+ region, 's3', 'regional',
251
+ {
252
+ dualstack: context[:use_dualstack_endpoint],
253
+ fips: context.config.use_fips_endpoint
254
+ }
255
+ )
210
256
  )
211
257
 
212
- if arn
213
- BucketARN.resolve_url!(uri, arn).host
258
+ if (arn = context.metadata[:s3_arn])
259
+ # Retry with the response region and not the ARN resolved one
260
+ ARN.resolve_url!(
261
+ uri, arn[:arn], region, arn[:fips], arn[:dualstack]
262
+ ).host
214
263
  else
215
- resolved_bucket + '.' + uri.host
264
+ "#{context.params[:bucket]}.#{uri.host}"
216
265
  end
217
266
  end
218
267
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module S3
5
+ module Plugins
6
+
7
+ # S3 GetObject results for whole Multipart Objects contain a checksum
8
+ # that cannot be validated. These should be skipped by the
9
+ # ChecksumAlgorithm plugin.
10
+ class SkipWholeMultipartGetChecksums < Seahorse::Client::Plugin
11
+
12
+ class Handler < Seahorse::Client::Handler
13
+
14
+ def call(context)
15
+ context[:http_checksum] ||= {}
16
+ context[:http_checksum][:skip_on_suffix] = true
17
+
18
+ @handler.call(context)
19
+ end
20
+
21
+ end
22
+
23
+ handler(
24
+ Handler,
25
+ step: :initialize,
26
+ operations: [:get_object]
27
+ )
28
+ end
29
+ end
30
+ end
31
+ end
@@ -36,6 +36,17 @@ module Aws
36
36
  def rewind; end
37
37
  end
38
38
 
39
+ class NonRetryableStreamingError < StandardError
40
+
41
+ def initialize(error)
42
+ super('Unable to retry request - retry could result in processing duplicated chunks.')
43
+ set_backtrace(error.backtrace)
44
+ @original_error = error
45
+ end
46
+
47
+ attr_reader :original_error
48
+ end
49
+
39
50
  # This handler works with the ResponseTarget plugin to provide smart
40
51
  # retries of S3 streaming operations that support the range parameter
41
52
  # (currently only: get_object). When a 200 OK with a TruncatedBodyError
@@ -84,8 +95,18 @@ module Aws
84
95
  end
85
96
 
86
97
  context.http_response.on_error do |error|
87
- if retryable_body?(context) && truncated_body?(error)
88
- context.http_request.headers[:range] = "bytes=#{context.http_response.body.size}-"
98
+ if retryable_body?(context)
99
+ if truncated_body?(error)
100
+ context.http_request.headers[:range] = "bytes=#{context.http_response.body.size}-"
101
+ else
102
+ case context.http_response.body
103
+ when RetryableManagedFile
104
+ # call rewind on the underlying file
105
+ context.http_response.body.instance_variable_get(:@file).rewind
106
+ else
107
+ raise NonRetryableStreamingError, error
108
+ end
109
+ end
89
110
  end
90
111
  end
91
112
  end
@@ -98,7 +98,7 @@ module Aws
98
98
  # or call the associated method.
99
99
  #
100
100
  # ```ruby
101
- # post = Aws::S3::PresignedPost.new(creds, region, bucket).
101
+ # post = Aws::S3::PresignedPost.new(creds, region, bucket)
102
102
  # post.content_type('text/plain')
103
103
  # ```
104
104
  #
@@ -176,11 +176,17 @@ module Aws
176
176
  # ```
177
177
  #
178
178
  class PresignedPost
179
+ @@allowed_fields = []
179
180
 
180
181
  # @param [Credentials] credentials Security credentials for signing
181
182
  # the post policy.
182
183
  # @param [String] bucket_region Region of the target bucket.
183
184
  # @param [String] bucket_name Name of the target bucket.
185
+ # @option options [Boolean] :use_accelerate_endpoint (false) When `true`,
186
+ # PresignedPost will attempt to use accelerated endpoint.
187
+ # @option options [String] :url See {PresignedPost#url}.
188
+ # @option options [Sting, Array<String>] :allow_any
189
+ # See {PresignedPost#allow_any}.
184
190
  # @option options [Time] :signature_expiration Specify when the signature on
185
191
  # the post will expire. Defaults to one hour from creation of the
186
192
  # presigned post. May not exceed one week from creation time.
@@ -205,7 +211,7 @@ module Aws
205
211
  # See {PresignedPost#content_encoding}.
206
212
  # @option options [String] :content_encoding_starts_with
207
213
  # See {PresignedPost#content_encoding_starts_with}.
208
- # @option options [String] :expires See {PresignedPost#expires}.
214
+ # @option options [Time] :expires See {PresignedPost#expires}.
209
215
  # @option options [String] :expires_starts_with
210
216
  # See {PresignedPost#expires_starts_with}.
211
217
  # @option options [Range<Integer>] :content_length_range
@@ -232,6 +238,8 @@ module Aws
232
238
  # See {PresignedPost#server_side_encryption_customer_algorithm}.
233
239
  # @option options [String] :server_side_encryption_customer_key
234
240
  # See {PresignedPost#server_side_encryption_customer_key}.
241
+ # @option options [String] :server_side_encryption_customer_key_starts_with
242
+ # See {PresignedPost#server_side_encryption_customer_key_starts_with}.
235
243
  def initialize(credentials, bucket_region, bucket_name, options = {})
236
244
  @credentials = credentials.credentials
237
245
  @bucket_region = bucket_region
@@ -247,7 +255,12 @@ module Aws
247
255
  case option_name
248
256
  when :allow_any then allow_any(option_value)
249
257
  when :signature_expiration then @signature_expiration = option_value
250
- else send("#{option_name}", option_value)
258
+ else
259
+ if @@allowed_fields.include?(option_name)
260
+ send("#{option_name}", option_value)
261
+ else
262
+ raise ArgumentError, "Unsupported option: #{option_name}"
263
+ end
251
264
  end
252
265
  end
253
266
  end
@@ -279,17 +292,23 @@ module Aws
279
292
  end
280
293
 
281
294
  # @api private
282
- def self.define_field(field, *args)
295
+ def self.define_field(field, *args, &block)
296
+ @@allowed_fields << field
283
297
  options = args.last.is_a?(Hash) ? args.pop : {}
284
298
  field_name = args.last || field.to_s
285
299
 
286
- define_method("#{field}") do |value|
287
- with(field_name, value)
288
- end
300
+ if block_given?
301
+ define_method("#{field}", block)
302
+ else
303
+ define_method("#{field}") do |value|
304
+ with(field_name, value)
305
+ end
289
306
 
290
- if options[:starts_with]
291
- define_method("#{field}_starts_with") do |value|
292
- starts_with(field_name, value)
307
+ if options[:starts_with]
308
+ @@allowed_fields << "#{field}_starts_with".to_sym
309
+ define_method("#{field}_starts_with") do |value|
310
+ starts_with(field_name, value)
311
+ end
293
312
  end
294
313
  end
295
314
  end
@@ -307,7 +326,7 @@ module Aws
307
326
  # @param [String] key
308
327
  # @see http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html)
309
328
  # @return [self]
310
- def key(key)
329
+ define_field(:key) do |key|
311
330
  @key_set = true
312
331
  with('key', key)
313
332
  end
@@ -316,7 +335,7 @@ module Aws
316
335
  # @param [String] prefix
317
336
  # @see #key
318
337
  # @return [self]
319
- def key_starts_with(prefix)
338
+ define_field(:key_starts_with) do |prefix|
320
339
  @key_set = true
321
340
  starts_with('key', prefix)
322
341
  end
@@ -399,21 +418,21 @@ module Aws
399
418
  # @param [Time] time
400
419
  # @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.21
401
420
  # @return [self]
402
- def expires(time)
421
+ define_field(:expires) do |time|
403
422
  with('Expires', time.httpdate)
404
423
  end
405
424
 
406
425
  # @param [String] prefix
407
426
  # @see #expires
408
427
  # @return [self]
409
- def expires_starts_with(prefix)
428
+ define_field(:expires_starts_with) do |prefix|
410
429
  starts_with('Expires', prefix)
411
430
  end
412
431
 
413
432
  # The minimum and maximum allowable size for the uploaded content.
414
433
  # @param [Range<Integer>] byte_range
415
434
  # @return [self]
416
- def content_length_range(byte_range)
435
+ define_field(:content_length_range) do |byte_range|
417
436
  min = byte_range.begin
418
437
  max = byte_range.end
419
438
  max -= 1 if byte_range.exclude_end?
@@ -492,7 +511,7 @@ module Aws
492
511
  # prefixed with "x-amz-meta-".
493
512
  # @param [Hash<String,String>] hash
494
513
  # @return [self]
495
- def metadata(hash)
514
+ define_field(:metadata) do |hash|
496
515
  hash.each do |key, value|
497
516
  with("x-amz-meta-#{key}", value)
498
517
  end
@@ -503,7 +522,7 @@ module Aws
503
522
  # @param [Hash<String,String>] hash
504
523
  # @see #metadata
505
524
  # @return [self]
506
- def metadata_starts_with(hash)
525
+ define_field(:metadata_starts_with) do |hash|
507
526
  hash.each do |key, value|
508
527
  starts_with("x-amz-meta-#{key}", value)
509
528
  end
@@ -561,7 +580,7 @@ module Aws
561
580
  # @param [String] value
562
581
  # @see #server_side_encryption_customer_algorithm
563
582
  # @return [self]
564
- def server_side_encryption_customer_key(value)
583
+ define_field(:server_side_encryption_customer_key) do |value|
565
584
  field_name = 'x-amz-server-side-encryption-customer-key'
566
585
  with(field_name, base64(value))
567
586
  with(field_name + '-MD5', base64(OpenSSL::Digest::MD5.digest(value)))
@@ -570,7 +589,7 @@ module Aws
570
589
  # @param [String] prefix
571
590
  # @see #server_side_encryption_customer_key
572
591
  # @return [self]
573
- def server_side_encryption_customer_key_starts_with(prefix)
592
+ define_field(:server_side_encryption_customer_key_starts_with) do |prefix|
574
593
  field_name = 'x-amz-server-side-encryption-customer-key'
575
594
  starts_with(field_name, prefix)
576
595
  end
@@ -58,8 +58,7 @@ module Aws
58
58
  # is returned instead of the default HTTPS URL.
59
59
  #
60
60
  # @option params [Boolean] :virtual_host (false) When `true`, the
61
- # bucket name will be used as the hostname. This will cause
62
- # the returned URL to be 'http' and not 'https'.
61
+ # bucket name will be used as the hostname.
63
62
  #
64
63
  # @option params [Boolean] :use_accelerate_endpoint (false) When `true`,
65
64
  # Presigner will attempt to use accelerated endpoint.
@@ -139,6 +138,7 @@ module Aws
139
138
 
140
139
  req = @client.build_request(method, params)
141
140
  use_bucket_as_hostname(req) if virtual_host
141
+ handle_presigned_url_context(req)
142
142
 
143
143
  x_amz_headers = sign_but_dont_send(
144
144
  req, expires_in, scheme, time, unsigned_headers, hoist
@@ -184,6 +184,17 @@ module Aws
184
184
  end
185
185
  end
186
186
 
187
+ # Used for excluding presigned_urls from API request count.
188
+ #
189
+ # Store context information as early as possible, to allow
190
+ # handlers to perform decisions based on this flag if need.
191
+ def handle_presigned_url_context(req)
192
+ req.handle(step: :initialize, priority: 98) do |context|
193
+ context[:presigned_url] = true
194
+ @handler.call(context)
195
+ end
196
+ end
197
+
187
198
  # @param [Seahorse::Client::Request] req
188
199
  def sign_but_dont_send(
189
200
  req, expires_in, scheme, time, unsigned_headers, hoist = true
@@ -196,8 +207,6 @@ module Aws
196
207
  req.handlers.remove(Aws::S3::Plugins::S3Signer::V4Handler)
197
208
  req.handlers.remove(Seahorse::Client::Plugins::ContentLength::Handler)
198
209
 
199
- signer = build_signer(req.context.config, unsigned_headers)
200
-
201
210
  req.handle(step: :send) do |context|
202
211
  if scheme != http_req.endpoint.scheme
203
212
  endpoint = http_req.endpoint.dup
@@ -222,6 +231,26 @@ module Aws
222
231
  end
223
232
  http_req.endpoint.query = query.join('&') unless query.empty?
224
233
 
234
+ signing_algorithm = :sigv4
235
+
236
+ # If it's an ARN, get the resolved region and service
237
+ if (arn = context.metadata[:s3_arn])
238
+ region = arn[:resolved_region]
239
+ service = arn[:arn].service
240
+ region = arn[:arn].is_a?(MultiRegionAccessPointARN) ? '*': arn[:resolved_region]
241
+ signing_algorithm = arn[:arn].is_a?(MultiRegionAccessPointARN) ? :sigv4a : :sigv4
242
+ end
243
+
244
+ signer = Aws::Sigv4::Signer.new(
245
+ service: service || 's3',
246
+ region: region || context.config.region,
247
+ signing_algorithm: signing_algorithm,
248
+ credentials_provider: context.config.credentials,
249
+ unsigned_headers: unsigned_headers,
250
+ apply_checksum_header: false,
251
+ uri_escape_path: false
252
+ )
253
+
225
254
  url = signer.presign_url(
226
255
  http_method: http_req.http_method,
227
256
  url: http_req.endpoint,
@@ -231,24 +260,11 @@ module Aws
231
260
  time: time
232
261
  ).to_s
233
262
 
234
- # Used for excluding presigned_urls from API request count
235
- context[:presigned_url] = true
236
-
237
263
  Seahorse::Client::Response.new(context: context, data: url)
238
264
  end
239
265
  # Return the headers
240
266
  x_amz_headers
241
267
  end
242
-
243
- def build_signer(cfg, unsigned_headers)
244
- Aws::Sigv4::Signer.new(
245
- service: 's3',
246
- region: cfg.region,
247
- credentials_provider: cfg.credentials,
248
- unsigned_headers: unsigned_headers,
249
- uri_escape_path: false
250
- )
251
- end
252
268
  end
253
269
  end
254
270
  end
@@ -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
 
@@ -49,6 +49,7 @@ module Aws::S3
49
49
  # grant_write: "GrantWrite",
50
50
  # grant_write_acp: "GrantWriteACP",
51
51
  # object_lock_enabled_for_bucket: false,
52
+ # object_ownership: "BucketOwnerPreferred", # accepts BucketOwnerPreferred, ObjectWriter, BucketOwnerEnforced
52
53
  # })
53
54
  # @param [Hash] options ({})
54
55
  # @option options [String] :acl
@@ -65,13 +66,32 @@ module Aws::S3
65
66
  # @option options [String] :grant_read_acp
66
67
  # Allows grantee to read the bucket ACL.
67
68
  # @option options [String] :grant_write
68
- # Allows grantee to create, overwrite, and delete any object in the
69
- # bucket.
69
+ # Allows grantee to create new objects in the bucket.
70
+ #
71
+ # For the bucket and object owners of existing objects, also allows
72
+ # deletions and overwrites of those objects.
70
73
  # @option options [String] :grant_write_acp
71
74
  # Allows grantee to write the ACL for the applicable bucket.
72
75
  # @option options [Boolean] :object_lock_enabled_for_bucket
73
76
  # Specifies whether you want S3 Object Lock to be enabled for the new
74
77
  # bucket.
78
+ # @option options [String] :object_ownership
79
+ # The container element for object ownership for a bucket's ownership
80
+ # controls.
81
+ #
82
+ # BucketOwnerPreferred - Objects uploaded to the bucket change ownership
83
+ # to the bucket owner if the objects are uploaded with the
84
+ # `bucket-owner-full-control` canned ACL.
85
+ #
86
+ # ObjectWriter - The uploading account will own the object if the object
87
+ # is uploaded with the `bucket-owner-full-control` canned ACL.
88
+ #
89
+ # BucketOwnerEnforced - Access control lists (ACLs) are disabled and no
90
+ # longer affect permissions. The bucket owner automatically owns and has
91
+ # full control over every object in the bucket. The bucket only accepts
92
+ # PUT requests that don't specify an ACL or bucket owner full control
93
+ # ACLs, such as the `bucket-owner-full-control` canned ACL or an
94
+ # equivalent form of this ACL expressed in the XML format.
75
95
  # @return [Bucket]
76
96
  def create_bucket(options = {})
77
97
  @client.create_bucket(options)