require "set" require "uri" require "ldap" conn = nil basedn = nil File.readlines("/etc/openldap/ldap.conf").each do |line| line = line.strip next if line.empty? or line.start_with?("#") line = line.split if line[0] == "BASE" basedn = line[1] elsif line[0] == "URI" line.shift line.each do |uri| uri = URI.parse(uri) begin if uri.scheme == "ldaps" uri.port = 636 unless uri.port conn = LDAP::SSLConn.new(uri.host, uri.port) else uri.port = 389 unless uri.port conn = LDAP::Conn.new(uri.host, uri.port) end conn.bind break rescue LDAP::ResultError next end end end end virtual = "class user::virtual {\n" filter = "objectClass=posixAccount" attrib = %w(uid uidNumber gidNumber gecos homeDirectory loginShell) conn.search(basedn, LDAP::LDAP_SCOPE_SUBTREE, filter, attrib) do |entry| dn = entry.get_dn uid = entry["uid"].first uidnumber = entry["uidNumber"].first gidnumber = entry["gidNumber"].first primarygroup = nil groups = Set.new filter = "(&(objectClass=posixGroup)(gidNumber=#{gidnumber}))" conn.search(basedn, LDAP::LDAP_SCOPE_SUBTREE, filter, ["cn"]) do |group| primarygroup = group["cn"].first end continue if primarygroup.nil? filter = "(&(objectClass=posixGroup)(|(uniqueMember=#{dn})(memberUid=#{uid})))" conn.search(basedn, LDAP::LDAP_SCOPE_SUBTREE, filter, ["cn"]) do |group| groups << group["cn"].first end comment = entry["gecos"] ? entry["gecos"].first : entry["uid"].first shell = entry["loginShell"] ? entry["loginShell"].first : "/bin/bash" home = entry["homeDirectory"].first virtual << <<-EOF @user::add { "#{uid}": uid => "#{uidnumber}", gid => "#{gidnumber}", comment => "#{comment}", home => "#{home}", shell => "#{shell}", EOF unless groups.empty? virtual << " groups => $::operatingsystem ? {\n" virtual << " \"openbsd\" => [ " groups.each { |group| virtual << "\"#{group}\", " } virtual << "\"wheel\", " if groups.include?("sysadm") virtual << "],\n default => [ " groups.each { |group| virtual << "\"#{group}\", " } virtual << "],\n },\n" end virtual << " require => [\n" virtual << " Group[\"#{primarygroup}\"],\n" groups.each { |group| virtual << " Group[\"#{group}\"],\n" } virtual << " ],\n }\n" end filter = "objectClass=posixGroup" attrib = %w(cn gidNumber memberUid uniqueMember) conn.search(basedn, LDAP::LDAP_SCOPE_SUBTREE, filter, attrib) do |entry| cn = entry["cn"].first gid = entry["gidNumber"].first virtual << <<-EOF @group { "#{cn}": ensure => present, gid => "#{gid}", } EOF end puts virtual, "\n}"