Ejemplo n.º 1
0
    def test_max_uid_constant_not_too_small(self):
        """Test that the known_min constant is sufficiently large.

        The way we find the next available UID is very slow because there is no
        way to do a query like "find the max UID from all users" in LDAP.
        We instead have to find all users and take the max ourselves. This can
        take ~15 seconds.

        By hardcoding a known min, we just select accounts with uid >
        known_min, which is much faster. But it means we need to bump the
        constant occasionally to keep it fast.
        """
        known_uid = _cache['known_uid']
        with ldap_ocf() as c:
            c.search(
                constants.OCF_LDAP_PEOPLE,
                '(uidNumber>={KNOWN_MIN})'.format(KNOWN_MIN=known_uid),
                attributes=['uidNumber'],
            )
            num_uids = len(c.response)

        if num_uids > 2500:
            raise AssertionError((
                'Found {} accounts with UID >= {}, you should bump the constant for speed.'
            ).format(num_uids, known_uid))
Ejemplo n.º 2
0
    def test_max_uid_constant_not_too_small(self):
        """Test that the _KNOWN_UID constant is sufficiently large.

        The way we find the next available UID is very slow because there is no
        way to do a query like "find the max UID from all users" in LDAP.
        We instead have to find all users and take the max ourselves. This can
        take ~15 seconds.

        By hardcoding a known min, we just select accounts with uid >
        _KNOWN_UID, which is much faster. This makes finding available UIDs
        faster the first time a query is made. The result can be cached to make
        subsequent attempts even faster.
        """
        with ldap_ocf() as c:
            c.search(
                constants.OCF_LDAP_PEOPLE,
                '(uidNumber>={KNOWN_MIN})'.format(KNOWN_MIN=_KNOWN_UID),
                attributes=['uidNumber'],
            )
            num_uids = len(c.response)

        if num_uids > 2500:
            raise AssertionError((
                'Found {} accounts with UID >= {}, you should bump the constant for speed.'
            ).format(num_uids, _KNOWN_UID))
Ejemplo n.º 3
0
def _get_first_available_uid():
    """Return the first available UID number.

    Searches our entire People ou in order to find it. It seems like there
    should be a better way to do this, but quick searches don't show any.

    We hard-code a value we know has already been reached and only select
    entries greater than that for performance. We then use a module-level
    dict to cache our output for the next function call.
    """
    min_uid = _cache['known_uid']
    with ldap_ocf() as c:
        c.search(
            constants.OCF_LDAP_PEOPLE,
            '(uidNumber>={KNOWN_MIN})'.format(KNOWN_MIN=min_uid),
            attributes=['uidNumber'],
        )
        uids = [int(entry['attributes']['uidNumber'][0]) for entry in c.response]
    if uids:
        max_uid = max(uids)
        _cache['known_uid'] = max_uid
    else:
        # If cached UID is later deleted, LDAP response will be empty.
        max_uid = min_uid
    return max_uid + 1
Ejemplo n.º 4
0
def hosts_by_filter(ldap_filter):
    """Return a list of hosts satisfying the LDAP filter."""

    with ldap.ldap_ocf() as c:
        c.search(constants.OCF_LDAP_HOSTS, ldap_filter, attributes=ldap3.ALL_ATTRIBUTES)

        return [entry["attributes"] for entry in c.response]
Ejemplo n.º 5
0
    def test_max_uid_constant_not_too_small(self):
        """Test that the known_min constant is sufficiently large.

        The way we find the next available UID is very slow because there is no
        way to do a query like "find the max UID from all users" in LDAP.
        We instead have to find all users and take the max ourselves. This can
        take ~15 seconds.

        By hardcoding a known min, we just select accounts with uid >
        known_min, which is much faster. But it means we need to bump the
        constant occasionally to keep it fast.
        """
        known_uid = _cache['known_uid']
        with ldap_ocf() as c:
            c.search(
                constants.OCF_LDAP_PEOPLE,
                '(uidNumber>={KNOWN_MIN})'.format(KNOWN_MIN=known_uid),
                attributes=['uidNumber'],
            )
            num_uids = len(c.response)

        if num_uids > 2500:
            raise AssertionError((
                'Found {} accounts with UID >= {}, you should bump the constant for speed.'
            ).format(num_uids, known_uid))
Ejemplo n.º 6
0
def _get_first_available_uid(known_uid=_KNOWN_UID):
    """Return the first available UID number.

    Searches our entire People ou in order to find it. It seems like there
    should be a better way to do this, but quick searches don't show any.

    We hard-code a value we know has already been reached and only select
    entries greater than that for performance. This value can then be cached
    and passed back in to make subsequent calls faster.
    """
    with ldap_ocf() as c:
        c.search(
            OCF_LDAP_PEOPLE,
            '(uidNumber>={KNOWN_MIN})'.format(KNOWN_MIN=known_uid),
            attributes=['uidNumber'],
        )
        uids = [int(entry['attributes']['uidNumber']) for entry in c.response]
    if uids:
        max_uid = max(uids)
    else:
        # If cached UID is later deleted, LDAP response will be empty.
        max_uid = known_uid

    assert all(start <= end for start, end in RESERVED_UID_RANGES)
    next_uid = max_uid + 1
    for start, end in sorted(RESERVED_UID_RANGES):
        if start <= next_uid <= end:
            next_uid = end + 1

    return next_uid
Ejemplo n.º 7
0
def checkacct(bot, msg):
    """Print matching OCF usernames."""
    search_term = msg.match.group(1).strip()
    keywords = search_term.split()

    if len(keywords) > 0:
        search = '(&{})'.format(
            ''.join(
                # all keywords must match either uid or cn
                '(|(uid=*{keyword}*)(cn=*{keyword}*))'.format(keyword=alphanum(
                    keyword), ) for keyword in keywords), )

        with ldap.ldap_ocf() as c:
            c.search(
                ldap.OCF_LDAP_PEOPLE,
                search,
                attributes=('uid', 'cn'),
                size_limit=5,
            )

            if len(c.response) > 0:
                msg.respond(
                    ', '.join(
                        sorted('{} ({})'.format(
                            entry['attributes']['uid'][0],
                            entry['attributes']['cn'][0],
                        ) for entry in c.response)), )
            else:
                msg.respond('no results found')
Ejemplo n.º 8
0
    def test_max_uid_constant_not_too_small(self):
        """Test that the _KNOWN_UID constant is sufficiently large.

        The way we find the next available UID is very slow because there is no
        way to do a query like "find the max UID from all users" in LDAP.
        We instead have to find all users and take the max ourselves. This can
        take ~15 seconds.

        By hardcoding a known min, we just select accounts with uid >
        _KNOWN_UID, which is much faster. This makes finding available UIDs
        faster the first time a query is made. The result can be cached to make
        subsequent attempts even faster.
        """
        with ldap_ocf() as c:
            c.search(
                OCF_LDAP_PEOPLE,
                '(uidNumber>={KNOWN_MIN})'.format(KNOWN_MIN=_KNOWN_UID),
                attributes=['uidNumber'],
            )
            num_uids = len(c.response)

        if num_uids > 2500:
            raise AssertionError((
                'Found {} accounts with UID >= {}, you should bump the constant for speed.'
            ).format(num_uids, _KNOWN_UID))
Ejemplo n.º 9
0
def _get_first_available_uid():
    """Return the first available UID number.

    Searches our entire People ou in order to find it. It seems like there
    should be a better way to do this, but quick searches don't show any.

    We hard-code a value we know has already been reached and only select
    entries greater than that for performance. We then use a module-level
    dict to cache our output for the next function call.
    """
    min_uid = _cache['known_uid']
    with ldap_ocf() as c:
        c.search(
            constants.OCF_LDAP_PEOPLE,
            '(uidNumber>={KNOWN_MIN})'.format(KNOWN_MIN=min_uid),
            attributes=['uidNumber'],
        )
        uids = [
            int(entry['attributes']['uidNumber'][0]) for entry in c.response
        ]
        if len(uids) > 2500:
            send_problem_report(
                ('Found {} accounts with UID >= {}, '
                 'you should bump the constant for speed.').format(
                     len(uids), min_uid))
        if uids:
            max_uid = max(uids)
            _cache['known_uid'] = max_uid
        else:
            # If cached UID is later deleted, LDAP response will be empty.
            max_uid = min_uid
        return max_uid + 1
Ejemplo n.º 10
0
def list_desktops(public_only=False):
    if not public_only:
        filter = '(type=desktop)'
    else:
        filter = '(&(type=desktop)(!(|(puppetVar=staff_only=true)(puppetVar=pubstaff_only=true))))'

    with ldap_ocf() as c:
        c.search(OCF_LDAP_HOSTS, filter, attributes=['cn'])
        return [entry['attributes']['cn'][0] for entry in c.response]
Ejemplo n.º 11
0
def list_desktops(public_only=False):
    if not public_only:
        filter = '(type=desktop)'
    else:
        filter = '(&(type=desktop)(!(|(dnsA=frontdesk)(dnsA=staffdesk))))'

    with ldap_ocf() as c:
        c.search(OCF_LDAP_HOSTS, filter, attributes=['cn'])
        return [entry['attributes']['cn'][0] for entry in c.response]
Ejemplo n.º 12
0
def users_by_filter(ldap_filter):
    """Returns a list of users matching an LDAP filter"""
    with ldap.ldap_ocf() as c:
        c.search(
            OCF_LDAP_PEOPLE,
            ldap_filter,
            attributes=('uid', ),
            search_scope=ldap3.LEVEL,
        )
        return [entry['attributes']['uid'][0] for entry in c.response]
Ejemplo n.º 13
0
def users_by_filter(ldap_filter):
    """Returns a list of users matching an LDAP filter"""
    with ldap.ldap_ocf() as c:
        c.search(
            constants.OCF_LDAP_PEOPLE,
            ldap_filter,
            attributes=('uid',),
            search_scope=ldap3.LEVEL,
        )
        return [entry['attributes']['uid'][0] for entry in c.response]
Ejemplo n.º 14
0
def hosts_by_filter(ldap_filter):
    """Return a list of hosts satisfying the LDAP filter."""

    with ldap.ldap_ocf() as c:
        c.search(
            constants.OCF_LDAP_HOSTS,
            ldap_filter,
            attributes=ldap3.ALL_ATTRIBUTES,
        )

        return [entry['attributes'] for entry in c.response]
Ejemplo n.º 15
0
def _get_account_stats():
    with ldap_ocf() as c:
        c.search(OCF_LDAP_PEOPLE, "(cn=*)", attributes=["creationTime", "uidNumber", "callinkOid"])
        response = c.response

    # Some accounts don't have creation times, so we assume that as UIDs
    # increase, so does time. We use this assumption to fill in the gaps.
    start_date = date(1989, 1, 1)
    last_creation_time = start_date
    sorted_accounts = sorted(response, key=lambda record: record["attributes"]["uidNumber"][0])
    counts = defaultdict(int)
    group_counts = defaultdict(int)

    for account in sorted_accounts:
        creation_time, = account["attributes"].get("creationTime", [None])
        if creation_time:
            creation_time = parse(creation_time).date()
            last_creation_time = creation_time
        else:
            creation_time = last_creation_time
        assert creation_time is not None

        counts[creation_time] += 1
        if "callinkOid" in account["attributes"]:
            group_counts[creation_time] += 1

    one_day = timedelta(days=1)
    cur = start_date
    total = group_total = 0
    dates = []
    cumulative_accounts = []
    cumulative_group_accounts = []
    accounts_each_day = []
    while cur <= date.today():
        total += counts[cur]
        group_total += group_counts[cur]
        dates.append(cur)

        cumulative_accounts.append(total)
        cumulative_group_accounts.append(group_total)
        accounts_each_day.append(counts[cur])

        cur += one_day

    return {
        "dates": dates,
        "cumulative_accounts": cumulative_accounts,
        "cumulative_group_accounts": cumulative_group_accounts,
        "accounts_each_day": accounts_each_day,
    }
Ejemplo n.º 16
0
def hosts_by_filter(ldap_filter):
    """Return a list of hosts satisfying the LDAP filter.

    The list returned contains a dictionary of LDAP attributes for each host.
    """

    with ldap.ldap_ocf() as c:
        c.search(
            constants.OCF_LDAP_HOSTS,
            ldap_filter,
            attributes=ldap3.ALL_ATTRIBUTES,
        )

        return [entry['attributes'] for entry in c.response]
Ejemplo n.º 17
0
def hosts_by_filter(ldap_filter):
    """Return a list of hosts satisfying the LDAP filter.

    The list returned contains a dictionary of LDAP attributes for each host.
    """

    with ldap.ldap_ocf() as c:
        c.search(
            OCF_LDAP_HOSTS,
            ldap_filter,
            attributes=ldap3.ALL_ATTRIBUTES,
        )

        return [entry['attributes'] for entry in c.response]
Ejemplo n.º 18
0
def _get_account_stats():
    with ldap_ocf() as c:
        c.search(OCF_LDAP_PEOPLE, '(cn=*)', attributes=['creationTime', 'uidNumber', 'callinkOid'])
        response = c.response

    # Some accounts don't have creation times, so we assume that as UIDs
    # increase, so does time. We use this assumption to fill in the gaps.
    start_date = date(1989, 1, 1)
    last_creation_time = start_date
    sorted_accounts = sorted(response, key=lambda record: record['attributes']['uidNumber'])
    counts = defaultdict(int)
    group_counts = defaultdict(int)

    for account in sorted_accounts:
        creation_time = account['attributes'].get('creationTime', None)
        if creation_time:
            creation_time = creation_time.date()
            last_creation_time = creation_time
        else:
            creation_time = last_creation_time
        assert creation_time is not None

        counts[creation_time] += 1
        if 'callinkOid' in account['attributes']:
            group_counts[creation_time] += 1

    one_day = timedelta(days=1)
    cur = start_date
    total = group_total = 0
    dates = []
    cumulative_accounts = []
    cumulative_group_accounts = []
    accounts_each_day = []
    while cur <= date.today():
        total += counts[cur]
        group_total += group_counts[cur]
        dates.append(cur)

        cumulative_accounts.append(total)
        cumulative_group_accounts.append(group_total)
        accounts_each_day.append(counts[cur])

        cur += one_day

    return {
        'dates': dates,
        'cumulative_accounts': cumulative_accounts,
        'cumulative_group_accounts': cumulative_group_accounts,
        'accounts_each_day': accounts_each_day,
    }
Ejemplo n.º 19
0
def _get_account_stats():
    with ldap_ocf() as c:
        c.search(OCF_LDAP_PEOPLE,
                 '(cn=*)',
                 attributes=['creationTime', 'uidNumber', 'callinkOid'])
        response = c.response

    # Some accounts don't have creation times, so we assume that as UIDs
    # increase, so does time. We use this assumption to fill in the gaps.
    start_date = date(1989, 1, 1)
    last_creation_time = start_date
    sorted_accounts = sorted(
        response, key=lambda record: record['attributes']['uidNumber'])
    counts = defaultdict(int)
    group_counts = defaultdict(int)

    for account in sorted_accounts:
        creation_time = account['attributes'].get('creationTime', None)
        if creation_time:
            creation_time = creation_time.date()
            last_creation_time = creation_time
        else:
            creation_time = last_creation_time
        assert creation_time is not None

        counts[creation_time] += 1
        if isinstance(account['attributes']['callinkOid'], int):
            group_counts[creation_time] += 1

    one_day = timedelta(days=1)
    cur = start_date
    total = group_total = 0
    dates = []
    cumulative_accounts = []
    cumulative_group_accounts = []
    while cur <= date.today():
        total += counts[cur]
        group_total += group_counts[cur]
        dates.append(cur)

        cumulative_accounts.append(total)
        cumulative_group_accounts.append(group_total)

        cur += one_day

    return {
        'dates': dates,
        'cumulative_accounts': cumulative_accounts,
        'cumulative_group_accounts': cumulative_group_accounts,
    }
Ejemplo n.º 20
0
def _get_first_available_uid(known_uid=_KNOWN_UID):
    """Return the first available UID number.

    Searches our entire People ou in order to find it. It seems like there
    should be a better way to do this, but quick searches don't show any.

    We hard-code a value we know has already been reached and only select
    entries greater than that for performance. This value can then be cached
    and passed back in to make subsequent calls faster.
    """
    with ldap_ocf() as c:
        c.search(
            constants.OCF_LDAP_PEOPLE,
            '(uidNumber>={KNOWN_MIN})'.format(KNOWN_MIN=known_uid),
            attributes=['uidNumber'],
        )
        uids = [int(entry['attributes']['uidNumber']) for entry in c.response]
    if uids:
        max_uid = max(uids)
    else:
        # If cached UID is later deleted, LDAP response will be empty.
        max_uid = known_uid
    return max_uid + 1