143 lines
3.7 KiB
Python
Executable file
143 lines
3.7 KiB
Python
Executable file
#!/usr/bin/python
|
|
"""
|
|
Tool to force update memberOf attributes of users on OpenLDAP directory using
|
|
memberOf overlay
|
|
"""
|
|
|
|
import getpass
|
|
import logging
|
|
|
|
from mylib.ldap import LdapClient
|
|
from mylib.ldap import LdapServer
|
|
from mylib.pbar import Pbar
|
|
from mylib.scripts.helpers import get_opts_parser
|
|
from mylib.scripts.helpers import init_logging
|
|
|
|
default_host = 'ldapi:///'
|
|
default_filter = '(objectClass=posixGroup)'
|
|
default_attr = 'uniqueMember'
|
|
|
|
parser = get_opts_parser(
|
|
desc="Update memberOf attributes", just_try=True, progress=True)
|
|
|
|
# options
|
|
ldap_opts = parser.add_argument_group('LDAP options')
|
|
|
|
ldap_opts.add_argument(
|
|
'-H', '--host',
|
|
action="store",
|
|
type=str,
|
|
dest="host",
|
|
help="LDAP server URI (default: %s)" % default_host,
|
|
default=default_host
|
|
)
|
|
ldap_opts.add_argument(
|
|
'-D', '--dn',
|
|
action="store",
|
|
type=str,
|
|
dest="dn",
|
|
help="LDAP bind DN",
|
|
default=None
|
|
)
|
|
ldap_opts.add_argument(
|
|
'-P', '--password',
|
|
action="store",
|
|
type=str,
|
|
dest="pwd",
|
|
help="LDAP bind password",
|
|
default=None
|
|
)
|
|
ldap_opts.add_argument(
|
|
'-f', '--filter',
|
|
action="store",
|
|
type=str,
|
|
dest="filter",
|
|
help="LDAP groups filter (default: %s)" % default_filter,
|
|
default=default_filter
|
|
)
|
|
ldap_opts.add_argument(
|
|
'-b', '--base',
|
|
action="store",
|
|
type=str,
|
|
dest="base",
|
|
help="LDAP group base DN",
|
|
default=None
|
|
)
|
|
ldap_opts.add_argument(
|
|
'--v2',
|
|
action="store_true",
|
|
dest="ldapv2",
|
|
help="Utiliser le protocole LDAP v2.",
|
|
default=None
|
|
)
|
|
ldap_opts.add_argument(
|
|
'-a', '--attr',
|
|
action="store",
|
|
type=str,
|
|
dest="attr",
|
|
help="Group members attribute (default: %s)" % default_attr,
|
|
default=default_attr
|
|
)
|
|
|
|
options = parser.parse_args()
|
|
|
|
if options.base is None:
|
|
parser.error('You must specify base DN using --base parameter')
|
|
|
|
init_logging(options, "Update memberOf")
|
|
|
|
if options.dn and not options.pwd:
|
|
options.pwd = getpass.getpass()
|
|
|
|
|
|
class MyLdapClient(LdapClient):
|
|
""" Implement a custom LdapClient to handle group objects """
|
|
|
|
# pylint: disable=super-init-not-called
|
|
def __init__(self, scripts_options):
|
|
self.options = scripts_options
|
|
logging.info(u"Connect to LDAP server %s", self.options.host)
|
|
self.cnx = LdapServer(
|
|
self.options.host, dn=self.options.dn, pwd=self.options.pwd,
|
|
v2=self.options.ldapv2)
|
|
self.cnx.connect()
|
|
|
|
def get_groups(self):
|
|
""" Retreive groups form LDAP server """
|
|
return self.get_objects(
|
|
'group',
|
|
self.options.filter,
|
|
self.options.base,
|
|
[self.options.attr]
|
|
)
|
|
|
|
def touch_group_members(self, obj):
|
|
""" Touch group members attribute """
|
|
current = self.get_attr(obj, self.options.attr, all_values=True)
|
|
if not current:
|
|
return True
|
|
|
|
logging.debug('Update - remove values of %s', obj['dn'])
|
|
changes = self.get_changes(obj, {options.attr: []})
|
|
logging.debug('Changes:\n%s', self.format_changes(changes))
|
|
if self.update_object(obj, changes):
|
|
obj[options.attr] = []
|
|
logging.debug('Update - restore values of %s', obj['dn'])
|
|
changes = self.get_changes(obj, {options.attr: current})
|
|
logging.debug('Changes:\n%s', self.format_changes(changes))
|
|
return myldap.update_object(obj, changes)
|
|
return False
|
|
|
|
|
|
# Start LDAP connection
|
|
myldap = MyLdapClient(options)
|
|
groups = myldap.get_groups()
|
|
|
|
logging.info('%s groups found', len(groups))
|
|
|
|
pbar = Pbar('Update memberOf', len(groups), enabled=options.progress)
|
|
for dn, group in groups.items():
|
|
myldap.touch_group_members(group)
|
|
pbar.increment()
|
|
|
|
pbar.finish()
|