ec2-signature 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/README +9 -6
- data/lib/ec2-signature.rb +8 -6
- data/lib/ec2-signature/version.rb +1 -1
- data/test/test_ec2_signature.rb +134 -0
- data/test/test_helper.rb +4 -0
- metadata +15 -7
data/.gitignore
CHANGED
data/README
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Code borrowed from fog (https://github.com/geemus/fog).
|
2
2
|
|
3
|
-
This gem will simply generate the AWS EC2 signature so that you can use your own HTTP methods and libraries to POST to your choice of AWS/EC2 compatible API servers such as Eucalyptus, OpenNebula,
|
3
|
+
This gem will simply generate the AWS EC2 signature so that you can use your own HTTP methods and libraries to POST/GET to your choice of AWS/EC2 compatible API servers such as Eucalyptus, OpenNebula, OpenStack. Apparently, most of the AWS/EC2 API gems out there are not compatible with the aforementioned cloud frameworks, due to running on a custom port they do not account for that when generating the signature. Fog had implemented a compatible signature method, however, I did not want to use the EXCON http library implemented in it so I extracted the signature method only for use with my own choice of HTTP library.
|
4
4
|
|
5
5
|
##############################
|
6
6
|
#### OpenStack Example 1 ####
|
@@ -13,11 +13,11 @@ mysig = EC2Signature.new( {
|
|
13
13
|
:awssecretkey => '1380adj13j43jklj32a',
|
14
14
|
:ec2url => 'http://myec2server:8773/services/Cloud'
|
15
15
|
} )
|
16
|
-
# generate
|
16
|
+
# to generate a signature only, provide the query action you want to issue to your ec2 provider
|
17
17
|
mysig.sign 'DescribeImages'
|
18
18
|
signature = mysig.signature
|
19
|
-
# use the example net/http post method to post your signature to the ec2_url specified above
|
20
|
-
mysig.submit
|
19
|
+
# OR use the example net/http post method to post your signature to the ec2_url specified above
|
20
|
+
mysig.submit 'DescribeImages' # will parse the xml body and return a data hash
|
21
21
|
|
22
22
|
|
23
23
|
##############################
|
@@ -25,5 +25,8 @@ mysig.submit
|
|
25
25
|
##############################
|
26
26
|
# opennebula's aws/ec2 api implementation has a diff path for admin cmds
|
27
27
|
mysig.path = '/services/Admin'
|
28
|
-
|
29
|
-
mysig.
|
28
|
+
# generate only the signature if you want:
|
29
|
+
mysig.sign 'DescribeUser', {'Name' => 'jsmith', }
|
30
|
+
signature = mysig.signature
|
31
|
+
# OR use the example net/http post method to post your signature to the ec2_url specified above
|
32
|
+
mysig.submit 'DescribeUser', {'Name' => 'jsmith', }
|
data/lib/ec2-signature.rb
CHANGED
@@ -2,6 +2,7 @@ require 'uri'
|
|
2
2
|
require 'openssl'
|
3
3
|
require 'base64'
|
4
4
|
require 'cgi'
|
5
|
+
require 'net/http'
|
5
6
|
|
6
7
|
class EC2Signature
|
7
8
|
|
@@ -25,7 +26,7 @@ class EC2Signature
|
|
25
26
|
self.method = method
|
26
27
|
end
|
27
28
|
|
28
|
-
def sign action='DescribeInstances', actionparams={}
|
29
|
+
def sign action='DescribeInstances', actionparams={}, timestamp=Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ")
|
29
30
|
raise 'actionparams needs to be a Hash' unless actionparams.kind_of?(Hash)
|
30
31
|
# openstack requires project names added to end of awssecretkey to change project context
|
31
32
|
newaccessid = ( project ? awsaccessid+':'+project : awsaccessid )
|
@@ -34,7 +35,7 @@ class EC2Signature
|
|
34
35
|
'AWSAccessKeyId' => newaccessid,
|
35
36
|
'SignatureMethod' => 'HmacSHA256',
|
36
37
|
'SignatureVersion' => '2',
|
37
|
-
'Timestamp' =>
|
38
|
+
'Timestamp' => timestamp,
|
38
39
|
'Version' => '2010-08-31'
|
39
40
|
})
|
40
41
|
|
@@ -52,14 +53,15 @@ class EC2Signature
|
|
52
53
|
self
|
53
54
|
end
|
54
55
|
|
55
|
-
def submit
|
56
|
-
require '
|
56
|
+
def submit action='DescribeInstances', actionparams={}, timestamp=Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ"), raw=false
|
57
|
+
require 'crack'
|
58
|
+
sign action, actionparams, timestamp
|
57
59
|
http = Net::HTTP.new host, port
|
58
60
|
resp = case method
|
59
|
-
when 'GET' then http.get path
|
61
|
+
when 'GET' then http.get path.concat('?'+signature)
|
60
62
|
when 'POST' then http.post path, signature
|
61
63
|
end
|
62
|
-
resp.body
|
64
|
+
raw ? resp.body : Crack::XML.parse(resp.body)[action.concat('Response')]
|
63
65
|
end
|
64
66
|
|
65
67
|
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'cgi'
|
3
|
+
|
4
|
+
$creds = {:awsaccessid => 'abc123', :awssecretkey => '12i3jfae138', :ec2url => 'http://blah.com:112/some/yo'}
|
5
|
+
$timestamp = Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ")
|
6
|
+
|
7
|
+
describe EC2Signature do
|
8
|
+
describe '#new' do
|
9
|
+
it 'should accept :awsaccessid, :awssecretkey, :ec2url' do
|
10
|
+
assert EC2Signature.new $creds
|
11
|
+
end
|
12
|
+
it 'should throw an error if missing :ec2url' do
|
13
|
+
tmpcreds = $creds.dup.delete :ec2url
|
14
|
+
proc { EC2Signature.new tmpcreds }.must_raise RuntimeError
|
15
|
+
end
|
16
|
+
it 'should throw an error if missing :awssecretkey' do
|
17
|
+
tmpcreds = $creds.dup.delete :awssecretkey
|
18
|
+
proc {EC2Signature.new tmpcreds }.must_raise RuntimeError
|
19
|
+
end
|
20
|
+
it 'should throw an error if missing :awsaccessid' do
|
21
|
+
tmpcreds = $creds.dup.delete :awsaccessid
|
22
|
+
proc {EC2Signature.new tmpcreds}.must_raise RuntimeError
|
23
|
+
end
|
24
|
+
it 'should create an EC2Signature class obj' do
|
25
|
+
EC2Signature.new($creds).must_be_kind_of EC2Signature
|
26
|
+
end
|
27
|
+
it 'should only allow GET or POST methods' do
|
28
|
+
proc {EC2Signature.new $creds, 'PUT' }.must_raise RuntimeError
|
29
|
+
assert EC2Signature.new $creds, 'GET'
|
30
|
+
end
|
31
|
+
end # describe '#new' do
|
32
|
+
|
33
|
+
describe 'the instance' do
|
34
|
+
before do
|
35
|
+
@ec2 = EC2Signature.new $creds
|
36
|
+
end
|
37
|
+
it 'should have an :awsaccessid attribute' do
|
38
|
+
assert @ec2.awsaccessid
|
39
|
+
assert_equal @ec2.awsaccessid, $creds[:awsaccessid]
|
40
|
+
end
|
41
|
+
it 'should have an :awssecretkey attribute' do
|
42
|
+
assert_equal @ec2.awssecretkey, $creds[:awssecretkey]
|
43
|
+
end
|
44
|
+
it 'should have an :ec2url attribute' do
|
45
|
+
assert_equal @ec2.ec2url, $creds[:ec2url]
|
46
|
+
end
|
47
|
+
it 'should have a :host attribute parsed from the ec2url' do
|
48
|
+
assert_equal @ec2.host, 'blah.com'
|
49
|
+
end
|
50
|
+
it 'should have a :port attribute parsed from the ec2url' do
|
51
|
+
assert_equal @ec2.port, 112
|
52
|
+
end
|
53
|
+
it 'should have a :path attribute parsed from the ec2url' do
|
54
|
+
assert_equal @ec2.path, '/some/yo'
|
55
|
+
end
|
56
|
+
it 'should have a :scheme attribute parsed from the ec2url' do
|
57
|
+
assert_equal @ec2.scheme, 'http'
|
58
|
+
end
|
59
|
+
it 'should have a :method attribute and default value should be POST' do
|
60
|
+
assert_equal @ec2.method, 'POST'
|
61
|
+
end
|
62
|
+
it 'should start with a nil project' do
|
63
|
+
@ec2.project.must_be_nil
|
64
|
+
end
|
65
|
+
it 'should allow you to set a project' do
|
66
|
+
@ec2.project='testproject'.must_equal 'testproject'
|
67
|
+
end
|
68
|
+
it 'should start with a nil signature' do
|
69
|
+
@ec2.signature.must_be_nil
|
70
|
+
end
|
71
|
+
end # describe 'the instance' do
|
72
|
+
|
73
|
+
describe '#sign' do
|
74
|
+
before do
|
75
|
+
@ec2 = EC2Signature.new $creds
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'should require no args' do
|
79
|
+
@ec2.sign.must_be_kind_of EC2Signature
|
80
|
+
@ec2.signature.wont_be_nil
|
81
|
+
end
|
82
|
+
it 'should default to DescribeInstances action param' do
|
83
|
+
@ec2.sign.signature.must_match /Action=DescribeInstances/
|
84
|
+
end
|
85
|
+
it 'should allow custom ec2 action string' do
|
86
|
+
@ec2.sign('DescribeImages').signature.must_match /Action=DescribeImages/
|
87
|
+
end
|
88
|
+
it 'should allow custom ec2 action strings that have more than one query param' do
|
89
|
+
actionparams = {'Name' => 'ami1390'}
|
90
|
+
@ec2.sign('DescribeImage', actionparams).signature.must_match /Action=DescribeImage&Name=ami1390/
|
91
|
+
end
|
92
|
+
it 'should allow specify a timestamp' do
|
93
|
+
@ec2.sign('DescribeInstances',{},$timestamp).signature.must_match /Timestamp=#{CGI::escape $timestamp}/
|
94
|
+
end
|
95
|
+
it 'should return an ec2 compatible signature' do
|
96
|
+
known_timestamp = '2011-02-20T06:25:50Z'
|
97
|
+
known_signature = 'AWSAccessKeyId=abc123&Action=DescribeInstances&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2011-02-20T06%3A25%3A50Z&Version=2010-08-31&Signature=0fuHYXhygt2osdqtnRww1WFR2nHMwk0wvhiCOxuS3AY%3D'
|
98
|
+
@ec2.sign('DescribeInstances',{},known_timestamp).signature.must_equal known_signature
|
99
|
+
end
|
100
|
+
it 'should append the ":project" string to awsaccessid in the signature (cgi escaped)' do
|
101
|
+
@ec2.sign.signature.must_match /KeyId=#{$creds[:awsaccessid]}&Action/ # before specifying project
|
102
|
+
@ec2.project = 'someproj'
|
103
|
+
@ec2.sign.signature.must_match /KeyId=#{CGI::escape $creds[:awsaccessid]+':someproj'}/
|
104
|
+
end
|
105
|
+
end # describe '#sign' do
|
106
|
+
|
107
|
+
describe '#submit' do
|
108
|
+
$xml = "<?xml version=\"1.0\" ?><DescribeInstancesResponse xmlns=\"http://ec2.amazonaws.com/doc/2010-08-31/\"><requestId>G4DU2RXB59NMIX84UW9F</requestId><reservationSet><item><ownerId>jsmith</ownerId><groupSet><item><groupId>default</groupId></item></groupSet><reservationId>r-5oexkoz1</reservationId><instancesSet><item><displayDescription/><displayName>Server 198</displayName><keyName>None (jsmith, cm-02)</keyName><instanceId>i-000000c6</instanceId><instanceState><code>1</code><name>running</name></instanceState><publicDnsName/><imageId>ami-usc3oydl</imageId><productCodesSet/><privateDnsName>10.1.1.17</privateDnsName><dnsName>10.1.1.17</dnsName><launchTime>2011-02-20 07:17:03</launchTime><placement><availabilityZone>nova</availabilityZone></placement><amiLaunchIndex>0</amiLaunchIndex><instanceType>m1.small</instanceType></item></instancesSet></item></reservationSet></DescribeInstancesResponse>"
|
109
|
+
|
110
|
+
before do
|
111
|
+
FakeWeb.register_uri(:post, $creds[:ec2url], :body => $xml)
|
112
|
+
@ec2 = EC2Signature.new $creds
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'by default should submit via POST' do
|
116
|
+
@ec2.submit.must_be_kind_of Hash
|
117
|
+
end
|
118
|
+
it 'should allow you to also submit via GET' do
|
119
|
+
FakeWeb.register_uri(:get, %r|#{$creds[:ec2url]}|, :body => $xml)
|
120
|
+
@ec2.method = 'GET'
|
121
|
+
@ec2.submit.must_be_kind_of Hash
|
122
|
+
end
|
123
|
+
it 'by default should return a Hash' do
|
124
|
+
@ec2.submit.must_be_kind_of Hash
|
125
|
+
end
|
126
|
+
it 'should allow you to return the raw xml instead of Hash' do
|
127
|
+
# the catch is that you won't be able to use the default arg param values
|
128
|
+
raw = @ec2.submit('DescribeInstances', {}, $timestamp, true)
|
129
|
+
raw.must_be_kind_of String
|
130
|
+
raw.must_match /<?xml version=\"1.0\"/
|
131
|
+
end
|
132
|
+
end # describe '#submit' do
|
133
|
+
|
134
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ec2-signature
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 21
|
5
|
+
prerelease:
|
5
6
|
segments:
|
6
7
|
- 0
|
7
8
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
9
|
+
- 5
|
10
|
+
version: 0.0.5
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- John Tran
|
@@ -14,7 +15,7 @@ autorequire:
|
|
14
15
|
bindir: bin
|
15
16
|
cert_chain: []
|
16
17
|
|
17
|
-
date: 2011-02-
|
18
|
+
date: 2011-02-20 00:00:00 -08:00
|
18
19
|
default_executable:
|
19
20
|
dependencies: []
|
20
21
|
|
@@ -35,6 +36,8 @@ files:
|
|
35
36
|
- ec2-signature.gemspec
|
36
37
|
- lib/ec2-signature.rb
|
37
38
|
- lib/ec2-signature/version.rb
|
39
|
+
- test/test_ec2_signature.rb
|
40
|
+
- test/test_helper.rb
|
38
41
|
has_rdoc: true
|
39
42
|
homepage: http://rubygems.org/gems/ec2-signature
|
40
43
|
licenses: []
|
@@ -45,25 +48,30 @@ rdoc_options: []
|
|
45
48
|
require_paths:
|
46
49
|
- lib
|
47
50
|
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
48
52
|
requirements:
|
49
53
|
- - ">="
|
50
54
|
- !ruby/object:Gem::Version
|
55
|
+
hash: 3
|
51
56
|
segments:
|
52
57
|
- 0
|
53
58
|
version: "0"
|
54
59
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
55
61
|
requirements:
|
56
62
|
- - ">="
|
57
63
|
- !ruby/object:Gem::Version
|
64
|
+
hash: 3
|
58
65
|
segments:
|
59
66
|
- 0
|
60
67
|
version: "0"
|
61
68
|
requirements: []
|
62
69
|
|
63
70
|
rubyforge_project: ec2-signature
|
64
|
-
rubygems_version: 1.
|
71
|
+
rubygems_version: 1.5.2
|
65
72
|
signing_key:
|
66
73
|
specification_version: 3
|
67
74
|
summary: generate a signature to be posted to any EC2 compatible API
|
68
|
-
test_files:
|
69
|
-
|
75
|
+
test_files:
|
76
|
+
- test/test_ec2_signature.rb
|
77
|
+
- test/test_helper.rb
|