aws-sdk-s3 1.103.0 → 1.202.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +664 -0
- data/VERSION +1 -1
- data/lib/aws-sdk-s3/access_grants_credentials.rb +57 -0
- data/lib/aws-sdk-s3/access_grants_credentials_provider.rb +250 -0
- data/lib/aws-sdk-s3/bucket.rb +858 -116
- data/lib/aws-sdk-s3/bucket_acl.rb +32 -9
- data/lib/aws-sdk-s3/bucket_cors.rb +38 -13
- data/lib/aws-sdk-s3/bucket_lifecycle.rb +43 -12
- data/lib/aws-sdk-s3/bucket_lifecycle_configuration.rb +100 -13
- data/lib/aws-sdk-s3/bucket_logging.rb +35 -6
- data/lib/aws-sdk-s3/bucket_notification.rb +27 -9
- data/lib/aws-sdk-s3/bucket_policy.rb +79 -10
- data/lib/aws-sdk-s3/bucket_region_cache.rb +9 -5
- data/lib/aws-sdk-s3/bucket_request_payment.rb +29 -7
- data/lib/aws-sdk-s3/bucket_tagging.rb +35 -11
- data/lib/aws-sdk-s3/bucket_versioning.rb +108 -17
- data/lib/aws-sdk-s3/bucket_website.rb +35 -11
- data/lib/aws-sdk-s3/client.rb +11799 -3636
- data/lib/aws-sdk-s3/client_api.rb +1201 -276
- data/lib/aws-sdk-s3/customizations/bucket.rb +23 -47
- data/lib/aws-sdk-s3/customizations/errors.rb +40 -0
- data/lib/aws-sdk-s3/customizations/object.rb +216 -70
- data/lib/aws-sdk-s3/customizations/object_summary.rb +5 -0
- data/lib/aws-sdk-s3/customizations/object_version.rb +13 -0
- data/lib/aws-sdk-s3/customizations/types/permanent_redirect.rb +26 -0
- data/lib/aws-sdk-s3/customizations.rb +27 -29
- data/lib/aws-sdk-s3/default_executor.rb +103 -0
- data/lib/aws-sdk-s3/encryption/client.rb +6 -2
- data/lib/aws-sdk-s3/encryption/kms_cipher_provider.rb +13 -9
- data/lib/aws-sdk-s3/encryptionV2/client.rb +6 -2
- data/lib/aws-sdk-s3/encryptionV2/decrypt_handler.rb +1 -0
- data/lib/aws-sdk-s3/encryptionV2/kms_cipher_provider.rb +10 -6
- data/lib/aws-sdk-s3/endpoint_parameters.rb +181 -0
- data/lib/aws-sdk-s3/endpoint_provider.rb +716 -0
- data/lib/aws-sdk-s3/endpoints.rb +1518 -0
- data/lib/aws-sdk-s3/errors.rb +58 -0
- data/lib/aws-sdk-s3/express_credentials.rb +55 -0
- data/lib/aws-sdk-s3/express_credentials_provider.rb +59 -0
- data/lib/aws-sdk-s3/file_downloader.rb +241 -87
- data/lib/aws-sdk-s3/file_uploader.rb +16 -13
- data/lib/aws-sdk-s3/legacy_signer.rb +2 -1
- data/lib/aws-sdk-s3/multipart_download_error.rb +8 -0
- data/lib/aws-sdk-s3/multipart_file_uploader.rb +108 -86
- data/lib/aws-sdk-s3/multipart_stream_uploader.rb +110 -92
- data/lib/aws-sdk-s3/multipart_upload.rb +294 -19
- data/lib/aws-sdk-s3/multipart_upload_error.rb +3 -4
- data/lib/aws-sdk-s3/multipart_upload_part.rb +297 -31
- data/lib/aws-sdk-s3/object.rb +2224 -269
- data/lib/aws-sdk-s3/object_acl.rb +59 -17
- data/lib/aws-sdk-s3/object_copier.rb +7 -5
- data/lib/aws-sdk-s3/object_multipart_copier.rb +48 -23
- data/lib/aws-sdk-s3/object_summary.rb +1915 -220
- data/lib/aws-sdk-s3/object_version.rb +450 -58
- data/lib/aws-sdk-s3/plugins/accelerate.rb +3 -44
- data/lib/aws-sdk-s3/plugins/access_grants.rb +178 -0
- data/lib/aws-sdk-s3/plugins/arn.rb +0 -197
- data/lib/aws-sdk-s3/plugins/bucket_dns.rb +3 -39
- data/lib/aws-sdk-s3/plugins/bucket_name_restrictions.rb +1 -6
- data/lib/aws-sdk-s3/plugins/checksum_algorithm.rb +31 -0
- data/lib/aws-sdk-s3/plugins/dualstack.rb +1 -55
- data/lib/aws-sdk-s3/plugins/endpoints.rb +86 -0
- data/lib/aws-sdk-s3/plugins/expect_100_continue.rb +2 -1
- data/lib/aws-sdk-s3/plugins/express_session_auth.rb +88 -0
- data/lib/aws-sdk-s3/plugins/http_200_errors.rb +55 -18
- data/lib/aws-sdk-s3/plugins/iad_regional_endpoint.rb +6 -29
- data/lib/aws-sdk-s3/plugins/location_constraint.rb +3 -1
- data/lib/aws-sdk-s3/plugins/md5s.rb +10 -68
- data/lib/aws-sdk-s3/plugins/s3_signer.rb +42 -111
- data/lib/aws-sdk-s3/plugins/streaming_retry.rb +28 -9
- data/lib/aws-sdk-s3/plugins/url_encoded_keys.rb +2 -1
- data/lib/aws-sdk-s3/presigned_post.rb +99 -78
- data/lib/aws-sdk-s3/presigner.rb +32 -41
- data/lib/aws-sdk-s3/resource.rb +139 -12
- data/lib/aws-sdk-s3/transfer_manager.rb +304 -0
- data/lib/aws-sdk-s3/types.rb +10204 -5378
- data/lib/aws-sdk-s3.rb +35 -27
- data/sig/bucket.rbs +231 -0
- data/sig/bucket_acl.rbs +78 -0
- data/sig/bucket_cors.rbs +69 -0
- data/sig/bucket_lifecycle.rbs +88 -0
- data/sig/bucket_lifecycle_configuration.rbs +115 -0
- data/sig/bucket_logging.rbs +76 -0
- data/sig/bucket_notification.rbs +114 -0
- data/sig/bucket_policy.rbs +59 -0
- data/sig/bucket_request_payment.rbs +54 -0
- data/sig/bucket_tagging.rbs +65 -0
- data/sig/bucket_versioning.rbs +77 -0
- data/sig/bucket_website.rbs +93 -0
- data/sig/client.rbs +2586 -0
- data/sig/customizations/bucket.rbs +19 -0
- data/sig/customizations/object.rbs +38 -0
- data/sig/customizations/object_summary.rbs +35 -0
- data/sig/errors.rbs +44 -0
- data/sig/multipart_upload.rbs +120 -0
- data/sig/multipart_upload_part.rbs +109 -0
- data/sig/object.rbs +464 -0
- data/sig/object_acl.rbs +86 -0
- data/sig/object_summary.rbs +347 -0
- data/sig/object_version.rbs +143 -0
- data/sig/resource.rbs +141 -0
- data/sig/types.rbs +2868 -0
- data/sig/waiters.rbs +95 -0
- metadata +51 -16
- data/lib/aws-sdk-s3/arn/access_point_arn.rb +0 -69
- data/lib/aws-sdk-s3/arn/multi_region_access_point_arn.rb +0 -69
- data/lib/aws-sdk-s3/arn/object_lambda_arn.rb +0 -69
- data/lib/aws-sdk-s3/arn/outpost_access_point_arn.rb +0 -73
- data/lib/aws-sdk-s3/plugins/object_lambda_endpoint.rb +0 -25
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# WARNING ABOUT GENERATED CODE
|
|
4
|
+
#
|
|
5
|
+
# This file is generated. See the contributing guide for more information:
|
|
6
|
+
# https://github.com/aws/aws-sdk-ruby/blob/version-3/CONTRIBUTING.md
|
|
7
|
+
#
|
|
8
|
+
# WARNING ABOUT GENERATED CODE
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
module Aws::S3
|
|
12
|
+
module Plugins
|
|
13
|
+
class Endpoints < Seahorse::Client::Plugin
|
|
14
|
+
option(
|
|
15
|
+
:endpoint_provider,
|
|
16
|
+
doc_type: 'Aws::S3::EndpointProvider',
|
|
17
|
+
rbs_type: 'untyped',
|
|
18
|
+
docstring: <<~DOCS) do |_cfg|
|
|
19
|
+
The endpoint provider used to resolve endpoints. Any object that responds to
|
|
20
|
+
`#resolve_endpoint(parameters)` where `parameters` is a Struct similar to
|
|
21
|
+
`Aws::S3::EndpointParameters`.
|
|
22
|
+
DOCS
|
|
23
|
+
Aws::S3::EndpointProvider.new
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
option(
|
|
27
|
+
:disable_s3_express_session_auth,
|
|
28
|
+
doc_type: 'boolean',
|
|
29
|
+
docstring: <<~DOCS) do |cfg|
|
|
30
|
+
Parameter to indicate whether S3Express session auth should be disabled
|
|
31
|
+
DOCS
|
|
32
|
+
nil
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# @api private
|
|
36
|
+
class Handler < Seahorse::Client::Handler
|
|
37
|
+
def call(context)
|
|
38
|
+
unless context[:discovered_endpoint]
|
|
39
|
+
params = Aws::S3::Endpoints.parameters_for_operation(context)
|
|
40
|
+
endpoint = context.config.endpoint_provider.resolve_endpoint(params)
|
|
41
|
+
|
|
42
|
+
context.http_request.endpoint = endpoint.url
|
|
43
|
+
apply_endpoint_headers(context, endpoint.headers)
|
|
44
|
+
|
|
45
|
+
context[:endpoint_params] = params
|
|
46
|
+
context[:endpoint_properties] = endpoint.properties
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
context[:auth_scheme] =
|
|
50
|
+
Aws::Endpoints.resolve_auth_scheme(context, endpoint)
|
|
51
|
+
|
|
52
|
+
with_metrics(context) { @handler.call(context) }
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
def with_metrics(context, &block)
|
|
58
|
+
metrics = []
|
|
59
|
+
metrics << 'ENDPOINT_OVERRIDE' unless context.config.regional_endpoint
|
|
60
|
+
if context[:auth_scheme] && context[:auth_scheme]['name'] == 'sigv4a'
|
|
61
|
+
metrics << 'SIGV4A_SIGNING'
|
|
62
|
+
end
|
|
63
|
+
if context.config.credentials&.credentials&.account_id
|
|
64
|
+
metrics << 'RESOLVED_ACCOUNT_ID'
|
|
65
|
+
end
|
|
66
|
+
Aws::Plugins::UserAgent.metric(*metrics, &block)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def apply_endpoint_headers(context, headers)
|
|
70
|
+
headers.each do |key, values|
|
|
71
|
+
value = values
|
|
72
|
+
.compact
|
|
73
|
+
.map { |s| Seahorse::Util.escape_header_list_string(s.to_s) }
|
|
74
|
+
.join(',')
|
|
75
|
+
|
|
76
|
+
context.http_request.headers[key] = value
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def add_handlers(handlers, _config)
|
|
82
|
+
handlers.add(Handler, step: :build, priority: 75)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -16,7 +16,8 @@ module Aws
|
|
|
16
16
|
|
|
17
17
|
def call(context)
|
|
18
18
|
body = context.http_request.body
|
|
19
|
-
if body.respond_to?(:size) && body.size > 0
|
|
19
|
+
if body.respond_to?(:size) && body.size > 0 &&
|
|
20
|
+
!context[:use_accelerate_endpoint]
|
|
20
21
|
context.http_request.headers['expect'] = '100-continue'
|
|
21
22
|
end
|
|
22
23
|
@handler.call(context)
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Aws
|
|
4
|
+
module S3
|
|
5
|
+
module Plugins
|
|
6
|
+
# @api private
|
|
7
|
+
class ExpressSessionAuth < Seahorse::Client::Plugin
|
|
8
|
+
# This should be s3_disable_express_auth instead
|
|
9
|
+
# But this is not a built in. We're overwriting the generated value
|
|
10
|
+
option(:disable_s3_express_session_auth,
|
|
11
|
+
default: false,
|
|
12
|
+
doc_type: 'Boolean',
|
|
13
|
+
docstring: <<-DOCS) do |cfg|
|
|
14
|
+
When `true`, S3 Express session authentication is disabled.
|
|
15
|
+
DOCS
|
|
16
|
+
resolve_disable_s3_express_session_auth(cfg)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
option(:express_credentials_provider,
|
|
20
|
+
doc_type: 'Aws::S3::ExpressCredentialsProvider',
|
|
21
|
+
rbs_type: 'untyped',
|
|
22
|
+
docstring: <<-DOCS) do |_cfg|
|
|
23
|
+
Credential Provider for S3 Express endpoints. Manages credentials
|
|
24
|
+
for different buckets.
|
|
25
|
+
DOCS
|
|
26
|
+
Aws::S3::ExpressCredentialsProvider.new
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# @api private
|
|
30
|
+
class Handler < Seahorse::Client::Handler
|
|
31
|
+
def call(context)
|
|
32
|
+
context[:s3_express_endpoint] = true if s3_express_endpoint?(context)
|
|
33
|
+
|
|
34
|
+
# if s3 express auth, use new credentials and sign additional header
|
|
35
|
+
if context[:auth_scheme]['name'] == 'sigv4-s3express' &&
|
|
36
|
+
!context.config.disable_s3_express_session_auth
|
|
37
|
+
bucket = context.params[:bucket]
|
|
38
|
+
credentials_provider = context.config.express_credentials_provider
|
|
39
|
+
credentials = credentials_provider.express_credentials_for(bucket)
|
|
40
|
+
context[:sigv4_credentials] = credentials # Sign will use this
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
with_metric(credentials) { @handler.call(context) }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
def with_metric(credentials, &block)
|
|
49
|
+
return block.call unless credentials
|
|
50
|
+
|
|
51
|
+
Aws::Plugins::UserAgent.metric('S3_EXPRESS_BUCKET', &block)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def s3_express_endpoint?(context)
|
|
55
|
+
context[:endpoint_properties]['backend'] == 'S3Express'
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
handler(Handler)
|
|
60
|
+
|
|
61
|
+
# Optimization - sets this client as the client to create sessions.
|
|
62
|
+
def after_initialize(client)
|
|
63
|
+
provider = client.config.express_credentials_provider
|
|
64
|
+
provider.client = client unless provider.client
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
class << self
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
def resolve_disable_s3_express_session_auth(cfg)
|
|
71
|
+
value = ENV['AWS_S3_DISABLE_EXPRESS_SESSION_AUTH'] ||
|
|
72
|
+
Aws.shared_config.s3_disable_express_session_auth(profile: cfg.profile) ||
|
|
73
|
+
'false'
|
|
74
|
+
value = Aws::Util.str_2_bool(value)
|
|
75
|
+
# Raise if provided value is not true or false
|
|
76
|
+
if value.nil?
|
|
77
|
+
raise ArgumentError,
|
|
78
|
+
'Must provide either `true` or `false` for the '\
|
|
79
|
+
'`s3_disable_express_session_auth` profile option or for '\
|
|
80
|
+
"ENV['AWS_S3_DISABLE_EXPRESS_SESSION_AUTH']."
|
|
81
|
+
end
|
|
82
|
+
value
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -15,22 +15,67 @@ module Aws
|
|
|
15
15
|
|
|
16
16
|
def call(context)
|
|
17
17
|
@handler.call(context).on(200) do |response|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
return response if streaming_output?(context.operation.output)
|
|
19
|
+
|
|
20
|
+
error = check_for_error(context)
|
|
21
|
+
return response unless error
|
|
22
|
+
|
|
23
|
+
context.http_response.status_code = 500
|
|
24
|
+
response.data = nil
|
|
25
|
+
response.error = error
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
# Streaming outputs are not subject to 200 errors.
|
|
32
|
+
def streaming_output?(output)
|
|
33
|
+
if (payload = output[:payload_member])
|
|
34
|
+
# checking ref and shape
|
|
35
|
+
payload['streaming'] || payload.shape['streaming'] ||
|
|
36
|
+
payload.eventstream
|
|
37
|
+
else
|
|
38
|
+
false
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Checks if the output shape is a structure shape and has members that
|
|
43
|
+
# are in the body for the case of a payload and a normal structure. A
|
|
44
|
+
# non-structure shape will not have members in the body. In the case
|
|
45
|
+
# of a string or blob, the body contents would have been checked first
|
|
46
|
+
# before this method is called in incomplete_xml_body?.
|
|
47
|
+
def members_in_body?(output)
|
|
48
|
+
shape =
|
|
49
|
+
if output[:payload_member]
|
|
50
|
+
output[:payload_member].shape
|
|
51
|
+
else
|
|
52
|
+
output.shape
|
|
22
53
|
end
|
|
54
|
+
|
|
55
|
+
if structure_shape?(shape)
|
|
56
|
+
shape.members.any? { |_, k| k.location.nil? }
|
|
57
|
+
else
|
|
58
|
+
false
|
|
23
59
|
end
|
|
24
60
|
end
|
|
25
61
|
|
|
62
|
+
def structure_shape?(shape)
|
|
63
|
+
shape.is_a?(Seahorse::Model::Shapes::StructureShape)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Must have a member in the body and have the start of an XML Tag.
|
|
67
|
+
# Other incomplete xml bodies will result in an XML ParsingError.
|
|
68
|
+
def incomplete_xml_body?(xml, output)
|
|
69
|
+
members_in_body?(output) && !xml.match(/<\w/)
|
|
70
|
+
end
|
|
71
|
+
|
|
26
72
|
def check_for_error(context)
|
|
27
73
|
xml = context.http_response.body_contents
|
|
28
|
-
if xml.match(
|
|
29
|
-
error_code = xml.match(
|
|
30
|
-
error_message = xml.match(
|
|
74
|
+
if xml.match(/<\?xml\s[^>]*\?>\s*<Error>/)
|
|
75
|
+
error_code = xml.match(%r{<Code>(.+?)</Code>})[1]
|
|
76
|
+
error_message = xml.match(%r{<Message>(.+?)</Message>})[1]
|
|
31
77
|
S3::Errors.error_class(error_code).new(context, error_message)
|
|
32
|
-
elsif
|
|
33
|
-
# Other incomplete xml bodies will result in XML ParsingError
|
|
78
|
+
elsif incomplete_xml_body?(xml, context.operation.output)
|
|
34
79
|
Seahorse::Client::NetworkingError.new(
|
|
35
80
|
S3::Errors
|
|
36
81
|
.error_class('InternalError')
|
|
@@ -40,15 +85,7 @@ module Aws
|
|
|
40
85
|
end
|
|
41
86
|
end
|
|
42
87
|
|
|
43
|
-
handler(
|
|
44
|
-
Handler,
|
|
45
|
-
step: :sign,
|
|
46
|
-
operations: [
|
|
47
|
-
:complete_multipart_upload,
|
|
48
|
-
:copy_object,
|
|
49
|
-
:upload_part_copy,
|
|
50
|
-
]
|
|
51
|
-
)
|
|
88
|
+
handler(Handler, step: :sign)
|
|
52
89
|
end
|
|
53
90
|
end
|
|
54
91
|
end
|
|
@@ -16,40 +16,17 @@ Defaults to `legacy` mode which uses the global endpoint.
|
|
|
16
16
|
resolve_iad_regional_endpoint(cfg)
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
def add_handlers(handlers, config)
|
|
20
|
-
# only modify non-custom endpoints
|
|
21
|
-
if config.regional_endpoint && config.region == 'us-east-1'
|
|
22
|
-
handlers.add(Handler)
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
# @api private
|
|
27
|
-
class Handler < Seahorse::Client::Handler
|
|
28
|
-
|
|
29
|
-
def call(context)
|
|
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
|
|
38
|
-
end
|
|
39
|
-
@handler.call(context)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def self.legacy_host(host)
|
|
45
|
-
host.sub(".us-east-1", '')
|
|
46
|
-
end
|
|
47
|
-
|
|
48
19
|
private
|
|
49
20
|
|
|
50
21
|
def self.resolve_iad_regional_endpoint(cfg)
|
|
22
|
+
default_mode_value =
|
|
23
|
+
if cfg.respond_to?(:defaults_mode_config_resolver)
|
|
24
|
+
cfg.defaults_mode_config_resolver.resolve(:s3_us_east_1_regional_endpoint)
|
|
25
|
+
end
|
|
26
|
+
|
|
51
27
|
mode = ENV['AWS_S3_US_EAST_1_REGIONAL_ENDPOINT'] ||
|
|
52
28
|
Aws.shared_config.s3_us_east_1_regional_endpoint(profile: cfg.profile) ||
|
|
29
|
+
default_mode_value ||
|
|
53
30
|
'legacy'
|
|
54
31
|
mode = mode.downcase
|
|
55
32
|
unless %w(legacy regional).include?(mode)
|
|
@@ -22,7 +22,9 @@ module Aws
|
|
|
22
22
|
|
|
23
23
|
def populate_location_constraint(params, region)
|
|
24
24
|
params[:create_bucket_configuration] ||= {}
|
|
25
|
-
params[:create_bucket_configuration][:
|
|
25
|
+
unless params[:create_bucket_configuration][:location]
|
|
26
|
+
params[:create_bucket_configuration][:location_constraint] ||= region
|
|
27
|
+
end
|
|
26
28
|
end
|
|
27
29
|
|
|
28
30
|
end
|
|
@@ -6,78 +6,20 @@ module Aws
|
|
|
6
6
|
module S3
|
|
7
7
|
module Plugins
|
|
8
8
|
# @api private
|
|
9
|
-
# This plugin is
|
|
9
|
+
# This plugin is deprecated in favor of modeled
|
|
10
10
|
# httpChecksumRequired traits.
|
|
11
11
|
class Md5s < Seahorse::Client::Plugin
|
|
12
|
-
# These operations allow Content MD5 but are not required by
|
|
13
|
-
# httpChecksumRequired. This list should not grow.
|
|
14
|
-
OPTIONAL_OPERATIONS = [
|
|
15
|
-
:put_object,
|
|
16
|
-
:upload_part
|
|
17
|
-
]
|
|
18
|
-
|
|
19
|
-
# @api private
|
|
20
|
-
class Handler < Seahorse::Client::Handler
|
|
21
|
-
|
|
22
|
-
CHUNK_SIZE = 1 * 1024 * 1024 # one MB
|
|
23
|
-
|
|
24
|
-
def call(context)
|
|
25
|
-
body = context.http_request.body
|
|
26
|
-
if body.respond_to?(:size) && body.size > 0
|
|
27
|
-
context.http_request.headers['Content-Md5'] ||= md5(body)
|
|
28
|
-
end
|
|
29
|
-
@handler.call(context)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
private
|
|
33
|
-
|
|
34
|
-
# @param [File, Tempfile, IO#read, String] value
|
|
35
|
-
# @return [String<MD5>]
|
|
36
|
-
def md5(value)
|
|
37
|
-
if (File === value || Tempfile === value) && !value.path.nil? && File.exist?(value.path)
|
|
38
|
-
OpenSSL::Digest::MD5.file(value).base64digest
|
|
39
|
-
elsif value.respond_to?(:read)
|
|
40
|
-
md5 = OpenSSL::Digest::MD5.new
|
|
41
|
-
update_in_chunks(md5, value)
|
|
42
|
-
md5.base64digest
|
|
43
|
-
else
|
|
44
|
-
OpenSSL::Digest::MD5.digest(value).base64digest
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def update_in_chunks(digest, io)
|
|
49
|
-
loop do
|
|
50
|
-
chunk = io.read(CHUNK_SIZE)
|
|
51
|
-
break unless chunk
|
|
52
|
-
digest.update(chunk)
|
|
53
|
-
end
|
|
54
|
-
io.rewind
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
end
|
|
58
|
-
|
|
59
12
|
option(:compute_checksums,
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
def add_handlers(handlers, config)
|
|
71
|
-
if config.compute_checksums
|
|
72
|
-
# priority set low to ensure md5 is computed AFTER the request is
|
|
73
|
-
# built but before it is signed
|
|
74
|
-
handlers.add(
|
|
75
|
-
Handler,
|
|
76
|
-
priority: 10, step: :build, operations: OPTIONAL_OPERATIONS
|
|
77
|
-
)
|
|
78
|
-
end
|
|
13
|
+
default: true,
|
|
14
|
+
doc_type: 'Boolean',
|
|
15
|
+
docstring: <<~DOCS)
|
|
16
|
+
This option is deprecated. Please use `:request_checksum_calculation` instead.
|
|
17
|
+
When `false`, `request_checksum_calculation` is overridden to `when_required`.
|
|
18
|
+
DOCS
|
|
19
|
+
|
|
20
|
+
def after_initialize(client)
|
|
21
|
+
client.config.request_checksum_calculation = 'when_required' unless client.config.compute_checksums
|
|
79
22
|
end
|
|
80
|
-
|
|
81
23
|
end
|
|
82
24
|
end
|
|
83
25
|
end
|
|
@@ -4,27 +4,19 @@ require 'aws-sigv4'
|
|
|
4
4
|
|
|
5
5
|
module Aws
|
|
6
6
|
module S3
|
|
7
|
+
# @api private
|
|
8
|
+
def self.bucket_region_cache
|
|
9
|
+
@bucket_region_cache ||= BucketRegionCache.new
|
|
10
|
+
end
|
|
11
|
+
|
|
7
12
|
module Plugins
|
|
8
|
-
# This plugin
|
|
13
|
+
# This plugin used to have a V4 signer but it was removed in favor of
|
|
14
|
+
# generic Sign plugin that uses endpoint auth scheme.
|
|
15
|
+
#
|
|
9
16
|
# @api private
|
|
10
17
|
class S3Signer < Seahorse::Client::Plugin
|
|
11
18
|
option(:signature_version, 'v4')
|
|
12
19
|
|
|
13
|
-
option(:sigv4_signer) do |cfg|
|
|
14
|
-
S3Signer.build_v4_signer(
|
|
15
|
-
service: 's3',
|
|
16
|
-
region: cfg.sigv4_region,
|
|
17
|
-
credentials: cfg.credentials
|
|
18
|
-
)
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
option(:sigv4_region) do |cfg|
|
|
22
|
-
# S3 removes core's signature_v4 plugin that checks for this
|
|
23
|
-
raise Aws::Errors::MissingRegionError if cfg.region.nil?
|
|
24
|
-
|
|
25
|
-
Aws::Partitions::EndpointProvider.signing_region(cfg.region, 's3')
|
|
26
|
-
end
|
|
27
|
-
|
|
28
20
|
def add_handlers(handlers, cfg)
|
|
29
21
|
case cfg.signature_version
|
|
30
22
|
when 'v4' then add_v4_handlers(handlers)
|
|
@@ -37,11 +29,11 @@ module Aws
|
|
|
37
29
|
|
|
38
30
|
def add_v4_handlers(handlers)
|
|
39
31
|
handlers.add(CachedBucketRegionHandler, step: :sign, priority: 60)
|
|
40
|
-
handlers.add(V4Handler, step: :sign)
|
|
41
32
|
handlers.add(BucketRegionErrorHandler, step: :sign, priority: 40)
|
|
42
33
|
end
|
|
43
34
|
|
|
44
35
|
def add_legacy_handler(handlers)
|
|
36
|
+
# generic Sign plugin will be skipped if it sees sigv2
|
|
45
37
|
handlers.add(LegacyHandler, step: :sign)
|
|
46
38
|
end
|
|
47
39
|
|
|
@@ -52,53 +44,6 @@ module Aws
|
|
|
52
44
|
end
|
|
53
45
|
end
|
|
54
46
|
|
|
55
|
-
class V4Handler < Seahorse::Client::Handler
|
|
56
|
-
def call(context)
|
|
57
|
-
Aws::Plugins::SignatureV4.apply_signature(
|
|
58
|
-
context: context,
|
|
59
|
-
signer: sigv4_signer(context)
|
|
60
|
-
)
|
|
61
|
-
@handler.call(context)
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
private
|
|
65
|
-
|
|
66
|
-
def sigv4_signer(context)
|
|
67
|
-
# If the client was configured with the wrong region,
|
|
68
|
-
# we have to build a new signer.
|
|
69
|
-
if context[:cached_sigv4_region] &&
|
|
70
|
-
context[:cached_sigv4_region] != context.config.sigv4_signer.region
|
|
71
|
-
S3Signer.build_v4_signer(
|
|
72
|
-
service: 's3',
|
|
73
|
-
region: context[:cached_sigv4_region],
|
|
74
|
-
credentials: context.config.credentials
|
|
75
|
-
)
|
|
76
|
-
elsif (arn = context.metadata[:s3_arn])
|
|
77
|
-
if arn[:arn].is_a?(MultiRegionAccessPointARN)
|
|
78
|
-
signing_region = '*'
|
|
79
|
-
signing_algorithm = :sigv4a
|
|
80
|
-
else
|
|
81
|
-
signing_region = arn[:resolved_region]
|
|
82
|
-
signing_algorithm = :sigv4
|
|
83
|
-
end
|
|
84
|
-
S3Signer.build_v4_signer(
|
|
85
|
-
service: arn[:arn].service,
|
|
86
|
-
signing_algorithm: signing_algorithm,
|
|
87
|
-
region: signing_region,
|
|
88
|
-
credentials: context.config.credentials
|
|
89
|
-
)
|
|
90
|
-
elsif context.operation.name == 'WriteGetObjectResponse'
|
|
91
|
-
S3Signer.build_v4_signer(
|
|
92
|
-
service: 's3-object-lambda',
|
|
93
|
-
region: context.config.sigv4_region,
|
|
94
|
-
credentials: context.config.credentials
|
|
95
|
-
)
|
|
96
|
-
else
|
|
97
|
-
context.config.sigv4_signer
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
|
|
102
47
|
# This handler will update the http endpoint when the bucket region
|
|
103
48
|
# is known/cached.
|
|
104
49
|
class CachedBucketRegionHandler < Seahorse::Client::Handler
|
|
@@ -111,12 +56,14 @@ module Aws
|
|
|
111
56
|
private
|
|
112
57
|
|
|
113
58
|
def check_for_cached_region(context, bucket)
|
|
114
|
-
cached_region = S3
|
|
115
|
-
if cached_region &&
|
|
59
|
+
cached_region = Aws::S3.bucket_region_cache[bucket]
|
|
60
|
+
if cached_region &&
|
|
61
|
+
cached_region != context.config.region &&
|
|
62
|
+
!S3Signer.custom_endpoint?(context)
|
|
116
63
|
context.http_request.endpoint.host = S3Signer.new_hostname(
|
|
117
64
|
context, cached_region
|
|
118
65
|
)
|
|
119
|
-
context[:
|
|
66
|
+
context[:sigv4_region] = cached_region # Sign plugin will use this
|
|
120
67
|
end
|
|
121
68
|
end
|
|
122
69
|
end
|
|
@@ -124,7 +71,8 @@ module Aws
|
|
|
124
71
|
# This handler detects when a request fails because of a mismatched bucket
|
|
125
72
|
# region. It follows up by making a request to determine the correct
|
|
126
73
|
# region, then finally a version 4 signed request against the correct
|
|
127
|
-
# regional endpoint.
|
|
74
|
+
# regional endpoint. This is intended for s3's global endpoint which
|
|
75
|
+
# will return 400 if the bucket is not in region.
|
|
128
76
|
class BucketRegionErrorHandler < Seahorse::Client::Handler
|
|
129
77
|
def call(context)
|
|
130
78
|
response = @handler.call(context)
|
|
@@ -136,7 +84,8 @@ module Aws
|
|
|
136
84
|
def handle_region_errors(response)
|
|
137
85
|
if wrong_sigv4_region?(response) &&
|
|
138
86
|
!fips_region?(response) &&
|
|
139
|
-
!custom_endpoint?(response)
|
|
87
|
+
!S3Signer.custom_endpoint?(response.context) &&
|
|
88
|
+
!expired_credentials?(response)
|
|
140
89
|
get_region_and_retry(response.context)
|
|
141
90
|
else
|
|
142
91
|
response
|
|
@@ -153,18 +102,15 @@ module Aws
|
|
|
153
102
|
end
|
|
154
103
|
|
|
155
104
|
def update_bucket_cache(context, actual_region)
|
|
156
|
-
S3
|
|
105
|
+
Aws::S3.bucket_region_cache[context.params[:bucket]] = actual_region
|
|
157
106
|
end
|
|
158
107
|
|
|
159
108
|
def fips_region?(resp)
|
|
160
|
-
resp.context.http_request.endpoint.host.include?('fips')
|
|
109
|
+
resp.context.http_request.endpoint.host.include?('s3-fips.')
|
|
161
110
|
end
|
|
162
111
|
|
|
163
|
-
def
|
|
164
|
-
|
|
165
|
-
resp.context.config.region
|
|
166
|
-
)
|
|
167
|
-
!resp.context.http_request.endpoint.hostname.include?(resolved_suffix)
|
|
112
|
+
def expired_credentials?(resp)
|
|
113
|
+
resp.context.http_response.body_contents.match(/<Code>ExpiredToken<\/Code>/)
|
|
168
114
|
end
|
|
169
115
|
|
|
170
116
|
def wrong_sigv4_region?(resp)
|
|
@@ -179,18 +125,14 @@ module Aws
|
|
|
179
125
|
context, actual_region
|
|
180
126
|
)
|
|
181
127
|
context.metadata[:redirect_region] = actual_region
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
context: context,
|
|
188
|
-
signer: S3Signer.build_v4_signer(
|
|
189
|
-
service: service || 's3',
|
|
190
|
-
region: actual_region,
|
|
191
|
-
credentials: context.config.credentials
|
|
192
|
-
)
|
|
128
|
+
|
|
129
|
+
signer = Aws::Plugins::Sign.signer_for(
|
|
130
|
+
context[:auth_scheme],
|
|
131
|
+
context.config,
|
|
132
|
+
actual_region
|
|
193
133
|
)
|
|
134
|
+
|
|
135
|
+
signer.sign(context)
|
|
194
136
|
end
|
|
195
137
|
|
|
196
138
|
def region_from_body(body)
|
|
@@ -216,33 +158,22 @@ module Aws
|
|
|
216
158
|
end
|
|
217
159
|
|
|
218
160
|
class << self
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
credentials_provider: options[:credentials],
|
|
227
|
-
signing_algorithm: options.fetch(:signing_algorithm, :sigv4),
|
|
228
|
-
uri_escape_path: false,
|
|
229
|
-
unsigned_headers: ['content-length', 'x-amzn-trace-id']
|
|
230
|
-
)
|
|
161
|
+
def new_hostname(context, region)
|
|
162
|
+
endpoint_params = context[:endpoint_params].dup
|
|
163
|
+
endpoint_params.region = region
|
|
164
|
+
endpoint_params.endpoint = nil
|
|
165
|
+
endpoint =
|
|
166
|
+
context.config.endpoint_provider.resolve_endpoint(endpoint_params)
|
|
167
|
+
URI(endpoint.url).host
|
|
231
168
|
end
|
|
232
169
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
Aws::Partitions::EndpointProvider.resolve(region, 's3')
|
|
238
|
-
)
|
|
170
|
+
def custom_endpoint?(context)
|
|
171
|
+
region = context.config.region
|
|
172
|
+
partition = Aws::Endpoints::Matchers.aws_partition(region)
|
|
173
|
+
endpoint = context.http_request.endpoint
|
|
239
174
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
ARN.resolve_url!(uri, arn[:arn], region).host
|
|
243
|
-
else
|
|
244
|
-
"#{context.params[:bucket]}.#{uri.host}"
|
|
245
|
-
end
|
|
175
|
+
!endpoint.hostname.include?(partition['dnsSuffix']) &&
|
|
176
|
+
!endpoint.hostname.include?(partition['dualStackDnsSuffix'])
|
|
246
177
|
end
|
|
247
178
|
end
|
|
248
179
|
end
|