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.
Files changed (41) hide show
  1. data/lib/aws/api_config/AutoScaling-2011-01-01.yml +6 -2
  2. data/lib/aws/api_config/{EC2-2012-04-01.yml → EC2-2012-06-01.yml} +12 -0
  3. data/lib/aws/api_config/STS-2011-06-15.yml +0 -4
  4. data/lib/aws/auto_scaling/client.rb +6 -2
  5. data/lib/aws/auto_scaling/launch_configuration.rb +8 -0
  6. data/lib/aws/auto_scaling/launch_configuration_collection.rb +14 -4
  7. data/lib/aws/auto_scaling/scaling_policy.rb +17 -0
  8. data/lib/aws/auto_scaling/scaling_policy_options.rb +2 -0
  9. data/lib/aws/core.rb +13 -11
  10. data/lib/aws/core/cacheable.rb +1 -1
  11. data/lib/aws/core/client.rb +40 -39
  12. data/lib/aws/core/configuration.rb +24 -15
  13. data/lib/aws/core/credential_providers.rb +395 -0
  14. data/lib/aws/core/http/net_http_handler.rb +1 -0
  15. data/lib/aws/core/http/request.rb +4 -4
  16. data/lib/aws/core/log_formatter.rb +2 -0
  17. data/lib/aws/core/signature/version_2.rb +18 -5
  18. data/lib/aws/core/signature/version_3.rb +10 -10
  19. data/lib/aws/core/signature/version_4.rb +13 -13
  20. data/lib/aws/core/signer.rb +46 -0
  21. data/lib/aws/dynamo_db/batch_write.rb +2 -1
  22. data/lib/aws/dynamo_db/client.rb +9 -24
  23. data/lib/aws/dynamo_db/table.rb +0 -23
  24. data/lib/aws/ec2/client.rb +19 -1
  25. data/lib/aws/ec2/image.rb +4 -4
  26. data/lib/aws/ec2/instance.rb +17 -5
  27. data/lib/aws/ec2/instance_collection.rb +16 -1
  28. data/lib/aws/errors.rb +40 -0
  29. data/lib/aws/s3/client.rb +2 -1
  30. data/lib/aws/s3/presigned_post.rb +10 -8
  31. data/lib/aws/s3/request.rb +7 -5
  32. data/lib/aws/s3/s3_object.rb +10 -9
  33. data/lib/aws/simple_email_service.rb +1 -1
  34. data/lib/aws/simple_email_service/identity_collection.rb +1 -1
  35. data/lib/aws/sts.rb +2 -6
  36. data/lib/aws/sts/client.rb +14 -17
  37. metadata +7 -9
  38. data/lib/aws/api_config/EC2-2011-12-15.yml +0 -3638
  39. data/lib/aws/core/default_signer.rb +0 -67
  40. data/lib/aws/core/session_signer.rb +0 -90
  41. data/lib/aws/core/signature/version_3_http.rb +0 -72
@@ -19,37 +19,37 @@ module AWS
19
19
  module Signature
20
20
  module Version3
21
21
 
22
- def add_authorization!(signer)
22
+ def self.included base
23
+ base.send(:include, Signer)
24
+ end
23
25
 
24
- self.access_key_id = signer.access_key_id
26
+ def add_authorization! credentials
25
27
 
26
28
  headers["x-amz-date"] ||= (headers["date"] ||= Time.now.rfc822)
27
29
  headers["host"] ||= host
28
30
 
29
- headers["x-amz-security-token"] = signer.session_token if
30
- signer.respond_to?(:session_token) and signer.session_token
31
+ headers["x-amz-security-token"] = credentials.session_token if
32
+ credentials.session_token
31
33
 
32
34
  # compute the authorization
33
- request_hash = OpenSSL::Digest::SHA256.digest(string_to_sign)
34
- signature = signer.sign(request_hash)
35
35
  headers["x-amzn-authorization"] =
36
36
  "AWS3 "+
37
- "AWSAccessKeyId=#{signer.access_key_id},"+
37
+ "AWSAccessKeyId=#{credentials.access_key_id},"+
38
38
  "Algorithm=HmacSHA256,"+
39
39
  "SignedHeaders=#{headers_to_sign.join(';')},"+
40
- "Signature=#{signature}"
40
+ "Signature=#{sign(credentials.secret_access_key, string_to_sign)}"
41
41
  end
42
42
 
43
43
  protected
44
44
 
45
45
  def string_to_sign
46
- [
46
+ OpenSSL::Digest::SHA256.digest([
47
47
  http_method,
48
48
  "/",
49
49
  "",
50
50
  canonical_headers,
51
51
  body
52
- ].join("\n")
52
+ ].join("\n"))
53
53
  end
54
54
 
55
55
  def canonical_headers
@@ -20,28 +20,32 @@ module AWS
20
20
  module Signature
21
21
  module Version4
22
22
 
23
- def add_authorization! signer
24
- self.access_key_id = signer.access_key_id
23
+ def self.included base
24
+ base.send(:include, Signer)
25
+ end
26
+
27
+ def add_authorization! credentials
25
28
  datetime = Time.now.utc.strftime("%Y%m%dT%H%M%SZ")
26
29
  headers['content-type'] ||= 'application/x-www-form-urlencoded'
27
30
  headers['host'] = host
28
31
  headers['x-amz-date'] = datetime
29
- headers['x-amz-security-token'] = signer.session_token if signer.session_token
30
- headers['authorization'] = authorization(signer, datetime)
32
+ headers['x-amz-security-token'] = credentials.session_token if
33
+ credentials.session_token
34
+ headers['authorization'] = authorization(credentials, datetime)
31
35
  end
32
36
 
33
37
  protected
34
38
 
35
- def authorization signer, datetime
39
+ def authorization credentials, datetime
36
40
  parts = []
37
- parts << "AWS4-HMAC-SHA256 Credential=#{access_key_id}/#{credential_string(datetime)}"
41
+ parts << "AWS4-HMAC-SHA256 Credential=#{credentials.access_key_id}/#{credential_string(datetime)}"
38
42
  parts << "SignedHeaders=#{signed_headers}"
39
- parts << "Signature=#{hex16(signature(signer, datetime))}"
43
+ parts << "Signature=#{hex16(signature(credentials, datetime))}"
40
44
  parts.join(', ')
41
45
  end
42
46
 
43
- def signature signer, datetime
44
- k_secret = signer.secret_access_key
47
+ def signature credentials, datetime
48
+ k_secret = credentials.secret_access_key
45
49
  k_date = hmac("AWS4" + k_secret, datetime[0,8])
46
50
  k_region = hmac(k_date, region)
47
51
  k_service = hmac(k_region, service)
@@ -124,10 +128,6 @@ module AWS
124
128
  string.unpack('H*').first
125
129
  end
126
130
 
127
- def hmac key, string
128
- OpenSSL::HMAC.digest(OpenSSL::Digest::Digest.new('sha256'), key, string)
129
- end
130
-
131
131
  def hash string
132
132
  Digest::SHA256.digest(string)
133
133
  end
@@ -0,0 +1,46 @@
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 'base64'
15
+
16
+ module AWS
17
+ module Core
18
+
19
+ # This module provides a {#sign} method that accepts a secret
20
+ # and a string to sign.
21
+ module Signer
22
+
23
+ # Signs a string using the credentials stored in memory.
24
+ # @param [String] secret Usually an AWS secret access key.
25
+ # @param [String] string_to_sign The string to sign.
26
+ # @param [String] digest_method The digest method to use when
27
+ # computing the HMAC digest.
28
+ # @return [String] Returns the computed signature.
29
+ def sign secret, string_to_sign, digest_method = 'sha256'
30
+ Base64.encode64(hmac(secret, string_to_sign, digest_method)).strip
31
+ end
32
+ module_function :sign
33
+
34
+ # Computes an HMAC digest of the passed string.
35
+ # @param [String] key
36
+ # @param [String] value
37
+ # @param [String] digest ('sha256')
38
+ # @return [String]
39
+ def hmac key, value, digest = 'sha256'
40
+ OpenSSL::HMAC.digest(OpenSSL::Digest::Digest.new(digest), key, value)
41
+ end
42
+ module_function :hmac
43
+
44
+ end
45
+ end
46
+ end
@@ -235,7 +235,8 @@ module AWS
235
235
  end
236
236
 
237
237
  def str2sym key_desc
238
- type, value = key_desc.to_a.flatten
238
+ type = key_desc.keys.first
239
+ value = key_desc[type]
239
240
  case type
240
241
  when "S" then { :s => value }
241
242
  when "N" then { :n => value }
@@ -35,12 +35,13 @@ module AWS
35
35
 
36
36
  super
37
37
 
38
- # If the signer does not provide a session token, then we will
39
- # replace it with another signer that manages an AWS STS session.
40
- # This session will auto renew whenever it has expired and will
41
- # be shared across threads.
42
- if config.signer.session_token.nil?
43
- @signer = Core::SessionSigner.for(config)
38
+ # Replaces the current credential provider with a SessionProvider
39
+ # that provides refreshable STS session credentials. DynamoDB
40
+ # requires session credentials.
41
+ if credential_provider.session_token.nil?
42
+ long_term_credentials = credential_provider.credentials
43
+ @credential_provider = Core::CredentialProviders::SessionProvider.for(
44
+ long_term_credentials)
44
45
  end
45
46
 
46
47
  end
@@ -839,26 +840,17 @@ module AWS
839
840
  end
840
841
 
841
842
  def should_retry? response
842
- if possible_expired_credentials?(response)
843
- true
844
- elsif response.error.is_a?(Errors::ProvisionedThroughputExceededException)
843
+ if response.error.is_a?(Errors::ProvisionedThroughputExceededException)
845
844
  config.dynamo_db_retry_throughput_errors?
846
845
  else
847
846
  super
848
847
  end
849
848
  end
850
849
 
851
- def rebuild_http_request response
852
- # called when a request is going to be retried, in case of
853
- # expired credentials we should refresh the session
854
- signer.refresh_session if possible_expired_credentials?(response)
855
- super
856
- end
857
-
858
850
  def sleep_durations response
859
851
 
860
852
  retry_count =
861
- if possible_expired_credentials?(response)
853
+ if expired_credentials?(response)
862
854
  config.max_retries == 0 ? 0 : 1
863
855
  else
864
856
  config.max_retries { 10 }
@@ -876,13 +868,6 @@ module AWS
876
868
 
877
869
  end
878
870
 
879
- # Returns true if we get an access denied error from the service AND
880
- # our signer is capible of getting new short-term credentials
881
- def possible_expired_credentials? response
882
- signer.respond_to?(:refresh_session) and
883
- response.error.is_a?(Errors::ExpiredTokenException)
884
- end
885
-
886
871
  end
887
872
  end
888
873
  end
@@ -420,29 +420,6 @@ module AWS
420
420
  #
421
421
  # @return (see BatchWrite#process!)
422
422
  #
423
- def batch_put items
424
- batch = BatchWrite.new(:config => config)
425
- batch.put(self, options)
426
- batch.process!
427
- end
428
-
429
- # Batch delets up to 25 items.
430
- #
431
- # table.batch_delete(%w(id1 id2 id3 id4))
432
- #
433
- # @param [Array<String>,Array<Array>] items A list of item keys to
434
- # delete. For tables without a range key, items should be an array
435
- # of hash key strings.
436
- #
437
- # batch.delete('table-name', ['hk1', 'hk2', 'hk3'])
438
- #
439
- # For tables with a range key, items should be an array of
440
- # hash key and range key pairs.
441
- #
442
- # batch.delete('table-name', [['hk1', 'rk1'], ['hk1', 'rk2']])
443
- #
444
- # @return (see BatchWrite#process!)
445
- #
446
423
  def batch_put items
447
424
  batch = BatchWrite.new(:config => config)
448
425
  batch.put(self, items)
@@ -17,7 +17,7 @@ module AWS
17
17
  # Client class for Amazon Elastic Compute Cloud (EC2).
18
18
  class Client < Core::Client
19
19
 
20
- API_VERSION = '2012-04-01'
20
+ API_VERSION = '2012-06-01'
21
21
 
22
22
  extend Core::Client::QueryXML
23
23
 
@@ -1883,6 +1883,9 @@ module AWS
1883
1883
  # * +:association+ - (Hash)
1884
1884
  # * +:public_ip+ - (String)
1885
1885
  # * +:ip_owner_id+ - (String)
1886
+ # * +:iam_instance_profile+ - (Hash)
1887
+ # * +:arn+ - (String)
1888
+ # * +:id+ - (String)
1886
1889
  #
1887
1890
  # @return [Core::Response]
1888
1891
  #
@@ -2471,6 +2474,9 @@ module AWS
2471
2474
  # * +:private_ip_address+ - (String)
2472
2475
  # * +:security_group_id+ - (Array<String>)
2473
2476
  # * +:delete_on_termination+ - (Boolean)
2477
+ # * +:iam_instance_profile+ - (Hash)
2478
+ # * +:arn+ - (String)
2479
+ # * +:name+ - (String)
2474
2480
  # * +:instance_id+ - (String)
2475
2481
  # * +:create_time+ - (Time)
2476
2482
  # * +:product_description+ - (String)
@@ -3612,6 +3618,9 @@ module AWS
3612
3618
  # * +:private_ip_address+ - (String)
3613
3619
  # * +:groups+ - (Array<String>)
3614
3620
  # * +:delete_on_termination+ - (Boolean)
3621
+ # * +:iam_instance_profile+ - (Hash)
3622
+ # * +:arn+ - (String)
3623
+ # * +:name+ - (String)
3615
3624
  #
3616
3625
  # === Response Structure:
3617
3626
  #
@@ -3659,6 +3668,9 @@ module AWS
3659
3668
  # * +:private_ip_address+ - (String)
3660
3669
  # * +:security_group_id+ - (Array<String>)
3661
3670
  # * +:delete_on_termination+ - (Boolean)
3671
+ # * +:iam_instance_profile+ - (Hash)
3672
+ # * +:arn+ - (String)
3673
+ # * +:name+ - (String)
3662
3674
  # * +:instance_id+ - (String)
3663
3675
  # * +:create_time+ - (Time)
3664
3676
  # * +:product_description+ - (String)
@@ -3929,6 +3941,9 @@ module AWS
3929
3941
  # * +:private_ip_address+ - (String)
3930
3942
  # * +:groups+ - (Array<String>)
3931
3943
  # * +:delete_on_termination+ - (Boolean)
3944
+ # * +:iam_instance_profile+ - (Hash)
3945
+ # * +:arn+ - (String)
3946
+ # * +:name+ - (String)
3932
3947
  #
3933
3948
  # === Response Structure:
3934
3949
  #
@@ -4016,6 +4031,9 @@ module AWS
4016
4031
  # * +:association+ - (Hash)
4017
4032
  # * +:public_ip+ - (String)
4018
4033
  # * +:ip_owner_id+ - (String)
4034
+ # * +:iam_instance_profile+ - (Hash)
4035
+ # * +:arn+ - (String)
4036
+ # * +:id+ - (String)
4019
4037
  #
4020
4038
  # @return [Core::Response]
4021
4039
  #
@@ -146,15 +146,15 @@ module AWS
146
146
  # @return [Hash] Returns a hash of block
147
147
  # device mappings for the image. In each entry, the key is
148
148
  # the device name (e.g. +"/dev/sda1"+) and the value is an
149
- # object with the following methods that return information
149
+ # hash with the following keys that return information
150
150
  # about the block device:
151
151
  #
152
- # [snapshot_id] The ID of the snapshot that will be used to
152
+ # [:snapshot_id] The ID of the snapshot that will be used to
153
153
  # create this device (may be nil).
154
154
  #
155
- # [volume_size] The size of the volume, in GiBs.
155
+ # [:volume_size] The size of the volume, in GiBs.
156
156
  #
157
- # [delete_on_termination] True if the Amazon EBS volume is
157
+ # [:delete_on_termination] True if the Amazon EBS volume is
158
158
  # deleted on instance termination.
159
159
  def block_device_mappings
160
160
  (block_device_mapping || []).inject({}) do |h,mapping|
@@ -144,6 +144,10 @@ module AWS
144
144
  # @attr_reader [String,nil] subnet_id Instances launched in a VPC have
145
145
  # a subnet_id. Normal EC2 instances return nil.
146
146
  #
147
+ # @attr_reader [String,nil] iam_instance_profile_id
148
+ #
149
+ # @attr_reader [String,nil] iam_instance_profile_arn
150
+ #
147
151
  class Instance < Resource
148
152
 
149
153
  include TaggedItem
@@ -260,6 +264,18 @@ module AWS
260
264
 
261
265
  describe_call_attribute :subnet_id, :static => true
262
266
 
267
+ describe_call_attribute :iam_instance_profile_id,
268
+ :as => :iam_instance_profile,
269
+ :static => true do
270
+ translates_output{|profile| profile[:id] }
271
+ end
272
+
273
+ describe_call_attribute :iam_instance_profile_arn,
274
+ :as => :iam_instance_profile,
275
+ :static => true do
276
+ translates_output{|profile| profile[:arn] }
277
+ end
278
+
263
279
  attribute :status do
264
280
  translates_output{|state| state.name.tr("-","_").to_sym }
265
281
  end
@@ -631,20 +647,17 @@ module AWS
631
647
  instance_action :stop
632
648
  end
633
649
 
634
- # @private
635
650
  protected
651
+
636
652
  def find_in_response resp
637
653
  resp.instance_index[id]
638
654
  end
639
655
 
640
- # @private
641
- protected
642
656
  def instance_action name
643
657
  client.send("#{name}_instances", :instance_ids => [id])
644
658
  nil
645
659
  end
646
660
 
647
- protected
648
661
  def get_resource attribute
649
662
  if self.class.mutable_describe_attributes.include?(attribute.name)
650
663
  describe_attribute_call(attribute)
@@ -653,7 +666,6 @@ module AWS
653
666
  end
654
667
  end
655
668
 
656
- protected
657
669
  def attributes_from_response_object(obj)
658
670
  if atts = super(obj)
659
671
  if obj[:instance_state]
@@ -76,13 +76,17 @@ module AWS
76
76
  # @param [Hash] options Options for new instance. +:image_id+ is
77
77
  # the only required option.
78
78
  #
79
- # @option options :count How many instances to request. By
79
+ # @option options [Integer] :count How many instances to request. By
80
80
  # default one instance is requested. You can specify this
81
81
  # either as an integer or as a Range, to indicate the
82
82
  # minimum and maximum number of instances to run. Note that
83
83
  # for a new account you can request at most 20 instances at
84
84
  # once.
85
85
  #
86
+ # @option options [String] :iam_instance_profile The name or
87
+ # ARN of an IAM instance profile. This provides credentials
88
+ # to the EC2 instance(s) via the instance metadata service.
89
+ #
86
90
  # @option options [Hash] :block_device_mappings This must be a
87
91
  # hash; the keys are device names to map, and the value for
88
92
  # each entry determines how that device is mapped. Valid
@@ -192,6 +196,17 @@ module AWS
192
196
  #
193
197
  def create options = {}
194
198
 
199
+ if profile = options.delete(:iam_instance_profile)
200
+ profile = case profile
201
+ when /^arn:aws:iam::/ then { :arn => profile }
202
+ when String then { :name => profile }
203
+ when Hash then profile
204
+ else
205
+ msg = "expected a name or ARN string for :iam_instance_profile"
206
+ end
207
+ options[:iam_instance_profile] = profile
208
+ end
209
+
195
210
  if image = options.delete(:image)
196
211
  options[:image_id] = image.id
197
212
  end
@@ -118,5 +118,45 @@ module AWS
118
118
  extend ExceptionMixinClassMethods
119
119
  end
120
120
 
121
+ # Raised when AWS credentials could not be found.
122
+ class MissingCredentialsError < StandardError
123
+
124
+ def initialize msg = nil
125
+ msg ||= <<-MSG
126
+
127
+ Missing Credentials.
128
+
129
+ Unable to find AWS credentials. You can configure your AWS credentials
130
+ a few different ways:
131
+
132
+ * Call AWS.config with :access_key_id and :secret_access_key
133
+
134
+ * Export AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY to ENV
135
+
136
+ * On EC2 you can run instances with an IAM instance profile and credentials
137
+ will be auto loaded from the instance metadata service on those
138
+ instances.
139
+
140
+ * Call AWS.config with :credential_provider. A credential provider should
141
+ either include AWS::Core::CredentialProviders::Provider or respond to
142
+ the same public methods.
143
+
144
+ = Ruby on Rails
145
+
146
+ In a Ruby on Rails application you may also specify your credentials in
147
+ the following ways:
148
+
149
+ * Via a config initializer script using any of the methods mentioned above
150
+ (e.g. RAILS_ROOT/config/initializers/aws-sdk.rb).
151
+
152
+ * Via a yaml configuration file located at RAILS_ROOT/config/aws.yml.
153
+ This file should be formated like the default RAILS_ROOT/config/database.yml
154
+ file.
155
+
156
+ MSG
157
+ super(msg)
158
+ end
159
+ end
160
+
121
161
  end
122
162
  end