Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Adding LDAP protocol ping support #4

Merged
merged 5 commits into from

2 participants

Paul Gallagher Daniel Berger
Paul Gallagher

Hi Daniel, I've added an ldap module with tests to net-ping. It helps go beyond simple tcp tests and actually talk LDAP to bind/verify. I've also removed a deprecated gemspec element but left the version and other details as before.

  • LDAP protocol-specific ping
  • added Gemfile for bundler
  • removed deprecated gemspec elements
tardate added some commits
Paul Gallagher tardate Added initial Net::Ping::LDAP implementation
* LDAP protocol-specific ping
* added Gemfile for bundler
* removed deprecated gemspec elements
0f62d00
Paul Gallagher tardate Add ping/ldap include to main project 84dee6b
Daniel Berger
Owner

Looks pretty good, thanks. The only mistake I noticed was the documentation for intialize.

I'll pull after you fix the docs. Also, I don't want Gemfiles in my project.

Paul Gallagher tardate Update Ping::LDAP documentation
* removed Gemfile from the project
01f8ac7
Paul Gallagher

Hi Daniel, here you go .. updated the docs and removed the Gemfile. I think you should see the pull request now includes updated commit range.
Cheers, and thanks for the library .. have you really been maintaining this since 2002? Impressive!

tardate added some commits
Paul Gallagher tardate bad ping after good should unset duration
* in 1.4.1, a bad ping after a good ping will leave @duration set at the result of the good ping. I'd expect it to unset @duration .. this commit includes a test and a fix for this behaviour
4c18e5b
Paul Gallagher tardate Add Ping::LDAP test for bad ping after good 965031c
Daniel Berger djberg96 merged commit 965031c into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 29, 2011
  1. Paul Gallagher

    Added initial Net::Ping::LDAP implementation

    tardate authored
    * LDAP protocol-specific ping
    * added Gemfile for bundler
    * removed deprecated gemspec elements
  2. Paul Gallagher
Commits on Apr 30, 2011
  1. Paul Gallagher

    Update Ping::LDAP documentation

    tardate authored
    * removed Gemfile from the project
Commits on May 4, 2011
  1. Paul Gallagher

    bad ping after good should unset duration

    tardate authored
    * in 1.4.1, a bad ping after a good ping will leave @duration set at the result of the good ping. I'd expect it to unset @duration .. this commit includes a test and a fix for this behaviour
  2. Paul Gallagher
This page is out of date. Refresh to see the latest.
11 Rakefile
View
@@ -39,6 +39,11 @@ namespace 'example' do
task :udp do
ruby '-Ilib examples/example_pingudp.rb'
end
+
+ desc 'Run the ldap ping example program'
+ task :ldap do
+ ruby '-Ilib examples/example_pingldap.rb'
+ end
end
Rake::TestTask.new do |t|
@@ -84,6 +89,12 @@ namespace 'test' do
t.verbose = true
t.test_files = FileList['test/test_net_ping_wmi.rb']
end
+
+ Rake::TestTask.new('ldap') do |t|
+ t.warning = true
+ t.verbose = true
+ t.test_files = FileList['test/test_net_ping_ldap.rb']
+ end
end
task :default => :test
25 doc/ping.txt
View
@@ -43,6 +43,7 @@
* Ping::HTTP
* Ping::ICMP
* Ping::WMI
+ * Ping::LDAP
All Ping classes are children of the Ping parent class (which should
never be instantiated directly).
@@ -135,6 +136,30 @@ Ping::WMI#ping(host, options={})
Ping::WMI#ping?(host, options={})
Returns whether or not the ping succeeded.
+== Ping::LDAP
+Ping::LDAP.new(uri=nil, timeout=5)
+ Performs a 'ping' to an LDAP server in the form of either an anonymous
+ or an authenticated LDAP bind.
+ Identical to Net::Ping.new except that, instead of a host, the first
+ argument is a URI.
+ The default +timeout+ is 5 seconds.
+
+ +uri+ string is expected to be a full URI with scheme (ldap/ldaps)
+ and optionally the port (else default port is assumed) e.g.
+ ldap://my.ldap.host.com
+ ldap://my.ldap.host.com:1389
+ ldaps://my.ldap.host.com
+ ldaps://my.ldap.host.com:6636
+
+ If a plain hostname is provided as the +uri+, a default port of 389 is assumed
+
+Ping::LDAP#encryption
+ Set/get the encyption method. By default is nil, but may be set to :simple_tls
+
+Ping::LDAP#username
+Ping::LDAP#password
+ set/get the username and password for ping using and authenticated bind.
+
= Common Instance Methods
Ping#exception
Returns the error string that was set if a ping call failed. If an exception
22 examples/example_pingldap.rb
View
@@ -0,0 +1,22 @@
+########################################################################
+# example_pingldap.rb
+#
+# A short sample program demonstrating an ldap ping. You can run
+# this program via the example:ldap task. Modify as you see fit.
+########################################################################
+require 'net/ping/ldap'
+
+good = 'ldap://localhost'
+bad = 'ldap://example.com'
+
+puts "== Good ping (if you have an ldap server at #{good})"
+
+p1 = Net::Ping::LDAP.new(good)
+p p1.ping?
+
+puts "== Bad ping"
+
+p2 = Net::Ping::LDAP.new(bad)
+p p2.ping?
+p p2.warning
+p p2.exception
1  lib/net/ping.rb
View
@@ -9,6 +9,7 @@
require File.join(File.dirname(__FILE__), 'ping/icmp')
require File.join(File.dirname(__FILE__), 'ping/external')
require File.join(File.dirname(__FILE__), 'ping/http')
+require File.join(File.dirname(__FILE__), 'ping/ldap')
if Config::CONFIG['host_os'] =~ /msdos|mswin|cygwin|mingw|win32|windows/i
require File.join(File.dirname(__FILE__), 'ping/wmi')
107 lib/net/ping/ldap.rb
View
@@ -0,0 +1,107 @@
+require File.join(File.dirname(__FILE__), 'ping')
+require 'net/ldap'
+require 'uri'
+
+
+# The Net module serves as a namespace only.
+module Net
+
+ # The Ping::LDAP class encapsulates methods for LDAP pings.
+ class Ping::LDAP < Ping
+
+ # uri contains the URI object for the request
+ #
+ attr_accessor :uri
+
+ # username and password may be set for ping using
+ # an authenticated LDAP bind
+ #
+ attr_accessor :username
+ attr_accessor :password
+
+ # set/get the encryption method. By default nil,
+ # but may be set to :simple_tls
+ #
+ attr_accessor :encryption
+ def encryption=(value)
+ @encryption = (value.is_a? Symbol) ? value : value.to_sym
+ end
+
+ # Creates and returns a new Ping::LDAP object.
+ # The default +timeout+ is 5 seconds.
+ #
+ # +uri+ string is expected to be a full URI with scheme (ldap/ldaps)
+ # and optionally the port (else default port is assumed) e.g.
+ # ldap://my.ldap.host.com
+ # ldap://my.ldap.host.com:1389
+ # ldaps://my.ldap.host.com
+ # ldaps://my.ldap.host.com:6636
+ #
+ # If a plain hostname is provided as the +uri+, a default port of 389 is assumed
+ #
+ def initialize(uri=nil, timeout=5)
+ host, port = decode_uri(uri)
+ super(host, port, timeout)
+ end
+
+ # method used to decode uri string
+ #
+ def decode_uri(value)
+ @uri = URI.parse(value)
+ if uri.scheme =~ /ldap/
+ p = @port = uri.port
+ h = @host = uri.host
+ @encryption = uri.scheme=='ldaps' ? :simple_tls : nil
+ else
+ h = value
+ p = 389
+ end
+ [h, p]
+ end
+
+ # constructs the LDAP configuration structure
+ #
+ def config
+ {
+ :host => uri.host,
+ :port => uri.port,
+ :encryption => encryption
+ }.merge(
+ (username && password) ?
+ { :auth => {:method => :simple, :username => username, :password => password} } :
+ { :auth => {:method => :anonymous} }
+ )
+ end
+
+ # perform ping, optionally providing the ping destination uri
+ #
+ def ping(host = nil)
+ decode_uri(host) if host
+ super(@host)
+
+ bool = false
+
+ start_time = Time.now
+
+ begin
+ Timeout.timeout(@timeout) do
+ Net::LDAP.new( config ).bind
+ end
+ rescue Net::LDAP::LdapError => e
+ @exception = e.message
+ rescue Exception => e
+ @exception = e.message
+ else
+ bool = true
+ end
+
+ # There is no duration if the ping failed
+ @duration = Time.now - start_time if bool
+
+ bool
+ end
+
+ alias ping? ping
+ alias pingecho ping
+ end
+end
1  lib/net/ping/ping.rb
View
@@ -80,6 +80,7 @@ def ping(host = @host)
raise ArgumentError, 'no host specified' unless host
@exception = nil
@warning = nil
+ @duration = nil
end
alias ping? ping
5 net-ping.gemspec
View
@@ -10,14 +10,15 @@ Gem::Specification.new do |gem|
gem.homepage = 'http://www.rubyforge.org/projects/shards'
gem.summary = 'A ping interface for Ruby.'
gem.test_file = 'test/test_net_ping.rb'
- gem.has_rdoc = true
gem.files = Dir['**/*'].reject{ |f| f.include?('git') }
gem.rubyforge_project = 'shards'
gem.extra_rdoc_files = ['README', 'CHANGES', 'doc/ping.txt']
+ gem.add_dependency('net-ldap', '~> 0.2.2')
gem.add_development_dependency('test-unit', '>= 2.1.2')
gem.add_development_dependency('fakeweb', '>= 1.3.0')
+ gem.add_development_dependency('fakeldap', '~> 0.0.1')
# These dependencies are for Net::Ping::External
if File::ALT_SEPARATOR && RUBY_PLATFORM != 'java'
@@ -32,7 +33,7 @@ Gem::Specification.new do |gem|
gem.description = <<-EOF
The net-ping library provides a ping interface for Ruby. It includes
- separate TCP, HTTP, ICMP, UDP, WMI (for Windows) and external ping
+ separate TCP, HTTP, LDAP, ICMP, UDP, WMI (for Windows) and external ping
classes.
EOF
end
7 test/test_net_ping_external.rb
View
@@ -59,6 +59,13 @@ def setup
assert_kind_of(Float, @pe.duration)
end
+ test "duration is unset if a bad ping follows a good ping" do
+ assert_nothing_raised{ @pe.ping }
+ assert_not_nil(@pe.duration)
+ assert_false(@pe.ping?(@bogus))
+ assert_nil(@pe.duration)
+ end
+
test "host getter basic functionality" do
assert_respond_to(@pe, :host)
assert_equal('www.ruby-lang.org', @pe.host)
200 test/test_net_ping_ldap.rb
View
@@ -0,0 +1,200 @@
+#################################################################################
+# test_net_ping_http.rb
+#
+# Test case for the Net::PingHTTP class. This should be run via the 'test' or
+# 'test:http' Rake task.
+#################################################################################
+require 'rubygems'
+gem 'test-unit'
+
+require 'test/unit'
+require 'net/ping/ldap'
+require 'fakeldap'
+
+class TC_Net_Ping_LDAP < Test::Unit::TestCase
+ class << self
+ def startup
+ @@host = 'localhost'
+ @@port = 2389
+ @@uri = "ldap://#{@@host}:#{@@port}"
+ @@timeout = 30
+ @@cn = 'el.Daper'
+ @@password = 'ldappassword'
+
+ @@ldap_server = FakeLDAP::Server.new(:port => @@port)
+ @@ldap_server.run_tcpserver
+ @@ldap_server.add_user("cn=#{@@cn},ou=USERS,dc=example,dc=com", @@password)
+ end
+ def shutdown
+ @@ldap_server.stop
+ end
+ end
+ def setup
+ @ldap = Net::Ping::LDAP.new(@@uri, @@timeout)
+ @ldap.username = @@cn
+ @ldap.password = @@password
+ @bogus = 'ldap://blabfoobarurghxxxx.com' # One hopes so
+ @bad = Net::Ping::LDAP.new(@bogus)
+ end
+
+ def teardown
+ @ldap = nil
+ end
+
+ test 'ping basic functionality' do
+ assert_respond_to(@ldap, :ping)
+ assert_nothing_raised{ @ldap.ping }
+ end
+
+ test 'ping returns a boolean value' do
+ assert_boolean(@ldap.ping?)
+ assert_boolean(@bad.ping?)
+ end
+
+ test 'ping? is an alias for ping' do
+ assert_alias_method(@ldap, :ping?, :ping)
+ end
+
+ test 'pingecho is an alias for ping' do
+ assert_alias_method(@ldap, :pingecho, :ping)
+ end
+
+ test 'ping should succeed for a valid website' do
+ assert_true(@ldap.ping?)
+ end
+
+ test 'ping should fail for an invalid website' do
+ assert_false(@bad.ping?)
+ end
+
+ test 'duration basic functionality' do
+ assert_respond_to(@ldap, :duration)
+ assert_nothing_raised{ @ldap.ping }
+ end
+
+ test 'duration returns a float value on a successful ping' do
+ assert_true(@ldap.ping)
+ assert_kind_of(Float, @ldap.duration)
+ end
+
+ test 'duration is nil on an unsuccessful ping' do
+ assert_false(@bad.ping)
+ assert_nil(@ldap.duration)
+ end
+
+ test "duration is unset if a bad ping follows a good ping" do
+ assert_true{ @ldap.ping }
+ assert_not_nil(@ldap.duration)
+ assert_false(@ldap.ping?(@bogus))
+ assert_nil(@ldap.duration)
+ end
+
+ test 'host attribute basic functionality' do
+ assert_respond_to(@ldap, :host)
+ assert_respond_to(@ldap, :host=)
+ assert_equal(@@host, @ldap.host)
+ end
+
+ test 'port attribute basic functionality' do
+ assert_respond_to(@ldap, :port)
+ assert_respond_to(@ldap, :port=)
+ end
+
+ test 'port attribute expected value' do
+ assert_equal(@@port, @ldap.port)
+ end
+
+ test 'timeout attribute basic functionality' do
+ assert_respond_to(@ldap, :timeout)
+ assert_respond_to(@ldap, :timeout=)
+ end
+
+ test 'timeout attribute expected values' do
+ assert_equal(@@timeout, @ldap.timeout)
+ assert_equal(5, @bad.timeout)
+ end
+
+ test 'exception attribute basic functionality' do
+ assert_respond_to(@ldap, :exception)
+ assert_nil(@ldap.exception)
+ end
+
+ test 'exception attribute is nil if the ping is successful' do
+ assert_true(@ldap.ping)
+ assert_nil(@ldap.exception)
+ end
+
+ test 'exception attribute is not nil if the ping is unsuccessful' do
+ assert_false(@bad.ping)
+ assert_not_nil(@bad.exception)
+ end
+
+ test 'warning attribute basic functionality' do
+ assert_respond_to(@ldap, :warning)
+ assert_nil(@ldap.warning)
+ end
+
+ test 'uri attribute basic functionality' do
+ assert_respond_to(@ldap, :uri)
+ assert_respond_to(@ldap, :uri=)
+ end
+
+ test 'username attribute basic functionality' do
+ assert_respond_to(@ldap, :username)
+ assert_respond_to(@ldap, :username=)
+ end
+
+ test 'password attribute basic functionality' do
+ assert_respond_to(@ldap, :password)
+ assert_respond_to(@ldap, :password=)
+ end
+
+ test 'encryption attribute basic functionality' do
+ assert_respond_to(@ldap, :encryption)
+ assert_respond_to(@ldap, :encryption=)
+ end
+
+ test 'encryption defaults to nil for ldap' do
+ assert_nil(Net::Ping::LDAP.new('ldap://somehost.example.net').encryption)
+ end
+
+ test 'encryption defaults to simple_tls for ldaps' do
+ assert_equal(:simple_tls, Net::Ping::LDAP.new('ldaps://somehost.example.net').encryption)
+ end
+
+ test 'port defaults to 389 for ldap' do
+ assert_equal(389, Net::Ping::LDAP.new('ldap://somehost.example.net').port)
+ end
+
+ test 'port defaults to 636 for ldaps' do
+ assert_equal(636, Net::Ping::LDAP.new('ldaps://somehost.example.net').port)
+ end
+
+ test 'port extracted from uri if provided' do
+ assert_equal(12345, Net::Ping::LDAP.new('ldap://somehost.example.net:12345').port)
+ assert_equal(12345, Net::Ping::LDAP.new('ldaps://somehost.example.net:12345').port)
+ end
+
+ test 'encryption setting is forced to symbol' do
+ @ldap.encryption = 'simple_tls'
+ assert_true( @ldap.encryption.is_a? Symbol )
+ assert_true( @ldap.config[:encryption].is_a? Symbol )
+ end
+
+ test 'username/password set in config auth section' do
+ @ldap.username, @ldap.password = 'fred', 'derf'
+ assert_equal('fred', @ldap.config[:auth][:username] )
+ assert_equal('derf', @ldap.config[:auth][:password] )
+ end
+
+ test 'auth method defaults to simple if username/password set' do
+ @ldap.username, @ldap.password = 'fred', 'derf'
+ assert_equal(:simple, @ldap.config[:auth][:method] )
+ end
+
+ test 'if no username/password then defaults to auth anonymous' do
+ @ldap.username = @ldap.password = nil
+ assert_equal({:method => :anonymous}, @ldap.config[:auth] )
+ end
+
+end
Something went wrong with that request. Please try again.