def renew_user(self, uid, num_terms=None): "Renews the user 'uid' for the current term, or a number of terms." if num_terms is None: num_terms = 1 if num_terms > 3: debug('Warning: I can only renew a member for up to 3 terms at a ' 'time! I will renew for the maximum possible number.') term = 3 if num_terms < 1: error("Your number of terms doesn't make any sense! You said: %s" % num_terms) return terms = [] for num in range(num_terms): terms.append( get_term(datetime.date.today() + relativedelta(months=(num * 4)))) for term in terms: try: debug('Renewing user for term ' + term) verbose('dn: uid=%s,ou=People,%s' % (uid, BASE)) ml = [(ldap.MOD_ADD, 'term', term)] verbose('modlist: ' + str(ml)) self.ldap_wics.modify_s('uid=%s,ou=People,%s' % (uid, BASE), ml) except: print_exc(sys.exc_info()) error('Failed to renew user for term ' + term + '!')
def unlock(self, dn, newdn): ''' This helper performs an unlock using LDAP attributes. dn: the distinguished name of our mutex object newdn: new distinguished name object, e.g. "cn=newuid" ''' self.ldap_wics.modrdn_s(dn, newdn) debug('Unlocked database.')
def add_princ(self, uid, password=None): ''' Adds a Kerberos principal. uid: the user id for the principal password: (optional) a string consisting of the user's password; if no string is provided the user will be prompted to enter one ''' if password is None: password = get_user_password( 'Enter password for principal %s@%s: ' % (uid, REALM)) debug('Adding Kerberos principal...') self.krb_wics.addprinc('%s@%s' % (uid, REALM), password)
def lock(self, dn, newdn): ''' This helper performs a simple atomic test and set lock using LDAP attributes. dn: the distinguished name of our mutex object newdn: new distinguished name object, e.g. "cn=newuid" ''' debug('Locking LDAP database...') for x in range(NUM_TRIES): try: self.ldap_wics.modrdn_s(dn, newdn) return except: print_exc(sys.exc_info()) time.sleep(SLEEP_DUR) raise ldap.TIMEOUT('Could not obtain lock on ' + dn)
def remove_user_from_group(self, gid, uid): ''' Removes a user from an LDAP group. gid: the group to remove the user from uid: the user to remove from the group ''' try: debug('Removing user from group...') verbose('dn: cn=%s,ou=Group,%s' % (gid, BASE)) ml = [(ldap.MOD_DELETE, 'uniqueMember', 'uid=%s,ou=People,%s' % (uid, BASE))] verbose('modlist: ' + str(ml)) self.ldap_wics.modify_s('cn=%s,ou=Group,%s' % (gid, BASE), ml) except: print_exc(sys.exc_info()) error('Failed to remove user from group!')
def add_user_to_group(self, gid, uid): ''' Adds a user to an LDAP group. gid: the group to add the user to uid: the user to add to the group ''' try: debug('Adding user to group...') verbose('dn: cn=%s,ou=Group,%s' % (gid, BASE)) ml = [(ldap.MOD_ADD, 'uniqueMember', 'uid=%s,ou=People,%s' % (uid, BASE))] verbose('modlist: ' + str(ml)) self.ldap_wics.modify_s('cn=%s,ou=Group,%s' % (gid, BASE), ml) except: print_exc(sys.exc_info()) error('Failed to add user to group!')
def add_group(self, gid, desc): ''' Adds a group to the LDAP database. gid: the unique group id for our new group desc: a longer, descriptive name for the group ''' self.lock('cn=nextgid,ou=Group,' + BASE, 'cn=inuse') nextgid = self.ldap_wics.search_s('cn=inuse,ou=Group,' + BASE, ldap.SCOPE_BASE) nextgid = nextgid[0][1] next_gid = int(nextgid['gidNumber'][0]) attrs = { 'cn': gid, 'objectClass': ['group', 'posixGroup', 'top'], 'gidNumber': str(next_gid), 'description': desc, } try: self.ldap_wics.modify_s( 'cn=inuse,ou=Group,' + BASE, [(ldap.MOD_REPLACE, 'gidNumber', str(next_gid + 1))]) debug('Adding group...') verbose('dn: cn=%s,ou=Group,%s' % (gid, BASE)) ml = modlist.addModlist(attrs) verbose('modlist: ' + str(ml)) self.ldap_wics.add_s('cn=%s,ou=Group,%s' % (gid, BASE), ml) except: print_exc(sys.exc_info()) error('Failed to add group!') # Reset GID before unlocking self.ldap_wics.modify_s( 'cn=inuse,ou=Group,' + BASE, [(ldap.MOD_REPLACE, 'gidNumber', str(next_gid))]) finally: self.unlock('cn=inuse,ou=Group,' + BASE, 'cn=nextgid')
def add_user(self, uid, username): ''' Adds a user to the LDAP database. uid: the unique user id for our new user username: the user's full name ''' self.lock('uid=nextuid,ou=People,' + BASE, 'uid=inuse') nextuid = self.ldap_wics.search_s('uid=inuse,ou=People,' + BASE, ldap.SCOPE_BASE) nextuid_obj = nextuid[0][1] next_uid = int(nextuid_obj['uidNumber'][0]) next_gid = int(nextuid_obj['gidNumber'][0]) if next_uid != next_gid: # This isn't enforced at the schema level but close enough raise ldap.OBJECT_CLASS_VIOLATION( "UID and GID on nextuid are out of sync. Tell the sysadmin!") current_term = get_term() attrs_user = { # 'uid': uid, 'cn': username, 'objectClass': ['account', 'member', 'posixAccount', 'shadowAccount', 'top'], 'homeDirectory': '/home/' + uid, 'loginShell': '/bin/bash', 'uidNumber': str(next_uid), 'gidNumber': str(next_gid), 'term': current_term, # 'program': program, TODO: add query to uwldap for autocompletion # 'cn': name, } attrs_grp = { 'cn': uid, 'objectClass': ['group', 'posixGroup', 'top'], 'gidNumber': str(next_gid), } try: self.ldap_wics.modify_s( 'uid=inuse,ou=People,' + BASE, [(ldap.MOD_REPLACE, 'uidNumber', str(next_uid + 1)), (ldap.MOD_REPLACE, 'gidNumber', str(next_gid + 1))]) debug('Adding user...') verbose('dn: uid=%s,ou=People,%s' % (uid, BASE)) ml = modlist.addModlist(attrs_user) verbose('modlist: ' + str(ml)) self.ldap_wics.add_s('uid=%s,ou=People,%s' % (uid, BASE), ml) debug("Adding user's group...") verbose('dn: cn=%s,ou=Group,%s' % (uid, BASE)) ml = modlist.addModlist(attrs_grp) verbose('modlist: ' + str(ml)) self.ldap_wics.add_s('cn=%s,ou=Group,%s' % (uid, BASE), ml) except: print_exc(sys.exc_info()) error('Failed to add user!') # Reset UID/GID before unlocking self.ldap_wics.modify_s( 'uid=inuse,ou=People,' + BASE, [(ldap.MOD_REPLACE, 'uidNumber', str(next_uid)), (ldap.MOD_REPLACE, 'gidNumber', str(next_gid))]) finally: self.unlock('uid=inuse,ou=People,' + BASE, 'uid=nextuid')
def main(): 'CLI dispatch logic' def print_usage(): print ''' Usage: python weo.py [OPTIONS...] -h, --help Prints this help message -v Turns on verbose mode Standard commands ----------------- --renew Renews a user's account. Can optionally specify number of terms, up to three (i.e. --num-terms=2). Must specify --username --adduser Adds a user. Must also specify --username and --fullname --addgroup Adds a group. Must also specify --groupname and --groupdesc --add-user-to-group Adds a user to a group. Must also specify --groupname and --username --remove-user-from-group Removes a user from a group. Must also specify --groupname and --username Parameters: --username=[name] A user's id. Must be 3-8 lowercase ASCII characters. --fullname=["N. Ame"] A user's full name. Use quotes if it contains spaces. --groupname=[name] A group's id. Must be 3-10 lowercase ASCII characters. --groupdesc=["D Esc"] A group's description. Use quotes if it contains spaces. Advanced commands ----------------- LDAP Only: --add-ldap-user Adds a user to the LDAP database. Must also specify --username and --fullname --unlock-nextuid Unlocks the special nextuid user. --unlock-nextgid Unlocks the special nextgid group. Kerberos Only: --add-krb-princ Adds a Kerberos principal for a user. Must also specify --username ''' # getopt returns options and arguments, but we take no arguments (opts, _) = getopt.getopt( sys.argv[1:], 'hv', [ 'help', 'unlock-nextuid', 'unlock-nextgid', 'add-ldap-user', 'add-krb-princ', 'adduser', 'addgroup', 'add-user-to-group', 'remove-user-from-group', 'renew', 'username='******'fullname=', 'groupname=', 'groupdesc=', 'num-terms=', ]) opts = dict(opts) if '-v' in opts: weo.log.VERBOSE = True verbose('opts: ' + str(opts)) if not opts or '--help' in opts or '-h' in opts: print_usage() sys.exit(0) if '--add-ldap-user' in opts: if opts.get('--username') and opts.get('--fullname'): username = check_username(opts['--username']) debug('Okay, adding user %s' % username) l = wics_ldap() l.add_user(username, opts['--fullname']) exit_with_msg( 'Failed to add user %s :(' % username, 'User %s successfully added.' % username) if '--add-krb-princ' in opts: if opts.get('--username'): username = check_username(opts['--username']) debug('Okay, adding Kerberos principal %s@%s' % (username, REALM)) k = wics_krb5() k.add_princ(username) exit_with_msg( 'Failed to add Kerberos principal %s@%s :(' % (username, REALM), 'Principal %s@%s successfully added.' % (username, REALM)) if '--adduser' in opts: if opts.get('--username') and opts.get('--fullname'): username = check_username(opts['--username']) debug('Okay, adding user %s' % username) # Throws an exception before opening LDAP/KRB connections # if passwords don't match password = get_user_password( "Please enter the new user's password: ") l = wics_ldap() k = wics_krb5() l.add_user(username, opts['--fullname']) k.add_princ(username, password=password) exit_with_msg( 'Failed to add user %s :(' % username, 'User %s successfully added.' % username) if '--addgroup' in opts: if opts.get('--groupname') and opts.get('--groupdesc'): groupname = check_username(opts['--groupname'], maxlen=10) debug('Okay, adding group %s' % groupname) l = wics_ldap() l.add_group(groupname, opts['--groupdesc']) exit_with_msg( 'Failed to add group %s :(' % groupname, 'Group %s successfully added.' % groupname) if '--add-user-to-group' in opts: if opts.get('--username') and opts.get('--groupname'): username = opts['--username'] groupname = opts['--groupname'] debug('Okay, adding user %s to group %s' % (username, groupname)) l = wics_ldap() l.add_user_to_group(groupname, username) exit_with_msg( 'Failed to add user %s to group %s :(' % (username, groupname), 'User %s successfully added to group %s' % (username, groupname)) if '--remove-user-from-group' in opts: if opts.get('--username') and opts.get('--groupname'): username = opts['--username'] groupname = opts['--groupname'] debug('Okay, removing user %s from group %s' % (username, groupname)) l = wics_ldap() l.remove_user_from_group(groupname, username) exit_with_msg( 'Failed to remove user %s from group %s :(' % (username, groupname), 'User %s successfully removed from group %s' % (username, groupname)) if '--renew' in opts: if opts.get('--username'): username = opts['--username'] num_terms = opts.get('--num-terms') l = wics_ldap() if num_terms is not None: debug('Okay, renewing user %s for %s terms' % (username, num_terms)) l.renew_user(username, num_terms=int(num_terms)) else: debug('Okay, renewing user %s' % username) l.renew_user(username) exit_with_msg( 'Failed to renew user %s for specified terms :(' % username, 'User %s successfully renewed!' % username) if '--unlock-nextuid' in opts: l = wics_ldap() l.unlock('uid=inuse,ou=People,' + BASE, 'uid=nextuid') sys.exit(0) if '--unlock-nextgid' in opts: l = wics_ldap() l.unlock('cn=inuse,ou=Group,' + BASE, 'cn=nextgid') sys.exit(0)