summaryrefslogtreecommitdiffstats
path: root/lib/puppet/provider/user/ldap.rb
blob: ba91a871e154a88aa68f6391e85981439d8b33e9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
require 'puppet/provider/ldap'

Puppet::Type.type(:user).provide :ldap, :parent => Puppet::Provider::Ldap do
    desc "User management via ``ldap``.  This provider requires that you
        have valid values for all of the ldap-related settings,
        including ``ldapbase``.  You will also almost definitely need settings
        for ``ldapuser`` and ``ldappassword``, so that your clients can write
        to ldap.
        
        Note that this provider will automatically generate a UID for you if
        you do not specify one, but it is a potentially expensive operation,
        as it iterates across all existing users to pick the appropriate next
        one."

    confine :true => Puppet.features.ldap?

    manages(:posixAccount, :person).at("ou=People").named_by(:uid).and.maps :name => :uid,
        :password => :userPassword,
        :comment => :cn,
        :uid => :uidNumber,
        :gid => :gidNumber,
        :home => :homeDirectory,
        :shell => :loginShell

    # Use the last field of a space-separated array as
    # the sn.  LDAP requires a surname, for some stupid reason.
    manager.generates(:sn).from(:cn).with do |cn|
        x = 1
        cn[0].split(/\s+/)[-1]
    end

    # Find the next uid after the current largest uid.
    provider = self
    manager.generates(:uidNumber).with do 
        largest = 0
        provider.manager.search.each do |hash|
            next unless value = hash[:uid]
            num = value[0].to_i
            if num > largest
                largest = num
            end
        end
        largest + 1
    end

    # Find all groups this user is a member of in ldap.
    def groups
        # We want to cache the current result, so we know if we
        # have to remove old values.
        unless @property_hash[:groups]
            unless result = group_manager.search("memberUid=%s" % name)
                return @property_hash[:groups] = :absent
            end

            return @property_hash[:groups] = result.collect { |r| r[:name] }.join(",")
        end
        return @property_hash[:groups]
    end

    # Manage the list of groups this user is a member of.
    def groups=(values)
        should = values.split(",")

        if groups() == :absent
            is = []
        else
            is = groups().split(",")
        end

        modes = {}
        [is, should].flatten.uniq.each do |group|
            # Skip it when they're in both
            next if is.include?(group) and should.include?(group)

            # We're adding a group.
            modes[group] = :add and next unless is.include?(group)

            # We're removing a group.
            modes[group] = :remove and next unless should.include?(group)
        end

        modes.each do |group, form|
            self.fail "Could not find ldap group %s" % group unless ldap_group = group_manager.find(group)

            current = ldap_group[:members]

            if form == :add
                if current.is_a?(Array) and ! current.empty?
                    new = current + [name]
                else
                    new = [name]
                end
            else
                new = current - [name]
                new = :absent if new.empty?
            end

            group_manager.update(group, {:ensure => :present, :members => current}, {:ensure => :present, :members => new})
        end
    end

    private

    def group_manager
        Puppet::Type.type(:group).provider(:ldap).manager
    end

    def group_properties(values)
        if values.empty? or values == :absent
            {:ensure => :present}
        else
            {:ensure => :present, :members => values}
        end
    end
end