openldap 0.0.1pre11

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,65 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'rbconfig'
4
+ require 'erb'
5
+ require 'etc'
6
+ require 'logger'
7
+
8
+ require 'openldap'
9
+
10
+
11
+ #--
12
+ # A collection of mixins shared between OpenLDAP classes. Stolen mostly from ThingFish.
13
+ #
14
+ module OpenLDAP # :nodoc:
15
+
16
+ # Add logging to a OpenLDAP class. Including classes get #log and #log_debug methods.
17
+ module Loggable
18
+
19
+ LEVEL = {
20
+ :debug => Logger::DEBUG,
21
+ :info => Logger::INFO,
22
+ :warn => Logger::WARN,
23
+ :error => Logger::ERROR,
24
+ :fatal => Logger::FATAL,
25
+ }
26
+
27
+ ### A logging proxy class that wraps calls to the logger into calls that include
28
+ ### the name of the calling class.
29
+ class ClassNameProxy # :nodoc:
30
+
31
+ ### Create a new proxy for the given +klass+.
32
+ def initialize( klass, force_debug=false )
33
+ @classname = klass.name
34
+ @force_debug = force_debug
35
+ end
36
+
37
+ ### Delegate calls the global logger with the class name as the 'progname'
38
+ ### argument.
39
+ def method_missing( sym, msg=nil, &block )
40
+ return super unless LEVEL.key?( sym )
41
+ sym = :debug if @force_debug
42
+ OpenLDAP.logger.add( LEVEL[sym], msg, @classname, &block )
43
+ end
44
+ end # ClassNameProxy
45
+
46
+ #########
47
+ protected
48
+ #########
49
+
50
+ ### Return the proxied logger.
51
+ def log
52
+ @log_proxy ||= ClassNameProxy.new( self.class )
53
+ end
54
+
55
+ ### Return a proxied "debug" logger that ignores other level specification.
56
+ def log_debug
57
+ @log_debug_proxy ||= ClassNameProxy.new( self.class, true )
58
+ end
59
+ end # module Loggable
60
+
61
+
62
+ end # module OpenLDAP
63
+
64
+ # vim: set nosta noet ts=4 sw=4:
65
+
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'logger'
4
+ require 'erb'
5
+
6
+ require 'openldap' unless defined?( OpenLDAP )
7
+
8
+ module OpenLDAP # :nodoc:
9
+
10
+ # A alternate formatter for Logger instances.
11
+ class LogFormatter < Logger::Formatter # :nodoc:
12
+
13
+ # The format to output unless debugging is turned on
14
+ DEFAULT_FORMAT = "[%1$s.%2$06d %3$d/%4$s] %5$5s -- %7$s\n"
15
+
16
+ # The format to output if debugging is turned on
17
+ DEFAULT_DEBUG_FORMAT = "[%1$s.%2$06d %3$d/%4$s] %5$5s {%6$s} -- %7$s\n"
18
+
19
+
20
+ ### Initialize the formatter with a reference to the logger so it can check for log level.
21
+ def initialize( logger, format=DEFAULT_FORMAT, debug=DEFAULT_DEBUG_FORMAT ) # :notnew:
22
+ @logger = logger
23
+ @format = format
24
+ @debug_format = debug
25
+
26
+ super()
27
+ end
28
+
29
+ ######
30
+ public
31
+ ######
32
+
33
+ # The Logger object associated with the formatter
34
+ attr_accessor :logger
35
+
36
+ # The logging format string
37
+ attr_accessor :format
38
+
39
+ # The logging format string that's used when outputting in debug mode
40
+ attr_accessor :debug_format
41
+
42
+
43
+ ### Log using either the DEBUG_FORMAT if the associated logger is at ::DEBUG level or
44
+ ### using FORMAT if it's anything less verbose.
45
+ def call( severity, time, progname, msg )
46
+ args = [
47
+ time.strftime( '%Y-%m-%d %H:%M:%S' ), # %1$s
48
+ time.usec, # %2$d
49
+ Process.pid, # %3$d
50
+ Thread.current == Thread.main ? 'main' : Thread.object_id, # %4$s
51
+ severity, # %5$s
52
+ progname, # %6$s
53
+ msg # %7$s
54
+ ]
55
+
56
+ if @logger.level == Logger::DEBUG
57
+ return self.debug_format % args
58
+ else
59
+ return self.format % args
60
+ end
61
+ end
62
+ end # class LogFormatter
63
+
64
+
65
+ # An alternate formatter for Logger instances that outputs +dd+ HTML
66
+ # fragments.
67
+ class HtmlLogFormatter < Logger::Formatter # :nodoc:
68
+ include ERB::Util # for html_escape()
69
+
70
+ # The default HTML fragment that'll be used as the template for each log message.
71
+ HTML_LOG_FORMAT = %q{
72
+ <div class="log-message %5$s">
73
+ <span class="log-time">%1$s.%2$06d</span>
74
+ [
75
+ <span class="log-pid">%3$d</span>
76
+ /
77
+ <span class="log-tid">%4$s</span>
78
+ ]
79
+ <span class="log-level">%5$s</span>
80
+ :
81
+ <span class="log-name">%6$s</span>
82
+ <span class="log-message-text">%7$s</span>
83
+ </div>
84
+ }
85
+
86
+ ### Override the logging formats with ones that generate HTML fragments
87
+ def initialize( logger, format=HTML_LOG_FORMAT ) # :notnew:
88
+ @logger = logger
89
+ @format = format
90
+ super()
91
+ end
92
+
93
+
94
+ ######
95
+ public
96
+ ######
97
+
98
+ # The HTML fragment that will be used as a format() string for the log
99
+ attr_accessor :format
100
+
101
+
102
+ ### Return a log message composed out of the arguments formatted using the
103
+ ### formatter's format string
104
+ def call( severity, time, progname, msg )
105
+ args = [
106
+ time.strftime( '%Y-%m-%d %H:%M:%S' ), # %1$s
107
+ time.usec, # %2$d
108
+ Process.pid, # %3$d
109
+ Thread.current == Thread.main ? 'main' : Thread.object_id, # %4$s
110
+ severity.downcase, # %5$s
111
+ progname, # %6$s
112
+ html_escape( msg ).gsub(/\n/, '<br />') # %7$s
113
+ ]
114
+
115
+ return self.format % args
116
+ end
117
+
118
+ end # class HtmlLogFormatter
119
+
120
+ end # module OpenLDAP
121
+
122
+ # vim: set nosta noet ts=4 sw=4:
123
+
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pathname'
4
+
5
+ require 'openldap'
6
+
7
+
8
+ module OpenLDAP::TestConstants
9
+
10
+ unless defined?( TEST_LDAP_URI )
11
+
12
+ TEST_CONFIG_FILE = Pathname( __FILE__ ).dirname.parent.parent + 'test.conf'
13
+
14
+ TEST_LOCAL_LDAP_STRING = 'ldap://localhost'
15
+ TEST_LOCAL_LDAP_URI = URI( TEST_LOCAL_LDAP_STRING )
16
+
17
+ TEST_LDAP_STRING = 'ldap://ldap.example.com'
18
+ TEST_LDAP_URI = URI( TEST_LDAP_STRING )
19
+
20
+ TEST_LDAPBASE_STRING = 'ldap://ldap.example.com/dc=example,dc=com'
21
+ TEST_LDAPBASE_URI = URI( TEST_LDAPBASE_STRING )
22
+
23
+ constants.each do |cname|
24
+ const_get(cname).freeze
25
+ end
26
+ end
27
+
28
+ end
29
+
@@ -0,0 +1,128 @@
1
+ #!/usr/bin/ruby
2
+ # coding: utf-8
3
+
4
+ BEGIN {
5
+ require 'rbconfig'
6
+ require 'pathname'
7
+ basedir = Pathname.new( __FILE__ ).dirname.parent
8
+
9
+ libdir = basedir + "lib"
10
+ extdir = libdir + Config::CONFIG['sitearch']
11
+
12
+ $LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
13
+ $LOAD_PATH.unshift( extdir.to_s ) unless $LOAD_PATH.include?( extdir.to_s )
14
+ }
15
+
16
+ require 'pp'
17
+ require 'yaml'
18
+ require 'logger'
19
+
20
+ require 'openldap'
21
+ require 'openldap/mixins'
22
+
23
+ require 'spec/lib/constants'
24
+
25
+ ### Return a string-comparable version vector from +version+.
26
+ def vvec( version )
27
+ return version.split( '.' ).map( &:to_i ).pack( 'N' )
28
+ end
29
+
30
+
31
+ ### RSpec helper functions.
32
+ module OpenLDAP::SpecHelpers
33
+ include OpenLDAP::TestConstants
34
+
35
+ class ArrayLogger
36
+ ### Create a new ArrayLogger that will append content to +array+.
37
+ def initialize( array )
38
+ @array = array
39
+ end
40
+
41
+ ### Write the specified +message+ to the array.
42
+ def write( message )
43
+ @array << message
44
+ end
45
+
46
+ ### No-op -- this is here just so Logger doesn't complain
47
+ def close; end
48
+
49
+ end # class ArrayLogger
50
+
51
+
52
+ unless defined?( LEVEL )
53
+ LEVEL = {
54
+ :debug => Logger::DEBUG,
55
+ :info => Logger::INFO,
56
+ :warn => Logger::WARN,
57
+ :error => Logger::ERROR,
58
+ :fatal => Logger::FATAL,
59
+ }
60
+ end
61
+
62
+
63
+ ###############
64
+ module_function
65
+ ###############
66
+
67
+ ### Reset the logging subsystem to its default state.
68
+ def reset_logging
69
+ OpenLDAP.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 OpenLDAP::Loggable::LEVEL.key?( level )
78
+ level = OpenLDAP::Loggable::LEVEL[ level ]
79
+ end
80
+
81
+ logger = Logger.new( $stderr )
82
+ OpenLDAP.logger = logger
83
+ OpenLDAP.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
+ OpenLDAP.logger = Logger.new( logdevice )
90
+ # OpenLDAP.logger.level = level
91
+ OpenLDAP.logger.formatter = OpenLDAP::HtmlLogFormatter.new( OpenLDAP.logger )
92
+ end
93
+ end
94
+
95
+
96
+ ### Load the testing LDAP config options from a YAML file.
97
+ def load_ldap_config
98
+ unless defined?( @ldap_config ) && @ldap_config
99
+ if TEST_CONFIG_FILE.exist?
100
+ $stderr.puts "Loading LDAP config from #{TEST_CONFIG_FILE}" if $VERBOSE
101
+ @ldap_config = YAML.load( TEST_CONFIG_FILE.read )
102
+ else
103
+ $stderr.puts "Skipping tests that require access to a live directory. Copy the ",
104
+ "#{TEST_CONFIG_FILE}-example file and provide valid values for testing",
105
+ "with an actual LDAP."
106
+ @ldap_config = {}
107
+ end
108
+ end
109
+
110
+ return @ldap_config
111
+ end
112
+
113
+ end
114
+
115
+
116
+ ### Mock with Rspec
117
+ RSpec.configure do |config|
118
+ include OpenLDAP::TestConstants
119
+
120
+ config.mock_with :rspec
121
+ config.include( OpenLDAP::SpecHelpers )
122
+
123
+ config.filter_run_excluding( :ruby_1_9_only => true ) if vvec( RUBY_VERSION ) >= vvec( '1.9.0' )
124
+ config.filter_run_excluding( :with_ldap_server => true ) unless TEST_CONFIG_FILE.exist?
125
+ end
126
+
127
+ # vim: set nosta noet ts=4 sw=4:
128
+
@@ -0,0 +1,190 @@
1
+ #!/usr/bin/env rspec -cfd -b
2
+
3
+ BEGIN {
4
+ require 'pathname'
5
+ basedir = Pathname( __FILE__ ).dirname.parent.parent
6
+ libdir = basedir + 'lib'
7
+
8
+ $LOAD_PATH.unshift( basedir.to_s ) unless $LOAD_PATH.include?( basedir.to_s )
9
+ $LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
10
+ }
11
+
12
+ require 'uri'
13
+ require 'rspec'
14
+ require 'spec/lib/helpers'
15
+ require 'openldap/connection'
16
+
17
+ describe OpenLDAP::Connection do
18
+
19
+ before( :all ) do
20
+ setup_logging( :fatal )
21
+ end
22
+
23
+ after( :all ) do
24
+ reset_logging()
25
+ end
26
+
27
+
28
+ it "can be created with an LDAP URI" do
29
+ conn = OpenLDAP::Connection.new( TEST_LDAP_URI )
30
+ conn.uris.should == [ TEST_LDAP_URI ]
31
+ end
32
+
33
+ it "can be created with an LDAP URI String" do
34
+ conn = OpenLDAP::Connection.new( TEST_LDAP_URI.to_s )
35
+ conn.uris.should == [ TEST_LDAP_URI ]
36
+ end
37
+
38
+ it "can be created with several LDAP URIs" do
39
+ conn = OpenLDAP::Connection.new( TEST_LDAP_URI, TEST_LOCAL_LDAP_URI )
40
+ conn.uris.should == [ TEST_LDAP_URI, TEST_LOCAL_LDAP_URI ]
41
+ end
42
+
43
+ context "an instance" do
44
+
45
+ before( :each ) do
46
+ @conn = OpenLDAP::Connection.new( TEST_LDAP_URI )
47
+ end
48
+
49
+ it "can set the cacert file used for TLS" do
50
+ @conn.tls_cacertfile = Pathname( '/etc/openssl/cacerts/ldap.pem' )
51
+ @conn.tls_cacertfile.should == '/etc/openssl/cacerts/ldap.pem'
52
+ end
53
+
54
+ it "can set the cacert directory used for TLS" do
55
+ @conn.tls_cacertdir = Pathname( '/etc/openssl/cacerts' )
56
+ @conn.tls_cacertdir.should == '/etc/openssl/cacerts'
57
+ end
58
+
59
+ it "can set the certificate file used for TLS" do
60
+ @conn.tls_certfile = Pathname( '/etc/openssl/host.pem' )
61
+ @conn.tls_certfile.should == '/etc/openssl/host.pem'
62
+ end
63
+
64
+
65
+ it "can set the cipher suite used for TLS" do
66
+ @conn.tls_cipher_suite = 'HIGH:MEDIUM:+SSLv2'
67
+ @conn.tls_cipher_suite.should == 'HIGH:MEDIUM:+SSLv2'
68
+ end
69
+
70
+ it "can set the CRL checking strategy used for TLS" do
71
+ @conn.tls_crlcheck = :all
72
+ @conn.tls_crlcheck.should == :all
73
+ end
74
+
75
+ it "can set the CRL file used for TLS" do
76
+ @conn.tls_crlfile = '/var/db/036D5FF52BA395A08BA2F780F9ADEAD905431757.crl'
77
+ @conn.tls_crlfile.should == '/var/db/036D5FF52BA395A08BA2F780F9ADEAD905431757.crl'
78
+ end
79
+
80
+ it "can set the dhfile used for TLS" do
81
+ @conn.tls_dhfile = '/etc/openssl/dh1024.pem'
82
+ @conn.tls_dhfile.should == '/etc/openssl/dh1024.pem'
83
+ end
84
+
85
+ it "can set the keyfile used for TLS" do
86
+ @conn.tls_keyfile = '/etc/openssl/host.key'
87
+ @conn.tls_keyfile.should == '/etc/openssl/host.key'
88
+ end
89
+
90
+ it "can set the package used for TLS in recent versions of libldap" do
91
+ if OpenLDAP.api_info[:vendor_name] == "OpenLDAP" &&
92
+ OpenLDAP.api_info[:vendor_version] >= 20426
93
+ @conn.tls_package.should == 'OpenSSL'
94
+ else
95
+ expect {
96
+ @conn.tls_package
97
+ }.to raise_error( NotImplementedError, /version of libldap/i )
98
+ end
99
+ end
100
+
101
+ it "can set the minimum protocol version used for TLS" do
102
+ @conn.tls_protocol_min = 11
103
+ @conn.tls_protocol_min.should == 11
104
+ end
105
+
106
+ it "can set the random_file used for TLS" do
107
+ # :TODO: Don't know how to test this appropriately.
108
+ # @conn.tls_random_file = '/dev/urandom'
109
+ @conn.tls_random_file.should be_nil()
110
+ end
111
+
112
+ it "can set the certificate verification strategy used for TLS" do
113
+ @conn.tls_require_cert = :demand
114
+ @conn.tls_require_cert.should == :demand
115
+ end
116
+
117
+ it "can be set to time out if the connect(2) takes longer than 2 seconds" do
118
+ @conn.network_timeout = 2.0
119
+ @conn.network_timeout.should == 2.0
120
+ end
121
+
122
+ it "can have its network timeout reset" do
123
+ @conn.network_timeout = nil
124
+ @conn.network_timeout.should be_nil()
125
+ end
126
+
127
+ it "can connect asynchronously" do
128
+ @conn.async_connect?.should be_false()
129
+ @conn.async_connect = true
130
+ @conn.async_connect?.should be_true()
131
+ end
132
+
133
+ it "can disable asynchronous connections after they've been enabled" do
134
+ @conn.async_connect = true
135
+ @conn.async_connect = false
136
+ @conn.async_connect?.should be_false()
137
+ end
138
+
139
+ end
140
+
141
+ context "an unconnected instance" do
142
+
143
+ before( :each ) do
144
+ @conn = OpenLDAP::Connection.new( TEST_LDAP_URI )
145
+ end
146
+
147
+ it "knows that its file-descriptor is nil" do
148
+ @conn.fdno.should be_nil()
149
+ end
150
+
151
+ end
152
+
153
+
154
+ it "can start TLS negotiation synchronously", :with_ldap_server => true do
155
+ config = load_ldap_config()
156
+ uri = config['uri'] or abort "No 'uri' in the test config!"
157
+
158
+ conn = OpenLDAP::Connection.new( uri )
159
+ conn.start_tls
160
+ end
161
+
162
+ context "a connected instance", :with_ldap_server => true do
163
+
164
+ before( :all ) do
165
+ config = load_ldap_config()
166
+ @uri = config['uri'] or abort "No 'uri' in the test config!"
167
+ end
168
+
169
+ before( :each ) do
170
+ @conn = OpenLDAP::Connection.new( @uri )
171
+ @conn.start_tls
172
+ end
173
+
174
+ it "knows what its file-descriptor is" do
175
+ @conn.fdno.should be_a( Fixnum )
176
+ @conn.fdno.should > 2 # Something past STDERR
177
+ end
178
+
179
+ it "can return an IO for selecting against its file-descriptor" do
180
+ @conn.socket.should be_an( IO )
181
+ @conn.socket.fileno.should == @conn.fdno
182
+ @conn.socket.should_not be_autoclose()
183
+ @conn.socket.should_not be_close_on_exec()
184
+ @conn.socket.should be_binmode()
185
+ end
186
+
187
+ end
188
+
189
+ end
190
+