Yuvipanda has uploaded a new change for review.
https://gerrit.wikimedia.org/r/301058
Change subject: WIP replacement of modify-ldap-groups
......................................................................
WIP replacement of modify-ldap-groups
Change-Id: Ibc9e5bf28826804e90b9ae143bcdd4cf0020b11d
---
M modules/ldap/files/scripts/modify-ldap-group
1 file changed, 91 insertions(+), 132 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/operations/puppet
refs/changes/58/301058/1
diff --git a/modules/ldap/files/scripts/modify-ldap-group
b/modules/ldap/files/scripts/modify-ldap-group
index 6c7978d..9dd3c22 100755
--- a/modules/ldap/files/scripts/modify-ldap-group
+++ b/modules/ldap/files/scripts/modify-ldap-group
@@ -1,143 +1,102 @@
-#!/usr/bin/python
-
-#####################################################################
-### THIS FILE IS MANAGED BY PUPPET
-### puppet:///modules/ldap/scripts/modify-ldap-group
-#####################################################################
-
-import sys
-import grp
-import traceback
-import ldapsupportlib
-import copy
-from optparse import OptionParser
-
-try:
- import ldap
- import ldap.modlist
-except ImportError:
- sys.stderr.write("Unable to import LDAP library.\n")
- sys.exit(1)
+#!/usr/bin/python3
+"""
+Add / Remove users from LDAP group
+"""
+import ldap3
+import yaml
+import argparse
-def main():
- parser = OptionParser(conflict_handler="resolve")
- parser.set_usage('modify-ldap-group [options] <groupname> [--rename
<newusergroup>]\nexample: modify-ldap-group --gid=501 wikidev')
+def get_members_list(conn, basedn, group, user):
+ """
+ Get list of members of the given group
+ """
+ conn.search(
+ 'ou=groups,{base}'.format(base=basedn),
+ '(cn={group})'.format(group=group),
+ ldap3.SEARCH_SCOPE_WHOLE_SUBTREE,
+ attributes=['member']
+ )
+ return conn.response[0]['attributes']['member']
- ldapSupportLib = ldapsupportlib.LDAPSupportLib()
- ldapSupportLib.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="gidNumber", help="Set the
group's gid")
- parser.add_option("--rename", action="store_true", dest="rename",
help="Rename the user")
- parser.add_option("--addmembers", action="store", dest="addMembers",
help="Add a comma separated list of users to this group")
- parser.add_option("--deletemembers", action="store", dest="deleteMembers",
help="Delete a comma separated list of users from this")
- (options, args) = parser.parse_args()
+def add_member(conn, basedn, group, user):
+ """
+ Adds user to group as a mmeber
+ """
+ userdn = 'uid={user},ou=people,{base}'.format(
+ user=user,
+ base=basedn,
+ )
+ groupdn = 'cn={group},ou=groups,{base}'.format(
+ group=group,
+ base=basedn,
+ )
+ members = get_members_list(conn, basedn, group, user)
+ if userdn in members:
+ raise Exception("User already is member of given group")
+ members.append(userdn)
+ op = {
+ 'member': [(ldap3.MODIFY_REPLACE, [members])]
+ }
+ return conn.modify(groupdn, op).result
- if len(args) != 1:
- if options.rename and len(args) != 2:
- parser.error("modify-ldap-group expects exactly two arguments when
using rename.")
- elif not options.rename:
- parser.error("modify-ldap-group expects exactly one argument,
unless using --rename.")
- ldapSupportLib.setBindInfoByOptions(options, parser)
+def remove_member(conn, basedn, group, user):
+ """
+ Remove user from group as a member
+ """
+ userdn = 'uid={user},ou=people,{base}'.format(
+ user=user,
+ base=basedn,
+ )
+ groupdn = 'cn={group},ou=groups,{base}'.format(
+ group=group,
+ base=basedn,
+ )
+ members = get_members_list(conn, basedn, group, user)
+ if userdn not in members:
+ raise Exception("User already is not a member of given group")
+ members.remove(userdn)
+ op = {
+ 'member': [(ldap3.MODIFY_REPLACE, [members])]
+ }
+ return conn.modify(groupdn, op).result
- base = ldapSupportLib.getBase()
- ds = ldapSupportLib.connect()
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ 'action',
+ help='Action to perform',
+ choices=['adduser', 'removeuser'],
+ )
+ parser.add_argument(
+ 'group',
+ help='Name of group to modify',
+ )
+ parser.add_argument(
+ 'user',
+ help='Name of user to add/remove'
+ )
+ parser.add_argument(
+ '--ldapconfig',
+ help='Path to LDAP connection config in YAML format',
+ default='/etc/ldap.scriptuser.yaml',
+ )
- # w00t We're in!
- try:
- groupname = args[0]
- PosixData = ds.search_s("ou=groups," + base, ldap.SCOPE_SUBTREE,
"(&(objectclass=posixGroup)(cn=" + groupname + "))")
- if not PosixData:
- raise ldap.NO_SUCH_OBJECT()
- dn = PosixData[0][0]
+ args = parser.parse_args()
- if options.rename:
- newgroupname = args[1]
+ with open(args.ldapconfig, encoding='utf-8') as f:
+ ldapconfig = yaml.safe_load(f)
- # Rename the entry
- newrdn = 'cn=' + newgroupname
- ds.rename_s(dn, newrdn)
- else:
- PosixData = PosixData[0][1]
- NewPosixData = copy.deepcopy(PosixData)
- if options.gidNumber:
- try:
- groupcheck = grp.getgrgid(options.gidNumber)
- raise ldap.TYPE_OR_VALUE_EXISTS()
- except KeyError:
- NewPosixData['gidNumber'] = options.gidNumber
- if options.addMembers:
- raw_members = options.addMembers.split(',')
- for raw_member in raw_members:
- try:
- user=ds.search_s("ou=people," + base,
ldap.SCOPE_SUBTREE, "uid=%s" % raw_member, ("dn",))
- if len(user) == 0:
- sys.stderr.write(raw_member + " doesn't exist, and
won't be added to the group.\n")
- return
- if len(user) > 1:
- sys.stderr.write(raw_member + " exist multiple
times, this is so wrong, abandon all hope\n")
- return
- except Exception as e:
- sys.stderr.write("Failed to search user in LDAP.
Error: %s\n" % str(e))
- raise e
- membertoadd = user[0][0]
- # member expects DNs
- if 'member' in NewPosixData.keys():
- if membertoadd in NewPosixData['member']:
- sys.stderr.write(raw_member + " is already a
member of the group, skipping.\n")
- else:
- NewPosixData['member'].append(membertoadd)
- else:
- NewPosixData['member'] = [membertoadd]
- elif options.deleteMembers:
- raw_members = options.deleteMembers.split(',')
- for raw_member in raw_members:
- membertoremove = 'uid=' + raw_member + ',ou=people,' + base
- if 'member' in NewPosixData.keys():
- if membertoremove in NewPosixData['member']:
- NewPosixData['member'].remove(membertoremove)
- else:
- sys.stderr.write(raw_member + " isn't a
member of the group, skipping.\n")
- else:
- sys.stderr.write("This group contains no
members.\n")
-
- if PosixData == NewPosixData:
- sys.stderr.write("No changes to make; exiting.\n")
- else:
- modlist = ldap.modlist.modifyModlist(PosixData, NewPosixData)
- ds.modify_s(dn, modlist)
- except ldap.UNWILLING_TO_PERFORM, msg:
- sys.stderr.write("LDAP was unwilling to modify the group. Error was:
%s\n" % msg[0]["info"])
- ds.unbind()
- sys.exit(1)
- except ldap.NO_SUCH_OBJECT:
- sys.stderr.write("The group you are trying to modify doesn't exist.\n")
- ds.unbind()
- sys.exit(1)
- except ldap.TYPE_OR_VALUE_EXISTS:
- sys.stderr.write("The gid given already exists.\n")
- 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)
-
-if __name__ == "__main__":
- main()
+ with ldap3.Connection([
+ ldap3.Server(s) for s in ldapconfig['servers']],
+ user=ldapconfig['user'],
+ auto_bind=True,
+ password=ldapconfig['password']
+ ) as conn:
+ if args.action == 'adduser':
+ print(add_member(conn, ldapconfig['basedn'], args.group,
args.user))
+ elif args.action == 'removeuser':
+ print(remove_member(conn, ldapconfig['basedn'], args.group,
args.user))
\ No newline at end of file
--
To view, visit https://gerrit.wikimedia.org/r/301058
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ibc9e5bf28826804e90b9ae143bcdd4cf0020b11d
Gerrit-PatchSet: 1
Gerrit-Project: operations/puppet
Gerrit-Branch: production
Gerrit-Owner: Yuvipanda <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits