예제 #1
0
    def PostProcess(self, data_map, source, search_filter, search_scope):
        """Perform some post-process of the data."""
        if 'uniqueMember' in self.attrs:
            for gr in data_map:
                uidmembers = []
                for member in gr.members:
                    source.Search(search_base=member,
                                  search_filter='(objectClass=*)',
                                  search_scope=ldap.SCOPE_BASE,
                                  attrs=['uid'])
                    for obj in source:
                        if 'uid' in obj:
                            uidmembers.extend(obj['uid'])
                del gr.members[:]
                gr.members.extend(uidmembers)

        _group_map = {i.name: i for i in data_map}

        def _expand_members(obj, visited=None):
            """Expand all subgroups recursively."""
            for member_name in obj.groupmembers:
                if member_name in _group_map and member_name not in visited:
                    gmember = _group_map[member_name]
                    for member in gmember.members:
                        if member not in obj.members:
                            obj.members.append(member)
                    for submember_name in gmember.groupmembers:
                        if submember_name in _group_map and submember_name not in visited:
                            visited.append(submember_name)
                            _expand_members(_group_map[submember_name], visited)

        if self.conf.get("nested_groups"):
            self.log.info("Expanding nested groups")
            for gr in data_map:
                _expand_members(gr, [gr.name])
예제 #2
0
 def PostProcess(self, data_map, source, search_filter, search_scope):
   """Perform some post-process of the data."""
   if 'uniqueMember' in self.attrs:
     for gr in data_map:
       uidmembers=[]
       for member in gr.members:
         source.Search(search_base=member,
                       search_filter='(objectClass=*)',
                       search_scope=ldap.SCOPE_BASE,
                       attrs=['uid'])
         for obj in source:
           if 'uid' in obj:
             uidmembers.extend(obj['uid'])
       del gr.members[:]
       gr.members.extend(uidmembers)
예제 #3
0
    def GetUpdates(self, source, search_base, search_filter, search_scope,
                   since):
        """Get updates from a source.

        Args:
          source: a data source
          search_base: the LDAP base of the tree
          search_filter: the LDAP object filter
          search_scope:  the LDAP scope filter, one of 'base', 'one', or 'sub'.
          since: a timestamp to get updates since (None for 'get everything')

        Returns:
          a tuple containing the map of updates and a maximum timestamp

        Raises:
          error.ConfigurationError: scope is invalid
          ValueError: an object in the source map is malformed
        """
        if self.conf.get('ad'):
            # AD attribute for modifyTimestamp is whenChanged
            self.attrs.append('whenChanged')
        else:
            self.attrs.append('modifyTimestamp')

        if since is not None:
            ts = self.FromTimestampToLdap(since)
            # since openldap disallows modifyTimestamp "greater than" we have to
            # increment by one second.
            if self.conf.get('ad'):
                ts = int(ts.rstrip('.0Z')) + 1
                ts = '%s.0Z' % ts
                search_filter = ('(&%s(whenChanged>=%s))' % (search_filter, ts))
            else:
                ts = int(ts.rstrip('Z')) + 1
                ts = '%sZ' % ts
                search_filter = ('(&%s(modifyTimestamp>=%s))' %
                                 (search_filter, ts))

        if search_scope == 'base':
            search_scope = ldap.SCOPE_BASE
        elif search_scope in ['one', 'onelevel']:
            search_scope = ldap.SCOPE_ONELEVEL
        elif search_scope in ['sub', 'subtree']:
            search_scope = ldap.SCOPE_SUBTREE
        else:
            raise error.ConfigurationError('Invalid scope: %s' % search_scope)

        source.Search(search_base=search_base,
                      search_filter=search_filter,
                      search_scope=search_scope,
                      attrs=self.attrs)

        # Don't initialize with since, because we really want to get the
        # latest timestamp read, and if somehow a larger 'since' slips through
        # the checks in main(), we'd better catch it here.
        max_ts = None

        data_map = self.CreateMap()

        for obj in source:
            for field in self.essential_fields:
                if field not in obj:
                    logging.warn('invalid object passed: %r not in %r', field,
                                 obj)
                    raise ValueError('Invalid object passed: %r', obj)

            if self.conf.get('ad'):
                obj_ts = self.FromLdapToTimestamp(obj['whenChanged'][0])
            else:
                try:
                    obj_ts = self.FromLdapToTimestamp(obj['modifyTimestamp'][0])
                except KeyError:
                    obj_ts = self.FromLdapToTimestamp(obj['modifyTimeStamp'][0])

            if max_ts is None or obj_ts > max_ts:
                max_ts = obj_ts

            try:
                if not data_map.Add(self.Transform(obj)):
                    logging.info('could not add obj: %r', obj)
            except AttributeError as e:
                logging.warning('error %r, discarding malformed obj: %r',
                                str(e), obj)
        # Perform some post processing on the data_map.
        self.PostProcess(data_map, source, search_filter, search_scope)

        data_map.SetModifyTimestamp(max_ts)

        return data_map