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 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