Ajout commande d'import LDIF
This commit is contained in:
parent
5f2e5058c4
commit
61bef2a4c7
|
@ -0,0 +1,135 @@
|
|||
#!/usr/bin/env python
|
||||
import os
|
||||
import hashlib
|
||||
import argparse
|
||||
import ldif
|
||||
import sys
|
||||
import ldap
|
||||
import ldap.sasl
|
||||
import ldap.dn
|
||||
import ldap.modlist
|
||||
import base64
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(description='Load LDIF files into and LDAP server.')
|
||||
parser.add_argument('ldifs', metavar='LDIF', nargs='+', help='files to parse')
|
||||
parser.add_argument('-H', dest='url', help='URL of the LDAP server')
|
||||
parser.add_argument('--quiet', dest='verbose', action='store_false', default=True, help='do not report all modifications')
|
||||
parser.add_argument('--fake', action='store_true', default=False, help='do not apply modifications, only simulate them')
|
||||
parser.add_argument('--merged-attribute', dest='merged_attribute', action='append',
|
||||
default=[], help='attribute that should be merged, not replaced (old values are merged with the new ones)')
|
||||
|
||||
|
||||
conn = ldap.initialize('ldapi://')
|
||||
conn.sasl_interactive_bind_s("", ldap.sasl.external())
|
||||
|
||||
def lower_keys(d):
|
||||
return dict((key.lower(), value) for key, value in d.iteritems())
|
||||
|
||||
def ssha_password(password):
|
||||
'''Hash a password using salted SHA1'''
|
||||
salt = os.urandom(4)
|
||||
h = hashlib.sha1(password)
|
||||
h.update(salt)
|
||||
return "{SSHA}" + base64.urlsafe_b64encode(h.digest() + salt)
|
||||
|
||||
class MyLDIFParser(ldif.LDIFParser):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.entries = []
|
||||
ldif.LDIFParser.__init__(self, *args, **kwargs)
|
||||
|
||||
def transform_entry(self, entry):
|
||||
# crypt passwords with SSHA
|
||||
for key in entry:
|
||||
if key.lower() == 'userpassword':
|
||||
hashed_passwords = []
|
||||
for value in entry['userPassword']:
|
||||
if not value.startswith('{'):
|
||||
value = ssha_password(value)
|
||||
hashed_passwords.append(value)
|
||||
entry[key] = hashed_passwords
|
||||
|
||||
def handle(self, dn, entry):
|
||||
self.transform_entry(entry)
|
||||
self.entries.append((dn, lower_keys(entry)))
|
||||
|
||||
args = parser.parse_args()
|
||||
args.merged_attribute = map(str.lower, args.merged_attribute)
|
||||
|
||||
# Array to store futures adds and modifies
|
||||
adds = []
|
||||
modifies = []
|
||||
|
||||
for ldif_path in args.ldifs:
|
||||
parser = MyLDIFParser(file(ldif_path))
|
||||
parser.parse()
|
||||
parser.entries.sort(key=lambda x: ldap.dn.str2dn(x[0])[::-1])
|
||||
|
||||
for dn, attrs in parser.entries:
|
||||
pass
|
||||
try:
|
||||
result = conn.search_s(dn, ldap.SCOPE_BASE)
|
||||
old_attrs = lower_keys(result[0][1])
|
||||
new_attrs = {}
|
||||
# keep attributes to merge that are unchanged
|
||||
for key in args.merged_attribute:
|
||||
if key not in attrs:
|
||||
new_attrs[key] = old_attrs[key]
|
||||
for key in attrs:
|
||||
# merge attributes with their old value
|
||||
if key in args.merged_attribute:
|
||||
new_attrs[key] = list(set(old_attrs[key])|set(attrs[key]))
|
||||
else:
|
||||
new_attrs[key] = attrs[key]
|
||||
modlist = []
|
||||
for key in old_attrs:
|
||||
if key not in new_attrs:
|
||||
modlist.append((ldap.MOD_DELETE, key, None))
|
||||
for key in new_attrs:
|
||||
if key in old_attrs:
|
||||
old = set(old_attrs[key])
|
||||
new = set(new_attrs[key])
|
||||
if old & new:
|
||||
if old-new:
|
||||
modlist.append((ldap.MOD_DELETE, key, list(old-new)))
|
||||
if new-old:
|
||||
modlist.append((ldap.MOD_ADD, key, list(new-old)))
|
||||
else:
|
||||
modlist.append((ldap.MOD_REPLACE, key, list(new)))
|
||||
else:
|
||||
modlist.append((ldap.MOD_ADD, key, list(new)))
|
||||
if modlist:
|
||||
modifies.append((dn, modlist))
|
||||
except ldap.NO_SUCH_OBJECT:
|
||||
adds.append((dn, ldap.modlist.addModlist(attrs)))
|
||||
|
||||
for dn, add in adds:
|
||||
try:
|
||||
if not args.fake:
|
||||
conn.add_s(dn, add)
|
||||
if args.verbose:
|
||||
attributes = [entry[0] for entry in add]
|
||||
print '- added entry %s' % dn
|
||||
for name, values in add:
|
||||
print ' -', name, ':', ', '.join(values)
|
||||
except ldap.LDAPError, e:
|
||||
print >>sys.stderr, 'Unable to create entry %s: %s' % (dn, e)
|
||||
for dn, modify in modifies:
|
||||
try:
|
||||
if not args.fake:
|
||||
conn.modify_s(dn, modify)
|
||||
if args.verbose:
|
||||
print 'modified entry %s' % dn
|
||||
for op, name, values in modify:
|
||||
if op == ldap.MOD_ADD:
|
||||
print ' - add values "', ', '.join(values), '" to attribute', name
|
||||
elif op == ldap.MOD_DELETE:
|
||||
if values == None:
|
||||
print ' - removed all values of attribute', name
|
||||
else:
|
||||
print ' - removed values "', ', '.join(values), '" from attribute', name
|
||||
elif op == ldap.MOD_REPLACE:
|
||||
print ' - replaced values of attribute', name, 'with values "', ', '.join(values), '"'
|
||||
except ldap.LDAPError, e:
|
||||
print >>sys.stderr, 'Unable to modify entry %s: %s' % (dn, e)
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
import d'un ou plusieurs fichiers LDIF
|
||||
|
||||
aucune vérification n'est faite au delà de celles implémentées dans le LDAP;
|
||||
seul les mots de passe sont hachés en utilisant la version salée de SHA1 s'ils
|
||||
sont en clair.
|
||||
|
Reference in New Issue