class Cloudscaling::LDAPUtils

Tools for interacting with LDAP using a TCP connection

Public Class Methods

first_item(dn) click to toggle source
# File lib/cloudscaling/ldap.rb, line 170
def self.first_item(dn)
  m = dn.match(/^([^=]+)=([^,]+)/)
  { m[1] => m[2] }
end
new(server, port = 389, auth_dn = nil, password = nil, tls_enable = true) click to toggle source
# File lib/cloudscaling/ldap.rb, line 136
def initialize(server, port = 389, auth_dn = nil, password = nil,
               tls_enable = true)
  args = { host: server,
           port: port }
  auth_dn && args.update(auth: { method: :simple,
                                 username: auth_dn,
                                 password: password })
  tls_enable && args.update(encryption: { method: :start_tls })
  @ldap = Net::LDAP.new(args)
  @ldap.bind || fail("LDAP bind failed: #{@ldap.get_operation_result}")
end
openssl_extract_cert(rawcert) click to toggle source
# File lib/cloudscaling/ldap.rb, line 148
def self.openssl_extract_cert(rawcert)
  OpenSSL::X509::Certificate.new(rawcert).to_s
end
openssl_extract_key(rawcert, passphrase = nil) click to toggle source
# File lib/cloudscaling/ldap.rb, line 152
def self.openssl_extract_key(rawcert, passphrase = nil)
  OpenSSL::PKey.read(rawcert, passphrase).to_s
end
ssha_password(clear_password, salt = nil) click to toggle source

Generate a rfc2307 SSHA-hashed password in the format that slapd likes www.openldap.org/faq/data/cache/347.html

# File lib/cloudscaling/ldap.rb, line 158
def self.ssha_password(clear_password, salt = nil)
  unless salt
    len = 16
    base = 16
    # rubocop:disable Style/SingleLineBlockParams
    salt = len.times.reduce('') { |a| a << rand(base).to_s(base) }
  end
  digest = Digest::SHA1.digest("#{clear_password}#{salt}")
  hash = Base64.encode64("#{digest}#{salt}").chomp
  "{SSHA}#{hash}"
end

Public Instance Methods

add_entry(dn, attrs) click to toggle source

Add an entry to the directory dn: Distinguished name of the new entry attrs: hash of entry attributes

# File lib/cloudscaling/ldap.rb, line 184
def add_entry(dn, attrs)
  # Chef::Log.info "Add LDAP entry: #{dn} #{attrs}"
  @ldap.add(dn: dn, attributes: attrs) ||
    fail("LDAP add failure: #{@ldap.get_operation_result}")
end
add_or_update_entry(dn, attrs) click to toggle source

Add or update a directory entry. If the entry exists, any attributes provided to this function will be updated with a “replace” operation, which will add the attributes if necessary, and replace all values of the attribute otherwise.

# File lib/cloudscaling/ldap.rb, line 194
def add_or_update_entry(dn, attrs)
  ret = @ldap.search(base: dn,
                     scope: Net::LAP::SearchScope_BaseObject,
                     return_result: true)
  entries && entries.size > 1 && fail("#{dn} matches more than one entry")
  if ret.nil?
    add_entry(dn, attrs)
  else
    entry = ret.first
    ops = attrs.each_with_object(Array.new) do |(k, v), acc|
      acc << [:replace, k, v] unless entry[k] == [v].flatten
    end
    # Chef::Log.info("Update LDAP entry: dn=#{dn}")
    @ldap.modify(dn: dn, operations: ops) ||
      fail("LDAP update failure: #{@ldap.get_operation_result}")
  end
end
dn_exists?(dn) click to toggle source
# File lib/cloudscaling/ldap.rb, line 175
def dn_exists?(dn)
  @ldap.search(base: dn,
               scope: Net::LDAP::SearchScope_BaseObject,
               return_result: false)
end