Процесс изменения записей LDIF с помощью python-ldap

#python #ldap #python-ldap #ldif

Вопрос:

Я использую python-ldap для обработки файла LDIF и (условно) импорта записей из этого файла на сервер LDAP. Каждая часть документации и каждый пример, который я могу найти, просто предполагает, что записи LDIF являются дополнениями. Однако файлы LDIF, которые обрабатывает мой скрипт, являются файлами версии 1 с типом изменений, например так:

 version: 1  dn: cn=group,ou=groups,o=vault changetype: add cn: group mail: group@a.org member: cn=users,ou=users,o=vault  dn:cn=users,ou=users,o=vault changetype: modify add: memberOf memberOf: cn=group,ou=groups,o=vault -  

Согласно документации python-ldap, которую мне нужно использовать modlist.addModlist для добавлений и modlist.modifyModlist модификаций.

Мой вопрос: как мне перейти от проанализированных данных LDIF к модификации в LDAP? Что-то вроде:

 parser = ldif.LDIFRecordList(open(filename,'r')) parser.parse() for dn, entry in parser.all_records:  if entry['changetype'] == "add":  crud = modlist.addModlist(entry)  ldapcon.add_s(dn,crud)  else:  crud = modlist.modifyModlist(entry)  ldapcon.modify_s(dn,crud)  

Вышесказанное не работает; modlist.modifyModlist() требуется два аргумента. Кроме того, entry он содержит только точные строки из LDIF в массиве кортежей, включая тип изменений и (обязательную) разделительную строку с одним тире 🙁

Действительно ли мне нужно анализировать входные данные строка за строкой и создавать свои собственные изменения? Какова дополнительная ценность анализатора LDIF, если это так?

Ответ №1:

Прежде всего, вы должны обрабатывать записи в методе обработки синтаксического анализатора, а не во внешнем цикле после того, как все записи будут проанализированы. Так что это:

 class myParser( LDIFParser ):   def handle( self, dn, entry ):  # Your code/logic here...  parser = myParser( open(.... parser.parse()  

вместо:

 parser = myParser( open(... parser.parse()  for dn, entry...  

Что касается модлиста, вам нужно передать старую запись (словарь, представленный в методе дескриптора) и новый, измененный словарь со всеми неизмененными элементами, новыми, измененными и без удаленных. Что-то вроде этого:

 class myParser( LDIFParser ):   def handle( self, dn, entry ):   # Filter for objectClass if needed  if b'some_class' not in entry['objectClass']:  return    # new_entry is a copy of old entry  new_entry = entry.copy()    # Add an attribute named 'add_new'  new_entry['add_new'] = 'Added'    # Modify an attribute named 'modify existing'  new_entry['modify_existing'] = [b'99']    print( 'OLD:', entry )  print( 'NEW:', new_entry )    print( ldap.modlist.modifyModlist( entry, new_entry ) )  

Комментарии:

1. Спасибо вам за этот ответ. В вашем примере также предполагается наличие полных записей, а не записей изменений. После проведения дополнительных тестов и изучения исходного кода анализатора LDIF я пришел к выводу, что обработка записей изменения LDIF невозможна.

Ответ №2:

Я провел больше исследований и тестов.

С текущей версией (3.3.1) python-ldap невозможно надежно обрабатывать записи об изменении LDIF. Рассмотрим следующий фрагмент LDIF:

 dn: cn=user,ou=org changetype: modify add: memberOf memberOf: cn=group,o=org - delete: description description: groupless - add: description description: grouped -  

При чтении этого из файла LDIF с python-ldap данные передаются в dict файл с key: [value] записями. Однако dict не позволяет дублировать ключи, поэтому ключи объединяются, что нежелательно.

Это и есть результат dict :

 {'changetype': [b'modify'], 'add': [b'memberOf', b'description'],   'memberOf': [b'cn=group,o=org'], '-': [None, None, None],   'delete': [b'description'], 'description': [b'groupless', b'grouped']}  

Как вы можете видеть, больше невозможно определить, какая операция должна быть первой (добавление или удаление), или какое значение должно быть удалено, а какое добавлено (без групп или сгруппировано).