aws-sdk 1.5.2 → 1.5.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|