aws-sdk-s3 1.79.1 → 1.212.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 +1548 -0
- data/LICENSE.txt +202 -0
- data/VERSION +1 -0
- 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 +900 -98
- data/lib/aws-sdk-s3/bucket_acl.rb +44 -10
- data/lib/aws-sdk-s3/bucket_cors.rb +51 -11
- data/lib/aws-sdk-s3/bucket_lifecycle.rb +53 -8
- data/lib/aws-sdk-s3/bucket_lifecycle_configuration.rb +107 -9
- data/lib/aws-sdk-s3/bucket_logging.rb +43 -6
- data/lib/aws-sdk-s3/bucket_notification.rb +32 -9
- data/lib/aws-sdk-s3/bucket_policy.rb +90 -6
- data/lib/aws-sdk-s3/bucket_region_cache.rb +9 -5
- data/lib/aws-sdk-s3/bucket_request_payment.rb +38 -8
- data/lib/aws-sdk-s3/bucket_tagging.rb +46 -7
- data/lib/aws-sdk-s3/bucket_versioning.rb +127 -9
- data/lib/aws-sdk-s3/bucket_website.rb +46 -7
- data/lib/aws-sdk-s3/client.rb +13729 -3146
- data/lib/aws-sdk-s3/client_api.rb +1604 -277
- data/lib/aws-sdk-s3/customizations/bucket.rb +31 -47
- data/lib/aws-sdk-s3/customizations/errors.rb +40 -0
- data/lib/aws-sdk-s3/customizations/object.rb +253 -82
- 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 +28 -29
- data/lib/aws-sdk-s3/default_executor.rb +103 -0
- data/lib/aws-sdk-s3/encryption/client.rb +9 -5
- data/lib/aws-sdk-s3/encryption/decrypt_handler.rb +0 -4
- data/lib/aws-sdk-s3/encryption/default_cipher_provider.rb +2 -0
- data/lib/aws-sdk-s3/encryption/encrypt_handler.rb +2 -0
- data/lib/aws-sdk-s3/encryption/kms_cipher_provider.rb +15 -9
- data/lib/aws-sdk-s3/encryptionV2/client.rb +105 -26
- data/lib/aws-sdk-s3/encryptionV2/decrypt_handler.rb +7 -165
- data/lib/aws-sdk-s3/encryptionV2/decryption.rb +205 -0
- data/lib/aws-sdk-s3/encryptionV2/default_cipher_provider.rb +20 -3
- data/lib/aws-sdk-s3/encryptionV2/encrypt_handler.rb +2 -4
- data/lib/aws-sdk-s3/encryptionV2/io_encrypter.rb +2 -0
- data/lib/aws-sdk-s3/encryptionV2/kms_cipher_provider.rb +18 -6
- data/lib/aws-sdk-s3/encryptionV2/utils.rb +5 -0
- data/lib/aws-sdk-s3/encryptionV3/client.rb +885 -0
- data/lib/aws-sdk-s3/encryptionV3/decrypt_handler.rb +98 -0
- data/lib/aws-sdk-s3/encryptionV3/decryption.rb +244 -0
- data/lib/aws-sdk-s3/encryptionV3/default_cipher_provider.rb +159 -0
- data/lib/aws-sdk-s3/encryptionV3/default_key_provider.rb +35 -0
- data/lib/aws-sdk-s3/encryptionV3/encrypt_handler.rb +98 -0
- data/lib/aws-sdk-s3/encryptionV3/errors.rb +47 -0
- data/lib/aws-sdk-s3/encryptionV3/io_auth_decrypter.rb +60 -0
- data/lib/aws-sdk-s3/encryptionV3/io_decrypter.rb +35 -0
- data/lib/aws-sdk-s3/encryptionV3/io_encrypter.rb +84 -0
- data/lib/aws-sdk-s3/encryptionV3/key_provider.rb +28 -0
- data/lib/aws-sdk-s3/encryptionV3/kms_cipher_provider.rb +159 -0
- data/lib/aws-sdk-s3/encryptionV3/materials.rb +58 -0
- data/lib/aws-sdk-s3/encryptionV3/utils.rb +321 -0
- data/lib/aws-sdk-s3/encryption_v2.rb +1 -0
- data/lib/aws-sdk-s3/encryption_v3.rb +24 -0
- data/lib/aws-sdk-s3/endpoint_parameters.rb +181 -0
- data/lib/aws-sdk-s3/endpoint_provider.rb +889 -0
- data/lib/aws-sdk-s3/endpoints.rb +1544 -0
- data/lib/aws-sdk-s3/errors.rb +80 -1
- data/lib/aws-sdk-s3/event_streams.rb +1 -1
- 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 +258 -82
- data/lib/aws-sdk-s3/file_uploader.rb +25 -14
- data/lib/aws-sdk-s3/legacy_signer.rb +17 -26
- data/lib/aws-sdk-s3/multipart_download_error.rb +8 -0
- data/lib/aws-sdk-s3/multipart_file_uploader.rb +111 -86
- data/lib/aws-sdk-s3/multipart_stream_uploader.rb +110 -92
- data/lib/aws-sdk-s3/multipart_upload.rb +304 -14
- data/lib/aws-sdk-s3/multipart_upload_error.rb +3 -4
- data/lib/aws-sdk-s3/multipart_upload_part.rb +344 -20
- data/lib/aws-sdk-s3/object.rb +2457 -225
- data/lib/aws-sdk-s3/object_acl.rb +76 -15
- 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 +2033 -169
- data/lib/aws-sdk-s3/object_version.rb +470 -53
- data/lib/aws-sdk-s3/plugins/accelerate.rb +1 -39
- data/lib/aws-sdk-s3/plugins/access_grants.rb +178 -0
- data/lib/aws-sdk-s3/plugins/arn.rb +70 -0
- data/lib/aws-sdk-s3/plugins/bucket_dns.rb +3 -41
- data/lib/aws-sdk-s3/plugins/bucket_name_restrictions.rb +1 -6
- data/lib/aws-sdk-s3/plugins/checksum_algorithm.rb +44 -0
- data/lib/aws-sdk-s3/plugins/dualstack.rb +2 -49
- data/lib/aws-sdk-s3/plugins/endpoints.rb +86 -0
- data/lib/aws-sdk-s3/plugins/expect_100_continue.rb +3 -1
- data/lib/aws-sdk-s3/plugins/express_session_auth.rb +88 -0
- data/lib/aws-sdk-s3/plugins/get_bucket_location_fix.rb +1 -1
- data/lib/aws-sdk-s3/plugins/http_200_errors.rb +87 -26
- data/lib/aws-sdk-s3/plugins/iad_regional_endpoint.rb +8 -26
- 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 +48 -88
- 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 +50 -42
- data/lib/aws-sdk-s3/resource.rb +144 -15
- data/lib/aws-sdk-s3/transfer_manager.rb +321 -0
- data/lib/aws-sdk-s3/types.rb +12223 -4723
- data/lib/aws-sdk-s3/waiters.rb +1 -1
- data/lib/aws-sdk-s3.rb +37 -28
- 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 +2612 -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 +2899 -0
- data/sig/waiters.rbs +95 -0
- metadata +74 -16
- data/lib/aws-sdk-s3/plugins/bucket_arn.rb +0 -212
|
@@ -23,20 +23,16 @@ each bucket. [Go here for more information](http://docs.aws.amazon.com/AmazonS3/
|
|
|
23
23
|
operations = config.api.operation_names - [
|
|
24
24
|
:create_bucket, :list_buckets, :delete_bucket
|
|
25
25
|
]
|
|
26
|
-
# Need 2 handlers so that the context can be set for other plugins
|
|
27
|
-
# and to remove :use_accelerate_endpoint from the params.
|
|
28
26
|
handlers.add(
|
|
29
27
|
OptionHandler, step: :initialize, operations: operations
|
|
30
28
|
)
|
|
31
|
-
handlers.add(
|
|
32
|
-
AccelerateHandler, step: :build, priority: 0, operations: operations
|
|
33
|
-
)
|
|
34
29
|
end
|
|
35
30
|
|
|
36
31
|
# @api private
|
|
37
32
|
class OptionHandler < Seahorse::Client::Handler
|
|
38
33
|
def call(context)
|
|
39
34
|
# Support client configuration and per-operation configuration
|
|
35
|
+
# TODO: move this to an options hash and warn here.
|
|
40
36
|
if context.params.is_a?(Hash)
|
|
41
37
|
accelerate = context.params.delete(:use_accelerate_endpoint)
|
|
42
38
|
end
|
|
@@ -47,40 +43,6 @@ each bucket. [Go here for more information](http://docs.aws.amazon.com/AmazonS3/
|
|
|
47
43
|
@handler.call(context)
|
|
48
44
|
end
|
|
49
45
|
end
|
|
50
|
-
|
|
51
|
-
# @api private
|
|
52
|
-
class AccelerateHandler < Seahorse::Client::Handler
|
|
53
|
-
def call(context)
|
|
54
|
-
if context[:use_accelerate_endpoint]
|
|
55
|
-
dualstack = !!context[:use_dualstack_endpoint]
|
|
56
|
-
use_accelerate_endpoint(context, dualstack)
|
|
57
|
-
end
|
|
58
|
-
@handler.call(context)
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
private
|
|
62
|
-
|
|
63
|
-
def use_accelerate_endpoint(context, dualstack)
|
|
64
|
-
bucket_name = context.params[:bucket]
|
|
65
|
-
validate_bucket_name!(bucket_name)
|
|
66
|
-
endpoint = URI.parse(context.http_request.endpoint.to_s)
|
|
67
|
-
endpoint.scheme = 'https'
|
|
68
|
-
endpoint.port = 443
|
|
69
|
-
endpoint.host = "#{bucket_name}.s3-accelerate"\
|
|
70
|
-
"#{'.dualstack' if dualstack}.amazonaws.com"
|
|
71
|
-
context.http_request.endpoint = endpoint.to_s
|
|
72
|
-
# s3 accelerate endpoint doesn't work with 'expect' header
|
|
73
|
-
context.http_request.headers.delete('expect')
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def validate_bucket_name!(bucket_name)
|
|
77
|
-
unless BucketDns.dns_compatible?(bucket_name, _ssl = true)
|
|
78
|
-
raise ArgumentError,
|
|
79
|
-
'Unable to use `use_accelerate_endpoint: true` on buckets '\
|
|
80
|
-
'with non-DNS compatible names.'
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
46
|
end
|
|
85
47
|
end
|
|
86
48
|
end
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Aws
|
|
4
|
+
module S3
|
|
5
|
+
module Plugins
|
|
6
|
+
# @api private
|
|
7
|
+
class AccessGrants < Seahorse::Client::Plugin
|
|
8
|
+
@s3control =
|
|
9
|
+
begin
|
|
10
|
+
require 'aws-sdk-s3control'
|
|
11
|
+
true
|
|
12
|
+
rescue LoadError
|
|
13
|
+
false
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
option(
|
|
17
|
+
:access_grants,
|
|
18
|
+
default: false,
|
|
19
|
+
doc_type: 'Boolean',
|
|
20
|
+
docstring: <<-DOCS)
|
|
21
|
+
When `true`, the S3 client will use the S3 Access Grants feature to
|
|
22
|
+
authenticate requests. Bucket credentials will be fetched from S3
|
|
23
|
+
Control using the `get_data_access` API.
|
|
24
|
+
DOCS
|
|
25
|
+
|
|
26
|
+
option(:access_grants_credentials_provider,
|
|
27
|
+
doc_type: 'Aws::S3::AccessGrantsCredentialsProvider',
|
|
28
|
+
rbs_type: 'untyped',
|
|
29
|
+
docstring: <<-DOCS) do |_cfg|
|
|
30
|
+
When `access_grants` is `true`, this option can be used to provide
|
|
31
|
+
additional options to the credentials provider, including a privilege
|
|
32
|
+
setting, caching, and fallback behavior.
|
|
33
|
+
DOCS
|
|
34
|
+
Aws::S3::AccessGrantsCredentialsProvider.new
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# @api private
|
|
38
|
+
class Handler < Seahorse::Client::Handler
|
|
39
|
+
PERMISSION_MAP = {
|
|
40
|
+
head_object: 'READ',
|
|
41
|
+
get_object: 'READ',
|
|
42
|
+
get_object_acl: 'READ',
|
|
43
|
+
list_multipart_uploads: 'READ',
|
|
44
|
+
list_objects_v2: 'READ',
|
|
45
|
+
list_object_versions: 'READ',
|
|
46
|
+
list_parts: 'READ',
|
|
47
|
+
head_bucket: 'READ',
|
|
48
|
+
get_object_attributes: 'READ',
|
|
49
|
+
put_object: 'WRITE',
|
|
50
|
+
put_object_acl: 'WRITE',
|
|
51
|
+
delete_object: 'WRITE',
|
|
52
|
+
abort_multipart_upload: 'WRITE',
|
|
53
|
+
create_multipart_upload: 'WRITE',
|
|
54
|
+
upload_part: 'WRITE',
|
|
55
|
+
complete_multipart_upload: 'WRITE',
|
|
56
|
+
delete_objects: 'WRITE',
|
|
57
|
+
copy_object: 'READWRITE'
|
|
58
|
+
}.freeze
|
|
59
|
+
|
|
60
|
+
def call(context)
|
|
61
|
+
provider = context.config.access_grants_credentials_provider
|
|
62
|
+
|
|
63
|
+
if access_grants_operation?(context) &&
|
|
64
|
+
!s3_express_endpoint?(context) &&
|
|
65
|
+
!credentials_head_bucket_call?(provider)
|
|
66
|
+
params = context[:endpoint_params]
|
|
67
|
+
permission = PERMISSION_MAP[context.operation_name]
|
|
68
|
+
|
|
69
|
+
key =
|
|
70
|
+
case context.operation_name
|
|
71
|
+
when :delete_objects
|
|
72
|
+
delete_params = context.params[:delete]
|
|
73
|
+
common_prefixes(delete_params[:objects].map { |o| o[:key] })
|
|
74
|
+
when :copy_object
|
|
75
|
+
source_bucket, source_key = params[:copy_source].split('/', 2)
|
|
76
|
+
if params[:bucket] != source_bucket
|
|
77
|
+
raise ArgumentError,
|
|
78
|
+
'source and destination bucket must be the same'
|
|
79
|
+
end
|
|
80
|
+
common_prefixes([params[:key], source_key])
|
|
81
|
+
else
|
|
82
|
+
params[:key]
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
credentials = provider.access_grants_credentials_for(
|
|
86
|
+
bucket: params[:bucket],
|
|
87
|
+
key: key,
|
|
88
|
+
prefix: params[:prefix],
|
|
89
|
+
permission: permission
|
|
90
|
+
)
|
|
91
|
+
context[:sigv4_credentials] = credentials # Sign will use this
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
with_metric(credentials) { @handler.call(context) }
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
private
|
|
98
|
+
|
|
99
|
+
def with_metric(credentials, &block)
|
|
100
|
+
return block.call unless credentials
|
|
101
|
+
|
|
102
|
+
Aws::Plugins::UserAgent.metric('S3_ACCESS_GRANTS', &block)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# HeadBucket is a supported call. When fetching credentials,
|
|
106
|
+
# this plugin is executed again, and becomes recursive.
|
|
107
|
+
def credentials_head_bucket_call?(provider)
|
|
108
|
+
provider.instance_variable_get(:@head_bucket_call)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def access_grants_operation?(context)
|
|
112
|
+
params = context[:endpoint_params]
|
|
113
|
+
params[:bucket] && PERMISSION_MAP[context.operation_name]
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def s3_express_endpoint?(context)
|
|
117
|
+
context[:endpoint_properties]['backend'] == 'S3Express'
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Return the common prefix of the keys, regardless of the delimiter.
|
|
121
|
+
# For example, given keys ['foo/bar', 'foo/baz'], the common prefix
|
|
122
|
+
# is 'foo/ba'.
|
|
123
|
+
def common_prefixes(keys)
|
|
124
|
+
return '' if keys.empty?
|
|
125
|
+
|
|
126
|
+
first_key = keys[0]
|
|
127
|
+
common_ancestor = first_key
|
|
128
|
+
last_prefix = ''
|
|
129
|
+
keys.each do |k|
|
|
130
|
+
until common_ancestor.empty?
|
|
131
|
+
break if k.start_with?(common_ancestor)
|
|
132
|
+
|
|
133
|
+
last_index = common_ancestor.rindex('/')
|
|
134
|
+
return '' if last_index.nil?
|
|
135
|
+
|
|
136
|
+
last_prefix = common_ancestor[(last_index + 1)..-1]
|
|
137
|
+
common_ancestor = common_ancestor[0...last_index]
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
new_common_ancestor = "#{common_ancestor}/#{last_prefix}"
|
|
141
|
+
keys.each do |k|
|
|
142
|
+
until last_prefix.empty?
|
|
143
|
+
break if k.start_with?(new_common_ancestor)
|
|
144
|
+
|
|
145
|
+
last_prefix = last_prefix[0...-1]
|
|
146
|
+
new_common_ancestor = "#{common_ancestor}/#{last_prefix}"
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
if new_common_ancestor == "#{first_key}/"
|
|
150
|
+
first_key
|
|
151
|
+
else
|
|
152
|
+
new_common_ancestor
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def add_handlers(handlers, config)
|
|
158
|
+
return unless AccessGrants.s3control? && config.access_grants
|
|
159
|
+
|
|
160
|
+
handlers.add(Handler)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def after_initialize(client)
|
|
164
|
+
return unless AccessGrants.s3control? && client.config.access_grants
|
|
165
|
+
|
|
166
|
+
provider = client.config.access_grants_credentials_provider
|
|
167
|
+
provider.s3_client = client unless provider.s3_client
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
class << self
|
|
171
|
+
def s3control?
|
|
172
|
+
@s3control
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Aws
|
|
4
|
+
module S3
|
|
5
|
+
module Plugins
|
|
6
|
+
# When an accesspoint ARN is provided for :bucket in S3 operations, this
|
|
7
|
+
# plugin resolves the request endpoint from the ARN when possible.
|
|
8
|
+
# @api private
|
|
9
|
+
class ARN < Seahorse::Client::Plugin
|
|
10
|
+
option(
|
|
11
|
+
:s3_use_arn_region,
|
|
12
|
+
default: true,
|
|
13
|
+
doc_type: 'Boolean',
|
|
14
|
+
docstring: <<-DOCS) do |cfg|
|
|
15
|
+
For S3 ARNs passed into the `:bucket` parameter, this option will
|
|
16
|
+
use the region in the ARN, allowing for cross-region requests to
|
|
17
|
+
be made. Set to `false` to use the client's region instead.
|
|
18
|
+
DOCS
|
|
19
|
+
resolve_s3_use_arn_region(cfg)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
option(
|
|
23
|
+
:s3_disable_multiregion_access_points,
|
|
24
|
+
default: false,
|
|
25
|
+
doc_type: 'Boolean',
|
|
26
|
+
docstring: <<-DOCS) do |cfg|
|
|
27
|
+
When set to `false` this will option will raise errors when multi-region
|
|
28
|
+
access point ARNs are used. Multi-region access points can potentially
|
|
29
|
+
result in cross region requests.
|
|
30
|
+
DOCS
|
|
31
|
+
resolve_s3_disable_multiregion_access_points(cfg)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
class << self
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def resolve_s3_use_arn_region(cfg)
|
|
38
|
+
value = ENV['AWS_S3_USE_ARN_REGION'] ||
|
|
39
|
+
Aws.shared_config.s3_use_arn_region(profile: cfg.profile) ||
|
|
40
|
+
'true'
|
|
41
|
+
value = Aws::Util.str_2_bool(value)
|
|
42
|
+
# Raise if provided value is not true or false
|
|
43
|
+
if value.nil?
|
|
44
|
+
raise ArgumentError,
|
|
45
|
+
'Must provide either `true` or `false` for the '\
|
|
46
|
+
'`s3_use_arn_region` profile option or for '\
|
|
47
|
+
"ENV['AWS_S3_USE_ARN_REGION']."
|
|
48
|
+
end
|
|
49
|
+
value
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def resolve_s3_disable_multiregion_access_points(cfg)
|
|
53
|
+
value = ENV['AWS_S3_DISABLE_MULTIREGION_ACCESS_POINTS'] ||
|
|
54
|
+
Aws.shared_config.s3_disable_multiregion_access_points(profile: cfg.profile) ||
|
|
55
|
+
'false'
|
|
56
|
+
value = Aws::Util.str_2_bool(value)
|
|
57
|
+
# Raise if provided value is not true or false
|
|
58
|
+
if value.nil?
|
|
59
|
+
raise ArgumentError,
|
|
60
|
+
'Must provide either `true` or `false` for '\
|
|
61
|
+
's3_use_arn_region profile option or for '\
|
|
62
|
+
"ENV['AWS_S3_USE_ARN_REGION']"
|
|
63
|
+
end
|
|
64
|
+
value
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -23,45 +23,10 @@ When set to `true`, the bucket name is always left in the
|
|
|
23
23
|
request URI and never moved to the host as a sub-domain.
|
|
24
24
|
DOCS
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
# @api private
|
|
31
|
-
class Handler < Seahorse::Client::Handler
|
|
32
|
-
|
|
33
|
-
def call(context)
|
|
34
|
-
move_dns_compat_bucket_to_subdomain(context)
|
|
35
|
-
@handler.call(context)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
private
|
|
39
|
-
|
|
40
|
-
def move_dns_compat_bucket_to_subdomain(context)
|
|
41
|
-
bucket_name = context.params[:bucket]
|
|
42
|
-
endpoint = context.http_request.endpoint
|
|
43
|
-
if bucket_name &&
|
|
44
|
-
BucketDns.dns_compatible?(bucket_name, https?(endpoint)) &&
|
|
45
|
-
context.operation_name.to_s != 'get_bucket_location'
|
|
46
|
-
move_bucket_to_subdomain(bucket_name, endpoint)
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def move_bucket_to_subdomain(bucket_name, endpoint)
|
|
51
|
-
endpoint.host = "#{bucket_name}.#{endpoint.host}"
|
|
52
|
-
path = endpoint.path.sub("/#{bucket_name}", '')
|
|
53
|
-
path = "/#{path}" unless path.match(/^\//)
|
|
54
|
-
endpoint.path = path
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def https?(uri)
|
|
58
|
-
uri.scheme == 'https'
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
end
|
|
62
|
-
|
|
26
|
+
# These class methods were originally used in a handler in this plugin.
|
|
27
|
+
# SigV2 legacy signer needs this logic so we keep it here as utility.
|
|
28
|
+
# New endpoint resolution will check this as a matcher.
|
|
63
29
|
class << self
|
|
64
|
-
|
|
65
30
|
# @param [String] bucket_name
|
|
66
31
|
# @param [Boolean] ssl
|
|
67
32
|
# @return [Boolean]
|
|
@@ -73,8 +38,6 @@ request URI and never moved to the host as a sub-domain.
|
|
|
73
38
|
end
|
|
74
39
|
end
|
|
75
40
|
|
|
76
|
-
# Checks for a valid RFC-3986 host name
|
|
77
|
-
# @see https://tools.ietf.org/html/rfc3986#section-3.2.2
|
|
78
41
|
# @param [String] bucket_name
|
|
79
42
|
# @return [Boolean]
|
|
80
43
|
def valid_subdomain?(bucket_name)
|
|
@@ -83,7 +46,6 @@ request URI and never moved to the host as a sub-domain.
|
|
|
83
46
|
bucket_name !~ /(\d+\.){3}\d+/ &&
|
|
84
47
|
bucket_name !~ /[.-]{2}/
|
|
85
48
|
end
|
|
86
|
-
|
|
87
49
|
end
|
|
88
50
|
end
|
|
89
51
|
end
|
|
@@ -13,12 +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
|
-
|
|
17
|
-
bucket,
|
|
18
|
-
context.config.region,
|
|
19
|
-
context.config.s3_use_arn_region
|
|
20
|
-
)
|
|
21
|
-
if !arn && bucket.include?('/')
|
|
16
|
+
if !Aws::ARNParser.arn?(bucket) && bucket.include?('/')
|
|
22
17
|
raise ArgumentError,
|
|
23
18
|
'bucket name must not contain a forward-slash (/)'
|
|
24
19
|
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Aws
|
|
4
|
+
module S3
|
|
5
|
+
module Plugins
|
|
6
|
+
# @api private
|
|
7
|
+
class ChecksumAlgorithm < Seahorse::Client::Plugin
|
|
8
|
+
|
|
9
|
+
# S3 GetObject results for whole Multipart Objects contain a checksum
|
|
10
|
+
# that cannot be validated. These should be skipped by the
|
|
11
|
+
# ChecksumAlgorithm plugin.
|
|
12
|
+
class SkipWholeMultipartGetChecksumsHandler < Seahorse::Client::Handler
|
|
13
|
+
def call(context)
|
|
14
|
+
context[:http_checksum] ||= {}
|
|
15
|
+
context[:http_checksum][:skip_on_suffix] = true
|
|
16
|
+
|
|
17
|
+
@handler.call(context)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Handler to disable trailer checksums for S3-compatible services
|
|
22
|
+
# that don't support STREAMING-UNSIGNED-PAYLOAD-TRAILER
|
|
23
|
+
# See: https://github.com/aws/aws-sdk-ruby/issues/3338
|
|
24
|
+
class SkipTrailerChecksumsHandler < Seahorse::Client::Handler
|
|
25
|
+
def call(context)
|
|
26
|
+
context[:skip_trailer_checksums] = true if custom_endpoint?(context.config)
|
|
27
|
+
@handler.call(context)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def custom_endpoint?(config)
|
|
33
|
+
!config.regional_endpoint || !config.endpoint_provider.instance_of?(Aws::S3::EndpointProvider)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def add_handlers(handlers, _config)
|
|
38
|
+
handlers.add(SkipWholeMultipartGetChecksumsHandler, step: :initialize, operations: [:get_object])
|
|
39
|
+
handlers.add(SkipTrailerChecksumsHandler, step: :build, priority: 16, operations: %i[put_object upload_part])
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -5,23 +5,14 @@ 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
|
-
def add_handlers(handlers, config)
|
|
8
|
+
def add_handlers(handlers, _config)
|
|
18
9
|
handlers.add(OptionHandler, step: :initialize)
|
|
19
|
-
handlers.add(DualstackHandler, step: :build, priority: 0)
|
|
20
10
|
end
|
|
21
11
|
|
|
22
12
|
# @api private
|
|
23
13
|
class OptionHandler < Seahorse::Client::Handler
|
|
24
14
|
def call(context)
|
|
15
|
+
# Support client configuration and per-operation configuration
|
|
25
16
|
if context.params.is_a?(Hash)
|
|
26
17
|
dualstack = context.params.delete(:use_dualstack_endpoint)
|
|
27
18
|
end
|
|
@@ -30,44 +21,6 @@ for all operations.
|
|
|
30
21
|
@handler.call(context)
|
|
31
22
|
end
|
|
32
23
|
end
|
|
33
|
-
|
|
34
|
-
# @api private
|
|
35
|
-
class DualstackHandler < Seahorse::Client::Handler
|
|
36
|
-
def call(context)
|
|
37
|
-
apply_dualstack_endpoint(context) if use_dualstack_endpoint?(context)
|
|
38
|
-
@handler.call(context)
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
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
|
-
|
|
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
|
|
53
|
-
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
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def use_dualstack_endpoint?(context)
|
|
67
|
-
context[:use_dualstack_endpoint] && !context[:use_accelerate_endpoint]
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
|
|
71
24
|
end
|
|
72
25
|
end
|
|
73
26
|
end
|
|
@@ -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
|
|
@@ -15,7 +15,9 @@ module Aws
|
|
|
15
15
|
class Handler < Seahorse::Client::Handler
|
|
16
16
|
|
|
17
17
|
def call(context)
|
|
18
|
-
|
|
18
|
+
body = context.http_request.body
|
|
19
|
+
if body.respond_to?(:size) && body.size > 0 &&
|
|
20
|
+
!context[:use_accelerate_endpoint]
|
|
19
21
|
context.http_request.headers['expect'] = '100-continue'
|
|
20
22
|
end
|
|
21
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
|