ec2-signature 0.0.4 → 0.0.5
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/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
|