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)
Exemple #3
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
Exemple #4
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()
Exemple #5
0
        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 = {
Exemple #6
0
 def connect(self):
     self.ldapConn = ldapsupportlib.LDAPSupportLib().connect()
Exemple #7
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(
            "--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
Exemple #8
0
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)
Exemple #9
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)
Exemple #10
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] == "(":