aws-sdk-core 2.0.9 → 2.0.10
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/apis/EC2.waiters.json +2 -2
- data/apis/KMS.paginators.json +6 -6
- data/apis/Lambda.api.json +1 -1
- data/apis/Redshift.api.json +401 -26
- data/apis/S3.api.json +8 -17
- data/lib/aws-sdk-core.rb +1 -1
- data/lib/aws-sdk-core/api/service_customizations.rb +1 -1
- data/lib/aws-sdk-core/configservice.rb +1 -0
- data/lib/aws-sdk-core/lambda.rb +1 -0
- data/lib/aws-sdk-core/plugins/global_configuration.rb +1 -1
- data/lib/aws-sdk-core/plugins/request_signer.rb +8 -5
- data/lib/aws-sdk-core/plugins/s3_bucket_dns.rb +2 -1
- data/lib/aws-sdk-core/plugins/s3_request_signer.rb +241 -0
- data/lib/aws-sdk-core/signers/s3.rb +5 -3
- data/lib/aws-sdk-core/signers/v4.rb +1 -1
- data/lib/aws-sdk-core/version.rb +1 -1
- metadata +3 -3
- data/lib/aws-sdk-core/plugins/s3_region_detection.rb +0 -144
data/apis/S3.api.json
CHANGED
|
@@ -6,18 +6,6 @@
|
|
|
6
6
|
"globalEndpoint":"s3.amazonaws.com",
|
|
7
7
|
"serviceAbbreviation":"Amazon S3",
|
|
8
8
|
"serviceFullName":"Amazon Simple Storage Service",
|
|
9
|
-
"signatureVersion":"v4",
|
|
10
|
-
"sigv2Regions": [
|
|
11
|
-
"us-east-1",
|
|
12
|
-
"us-west-1",
|
|
13
|
-
"us-west-2",
|
|
14
|
-
"ap-northeast-1",
|
|
15
|
-
"ap-southeast-1",
|
|
16
|
-
"ap-southeast-2",
|
|
17
|
-
"sa-east-1",
|
|
18
|
-
"eu-west-1",
|
|
19
|
-
"us-gov-west-1"
|
|
20
|
-
],
|
|
21
9
|
"timestampFormat":"rfc822",
|
|
22
10
|
"protocol":"rest-xml"
|
|
23
11
|
},
|
|
@@ -650,7 +638,8 @@
|
|
|
650
638
|
"ap-northeast-1",
|
|
651
639
|
"sa-east-1",
|
|
652
640
|
"",
|
|
653
|
-
"cn-north-1"
|
|
641
|
+
"cn-north-1",
|
|
642
|
+
"eu-central-1"
|
|
654
643
|
]
|
|
655
644
|
},
|
|
656
645
|
"BucketLoggingStatus":{
|
|
@@ -2038,7 +2027,11 @@
|
|
|
2038
2027
|
"DisplayName":{"shape":"DisplayName"},
|
|
2039
2028
|
"EmailAddress":{"shape":"EmailAddress"},
|
|
2040
2029
|
"ID":{"shape":"ID"},
|
|
2041
|
-
"Type":{
|
|
2030
|
+
"Type":{
|
|
2031
|
+
"shape":"Type",
|
|
2032
|
+
"xmlAttribute":true,
|
|
2033
|
+
"locationName":"xsi:type"
|
|
2034
|
+
},
|
|
2042
2035
|
"URI":{"shape":"URI"}
|
|
2043
2036
|
},
|
|
2044
2037
|
"xmlNamespace":{
|
|
@@ -3490,9 +3483,7 @@
|
|
|
3490
3483
|
"CanonicalUser",
|
|
3491
3484
|
"AmazonCustomerByEmail",
|
|
3492
3485
|
"Group"
|
|
3493
|
-
]
|
|
3494
|
-
"xmlAttribute":true,
|
|
3495
|
-
"locationName":"xsi:type"
|
|
3486
|
+
]
|
|
3496
3487
|
},
|
|
3497
3488
|
"URI":{"type":"string"},
|
|
3498
3489
|
"UploadIdMarker":{"type":"string"},
|
data/lib/aws-sdk-core.rb
CHANGED
|
@@ -140,7 +140,7 @@ module Aws
|
|
|
140
140
|
autoload :S3LocationConstraint, 'aws-sdk-core/plugins/s3_location_constraint'
|
|
141
141
|
autoload :S3Md5s, 'aws-sdk-core/plugins/s3_md5s'
|
|
142
142
|
autoload :S3Redirects, 'aws-sdk-core/plugins/s3_redirects'
|
|
143
|
-
autoload :
|
|
143
|
+
autoload :S3RequestSigner, 'aws-sdk-core/plugins/s3_request_signer'
|
|
144
144
|
autoload :S3SseCpk, 'aws-sdk-core/plugins/s3_sse_cpk'
|
|
145
145
|
autoload :S3UrlEncodedKeys, 'aws-sdk-core/plugins/s3_url_encoded_keys'
|
|
146
146
|
autoload :SQSQueueUrls, 'aws-sdk-core/plugins/sqs_queue_urls'
|
|
@@ -102,7 +102,7 @@ module Aws
|
|
|
102
102
|
add_plugin 'Aws::Plugins::S3Redirects'
|
|
103
103
|
add_plugin 'Aws::Plugins::S3SseCpk'
|
|
104
104
|
add_plugin 'Aws::Plugins::S3UrlEncodedKeys'
|
|
105
|
-
add_plugin 'Aws::Plugins::
|
|
105
|
+
add_plugin 'Aws::Plugins::S3RequestSigner'
|
|
106
106
|
defs = client_class.waiters.instance_variable_get("@definitions")
|
|
107
107
|
defs[:bucket_exists]['ignore_errors'] = ['NotFound']
|
|
108
108
|
defs[:object_exists]['ignore_errors'] = ['NotFound']
|
data/lib/aws-sdk-core/lambda.rb
CHANGED
|
@@ -49,8 +49,9 @@ module Aws
|
|
|
49
49
|
|
|
50
50
|
option(:sigv4_region) do |cfg|
|
|
51
51
|
prefix = cfg.api.metadata('endpointPrefix')
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
endpoint = cfg.endpoint.to_s
|
|
53
|
+
if matches = endpoint.match(/#{prefix}[.-](.+)\.amazonaws\.com/)
|
|
54
|
+
matches[1] == 'us-gov' ? 'us-gov-west-1' : matches[1]
|
|
54
55
|
elsif cfg.endpoint.to_s.match(/#{prefix}\.amazonaws\.com/)
|
|
55
56
|
'us-east-1'
|
|
56
57
|
else
|
|
@@ -75,8 +76,7 @@ module Aws
|
|
|
75
76
|
private
|
|
76
77
|
|
|
77
78
|
def sign_authenticated_requests(context)
|
|
78
|
-
|
|
79
|
-
if signer = SIGNERS[version]
|
|
79
|
+
if signer = SIGNERS[context.config.signature_version]
|
|
80
80
|
require_credentials(context)
|
|
81
81
|
signer.sign(context)
|
|
82
82
|
end
|
|
@@ -94,7 +94,10 @@ module Aws
|
|
|
94
94
|
|
|
95
95
|
end
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
def add_handlers(handlers, config)
|
|
98
|
+
# See the S3RequestSignerPlugin for Amazon S3 signature logic
|
|
99
|
+
handlers.add(Handler, step: :sign) unless config.sigv4_name == 's3'
|
|
100
|
+
end
|
|
98
101
|
|
|
99
102
|
end
|
|
100
103
|
end
|
|
@@ -38,7 +38,8 @@ module Aws
|
|
|
38
38
|
endpoint = context.http_request.endpoint
|
|
39
39
|
if
|
|
40
40
|
bucket_name &&
|
|
41
|
-
S3BucketDns.dns_compatible?(bucket_name, https?(endpoint))
|
|
41
|
+
S3BucketDns.dns_compatible?(bucket_name, https?(endpoint)) &&
|
|
42
|
+
context.operation_name != 'get_bucket_location'
|
|
42
43
|
then
|
|
43
44
|
move_bucket_to_subdomain(bucket_name, endpoint)
|
|
44
45
|
end
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
require 'set'
|
|
2
|
+
|
|
3
|
+
module Aws
|
|
4
|
+
module Plugins
|
|
5
|
+
# This plugin is an implementation detail and may be modified.
|
|
6
|
+
# @api private
|
|
7
|
+
class S3RequestSigner < Seahorse::Client::Plugin
|
|
8
|
+
|
|
9
|
+
class SigningHandler < Seahorse::Client::Handler
|
|
10
|
+
|
|
11
|
+
# List of regions that support older S3 signature versions.
|
|
12
|
+
# All new regions only support signature version 4.
|
|
13
|
+
V2_REGIONS = Set.new(%w(
|
|
14
|
+
us-east-1
|
|
15
|
+
us-west-1
|
|
16
|
+
us-west-2
|
|
17
|
+
ap-northeast-1
|
|
18
|
+
ap-southeast-1
|
|
19
|
+
ap-southeast-2
|
|
20
|
+
sa-east-1
|
|
21
|
+
eu-west-1
|
|
22
|
+
us-gov-west-1
|
|
23
|
+
))
|
|
24
|
+
|
|
25
|
+
def call(context)
|
|
26
|
+
version = signature_version(context)
|
|
27
|
+
case version
|
|
28
|
+
when /v4/ then apply_v4_signature(context)
|
|
29
|
+
when /s3/ then apply_v2_signature(context)
|
|
30
|
+
else raise "unsupported signature version #{version.inspect}"
|
|
31
|
+
end
|
|
32
|
+
@handler.call(context)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def apply_v4_signature(context)
|
|
38
|
+
Signers::V4.new(
|
|
39
|
+
context.config.credentials, 's3',
|
|
40
|
+
context[:cached_sigv4_region] || context.config.sigv4_region,
|
|
41
|
+
).sign(context.http_request)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def apply_v2_signature(context)
|
|
45
|
+
Signers::S3.sign(context)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def signature_version(context)
|
|
49
|
+
context[:cached_signature_version] ||
|
|
50
|
+
context.config.signature_version ||
|
|
51
|
+
version_by_region(context)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def version_by_region(context)
|
|
55
|
+
if classic_endpoint?(context)
|
|
56
|
+
classic_sigv(context)
|
|
57
|
+
else
|
|
58
|
+
regional_sigv(context)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def classic_endpoint?(context)
|
|
63
|
+
context.config.region == 'us-east-1'
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# When accessing the classic endpoint, s3.amazonaws.com, we don't know
|
|
67
|
+
# the region name. This makes creating a version 4 signature difficult.
|
|
68
|
+
# Choose v4 only if using KMS encryptions, which requires v4.
|
|
69
|
+
def classic_sigv(context)
|
|
70
|
+
if kms_encrypted?(context)
|
|
71
|
+
:v4
|
|
72
|
+
else
|
|
73
|
+
:s3
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def regional_sigv(context)
|
|
78
|
+
# Drop back to older S3 signature version when uploading objects for
|
|
79
|
+
# better performance. This optimization may be removed at some point
|
|
80
|
+
# in favor of always using signature version 4.
|
|
81
|
+
if V2_REGIONS.include?(context.config.region)
|
|
82
|
+
uploading_file?(context) && !kms_encrypted?(context) ? :s3 : :v4
|
|
83
|
+
else
|
|
84
|
+
:v4
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def kms_encrypted?(context)
|
|
89
|
+
context.params[:server_side_encryption] == 'aws:kms'
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def uploading_file?(context)
|
|
93
|
+
%w(put_object upload_part).include?(context.operation_name) &&
|
|
94
|
+
context.http_request.body.size > 0
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Abstract base class for the other two handlers
|
|
100
|
+
class Handler < Seahorse::Client::Handler
|
|
101
|
+
|
|
102
|
+
private
|
|
103
|
+
|
|
104
|
+
def new_hostname(context, region)
|
|
105
|
+
bucket = context.params[:bucket]
|
|
106
|
+
if region == 'us-east-1'
|
|
107
|
+
"#{bucket}.s3-external-1.amazonaws.com"
|
|
108
|
+
else
|
|
109
|
+
bucket + '.' + URI.parse(EndpointProvider.resolve(region, 's3')).host
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# This handler will update the http endpoint when the bucket region
|
|
116
|
+
# is known/cached.
|
|
117
|
+
class CachedBucketRegionHandler < Handler
|
|
118
|
+
|
|
119
|
+
def call(context)
|
|
120
|
+
if bucket = context.params[:bucket]
|
|
121
|
+
use_regional_endpoint_when_known(context, bucket)
|
|
122
|
+
end
|
|
123
|
+
@handler.call(context)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
private
|
|
127
|
+
|
|
128
|
+
def use_regional_endpoint_when_known(context, bucket)
|
|
129
|
+
cached_region = S3::BUCKET_REGIONS[bucket]
|
|
130
|
+
if cached_region && cached_region != context.config.region
|
|
131
|
+
context.http_request.endpoint.host = new_hostname(context, cached_region)
|
|
132
|
+
context[:cached_sigv4_region] = cached_region
|
|
133
|
+
context[:cached_signature_version] = :v4
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# This handler detects when a request fails because signature version 4
|
|
140
|
+
# is required but not used. It follows up by making a request to
|
|
141
|
+
# determine the correct region, then finally a version 4 signed
|
|
142
|
+
# request against the regional endpoint.
|
|
143
|
+
class BucketSigningErrorHandler < Handler
|
|
144
|
+
|
|
145
|
+
SIGV4_MSG = /(Please use AWS4-HMAC-SHA256|AWS Signature Version 4)/
|
|
146
|
+
|
|
147
|
+
def call(context)
|
|
148
|
+
response = @handler.call(context)
|
|
149
|
+
handle_region_errors(response)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
private
|
|
153
|
+
|
|
154
|
+
def handle_region_errors(response)
|
|
155
|
+
if sigv4_required_error?(response)
|
|
156
|
+
detect_region_and_retry(response)
|
|
157
|
+
elsif wrong_sigv4_region?(response)
|
|
158
|
+
extract_body_region_and_retry(response.context)
|
|
159
|
+
else
|
|
160
|
+
response
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def sigv4_required_error?(resp)
|
|
165
|
+
resp.context.http_response.status_code == 400 &&
|
|
166
|
+
resp.context.http_response.body_contents.match(SIGV4_MSG) &&
|
|
167
|
+
resp.context.http_response.body.respond_to?(:truncate)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def wrong_sigv4_region?(resp)
|
|
171
|
+
resp.context.http_response.status_code == 400 &&
|
|
172
|
+
resp.context.http_response.body_contents.match(/<Region>.+?<\/Region>/)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def extract_body_region_and_retry(context)
|
|
176
|
+
actual_region = region_from_body(context)
|
|
177
|
+
updgrade_to_v4(context, actual_region)
|
|
178
|
+
log_warning(context, actual_region)
|
|
179
|
+
@handler.call(context)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def region_from_body(context)
|
|
183
|
+
context.http_response.body_contents.match(/<Region>(.+?)<\/Region>/)[1]
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def detect_region_and_retry(resp)
|
|
187
|
+
context = resp.context
|
|
188
|
+
updgrade_to_v4(context, 'us-east-1')
|
|
189
|
+
resp = @handler.call(context)
|
|
190
|
+
if resp.successful?
|
|
191
|
+
resp
|
|
192
|
+
else
|
|
193
|
+
actual_region = region_from_location_header(context)
|
|
194
|
+
updgrade_to_v4(context, actual_region)
|
|
195
|
+
log_warning(context, actual_region)
|
|
196
|
+
@handler.call(context)
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def updgrade_to_v4(context, region)
|
|
201
|
+
bucket = context.params[:bucket]
|
|
202
|
+
context.http_response.body.truncate(0)
|
|
203
|
+
context.http_request.headers.delete('authorization')
|
|
204
|
+
context.http_request.headers.delete('x-amz-security-token')
|
|
205
|
+
context.http_request.endpoint.host = new_hostname(context, region)
|
|
206
|
+
signer = Signers::V4.new(context.config.credentials, 's3', region)
|
|
207
|
+
signer.sign(context.http_request)
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def region_from_location_header(context)
|
|
211
|
+
location = context.http_response.headers['location']
|
|
212
|
+
location.match(/s3[.-](.+?)\.amazonaws\.com/)[1]
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def log_warning(context, actual_region)
|
|
216
|
+
S3::BUCKET_REGIONS[context.params[:bucket]] = actual_region
|
|
217
|
+
msg = "S3 client configured for #{context.config.region.inspect} " +
|
|
218
|
+
"but the bucket #{context.params[:bucket].inspect} is in " +
|
|
219
|
+
"#{actual_region.inspect}; Please configure the proper region " +
|
|
220
|
+
"to avoid multiple unecessary redirects and signing attempts\n"
|
|
221
|
+
if logger = context.config.logger
|
|
222
|
+
logger.warn(msg)
|
|
223
|
+
else
|
|
224
|
+
warn(msg)
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
# BEFORE signing
|
|
231
|
+
handle(CachedBucketRegionHandler, step: :sign, priority: 60)
|
|
232
|
+
|
|
233
|
+
# sign the request
|
|
234
|
+
handler(SigningHandler, step: :sign)
|
|
235
|
+
|
|
236
|
+
# AFTER signing
|
|
237
|
+
handle(BucketSigningErrorHandler, step: :sign, priority: 40)
|
|
238
|
+
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
end
|
|
@@ -123,11 +123,13 @@ module Aws
|
|
|
123
123
|
# virtual hosted-style requests require the hostname to appear
|
|
124
124
|
# in the canonicalized resource prefixed by a forward slash.
|
|
125
125
|
if bucket = params[:bucket]
|
|
126
|
+
bucket = bucket.value
|
|
126
127
|
ssl = endpoint.scheme == 'https'
|
|
127
|
-
if Plugins::S3BucketDns.dns_compatible?(bucket
|
|
128
|
-
!@force_path_style
|
|
128
|
+
if Plugins::S3BucketDns.dns_compatible?(bucket, ssl) &&
|
|
129
|
+
!@force_path_style &&
|
|
130
|
+
!endpoint.path.match(/^\/#{Regexp.escape(bucket)}/)
|
|
129
131
|
then
|
|
130
|
-
parts << "/#{bucket
|
|
132
|
+
parts << "/#{bucket}"
|
|
131
133
|
end
|
|
132
134
|
end
|
|
133
135
|
|
data/lib/aws-sdk-core/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: aws-sdk-core
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.0.
|
|
4
|
+
version: 2.0.10
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Amazon Web Services
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2014-11-
|
|
11
|
+
date: 2014-11-20 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: multi_json
|
|
@@ -157,7 +157,7 @@ files:
|
|
|
157
157
|
- lib/aws-sdk-core/plugins/s3_location_constraint.rb
|
|
158
158
|
- lib/aws-sdk-core/plugins/s3_md5s.rb
|
|
159
159
|
- lib/aws-sdk-core/plugins/s3_redirects.rb
|
|
160
|
-
- lib/aws-sdk-core/plugins/
|
|
160
|
+
- lib/aws-sdk-core/plugins/s3_request_signer.rb
|
|
161
161
|
- lib/aws-sdk-core/plugins/s3_sse_cpk.rb
|
|
162
162
|
- lib/aws-sdk-core/plugins/s3_url_encoded_keys.rb
|
|
163
163
|
- lib/aws-sdk-core/plugins/sqs_queue_urls.rb
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
module Aws
|
|
2
|
-
module Plugins
|
|
3
|
-
# This plugin is an implementation detail and may be modified.
|
|
4
|
-
# @api private
|
|
5
|
-
class S3RegionDetection < Seahorse::Client::Plugin
|
|
6
|
-
|
|
7
|
-
# Intentionally not documented - this should go away when all
|
|
8
|
-
# services support signature version 4 in every region.
|
|
9
|
-
option(:signature_version) do |cfg|
|
|
10
|
-
if S3.sigv2_region?(cfg.region)
|
|
11
|
-
's3'
|
|
12
|
-
else
|
|
13
|
-
'v4'
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
class Handler < Seahorse::Client::Handler
|
|
18
|
-
|
|
19
|
-
private
|
|
20
|
-
|
|
21
|
-
def new_hostname(context, region)
|
|
22
|
-
bucket = context.params[:bucket]
|
|
23
|
-
if region == 'us-east-1'
|
|
24
|
-
"#{bucket}.s3-external-1.amazonaws.com"
|
|
25
|
-
else
|
|
26
|
-
bucket + '.' + URI.parse(EndpointProvider.resolve(region, 's3')).host
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
class CachedBucketRegionHandler < Handler
|
|
33
|
-
|
|
34
|
-
def call(context)
|
|
35
|
-
if bucket = context.params[:bucket]
|
|
36
|
-
use_regional_endpoint_when_known(context, bucket)
|
|
37
|
-
end
|
|
38
|
-
@handler.call(context)
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
private
|
|
42
|
-
|
|
43
|
-
def use_regional_endpoint_when_known(context, bucket)
|
|
44
|
-
cached_region = S3::BUCKET_REGIONS[bucket]
|
|
45
|
-
if cached_region && cached_region != context.config.region
|
|
46
|
-
context.http_request.endpoint.host = new_hostname(context, cached_region)
|
|
47
|
-
context[:sigv4_region] = cached_region
|
|
48
|
-
context[:signature_version] = 'v4'
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
class DetectRegionHandler < Handler
|
|
55
|
-
|
|
56
|
-
def call(context)
|
|
57
|
-
response = @handler.call(context)
|
|
58
|
-
handle_region_errors(response)
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
private
|
|
62
|
-
|
|
63
|
-
def handle_region_errors(response)
|
|
64
|
-
if requires_sigv4?(response)
|
|
65
|
-
detect_region_and_retry(response)
|
|
66
|
-
elsif wrong_sigv4_region?(response)
|
|
67
|
-
extract_body_region_and_retry(response.context)
|
|
68
|
-
else
|
|
69
|
-
response
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
def requires_sigv4?(resp)
|
|
74
|
-
resp.context.http_response.status_code == 400 &&
|
|
75
|
-
resp.context.http_response.body_contents.include?('Please use AWS4-HMAC-SHA256') &&
|
|
76
|
-
resp.context.http_response.body.respond_to?(:truncate)
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
def wrong_sigv4_region?(resp)
|
|
80
|
-
resp.context.http_response.status_code == 400 &&
|
|
81
|
-
resp.context.http_response.body_contents.match(/<Region>.+?<\/Region>/)
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
def extract_body_region_and_retry(context)
|
|
85
|
-
actual_region = region_from_body(context)
|
|
86
|
-
updgrade_to_v4(context, actual_region)
|
|
87
|
-
log_warning(context, actual_region)
|
|
88
|
-
@handler.call(context)
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
def region_from_body(context)
|
|
92
|
-
context.http_response.body_contents.match(/<Region>(.+?)<\/Region>/)[1]
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
def detect_region_and_retry(resp)
|
|
96
|
-
context = resp.context
|
|
97
|
-
updgrade_to_v4(context, 'us-east-1')
|
|
98
|
-
resp = @handler.call(context)
|
|
99
|
-
actual_region = region_from_location_header(context)
|
|
100
|
-
updgrade_to_v4(context, actual_region)
|
|
101
|
-
log_warning(context, actual_region)
|
|
102
|
-
@handler.call(context)
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def updgrade_to_v4(context, region)
|
|
106
|
-
bucket = context.params[:bucket]
|
|
107
|
-
context.http_response.body.truncate(0)
|
|
108
|
-
context.http_request.headers.delete('authorization')
|
|
109
|
-
context.http_request.headers.delete('x-amz-security-token')
|
|
110
|
-
context.http_request.endpoint.host = new_hostname(context, region)
|
|
111
|
-
signer = Signers::V4.new(context.config.credentials, 's3', region)
|
|
112
|
-
signer.sign(context.http_request)
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
def region_from_location_header(context)
|
|
116
|
-
location = context.http_response.headers['location']
|
|
117
|
-
location.match(/s3.(.+?)\.amazonaws\.com/)[1]
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
def log_warning(context, actual_region)
|
|
121
|
-
S3::BUCKET_REGIONS[context.params[:bucket]] = actual_region
|
|
122
|
-
msg = "S3 client configured for #{context.config.region.inspect} " +
|
|
123
|
-
"but the bucket #{context.params[:bucket].inspect} is in " +
|
|
124
|
-
"#{actual_region.inspect}; Please configure the proper region " +
|
|
125
|
-
"to avoid multiple unecessary redirects and signing attempts"
|
|
126
|
-
if logger = context.config.logger
|
|
127
|
-
logger.warn(msg)
|
|
128
|
-
else
|
|
129
|
-
warn(msg)
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
# BEFORE the request is signed
|
|
137
|
-
handle(CachedBucketRegionHandler, step: :sign, priority: 60)
|
|
138
|
-
|
|
139
|
-
# AFTER the request is signed
|
|
140
|
-
handle(DetectRegionHandler, step: :sign, priority: 40)
|
|
141
|
-
|
|
142
|
-
end
|
|
143
|
-
end
|
|
144
|
-
end
|