From: Frank Brehm Date: Fri, 13 Nov 2020 13:05:48 +0000 (+0100) Subject: Collecting a list of all entries X-Git-Url: https://git.uhu-banane.de/?a=commitdiff_plain;h=50aca825839a8e4982bc3446f9c0c9202c13af6c;p=pixelpark%2Fldap-migration.git Collecting a list of all entries --- diff --git a/lib/ldap_migration/__init__.py b/lib/ldap_migration/__init__.py index b24da97..a790614 100644 --- a/lib/ldap_migration/__init__.py +++ b/lib/ldap_migration/__init__.py @@ -14,10 +14,14 @@ import copy import sys import os import time +import re # 3rd party modules from ldap3 import Server, Connection, ALL, DSA, IP_V4_PREFERRED, SAFE_SYNC +from ldap3 import BASE, LEVEL, SUBTREE, DEREF_NEVER, DEREF_SEARCH, DEREF_BASE, DEREF_ALWAYS +from ldap3 import ALL_ATTRIBUTES, ALL_OPERATIONAL_ATTRIBUTES + from ldap3.core.exceptions import LDAPException # Own modules @@ -30,7 +34,7 @@ from fb_tools.errors import FbAppError from .config import LDAPMigrationConfiguration -__version__ = '0.4.0' +__version__ = '0.5.0' LOG = logging.getLogger(__name__) CFG_BASENAME = 'ldap-migration.ini' @@ -53,6 +57,9 @@ class LDAPMigrationApplication(BaseApplication): Class for the application objects. """ + re_dn_split = re.compile(r'\s*,\s*') + re_token_split = re.compile(r'^\s*([a-z0-9]+)\s*=\s*(\S(?:.*\S)?)\s*$', re.IGNORECASE) + # ------------------------------------------------------------------------- def __init__( self, appname=None, verbose=0, version=__version__, base_dir=None): @@ -69,6 +76,8 @@ class LDAPMigrationApplication(BaseApplication): self.source = None self.tgt_server = None self.target = None + self.tmp_dir = None + self.all_dns_file = None self.object_classes = {} self.attribute_types = {} @@ -78,6 +87,8 @@ class LDAPMigrationApplication(BaseApplication): description=description, initialized=False, ) + self.tmp_dir = self.base_dir / 'tmp' + self.all_dns_file = self.tmp_dir / 'all-dns.txt' self.initialized = True # ------------------------------------------------------------------------- @@ -482,6 +493,110 @@ class LDAPMigrationApplication(BaseApplication): tmp_dict[name_lc] = self.attribute_types[name_lc]['single_name'] LOG.debug("Discovered AttributeTypes:\n" + pp(tmp_dict)) + # ------------------------------------------------------------------------- + def check_tmp_dir(self): + """Checking existence of temp-dir and creating it, if necessary.""" + + LOG.debug("Checking temporary directory {!r} ...".format(str(self.tmp_dir))) + + if self.tmp_dir.exists(): + if self.tmp_dir.is_dir(): + LOG.debug("Temporary directory {!r} is already existing.".format( + str(self.tmp_dir))) + else: + msg = "Path {!r} is already existing, but is not a directory.".format( + str(self.tmp_dir)) + raise CommonLDAPMigrationError(msg) + else: + LOG.info("Creating temporary directory {!r} ...".format(str(self.tmp_dir))) + self.tmp_dir.mkdir(mode=0o755, exist_ok=True) + + mod2check = os.R_OK | os.W_OK | os.X_OK + euid = False + if os.access in os.supports_effective_ids: + euid = True + if not os.access(str(self.tmp_dir), mod2check, effective_ids=euid): + msg = "Insufficient access rights to temporary directory {!r}.".format( + str(self.tmp_dir)) + raise CommonLDAPMigrationError(msg) + + if self.verbose > 1: + LOG.debug("Access to {!r} is okay.".format(str(self.tmp_dir))) + + # ------------------------------------------------------------------------- + def lookup_for_attrtype(self, attrtype, silent=True): + + at_lc = attrtype.lower() + if at_lc not in self.attribute_types: + msg = "AttributeType {!r} not found.".format(attrtype) + if silent: + if self.verbose > 2: + LOG.debug(msg) + else: + LOG.error(msg) + return None + + new_at = self.attribute_types[at_lc]['single_name'] + return new_at + + # ------------------------------------------------------------------------- + def mangle_dn_token(self, old_token): + + match = self.re_token_split.search(old_token) + if not match: + return old_token + + key = match.group(1) + new_key = self.lookup_for_attrtype(key, silent=False) + if not new_key: + msg = "F***, Whats that?" + raise CommonLDAPMigrationError(msg) + value = match.group(2) + + return "{key}={val}".format(key=new_key, val=value) + + # ------------------------------------------------------------------------- + def mangle_dn(self, old_dn): + + parts = self.re_dn_split.split(old_dn) + new_parts = [] + for old_token in parts: + new_token = self.mangle_dn_token(old_token) + new_parts.append(new_token) + + return ','.join(parts) + + # ------------------------------------------------------------------------- + def get_all_dns(self): + + LOG.info("Collecting all source SNs and writing them into {!r} ...".format( + str(self.all_dns_file))) + + open_args = { + 'encoding': 'utf-8', + 'errors': 'surrogateescape', + 'mode': 'w', + } + sfilter = '(objectClass=*)' + + item_count = 0 + + with self.all_dns_file.open(**open_args) as fh: + + status, result, response, _ = self.source.search( + search_base=self.config.suffix, search_scope=SUBTREE, search_filter=sfilter, + attributes=['objectClass'], time_limit=self.config.timeout) + for entry in response: + item_count += 1 + old_dn = entry['dn'] + new_dn = self.mangle_dn(old_dn) + if self.verbose > 2: + LOG.debug("Found DN {!r}.".format(old_dn)) + fh.write("{old} => {new}\n".format(old=old_dn, new=new_dn)) + + LOG.info("Found {nr} items in subtree of {sfx!r}.".format( + nr=item_count, sfx=self.config.suffix)) + # ------------------------------------------------------------------------- def _run(self): @@ -492,6 +607,8 @@ class LDAPMigrationApplication(BaseApplication): self.connect_source() self.connect_target() self.discover_target_schema() + self.check_tmp_dir() + self.get_all_dns() LOG.info("Sleeping ...") time.sleep(2) finally: diff --git a/migrate-ldap b/migrate-ldap index 92684c9..d67bd67 100755 --- a/migrate-ldap +++ b/migrate-ldap @@ -48,7 +48,7 @@ locale.setlocale(locale.LC_ALL, '') app = LDAPMigrationApplication(appname=appname, base_dir=base_dir) app.initialized = True -if app.verbose > 2: +if app.verbose > 1: print("{c}-Object:\n{a}".format(c=app.__class__.__name__, a=app)) app()