4 # Copyright (c) 2000-2001 Jason Gunthorpe <jgg@debian.org>
5 # Copyright (c) 2001 Ryan Murray <rmurray@debian.org>
6 # Copyright (c) 2003 James Troup <troup@debian.org>
7 # Copyright (c) 2004 Joey Schulze <joey@infodrom.org>
9 # This program is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 2 of the License, or
12 # (at your option) any later version.
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
19 # You should have received a copy of the GNU General Public License
20 # along with this program; if not, write to the Free Software
21 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 # This script is an interactive way to manipulate fields in the LDAP directory.
24 # When run it connects to the directory using the current users ID and fetches
25 # all the attributes for the first machine. It then formats them nicely and
26 # allows the user to change them.
28 # Usage: userinfo -a <user> -u <user> -c <user> -r
29 # -a Set the authentication user (the user whose password you are
31 # -h Set the host to display
33 import string, time, os, pwd, sys, getopt, ldap, crypt, whrandom, readline, copy;
34 from userdir_ldap import *;
37 AttrInfo = {"description": ["Machine Descr.", 1],
38 "hostname": ["Host names", 2],
39 "status": ["Status", 3],
41 "sponsor": ["Sponsors", 5],
42 "distribution": ["Distribution", 6],
43 "access": ["Access", 7],
44 "admin": ["Admin", 8],
45 "architecture": ["Architecture", 9],
46 "machine": ["Machine Hardware", 10],
47 "memory": ["Memory", 11],
49 "sshRSAHostKey": ["SSH Host Keys", 14],
50 "bandwidth": ["Bandwidth", 15]};
52 AttrPrompt = {"description": ["Purpose of the machine"],
53 "hostname": ["The hostnames for the box (ipv4/ipv6)"],
54 "status": ["Blank if Up, explaination if not"],
55 "l": ["Physical location"],
56 "sponsor": ["Sponsors and their URLs"],
57 "distribution": ["The distribution version"],
58 "access": ["all, developer only, restricted"],
59 "admin": ["Admin email address"],
60 "architecture": ["Debian Architecture string"],
61 "machine": ["Hardware description"],
62 "memory": ["Installed RAM"],
63 "disk": ["Disk Space, RAID levels, etc"],
64 "sshRSAHostKey": ["A copy of /etc/ssh/ssh_*host_key.pub"],
65 "bandwidth": ["Available outbound"]};
67 # Create a map of IDs to desc,value,attr
69 for at in AttrInfo.keys():
70 if (AttrInfo[at][1] != 0):
71 OrderedIndex[AttrInfo[at][1]] = [AttrInfo[at][0], "", at];
72 OrigOrderedIndex = copy.deepcopy(OrderedIndex);
74 # Print out the automatic time stamp information
75 def PrintModTime(Attrs):
76 Stamp = GetAttr(Attrs,"modifyTimestamp","");
78 Time = (int(Stamp[0:4]),int(Stamp[4:6]),int(Stamp[6:8]),
79 int(Stamp[8:10]),int(Stamp[10:12]),int(Stamp[12:14]),0,0,-1);
80 print "%-24s:" % ("Record last modified on"), time.strftime("%a %d/%m/%Y %X UTC",Time),
81 print "by",ldap.explode_dn(GetAttr(Attrs,"modifiersName"),1)[0];
83 Stamp = GetAttr(Attrs,"createTimestamp","");
85 Time = (int(Stamp[0:4]),int(Stamp[4:6]),int(Stamp[6:8]),
86 int(Stamp[8:10]),int(Stamp[10:12]),int(Stamp[12:14]),0,0,-1);
87 print "%-24s:" % ("Record created on"), time.strftime("%a %d/%m/%Y %X UTC",Time);
89 # Display all of the attributes in a numbered list
94 for at in Attrs[1].keys():
95 if AttrInfo.has_key(at):
96 if AttrInfo[at][1] == 0:
97 print " %-18s:" % (AttrInfo[at][0]),
98 for x in Attrs[1][at]:
102 OrderedIndex[AttrInfo[at][1]][1] = Attrs[1][at];
104 Keys = OrderedIndex.keys();
107 if at < 100 or RootMode != 0:
108 print " %3u) %-18s: " % (at,OrderedIndex[at][0]),
109 for x in OrderedIndex[at][1]:
110 print "'%s'" % (re.sub('[\n\r]','?',x)),
113 # Change a single attribute
114 def ChangeAttr(Attrs,Attr):
115 if (Attr == "sponsor" or Attr == "hostname" or Attr == "sshRSAHostKey"):
116 return MultiChangeAttr(Attrs,Attr);
118 print "Old value: '%s'" % (GetAttr(Attrs,Attr,""));
119 print "Press enter to leave unchanged and a single space to set to empty";
120 NewValue = raw_input("New? ");
124 print "Leaving unchanged.";
127 # Single space designates delete, trap the delete error
128 if (NewValue == " "):
131 l.modify_s(HostDn,[(ldap.MOD_DELETE,Attr,None)]);
132 except ldap.NO_SUCH_ATTRIBUTE:
136 Attrs[1][Attr] = [""];
141 l.modify_s(HostDn,[(ldap.MOD_REPLACE,Attr,NewValue)]);
142 Attrs[1][Attr] = [NewValue];
145 def MultiChangeAttr(Attrs,Attr):
146 # Make sure that we have an entry
147 if not Attrs[1].has_key(Attr):
150 Attrs[1][Attr].sort();
151 print "Old values: ",Attrs[1][Attr];
153 Mode = string.upper(raw_input("[D]elete or [A]dd? "));
154 if (Mode != 'D' and Mode != 'A'):
157 NewValue = raw_input("Value? ");
160 print "Leaving unchanged.";
167 l.modify_s(HostDn,[(ldap.MOD_DELETE,Attr,NewValue)]);
168 except ldap.NO_SUCH_ATTRIBUTE:
172 Attrs[1][Attr].remove(NewValue);
177 l.modify_s(HostDn,[(ldap.MOD_ADD,Attr,NewValue)]);
178 Attrs[1][Attr].append(NewValue);
181 # Main program starts here
182 User = pwd.getpwuid(os.getuid())[0];
185 (options, arguments) = getopt.getopt(sys.argv[1:], "nh:a:r")
186 for (switch, val) in options:
189 elif (switch == '-a'):
191 elif (switch == '-r'):
193 elif (switch == '-n'):
197 l = passwdAccessLDAP(LDAPServer, BaseDn, BindUser)
199 l = ldap.open(LDAPServer);
200 l.simple_bind_s("","")
202 HBaseDn = "ou=hosts,dc=debian,dc=org";
203 HostDn = "host=" + Host + "," + HBaseDn;
205 # Query the server for all of the attributes
206 Attrs = l.search_s(HBaseDn,ldap.SCOPE_ONELEVEL,"host=" + Host);
208 print "Host",Host,"was not found.";
211 # repeatedly show the account configuration
218 print " a) Arbitary Change";
219 print " n) New Host";
220 print " d) Delete Host";
221 print " u) Switch Hosts";
225 Response = raw_input("Change? ");
226 if (Response == "x" or Response == "X" or Response == "q" or
227 Response == "quit" or Response == "exit"):
230 # Change who we are looking at
231 if (Response == 'u' or Response == 'U'):
232 NewHost = raw_input("Host? ");
235 NAttrs = l.search_s(HBaseDn,ldap.SCOPE_ONELEVEL,"host=" + NewHost);
237 print "Host",NewHost,"was not found.";
241 HostDn = "host=" + Host + "," + HBaseDn;
242 OrderedIndex = copy.deepcopy(OrigOrderedIndex);
245 # Create a new entry and change to it Change who we are looking at
246 if (Response == 'n' or Response == 'N'):
247 NewHost = raw_input("Host? ");
250 NAttrs = l.search_s(HBaseDn,ldap.SCOPE_ONELEVEL,"host=" + NewHost);
252 print "Host",NewHost,"already exists.";
254 NewHostName = raw_input("Hostname? ");
257 Dn = "host=" + NewHost + "," + HBaseDn;
258 l.add_s(Dn,[("host", NewHost),
259 ("hostname", NewHostName),
260 ("objectClass", ("top", "debianServer"))]);
263 NAttrs = l.search_s(HBaseDn,ldap.SCOPE_ONELEVEL,"host=" + NewHost);
265 print "Host",NewHost,"was not found.";
269 HostDn = "host=" + Host + "," + HBaseDn;
270 OrderedIndex = copy.deepcopy(OrigOrderedIndex);
273 # Handle changing an arbitary value
274 if (Response == "a"):
275 Attr = raw_input("Attr? ");
276 ChangeAttr(Attrs[0],Attr);
279 if (Response == 'd'):
280 Really = raw_input("Really (type yes)? ");
283 print "Deleting",HostDn;
287 # Convert the integer response
290 if (not OrderedIndex.has_key(ID) or (ID > 100 and RootMode == 0)):
296 # Print the what to do prompt
297 print "Changing LDAP entry '%s' (%s)" % (OrderedIndex[ID][0],OrderedIndex[ID][2]);
298 print AttrPrompt[OrderedIndex[ID][2]][0];
299 ChangeAttr(Attrs[0],OrderedIndex[ID][2]);