]> Frank Brehm's Git Trees - pixelpark/ldap-migration.git/commitdiff
Trying to evaluate dynamic groups
authorFrank Brehm <frank.brehm@pixelpark.com>
Fri, 15 Jan 2021 15:32:29 +0000 (16:32 +0100)
committerFrank Brehm <frank.brehm@pixelpark.com>
Fri, 15 Jan 2021 15:32:29 +0000 (16:32 +0100)
lib/ldap_migration/__init__.py

index c5589f2651c9a84ce58f6b9f1a9fa26368b1bd69..08926f23161b6082ab2c3aeab38523bfbee77607 100644 (file)
@@ -45,7 +45,7 @@ from fb_tools.collections import CIStringSet, CIDict
 
 from .config import LDAPMigrationConfiguration
 
-__version__ = '0.10.1'
+__version__ = '0.10.2'
 
 LOG = logging.getLogger(__name__)
 CFG_BASENAME = 'ldap-migration.ini'
@@ -185,8 +185,18 @@ class LDAPMigrationApplication(BaseApplication):
     re_token_split = re.compile(r'^\s*([a-z0-9]+)\s*=\s*(\S(?:.*\S)?)\s*$', re.IGNORECASE)
     re_plus_in_cn = re.compile(r'(?P<before>\S)(?:\s+\+\s+|\s+\+|\+\s+)\s*(?P<after>\S)')
 
+    pattern_member_url = r'^\s*ldaps?:///(?P<base>[^\?]+)(?:\?[^\?]*\?'
+    pattern_member_url += r'(?P<scope>[^\?]+)(?:\?(?P<filter>.+))?)?'
+    re_member_url = re.compile(pattern_member_url)
+
     rev_dn_samba_computers = 'o=isp:o=pixelpark:ou=Applications:ou=Unix NSS:ou=SambaComputers'
 
+    search_scope = {
+        'base': BASE,
+        'one': LEVEL,
+        'sub': SUBTREE,
+    }
+
     tz = get_localzone()
 
     syntax = {
@@ -1998,7 +2008,7 @@ class LDAPMigrationApplication(BaseApplication):
                 used_classes.add(tgt_oc_name)
                 if len(src_data['member_url']):
                     tgt_at_name = self.attribute_types.real_key('memberURL')
-                    target_entry[tgt_at_name] = src_data['member_url']
+                    target_entry[tgt_at_name] = copy.copy(src_data['member_url'])
             else:
                 tgt_oc_name = self.object_classes.real_key('groupOfUniqueNames')
                 used_classes.add(tgt_oc_name)
@@ -2022,10 +2032,56 @@ class LDAPMigrationApplication(BaseApplication):
         return (object_classes, target_entry)
 
     # -------------------------------------------------------------------------
-    def get_dyn_members(self, member_urls):
+    def get_dyn_members(self, member_urls, from_src=True):
 
         members = CIStringSet()
+        urls = member_urls
+        if not is_sequence(member_urls):
+            urls = [member_urls]
+
+        for member_url in urls:
+            match = self.re_member_url.match(member_url)
+            if not match:
+                msg = "Could not evaluate memberURL {!r}.".format(member_url)
+                LOG.error(msg)
+                continue
+            base = match.group('base')
+            scope = 'base'
+            if match.group('scope'):
+                scope = match.group('scope').lower()
+            search_filter = None
+            if match.group('filter'):
+                search_filter = match.group('filter')
+
+            if scope not in self.search_scope:
+                msg = "Wrong search scope {scope!r} in memberURL {url!r}.".format(
+                    scope=match.group('scope'), url=member_url)
+                LOG.error(msg)
+                continue
 
+            if self.verbose > 1:
+                target = 'target'
+                if from_src:
+                    target = 'source'
+                msg = ("Searching members from {t} on search base {b!r}, scope {sc!r}, "
+                    "filter {f!r} ...").format(t=target, b=base, sc=scope, f=search_filter)
+                LOG.debug(msg)
+            if from_src:
+                status, result, response, _ = self.source.search(
+                    search_base=base, search_scope=self.search_scope[scope],
+                    search_filter=search_filter, attributes=['dn'], time_limit=self.config.timeout)
+            else:
+                status, result, response, _ = self.target.search(
+                    search_base=base, search_scope=self.search_scope[scope],
+                    search_filter=search_filter, attributes=['dn'], time_limit=self.config.timeout)
+            for entry in response:
+                old_dn = entry['dn']
+                new_dn = old_dn
+                if from_src:
+                    new_dn = self.mangle_dn(old_dn)
+                if self.verbose > 1:
+                    LOG.debug("Found DN {!r}.".format(old_dn))
+                members.add(new_dn)
 
         return members