happening 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +25 -0
- data/lib/happening/s3/item.rb +6 -5
- data/lib/happening/s3/request.rb +7 -3
- data/lib/happening/s3.rb +16 -0
- data/lib/happening.rb +1 -0
- data/test/s3/item_test.rb +31 -0
- data/test/s3/request_test.rb +9 -2
- data/test/s3_test.rb +32 -0
- metadata +5 -3
data/README.md
CHANGED
@@ -124,6 +124,31 @@ Happening support the simple S3 PUT upload:
|
|
124
124
|
|
125
125
|
Amazon returns no content on delete, so having a success handler is usually not needed for delete operations.
|
126
126
|
|
127
|
+
SSL Support
|
128
|
+
=============
|
129
|
+
|
130
|
+
Happening will use SSL/HTTPS by default. What it cannot do by default is verify the SSL certificate. This means
|
131
|
+
that traffic is encrypted but nobody can say if the SSL-endpoint is the one you except. In order to verify the
|
132
|
+
SSL certificate you need to provide Happening with the path to a certificate CA collection in PEM format:
|
133
|
+
|
134
|
+
Happening::S3.ssl_options[:cert_chain_file] = '/etc/ca-bundle.crt'
|
135
|
+
|
136
|
+
You can also set this option on each item:
|
137
|
+
|
138
|
+
Happening::S3::Item.new('bucket', 'item_id',
|
139
|
+
:aws_access_key_id => 'A',
|
140
|
+
:aws_secret_access_key => 'B',
|
141
|
+
:ssl => {
|
142
|
+
:cert_chain_file => '/etc/ca-bundle.crt'
|
143
|
+
}
|
144
|
+
|
145
|
+
Or even on the request:
|
146
|
+
|
147
|
+
item.get(:ssl => {:cert_chain_file => '/etc/ca-bundle.crt'})
|
148
|
+
|
149
|
+
The SSL options are directly passed to EventMachine, see the [EventMachine documentation](http://eventmachine.rubyforge.org/EventMachine/Connection.html#M000296) for more information on the SSL support.
|
150
|
+
|
151
|
+
|
127
152
|
Credits
|
128
153
|
=============
|
129
154
|
|
data/lib/happening/s3/item.rb
CHANGED
@@ -18,9 +18,10 @@ module Happening
|
|
18
18
|
:aws_access_key_id => nil,
|
19
19
|
:aws_secret_access_key => nil,
|
20
20
|
:retry_count => 4,
|
21
|
-
:permissions => 'private'
|
21
|
+
:permissions => 'private',
|
22
|
+
:ssl => Happening::S3.ssl_options
|
22
23
|
}.update(options.symbolize_keys)
|
23
|
-
options.assert_valid_keys(:timeout, :server, :protocol, :aws_access_key_id, :aws_secret_access_key, :retry_count, :permissions)
|
24
|
+
options.assert_valid_keys(:timeout, :server, :protocol, :aws_access_key_id, :aws_secret_access_key, :retry_count, :permissions, :ssl)
|
24
25
|
@aws_id = aws_id.to_s
|
25
26
|
@bucket = bucket.to_s
|
26
27
|
|
@@ -31,21 +32,21 @@ module Happening
|
|
31
32
|
headers = needs_to_sign? ? aws.sign("GET", path) : {}
|
32
33
|
request_options[:on_success] = blk if blk
|
33
34
|
request_options.update(:headers => headers)
|
34
|
-
Happening::S3::Request.new(:get, url, request_options).execute
|
35
|
+
Happening::S3::Request.new(:get, url, {:ssl => options[:ssl]}.update(request_options)).execute
|
35
36
|
end
|
36
37
|
|
37
38
|
def put(data, request_options = {}, &blk)
|
38
39
|
headers = construct_aws_headers('PUT', request_options.delete(:headers) || {})
|
39
40
|
request_options[:on_success] = blk if blk
|
40
41
|
request_options.update(:headers => headers, :data => data)
|
41
|
-
Happening::S3::Request.new(:put, url, request_options).execute
|
42
|
+
Happening::S3::Request.new(:put, url, {:ssl => options[:ssl]}.update(request_options)).execute
|
42
43
|
end
|
43
44
|
|
44
45
|
def delete(request_options = {}, &blk)
|
45
46
|
headers = needs_to_sign? ? aws.sign("DELETE", path, {'url' => path}) : {}
|
46
47
|
request_options[:on_success] = blk if blk
|
47
48
|
request_options.update(:headers => headers)
|
48
|
-
Happening::S3::Request.new(:delete, url, request_options).execute
|
49
|
+
Happening::S3::Request.new(:delete, url, {:ssl => options[:ssl]}.update(request_options)).execute
|
49
50
|
end
|
50
51
|
|
51
52
|
def url
|
data/lib/happening/s3/request.rb
CHANGED
@@ -13,9 +13,13 @@ module Happening
|
|
13
13
|
:headers => {},
|
14
14
|
:on_error => nil,
|
15
15
|
:on_success => nil,
|
16
|
-
:data => nil
|
16
|
+
:data => nil,
|
17
|
+
:ssl => {
|
18
|
+
:cert_chain_file => nil,
|
19
|
+
:verify_peer => false
|
20
|
+
}
|
17
21
|
}.update(options)
|
18
|
-
options.assert_valid_keys(:timeout, :on_success, :on_error, :retry_count, :headers, :data)
|
22
|
+
options.assert_valid_keys(:timeout, :on_success, :on_error, :retry_count, :headers, :data, :ssl)
|
19
23
|
@http_method = http_method
|
20
24
|
@url = url
|
21
25
|
|
@@ -24,7 +28,7 @@ module Happening
|
|
24
28
|
|
25
29
|
def execute
|
26
30
|
Happening::Log.debug "#{http_method.to_s.upcase} #{url}"
|
27
|
-
@response = http_class.new(url).send(http_method, :timeout => options[:timeout], :head => options[:headers], :body => options[:data])
|
31
|
+
@response = http_class.new(url).send(http_method, :timeout => options[:timeout], :head => options[:headers], :body => options[:data], :ssl => options[:ssl])
|
28
32
|
|
29
33
|
@response.errback { error_callback }
|
30
34
|
@response.callback { success_callback }
|
data/lib/happening/s3.rb
ADDED
data/lib/happening.rb
CHANGED
@@ -5,6 +5,7 @@ require 'active_support'
|
|
5
5
|
|
6
6
|
require File.dirname(__FILE__) + '/happening/log'
|
7
7
|
require File.dirname(__FILE__) + '/happening/aws'
|
8
|
+
require File.dirname(__FILE__) + '/happening/s3'
|
8
9
|
require File.dirname(__FILE__) + '/happening/s3/request'
|
9
10
|
require File.dirname(__FILE__) + '/happening/s3/item'
|
10
11
|
|
data/test/s3/item_test.rb
CHANGED
@@ -454,5 +454,36 @@ class ItemTest < Test::Unit::TestCase
|
|
454
454
|
|
455
455
|
end
|
456
456
|
|
457
|
+
context "SSL options" do
|
458
|
+
setup do
|
459
|
+
Happening::S3.ssl_options[:verify_peer] = true
|
460
|
+
Happening::S3.ssl_options[:cert_chain_file] = '/etc/foo.ca'
|
461
|
+
end
|
462
|
+
|
463
|
+
should "re-use the global options" do
|
464
|
+
item = Happening::S3::Item.new('bucket', 'the-key', :aws_access_key_id => 'abc', :aws_secret_access_key => '123')
|
465
|
+
assert item.options[:ssl][:verify_peer]
|
466
|
+
assert_equal '/etc/foo.ca', item.options[:ssl][:cert_chain_file]
|
467
|
+
end
|
468
|
+
|
469
|
+
should "allow to override global options" do
|
470
|
+
item = Happening::S3::Item.new('bucket', 'the-key', :aws_access_key_id => 'abc', :aws_secret_access_key => '123', :ssl => {:cert_chain_file => nil, :verify_peer => false})
|
471
|
+
assert !item.options[:ssl][:verify_peer]
|
472
|
+
assert_nil item.options[:ssl][:cert_chain_file]
|
473
|
+
end
|
474
|
+
|
475
|
+
should "pass the options to the Request" do
|
476
|
+
item = Happening::S3::Item.new('bucket', 'the-key', :aws_access_key_id => 'abc', :aws_secret_access_key => '123')
|
477
|
+
Happening::S3::Request.expects(:new).with(:get, anything, {:ssl => {:cert_chain_file => '/etc/foo.ca', :verify_peer => true}, :headers => {'Authorization' => 'AWS abc:LGLdCdGTuLAHs+InbMWEnQR6djc=', 'date' => 'Thu, 25 Feb 2010 10:00:00 GMT'}}).returns(stub(:execute => nil))
|
478
|
+
item.get
|
479
|
+
end
|
480
|
+
|
481
|
+
should "allow to override the options per request" do
|
482
|
+
item = Happening::S3::Item.new('bucket', 'the-key', :aws_access_key_id => 'abc', :aws_secret_access_key => '123')
|
483
|
+
Happening::S3::Request.expects(:new).with(:get, anything, {:ssl => {:foo => :bar}, :headers => {'Authorization' => 'AWS abc:LGLdCdGTuLAHs+InbMWEnQR6djc=', 'date' => 'Thu, 25 Feb 2010 10:00:00 GMT'}}).returns(stub(:execute => nil))
|
484
|
+
item.get(:ssl => {:foo => :bar})
|
485
|
+
end
|
486
|
+
end
|
487
|
+
|
457
488
|
end
|
458
489
|
end
|
data/test/s3/request_test.rb
CHANGED
@@ -45,18 +45,25 @@ class ItemTest < Test::Unit::TestCase
|
|
45
45
|
|
46
46
|
should "pass the given headers and options" do
|
47
47
|
request = mock('em-http-request')
|
48
|
-
request.expects(:get).with(:timeout => 10, :head => {'a' => 'b'}, :body => nil).returns(@response_stub)
|
48
|
+
request.expects(:get).with(:timeout => 10, :head => {'a' => 'b'}, :body => nil, :ssl => {:verify_peer => false, :cert_chain_file => nil}).returns(@response_stub)
|
49
49
|
EventMachine::MockHttpRequest.expects(:new).with('https://www.example.com').returns(request)
|
50
50
|
Happening::S3::Request.new(:get, 'https://www.example.com', :headers => {'a' => 'b'}).execute
|
51
51
|
end
|
52
52
|
|
53
53
|
should "post any given data" do
|
54
54
|
request = mock('em-http-request')
|
55
|
-
request.expects(:put).with(:timeout => 10, :body => 'the-data', :head => {}).returns(@response_stub)
|
55
|
+
request.expects(:put).with(:timeout => 10, :body => 'the-data', :head => {}, :ssl => {:verify_peer => false, :cert_chain_file => nil}).returns(@response_stub)
|
56
56
|
EventMachine::MockHttpRequest.expects(:new).with('https://www.example.com').returns(request)
|
57
57
|
Happening::S3::Request.new(:put, 'https://www.example.com', :data => 'the-data').execute
|
58
58
|
end
|
59
59
|
|
60
|
+
should "pass SSL options to em-http-request" do
|
61
|
+
request = mock('em-http-request')
|
62
|
+
request.expects(:put).with(:timeout => 10, :body => 'the-data', :head => {}, :ssl => {:verfiy_peer => true, :cert_chain_file => '/tmp/server.crt'}).returns(@response_stub)
|
63
|
+
EventMachine::MockHttpRequest.expects(:new).with('https://www.example.com').returns(request)
|
64
|
+
Happening::S3::Request.new(:put, 'https://www.example.com', :data => 'the-data', :ssl => {:verfiy_peer => true, :cert_chain_file => '/tmp/server.crt'}).execute
|
65
|
+
end
|
66
|
+
|
60
67
|
context "when handling errors" do
|
61
68
|
should "call the user error handler" do
|
62
69
|
EventMachine::MockHttpRequest.register('http://www.example.com:80/', :get, {}, error_response(400))
|
data/test/s3_test.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/test_helper"
|
2
|
+
|
3
|
+
class S3Test < Test::Unit::TestCase
|
4
|
+
context "The Happening::S3 module" do
|
5
|
+
|
6
|
+
should "allow to set global SSL options" do
|
7
|
+
assert Happening::S3.respond_to?(:ssl_options)
|
8
|
+
assert Happening::S3.respond_to?(:ssl_options=)
|
9
|
+
end
|
10
|
+
|
11
|
+
should "set and get verify_peer" do
|
12
|
+
Happening::S3.ssl_options[:verify_peer] = true
|
13
|
+
assert Happening::S3.ssl_options[:verify_peer]
|
14
|
+
Happening::S3.ssl_options[:verify_peer] = false
|
15
|
+
assert !Happening::S3.ssl_options[:verify_peer]
|
16
|
+
end
|
17
|
+
|
18
|
+
should "set and get cert_chain_file" do
|
19
|
+
Happening::S3.ssl_options[:cert_chain_file] = '/etc/cacert'
|
20
|
+
assert_equal '/etc/cacert', Happening::S3.ssl_options[:cert_chain_file]
|
21
|
+
Happening::S3.ssl_options[:cert_chain_file] = nil
|
22
|
+
assert_nil Happening::S3.ssl_options[:cert_chain_file]
|
23
|
+
end
|
24
|
+
|
25
|
+
should "default to no certificate file and no verification" do
|
26
|
+
Happening::S3.instance_variable_set("@_ssl_options", nil)
|
27
|
+
assert !Happening::S3.ssl_options[:verify_peer]
|
28
|
+
assert_nil Happening::S3.ssl_options[:cert_chain_file]
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 8
|
9
|
+
version: 0.0.8
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Jonathan Weiss
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-04-
|
17
|
+
date: 2010-04-30 00:00:00 +02:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -56,6 +56,7 @@ files:
|
|
56
56
|
- lib/happening.rb
|
57
57
|
- lib/happening/aws.rb
|
58
58
|
- lib/happening/log.rb
|
59
|
+
- lib/happening/s3.rb
|
59
60
|
- lib/happening/s3/item.rb
|
60
61
|
- lib/happening/s3/request.rb
|
61
62
|
has_rdoc: true
|
@@ -92,4 +93,5 @@ test_files:
|
|
92
93
|
- test/aws_test.rb
|
93
94
|
- test/s3/item_test.rb
|
94
95
|
- test/s3/request_test.rb
|
96
|
+
- test/s3_test.rb
|
95
97
|
- test/test_helper.rb
|