dynamodb 0.0.2 → 1.1.1
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/.gitignore +1 -0
- data/Gemfile +2 -1
- data/README.md +41 -11
- data/dynamodb.gemspec +3 -2
- data/lib/dynamodb.rb +18 -17
- data/lib/dynamodb/connection.rb +34 -70
- data/lib/dynamodb/failure_response.rb +41 -0
- data/lib/dynamodb/http_handler.rb +74 -0
- data/lib/dynamodb/request.rb +107 -0
- data/lib/dynamodb/success_response.rb +51 -0
- data/lib/dynamodb/version.rb +3 -0
- data/lib/net/http/connection_pool.rb +226 -0
- data/lib/net/http/connection_pool/connection.rb +189 -0
- data/lib/net/http/connection_pool/session.rb +126 -0
- data/spec/dynamodb/connection_spec.rb +14 -117
- data/spec/dynamodb/failure_response_spec.rb +27 -0
- data/spec/dynamodb/http_handler_spec.rb +71 -0
- data/spec/dynamodb/request_spec.rb +31 -0
- data/spec/dynamodb/success_response_spec.rb +93 -0
- data/spec/dynamodb_spec.rb +24 -0
- metadata +18 -28
- data/lib/dynamodb/credentials.rb +0 -30
- data/lib/dynamodb/response.rb +0 -33
- data/lib/dynamodb/security_token_service.rb +0 -110
- data/lib/dynamodb/typhoeus/request.rb +0 -27
- data/spec/dynamodb/credentials_spec.rb +0 -22
- data/spec/dynamodb/response_spec.rb +0 -87
- data/spec/dynamodb/security_token_service_spec.rb +0 -97
data/spec/dynamodb_spec.rb
CHANGED
@@ -31,6 +31,20 @@ describe DynamoDB do
|
|
31
31
|
DynamoDB.serialize("foo" => nil).should == {}
|
32
32
|
DynamoDB.serialize("foo" => "").should == {}
|
33
33
|
end
|
34
|
+
|
35
|
+
it "serializes StringSet" do
|
36
|
+
DynamoDB.serialize(["foo", "bar", "foo"]).should == {"SS" => ["foo", "bar"]}
|
37
|
+
end
|
38
|
+
|
39
|
+
it "serializes NumberSet" do
|
40
|
+
DynamoDB.serialize([1, 2, 1]).should == {"NS" => [1,2]}
|
41
|
+
end
|
42
|
+
|
43
|
+
it "raises an error on mixed types" do
|
44
|
+
lambda {
|
45
|
+
DynamoDB.serialize([1, "2", 1])
|
46
|
+
}.should raise_error
|
47
|
+
end
|
34
48
|
end
|
35
49
|
|
36
50
|
describe "#deserialize" do
|
@@ -55,5 +69,15 @@ describe DynamoDB do
|
|
55
69
|
deserialized["price"].should == 11.99
|
56
70
|
deserialized["active"].should == 1
|
57
71
|
end
|
72
|
+
|
73
|
+
it "deserializes StringSet and NumberSet" do
|
74
|
+
item = {
|
75
|
+
"turtles" => {"SS" => ["Leonardo", "Michelangelo"]},
|
76
|
+
"powerball" => {"NS" => [1,2]}
|
77
|
+
}
|
78
|
+
deserialized = DynamoDB.deserialize(item)
|
79
|
+
deserialized["turtles"].should == ["Leonardo", "Michelangelo"]
|
80
|
+
deserialized["powerball"].should == [1,2]
|
81
|
+
end
|
58
82
|
end
|
59
83
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dynamodb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.1.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,24 +10,8 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2013-05-08 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
|
-
- !ruby/object:Gem::Dependency
|
16
|
-
name: typhoeus
|
17
|
-
requirement: !ruby/object:Gem::Requirement
|
18
|
-
none: false
|
19
|
-
requirements:
|
20
|
-
- - '='
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: 0.4.2
|
23
|
-
type: :runtime
|
24
|
-
prerelease: false
|
25
|
-
version_requirements: !ruby/object:Gem::Requirement
|
26
|
-
none: false
|
27
|
-
requirements:
|
28
|
-
- - '='
|
29
|
-
- !ruby/object:Gem::Version
|
30
|
-
version: 0.4.2
|
31
15
|
- !ruby/object:Gem::Dependency
|
32
16
|
name: multi_json
|
33
17
|
requirement: !ruby/object:Gem::Requirement
|
@@ -93,14 +77,19 @@ files:
|
|
93
77
|
- dynamodb.gemspec
|
94
78
|
- lib/dynamodb.rb
|
95
79
|
- lib/dynamodb/connection.rb
|
96
|
-
- lib/dynamodb/
|
97
|
-
- lib/dynamodb/
|
98
|
-
- lib/dynamodb/
|
99
|
-
- lib/dynamodb/
|
80
|
+
- lib/dynamodb/failure_response.rb
|
81
|
+
- lib/dynamodb/http_handler.rb
|
82
|
+
- lib/dynamodb/request.rb
|
83
|
+
- lib/dynamodb/success_response.rb
|
84
|
+
- lib/dynamodb/version.rb
|
85
|
+
- lib/net/http/connection_pool.rb
|
86
|
+
- lib/net/http/connection_pool/connection.rb
|
87
|
+
- lib/net/http/connection_pool/session.rb
|
100
88
|
- spec/dynamodb/connection_spec.rb
|
101
|
-
- spec/dynamodb/
|
102
|
-
- spec/dynamodb/
|
103
|
-
- spec/dynamodb/
|
89
|
+
- spec/dynamodb/failure_response_spec.rb
|
90
|
+
- spec/dynamodb/http_handler_spec.rb
|
91
|
+
- spec/dynamodb/request_spec.rb
|
92
|
+
- spec/dynamodb/success_response_spec.rb
|
104
93
|
- spec/dynamodb_spec.rb
|
105
94
|
- spec/spec_helper.rb
|
106
95
|
homepage: http://github.com/groupme/dynamodb
|
@@ -129,8 +118,9 @@ specification_version: 3
|
|
129
118
|
summary: Communicate with Amazon DynamoDB.
|
130
119
|
test_files:
|
131
120
|
- spec/dynamodb/connection_spec.rb
|
132
|
-
- spec/dynamodb/
|
133
|
-
- spec/dynamodb/
|
134
|
-
- spec/dynamodb/
|
121
|
+
- spec/dynamodb/failure_response_spec.rb
|
122
|
+
- spec/dynamodb/http_handler_spec.rb
|
123
|
+
- spec/dynamodb/request_spec.rb
|
124
|
+
- spec/dynamodb/success_response_spec.rb
|
135
125
|
- spec/dynamodb_spec.rb
|
136
126
|
- spec/spec_helper.rb
|
data/lib/dynamodb/credentials.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
module DynamoDB
|
2
|
-
class Credentials
|
3
|
-
attr_reader :access_key_id, :secret_access_key, :session_token
|
4
|
-
|
5
|
-
def self.from_hash(hash)
|
6
|
-
new(hash["access_key_id"], hash["secret_access_key"], hash["session_token"])
|
7
|
-
end
|
8
|
-
|
9
|
-
def initialize(access_key_id, secret_access_key, session_token)
|
10
|
-
@access_key_id = access_key_id
|
11
|
-
@secret_access_key = secret_access_key
|
12
|
-
@session_token = session_token
|
13
|
-
end
|
14
|
-
|
15
|
-
def to_hash
|
16
|
-
{
|
17
|
-
"access_key_id" => access_key_id,
|
18
|
-
"secret_access_key" => secret_access_key,
|
19
|
-
"session_token" => session_token
|
20
|
-
}
|
21
|
-
end
|
22
|
-
|
23
|
-
def ==(other)
|
24
|
-
self.class == other.class &&
|
25
|
-
access_key_id == other.access_key_id &&
|
26
|
-
secret_access_key == other.secret_access_key &&
|
27
|
-
session_token == other.session_token
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
data/lib/dynamodb/response.rb
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
module DynamoDB
|
2
|
-
class Response
|
3
|
-
attr_reader :typhoeus_response
|
4
|
-
|
5
|
-
def initialize(typhoeus_response)
|
6
|
-
@typhoeus_response = typhoeus_response
|
7
|
-
end
|
8
|
-
|
9
|
-
def hash_key_element
|
10
|
-
DynamoDB.deserialize(json["LastEvaluatedKey"]["HashKeyElement"])
|
11
|
-
end
|
12
|
-
|
13
|
-
def range_key_element
|
14
|
-
DynamoDB.deserialize(json["LastEvaluatedKey"]["RangeKeyElement"])
|
15
|
-
end
|
16
|
-
|
17
|
-
def item
|
18
|
-
return unless json["Item"]
|
19
|
-
@item ||= DynamoDB.deserialize(json["Item"])
|
20
|
-
end
|
21
|
-
|
22
|
-
def items
|
23
|
-
return unless json["Items"]
|
24
|
-
@items ||= json["Items"].map { |i| DynamoDB.deserialize(i) }
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
def json
|
30
|
-
@json ||= MultiJson.load(typhoeus_response.body)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
@@ -1,110 +0,0 @@
|
|
1
|
-
module DynamoDB
|
2
|
-
attr_writer :access_key_id
|
3
|
-
attr_writer :secret_acces_key
|
4
|
-
attr_writer :session_token
|
5
|
-
|
6
|
-
# SecurityTokenService automatically manages the creation and renewal of
|
7
|
-
# temporary AWS credentials.
|
8
|
-
#
|
9
|
-
# Usage:
|
10
|
-
#
|
11
|
-
# credentials = SecurityTokenService.new "id", "secret key"
|
12
|
-
# credentials.access_key_id # => String
|
13
|
-
# credentials.secret_access_key # => String
|
14
|
-
# credentials.session_token # => String
|
15
|
-
#
|
16
|
-
class SecurityTokenService
|
17
|
-
THIRTY_SIX_HOURS = 129600
|
18
|
-
|
19
|
-
# A SecurityTokenService is initialized for a single AWS user using his
|
20
|
-
# credentials.
|
21
|
-
def initialize(access_key_id, secret_access_key)
|
22
|
-
@_access_key_id = access_key_id
|
23
|
-
@_secret_access_key = secret_access_key
|
24
|
-
@credentials = nil
|
25
|
-
end
|
26
|
-
|
27
|
-
def credentials
|
28
|
-
obtain_credentials
|
29
|
-
@credentials
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def signature(authorization_params)
|
35
|
-
sign(string_to_sign(authorization_params))
|
36
|
-
end
|
37
|
-
|
38
|
-
# The last line needs to be a query string of all parameters
|
39
|
-
# in the request in alphabetical order.
|
40
|
-
def string_to_sign(authorization_params)
|
41
|
-
[
|
42
|
-
"GET",
|
43
|
-
"sts.amazonaws.com",
|
44
|
-
"/",
|
45
|
-
"AWSAccessKeyId=#{@_access_key_id}" +
|
46
|
-
"&Action=GetSessionToken" +
|
47
|
-
"&DurationSeconds=#{THIRTY_SIX_HOURS}" +
|
48
|
-
"&SignatureMethod=HmacSHA256" +
|
49
|
-
"&SignatureVersion=2" +
|
50
|
-
"&Timestamp=#{CGI.escape(authorization_params[:Timestamp])}" +
|
51
|
-
"&Version=2011-06-15"
|
52
|
-
].join("\n")
|
53
|
-
end
|
54
|
-
|
55
|
-
# Extract the contents of a given tag.
|
56
|
-
def get_tag(tag, string)
|
57
|
-
# Considering that the XML string received from STS is sane and always
|
58
|
-
# has the same simple structure, I think a simple regular expression
|
59
|
-
# can do the job (with the benefit of not adding a dependency on
|
60
|
-
# another library just for ONE method). I will switch to Nokogiri if
|
61
|
-
# needed.
|
62
|
-
string.match(/#{tag.to_s}>([^<]*)/)[1]
|
63
|
-
end
|
64
|
-
|
65
|
-
# Obtain temporary credentials, set to expire after 1 hour. If
|
66
|
-
# credentials were previously obtained, no request is made until they
|
67
|
-
# expire.
|
68
|
-
def obtain_credentials
|
69
|
-
return unless credentials_expired?
|
70
|
-
|
71
|
-
authorization_params = {
|
72
|
-
:Action => 'GetSessionToken',
|
73
|
-
:Timestamp => Time.now.utc.iso8601,
|
74
|
-
:Version => '2011-06-15',
|
75
|
-
:DurationSeconds => THIRTY_SIX_HOURS # 36 hour expiration
|
76
|
-
}
|
77
|
-
|
78
|
-
params = {
|
79
|
-
:AWSAccessKeyId => @_access_key_id,
|
80
|
-
:SignatureMethod => 'HmacSHA256',
|
81
|
-
:SignatureVersion => '2',
|
82
|
-
:Signature => signature(authorization_params)
|
83
|
-
}.merge(authorization_params)
|
84
|
-
|
85
|
-
response = Typhoeus::Request.get("https://sts.amazonaws.com", :params => params)
|
86
|
-
if response.success?
|
87
|
-
body = response.body
|
88
|
-
@expiration = Time.parse(get_tag(:Expiration, body))
|
89
|
-
@credentials = Credentials.new(
|
90
|
-
get_tag(:AccessKeyId, body),
|
91
|
-
get_tag(:SecretAccessKey, body),
|
92
|
-
get_tag(:SessionToken, body))
|
93
|
-
else
|
94
|
-
raise AuthenticationError.new(response)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
# Sign (HMAC-SHA256) a string using the secret key given at
|
99
|
-
# initialization.
|
100
|
-
def sign(string)
|
101
|
-
Base64.encode64(
|
102
|
-
OpenSSL::HMAC.digest('sha256', @_secret_access_key, string)
|
103
|
-
).strip
|
104
|
-
end
|
105
|
-
|
106
|
-
def credentials_expired?
|
107
|
-
@expiration.nil? || @expiration <= Time.now.utc
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
module Typhoeus
|
2
|
-
class Request
|
3
|
-
def sign(credentials)
|
4
|
-
headers.merge!('x-amzn-authorization' => "AWS3 AWSAccessKeyId=#{credentials.access_key_id},Algorithm=HmacSHA256,Signature=#{digest(credentials.secret_access_key)}")
|
5
|
-
end
|
6
|
-
|
7
|
-
private
|
8
|
-
|
9
|
-
def digest(secret_key)
|
10
|
-
Base64.encode64(
|
11
|
-
OpenSSL::HMAC.digest('sha256', secret_key, Digest::SHA256.digest(string_to_sign))
|
12
|
-
).strip
|
13
|
-
end
|
14
|
-
|
15
|
-
def string_to_sign
|
16
|
-
"POST\n/\n\nhost:#{parsed_uri.host}\n#{amz_to_sts}\n#{body}"
|
17
|
-
end
|
18
|
-
|
19
|
-
def amz_to_sts
|
20
|
-
get_amz_headers.sort.map {|key, val| [key, val].join(':') + "\n"}.join
|
21
|
-
end
|
22
|
-
|
23
|
-
def get_amz_headers
|
24
|
-
headers.select {|key, val| key =~ /\Ax-amz-/}
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe DynamoDB::Credentials do
|
4
|
-
describe "#==" do
|
5
|
-
it "is true for identical credentials" do
|
6
|
-
DynamoDB::Credentials.new("abc", "123", "token").should ==
|
7
|
-
DynamoDB::Credentials.new("abc", "123", "token")
|
8
|
-
end
|
9
|
-
|
10
|
-
it "is false otherwise" do
|
11
|
-
DynamoDB::Credentials.new("abc", "123", "token").should_not ==
|
12
|
-
DynamoDB::Credentials.new("abc", "123", "different token")
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
describe "#to_hash" do
|
17
|
-
it "converts to a hash and back" do
|
18
|
-
credentials = DynamoDB::Credentials.new("abc", "123", "token")
|
19
|
-
DynamoDB::Credentials.from_hash(credentials.to_hash).should == credentials
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,87 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe DynamoDB::Response do
|
4
|
-
before do
|
5
|
-
body = {
|
6
|
-
"LastEvaluatedKey" => {
|
7
|
-
"HashKeyElement" => {"N"=>"1"},
|
8
|
-
"RangeKeyElement"=>{"N"=>"1501"}
|
9
|
-
},
|
10
|
-
"Items"=>[
|
11
|
-
{
|
12
|
-
"name"=>{"S"=>"John Smith"},
|
13
|
-
"created_at"=>{"N"=>"1321564309.99428"},
|
14
|
-
"disabled"=>{"N"=>"0"},
|
15
|
-
"group_id"=>{"N"=>"1"},
|
16
|
-
"person_id"=>{"N" => "1500"}
|
17
|
-
},
|
18
|
-
{
|
19
|
-
"name"=>{"S"=>"Jane Smith"},
|
20
|
-
"created_at"=>{"N"=>"1321564309.99428"},
|
21
|
-
"disabled"=>{"N"=>"1"},
|
22
|
-
"group_id"=>{"N"=>"1"},
|
23
|
-
"person_id"=>{"N" => "1501"}
|
24
|
-
}
|
25
|
-
],
|
26
|
-
"Count" => 1,
|
27
|
-
"ConsumedCapacityUnits" => 0.5
|
28
|
-
}
|
29
|
-
@typhoeus_response = mock("response", :body => MultiJson.dump(body))
|
30
|
-
end
|
31
|
-
|
32
|
-
describe "#hash_key_element" do
|
33
|
-
it "returns the typecast value of HashKeyElement" do
|
34
|
-
response = DynamoDB::Response.new(@typhoeus_response)
|
35
|
-
response.hash_key_element.should == 1
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
describe "#range_key_element" do
|
40
|
-
it "returns the typecast value of RangeKeyElement" do
|
41
|
-
response = DynamoDB::Response.new(@typhoeus_response)
|
42
|
-
response.range_key_element.should == 1501
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
context "Items" do
|
47
|
-
it "type casts response" do
|
48
|
-
response = DynamoDB::Response.new(@typhoeus_response)
|
49
|
-
response.items[0]["name"].should == "John Smith"
|
50
|
-
response.items[0]["created_at"].should == 1321564309.99428
|
51
|
-
response.items[0]["disabled"].should == 0
|
52
|
-
response.items[0]["group_id"].should == 1
|
53
|
-
response.items[0]["person_id"].should == 1500
|
54
|
-
|
55
|
-
response.items[1]["name"].should == "Jane Smith"
|
56
|
-
response.items[1]["created_at"].should == 1321564309.99428
|
57
|
-
response.items[1]["disabled"].should == 1
|
58
|
-
response.items[1]["group_id"].should == 1
|
59
|
-
response.items[1]["person_id"].should == 1501
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
context "Item" do
|
64
|
-
before do
|
65
|
-
body = {
|
66
|
-
"Item"=> {
|
67
|
-
"name"=>{"S"=>"John Smith"},
|
68
|
-
"created_at"=>{"N"=>"1321564309.99428"},
|
69
|
-
"disabled"=>{"N"=>"0"},
|
70
|
-
"group_id"=>{"N"=>"1"},
|
71
|
-
"person_id"=>{"N" => "1500"}
|
72
|
-
},
|
73
|
-
"ConsumedCapacityUnits" => 0.5
|
74
|
-
}
|
75
|
-
@typhoeus_response = mock("response", :body => MultiJson.dump(body))
|
76
|
-
end
|
77
|
-
|
78
|
-
it "type casts response" do
|
79
|
-
response = DynamoDB::Response.new(@typhoeus_response)
|
80
|
-
response.item["name"].should == "John Smith"
|
81
|
-
response.item["created_at"].should == 1321564309.99428
|
82
|
-
response.item["disabled"].should == 0
|
83
|
-
response.item["group_id"].should == 1
|
84
|
-
response.item["person_id"].should == 1500
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
@@ -1,97 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
-
|
3
|
-
module DynamoDB
|
4
|
-
describe SecurityTokenService do
|
5
|
-
let(:sts) { SecurityTokenService.new("access_key_id", "secret_access_key") }
|
6
|
-
|
7
|
-
context "success" do
|
8
|
-
before do
|
9
|
-
Time.stub(:now).and_return(Time.parse("2012-03-24T22:10:38Z"))
|
10
|
-
success_body = <<-XML
|
11
|
-
<GetSessionTokenResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
|
12
|
-
<GetSessionTokenResult>
|
13
|
-
<Credentials>
|
14
|
-
<SessionToken>session_token</SessionToken>
|
15
|
-
<SecretAccessKey>secret_access_key</SecretAccessKey>
|
16
|
-
<Expiration>2036-03-19T01:03:22.276Z</Expiration>
|
17
|
-
<AccessKeyId>access_key_id</AccessKeyId>
|
18
|
-
</Credentials>
|
19
|
-
</GetSessionTokenResult>
|
20
|
-
<ResponseMetadata>
|
21
|
-
<RequestId>f0fa5827-7156-11e1-8f1e-a92b58fdc66e</RequestId>
|
22
|
-
</ResponseMetadata>
|
23
|
-
</GetSessionTokenResponse>
|
24
|
-
XML
|
25
|
-
|
26
|
-
@request = stub_request(:get, "https://sts.amazonaws.com/").
|
27
|
-
with(:query => {
|
28
|
-
"AWSAccessKeyId" => "access_key_id",
|
29
|
-
"Action" => "GetSessionToken",
|
30
|
-
"Signature" => "HyF65paDxprCe+zEHx7wxah+hiZ43PhvtmeehDtfuw8=",
|
31
|
-
"SignatureMethod" => "HmacSHA256",
|
32
|
-
"SignatureVersion" => "2",
|
33
|
-
"Timestamp" => "2012-03-24T22:10:38Z",
|
34
|
-
"Version" => "2011-06-15",
|
35
|
-
"DurationSeconds" => "129600"
|
36
|
-
}).to_return(:status => 200, :body => success_body)
|
37
|
-
end
|
38
|
-
|
39
|
-
it "obtains session_token, access_key_id, secret_access_key" do
|
40
|
-
sts = SecurityTokenService.new("access_key_id", "secret_access_key")
|
41
|
-
credentials = sts.credentials
|
42
|
-
credentials.access_key_id.should == "access_key_id"
|
43
|
-
credentials.secret_access_key.should == "secret_access_key"
|
44
|
-
credentials.session_token.should == "session_token"
|
45
|
-
end
|
46
|
-
|
47
|
-
it "does not query STS if the credentials are not expired" do
|
48
|
-
sts = SecurityTokenService.new("access_key_id", "secret_access_key")
|
49
|
-
|
50
|
-
sts.stub(:credentials_expired?).and_return(true)
|
51
|
-
sts.credentials
|
52
|
-
@request.should have_been_requested
|
53
|
-
|
54
|
-
WebMock.reset!
|
55
|
-
|
56
|
-
sts.stub(:credentials_expired?).and_return(false)
|
57
|
-
sts.credentials
|
58
|
-
@request.should_not have_been_requested
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
context "failure" do
|
63
|
-
before do
|
64
|
-
Time.stub(:now).and_return(Time.parse("2012-03-24T22:10:38Z"))
|
65
|
-
error_body = <<-XML
|
66
|
-
<ErrorResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
|
67
|
-
<Error>
|
68
|
-
<Type>Sender</Type>
|
69
|
-
<Code>InvalidClientTokenId</Code>
|
70
|
-
<Message>The security token included in the request is invalid</Message>
|
71
|
-
</Error>
|
72
|
-
<RequestId>a9f51cd0-7f5b-11e1-8022-bd0f2fc51c4b</RequestId>
|
73
|
-
</ErrorResponse>
|
74
|
-
XML
|
75
|
-
|
76
|
-
stub_request(:get, "https://sts.amazonaws.com/").
|
77
|
-
with(:query => {
|
78
|
-
"AWSAccessKeyId" => "access_key_id",
|
79
|
-
"Action" => "GetSessionToken",
|
80
|
-
"Signature" => "HyF65paDxprCe+zEHx7wxah+hiZ43PhvtmeehDtfuw8=",
|
81
|
-
"SignatureMethod" => "HmacSHA256",
|
82
|
-
"SignatureVersion" => "2",
|
83
|
-
"Timestamp" => "2012-03-24T22:10:38Z",
|
84
|
-
"Version" => "2011-06-15",
|
85
|
-
"DurationSeconds" => "129600"
|
86
|
-
}).to_return(:status => 403, :body => error_body)
|
87
|
-
end
|
88
|
-
|
89
|
-
it "raises an AuthenticationError" do
|
90
|
-
s = SecurityTokenService.new("access_key_id", "secret_access_key")
|
91
|
-
proc {
|
92
|
-
s.credentials
|
93
|
-
}.should raise_error(DynamoDB::AuthenticationError)
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|