aws-sdk 1.5.2 → 1.5.3
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.
- data/lib/aws/api_config/AutoScaling-2011-01-01.yml +6 -2
- data/lib/aws/api_config/{EC2-2012-04-01.yml → EC2-2012-06-01.yml} +12 -0
- data/lib/aws/api_config/STS-2011-06-15.yml +0 -4
- data/lib/aws/auto_scaling/client.rb +6 -2
- data/lib/aws/auto_scaling/launch_configuration.rb +8 -0
- data/lib/aws/auto_scaling/launch_configuration_collection.rb +14 -4
- data/lib/aws/auto_scaling/scaling_policy.rb +17 -0
- data/lib/aws/auto_scaling/scaling_policy_options.rb +2 -0
- data/lib/aws/core.rb +13 -11
- data/lib/aws/core/cacheable.rb +1 -1
- data/lib/aws/core/client.rb +40 -39
- data/lib/aws/core/configuration.rb +24 -15
- data/lib/aws/core/credential_providers.rb +395 -0
- data/lib/aws/core/http/net_http_handler.rb +1 -0
- data/lib/aws/core/http/request.rb +4 -4
- data/lib/aws/core/log_formatter.rb +2 -0
- data/lib/aws/core/signature/version_2.rb +18 -5
- data/lib/aws/core/signature/version_3.rb +10 -10
- data/lib/aws/core/signature/version_4.rb +13 -13
- data/lib/aws/core/signer.rb +46 -0
- data/lib/aws/dynamo_db/batch_write.rb +2 -1
- data/lib/aws/dynamo_db/client.rb +9 -24
- data/lib/aws/dynamo_db/table.rb +0 -23
- data/lib/aws/ec2/client.rb +19 -1
- data/lib/aws/ec2/image.rb +4 -4
- data/lib/aws/ec2/instance.rb +17 -5
- data/lib/aws/ec2/instance_collection.rb +16 -1
- data/lib/aws/errors.rb +40 -0
- data/lib/aws/s3/client.rb +2 -1
- data/lib/aws/s3/presigned_post.rb +10 -8
- data/lib/aws/s3/request.rb +7 -5
- data/lib/aws/s3/s3_object.rb +10 -9
- data/lib/aws/simple_email_service.rb +1 -1
- data/lib/aws/simple_email_service/identity_collection.rb +1 -1
- data/lib/aws/sts.rb +2 -6
- data/lib/aws/sts/client.rb +14 -17
- metadata +7 -9
- data/lib/aws/api_config/EC2-2011-12-15.yml +0 -3638
- data/lib/aws/core/default_signer.rb +0 -67
- data/lib/aws/core/session_signer.rb +0 -90
- data/lib/aws/core/signature/version_3_http.rb +0 -72
@@ -0,0 +1,395 @@
|
|
1
|
+
# Copyright 2011-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"). You
|
4
|
+
# may not use this file except in compliance with the License. A copy of
|
5
|
+
# the License is located at
|
6
|
+
#
|
7
|
+
# http://aws.amazon.com/apache2.0/
|
8
|
+
#
|
9
|
+
# or in the "license" file accompanying this file. This file is
|
10
|
+
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
|
11
|
+
# ANY KIND, either express or implied. See the License for the specific
|
12
|
+
# language governing permissions and limitations under the License.
|
13
|
+
|
14
|
+
require 'set'
|
15
|
+
require 'net/http'
|
16
|
+
require 'timeout'
|
17
|
+
|
18
|
+
module AWS
|
19
|
+
module Core
|
20
|
+
module CredentialProviders
|
21
|
+
|
22
|
+
# This module is mixed into the various credential provider
|
23
|
+
# classes. It provides a unified interface for getting
|
24
|
+
# credentials and refreshing them.
|
25
|
+
module Provider
|
26
|
+
|
27
|
+
# The list of possible keys in the hash returned by {#credentials}.
|
28
|
+
KEYS = Set[:access_key_id, :secret_access_key, :session_token]
|
29
|
+
|
30
|
+
# @return [Hash] Returns a hash of credentials containg at least
|
31
|
+
# the +:access_key_id+ and +:secret_access_key+. The hash may
|
32
|
+
# also contain a +:session_token+.
|
33
|
+
#
|
34
|
+
# @raise [Errors::MissingCredentialsError] Raised when the
|
35
|
+
# +:access_key_id+ or the +:secret_access_key+ can not be found.
|
36
|
+
#
|
37
|
+
def credentials
|
38
|
+
@cached_credentials ||= begin
|
39
|
+
creds = get_credentials
|
40
|
+
unless creds[:access_key_id] and creds[:secret_access_key]
|
41
|
+
raise Errors::MissingCredentialsError
|
42
|
+
end
|
43
|
+
creds
|
44
|
+
end
|
45
|
+
@cached_credentials.dup
|
46
|
+
end
|
47
|
+
|
48
|
+
# @return [String] Returns the AWS access key id.
|
49
|
+
# @raise (see #credentials)
|
50
|
+
def access_key_id
|
51
|
+
credentials[:access_key_id]
|
52
|
+
end
|
53
|
+
|
54
|
+
# @return [String] Returns the AWS secret access key.
|
55
|
+
# @raise (see #credentials)
|
56
|
+
def secret_access_key
|
57
|
+
credentials[:secret_access_key]
|
58
|
+
end
|
59
|
+
|
60
|
+
# @return [String,nil] Returns the AWS session token or nil if these
|
61
|
+
# are not session credentials.
|
62
|
+
# @raise (see #credentials)
|
63
|
+
def session_token
|
64
|
+
credentials[:session_token]
|
65
|
+
end
|
66
|
+
|
67
|
+
# Clears out cached/memoized credentials. Causes the provider
|
68
|
+
# to refetch credentials from the source.
|
69
|
+
# @return [nil]
|
70
|
+
def refresh
|
71
|
+
@cached_credentials = nil
|
72
|
+
end
|
73
|
+
|
74
|
+
protected
|
75
|
+
|
76
|
+
# This method is called on a credential provider to fetch
|
77
|
+
# credentials. The credentials hash returned from this
|
78
|
+
# method will be cashed until the client calls {#refresh}.
|
79
|
+
# @return [Hash]
|
80
|
+
def get_credentials
|
81
|
+
# should be defined in provider classes.
|
82
|
+
raise NotImplementedError
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
# The default credential provider makes a best effort to
|
88
|
+
# locate your AWS credentials. It checks a variety of locations
|
89
|
+
# in the following order:
|
90
|
+
#
|
91
|
+
# * Static credentials from AWS.config (e.g. AWS.config.access_key_id,
|
92
|
+
# AWS.config.secret_access_key)
|
93
|
+
#
|
94
|
+
# * The environment (e.g. ENV['AWS_ACCESS_KEY_ID'] or
|
95
|
+
# ENV['AMAZON_ACCESS_KEY_ID'])
|
96
|
+
#
|
97
|
+
# * EC2 metadata service (checks for credentials provided by
|
98
|
+
# roles for instances).
|
99
|
+
#
|
100
|
+
class DefaultProvider
|
101
|
+
|
102
|
+
include Provider
|
103
|
+
|
104
|
+
# (see StaticProvider#new)
|
105
|
+
def initialize static_credentials = {}
|
106
|
+
@providers = []
|
107
|
+
@providers << StaticProvider.new(static_credentials)
|
108
|
+
@providers << ENVProvider.new('AWS')
|
109
|
+
@providers << ENVProvider.new('AMAZON')
|
110
|
+
@providers << EC2Provider.new
|
111
|
+
end
|
112
|
+
|
113
|
+
# @return [Array<Provider>]
|
114
|
+
attr_reader :providers
|
115
|
+
|
116
|
+
def get_credentials
|
117
|
+
providers.each do |provider|
|
118
|
+
return provider.credentials rescue Errors::MissingCredentialsError
|
119
|
+
end
|
120
|
+
{}
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
# Static credentials are provided directly to config via
|
126
|
+
# +:access_key_id+ and +:secret_access_key+ (and optionally
|
127
|
+
# +:session_token+).
|
128
|
+
# @private
|
129
|
+
class StaticProvider
|
130
|
+
|
131
|
+
include Provider
|
132
|
+
|
133
|
+
# @param [Hash] static_credentials
|
134
|
+
# @option static_credentials [required,String] :access_key_id
|
135
|
+
# @option static_credentials [required,String] :secret_access_key
|
136
|
+
# @option static_credentials [String] :session_token
|
137
|
+
def initialize static_credentials = {}
|
138
|
+
|
139
|
+
static_credentials.keys.each do |opt_name|
|
140
|
+
unless KEYS.include?(opt_name)
|
141
|
+
raise ArgumentError, "invalid option #{opt_name.inspect}"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
@static_credentials = {}
|
146
|
+
KEYS.each do |opt_name|
|
147
|
+
if opt_value = static_credentials[opt_name]
|
148
|
+
@static_credentials[opt_name] = opt_value
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
|
154
|
+
# (see Provider#get_credentials)
|
155
|
+
def get_credentials
|
156
|
+
@static_credentials
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
|
161
|
+
# Fetches credentials from the environment (ENV). You construct
|
162
|
+
# an ENV provider with a prefix. Given the prefix "AWS"
|
163
|
+
# ENV will be checked for the following keys:
|
164
|
+
#
|
165
|
+
# * AWS_ACCESS_KEY_ID
|
166
|
+
# * AWS_SECRET_ACCESS_KEY
|
167
|
+
# * AWS_SESSION_TOKEN (optional)
|
168
|
+
#
|
169
|
+
class ENVProvider
|
170
|
+
|
171
|
+
include Provider
|
172
|
+
|
173
|
+
# @param [String] prefix The prefix to apply to the ENV variable.
|
174
|
+
def initialize prefix
|
175
|
+
@prefix = prefix
|
176
|
+
end
|
177
|
+
|
178
|
+
# @return [String]
|
179
|
+
attr_reader :prefix
|
180
|
+
|
181
|
+
# (see Provider#get_credentials)
|
182
|
+
def get_credentials
|
183
|
+
credentials = {}
|
184
|
+
KEYS.each do |key|
|
185
|
+
if value = ENV["#{@prefix}_#{key.to_s.upcase}"]
|
186
|
+
credentials[key] = value
|
187
|
+
end
|
188
|
+
end
|
189
|
+
credentials
|
190
|
+
end
|
191
|
+
|
192
|
+
end
|
193
|
+
|
194
|
+
# This credential provider tries to get credentials from the EC2
|
195
|
+
# metadata service.
|
196
|
+
class EC2Provider
|
197
|
+
|
198
|
+
# Raised when an http response is recieved with a non 200
|
199
|
+
# http status code.
|
200
|
+
# @private
|
201
|
+
class FailedRequestError < StandardError; end
|
202
|
+
|
203
|
+
# These are the errors we trap when attempting to talk to the
|
204
|
+
# instance metadata service. Any of these imply the service
|
205
|
+
# is not present, no responding or some other non-recoverable
|
206
|
+
# error.
|
207
|
+
# @private
|
208
|
+
FAILURES = [
|
209
|
+
FailedRequestError,
|
210
|
+
Errno::EHOSTUNREACH,
|
211
|
+
Errno::ECONNREFUSED,
|
212
|
+
SocketError,
|
213
|
+
Timeout::Error,
|
214
|
+
]
|
215
|
+
|
216
|
+
include Provider
|
217
|
+
|
218
|
+
# @param [Hash] options
|
219
|
+
# @option options [String] :ip_address ('169.254.169.254')
|
220
|
+
# @option options [Integer] :port (80)
|
221
|
+
# @option options [Float] :http_open_timeout (1)
|
222
|
+
# @option options [Float] :http_read_timeout (1)
|
223
|
+
# @option options [Object] :http_debug_output (nil) HTTP wire
|
224
|
+
# traces are sent to this object. You can specify something
|
225
|
+
# like $stdout.
|
226
|
+
def initialize options = {}
|
227
|
+
@ip_address = options[:ip_address] || '169.254.169.254'
|
228
|
+
@port = options[:port] || 80
|
229
|
+
@http_open_timeout = options[:http_open_timeout] || 1
|
230
|
+
@http_read_timeout = options[:http_read_timeout] || 1
|
231
|
+
@http_debug_output = options[:http_debug_output]
|
232
|
+
end
|
233
|
+
|
234
|
+
# @return [String] Defaults to '169.254.169.254'.
|
235
|
+
attr_accessor :ip_address
|
236
|
+
|
237
|
+
# @return [Integer] Defaults to port 80.
|
238
|
+
attr_accessor :port
|
239
|
+
|
240
|
+
# @return [Float]
|
241
|
+
attr_accessor :http_open_timeout
|
242
|
+
|
243
|
+
# @return [Float]
|
244
|
+
attr_accessor :http_read_timeout
|
245
|
+
|
246
|
+
# @return [Object,nil]
|
247
|
+
attr_accessor :http_debug_output
|
248
|
+
|
249
|
+
protected
|
250
|
+
|
251
|
+
# (see Provider#get_credentials)
|
252
|
+
def get_credentials
|
253
|
+
begin
|
254
|
+
|
255
|
+
http = Net::HTTP.new(ip_address, port)
|
256
|
+
http.open_timeout = http_open_timeout
|
257
|
+
http.read_timeout = http_read_timeout
|
258
|
+
http.set_debug_output(http_debug_output) if
|
259
|
+
http_debug_output
|
260
|
+
http.start
|
261
|
+
|
262
|
+
# get the first/default instance profile name
|
263
|
+
path = '/latest/meta-data/iam/security-credentials/'
|
264
|
+
profile_name = get(http, path).lines.map(&:strip).first
|
265
|
+
|
266
|
+
# get the session details from the instance profile name
|
267
|
+
path << profile_name
|
268
|
+
session = JSON.parse(get(http, path))
|
269
|
+
|
270
|
+
http.finish
|
271
|
+
|
272
|
+
credentials = {}
|
273
|
+
credentials[:access_key_id] = session['AccessKeyId']
|
274
|
+
credentials[:secret_access_key] = session['SecretAccessKey']
|
275
|
+
credentials[:session_token] = session['Token']
|
276
|
+
credentials
|
277
|
+
|
278
|
+
rescue *FAILURES => e
|
279
|
+
{}
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
# Makes an HTTP Get request with the given path. If a non-200
|
284
|
+
# response is received, then a FailedRequestError is raised.
|
285
|
+
# a {FailedRequestError} is raised.
|
286
|
+
# @param [Net::HTTPSession] session
|
287
|
+
# @param [String] path
|
288
|
+
# @raise [FailedRequestError]
|
289
|
+
# @return [String] Returns the http response body.
|
290
|
+
def get session, path
|
291
|
+
response = session.request(Net::HTTP::Get.new(path))
|
292
|
+
if response.code.to_i == 200
|
293
|
+
response.body
|
294
|
+
else
|
295
|
+
raise FailedRequestError
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
end
|
300
|
+
|
301
|
+
# = Session Credential Provider
|
302
|
+
#
|
303
|
+
# The session provider consumes long term credentials (+:access_key_id+
|
304
|
+
# and +:secret_access_key+) and requests a session from STS.
|
305
|
+
# It then returns the short term credential set from STS.
|
306
|
+
#
|
307
|
+
# Calling {#refresh} causes the session provider to request a new
|
308
|
+
# set of credentials.
|
309
|
+
#
|
310
|
+
# This session provider is currently only used for DynamoDB which
|
311
|
+
# requires session credentials.
|
312
|
+
class SessionProvider
|
313
|
+
|
314
|
+
include Provider
|
315
|
+
|
316
|
+
@create_mutex = Mutex.new
|
317
|
+
|
318
|
+
class << self
|
319
|
+
|
320
|
+
# @param [Hash] long_term_credentials A hash of credentials with
|
321
|
+
# +:access_key_id+ and +:secret_access_key+ (but not
|
322
|
+
# +:session_token+).
|
323
|
+
def for long_term_credentials
|
324
|
+
@create_mutex.synchronize do
|
325
|
+
@session_providers ||= {}
|
326
|
+
@session_providers[long_term_credentials[:access_key_id]] =
|
327
|
+
self.new(long_term_credentials)
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
# Creation of SessionProviders *must* happen behind the mutex and
|
332
|
+
# we want to reuse session providers for the same access key id.
|
333
|
+
protected :new
|
334
|
+
|
335
|
+
end
|
336
|
+
|
337
|
+
# @param [Hash] long_term_credentials A hash of credentials with
|
338
|
+
# +:access_key_id+ and +:secret_access_key+ (but not
|
339
|
+
# +:session_token+).
|
340
|
+
def initialize long_term_credentials
|
341
|
+
@static = StaticProvider.new(long_term_credentials)
|
342
|
+
if @static.session_token
|
343
|
+
raise ArgumentError, 'invalid option :session_token'
|
344
|
+
end
|
345
|
+
@session_mutex = Mutex.new
|
346
|
+
end
|
347
|
+
|
348
|
+
# Aliasing the refresh method so we can call it from the refresh
|
349
|
+
# method defined in this class.
|
350
|
+
alias_method :orig_refresh, :refresh
|
351
|
+
protected :orig_refresh
|
352
|
+
|
353
|
+
# (see Provider#refresh)
|
354
|
+
def refresh
|
355
|
+
refresh_session
|
356
|
+
orig_refresh
|
357
|
+
end
|
358
|
+
|
359
|
+
protected
|
360
|
+
|
361
|
+
# (see Provider#get_credentials)
|
362
|
+
def get_credentials
|
363
|
+
session = cached_session
|
364
|
+
if session.nil?
|
365
|
+
refresh_session
|
366
|
+
session = cached_session
|
367
|
+
end
|
368
|
+
session.credentials
|
369
|
+
end
|
370
|
+
|
371
|
+
# Replaces the cached STS session with a new one.
|
372
|
+
# @return [nil]
|
373
|
+
def refresh_session
|
374
|
+
sts = AWS::STS.new(@static.credentials.merge(:use_ssl => true))
|
375
|
+
@session_mutex.synchronize do
|
376
|
+
@session = sts.new_session
|
377
|
+
end
|
378
|
+
nil
|
379
|
+
end
|
380
|
+
|
381
|
+
# @return [nil,STS::Session] Returns nil if a session has not
|
382
|
+
# already been started.
|
383
|
+
def cached_session
|
384
|
+
local_session = nil
|
385
|
+
@session_mutex.synchronize do
|
386
|
+
local_session = @session
|
387
|
+
end
|
388
|
+
local_session
|
389
|
+
end
|
390
|
+
|
391
|
+
end
|
392
|
+
|
393
|
+
end
|
394
|
+
end
|
395
|
+
end
|
@@ -58,10 +58,6 @@ module AWS
|
|
58
58
|
# @return [String] path of the request URI, defaults to /
|
59
59
|
attr_accessor :path
|
60
60
|
|
61
|
-
# @return [String] the AWS access key ID used to authorize the
|
62
|
-
# request
|
63
|
-
attr_accessor :access_key_id
|
64
|
-
|
65
61
|
# @return [nil, URI] The URI to the proxy server requests are
|
66
62
|
# sent through if configured. Returns nil if there is no proxy.
|
67
63
|
attr_accessor :proxy_uri
|
@@ -69,6 +65,10 @@ module AWS
|
|
69
65
|
# @return [String] The region name this request is for. Only needs
|
70
66
|
# to be populated for requests against signature v4 endpoints.
|
71
67
|
attr_accessor :region
|
68
|
+
|
69
|
+
# @return [String]
|
70
|
+
# @private
|
71
|
+
attr_accessor :access_key_id
|
72
72
|
|
73
73
|
# @param [Boolean] state If the request should be sent over ssl or not.
|
74
74
|
def use_ssl= state
|
@@ -16,24 +16,37 @@ module AWS
|
|
16
16
|
module Signature
|
17
17
|
module Version2
|
18
18
|
|
19
|
-
def
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
def self.included base
|
20
|
+
base.send(:include, Signer)
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_authorization! credentials
|
24
|
+
add_param('AWSAccessKeyId', credentials.access_key_id)
|
25
|
+
if token = credentials.session_token
|
23
26
|
add_param("SecurityToken", token)
|
24
27
|
end
|
25
28
|
add_param('SignatureVersion', '2')
|
26
29
|
add_param('SignatureMethod', 'HmacSHA256')
|
27
|
-
add_param('Signature',
|
30
|
+
add_param('Signature', sign(credentials.secret_access_key, string_to_sign))
|
28
31
|
end
|
29
32
|
|
33
|
+
protected
|
34
|
+
|
30
35
|
def string_to_sign
|
36
|
+
|
37
|
+
host =
|
38
|
+
case port
|
39
|
+
when 80, 443 then self.host
|
40
|
+
else "#{self.host}:#{port}"
|
41
|
+
end
|
42
|
+
|
31
43
|
[
|
32
44
|
http_method,
|
33
45
|
host,
|
34
46
|
path,
|
35
47
|
params.sort.collect { |p| p.encoded }.join('&'),
|
36
48
|
].join("\n")
|
49
|
+
|
37
50
|
end
|
38
51
|
|
39
52
|
end
|