drbservice 1.0.4

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.
@@ -0,0 +1,141 @@
1
+ #!/usr/bin/spec
2
+
3
+ BEGIN {
4
+ require 'pathname'
5
+
6
+ basedir = Pathname( __FILE__ ).dirname.parent.parent
7
+ libdir = basedir + 'lib'
8
+
9
+ $LOAD_PATH.unshift( basedir.to_s ) unless $LOAD_PATH.include?( basedir.to_s )
10
+ $LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
11
+ }
12
+
13
+ require 'digest/sha2'
14
+
15
+ require 'rspec'
16
+ require 'spec/lib/helpers'
17
+
18
+ require 'drbservice'
19
+ require 'drbservice/passwordauth'
20
+
21
+
22
+ describe DRbService::PasswordAuthentication do
23
+ include DRbService::SpecHelpers
24
+
25
+ TEST_PASSWORD = 'hungerlumpkins'
26
+
27
+ before( :all ) do
28
+ setup_logging( :fatal )
29
+ end
30
+
31
+ after( :all ) do
32
+ reset_logging()
33
+ end
34
+
35
+
36
+ describe "mixed into a DRbService" do
37
+
38
+ it "provides a declarative to set a password for the service" do
39
+ serviceclass = Class.new( DRbService ) do
40
+ include DRbService::PasswordAuthentication
41
+ def do_some_stuff; return "Yep."; end
42
+ service_password TEST_PASSWORD
43
+ end
44
+ serviceclass.password_digest.should == Digest::SHA2.hexdigest( TEST_PASSWORD )
45
+ end
46
+
47
+ describe "without a password set" do
48
+
49
+ before( :all ) do
50
+ @serviceclass = Class.new( DRbService ) do
51
+ def do_some_guarded_stuff; return "Ronk."; end
52
+ unguarded do
53
+ def do_some_unguarded_stuff; return "Adonk."; end
54
+ end
55
+ end
56
+ end
57
+
58
+ before( :each ) do
59
+ @serviceobj = @serviceclass.new
60
+ end
61
+
62
+
63
+ it "raises an exception without calling the block on any authentication" do
64
+ block_called = false
65
+ expect {
66
+ @serviceobj.authenticate( '' ) do
67
+ block_called = true
68
+ end
69
+ }.should raise_exception( SecurityError, /authentication failure/i )
70
+ block_called.should == false
71
+ end
72
+
73
+ it "doesn't allow access to guarded methods" do
74
+ expect {
75
+ @serviceobj.do_some_guarded_stuff
76
+ }.to raise_exception( SecurityError, /not authenticated/i )
77
+ end
78
+
79
+ it "allows access to unguarded methods" do
80
+ @serviceobj.do_some_unguarded_stuff.should == 'Adonk.'
81
+ end
82
+
83
+ end
84
+
85
+
86
+ describe "instances with a password set" do
87
+
88
+ before( :each ) do
89
+ @serviceclass = Class.new( DRbService ) do
90
+ include DRbService::PasswordAuthentication
91
+ service_password TEST_PASSWORD
92
+ def do_some_guarded_stuff; return "Ronk."; end
93
+ unguarded do
94
+ def do_some_unguarded_stuff; return "Adonk."; end
95
+ end
96
+ end
97
+ end
98
+
99
+ before( :each ) do
100
+ @serviceobj = @serviceclass.new
101
+ end
102
+
103
+
104
+ it "raises an exception without calling the block on failed authentication" do
105
+ block_called = false
106
+ expect {
107
+ @serviceobj.authenticate( '' ) do
108
+ block_called = true
109
+ end
110
+ }.should raise_exception( SecurityError, /authentication failure/i )
111
+ block_called.should == false
112
+ end
113
+
114
+ it "doesn't allow access to guarded methods before authenticating" do
115
+ expect {
116
+ @serviceobj.do_some_guarded_stuff
117
+ }.to raise_exception( SecurityError, /not authenticated/i )
118
+ end
119
+
120
+ it "allows access to guarded methods after authenticating successfully" do
121
+ @serviceobj.authenticate( TEST_PASSWORD ) do
122
+ @serviceobj.do_some_guarded_stuff.should == 'Ronk.'
123
+ end
124
+ end
125
+
126
+ it "allows access to unguarded methods before authenticating" do
127
+ @serviceobj.do_some_unguarded_stuff.should == 'Adonk.'
128
+ end
129
+
130
+ it "allows access to unguarded methods after authenticating" do
131
+ @serviceobj.authenticate( TEST_PASSWORD ) do
132
+ @serviceobj.do_some_unguarded_stuff.should == 'Adonk.'
133
+ end
134
+ end
135
+
136
+ end
137
+
138
+ end
139
+
140
+ end
141
+
@@ -0,0 +1,168 @@
1
+ #!/usr/bin/spec
2
+
3
+ BEGIN {
4
+ require 'pathname'
5
+
6
+ basedir = Pathname( __FILE__ ).dirname.parent
7
+ libdir = basedir + 'lib'
8
+
9
+ $LOAD_PATH.unshift( basedir.to_s ) unless $LOAD_PATH.include?( basedir.to_s )
10
+ $LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
11
+ }
12
+
13
+ require 'rspec'
14
+ require 'spec/lib/helpers'
15
+
16
+ require 'uri'
17
+ require 'drbservice'
18
+
19
+
20
+ describe DRbService do
21
+ include DRbService::SpecHelpers
22
+
23
+ SERVICE_URI = URI( "drbssl://localhost:8484" )
24
+
25
+ before( :all ) do
26
+ setup_logging( :fatal )
27
+ end
28
+
29
+ after( :all ) do
30
+ reset_logging()
31
+ end
32
+
33
+
34
+ it "is always an 'undumped' service object" do
35
+ testclass = Class.new( DRbService )
36
+ testclass.should include( DRbUndumped )
37
+ end
38
+
39
+ it "doesn't allow instances to be created of itself" do
40
+ expect {
41
+ DRbService.new
42
+ }.should raise_exception( ScriptError, /can't instantiate/ )
43
+ end
44
+
45
+ it "obscures instance methods declared by subclasses by default" do
46
+ testclass = Class.new( DRbService ) do
47
+ def do_some_stuff; return "Yep."; end
48
+ end
49
+ testclass.new.should_not respond_to( :do_some_stuff )
50
+ end
51
+
52
+
53
+ it "provides an 'unguarded' declarative to define instance methods that can " +
54
+ "be used without authentication" do
55
+ testclass = Class.new( DRbService ) do
56
+ unguarded do
57
+ def do_some_stuff; return "Yep."; end
58
+ end
59
+ end
60
+ testclass.new.should respond_to( :do_some_stuff )
61
+ end
62
+
63
+
64
+ describe "subclass" do
65
+
66
+ it "is an 'undumped' service objects" do
67
+ serviceclass = Class.new( DRbService )
68
+ serviceclass.should include( DRbUndumped )
69
+ end
70
+
71
+ it "obscures instance methods by default" do
72
+ serviceclass = Class.new( DRbService ) do
73
+ def do_some_stuff; return "Yep."; end
74
+ end
75
+ serviceclass.new.should_not respond_to( :do_some_stuff )
76
+ end
77
+
78
+
79
+ it "can use an 'unguarded' declarative to define instance methods that can " +
80
+ "be used without authentication" do
81
+ serviceclass = Class.new( DRbService ) do
82
+ unguarded do
83
+ def do_some_stuff; return "Yep."; end
84
+ end
85
+ end
86
+ serviceclass.new.should respond_to( :do_some_stuff )
87
+ end
88
+
89
+
90
+ it "has a .start class method that does the necessary DRb setup and runs the service" do
91
+ serviceclass = Class.new( DRbService )
92
+ drbserver = mock( "drb server" )
93
+ thread = mock( "drb service thread" )
94
+
95
+ File.should_receive( :read ).with( 'service-cert.pem' ).
96
+ and_return( :cert_data )
97
+ OpenSSL::X509::Certificate.should_receive( :new ).with( :cert_data ).
98
+ and_return( :ssl_cert )
99
+ File.should_receive( :read ).with( 'service-key.pem' ).
100
+ and_return( :key_data )
101
+ OpenSSL::PKey::RSA.should_receive( :new ).with( :key_data ).
102
+ and_return( :ssl_key )
103
+
104
+ expected_config = {
105
+ :SSLCertificate => :ssl_cert,
106
+ :SSLPrivateKey => :ssl_key,
107
+ :safe_level => 1,
108
+ :verbose => true,
109
+ }
110
+
111
+ DRb::DRbServer.should_receive( :new ).
112
+ with( SERVICE_URI.to_s, an_instance_of(serviceclass), expected_config ).
113
+ and_return( drbserver )
114
+ drbserver.should_receive( :thread ).and_return( thread )
115
+ thread.should_receive( :join )
116
+
117
+ serviceclass.start( :ip => SERVICE_URI.host, :port => SERVICE_URI.port )
118
+ end
119
+
120
+
121
+ describe "instances without an authentication strategy mixed in" do
122
+
123
+ before( :all ) do
124
+ @serviceclass = Class.new( DRbService ) do
125
+ def do_some_guarded_stuff; return "Ronk."; end
126
+
127
+ unguarded do
128
+ def make_authenticated
129
+ self.log.debug "Making it authenticated!"
130
+ @authenticated = true
131
+ end
132
+ def do_some_unguarded_stuff; return "Adonk."; end
133
+ end
134
+ end
135
+ end
136
+
137
+ before( :each ) do
138
+ @serviceobj = @serviceclass.new
139
+ end
140
+
141
+
142
+ it "raises an exception when #authenticate is called" do
143
+ expect {
144
+ @serviceobj.authenticate( '' )
145
+ }.to raise_exception( SecurityError, /authentication failure/i )
146
+ end
147
+
148
+ it "allows access to unguarded methods without authenticating" do
149
+ @serviceobj.do_some_unguarded_stuff.should == 'Adonk.'
150
+ end
151
+
152
+ it "knows whether the user is authenticated or not" do
153
+ @serviceobj.should_not be_authenticated()
154
+ @serviceobj.make_authenticated
155
+ @serviceobj.should be_authenticated()
156
+ end
157
+
158
+ it "knows whether the user is authorized or not; in the base class authentication " +
159
+ "is sufficient for authorization as well" do
160
+ @serviceobj.should_not be_authorized()
161
+ @serviceobj.make_authenticated
162
+ @serviceobj.should be_authorized()
163
+ end
164
+
165
+ end
166
+
167
+ end
168
+ end
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/ruby
2
+ # coding: utf-8
3
+
4
+ BEGIN {
5
+ require 'pathname'
6
+ basedir = Pathname.new( __FILE__ ).dirname.parent
7
+
8
+ libdir = basedir + "lib"
9
+
10
+ $LOAD_PATH.unshift( basedir.to_s ) unless $LOAD_PATH.include?( basedir.to_s )
11
+ $LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
12
+ }
13
+
14
+ require 'uri'
15
+ require 'yaml'
16
+ require 'drbservice'
17
+
18
+
19
+ module DRbService::TestConstants
20
+
21
+ VALID_SERVICE_URISTRING = "drbauthssl://localhost:8484"
22
+ VALID_SERVICE_URI = URI( VALID_SERVICE_URISTRING )
23
+
24
+ end # module DRbService::TestConstants
25
+
26
+
27
+ ### RSpec helper functions.
28
+ module DRbService::SpecHelpers
29
+
30
+ ### Make an easily-comparable version vector out of +ver+ and return it.
31
+ def vvec( ver )
32
+ return ver.split('.').collect {|char| char.to_i }.pack('N*')
33
+ end
34
+
35
+
36
+ class ArrayLogger
37
+ ### Create a new ArrayLogger that will append content to +array+.
38
+ def initialize( array )
39
+ @array = array
40
+ end
41
+
42
+ ### Write the specified +message+ to the array.
43
+ def write( message )
44
+ @array << message
45
+ end
46
+
47
+ ### No-op -- this is here just so Logger doesn't complain
48
+ def close; end
49
+
50
+ end # class ArrayLogger
51
+
52
+
53
+ unless defined?( LEVEL )
54
+ LEVEL = {
55
+ :debug => Logger::DEBUG,
56
+ :info => Logger::INFO,
57
+ :warn => Logger::WARN,
58
+ :error => Logger::ERROR,
59
+ :fatal => Logger::FATAL,
60
+ }
61
+ end
62
+
63
+ ###############
64
+ module_function
65
+ ###############
66
+
67
+ ### Reset the logging subsystem to its default state.
68
+ def reset_logging
69
+ DRbService.reset_logger
70
+ end
71
+
72
+
73
+ ### Alter the output of the default log formatter to be pretty in SpecMate output
74
+ def setup_logging( level=Logger::FATAL )
75
+
76
+ # Turn symbol-style level config into Logger's expected Fixnum level
77
+ if DRbService::Logging::LEVEL.key?( level )
78
+ level = DRbService::Logging::LEVEL[ level ]
79
+ end
80
+
81
+ logger = Logger.new( $stderr )
82
+ DRbService.logger = logger
83
+ DRbService.logger.level = level
84
+
85
+ # Only do this when executing from a spec in TextMate
86
+ if ENV['HTML_LOGGING'] || (ENV['TM_FILENAME'] && ENV['TM_FILENAME'] =~ /_spec\.rb/)
87
+ Thread.current['logger-output'] = []
88
+ logdevice = ArrayLogger.new( Thread.current['logger-output'] )
89
+ DRbService.logger = Logger.new( logdevice )
90
+ # DRbService.logger.level = level
91
+ DRbService.logger.formatter = DRbService::HtmlLogFormatter.new( logger )
92
+ end
93
+ end
94
+
95
+ end
96
+
97
+ ### Mock with Rspec
98
+ RSpec.configure do |c|
99
+ include DRbService::SpecHelpers,
100
+ DRbService::TestConstants
101
+
102
+ c.mock_with :rspec
103
+
104
+ c.filter_run_excluding( :ruby_1_9_only => true ) unless vvec( RUBY_VERSION ) >= vvec('1.9.0')
105
+ end
106
+
107
+ # vim: set nosta noet ts=4 sw=4:
108
+
metadata ADDED
@@ -0,0 +1,166 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: drbservice
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.4
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Michael Granger
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain:
12
+ - ! '-----BEGIN CERTIFICATE-----
13
+
14
+ MIIDLDCCAhSgAwIBAgIBADANBgkqhkiG9w0BAQUFADA8MQwwCgYDVQQDDANnZWQx
15
+
16
+ FzAVBgoJkiaJk/IsZAEZFgdfYWVyaWVfMRMwEQYKCZImiZPyLGQBGRYDb3JnMB4X
17
+
18
+ DTEwMDkxNjE0NDg1MVoXDTExMDkxNjE0NDg1MVowPDEMMAoGA1UEAwwDZ2VkMRcw
19
+
20
+ FQYKCZImiZPyLGQBGRYHX2FlcmllXzETMBEGCgmSJomT8ixkARkWA29yZzCCASIw
21
+
22
+ DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALy//BFxC1f/cPSnwtJBWoFiFrir
23
+
24
+ h7RicI+joq/ocVXQqI4TDWPyF/8tqkvt+rD99X9qs2YeR8CU/YiIpLWrQOYST70J
25
+
26
+ vDn7Uvhb2muFVqq6+vobeTkILBEO6pionWDG8jSbo3qKm1RjKJDwg9p4wNKhPuu8
27
+
28
+ KGue/BFb67KflqyApPmPeb3Vdd9clspzqeFqp7cUBMEpFS6LWxy4Gk+qvFFJBJLB
29
+
30
+ BUHE/LZVJMVzfpC5Uq+QmY7B+FH/QqNndn3tOHgsPadLTNimuB1sCuL1a4z3Pepd
31
+
32
+ TeLBEFmEao5Dk3K/Q8o8vlbIB/jBDTUx6Djbgxw77909x6gI9doU4LD5XMcCAwEA
33
+
34
+ AaM5MDcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFJeoGkOr9l4B
35
+
36
+ +saMkW/ZXT4UeSvVMA0GCSqGSIb3DQEBBQUAA4IBAQBG2KObvYI2eHyyBUJSJ3jN
37
+
38
+ vEnU3d60znAXbrSd2qb3r1lY1EPDD3bcy0MggCfGdg3Xu54z21oqyIdk8uGtWBPL
39
+
40
+ HIa9EgfFGSUEgvcIvaYqiN4jTUtidfEFw+Ltjs8AP9gWgSIYS6Gr38V0WGFFNzIH
41
+
42
+ aOD2wmu9oo/RffW4hS/8GuvfMzcw7CQ355wFR4KB/nyze+EsZ1Y5DerCAagMVuDQ
43
+
44
+ U0BLmWDFzPGGWlPeQCrYHCr+AcJz+NRnaHCKLZdSKj/RHuTOt+gblRex8FAh8NeA
45
+
46
+ cmlhXe46pZNJgWKbxZah85jIjx95hR8vOI+NAM5iH9kOqK13DrxacTKPhqj5PjwF
47
+
48
+ -----END CERTIFICATE-----
49
+
50
+ '
51
+ date: 2011-08-29 00:00:00.000000000Z
52
+ dependencies:
53
+ - !ruby/object:Gem::Dependency
54
+ name: hoe-mercurial
55
+ requirement: &70270604159400 !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ~>
59
+ - !ruby/object:Gem::Version
60
+ version: 1.2.1
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: *70270604159400
64
+ - !ruby/object:Gem::Dependency
65
+ name: hoe-highline
66
+ requirement: &70270604158900 !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ~>
70
+ - !ruby/object:Gem::Version
71
+ version: 0.0.1
72
+ type: :development
73
+ prerelease: false
74
+ version_requirements: *70270604158900
75
+ - !ruby/object:Gem::Dependency
76
+ name: rspec
77
+ requirement: &70270604158380 !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '2.6'
83
+ type: :development
84
+ prerelease: false
85
+ version_requirements: *70270604158380
86
+ - !ruby/object:Gem::Dependency
87
+ name: hoe
88
+ requirement: &70270604157920 !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: '2.10'
94
+ type: :development
95
+ prerelease: false
96
+ version_requirements: *70270604157920
97
+ description: ! "DRbService is a framework we use at LAIKA for creating authenticated\nSSL-encrypted
98
+ DRb services that provide access to privileged operations\nwithout the need to give
99
+ shell access to everyone.\n\nThere are a few examples in the `examples/` directory
100
+ of the gem, which\nare stripped-down versions of the services we actually use.\n\nThe
101
+ current implementation is kind of a hack, but I intend to \neventually finish a
102
+ DRb protocol that does the same thing in a more\nelegant, less-hackish way, as well
103
+ as a tool that can generate \na new service along with support files for one of
104
+ several different \nruntime environments.\n\nIf you're curious, see the `drb/authsslprotocol.rb`
105
+ file for the \nprotocol. This will replace the current method-hiding code in \n`drbservice.rb`,
106
+ but existing services should be able to switch over\nquite easily. Or that's the
107
+ intention."
108
+ email:
109
+ - ged@FaerieMUD.org
110
+ executables: []
111
+ extensions: []
112
+ extra_rdoc_files:
113
+ - Manifest.txt
114
+ - README.rdoc
115
+ - History.rdoc
116
+ files:
117
+ - ChangeLog
118
+ - History.rdoc
119
+ - LICENSE
120
+ - Manifest.txt
121
+ - README.rdoc
122
+ - Rakefile
123
+ - examples/homedirservice.rb
124
+ - examples/rubyversion.rb
125
+ - lib/drb/authsslprotocol.rb
126
+ - lib/drbservice.rb
127
+ - lib/drbservice/ldapauth.rb
128
+ - lib/drbservice/passwordauth.rb
129
+ - lib/drbservice/utils.rb
130
+ - spec/drb/authsslprotocol_spec.rb
131
+ - spec/drbservice/ldapauth_spec.rb
132
+ - spec/drbservice/passwordauth_spec.rb
133
+ - spec/drbservice_spec.rb
134
+ - spec/lib/helpers.rb
135
+ - .gemtest
136
+ homepage: https://bitbucket.org/ged/drbservice
137
+ licenses:
138
+ - BSD
139
+ post_install_message: ! "\n\nThis library isn't really ready for production use yet,
140
+ but\nfeel free to experiment with it.\n\n\t"
141
+ rdoc_options:
142
+ - --main
143
+ - README.rdoc
144
+ require_paths:
145
+ - lib
146
+ required_ruby_version: !ruby/object:Gem::Requirement
147
+ none: false
148
+ requirements:
149
+ - - ! '>='
150
+ - !ruby/object:Gem::Version
151
+ version: 1.8.7
152
+ required_rubygems_version: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ requirements: []
159
+ rubyforge_project: drbservice
160
+ rubygems_version: 1.8.8
161
+ signing_key:
162
+ specification_version: 3
163
+ summary: DRbService is a framework we use at LAIKA for creating authenticated SSL-encrypted
164
+ DRb services that provide access to privileged operations without the need to give
165
+ shell access to everyone
166
+ test_files: []