r86019 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r86018‎ | r86019 | r86020 >
Date:02:24, 14 April 2011
Author:tstarling
Status:deferred
Tags:
Comment:
Subversion user management scripts written by Ryan Lane.
Modified paths:
  • /trunk/tools/subversion/user-management (added) (history)
  • /trunk/tools/subversion/user-management/add-ldap-group (added) (history)
  • /trunk/tools/subversion/user-management/add-ldap-user (added) (history)
  • /trunk/tools/subversion/user-management/change-ldap-passwd (added) (history)
  • /trunk/tools/subversion/user-management/delete-ldap-group (added) (history)
  • /trunk/tools/subversion/user-management/delete-ldap-user (added) (history)
  • /trunk/tools/subversion/user-management/homedirectorymanager.py (added) (history)
  • /trunk/tools/subversion/user-management/ldaplist (added) (history)
  • /trunk/tools/subversion/user-management/ldapsupportlib.py (added) (history)
  • /trunk/tools/subversion/user-management/modify-ldap-group (added) (history)
  • /trunk/tools/subversion/user-management/modify-ldap-user (added) (history)
  • /trunk/tools/subversion/user-management/netgroup-mod (added) (history)

Diff [purge]

Index: trunk/tools/subversion/user-management/homedirectorymanager.py
@@ -0,0 +1,263 @@
 2+#!/usr/bin/python
 3+import sys, traceback, os, datetime, ldapsupportlib, shutil, pwd, re, pycurl
 4+from optparse import OptionParser
 5+from cStringIO import StringIO
 6+
 7+try:
 8+ import ldap
 9+ import ldap.modlist
 10+except ImportError:
 11+ sys.stderr.write("Unable to import LDAP library.\n")
 12+ sys.exit(1)
 13+
 14+class HomeDirectoryManager:
 15+
 16+ def __init__(self):
 17+ ###################################################
 18+ # Configuration options #
 19+ ###################################################
 20+
 21+ # Change this if we change the home directory location!
 22+ self.basedir = '/home/'
 23+
 24+ # Directory to move deleted user's home directories
 25+ self.savedir = self.basedir + 'SAVE/'
 26+
 27+ # Add to this array if we add LDAP accounts that shouldn't
 28+ # have NFS mounted home directories.
 29+ self.excludedFromCreation = []
 30+
 31+ # Add to this array if we add directories that don't have
 32+ # LDAP accounts associated with them
 33+ self.excludedFromModification = ['lost+found', 'SAVE', 'svn-private']
 34+
 35+ # Skeleton files to add to the user's home directory
 36+ self.skelFiles = {}
 37+ self.skelFiles['/etc/skel/'] = ['.bashrc', '.profile', '.bash_logout']
 38+
 39+ self.dryRun = False
 40+ self.debugStatus = False
 41+
 42+ os.system('nscd -i passwd')
 43+ os.system('nscd -i group')
 44+
 45+ def run(self):
 46+ parser = OptionParser(conflict_handler="resolve")
 47+ parser.set_usage("homedirectorymanager.py [options]\n\nexample: homedirectorymanager.py --dry-run")
 48+
 49+ ldapSupportLib = ldapsupportlib.LDAPSupportLib()
 50+ ldapSupportLib.addParserOptions(parser)
 51+
 52+ parser.add_option("--dry-run", action="store_true", dest="dryRun", help="Show what would be done, but don't actually do anything")
 53+ parser.add_option("--debug", action="store_true", dest="debugStatus", help="Run in debug mode (you likely want to use --dry-run with this)")
 54+ (self.options, args) = parser.parse_args()
 55+
 56+ self.dryRun = self.options.dryRun
 57+ self.debugStatus = self.options.debugStatus
 58+
 59+ # use proxy agent by default
 60+ ldapSupportLib.setBindInfoByOptions(self.options, parser)
 61+
 62+ base = ldapSupportLib.getBase()
 63+
 64+ ds = ldapSupportLib.connect()
 65+ self.logDebug("Connected")
 66+
 67+ # w00t We're in!
 68+ try:
 69+ # get all user's uids
 70+ UsersData = ldapSupportLib.getUsers(ds, '*')
 71+ self.logDebug("Pulled the user information")
 72+
 73+ # We are going to use a dictionary (associative array) as a hash bucket (keys pointing to dictionaries)
 74+ # for the AllUsers data structure.
 75+ # The data structure will look like this:
 76+ # {"<uid>": {"uidNumber": <uidNumber>, "gidNumber": <gidNumber>, "sshPublicKey": ['key1', 'key2']},
 77+ # "<uid>": {"uidNumber": <uidNumber>, "gidNumber": <gidNumber>, "sshPublicKey": ['key1', 'key2']}}
 78+ AllUsers = {}
 79+ for user in UsersData:
 80+ uid = user[1]['uid'][0]
 81+ # uidNumber and gidNumber come back from LDAP as strings, we need ints here.
 82+ uidNumber = int(user[1]['uidNumber'][0])
 83+ gidNumber = int(user[1]['gidNumber'][0])
 84+ sshPublicKey = user[1]['sshPublicKey']
 85+
 86+ AllUsers[uid] = {}
 87+ AllUsers[uid]["uidNumber"] = uidNumber
 88+ AllUsers[uid]["gidNumber"] = gidNumber
 89+ AllUsers[uid]["sshPublicKey"] = sshPublicKey
 90+
 91+ self.changeGid(AllUsers)
 92+ self.changeUid(AllUsers)
 93+ self.moveUsers(AllUsers)
 94+ self.createHomeDir(AllUsers)
 95+
 96+ except ldap.UNWILLING_TO_PERFORM, msg:
 97+ sys.stderr.write("The search returned an error. Error was: %s\n" % msg[0]["info"])
 98+ ds.unbind()
 99+ sys.exit(1)
 100+ except Exception:
 101+ try:
 102+ sys.stderr.write("There was a general error, please contact an administrator via the helpdesk. Please include the following stack trace with your report:\n")
 103+ traceback.print_exc(file=sys.stderr)
 104+ ds.unbind()
 105+ except Exception:
 106+ pass
 107+ sys.exit(1)
 108+
 109+ ds.unbind()
 110+ sys.exit(0)
 111+
 112+ # Creates home directories for new users. Will not create home directories
 113+ # for users that already have a directory in SAVE
 114+ def createHomeDir(self, users):
 115+ alreadyCreated = []
 116+
 117+ for user in users.keys():
 118+ if user not in self.excludedFromCreation:
 119+ if os.path.exists(self.savedir + user):
 120+ # User's home directory already exists
 121+ alreadyCreated.append(user)
 122+ continue
 123+ if not os.path.exists(self.basedir + user):
 124+ self.log( "Creating a home directory for %s at %s%s" % (user, self.basedir, user) )
 125+ if not self.dryRun:
 126+ os.mkdir(self.basedir + user, 0700)
 127+ os.mkdir(self.basedir + user + '/.ssh', 0700)
 128+ self.writeKeys(user, users[user]['sshPublicKey'])
 129+ os.chmod(self.basedir + user + '/.ssh/authorized_keys', 0600)
 130+ for skeldir,skels in self.skelFiles.iteritems():
 131+ for skel in skels:
 132+ shutil.copy(skeldir + skel, self.basedir + user + "/")
 133+ os.chmod(self.basedir + user + "/" + skel, 0600)
 134+ newGid = users[user]['gidNumber']
 135+ newUid = users[user]['uidNumber']
 136+ os.chown(self.basedir + user, newUid, newGid)
 137+ for root, dirs, files in os.walk(self.basedir + user):
 138+ for name in files:
 139+ os.chown(os.path.join(root, name), newUid, newGid)
 140+ for name in dirs:
 141+ os.chown(os.path.join(root, name), newUid, newGid)
 142+
 143+ if alreadyCreated != []:
 144+ self.log( "The following users already have a home directory in the SAVE directory: " + ", ".join(alreadyCreated) )
 145+
 146+ def fetchKeys(self, location):
 147+ keys = []
 148+ if re.match('^http', location):
 149+ buffer = StringIO()
 150+ c = pycurl.Curl()
 151+ c.setopt(c.URL, location)
 152+ c.setopt(c.WRITEFUNCTION, buffer.write)
 153+ c.perform()
 154+ c.close()
 155+ raw_keys = buffer.getvalue().splitlines(True)
 156+ else:
 157+ file = open(location, 'r')
 158+ raw_keys = file.readlines()
 159+ for raw_key in raw_keys:
 160+ if (re.match('^$', raw_key) or re.match('^#', raw_key)):
 161+ continue
 162+ keys.append(raw_key)
 163+ return self.uniqueKeys(keys)
 164+
 165+ def uniqueKeys(self, keys):
 166+ uniqueKeys = []
 167+ [uniqueKeys.append(i) for i in keys if not uniqueKeys.count(i)]
 168+
 169+ return uniqueKeys
 170+
 171+ # Write a list of keys to the user's authorized_keys file
 172+ def writeKeys(self, user, keys):
 173+ f = open(self.basedir + user + '/.ssh/authorized_keys', 'w')
 174+ f.writelines(keys)
 175+ f.close()
 176+
 177+ # Moved deleted users to SAVE
 178+ def moveUsers(self, users):
 179+ for userdir in os.listdir(self.basedir):
 180+ if os.path.isdir(self.basedir + userdir) and userdir not in self.excludedFromModification:
 181+ try:
 182+ stat = os.stat(self.basedir + userdir)
 183+ uidNumber = stat.st_uid
 184+ # index 0 of getpwuid's return tuple is pw_name
 185+ uid = pwd.getpwuid(uidNumber)[0]
 186+ if userdir != uid:
 187+ # User name has changed, rename the home directory
 188+ self.renameUser(userdir, uid)
 189+ continue
 190+ except KeyError:
 191+ pass
 192+ if userdir not in users.keys():
 193+ try:
 194+ # Ensure the user isn't local
 195+ checkexist = pwd.getpwnam(userdir)[0]
 196+ except KeyError:
 197+ self.deleteUser(userdir)
 198+
 199+ def renameUser(self, olduserdir, newuserdir):
 200+ self.log( "Moving " + self.basedir + olduserdir + " to " + self.basedir + newuserdir )
 201+ if not self.dryRun:
 202+ os.rename(self.basedir + olduserdir, self.basedir + newuserdir)
 203+
 204+ def deleteUser(self, userdir):
 205+ # User has been deleted, move user's home directory to SAVE
 206+ if os.path.isdir(self.savedir + userdir):
 207+ self.log( userdir + " exists at both " + self.basedir + userdir + " and " + self.savedir + userdir )
 208+ else:
 209+ self.log( "Moving " + self.basedir + userdir + " to " + self.savedir + userdir )
 210+ if not self.dryRun:
 211+ os.rename(self.basedir + userdir, self.savedir + userdir)
 212+
 213+ # Changes the group ownership of a directory when a user's gid changes
 214+ def changeGid(self, users):
 215+ for userdir in os.listdir(self.basedir):
 216+ if os.path.isdir(self.basedir + userdir) and userdir not in self.excludedFromModification:
 217+ stat = os.stat(self.basedir + userdir)
 218+ gid = stat.st_gid
 219+ if userdir in users.keys() and users[userdir]["gidNumber"] != gid:
 220+ newGid = users[userdir]["gidNumber"]
 221+ self.log( "Changing group ownership of %s%s to %s; was set to %s" % (self.basedir, userdir, newGid, gid) )
 222+ if not self.dryRun:
 223+ # Python doesn't have a recursive chown, so we have to walk the directory
 224+ # and change everything manually
 225+ self.logDebug("Doing chgrp for: " + self.basedir + userdir + " with gid: " + str(gid))
 226+ os.chown(self.basedir + userdir, -1, newGid)
 227+ for root, dirs, files in os.walk(self.basedir + userdir):
 228+ for name in files:
 229+ os.chown(os.path.join(root, name), -1, newGid)
 230+ for name in dirs:
 231+ os.chown(os.path.join(root, name), -1, newGid)
 232+
 233+ # Changes the ownership of a directory when a user's uid changes
 234+ def changeUid(self, users):
 235+ for userdir in os.listdir(self.basedir):
 236+ if os.path.isdir(self.basedir + userdir) and userdir not in self.excludedFromModification:
 237+ stat = os.stat(self.basedir + userdir)
 238+ uid = stat.st_uid
 239+ if userdir in users.keys() and users[userdir]["uidNumber"] != uid:
 240+ newUid = users[userdir]["uidNumber"]
 241+ self.log( "Changing ownership of %s%s to %s; was set to %s" % (self.basedir, userdir, newUid, uid) )
 242+ if not self.dryRun:
 243+ # Python doesn't have a recursive chown, so we have to walk the directory
 244+ # and change everything manually
 245+ os.chown(self.basedir + userdir, newUid, -1)
 246+ for root, dirs, files in os.walk(self.basedir + userdir):
 247+ for name in files:
 248+ os.chown(os.path.join(root, name), newUid, -1)
 249+ for name in dirs:
 250+ os.chown(os.path.join(root, name), newUid, -1)
 251+
 252+ def log(self, logstring):
 253+ print datetime.datetime.now().strftime("%m/%d/%Y - %H:%M:%S - ") + logstring
 254+
 255+ def logDebug(self, logstring):
 256+ if self.debugStatus == True:
 257+ sys.stderr.write("Debug: " + logstring + "\n")
 258+
 259+def main():
 260+ homeDirectoryManager = HomeDirectoryManager()
 261+ homeDirectoryManager.run()
 262+
 263+if __name__ == "__main__":
 264+ main()
Property changes on: trunk/tools/subversion/user-management/homedirectorymanager.py
___________________________________________________________________
Added: svn:eol-style
1265 + native
Added: svn:executable
2266 + *
Index: trunk/tools/subversion/user-management/modify-ldap-group
@@ -0,0 +1,128 @@
 2+#!/usr/bin/python
 3+import sys, pwd, grp, traceback, getpass, ldapsupportlib, copy
 4+from optparse import OptionParser
 5+
 6+try:
 7+ import ldap
 8+ import ldap.modlist
 9+except ImportError:
 10+ sys.stderr.write("Unable to import LDAP library.\n")
 11+ sys.exit(1)
 12+
 13+def main():
 14+ parser = OptionParser(conflict_handler="resolve")
 15+ parser.set_usage('modify-ldap-group [options] <groupname> [--rename <newusergroup>]\nexample: modify-ldap-group --gid=501 wikidev')
 16+
 17+ ldapSupportLib = ldapsupportlib.LDAPSupportLib()
 18+ ldapSupportLib.addParserOptions(parser, "scriptuser")
 19+
 20+ parser.add_option("-m", "--directorymanager", action="store_true", dest="directorymanager", help="Use the Directory Manager's credentials, rather than your own")
 21+ parser.add_option("--gid", action="store", dest="gidNumber", help="Set the group's gid")
 22+ parser.add_option("--rename", action="store_true", dest="rename", help="Rename the user")
 23+ parser.add_option("--addmembers", action="store", dest="addMembers", help="Add a comma separated list of users to this group")
 24+ parser.add_option("--deletemembers", action="store", dest="deleteMembers", help="Delete a comma separated list of users from this")
 25+ (options, args) = parser.parse_args()
 26+
 27+ if len(args) != 1:
 28+ if options.rename and len(args) != 2:
 29+ parser.error("modify-ldap-group expects exactly two arguments when using rename.")
 30+ elif not options.rename:
 31+ parser.error("modify-ldap-group expects exactly one argument, unless using --rename.")
 32+
 33+ ldapSupportLib.setBindInfoByOptions(options, parser)
 34+
 35+ base = ldapSupportLib.getBase()
 36+
 37+ ds = ldapSupportLib.connect()
 38+
 39+ # w00t We're in!
 40+ try:
 41+ groupname = args[0]
 42+ PosixData = ds.search_s("ou=group," + base,ldap.SCOPE_SUBTREE,"(&(objectclass=posixGroup)(cn=" + groupname + "))")
 43+ if not PosixData:
 44+ raise ldap.NO_SUCH_OBJECT()
 45+ dn = PosixData[0][0]
 46+
 47+ if options.rename:
 48+ newgroupname = args[1]
 49+
 50+ # Rename the entry
 51+ newrdn = 'cn=' + newgroupname
 52+ ds.rename_s(dn, newrdn)
 53+ else:
 54+ PosixData = PosixData[0][1]
 55+ NewPosixData = copy.deepcopy(PosixData)
 56+ if options.gidNumber:
 57+ try:
 58+ groupcheck = grp.getgrgid(options.gidNumber)
 59+ raise ldap.TYPE_OR_VALUE_EXISTS()
 60+ except KeyError:
 61+ NewPosixData['gidNumber'] = options.gidNumber
 62+ if options.addMembers:
 63+ raw_members = options.addMembers.split(',')
 64+ for raw_member in raw_members:
 65+ try:
 66+ # Ensure the user exists
 67+ # TODO: make this use LDAP calls instead of getent
 68+ checkuid = pwd.getpwnam(raw_member)
 69+
 70+ membertoadd = 'uid=' + raw_member + ',ou=people,' + base
 71+ # uniqueMember expects DNs
 72+ if 'uniqueMember' in NewPosixData.keys():
 73+ if membertoadd in NewPosixData['uniqueMember']:
 74+ sys.stderr.write(raw_member + " is already a member of the group, skipping.\n")
 75+ else:
 76+ NewPosixData['uniqueMember'].append(membertoadd)
 77+ else:
 78+ NewPosixData['uniqueMember'] = [ membertoadd ]
 79+ except KeyError:
 80+ sys.stderr.write(raw_member + " doesn't exist, and won't be added to the group.\n")
 81+ elif options.deleteMembers:
 82+ raw_members = options.deleteMembers.split(',')
 83+ for raw_member in raw_members:
 84+ membertoremove = 'uid=' + raw_member + ',ou=people,' + base
 85+ if 'uniqueMember' in NewPosixData.keys():
 86+ if membertoremove in NewPosixData['uniqueMember']:
 87+ NewPosixData['uniqueMember'].remove(membertoremove)
 88+ else:
 89+ sys.stderr.write(raw_member + " isn't a member of the group, skipping.\n")
 90+ else:
 91+ sys.stderr.write("This group contains no members.\n")
 92+
 93+ if PosixData == NewPosixData:
 94+ sys.stderr.write("No changes to make; exiting.\n")
 95+ else:
 96+ modlist = ldap.modlist.modifyModlist(PosixData,NewPosixData)
 97+ ds.modify_s(dn, modlist)
 98+ except ldap.UNWILLING_TO_PERFORM, msg:
 99+ sys.stderr.write("LDAP was unwilling to modify the group. Error was: %s\n" % msg[0]["info"])
 100+ ds.unbind()
 101+ sys.exit(1)
 102+ except ldap.NO_SUCH_OBJECT:
 103+ sys.stderr.write("The group you are trying to modify doesn't exist.\n")
 104+ ds.unbind()
 105+ sys.exit(1)
 106+ except ldap.TYPE_OR_VALUE_EXISTS:
 107+ sys.stderr.write("The gid given already exists.\n")
 108+ ds.unbind()
 109+ sys.exit(1)
 110+ except ldap.PROTOCOL_ERROR:
 111+ sys.stderr.write("There was an LDAP protocol error; see traceback.\n")
 112+ traceback.print_exc(file=sys.stderr)
 113+ ds.unbind()
 114+ sys.exit(1)
 115+ except Exception:
 116+ try:
 117+ sys.stderr.write("There was a general error, this is unexpected; see traceback.\n")
 118+ traceback.print_exc(file=sys.stderr)
 119+ ds.unbind()
 120+ except Exception:
 121+ sys.stderr.write("Also failed to unbind.\n")
 122+ traceback.print_exc(file=sys.stderr)
 123+ sys.exit(1)
 124+
 125+ ds.unbind()
 126+ sys.exit(0)
 127+
 128+if __name__ == "__main__":
 129+ main()
Property changes on: trunk/tools/subversion/user-management/modify-ldap-group
___________________________________________________________________
Added: svn:eol-style
1130 + native
Added: svn:executable
2131 + *
Index: trunk/tools/subversion/user-management/add-ldap-group
@@ -0,0 +1,109 @@
 2+#!/usr/bin/python
 3+import sys, grp, pwd, traceback, getpass, re, ldapsupportlib
 4+from optparse import OptionParser
 5+
 6+try:
 7+ import ldap
 8+ import ldap.modlist
 9+except ImportError:
 10+ sys.stderr.write("Unable to import LDAP library.\n")
 11+ sys.exit(1)
 12+
 13+def main():
 14+ parser = OptionParser(conflict_handler="resolve")
 15+ parser.set_usage('add-ldap-group [options] <groupname>\nexample: add-ldap-group wikidev')
 16+
 17+ ldapSupportLib = ldapsupportlib.LDAPSupportLib()
 18+ ldapSupportLib.addParserOptions(parser, "scriptuser")
 19+
 20+ parser.add_option("-m", "--directorymanager", action="store_true", dest="directorymanager", help="Use the Directory Manager's credentials, rather than your own")
 21+ parser.add_option("--gid", action="store", dest="gidNumber", help="The group's gid (default: next available gid)")
 22+ parser.add_option("--members", action="store", dest="members", help="A comma separated list of group members to add to this group")
 23+ (options, args) = parser.parse_args()
 24+
 25+ if len(args) != 1:
 26+ parser.error("add-ldap-group expects exactly one argument.")
 27+
 28+ ldapSupportLib.setBindInfoByOptions(options, parser)
 29+
 30+ base = ldapSupportLib.getBase()
 31+
 32+ ds = ldapSupportLib.connect()
 33+
 34+ # w00t We're in!
 35+ try:
 36+ groupname = args[0]
 37+
 38+ dn = 'cn=' + groupname + ',ou=group,' + base
 39+ cn = groupname
 40+ objectClasses = ['posixGroup', 'groupOfUniqueNames', 'top']
 41+ if options.gidNumber:
 42+ try:
 43+ groupcheck = grp.getgrgid(options.gidNumber)
 44+ raise ldap.TYPE_OR_VALUE_EXISTS()
 45+ except KeyError:
 46+ gidNumber = options.gidNumber
 47+ else:
 48+ # Find the next gid
 49+ # TODO: make this use LDAP calls instead of getent
 50+ gids = []
 51+ for group in grp.getgrall():
 52+ tmpgid = group[2]
 53+ if tmpgid < 50000:
 54+ gids.append(group[2])
 55+ gids.sort()
 56+ gidNumber = gids.pop()
 57+ gidNumber = str(gidNumber + 1)
 58+
 59+ members = []
 60+ if options.members:
 61+ raw_members = options.members.split(',')
 62+ for raw_member in raw_members:
 63+ try:
 64+ # Ensure the user exists
 65+ # TODO: make this use LDAP calls instead of getent
 66+ checkuid = pwd.getpwnam(raw_member)
 67+
 68+ # uniqueMember expects DNs
 69+ members.append('uid=' + raw_member + ',ou=people,' + base)
 70+ except KeyError:
 71+ sys.stderr.write(raw_member + " doesn't exist, and won't be added to the group.\n")
 72+
 73+ groupEntry = {}
 74+ groupEntry['objectclass'] = objectClasses
 75+ groupEntry['gidNumber'] = gidNumber
 76+ groupEntry['cn'] = cn
 77+ if members:
 78+ groupEntry['uniqueMember'] = members
 79+
 80+ modlist = ldap.modlist.addModlist(groupEntry)
 81+ ds.add_s(dn, modlist)
 82+ except ldap.UNWILLING_TO_PERFORM, msg:
 83+ sys.stderr.write("LDAP was unwilling to create the group. Error was: %s\n" % msg[0]["info"])
 84+ ds.unbind()
 85+ sys.exit(1)
 86+ except ldap.TYPE_OR_VALUE_EXISTS:
 87+ sys.stderr.write("The group or gid you are trying to add already exists.\n")
 88+ traceback.print_exc(file=sys.stderr)
 89+ ds.unbind()
 90+ sys.exit(1)
 91+ except ldap.PROTOCOL_ERROR:
 92+ sys.stderr.write("There was an LDAP protocol error; see traceback.\n")
 93+ traceback.print_exc(file=sys.stderr)
 94+ ds.unbind()
 95+ sys.exit(1)
 96+ except Exception:
 97+ try:
 98+ sys.stderr.write("There was a general error, this is unexpected; see traceback.\n")
 99+ traceback.print_exc(file=sys.stderr)
 100+ ds.unbind()
 101+ except Exception:
 102+ sys.stderr.write("Also failed to unbind.\n")
 103+ traceback.print_exc(file=sys.stderr)
 104+ sys.exit(1)
 105+
 106+ ds.unbind()
 107+ sys.exit(0)
 108+
 109+if __name__ == "__main__":
 110+ main()
Property changes on: trunk/tools/subversion/user-management/add-ldap-group
___________________________________________________________________
Added: svn:eol-style
1111 + native
Added: svn:executable
2112 + *
Index: trunk/tools/subversion/user-management/netgroup-mod
@@ -0,0 +1,286 @@
 2+#!/usr/bin/python
 3+import sys, os, getpass, socket, copy, string, ldapsupportlib, traceback
 4+from optparse import OptionParser
 5+
 6+try:
 7+ import ldap
 8+ import ldap.modlist
 9+except ImportError:
 10+ sys.stderr.write("Unable to import LDAP library.\n")
 11+ sys.exit(1)
 12+
 13+def main():
 14+ parser = OptionParser(conflict_handler="resolve")
 15+ parser.set_usage('netgroup-mod [options] netgroup-name [host|-u user] [-f|--file filename]\n\nexample: netgroup-mod "test-ng" "fenari.wikimedia.org"\nexample: netgroup-mod "test-ng" -f test.file')
 16+
 17+ ldapSupportLib = ldapsupportlib.LDAPSupportLib()
 18+ ldapSupportLib.addParserOptions(parser, "scriptuser")
 19+
 20+ parser.add_option("-m", "--directorymanager", action="store_true", dest="directorymanager", help="Use the Directory Manager's credentials, rather than your own")
 21+ parser.add_option("-u", "--user", action="store_true", dest="user", help="Modify a user netgroup instead of a host netgroup.")
 22+ parser.add_option("--add", action="store_true", dest="addentry", help="Add new netgroup")
 23+ parser.add_option("--delete", action="store_true", dest="deleteentry", help="Delete a netgroup")
 24+ parser.add_option("-h", action="store_true", dest="hosts", help="Show available hosts")
 25+ parser.add_option("-n", action="store_true", dest="netgroups", help="Show available netgroups (notice you may not be able to add hosts to some netgroups shown). This option will show all available netgroups unless the additional non-exclusive flags are used.")
 26+ parser.add_option("--showhost", action="store_true", dest="showhost", help="Show ou=host netgroups (used with -n)")
 27+ parser.add_option("--showshare", action="store_true", dest="showshares", help="Show ou=shares netgroups (used with -n)")
 28+ parser.add_option("--showuser", action="store_true", dest="showuser", help="Show ou=user netgroups (used with -n)")
 29+ parser.add_option("-d", action="store_true", dest="delete", help="Remove provided host/user from provided netgroup")
 30+ parser.add_option("-f", "--file", dest="file", help="Add hosts provided from the following file. The file should have one IP address or hostname per line. IP addresses that are not in DNS will be ignored (you will be informed though).", metavar="FILE")
 31+ (options, args) = parser.parse_args()
 32+
 33+ ldapSupportLib.setBindInfoByOptions(options, parser)
 34+
 35+ base = ldapSupportLib.getBase()
 36+
 37+ ds = ldapSupportLib.connect()
 38+
 39+ # w00t We're in!
 40+ try:
 41+ if options.hosts:
 42+ PosixData = ds.search_s("ou=hosts," + base,ldap.SCOPE_SUBTREE,"(&(objectclass=iphost)(cn=*))")
 43+ elif options.netgroups:
 44+ PosixData = ds.search_s("ou=netgroup," + base,ldap.SCOPE_SUBTREE,"(&(objectclass=nisnetgroup)(cn=*))")
 45+ elif options.addentry:
 46+ PosixData = ds.search_s("ou=netgroup," + base,ldap.SCOPE_SUBTREE,"(&(objectclass=nisNetGroup)(cn=" + args[0] + "))")
 47+ if PosixData:
 48+ sys.stderr.write("The entry you wish to add already exists.\n")
 49+ sys.exit(1)
 50+ if not PosixData and options.addentry:
 51+ nametoadd = args[1]
 52+ if options.user:
 53+ formattednametoadd = "(," + nametoadd + ",)"
 54+ else:
 55+ nametocheck = nametoadd
 56+ nametoadd = socket.gethostbyaddr(nametocheck)[0]
 57+ formattednametoadd = "(" + nametoadd + ",,)"
 58+ netgrouplist = []
 59+ if options.file:
 60+ infofromfile(netgrouplist, "add", options.file, netgrouptype, PosixCheckData)
 61+ else:
 62+ netgrouplist.append(formattednametoadd)
 63+ NewPosixData = {}
 64+ NewPosixData['objectclass'] = ['top', 'nisnetgroup']
 65+ NewPosixData['nisnetgrouptriple'] = netgrouplist
 66+ mods = ldap.modlist.addModlist(NewPosixData)
 67+ ds.add_s('cn=' + args[0] + ",ou=netgroup," + base, mods)
 68+ print "The netgroup was successfully added."
 69+ sys.exit(0)
 70+ elif options.deleteentry:
 71+ PosixData = ds.search_s("ou=netgroup," + base,ldap.SCOPE_SUBTREE,"(&(objectclass=nisNetGroup)(cn=" + args[0] + "))")
 72+ if not PosixData:
 73+ sys.stderr.write("The entry you wish to delete doesn't exist.\n")
 74+ sys.exit(1)
 75+ else:
 76+ dn = PosixData[0][0]
 77+ verification = raw_input("Are you sure you wish to delete the following entry: " + dn + "? [y/N] ")
 78+ if verification == "y" or verification == "Y":
 79+ try:
 80+ ds.delete_s(dn)
 81+ print "The netgroup was successfully deleted.\n"
 82+ except Exception:
 83+ sys.stderr.write("There was an error while trying to delete the netgroup; see traceback\n")
 84+ traceback.print_exc(file=sys.stderr)
 85+ sys.exit(1)
 86+ sys.exit(0)
 87+ else:
 88+ print "Cancelling deletion\n"
 89+ sys.exit()
 90+ else:
 91+ try:
 92+ if options.user:
 93+ netgrouptype = "user"
 94+ else:
 95+ netgrouptype = "host"
 96+ if not options.file:
 97+ nametoadd = args[1]
 98+ if options.user:
 99+ formattednametoadd = "(," + nametoadd + ",)"
 100+ else:
 101+ nametocheck = nametoadd
 102+ nametoadd = socket.gethostbyaddr(nametocheck)[0]
 103+ formattednametoadd = "(" + nametoadd + ",,)"
 104+
 105+ netgrouptomod = args[0]
 106+ try:
 107+ PosixData = ds.search_s("ou=netgroup," + base,ldap.SCOPE_SUBTREE,"(&(objectclass=nisNetGroup)(cn=" + netgrouptomod + "))")
 108+ except Exception:
 109+ sys.stderr.write("There was an error while searching for the netgroup; see traceback\n")
 110+ traceback.print_exc(file=sys.stderr)
 111+ ds.unbind()
 112+ sys.exit(1)
 113+ if options.user:
 114+ PosixCheckData = ds.search_s("ou=people," + base,ldap.SCOPE_SUBTREE,"(&(objectclass=posixaccount)(uid=*))")
 115+ else:
 116+ PosixCheckData = ds.search_s("ou=hosts," + base,ldap.SCOPE_SUBTREE,"(&(objectclass=iphost)(cn=*))")
 117+
 118+ NewPosixData = copy.deepcopy(PosixData)
 119+ if NewPosixData[0][1].has_key('nisNetgroupTriple'):
 120+ if options.delete:
 121+ if options.file:
 122+ infofromfile(NewPosixData[0][1]['nisNetgroupTriple'], "delete", options.file, netgrouptype, PosixCheckData)
 123+ elif "(" + nametoadd + ",,)" in NewPosixData[0][1]['nisNetgroupTriple']:
 124+ NewPosixData[0][1]['nisNetgroupTriple'].remove(formattednametoadd)
 125+ else:
 126+ if options.file:
 127+ infofromfile(NewPosixData[0][1]['nisNetgroupTriple'], "add", options.file, netgrouptype, PosixCheckData)
 128+ else:
 129+ NewPosixData[0][1]['nisNetgroupTriple'].append(formattednametoadd)
 130+ else:
 131+ if not options.delete:
 132+ if options.file:
 133+ NewPosixData[0][1]['nisNetgroupTriple'] = []
 134+ infofromfile(NewPosixData[0][1]['nisNetgroupTriple'], "add", options.file, netgrouptype, PosixCheckData)
 135+ else:
 136+ NewPosixData[0][1]['nisNetgroupTriple'] = [formattednametoadd]
 137+
 138+ if PosixData == NewPosixData:
 139+ if options.delete:
 140+ sys.stderr.write("The host/user(s) you are trying to remove are not in the netgroup provided.\n")
 141+ ds.unbind()
 142+ sys.exit(1)
 143+ else:
 144+ sys.stderr.write("The host/user(s) you are trying to add are already in the netgroup provided.\n")
 145+ ds.unbind()
 146+ sys.exit(1)
 147+
 148+ netgroupdn = PosixData[0][0]
 149+ modlist = ldap.modlist.modifyModlist(PosixData[0][1], NewPosixData[0][1])
 150+ ds.modify_s(netgroupdn, modlist)
 151+ except socket.herror:
 152+ sys.stderr.write("This IP address isn't in DNS, please have it added, then try again.\n")
 153+ ds.unbind()
 154+ sys.exit(1)
 155+ except ldap.UNWILLING_TO_PERFORM, msg:
 156+ sys.stderr.write("The search returned an error. Error was: %s\n" % msg[0]["info"])
 157+ ds.unbind()
 158+ sys.exit(1)
 159+ except ldap.NO_SUCH_OBJECT:
 160+ sys.stderr.write("The netgroup provided cannot be found, please try again.\n")
 161+ ds.unbind()
 162+ sys.exit(1)
 163+ except ldap.TYPE_OR_VALUE_EXISTS:
 164+ sys.stderr.write("The host/user you are trying to add is already in the netgroup you provided.\n")
 165+ ds.unbind()
 166+ sys.exit(1)
 167+ except ldap.PROTOCOL_ERROR:
 168+ if options.delete:
 169+ sys.stderr.write("The host/user you are trying to remove is not in the netgroup you provided.\n")
 170+ else:
 171+ sys.stderr.write("There was an LDAP protocol error, please contact an administrator via the helpdesk.\n")
 172+ ds.unbind()
 173+ sys.exit(1)
 174+ #except Exception:
 175+ # try:
 176+ # ds.unbind()
 177+ # sys.stderr.write("There was a general error, please contact an administrator via the helpdesk.\n")
 178+ # except Exception:
 179+ # pass
 180+ # sys.exit(1)
 181+
 182+ # /End of stolen stuff
 183+
 184+ # PosixData is a list of lists where:
 185+ # index 0 of PosixData[N]: contains the distinquished name
 186+ # index 1 of PosixData[N]: contains a dictionary of lists hashed by the following keys:
 187+ # telephoneNumber, departmentNumber, uid, objectClass, loginShell,
 188+ # uidNumber, gidNumber, sn, homeDirectory, givenName, cn
 189+
 190+ if options.hosts or options.netgroups:
 191+ for i in range(len(PosixData)):
 192+ if options.hosts:
 193+ print "hostname: " + PosixData[i][1]["cn"][0]
 194+ print " IP: " + PosixData[i][1]["ipHostNumber"][0]
 195+ elif options.netgroups:
 196+ if not (options.showhost or options.showshares or options.showuser):
 197+ print "Netgroup Name: " + PosixData[i][1]["cn"][0]
 198+ else:
 199+ if options.showhost:
 200+ if "ou=host" in PosixData[i][0]:
 201+ print "Netgroup Name: " + PosixData[i][1]["cn"][0]
 202+ if options.showshares:
 203+ if "ou=shares" in PosixData[i][0]:
 204+ print "Netgroup Name: " + PosixData[i][1]["cn"][0]
 205+ if options.showuser:
 206+ if "ou=user" in PosixData[i][0]:
 207+ print "Netgroup Name: " + PosixData[i][1]["cn"][0]
 208+ else:
 209+ if options.user:
 210+ netgrouptype = "user"
 211+ else:
 212+ netgrouptype = "host"
 213+ if options.delete:
 214+ print "The " + netgrouptype + "(s) were successfully removed."
 215+ else:
 216+ print "The " + netgrouptype + "(s) were successfully added."
 217+
 218+ ds.unbind()
 219+ sys.exit(0)
 220+
 221+def checkargs(options, args):
 222+ if (len(args) < 2 or len(args) > 2):
 223+ if options.file and len(args) == 1:
 224+ return
 225+ sys.stderr.write("Invalid syntax, please see \"netgroup-mod --help\"\n")
 226+ sys.exit(1)
 227+
 228+def infofromfile(list, changetype, file, netgrouptype, PosixCheckData):
 229+ f = open(file)
 230+ for line in f:
 231+ try:
 232+ line = string.strip(line)
 233+ if netgrouptype == "user":
 234+ nametoadd = "(," + line + ",)"
 235+ else:
 236+ # netgrouptype is "host"
 237+ nametoadd1 = socket.gethostbyaddr(line)[0]
 238+ nametoadd = "(" + nametoadd1 + ",,)"
 239+ if changetype == "delete" and nametoadd in list:
 240+ list.remove(nametoadd)
 241+ elif changetype == "add" and nametoadd not in list:
 242+ if netgrouptype == "user":
 243+ if checkuserinldap(line, PosixCheckData):
 244+ list.append(nametoadd)
 245+ else:
 246+ continue
 247+ else:
 248+ # netgrouptype is "host"
 249+ if checkhostinldap(line, nametoadd1, PosixCheckData):
 250+ list.append(nametoadd)
 251+ else:
 252+ continue
 253+ else:
 254+ if changetype == "delete":
 255+ sys.stderr.write(line + " is not in the netgroup provided.\n")
 256+ else:
 257+ sys.stderr.write(line + " is already in the netgroup provided.\n")
 258+ except socket.herror:
 259+ sys.stderr.write(line + " isn't in DNS, please have it added, then try again.\n")
 260+ except socket.gaierror:
 261+ sys.stderr.write(line + " isn't in DNS, please have it added, then try again.\n")
 262+
 263+def checkuserinldap(user, PosixCheckData):
 264+ for i in range(len(PosixCheckData)):
 265+ if string.lower(PosixCheckData[i][1]['uid'][0]) == string.lower(user):
 266+ return True
 267+ # We just looped through all the users in LDAP. The user doesn't exist.
 268+ sys.stderr.write(user + " cannot be found in LDAP.\n")
 269+ return False
 270+
 271+def checkhostinldap(host, hostfromdns, PosixCheckData):
 272+ for i in range(len(PosixCheckData)):
 273+ if string.lower(PosixCheckData[i][1]['cn'][0]) == string.lower(hostfromdns):
 274+ return True
 275+ elif string.lower(PosixCheckData[i][1]['cn'][0]) == string.lower(host):
 276+ sys.stderr.write(host + " matches an entry in LDAP; however, the DNS entry is different than the LDAP entry, please put in a ripken ticket (skipping)\n")
 277+ return False
 278+ elif string.lower(PosixCheckData[i][1]['ipHostNumber'][0]) == string.lower(host):
 279+ sys.stderr.write(host + " matches an IP address in LDAP; however, the LDAP entry and the DNS entry are in conflict, please put in a ripken ticket (skipping)\n")
 280+ return False
 281+ # We just looped through all the hosts in LDAP. The host doesn't exist.
 282+ # Since we are only checking to make sure there aren't LDAP/DNS
 283+ # conflicts, this is ok.
 284+ return True
 285+
 286+if __name__ == "__main__":
 287+ main()
Property changes on: trunk/tools/subversion/user-management/netgroup-mod
___________________________________________________________________
Added: svn:eol-style
1288 + native
Added: svn:executable
2289 + *
Index: trunk/tools/subversion/user-management/modify-ldap-user
@@ -0,0 +1,135 @@
 2+#!/usr/bin/python
 3+import sys, pwd, traceback, getpass, re, ldapsupportlib, pycurl, copy, homedirectorymanager
 4+from optparse import OptionParser
 5+
 6+try:
 7+ import ldap
 8+ import ldap.modlist
 9+except ImportError:
 10+ sys.stderr.write("Unable to import LDAP library.\n")
 11+ sys.exit(1)
 12+
 13+def main():
 14+ parser = OptionParser(conflict_handler="resolve")
 15+ parser.set_usage('modify-ldap-user [options] <username> [--rename <newusername>]\nexample: modify-ldap-user --replacekeys=http://ryandlane.com/static/pubkey.key laner')
 16+
 17+ ldapSupportLib = ldapsupportlib.LDAPSupportLib()
 18+ ldapSupportLib.addParserOptions(parser, "scriptuser")
 19+
 20+ parser.add_option("-m", "--directorymanager", action="store_true", dest="directorymanager", help="Use the Directory Manager's credentials, rather than your own")
 21+ parser.add_option("--shell", action="store", dest="loginShell", help="Set the user's shell")
 22+ parser.add_option("--gid", action="store", dest="gidNumber", help="Set the user's gid")
 23+ parser.add_option("--uid", action="store", dest="uidNumber", help="Set the user's uid")
 24+ parser.add_option("--cn", action="store", dest="cn", help="Set the user's CN")
 25+ parser.add_option("--firstname", action="store", dest="givenName", help="Set the user's first name")
 26+ parser.add_option("--lastname", action="store", dest="sn", help="Set the user's last name")
 27+ parser.add_option("--replacekeys", action="store", dest="replaceKeyLocation", help="Replaces all of the user's keys")
 28+ parser.add_option("--addkeys", action="store", dest="addKeyLocation", help="Adds keys to the user's entry")
 29+ parser.add_option("--rename", action="store_true", dest="rename", help="Rename the user")
 30+ (options, args) = parser.parse_args()
 31+
 32+ if len(args) != 1:
 33+ if options.rename and len(args) != 2:
 34+ parser.error("modify-ldap-user expects exactly two arguments when using rename.")
 35+ elif not options.rename:
 36+ parser.error("modify-ldap-user expects exactly one argument, unless using --rename.")
 37+
 38+ ldapSupportLib.setBindInfoByOptions(options, parser)
 39+
 40+ base = ldapSupportLib.getBase()
 41+
 42+ ds = ldapSupportLib.connect()
 43+
 44+ # w00t We're in!
 45+ try:
 46+ username = args[0]
 47+ PosixData = ds.search_s("ou=people," + base,ldap.SCOPE_SUBTREE,"(&(objectclass=inetOrgPerson)(uid=" + username + "))")
 48+ if not PosixData:
 49+ raise ldap.NO_SUCH_OBJECT()
 50+ dn = PosixData[0][0]
 51+ hdm = homedirectorymanager.HomeDirectoryManager()
 52+
 53+ if options.rename:
 54+ newusername = args[1]
 55+ if newusername == "root":
 56+ sys.stderr.write("You are not allowed to rename a user to root.\n")
 57+ sys.exit(1)
 58+
 59+ # Rename the entry
 60+ newrdn = 'uid=' + newusername
 61+ ds.rename_s(dn, newrdn)
 62+
 63+ # Fix the user's home directory
 64+ PosixData = ds.search_s("ou=people," + base,ldap.SCOPE_SUBTREE,"(&(objectclass=inetOrgPerson)(uid=" + newusername + "))")
 65+ dn = PosixData[0][0]
 66+ PosixData = PosixData[0][1]
 67+ NewPosixData = copy.deepcopy(PosixData)
 68+ NewPosixData['homeDirectory'] = '/home/' + newusername
 69+ modlist = ldap.modlist.modifyModlist(PosixData,NewPosixData)
 70+ ds.modify_s(dn, modlist)
 71+
 72+ # Update the home directory
 73+ hdm.moveUser(username, newusername)
 74+ else:
 75+ PosixData = PosixData[0][1]
 76+ NewPosixData = copy.deepcopy(PosixData)
 77+ if options.replaceKeyLocation:
 78+ keys = hdm.fetchKeys(options.replaceKeyLocation)
 79+ NewPosixData['sshPublicKey'] = keys
 80+ if options.addKeyLocation:
 81+ keys = hdm.fetchKeys(options.addKeyLocation)
 82+ NewPosixData['sshPublicKey'].extend(keys)
 83+ NewPosixData['sshPublicKey'] = hdm.uniqueKeys(NewPosixData['sshPublicKey'])
 84+ if options.loginShell:
 85+ NewPosixData['loginShell'] = options.loginShell
 86+ if options.uidNumber:
 87+ if int(options.uidNumber) < 500:
 88+ sys.stderr.write("Setting uid to less than 500 is not allowed.\n")
 89+ sys.exit(1)
 90+ NewPosixData['uidNumber'] = options.uidNumber
 91+ if options.gidNumber:
 92+ NewPosixData['gidNumber'] = options.gidNumber
 93+ if options.sn:
 94+ NewPosixData['sn'] = options.sn
 95+ if options.givenName:
 96+ NewPosixData['givenName'] = options.givenName
 97+ if options.cn:
 98+ NewPosixData['cn'] = options.cn
 99+
 100+ if PosixData == NewPosixData:
 101+ sys.stderr.write("No changes to make; exiting.\n")
 102+ else:
 103+ modlist = ldap.modlist.modifyModlist(PosixData,NewPosixData)
 104+ ds.modify_s(dn, modlist)
 105+
 106+ if options.replaceKeyLocation or options.addKeyLocation:
 107+ # Update the keys
 108+ hdm.writeKeys(username, NewPosixData['sshPublicKey'])
 109+ except ldap.UNWILLING_TO_PERFORM, msg:
 110+ sys.stderr.write("LDAP was unwilling to create the user. Error was: %s\n" % msg[0]["info"])
 111+ ds.unbind()
 112+ sys.exit(1)
 113+ except ldap.NO_SUCH_OBJECT:
 114+ sys.stderr.write("The user you are trying to modify doesn't exist.\n")
 115+ ds.unbind()
 116+ sys.exit(1)
 117+ except ldap.PROTOCOL_ERROR:
 118+ sys.stderr.write("There was an LDAP protocol error; see traceback.\n")
 119+ traceback.print_exc(file=sys.stderr)
 120+ ds.unbind()
 121+ sys.exit(1)
 122+ except Exception:
 123+ try:
 124+ sys.stderr.write("There was a general error, this is unexpected; see traceback.\n")
 125+ traceback.print_exc(file=sys.stderr)
 126+ ds.unbind()
 127+ except Exception:
 128+ sys.stderr.write("Also failed to unbind.\n")
 129+ traceback.print_exc(file=sys.stderr)
 130+ sys.exit(1)
 131+
 132+ ds.unbind()
 133+ sys.exit(0)
 134+
 135+if __name__ == "__main__":
 136+ main()
Property changes on: trunk/tools/subversion/user-management/modify-ldap-user
___________________________________________________________________
Added: svn:eol-style
1137 + native
Added: svn:executable
2138 + *
Index: trunk/tools/subversion/user-management/add-ldap-user
@@ -0,0 +1,155 @@
 2+#!/usr/bin/python
 3+import sys, pwd, traceback, getpass, re, ldapsupportlib, pycurl, homedirectorymanager
 4+from optparse import OptionParser
 5+from cStringIO import StringIO
 6+
 7+try:
 8+ import ldap
 9+ import ldap.modlist
 10+except ImportError:
 11+ sys.stderr.write("Unable to import LDAP library.\n")
 12+ sys.exit(1)
 13+
 14+def main():
 15+ parser = OptionParser(conflict_handler="resolve")
 16+ parser.set_usage('add-ldap-user [options] <username> <key(s)>\nexample: add-ldap-user laner http://ryandlane.com/static/pubkey.key')
 17+
 18+ ldapSupportLib = ldapsupportlib.LDAPSupportLib()
 19+ ldapSupportLib.addParserOptions(parser, "scriptuser")
 20+
 21+ parser.add_option("-m", "--directorymanager", action="store_true", dest="directorymanager", help="Use the Directory Manager's credentials, rather than your own")
 22+ parser.add_option("--shell", action="store", dest="loginShell", default="/usr/local/bin/sillyshell", help="The user's shell (default: /usr/bin/sillyshell)")
 23+ parser.add_option("--gid", action="store", dest="gidNumber", default="550", help="The user's gid (default: 550)")
 24+ parser.add_option("--uid", action="store", dest="uidNumber", help="The user's uid (default: next available uid)")
 25+ parser.add_option("--home", action="store", dest="homeDirectory", help="The user's home directory (default /home/username)")
 26+ parser.add_option("--cn", action="store", dest="cn", help="The user's CN (default: firstname + lastname, or username, if first/last not set)")
 27+ parser.add_option("--firstname", action="store", dest="givenName", help="The user's first name (default: username)")
 28+ parser.add_option("--lastname", action="store", dest="sn", help="The user's last name (default: username)")
 29+ (options, args) = parser.parse_args()
 30+
 31+ if len(args) != 2:
 32+ parser.error("add-ldap-user expects exactly two arguments.")
 33+
 34+ ldapSupportLib.setBindInfoByOptions(options, parser)
 35+
 36+ base = ldapSupportLib.getBase()
 37+
 38+ ds = ldapSupportLib.connect()
 39+
 40+ # w00t We're in!
 41+ try:
 42+ username = args[0]
 43+ if username == "root":
 44+ sys.stderr.write("You are not allowed to add a root user\n")
 45+ sys.exit(1)
 46+
 47+ keyLocation = args[1]
 48+ keys = []
 49+ if re.match('^http', keyLocation):
 50+ buffer = StringIO()
 51+ c = pycurl.Curl()
 52+ c.setopt(c.URL, keyLocation)
 53+ c.setopt(c.WRITEFUNCTION, buffer.write)
 54+ c.perform()
 55+ c.close()
 56+ raw_keys = buffer.getvalue()
 57+ else:
 58+ file = open(keyLocation, 'r')
 59+ raw_keys = file.readlines()
 60+ for raw_key in raw_keys:
 61+ if (re.match('^$', raw_key) or re.match('^#', raw_key)):
 62+ continue
 63+ raw_key = raw_key.strip()
 64+ keys.append(raw_key)
 65+
 66+ # We need to ensure the keys are unique to avoid an exception
 67+ uniqueKeys = []
 68+ [uniqueKeys.append(i) for i in keys if not uniqueKeys.count(i)]
 69+ keys = uniqueKeys
 70+
 71+ dn = 'uid=' + username + ',ou=people,' + base
 72+ uid = username
 73+ objectClasses = ['person', 'organizationalPerson', 'inetorgperson', 'ldapPublicKey', 'shadowaccount', 'posixaccount', 'top']
 74+ loginShell = options.loginShell
 75+ if options.homeDirectory:
 76+ homeDirectory = options.homeDirectory
 77+ else:
 78+ homeDirectory = '/home/' + username
 79+ if options.uidNumber:
 80+ uidNumber = options.uidNumber
 81+ if int(uidNumber) < 500:
 82+ sys.stderr.write("Setting uidnumber to less than 500 is not allowed\n")
 83+ sys.exit(1)
 84+ else:
 85+ # Find the next uid
 86+ uids = []
 87+ for user in pwd.getpwall():
 88+ tmpuid = user[2]
 89+ if tmpuid < 50000:
 90+ uids.append(user[2])
 91+ uids.sort()
 92+ uidNumber = uids.pop()
 93+ uidNumber = str(uidNumber + 1)
 94+ gidNumber = options.gidNumber
 95+ if options.sn:
 96+ sn = options.sn
 97+ else:
 98+ sn = username
 99+ if options.givenName:
 100+ givenName = options.givenName
 101+ else:
 102+ givenName = username
 103+ if options.cn:
 104+ cn = options.cn
 105+ elif options.givenName and options.sn:
 106+ cn = options.givenName + " " + options.sn
 107+ else:
 108+ cn = username
 109+
 110+ userEntry = {}
 111+ userEntry['uid'] = uid
 112+ userEntry['objectclass'] = objectClasses
 113+ userEntry['loginShell'] = loginShell
 114+ userEntry['homeDirectory'] = homeDirectory
 115+ userEntry['sshPublicKey'] = keys
 116+ userEntry['uidNumber'] = uidNumber
 117+ userEntry['gidNumber'] = gidNumber
 118+ userEntry['givenName'] = givenName
 119+ userEntry['sn'] = sn
 120+ userEntry['cn'] = cn
 121+
 122+ modlist = ldap.modlist.addModlist(userEntry)
 123+ ds.add_s(dn, modlist)
 124+
 125+ userdict = {uid: {"uidNumber": int(uidNumber), "gidNumber": int(gidNumber), "sshPublicKey": keys}}
 126+ hdm = homedirectorymanager.HomeDirectoryManager()
 127+ hdm.createHomeDir(userdict)
 128+ except ldap.UNWILLING_TO_PERFORM, msg:
 129+ sys.stderr.write("LDAP was unwilling to create the user. Error was: %s\n" % msg[0]["info"])
 130+ ds.unbind()
 131+ sys.exit(1)
 132+ except ldap.TYPE_OR_VALUE_EXISTS:
 133+ sys.stderr.write("The user you are trying to add already exists.\n")
 134+ traceback.print_exc(file=sys.stderr)
 135+ ds.unbind()
 136+ sys.exit(1)
 137+ except ldap.PROTOCOL_ERROR:
 138+ sys.stderr.write("There was an LDAP protocol error; see traceback.\n")
 139+ traceback.print_exc(file=sys.stderr)
 140+ ds.unbind()
 141+ sys.exit(1)
 142+ except Exception:
 143+ try:
 144+ sys.stderr.write("There was a general error, this is unexpected; see traceback.\n")
 145+ traceback.print_exc(file=sys.stderr)
 146+ ds.unbind()
 147+ except Exception:
 148+ sys.stderr.write("Also failed to unbind.\n")
 149+ traceback.print_exc(file=sys.stderr)
 150+ sys.exit(1)
 151+
 152+ ds.unbind()
 153+ sys.exit(0)
 154+
 155+if __name__ == "__main__":
 156+ main()
Property changes on: trunk/tools/subversion/user-management/add-ldap-user
___________________________________________________________________
Added: svn:eol-style
1157 + native
Added: svn:executable
2158 + *
Index: trunk/tools/subversion/user-management/change-ldap-passwd
@@ -0,0 +1,71 @@
 2+#!/usr/bin/python
 3+import sys, traceback, getpass, ldapsupportlib
 4+from optparse import OptionParser
 5+
 6+try:
 7+ import ldap
 8+ import ldap.modlist
 9+except ImportError:
 10+ sys.stderr.write("Unable to import LDAP library.\n")
 11+ sys.exit(1)
 12+
 13+def main():
 14+ parser = OptionParser(conflict_handler="resolve")
 15+ parser.set_usage('change-ldap-passwd [options] <username>')
 16+
 17+ ldapSupportLib = ldapsupportlib.LDAPSupportLib()
 18+ ldapSupportLib.addParserOptions(parser, "scriptuser")
 19+
 20+ parser.add_option("-m", "--directorymanager", action="store_true", dest="directorymanager", help="Use the Directory Manager's credentials, rather than your own")
 21+ (options, args) = parser.parse_args()
 22+
 23+ if len(args) != 1:
 24+ parser.error("add-ldap-user expects exactly one argument.")
 25+
 26+ ldapSupportLib.setBindInfoByOptions(options, parser)
 27+
 28+ base = ldapSupportLib.getBase()
 29+
 30+ ds = ldapSupportLib.connect()
 31+
 32+ # w00t We're in!
 33+ try:
 34+ username = args[0]
 35+ dn = 'uid=' + username + ',ou=people,' + base
 36+ while True:
 37+ newpass = getpass.getpass('New password: ')
 38+ repeat = getpass.getpass('Repeat new password: ')
 39+ if newpass != repeat:
 40+ print "Passwords do no match, please try again"
 41+ else:
 42+ break
 43+ mod_attrs = [( ldap.MOD_REPLACE, 'userPassword', newpass )]
 44+ ds.modify_s(dn, mod_attrs)
 45+ except ldap.UNWILLING_TO_PERFORM, msg:
 46+ sys.stderr.write("LDAP was unwilling to change the user's password. Error was: %s\n" % msg[0]["info"])
 47+ ds.unbind()
 48+ sys.exit(1)
 49+ except ldap.NO_SUCH_OBJECT:
 50+ sys.stderr.write("The user you are trying to modify does not exists.\n")
 51+ ds.unbind()
 52+ sys.exit(1)
 53+ except ldap.PROTOCOL_ERROR:
 54+ sys.stderr.write("There was an LDAP protocol error; see traceback.\n")
 55+ traceback.print_exc(file=sys.stderr)
 56+ ds.unbind()
 57+ sys.exit(1)
 58+ except Exception:
 59+ try:
 60+ sys.stderr.write("There was a general error, this is unexpected; see traceback.\n")
 61+ traceback.print_exc(file=sys.stderr)
 62+ ds.unbind()
 63+ except Exception:
 64+ sys.stderr.write("Also failed to unbind.\n")
 65+ traceback.print_exc(file=sys.stderr)
 66+ sys.exit(1)
 67+
 68+ ds.unbind()
 69+ sys.exit(0)
 70+
 71+if __name__ == "__main__":
 72+ main()
Property changes on: trunk/tools/subversion/user-management/change-ldap-passwd
___________________________________________________________________
Added: svn:eol-style
173 + native
Added: svn:executable
274 + *
Index: trunk/tools/subversion/user-management/delete-ldap-group
@@ -0,0 +1,63 @@
 2+#!/usr/bin/python
 3+import sys, pwd, traceback, getpass, ldapsupportlib, homedirectorymanager
 4+from optparse import OptionParser
 5+
 6+try:
 7+ import ldap
 8+ import ldap.modlist
 9+except ImportError:
 10+ sys.stderr.write("Unable to import LDAP library.\n")
 11+ sys.exit(1)
 12+
 13+def main():
 14+ parser = OptionParser(conflict_handler="resolve")
 15+ parser.set_usage('delete-ldap-group [options] <username>')
 16+
 17+ ldapSupportLib = ldapsupportlib.LDAPSupportLib()
 18+ ldapSupportLib.addParserOptions(parser, "scriptuser")
 19+
 20+ parser.add_option("-m", "--directorymanager", action="store_true", dest="directorymanager", help="Use the Directory Manager's credentials, rather than your own")
 21+ (options, args) = parser.parse_args()
 22+
 23+ if len(args) != 1:
 24+ parser.error("delete-ldap-group expects exactly one argument.")
 25+
 26+ ldapSupportLib.setBindInfoByOptions(options, parser)
 27+
 28+ base = ldapSupportLib.getBase()
 29+
 30+ ds = ldapSupportLib.connect()
 31+
 32+ # w00t We're in!
 33+ try:
 34+ groupname = args[0]
 35+ dn = 'cn=' + groupname + ',ou=group,' + base
 36+ ds.delete_s(dn)
 37+ except ldap.UNWILLING_TO_PERFORM, msg:
 38+ sys.stderr.write("LDAP was unwilling to delete the group. Error was: %s\n" % msg[0]["info"])
 39+ ds.unbind()
 40+ sys.exit(1)
 41+ except ldap.NO_SUCH_OBJECT:
 42+ sys.stderr.write("The group you are trying to delete does not exists.\n")
 43+ ds.unbind()
 44+ sys.exit(1)
 45+ except ldap.PROTOCOL_ERROR:
 46+ sys.stderr.write("There was an LDAP protocol error; see traceback.\n")
 47+ traceback.print_exc(file=sys.stderr)
 48+ ds.unbind()
 49+ sys.exit(1)
 50+ except Exception:
 51+ try:
 52+ sys.stderr.write("There was a general error, this is unexpected; see traceback.\n")
 53+ traceback.print_exc(file=sys.stderr)
 54+ ds.unbind()
 55+ except Exception:
 56+ sys.stderr.write("Also failed to unbind.\n")
 57+ traceback.print_exc(file=sys.stderr)
 58+ sys.exit(1)
 59+
 60+ ds.unbind()
 61+ sys.exit(0)
 62+
 63+if __name__ == "__main__":
 64+ main()
Property changes on: trunk/tools/subversion/user-management/delete-ldap-group
___________________________________________________________________
Added: svn:eol-style
165 + native
Added: svn:executable
266 + *
Index: trunk/tools/subversion/user-management/ldapsupportlib.py
@@ -0,0 +1,120 @@
 2+#!/usr/bin/python
 3+import os, traceback, getpass, sys
 4+
 5+try:
 6+ import ldap
 7+except ImportError:
 8+ sys.stderr.write("Unable to import LDAP library.\n")
 9+ sys.exit(1)
 10+
 11+class LDAPSupportLib:
 12+
 13+ def __init__(self):
 14+ self.base = self.getLdapInfo("base")
 15+ self.ldapHost = self.getLdapInfo("uri")
 16+ self.sslType = self.getLdapInfo("ssl")
 17+ self.binddn = self.getLdapInfo("binddn")
 18+ self.bindpw = self.getLdapInfo("bindpw")
 19+ self.defaults = {}
 20+
 21+ def addParserOptions(self, parser, default="proxy"):
 22+ parser.add_option("-s", "--self", action="store_true", dest="useself", help="Use your credentials")
 23+ parser.add_option("-D", "--bindas", action="store", dest="bindas", help="Specify user to bind as")
 24+ parser.add_option("-m", "--directorymanager", action="store_true", dest="directorymanager", help="Use the Directory Manager's credentials")
 25+ parser.add_option("--scriptuser", action="store_true", dest="scriptuser", help="Use the scriptusers' credentials")
 26+ self.defaults['authuser'] = "proxy"
 27+ if ( default == "user" ):
 28+ self.defaults['authuser'] = "user"
 29+ if ( default == "Directory Manager" ):
 30+ self.defaults['authuser'] = "Directory Manager"
 31+ if ( default == "scriptuser" ):
 32+ self.defaults['authuser'] = "scriptuser"
 33+
 34+ def getUsers(self, ds, username):
 35+ PosixData = ds.search_s("ou=people," + self.base,ldap.SCOPE_SUBTREE,"(&(objectclass=inetOrgPerson)(uid=" + username + "))")
 36+ return PosixData
 37+
 38+ def getKeys(self, ds, username):
 39+ user = self.getUsers(ds, username)
 40+ if 'sshPublicKey' in user[0][1].keys():
 41+ return user[1]['sshPublicKey']
 42+ else:
 43+ return []
 44+
 45+ def setHost(self, host):
 46+ self.ldapHost = host
 47+
 48+ def setBase(self, base):
 49+ self.base = base
 50+
 51+ def setBindInfoByOptions(self, options, parser):
 52+ if not (options.useself or options.directorymanager):
 53+ if self.defaults['authuser'] == "user":
 54+ options.useself = True
 55+ if self.defaults['authuser'] == "Directory Manager":
 56+ options.directorymanager = True
 57+ if self.defaults['authuser'] == "scriptuser":
 58+ options.scriptuser = True
 59+ if options.useself:
 60+ self.binddn = "uid=" + os.environ['USER'] + ",ou=people," + self.base
 61+ self.bindpw = getpass.getpass()
 62+ elif options.directorymanager:
 63+ self.binddn = "cn=Directory Manager"
 64+ self.bindpw = getpass.getpass()
 65+ elif options.bindas:
 66+ self.binddn = "uid=" + options.bindas + ",ou=people," + self.base
 67+ self.bindpw = getpass.getpass()
 68+ elif options.scriptuser:
 69+ self.binddn = self.getLdapInfo('USER', '/etc/ldap/.ldapscriptrc')
 70+ self.bindpw = self.getLdapInfo('PASS', '/etc/ldap/.ldapscriptrc')
 71+
 72+ def setBindDN(self, binddn):
 73+ self.binddn = binddn
 74+
 75+ def setBindPW(self, bindpw):
 76+ self.bindpw = bindpw
 77+
 78+ def getBase(self):
 79+ return self.base
 80+
 81+ def getHost(self):
 82+ return self.ldapHost
 83+
 84+ def getLdapInfo(self, attr, conffile="/etc/ldap.conf"):
 85+ f = open(conffile)
 86+ for line in f:
 87+ if line.split()[0] == attr:
 88+ return line.split()[1]
 89+ break
 90+
 91+ def connect(self):
 92+ try:
 93+ ds = ldap.initialize(self.ldapHost)
 94+ ds.protocol_version=ldap.VERSION3
 95+ if self.sslType == "start_tls":
 96+ ds.start_tls_s()
 97+ except Exception:
 98+ sys.stderr.write("Unable to connect to LDAP host: %s\n" % self.ldapHost)
 99+ traceback.print_exc(file=sys.stderr)
 100+ sys.exit(1)
 101+
 102+ try:
 103+ ds.simple_bind_s(self.binddn,self.bindpw)
 104+ return ds
 105+ except ldap.CONSTRAINT_VIOLATION:
 106+ sys.stderr.write("You typed your password incorrectly too many times, and are now locked out. Please try again later.\n")
 107+ sys.exit(1)
 108+ except ldap.INVALID_DN_SYNTAX:
 109+ sys.stderr.write("The bind DN is incorrect... \n")
 110+ sys.exit(1)
 111+ except ldap.NO_SUCH_OBJECT:
 112+ sys.stderr.write("Unable to locate the bind DN account.\n")
 113+ sys.exit(1)
 114+ except ldap.UNWILLING_TO_PERFORM, msg:
 115+ sys.stderr.write("The LDAP server was unwilling to perform the action requested.\nError was: %s\n" % msg[0]["info"])
 116+ sys.exit(1)
 117+ except ldap.INVALID_CREDENTIALS:
 118+ sys.stderr.write("Password incorrect.\n")
 119+ #traceback.print_exc(file=sys.stderr)
 120+ sys.exit(1)
 121+
Property changes on: trunk/tools/subversion/user-management/ldapsupportlib.py
___________________________________________________________________
Added: svn:eol-style
1122 + native
Index: trunk/tools/subversion/user-management/delete-ldap-user
@@ -0,0 +1,68 @@
 2+#!/usr/bin/python
 3+import sys, pwd, traceback, getpass, ldapsupportlib, homedirectorymanager
 4+from optparse import OptionParser
 5+
 6+try:
 7+ import ldap
 8+ import ldap.modlist
 9+except ImportError:
 10+ sys.stderr.write("Unable to import LDAP library.\n")
 11+ sys.exit(1)
 12+
 13+def main():
 14+ parser = OptionParser(conflict_handler="resolve")
 15+ parser.set_usage('delete-ldap-user [options] <username>')
 16+
 17+ ldapSupportLib = ldapsupportlib.LDAPSupportLib()
 18+ ldapSupportLib.addParserOptions(parser, "scriptuser")
 19+
 20+ parser.add_option("-m", "--directorymanager", action="store_true", dest="directorymanager", help="Use the Directory Manager's credentials, rather than your own")
 21+ parser.add_option("--no-delete-home", action="store_true", dest="nodeletehome", help="Don't delete the user's home directory")
 22+ (options, args) = parser.parse_args()
 23+
 24+ if len(args) != 1:
 25+ parser.error("add-ldap-user expects exactly one argument.")
 26+
 27+ ldapSupportLib.setBindInfoByOptions(options, parser)
 28+
 29+ base = ldapSupportLib.getBase()
 30+
 31+ ds = ldapSupportLib.connect()
 32+
 33+ # w00t We're in!
 34+ try:
 35+ username = args[0]
 36+ dn = 'uid=' + username + ',ou=people,' + base
 37+ ds.delete_s(dn)
 38+
 39+ if not options.nodeletehome:
 40+ hdm = homedirectorymanager.HomeDirectoryManager()
 41+ hdm.deleteUser(username)
 42+ except ldap.UNWILLING_TO_PERFORM, msg:
 43+ sys.stderr.write("LDAP was unwilling to delete the user. Error was: %s\n" % msg[0]["info"])
 44+ ds.unbind()
 45+ sys.exit(1)
 46+ except ldap.NO_SUCH_OBJECT:
 47+ sys.stderr.write("The user you are trying to delete does not exists.\n")
 48+ ds.unbind()
 49+ sys.exit(1)
 50+ except ldap.PROTOCOL_ERROR:
 51+ sys.stderr.write("There was an LDAP protocol error; see traceback.\n")
 52+ traceback.print_exc(file=sys.stderr)
 53+ ds.unbind()
 54+ sys.exit(1)
 55+ except Exception:
 56+ try:
 57+ sys.stderr.write("There was a general error, this is unexpected; see traceback.\n")
 58+ traceback.print_exc(file=sys.stderr)
 59+ ds.unbind()
 60+ except Exception:
 61+ sys.stderr.write("Also failed to unbind.\n")
 62+ traceback.print_exc(file=sys.stderr)
 63+ sys.exit(1)
 64+
 65+ ds.unbind()
 66+ sys.exit(0)
 67+
 68+if __name__ == "__main__":
 69+ main()
Property changes on: trunk/tools/subversion/user-management/delete-ldap-user
___________________________________________________________________
Added: svn:eol-style
170 + native
Added: svn:executable
271 + *
Index: trunk/tools/subversion/user-management/ldaplist
@@ -0,0 +1,214 @@
 2+#!/usr/bin/python
 3+import sys, traceback, re, ldapsupportlib
 4+from optparse import OptionParser
 5+
 6+try:
 7+ import ldap
 8+except ImportError:
 9+ sys.stderr.write("Unable to import LDAP library.\n")
 10+ sys.exit(1)
 11+
 12+def main():
 13+ "An application that implements the functionality of Solaris's ldaplist."
 14+
 15+ parser = OptionParser(conflict_handler="resolve")
 16+ parser.set_usage("ldaplist [options] [database] [object-name]\n\nexample: ldaplist -l passwd ldap_user")
 17+
 18+ ldapSupportLib = ldapsupportlib.LDAPSupportLib()
 19+ ldapSupportLib.addParserOptions(parser)
 20+
 21+ parser.add_option("-v", "--verbose", action="store_true", dest="verbose", help="Show the database and search filter used for this search")
 22+ parser.add_option("-l", "--longlisting", action="store_true", dest="longlisting", help="List all the attributes for each entry matching the search criteria. By default, ldaplist lists only the Distiguished Name of the entries found.")
 23+ parser.add_option("-h", action="store_true", dest="helpme", help="Show available databases to search")
 24+ parser.add_option("-d", "--showdatabase", action="store_true", dest="showdatabase", help="Show the base dn being used for this database")
 25+ parser.add_option("-a", "--showattributes", dest="showattributes", help="Show the given attributes")
 26+ parser.add_option("-r", "--recursive", action="store_true", dest="recursive", help="Recurse netgroups")
 27+ parser.add_option("--like", action="store_true", dest="like", help="Search for objects that equal or sound like [object-name]")
 28+ (options, args) = parser.parse_args()
 29+
 30+ ldapSupportLib.setBindInfoByOptions(options, parser)
 31+
 32+ base = ldapSupportLib.getBase()
 33+
 34+ objectbasedns = {"base":base, "passwd":"ou=people,"+base, "group":"ou=group,"+base, "netgroup":"ou=netgroup,"+base, "hosts":"ou=hosts,"+base, "automount":base, "auto_*":"nisMapName=auto_AUTO,"+base, "uids":"ou=uids,"+base}
 35+ objectdefaulttypes = {"base":"none", "passwd":"uid", "group":"cn", "netgroup":"cn", "hosts":"cn", "automount":"nisMapName", "auto_*":"cn", "uids":"cn"}
 36+ objectobjectclasses = {"base":"none", "passwd":"posixaccount", "group":"posixgroup", "netgroup":"nisNetGroup", "hosts":"iphost", "automount":"nisMap", "auto_*":"nisObject", "uids":"inetOrgPerson"}
 37+
 38+ if options.showdatabase:
 39+ showdatabase(objectbasedns, args)
 40+ sys.exit()
 41+
 42+ if options.helpme:
 43+ print ""
 44+ print 'database'.ljust(17) + 'default type'.ljust(20) + 'objectclass'
 45+ print '============='.ljust(17) + '================='.ljust(20)+ '============='
 46+
 47+ for a, b, c in zip(objectbasedns.keys(), objectdefaulttypes.values(), objectobjectclasses.values()):
 48+ print '%s%s%s' % (a.ljust(17), b.ljust(20), c)
 49+ sys.exit()
 50+
 51+ if len(args) >= 1:
 52+ if args[0].find('auto_') != -1:
 53+ objectbasedns["auto_*"] = objectbasedns["auto_*"].replace("auto_AUTO", args[0])
 54+ searchkeysave = args[0]
 55+ args[0] = "auto_*"
 56+ if objectbasedns.has_key(args[0]):
 57+ database = args[0]
 58+ base = objectbasedns[args[0]]
 59+ objectclass = objectobjectclasses[args[0]]
 60+ attribute = objectdefaulttypes[args[0]]
 61+ if len(args) > 1:
 62+ searchlist = args
 63+ del searchlist[0]
 64+ first = True
 65+ for key in searchlist:
 66+ if first == True:
 67+ searchkey = key
 68+ first = False
 69+ else:
 70+ searchkey = searchkey + " " + key
 71+ #elif args[0] == "auto_*":
 72+ #searchkey = searchkeysave
 73+ else:
 74+ searchkey = "*"
 75+ else:
 76+ print 'The database you selected does not exist. Please use "ldaplist -h" to see available databases.'
 77+ sys.exit(1)
 78+ else:
 79+ database = "base"
 80+ objectclass = "*"
 81+ attribute = ""
 82+
 83+ ds = ldapSupportLib.connect()
 84+
 85+ # w00t We're in!
 86+ try:
 87+ if database == "uids":
 88+ options.like = True
 89+ if options.showattributes is not None:
 90+ options.showattributes = options.showattributes + " cn uid departmentNumber employeeType seeAlso"
 91+ else:
 92+ options.showattributes = "cn uid departmentNumber employeeType seeAlso"
 93+ options.longlisting = True
 94+ if options.like and searchkey != "*":
 95+ searchoperator = "~="
 96+ else:
 97+ searchoperator = "="
 98+ if attribute != "":
 99+ attrlist = []
 100+ if options.showattributes is not None:
 101+ attrlist = re.split(" ", options.showattributes)
 102+ if options.verbose:
 103+ if options.showattributes is None:
 104+ attributes = ""
 105+ else:
 106+ attributes = options.showattributes
 107+ print "+++ database=" + database
 108+ print "+++ filter=(&(objectclass=" + objectclass + ")(" + attribute + searchoperator + searchkey + ")) " + attributes
 109+ PosixData = ds.search_s(base,ldap.SCOPE_SUBTREE,"(&(objectclass=" + objectclass + ")(" + attribute + searchoperator + searchkey + "))",attrlist)
 110+ else:
 111+ if options.verbose:
 112+ print "(objectclass=" + objectclass + ")"
 113+ PosixData = ds.search_s(base,ldap.SCOPE_SUBTREE,"(objectclass=" + objectclass + ")")
 114+ except ldap.NO_SUCH_OBJECT:
 115+ sys.stderr.write("Object not found. If you are trying to use * in your search, make sure that you wrap your string in single quotes to avoid shell expansion.\n")
 116+ ds.unbind()
 117+ sys.exit(1)
 118+ except ldap.PROTOCOL_ERROR:
 119+ sys.stderr.write("The search returned a protocol error, this shouldn't ever happen, please submit a trouble ticket.\n")
 120+ ds.unbind()
 121+ sys.exit(1)
 122+ except Exception:
 123+ sys.stderr.write("The search returned an error.\n")
 124+ ds.unbind()
 125+ sys.exit(1)
 126+
 127+ PosixData.sort()
 128+ # /End of stolen stuff
 129+
 130+ # PosixData is a list of lists where:
 131+ # index 0 of PosixData[N]: contains the distinquished name
 132+ # index 1 of PosixData[N]: contains a dictionary of lists hashed by the following keys:
 133+ # telephoneNumber, departmentNumber, uid, objectClass, loginShell,
 134+ # uidNumber, gidNumber, sn, homeDirectory, givenName, cn
 135+
 136+ if options.recursive:
 137+ members_array = []
 138+ triples = []
 139+
 140+ # get the members and triples from the entry we are looking for
 141+ for i in range(len(PosixData)):
 142+ if 'memberNisNetgroup' in PosixData[i][1]:
 143+ members_array.extend(PosixData[i][1]['memberNisNetgroup'])
 144+ if 'nisNetgroupTriple' in PosixData[i][1]:
 145+ triples.extend(PosixData[i][1]['nisNetgroupTriple'])
 146+
 147+ # get triples from any sub-members
 148+ triples = recursenetgroups(base, ds, members_array, triples)
 149+
 150+ for str in triples:
 151+ print str
 152+
 153+ # clean up
 154+ ds.unbind()
 155+ sys.exit(0)
 156+
 157+ for i in range(len(PosixData)):
 158+ print ""
 159+ if not options.longlisting:
 160+ print "dn: " + PosixData[i][0]
 161+ else:
 162+ print "dn: " + PosixData[i][0]
 163+ for (k,v) in PosixData[i][1].items():
 164+ if len(v) > 1:
 165+ for v2 in v:
 166+ print " %s: %s" % (k,v2)
 167+ else:
 168+ print " %s: %s" % (k,v[0])
 169+
 170+ ds.unbind()
 171+
 172+def showdatabase(objectbasedns, args):
 173+ print ""
 174+ if len(args) < 1:
 175+ print objectbasedns["base"]
 176+ else:
 177+ if args[0].find('auto_') != -1:
 178+ objectbasedns["auto_*"] = objectbasedns["auto_*"].replace("auto_AUTO", args[0])
 179+ args[0] = "auto_*"
 180+ if objectbasedns.has_key(args[0]):
 181+ print objectbasedns[args[0]]
 182+ else:
 183+ print "Database " + args[0] + " not found, use ldaplist -h to list database types."
 184+
 185+def recursenetgroups(base, ds, members_array, triples, oldmembers=[]):
 186+ # Base case. This netgroup has no netgroup members.
 187+ if members_array == []:
 188+ return triples
 189+
 190+ # members_array is the total list of netgroup members from the previous search.
 191+ for member in members_array:
 192+ if member in oldmembers:
 193+ # ensure we don't follow infinite recursion loops
 194+ members_array.remove(member)
 195+ continue
 196+ else:
 197+ # add this member to the oldmembers list to avoid infinite recursion loops
 198+ oldmembers.extend(member)
 199+
 200+ # we need to remove the member to avoid infinite recursion
 201+ members_array.remove(member)
 202+
 203+ # get the triples and members for this member, and add them to the current members list
 204+ PosixData = ds.search_s(base,ldap.SCOPE_SUBTREE,"(&(objectclass=nisNetgroup)(cn=" + member + "))")
 205+ for data in PosixData:
 206+ if 'nisNetgroupTriple' in data[1]:
 207+ triples.extend(data[1]['nisNetgroupTriple'])
 208+ if 'memberNisNetgroup' in data[1]:
 209+ members_array.extend(data[1]['memberNisNetgroup'])
 210+
 211+ # Recurse iteratively (tail recursion)
 212+ return recursenetgroups(base, ds, members_array, triples, oldmembers)
 213+
 214+if __name__ == "__main__":
 215+ main()
Property changes on: trunk/tools/subversion/user-management/ldaplist
___________________________________________________________________
Added: svn:eol-style
1216 + native
Added: svn:executable
2217 + *

Status & tagging log