def ldap_query_check(): # Run a simple known query and verify that ldap returns something ldapConn = ldapsupportlib.LDAPSupportLib().connect() query = '(cn=testlabs)' base = 'ou=projects,dc=wikimedia,dc=org' result = ldapConn.search_s(base, ldap.SCOPE_SUBTREE, query) if len(result) > 0: return True return False
def main(): parser = OptionParser(conflict_handler="resolve") parser.set_usage("puppetsigner [options]") ldapSupportLib = ldapsupportlib.LDAPSupportLib() ldapSupportLib.addParserOptions(parser) (options, args) = parser.parse_args() ldapSupportLib.setBindInfoByOptions(options, parser) ds = ldapSupportLib.connect() try: proc = subprocess.Popen('/usr/sbin/puppetca -l', shell=True, stdout=subprocess.PIPE) hosts = proc.communicate() hosts = hosts[0].split() for host in hosts: basedn = getPuppetInfo('ldapbase') query = "(&(objectclass=puppetclient)(|(dc=" + host + ")(cnamerecord=" + host + ")(associateddomain=" + host + ")))" PosixData = ds.search_s(basedn, ldap.SCOPE_SUBTREE, query) if not PosixData: path = getPuppetInfo( 'ssldir') + '/ca/requests/' + host + '.pem' try: os.remove(path) except Exception: sys.stderr.write('Failed to remove the certificate: ' + path + '\n') else: subprocess.Popen(['/usr/sbin/puppetca -s ' + host], shell=True, stderr=subprocess.PIPE) except ldap.PROTOCOL_ERROR: sys.stderr.write("There was an LDAP protocol error; see traceback.\n") traceback.print_exc(file=sys.stderr) ds.unbind() sys.exit(1) except Exception: try: sys.stderr.write( "There was a general error, this is unexpected; see traceback.\n" ) traceback.print_exc(file=sys.stderr) ds.unbind() except Exception: sys.stderr.write("Also failed to unbind.\n") traceback.print_exc(file=sys.stderr) sys.exit(1) ds.unbind() sys.exit(0)
def main(): """main script entry""" ldap_support_lib = ldapsupportlib.LDAPSupportLib() parser = OptionParser(conflict_handler="resolve") parser.set_usage( 'modify-mfa [--enable/--disable] <username>\nexample: modify-mfa --enable jbond' ) parser.add_option('--enable', action='store_true', help='enable mfa') parser.add_option('--disable', action='store_true', help='disable mfa') parser.add_option('--method', default='mfa-u2f', choices=['mfa-u2f'], help='the MFA type, currently only mfa-u2f is supported') ldap_support_lib.addParserOptions(parser, "scriptuser") (options, args) = parser.parse_args() if len(args) != 1: parser.error("must pass a username") username = args[0] if options.enable and options.disable: parser.error("options --enable and --disable are mutually exclusive") if not options.enable and not options.disable: parser.error("one of --enable or --disable must be specified") enable = options.enable if options.enable else False ldap_support_lib.setBindInfoByOptions(options, parser) ldap_user = LdapUser(username, ldap_support_lib) try: ldap_user.update_mfa(enable, options.method) except LdapUserNotFound: print('user ({}): Not Found'.format(username), file=sys.stderr) return 1 return 0
def main(): "An application that implements the functionality of Solaris's ldaplist." print '\033[91m' print 'If you are still relying on ldaplist and not using ldapsearch,' print 'please comment on https://phabricator.wikimedia.org/T114063' print 'before 30 August 2016. If nobody comments, ldaplist will be removed!' print '\033[0m' parser = OptionParser(conflict_handler="resolve") parser.set_usage( "ldaplist [options] [database] [object-name]\n\nexample: ldaplist -l passwd ldap_user" ) ldap_support_lib = ldapsupportlib.LDAPSupportLib() ldap_support_lib.addParserOptions(parser) parser.add_option( "-v", "--verbose", action="store_true", dest="verbose", help="Show the database and search filter used for this search") 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 Distinguished', ' Name of the entries found.')) parser.add_option("-h", action="store_true", dest="helpme", help="Show available databases to search") parser.add_option("-d", "--showdatabase", action="store_true", dest="showdatabase", help="Show the base dn being used for this database") parser.add_option("-a", "--showattributes", dest="showattributes", help="Show the given attributes") parser.add_option("-r", "--recursive", action="store_true", dest="recursive", help="Recurse netgroups") parser.add_option( "--like", action="store_true", dest="like", help="Search for objects that equal or sound like [object-name]") (options, args) = parser.parse_args() ldap_support_lib.setBindInfoByOptions(options, parser) base = ldap_support_lib.getBase() objectbasedns = { "base": base, "passwd": "ou=people," + base, "group": "ou=groups," + base, "netgroup": "ou=netgroup," + base, "automount": base, "auto_*": "nisMapName=auto_AUTO," + base, "uids": "ou=uids," + base, "servicegroups": "ou=servicegroups," + base, "projects": "ou=projects," + base, "projectroles": "ou=projects," + base } objectdefaulttypes = { "base": "none", "passwd": "uid", "group": "cn", "netgroup": "cn", "automount": "nisMapName", "auto_*": "cn", "uids": "cn", "servicegroups": "cn", "projects": "cn", "projectroles": "cn:dn:" } objectobjectclasses = { "base": "none", "passwd": "posixaccount", "group": "posixgroup", "netgroup": "nisNetGroup", "automount": "nisMap", "auto_*": "nisObject", "uids": "inetOrgPerson", "servicegroups": "posixgroup", "projects": "groupofnames", "projectroles": "organizationalrole" } if options.showdatabase: showdatabase(objectbasedns, args) sys.exit() if options.helpme: print "" print 'database'.ljust(17) + 'default type'.ljust(20) + 'objectclass' print '============='.ljust(17) + '================='.ljust( 20) + '=============' for a, b, c in zip(objectbasedns.keys(), objectdefaulttypes.values(), objectobjectclasses.values()): print '%s%s%s' % (a.ljust(17), b.ljust(20), c) sys.exit() if len(args) >= 1: if args[0].find('auto_') != -1: objectbasedns["auto_*"] = objectbasedns["auto_*"].replace( "auto_AUTO", args[0]) # searchkeysave = args[0] args[0] = "auto_*" if args[0] in objectbasedns: database = args[0] base = objectbasedns[args[0]] objectclass = objectobjectclasses[args[0]] attribute = objectdefaulttypes[args[0]] if len(args) > 1: searchlist = args del searchlist[0] first = True for key in searchlist: if first is True: searchkey = key first = False else: searchkey = searchkey + " " + key # elif args[0] == "auto_*": # searchkey = searchkeysave else: searchkey = "*" else: print('The database you selected does not exist. Please use ', '"ldaplist -h" to see available databases.') sys.exit(1) else: database = "base" objectclass = "*" attribute = "" ds = ldap_support_lib.connect() # w00t We're in! try: if database == "uids": options.like = True if options.showattributes is not None: options.showattributes += " cn uid departmentNumber employeeType seeAlso" else: options.showattributes = "cn uid departmentNumber employeeType seeAlso" options.longlisting = True if options.like and searchkey != "*": searchoperator = "~=" else: searchoperator = "=" if attribute != "": attrlist = [] if options.showattributes is not None: attrlist = re.split(" ", options.showattributes) if options.verbose: if options.showattributes is None: attributes = "" else: attributes = options.showattributes search_str = '(&(objectclass={objectclass})({search})) {attributes}'.format( objectclass, attribute + searchoperator + searchkey, attributes) print "+++ database=" + database print "+++ filter=" + search_str posix_data = ds.search_s(base, ldap.SCOPE_SUBTREE, search_str, attrlist) else: if options.verbose: print "(objectclass=" + objectclass + ")" posix_data = ds.search_s(base, ldap.SCOPE_SUBTREE, "(objectclass=" + objectclass + ")") except ldap.NO_SUCH_OBJECT: 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") ds.unbind() sys.exit(1) except ldap.PROTOCOL_ERROR: sys.stderr.write( "The search returned a protocol error, this shouldn't ever happen, ", "please submit a trouble ticket.\n") ds.unbind() sys.exit(1) except Exception: sys.stderr.write("The search returned an error.\n") ds.unbind() sys.exit(1) posix_data.sort() # /End of stolen stuff # posix_data is a list of lists where: # index 0 of posix_data[N]: contains the distinquished name # index 1 of posix_data[N]: contains a dictionary of lists hashed by the following keys: # telephoneNumber, departmentNumber, uid, objectClass, loginShell, # uidNumber, gidNumber, sn, homeDirectory, givenName, cn if options.recursive: members_array = [] triples = [] # get the members and triples from the entry we are looking for for i in range(len(posix_data)): if 'memberNisNetgroup' in posix_data[i][1]: members_array.extend(posix_data[i][1]['memberNisNetgroup']) if 'nisNetgroupTriple' in posix_data[i][1]: triples.extend(posix_data[i][1]['nisNetgroupTriple']) # get triples from any sub-members triples = recursenetgroups(base, ds, members_array, triples) for str in triples: print str # clean up ds.unbind() sys.exit(0) for i in range(len(posix_data)): print "" if not options.longlisting: print "dn: " + posix_data[i][0] else: print "dn: " + posix_data[i][0] for (k, v) in posix_data[i][1].items(): if len(v) > 1: for v2 in v: print "\t%s: %s" % (k, v2) else: print "\t%s: %s" % (k, v[0]) ds.unbind()
return int(value) return value if __name__ == '__main__': with open('/etc/wmflabs-project') as f: path = os.path.join('/var/lib/git/operations/puppet/nodes/labs/', f.read().strip() + '.yaml') if os.path.exists(path): with open(path) as f: rolesrules = YAMLRolesRules(yaml.load(f)) else: rolesrules = EmptyRolesRules() ldapConn = ldapsupportlib.LDAPSupportLib().connect() ec2id_name = sys.argv[1] # check to make sure ec2id_name is an actual ec2id based hostname, to prevent # ldap injection attacks if not re.match(r'^[a-zA-Z0-9_-]+\.eqiad\.wmflabs$', ec2id_name): print 'Invalid hostname', ec2id_name sys.exit(-1) query = 'dc=%s' % (ec2id_name) base = 'ou=hosts,dc=wikimedia,dc=org' result = ldapConn.search_s(base, ldap.SCOPE_SUBTREE, query) if result: host_info = result[0][1] roles = host_info['puppetClass'] puppetvars = {
def connect(self): self.ldapConn = ldapsupportlib.LDAPSupportLib().connect()
def run(self): parser = OptionParser(conflict_handler="resolve") parser.set_usage( "homedirectorymanager.py [options]\n\nexample: homedirectorymanager.py --dry-run" ) ldapSupportLib = ldapsupportlib.LDAPSupportLib() ldapSupportLib.addParserOptions(parser) parser.add_option( "--dry-run", action="store_true", dest="dryRun", help="Show what would be done, but don't actually do anything") parser.add_option( "--basedir", dest="basedir", help="Base directory to manage home directories (default: /home)") parser.add_option( "--group", dest="group", help= "Only manage home directories for users in the provided group (default: manage all users)" ) parser.add_option( "--loglevel", dest="loglevel", help="Change level of logging; NONE, INFO, DEBUG (default: INFO)") parser.add_option("--logfile", dest="logfile", help="Log file to write to (default: stdout)") (self.options, args) = parser.parse_args() self.dryRun = self.options.dryRun if self.options.basedir: self.basedir = self.options.basedir if self.options.group: self.group = self.options.group if self.options.logfile: self.logfile = self.options.logfile if self.options.loglevel: self.setLogLevel(self.options.loglevel) # use proxy agent by default ldapSupportLib.setBindInfoByOptions(self.options, parser) base = ldapSupportLib.getBase() ds = ldapSupportLib.connect() self.logDebug("Connected") # w00t We're in! try: # get all user's uids if self.UsersData: UsersData = self.UsersData else: UsersData = ldapSupportLib.getUsers(ds, '*') self.logDebug("Pulled the user information") if self.group: if self.GroupData: GroupData = self.GroupData else: GroupData = ds.search_s( "ou=groups," + base, ldap.SCOPE_SUBTREE, "(&(objectclass=posixGroup)(cn=" + self.group + "))") GroupData = GroupData[0] try: groupdns = GroupData[1]['member'] except KeyError: groupdns = [] # We are going to use a dictionary (associative array) as a hash bucket (keys pointing to dictionaries) # for the AllUsers data structure. # The data structure will look like this: # {"<uid>": {"uidNumber": <uidNumber>, "gidNumber": <gidNumber>, "sshPublicKey": ['key1', 'key2']}, # "<uid>": {"uidNumber": <uidNumber>, "gidNumber": <gidNumber>, "sshPublicKey": ['key1', 'key2']}} AllUsers = {} for user in UsersData: if self.group: dn = user[0] if dn not in groupdns: continue uid = user[1]['uid'][0] # uidNumber and gidNumber come back from LDAP as strings, we need ints here. uidNumber = int(user[1]['uidNumber'][0]) gidNumber = int(user[1]['gidNumber'][0]) # Not all users have an sshkey, if not continue if 'sshPublicKey' not in user[1]: continue sshPublicKey = user[1]['sshPublicKey'] try: modifyTimestamp = user[1]['modifyTimestamp'] except KeyError: self.logDebug("No modifyTimestamp for %s" % uid) continue AllUsers[uid] = {} AllUsers[uid]["uidNumber"] = uidNumber AllUsers[uid]["gidNumber"] = gidNumber AllUsers[uid]["sshPublicKey"] = sshPublicKey AllUsers[uid]["modifyTimestamp"] = modifyTimestamp[0] #self.changeGid(AllUsers) #self.changeUid(AllUsers) #self.moveUsers(AllUsers) self.updateKeys(AllUsers) self.createHomeDir(AllUsers) except ldap.UNWILLING_TO_PERFORM, msg: sys.stderr.write("The search returned an error. Error was: %s\n" % msg[0]["info"]) ds.unbind() return 1
def main(): parser = OptionParser(conflict_handler="resolve") parser.set_usage( 'add-ldap-group [options] <groupname>\nexample: add-ldap-group wikidev' ) ldap_support_lib = ldapsupportlib.LDAPSupportLib() ldap_support_lib.addParserOptions(parser, "scriptuser") parser.add_option( "-m", "--directorymanager", action="store_true", dest="directorymanager", help="Use the Directory Manager's credentials, rather than your own") parser.add_option("--gid", action="store", dest="gid_number", help="The group's gid (default: next available gid)") parser.add_option( "--members", action="store", dest="members", help="A comma separated list of group members to add to this group") (options, args) = parser.parse_args() if len(args) != 1: parser.error("add-ldap-group expects exactly one argument.") ldap_support_lib.setBindInfoByOptions(options, parser) base = ldap_support_lib.getBase() ds = ldap_support_lib.connect() # w00t We're in! try: groupname = args[0] dn = 'cn=' + groupname + ',ou=groups,' + base cn = groupname object_classes = ['posixGroup', 'groupOfNames', 'top'] if options.gid_number: try: grp.getgrgid(options.gid_number) raise ldap.TYPE_OR_VALUE_EXISTS() except KeyError: gid_number = options.gid_number else: # Find the next gid # TODO: make this use LDAP calls instead of getent gids = [] for group in grp.getgrall(): tmpgid = group[2] if tmpgid < 50000: gids.append(group[2]) gids.sort() gid_number = gids.pop() gid_number = str(gid_number + 1) members = [] if options.members: raw_members = options.members.split(',') for raw_member in raw_members: try: # Ensure the user exists # TODO: make this use LDAP calls instead of getent pwd.getpwnam(raw_member) # member expects DNs members.append('uid=' + raw_member + ',ou=people,' + base) except KeyError: sys.stderr.write( raw_member + " doesn't exist, and won't be added to the group.\n") group_entry = {} group_entry['objectclass'] = object_classes group_entry['gidNumber'] = gid_number group_entry['cn'] = cn if members: group_entry['member'] = members modlist = ldap.modlist.addModlist(group_entry) ds.add_s(dn, modlist) except ldap.UNWILLING_TO_PERFORM as msg: sys.stderr.write( "LDAP was unwilling to create the group. Error was: %s\n" % msg[0]["info"]) ds.unbind() sys.exit(1) except ldap.TYPE_OR_VALUE_EXISTS: sys.stderr.write( "The group or gid you are trying to add already exists.\n") traceback.print_exc(file=sys.stderr) ds.unbind() sys.exit(1) except ldap.PROTOCOL_ERROR: sys.stderr.write("There was an LDAP protocol error; see traceback.\n") traceback.print_exc(file=sys.stderr) ds.unbind() sys.exit(1) except Exception: try: sys.stderr.write( "There was a general error, this is unexpected; see traceback.\n" ) traceback.print_exc(file=sys.stderr) ds.unbind() except Exception: sys.stderr.write("Also failed to unbind.\n") traceback.print_exc(file=sys.stderr) sys.exit(1) ds.unbind() sys.exit(0)
def main(): parser = OptionParser(conflict_handler="resolve") parser.set_usage("puppetsigner [options]") ldapSupportLib = ldapsupportlib.LDAPSupportLib() ldapSupportLib.addParserOptions(parser) (options, args) = parser.parse_args() ldapSupportLib.setBindInfoByOptions(options, parser) ds = ldapSupportLib.connect() try: proc = subprocess.Popen('/usr/sbin/puppetca -l', shell=True, stdout=subprocess.PIPE) hosts = proc.communicate() hosts = hosts[0].split() for host in hosts: if host[0] == "(": continue host = host.strip('"') basedn = getPuppetInfo('ldapbase') query = "(&(objectclass=puppetclient)(|(dc=" + host + ")(cnamerecord=" + host + ")(associateddomain=" + host + ")))" PosixData = ds.search_s(basedn, ldap.SCOPE_SUBTREE, query) if not PosixData: path = getPuppetInfo( 'ssldir') + '/ca/requests/' + host + '.pem' try: os.remove(path) except Exception: sys.stderr.write('Failed to remove the certificate: ' + path + '\n') else: subprocess.Popen(['/usr/sbin/puppetca -s ' + host], shell=True, stderr=subprocess.PIPE) subprocess.Popen([ '/usr/bin/php /srv/org/wikimedia/controller/wikis/w/extensions/OpenStackManager/maintenance/onInstanceActionCompletion.php --action=build --instance=' + host ], shell=True, stderr=subprocess.PIPE) proc = subprocess.Popen( '/usr/bin/salt-key --list=unaccepted --out=json', shell=True, stdout=subprocess.PIPE) hosts = proc.communicate() hosts = json.loads(hosts[0]) for host in hosts["minions_pre"]: basedn = getPuppetInfo('ldapbase') query = "(&(objectclass=puppetclient)(|(dc=" + host + ")(cnamerecord=" + host + ")(associateddomain=" + host + ")))" PosixData = ds.search_s(basedn, ldap.SCOPE_SUBTREE, query) if not PosixData: subprocess.Popen(['/usr/bin/salt-key -y -d ' + host], shell=True, stdout=subprocess.PIPE) else: subprocess.Popen(['/usr/bin/salt-key -a ' + host], shell=True, stderr=subprocess.PIPE) except ldap.PROTOCOL_ERROR: sys.stderr.write("There was an LDAP protocol error; see traceback.\n") traceback.print_exc(file=sys.stderr) ds.unbind() sys.exit(1) except Exception: try: sys.stderr.write( "There was a general error, this is unexpected; see traceback.\n" ) traceback.print_exc(file=sys.stderr) ds.unbind() except Exception: sys.stderr.write("Also failed to unbind.\n") traceback.print_exc(file=sys.stderr) sys.exit(1) ds.unbind() sys.exit(0)
def run(self): parser = OptionParser(conflict_handler="resolve") parser.set_usage( "homedirectorymanager.py [options]\n\nexample: homedirectorymanager.py --dry-run" ) ldapSupportLib = ldapsupportlib.LDAPSupportLib() ldapSupportLib.addParserOptions(parser) parser.add_option( "--dry-run", action="store_true", dest="dryRun", help="Show what would be done, but don't actually do anything") parser.add_option( "--debug", action="store_true", dest="debugStatus", help= "Run in debug mode (you likely want to use --dry-run with this)") (self.options, args) = parser.parse_args() self.dryRun = self.options.dryRun self.debugStatus = self.options.debugStatus # use proxy agent by default ldapSupportLib.setBindInfoByOptions(self.options, parser) base = ldapSupportLib.getBase() ds = ldapSupportLib.connect() self.logDebug("Connected") # w00t We're in! try: # get all user's uids UsersData = ldapSupportLib.getUsers(ds, '*') self.logDebug("Pulled the user information") # We are going to use a dictionary (associative array) as a hash bucket (keys pointing to dictionaries) # for the AllUsers data structure. # The data structure will look like this: # {"<uid>": {"uidNumber": <uidNumber>, "gidNumber": <gidNumber>, "sshPublicKey": ['key1', 'key2']}, # "<uid>": {"uidNumber": <uidNumber>, "gidNumber": <gidNumber>, "sshPublicKey": ['key1', 'key2']}} AllUsers = {} for user in UsersData: uid = user[1]['uid'][0] if 'uidNumber' not in user[1].keys(): continue if 'gidNumber' not in user[1].keys(): continue if 'sshPublicKey' not in user[1].keys(): continue # uidNumber and gidNumber come back from LDAP as strings, we need ints here. uidNumber = int(user[1]['uidNumber'][0]) gidNumber = int(user[1]['gidNumber'][0]) sshPublicKey = user[1]['sshPublicKey'] AllUsers[uid] = {} AllUsers[uid]["uidNumber"] = uidNumber AllUsers[uid]["gidNumber"] = gidNumber AllUsers[uid]["sshPublicKey"] = sshPublicKey self.changeGid(AllUsers) self.changeUid(AllUsers) self.moveUsers(AllUsers) self.createHomeDir(AllUsers) except ldap.UNWILLING_TO_PERFORM, msg: sys.stderr.write("The search returned an error. Error was: %s\n" % msg[0]["info"]) ds.unbind() sys.exit(1)
import os import json import ldap from optparse import OptionParser # FIXME: Use argparse def getPuppetInfo(attr, conffile="/etc/puppet/puppet.conf"): f = open(conffile) for line in f: if line.split('=', 1)[0].strip() == attr: return line.split('=', 1)[1].strip() parser = OptionParser(conflict_handler="resolve") parser.set_usage("puppetsigner [options]") ldapSupportLib = ldapsupportlib.LDAPSupportLib() ldapSupportLib.addParserOptions(parser) (options, args) = parser.parse_args() ldapSupportLib.setBindInfoByOptions(options, parser) ds = ldapSupportLib.connect() basedn = ldapSupportLib.getLdapInfo('base') try: puppet_output = subprocess.check_output(['/usr/bin/puppet', 'cert', 'list', '--all']) hosts = puppet_output.strip().split("\n") for host_string in hosts: host = host_string.split() # check to make sure hostname is actual hostname, to prevent # ldap injection attacks if host[0] == "(":