
require 'ldap'
require 'uri'

basedn = ''
conn = ''

f = File.new('/etc/openldap/ldap.conf', 'r')
f.readlines.each do |line|
    line = line.strip
    next if line =~ /^#/
    next if line == ''
    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'
                    if ! uri.port
                        uri.port = 636
                    end
                    conn = LDAP::SSLConn.new(uri.host, uri.port)
                else
                    if ! uri.port
                        uri.port = 389
                    end
                    conn = LDAP::Conn.new(uri.host, uri.port)
                end
                conn.bind
                break
            rescue LDAP::ResultError
                next
            end
        end
    end
end
f.close


print <<EOF
define user::newuser($uid, $gid, $comment, $home, $shell, $groups=undef, $requiregroups=undef) {

    user { "${name}":
        ensure  => present,
        uid     => $uid,
        gid     => $gid,
        comment => $comment,
        home    => $home,
        shell   => $shell,
        groups  => $groups,
        require => $requiregroups,
        notify  => $operatingsystem ? {
            OpenBSD => [ Exec["user-mod-${name}"],
                         Exec["user-home-${name}"], ],
            default => undef,
        }
    }

    exec { "user-mod-${name}":
        command     => "usermod -L ldap ${name}",
        path        => "/sbin:/usr/sbin:/bin:/usr/bin",
        refreshonly => true,
        require     => File["/etc/login.conf"],
    }

    exec { "user-home-${name}":
        command     => "umask 077; mkdir -p ${home} && tar cf - . | tar xf - -C ${home} && chown -R ${uid}:${gid} ${home}",
        cwd         => "/etc/skel",
        path        => "/sbin:/usr/sbin:/bin:/usr/bin",
        creates     => "${home}",
        refreshonly => true,
    }

}

class user::virtual {
EOF


conn.search(basedn, LDAP::LDAP_SCOPE_SUBTREE, 'objectClass=posixAccount',
	    ['uid', 'uidNumber', 'gidNumber', 'gecos', 'homeDirectory',
	     'loginShell' ]) { |entry|
    groups = []
    filter = '(&(objectClass=posixGroup)(|(uniqueMember=' + entry.get_dn \
	     + ')(memberUid=' + entry['uid'][0] + ')))'
    conn.search(basedn, LDAP::LDAP_SCOPE_SUBTREE, filter, ['cn']) { |group|
	groups << group['cn'][0]
    }
    prigroup = nil
    conn.search(basedn, LDAP::LDAP_SCOPE_SUBTREE, \
		'(&(objectClass=posixGroup)(gidNumber=' + entry['gidNumber'][0] + '))', \
		['cn']) { |group|
	prigroup = group['cn'][0]
    }

    print "\n"
    print "    @user::newuser { '%s':\n" % entry['uid'][0]
    print "        uid           => '%s',\n" % entry['uidNumber'][0]
    print "        gid           => '%s',\n" % entry['gidNumber'][0]
    begin
        print "        comment       => '%s',\n" % entry['gecos'][0]
    rescue
        print "        comment       => '%s',\n" % entry['uid'][0]
    end
    print "        home          => '%s',\n" % entry['homeDirectory'][0]
    begin
        print "        shell         => '%s',\n" % entry['loginShell'][0]
    rescue
        print "        shell         => '%s',\n" % "/bin/bash"
    end
    if groups.length > 0
	print "        groups        => $operatingsystem ? {\n"
	print "            openbsd => [ "
	groups.each do |group|
	    print "'" + group + "', "
	end
	print "'wheel', " if groups.include?('sysadm')
	print "],\n"
	print "            default => [ "
	groups.each do |group|
	    print "'" + group + "', "
	end
	print "],\n        },\n"
    end
    print "        requiregroups => [ Group['" + prigroup + "'],"
    groups.each do |group|
	print "\n                           Group['" + group + "'],"
    end
    print " ],\n"
    print "    }\n"

}


conn.search(basedn, LDAP::LDAP_SCOPE_SUBTREE, 'objectClass=posixGroup',
	    ['cn', 'gidNumber', 'memberUid', 'uniqueMember']) { |entry|

    # generate virtual group entry
    print "\n"
    print "    @group { '" + entry['cn'][0] + "':\n"
    print "        ensure => present,\n"
    print "        gid    => '" + entry['gidNumber'][0] + "',\n"
    print "    }\n"

}


print "\n}\n"
