]>
Commit | Line | Data |
---|---|---|
40d8bc65 PR |
1 | import ldap |
2 | import ldap.sasl | |
bd40d105 | 3 | import socket |
40d8bc65 PR |
4 | |
5 | ldapurl = 'ldap://tsd-dc01.tsd.usit.no' | |
6 | ldapbase = 'DC=tsd,DC=usit,DC=no' | |
f021027f PR |
7 | |
8 | # use 2 to debug ldap connections. | |
9 | trace_level = 0 | |
10 | ||
a2948e2d | 11 | def ldap_uri(): |
2ca7ff37 | 12 | return ldapurl |
f021027f PR |
13 | |
14 | def ldap_base(): | |
15 | return ldapbase | |
40d8bc65 PR |
16 | |
17 | def ldap_connect(): | |
a2948e2d | 18 | lref = ldap.initialize(ldap_uri(), trace_level=trace_level) |
40d8bc65 PR |
19 | |
20 | auth_tokens = ldap.sasl.gssapi() | |
21 | lref.sasl_interactive_bind_s('', auth_tokens) | |
22 | return lref | |
23 | ||
40d8bc65 | 24 | def ldap_unbind(lref): |
d6fc5f2b | 25 | lref.unbind() |
8c00a9a1 | 26 | |
dff7f8d5 PR |
27 | def computermatch(enabled = None): |
28 | enablematch = '(userAccountControl:1.2.840.113556.1.4.803:=2)' | |
29 | if enabled is None: | |
30 | match = '(objectclass=computer)' | |
31 | elif enabled: | |
32 | match = '(&(objectclass=computer)(!%s))' % enablematch | |
33 | else: | |
34 | match = '(&(objectclass=computer)%s)' % enablematch | |
35 | return match | |
36 | ||
37 | def role2hosts(lref, rolename, enabled = None): | |
d6fc5f2b PR |
38 | """ |
39 | Look up all hosts with a given role. | |
40 | """ | |
8c00a9a1 PR |
41 | hosts = {} |
42 | policybase = 'OU=hostpolicies,' + ldap_base() | |
43 | rolebase = 'OU=roles,' + policybase | |
44 | atombase = 'OU=atoms,' + policybase | |
45 | ||
46 | # First look up host members in role | |
47 | roleres = lref.search_s(rolebase, ldap.SCOPE_SUBTREE, | |
48 | '(&(objectclass=group)(name=%s))' % rolename, | |
49 | ['member']) | |
50 | ||
51 | # Next, look up FQDN of host members | |
dff7f8d5 | 52 | match = computermatch(enabled) |
8c00a9a1 PR |
53 | for roledn, roleentry in roleres: |
54 | if 'member' in roleentry: | |
55 | for memberdn in roleentry['member']: | |
56 | hostres = lref.search_s(memberdn, ldap.SCOPE_BASE, | |
dff7f8d5 | 57 | match , ['dNSHostName']) |
8c00a9a1 PR |
58 | for hostdn, hostent in hostres: |
59 | hosts[hostent['dNSHostName'][0]] = memberdn; | |
60 | return hosts.keys() | |
d6fc5f2b PR |
61 | |
62 | def role4host(lref, hostname): | |
63 | """ | |
64 | Look up all roles of a given host | |
65 | """ | |
66 | roles = {} | |
67 | policybase = 'OU=hostpolicies,' + ldap_base() | |
68 | rolebase = 'OU=roles,' + policybase | |
69 | ||
70 | # First look up hostname | |
71 | hostres = lref.search_s(ldap_base(), ldap.SCOPE_SUBTREE, \ | |
72 | '(&(objectclass=computer)(dNSHostName=%s))' % hostname.lower(), \ | |
73 | ['memberOf']) | |
74 | ||
75 | # FIXME fail if more than one host is returned | |
76 | ||
77 | for hostdn, hostentry in hostres: | |
78 | if 'memberOf' in hostentry: | |
79 | for roledn in hostentry['memberOf']: | |
80 | # look up the role name | |
81 | entry = lref.search_s(roledn, ldap.SCOPE_BASE, \ | |
82 | '(objectclass=group)', \ | |
83 | ['name']) | |
84 | for dn, roleent in entry: | |
85 | roles[roleent['name'][0]] = 1 | |
86 | return roles.keys() | |
87 | ||
ad3fe95f | 88 | |
dff7f8d5 | 89 | def atom2hosts(lref, atomname, enabled = None): |
a9ff88cb PR |
90 | """ |
91 | Look up all hosts affected by a given cfengine atom (via role) | |
92 | """ | |
93 | hosts = {} | |
94 | policybase = 'OU=hostpolicies,' + ldap_base() | |
95 | rolebase = 'OU=roles,' + policybase | |
96 | atombase = 'OU=atoms,' + policybase | |
97 | ||
98 | # First look up role members in the atom | |
99 | atomres = lref.search_s(atombase, ldap.SCOPE_SUBTREE, | |
100 | '(&(objectclass=group)(name=%s))' % atomname, | |
101 | ['member']) | |
102 | ||
103 | # Next, look up FQDN of host members | |
dff7f8d5 | 104 | match = computermatch(enabled) |
a9ff88cb PR |
105 | for atomdn, atomentry in atomres: |
106 | if 'member' in atomentry: | |
107 | for roledn in atomentry['member']: | |
108 | roleres = lref.search_s(roledn, ldap.SCOPE_BASE, | |
109 | '(objectclass=group)', | |
110 | ['member']) | |
111 | for roledn, roleentry in roleres: | |
112 | if 'member' in roleentry: | |
113 | for memberdn in roleentry['member']: | |
114 | hostres = lref.search_s(memberdn, ldap.SCOPE_BASE, | |
dff7f8d5 | 115 | match, ['dNSHostName']) |
a9ff88cb PR |
116 | for hostdn, hostent in hostres: |
117 | hosts[hostent['dNSHostName'][0]] = memberdn; | |
118 | return hosts.keys() | |
119 | ||
ad3fe95f PR |
120 | def host2project(lref, fqdn): |
121 | """ | |
122 | Find computer object and its project based on FQDN. | |
123 | """ | |
722fb4f1 | 124 | res = lref.search_s(ldap_base(), ldap.SCOPE_SUBTREE, \ |
ad3fe95f PR |
125 | '(&(objectclass=computer)(dnshostname=%s))' % fqdn, |
126 | ['dn']) | |
127 | for dn, entry in res: | |
128 | if None is not dn: | |
129 | projectdn = ",".join((dn.split(","))[2:]) | |
cfc0d263 | 130 | projectnum = (dn.split(","))[-5].replace("OU=p", "") |
ad3fe95f PR |
131 | return (projectnum, dn) |
132 | return (None, None) | |
133 | ||
dcb3a3ad MB |
134 | def ip2host(lref, hostname): |
135 | """ | |
136 | Find network information about a host | |
137 | """ | |
138 | network = {} | |
139 | dnsinfo = socket.getaddrinfo(hostname, None) | |
140 | for (family, socktype, proto, canonname, sockaddr) in dnsinfo: | |
141 | if socket.AF_INET == family: | |
e2d42d78 | 142 | network['ipv4addr'] = sockaddr[0] |
dcb3a3ad | 143 | elif socket.AF_INET6 == family: |
e2d42d78 | 144 | network['ipv6addr'] = sockaddr[0] |
dcb3a3ad MB |
145 | hostres = lref.search_s(ldap_base(), ldap.SCOPE_SUBTREE, \ |
146 | '(&(objectclass=computer)(dNSHostName=%s))' % hostname.lower(), \ | |
147 | ['networkAddress']) | |
148 | for hostdn, hostaddr in hostres: | |
ef8b3468 MB |
149 | ipv6 = "" |
150 | ipv4 = "" | |
dcb3a3ad | 151 | if 'networkAddress' in hostaddr: |
b93ed7f2 MB |
152 | for i in hostaddr['networkAddress']: |
153 | if ":" in i: | |
154 | ipv6 = i | |
155 | elif "." in i: | |
156 | ipv4 = i | |
bd40d105 MB |
157 | else: |
158 | network['vlan'] = i | |
518cf84d MB |
159 | if "/" in ipv4: |
160 | vlan4, network4, prefix4 = ipv4.split("/") | |
161 | network['vlan'] = vlan4 | |
162 | network['ipv4prefix'] = prefix4 | |
163 | network['ipv4network'] = network4 | |
164 | if "/" in ipv6: | |
165 | vlan6, network6, prefix6 = ipv6.split("/") | |
166 | network['ipv6prefix'] = prefix6 | |
167 | network['ipv6network'] = network6 | |
168 | network['vlan'] = vlan6 | |
dcb3a3ad MB |
169 | return network |
170 | ||
a64f83d0 | 171 | def testfuncs(): |
d6fc5f2b PR |
172 | l = ldap_connect() |
173 | print "All hosts with role autoinstall_virtual_host" | |
174 | print role2hosts(l, 'autoinstall_virtual_host'); | |
dff7f8d5 | 175 | print role2hosts(l, 'autoinstall_virtual_host', enabled=True); |
d6fc5f2b PR |
176 | print "all roles of host tsd-prism.tsd.usit.no" |
177 | print role4host(l, 'tsd-prism.tsd.usit.no') | |
ad3fe95f PR |
178 | print "project number for host tsd-prism.tsd.usit.no" |
179 | print host2project(l, 'tsd-prism.tsd.usit.no') | |
a9ff88cb | 180 | print atom2hosts(l, 'root_for_dba') |
dff7f8d5 | 181 | print atom2hosts(l, 'root_for_dba', enabled=False) |
d6fc5f2b | 182 | ldap_unbind(l) |
a64f83d0 PR |
183 | |
184 | if __name__ == "__main__": | |
185 | testfuncs() |