The configuration class for LDAP providers, plus connection handling for actually interacting with ldap.
# File lib/puppet/util/ldap/manager.rb, line 155 def initialize @rdn = :cn @generators = [] end
A null-op that just returns the config.
# File lib/puppet/util/ldap/manager.rb, line 11 def and self end
Set the offset from the search base and return the config.
# File lib/puppet/util/ldap/manager.rb, line 16 def at(location) @location = location self end
The basic search base.
# File lib/puppet/util/ldap/manager.rb, line 22 def base [location, Puppet[:ldapbase]].join(",") end
Open, yield, and close the connection. Cannot be left open, at this point.
# File lib/puppet/util/ldap/manager.rb, line 46 def connect raise ArgumentError, "You must pass a block to #connect" unless block_given? unless @connection if Puppet[:ldaptls] ssl = :tls elsif Puppet[:ldapssl] ssl = true else ssl = false end options = {:ssl => ssl} if user = Puppet[:ldapuser] and user != "" options[:user] = user end if password = Puppet[:ldappassword] and password != "" options[:password] = password end @connection = Puppet::Util::Ldap::Connection.new(Puppet[:ldapserver], Puppet[:ldapport], options) end @connection.start begin yield @connection.connection ensure @connection.close end nil end
Convert the name to a dn, then pass the args along to our connection.
# File lib/puppet/util/ldap/manager.rb, line 28 def create(name, attributes) attributes = attributes.dup # Add the objectclasses attributes["objectClass"] = objectclasses.collect { |o| o.to_s } attributes["objectClass"] << "top" unless attributes["objectClass"].include?("top") attributes[rdn.to_s] = [name] # Generate any new values we might need. generate(attributes) # And create our resource. connect { |conn| conn.add dn(name), attributes } end
Convert the name to a dn, then pass the args along to our connection.
# File lib/puppet/util/ldap/manager.rb, line 77 def delete(name) connect { |connection| connection.delete dn(name) } end
Calculate the dn for a given resource.
# File lib/puppet/util/ldap/manager.rb, line 82 def dn(name) ["#{rdn}=#{name}", base].join(",") end
Convert an ldap-style entry hash to a provider-style hash.
# File lib/puppet/util/ldap/manager.rb, line 87 def entry2provider(entry) raise ArgumentError, "Could not get dn from ldap entry" unless entry["dn"] # DN is always a single-entry array. Strip off the bits before the # first comma, then the bits after the remaining equal sign. This is the # name. name = entry["dn"].dup.pop.split(",").shift.split("=").pop result = {:name => name} @ldap2puppet.each do |ldap, puppet| result[puppet] = entry[ldap.to_s] || :absent end result end
Create our normal search filter.
# File lib/puppet/util/ldap/manager.rb, line 105 def filter return(objectclasses.length == 1 ? "objectclass=#{objectclasses[0]}" : "(&(objectclass=" + objectclasses.join(")(objectclass=") + "))") end
Find the associated entry for a resource. Returns a hash, minus ‘dn’, or nil if the entry cannot be found.
# File lib/puppet/util/ldap/manager.rb, line 111 def find(name) result = nil connect do |conn| begin conn.search2(dn(name), 0, "objectclass=*") do |result| # Convert to puppet-appropriate attributes return entry2provider(result) end rescue => detail return nil end end end
Generate any extra values we need to make the ldap entry work.
# File lib/puppet/util/ldap/manager.rb, line 132 def generate(values) return unless @generators.length > 0 @generators.each do |generator| # Don't override any values that might exist. next if values[generator.name] if generator.source unless value = values[generator.source] raise ArgumentError, "#{generator.source} must be defined to generate #{generator.name}" end result = generator.generate(value) else result = generator.generate end result = [result] unless result.is_a?(Array) result = result.collect { |r| r.to_s } values[generator.name] = result end end
Declare a new attribute generator.
# File lib/puppet/util/ldap/manager.rb, line 126 def generates(parameter) @generators << Puppet::Util::Ldap::Generator.new(parameter) @generators[-1] end
Return the ldap name for a puppet attribute.
# File lib/puppet/util/ldap/manager.rb, line 180 def ldap_name(attribute) @puppet2ldap[attribute].to_s end
Specify what classes this provider models.
# File lib/puppet/util/ldap/manager.rb, line 161 def manages(*classes) @objectclasses = classes self end
Specify the attribute map. Assumes the keys are the puppet attributes, and the values are the ldap attributes, and creates a map for each direction.
# File lib/puppet/util/ldap/manager.rb, line 169 def maps(attributes) # The map with the puppet attributes as the keys @puppet2ldap = attributes # and the ldap attributes as the keys. @ldap2puppet = attributes.inject({}) { |map, ary| map[ary[1]] = ary[0]; map } self end
Convert the name to a dn, then pass the args along to our connection.
# File lib/puppet/util/ldap/manager.rb, line 186 def modify(name, mods) connect { |connection| connection.modify dn(name), mods } end
Specify the rdn that we use to build up our dn.
# File lib/puppet/util/ldap/manager.rb, line 191 def named_by(attribute) @rdn = attribute self end
Return the puppet name for an ldap attribute.
# File lib/puppet/util/ldap/manager.rb, line 197 def puppet_name(attribute) @ldap2puppet[attribute] end
Search for all entries at our base. A potentially expensive search.
# File lib/puppet/util/ldap/manager.rb, line 202 def search(sfilter = nil) sfilter ||= filter result = [] connect do |conn| conn.search2(base, 1, sfilter) do |entry| result << entry2provider(entry) end end return(result.empty? ? nil : result) end
Update the ldap entry with the desired state.
# File lib/puppet/util/ldap/manager.rb, line 215 def update(name, is, should) if should[:ensure] == :absent Puppet.info "Removing #{dn(name)} from ldap" delete(name) return end # We're creating a new entry if is.empty? or is[:ensure] == :absent Puppet.info "Creating #{dn(name)} in ldap" # Remove any :absent params and :ensure, then convert the names to ldap names. attrs = ldap_convert(should) create(name, attrs) return end # We're modifying an existing entry. Yuck. mods = [] # For each attribute we're deleting that is present, create a # modify instance for deletion. [is.keys, should.keys].flatten.uniq.each do |property| # They're equal, so do nothing. next if is[property] == should[property] attributes = ldap_convert(should) prop_name = ldap_name(property).to_s # We're creating it. if is[property] == :absent or is[property].nil? mods << LDAP::Mod.new(LDAP::LDAP_MOD_ADD, prop_name, attributes[prop_name]) next end # We're deleting it if should[property] == :absent or should[property].nil? mods << LDAP::Mod.new(LDAP::LDAP_MOD_DELETE, prop_name, []) next end # We're replacing an existing value mods << LDAP::Mod.new(LDAP::LDAP_MOD_REPLACE, prop_name, attributes[prop_name]) end modify(name, mods) end
Is this a complete ldap configuration?
# File lib/puppet/util/ldap/manager.rb, line 264 def valid? location and objectclasses and ! objectclasses.empty? and puppet2ldap end