class Puppet::Util::Ldap::Manager
The configuration class for LDAP providers, plus connection handling for actually interacting with ldap.
Attributes
Public Class Methods
# File lib/puppet/util/ldap/manager.rb 160 def initialize 161 @rdn = :cn 162 @generators = [] 163 end
Public Instance Methods
A null-op that just returns the config.
# File lib/puppet/util/ldap/manager.rb 11 def and 12 self 13 end
Set the offset from the search base and return the config.
# File lib/puppet/util/ldap/manager.rb 16 def at(location) 17 @location = location 18 self 19 end
The basic search base.
# File lib/puppet/util/ldap/manager.rb 22 def base 23 [location, Puppet[:ldapbase]].join(",") 24 end
Open, yield, and close the connection. Cannot be left open, at this point.
# File lib/puppet/util/ldap/manager.rb 46 def connect 47 #TRANSLATORS '#connect' is a method name and and should not be translated, 'block' refers to a Ruby code block 48 raise ArgumentError, _("You must pass a block to #connect") unless block_given? 49 50 unless @connection 51 if Puppet[:ldaptls] 52 ssl = :tls 53 elsif Puppet[:ldapssl] 54 ssl = true 55 else 56 ssl = false 57 end 58 options = {:ssl => ssl} 59 user = Puppet[:ldapuser] 60 if user && user != "" 61 options[:user] = user 62 end 63 password = Puppet[:ldappassword] 64 if password && password != "" 65 options[:password] = password 66 end 67 @connection = Puppet::Util::Ldap::Connection.new(Puppet[:ldapserver], Puppet[:ldapport], options) 68 end 69 @connection.start 70 begin 71 yield @connection.connection 72 ensure 73 @connection.close 74 end 75 nil 76 end
Convert the name to a dn, then pass the args along to our connection.
# File lib/puppet/util/ldap/manager.rb 28 def create(name, attributes) 29 attributes = attributes.dup 30 31 # Add the objectclasses 32 attributes["objectClass"] = objectclasses.collect { |o| o.to_s } 33 attributes["objectClass"] << "top" unless attributes["objectClass"].include?("top") 34 35 attributes[rdn.to_s] = [name] 36 37 # Generate any new values we might need. 38 generate(attributes) 39 40 # And create our resource. 41 connect { |conn| conn.add dn(name), attributes } 42 end
Convert the name to a dn, then pass the args along to our connection.
# File lib/puppet/util/ldap/manager.rb 80 def delete(name) 81 connect { |connection| connection.delete dn(name) } 82 end
Calculate the dn for a given resource.
# File lib/puppet/util/ldap/manager.rb 85 def dn(name) 86 ["#{rdn}=#{name}", base].join(",") 87 end
Convert an ldap-style entry hash to a provider-style hash.
# File lib/puppet/util/ldap/manager.rb 90 def entry2provider(entry) 91 #TRANSLATOR 'dn' refers to a 'distinguished name' in LDAP (Lightweight Directory Access Protocol) and they should not be translated 92 raise ArgumentError, _("Could not get dn from ldap entry") unless entry["dn"] 93 94 # DN is always a single-entry array. Strip off the bits before the 95 # first comma, then the bits after the remaining equal sign. This is the 96 # name. 97 name = entry["dn"].dup.pop.split(",").shift.split("=").pop 98 99 result = {:name => name} 100 101 @ldap2puppet.each do |ldap, puppet| 102 result[puppet] = entry[ldap.to_s] || :absent 103 end 104 105 result 106 end
Create our normal search filter.
# File lib/puppet/util/ldap/manager.rb 109 def filter 110 return(objectclasses.length == 1 ? "objectclass=#{objectclasses[0]}" : "(&(objectclass=" + objectclasses.join(")(objectclass=") + "))") 111 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 115 def find(name) 116 connect do |conn| 117 begin 118 conn.search2(dn(name), 0, "objectclass=*") do |result| 119 # Convert to puppet-appropriate attributes 120 return entry2provider(result) 121 end 122 rescue 123 return nil 124 end 125 end 126 end
Generate any extra values we need to make the ldap entry work.
# File lib/puppet/util/ldap/manager.rb 135 def generate(values) 136 return unless @generators.length > 0 137 138 @generators.each do |generator| 139 # Don't override any values that might exist. 140 next if values[generator.name] 141 142 if generator.source 143 value = values[generator.source] 144 unless value 145 raise ArgumentError, _("%{source} must be defined to generate %{name}") % 146 { source: generator.source, name: generator.name } 147 end 148 result = generator.generate(value) 149 else 150 result = generator.generate 151 end 152 153 result = [result] unless result.is_a?(Array) 154 result = result.collect { |r| r.to_s } 155 156 values[generator.name] = result 157 end 158 end
Declare a new attribute generator.
# File lib/puppet/util/ldap/manager.rb 129 def generates(parameter) 130 @generators << Puppet::Util::Ldap::Generator.new(parameter) 131 @generators[-1] 132 end
Return the ldap name for a puppet attribute.
# File lib/puppet/util/ldap/manager.rb 185 def ldap_name(attribute) 186 @puppet2ldap[attribute].to_s 187 end
Specify what classes this provider models.
# File lib/puppet/util/ldap/manager.rb 166 def manages(*classes) 167 @objectclasses = classes 168 self 169 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 174 def maps(attributes) 175 # The map with the puppet attributes as the keys 176 @puppet2ldap = attributes 177 178 # and the ldap attributes as the keys. 179 @ldap2puppet = attributes.inject({}) { |map, ary| map[ary[1]] = ary[0]; map } 180 181 self 182 end
Convert the name to a dn, then pass the args along to our connection.
# File lib/puppet/util/ldap/manager.rb 191 def modify(name, mods) 192 connect { |connection| connection.modify dn(name), mods } 193 end
Specify the rdn that we use to build up our dn.
# File lib/puppet/util/ldap/manager.rb 196 def named_by(attribute) 197 @rdn = attribute 198 self 199 end
Return the puppet name for an ldap attribute.
# File lib/puppet/util/ldap/manager.rb 202 def puppet_name(attribute) 203 @ldap2puppet[attribute] 204 end
Search for all entries at our base. A potentially expensive search.
# File lib/puppet/util/ldap/manager.rb 207 def search(sfilter = nil) 208 sfilter ||= filter 209 210 result = [] 211 connect do |conn| 212 conn.search2(base, 1, sfilter) do |entry| 213 result << entry2provider(entry) 214 end 215 end 216 return(result.empty? ? nil : result) 217 end
Update the ldap entry with the desired state.
# File lib/puppet/util/ldap/manager.rb 220 def update(name, is, should) 221 if should[:ensure] == :absent 222 Puppet.info _("Removing %{name} from ldap") % { name: dn(name) } 223 delete(name) 224 return 225 end 226 227 # We're creating a new entry 228 if is.empty? or is[:ensure] == :absent 229 Puppet.info _("Creating %{name} in ldap") % { name: dn(name) } 230 # Remove any :absent params and :ensure, then convert the names to ldap names. 231 attrs = ldap_convert(should) 232 create(name, attrs) 233 return 234 end 235 236 # We're modifying an existing entry. Yuck. 237 238 mods = [] 239 # For each attribute we're deleting that is present, create a 240 # modify instance for deletion. 241 [is.keys, should.keys].flatten.uniq.each do |property| 242 # They're equal, so do nothing. 243 next if is[property] == should[property] 244 245 attributes = ldap_convert(should) 246 247 prop_name = ldap_name(property).to_s 248 249 # We're creating it. 250 if is[property] == :absent or is[property].nil? 251 mods << LDAP::Mod.new(LDAP::LDAP_MOD_ADD, prop_name, attributes[prop_name]) 252 next 253 end 254 255 # We're deleting it 256 if should[property] == :absent or should[property].nil? 257 mods << LDAP::Mod.new(LDAP::LDAP_MOD_DELETE, prop_name, []) 258 next 259 end 260 261 # We're replacing an existing value 262 mods << LDAP::Mod.new(LDAP::LDAP_MOD_REPLACE, prop_name, attributes[prop_name]) 263 end 264 265 modify(name, mods) 266 end
Is this a complete ldap configuration?
# File lib/puppet/util/ldap/manager.rb 269 def valid? 270 location and objectclasses and ! objectclasses.empty? and puppet2ldap 271 end
Private Instance Methods
Convert a hash of attributes to ldap-like forms. This mostly means getting rid of :ensure and making sure everything's an array of strings.
# File lib/puppet/util/ldap/manager.rb 277 def ldap_convert(attributes) 278 attributes.reject { |param, value| value == :absent or param == :ensure }.inject({}) do |result, ary| 279 value = (ary[1].is_a?(Array) ? ary[1] : [ary[1]]).collect { |v| v.to_s } 280 result[ldap_name(ary[0])] = value 281 result 282 end 283 end