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 CHANGED
@@ -1,3 +1,4 @@
1
1
  pkg/*
2
2
  *.gem
3
3
  .bundle
4
+ lib/sample.rb
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, OpenAuth. 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.
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 the signature provided the query action you want to issue to your ec2 provider
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
- signature = mysig.sign 'DescribeUser', {'Name' => 'jsmith', }
29
- mysig.submit
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', }
@@ -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' => Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ"),
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 signature=signature
56
- require 'net/http'
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+'?'+signature
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
@@ -1,5 +1,5 @@
1
1
  module EC2
2
2
  module Signature
3
- VERSION = "0.0.4"
3
+ VERSION = "0.0.5"
4
4
  end
5
5
  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
@@ -0,0 +1,4 @@
1
+ require 'minitest/autorun'
2
+ $LOAD_PATH << File.expand_path( File.dirname(__FILE__) + '/../lib' )
3
+ require 'ec2-signature'
4
+ require 'fakeweb'
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
- prerelease: false
4
+ hash: 21
5
+ prerelease:
5
6
  segments:
6
7
  - 0
7
8
  - 0
8
- - 4
9
- version: 0.0.4
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-11 00:00:00 -08:00
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.3.6
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