示例#1
0
async def ldap_auth(request: web.Request) -> web.Response:
    ldap_uri = request.headers.get(LDAP_HEADERS.URI)
    ldap_user_dn_tpl = request.headers.get(LDAP_HEADERS.USER_DN_TEMPLATE)
    if not (ldap_uri and ldap_user_dn_tpl):
        logging.error("LDAP configuration headers missing.")
        return web.Response(status=400)

    auth_header = request.headers.get(hdrs.AUTHORIZATION)
    if not auth_header:
        logging.debug("Authorization header missing.")
        return challenge_response()
    auth = BasicAuth.decode(auth_header=auth_header, encoding="UTF-8")

    client = bonsai.LDAPClient(ldap_uri)
    client.set_credentials("SIMPLE",
                           user=ldap_user_dn_tpl.format(user=auth.login),
                           password=auth.password)
    try:
        async with client.connect(is_async=True) as conn:
            await conn.whoami()
            return web.Response(
                status=204, headers={"Cache-Control": "public, max-age=1800"})
    except bonsai.LDAPError as ex:
        logging.debug(repr(ex))
        return challenge_response()
示例#2
0
    async def search(self, host, port, base, filter, attributes):
        raised_exc = None
        n = 1

        try:
            client = bonsai.LDAPClient('ldap://' + host + ':' + port + '/')
            while n <= self.n_try:
                try:
                    conn = await client.connect(True,
                                                timeout=float(self.timeout))
                    res = await conn.search(base,
                                            bonsai.LDAPSearchScope.SUB,
                                            filter,
                                            attributes,
                                            timeout=float(self.timeout))

                    return res

                except Exception as exc:
                    self.logger.error('from {}.search() - {}'.format(
                        module_class_name(self), repr(exc)))
                    await asyncio.sleep(float(self.retry_sleep_list[n - 1]))
                    raised_exc = exc

                self.logger.info(f'LDAP Connection try - {n}')
                n += 1

            else:
                self.logger.error('LDAP Connection retry exhausted')

        except Exception as exc:
            self.logger.error('from {}.search() - {}'.format(
                module_class_name(self), repr(exc)))
            raise ConnectorHttpError()
示例#3
0
async def setup (app, loop):
	global client, refreshJobThread

	config = app.config

	client = bonsai.LDAPClient (config.LDAP_SERVER)
	client.set_credentials ("SIMPLE", user=config.LDAP_USER, password=config.LDAP_PASSWORD)
	refreshJobThread = asyncio.ensure_future (refreshJob (config.LDAP_TOS_BASE))
 async def is_password_for_user(self, name: str, password: str) -> bool:
     try:
         client = bonsai.LDAPClient(self.url)
         client.set_credentials("SIMPLE", user=name, password=password)
         async with client.connect(is_async=True):
             return True
     except Exception:
         return False
 async def is_valid(self, name: str) -> bool:
     client = bonsai.LDAPClient(self.url)
     client.set_credentials("SIMPLE", user=self.username, password=self.password)
     async with client.connect(is_async=True) as connection:
         results = await connection.search(
             self.base,
             bonsai.LDAPSearchScope.SUBTREE,
             f'(&(userAccountControl:1.2.840.113556.1.4.803:=2)(userPrincipalName={name}))',
             ['userPrincipalName']
         )
         return len(results) == 0
 async def bind(self, dn, password):
     """Asynchronous context manager for the LDAP BIND operation,
     yielding the open connection (``bonsai.Connection`` instance)
     or raising an ``LDAPInvalidCredentials``.
     """
     client = bonsai.LDAPClient(self.url)
     client.set_cert_policy("allow")  # TODO: Add certificate
     client.set_credentials("SIMPLE", user=dn, password=password)
     try:
         async with client.connect(is_async=True) as conn:
             yield conn
     except bonsai.AuthenticationError as exc:
         raise LDAPInvalidCredentials from exc
 async def disabled_users(self) -> AbstractSet[str]:
     """Find all disabled users"""
     client = bonsai.LDAPClient(self.url)
     client.set_credentials("SIMPLE", user=self.username, password=self.password)
     async with client.connect(is_async=True) as connection:
         results = await connection.search(
             self.base,
             bonsai.LDAPSearchScope.SUBTREE,
             '(userAccountControl:1.2.840.113556.1.4.803:=2)',
             ['userPrincipalName']
         )
         users = {entry['userPrincipalName'][0] for entry in results}
         return users
示例#8
0
    async def do_ldap_search(self, ldap_server: LdapServer, retry=False):
        """
        Searches the specified LDAP server after certificates

        Buypass caps the result at 20, and doesn't support "normal" paging
        so to get all the certs we need to do several searches and exclude the
        certs we have already gotten. The queries get uglier and uglier,
        so this shouldn't be repeatet too many times
        """
        client = bonsai.LDAPClient(f"ldap://{ldap_server.hostname}")
        count = 0
        results = []
        all_results = []
        search_filter = self.ldap_params.ldap_query
        logger.debug("Starting: ldap search against: %s", ldap_server.hostname)
        with (await client.connect(is_async=True, timeout=LDAP_TIMEOUT)) as conn:  # type: ignore
            while count < LDAP_RETRIES:
                logger.debug(
                    'Doing search with filter "%s" against "%s"',
                    search_filter,
                    ldap_server.hostname,
                )
                results = await conn.search(
                    ldap_server.base,
                    self.ldap_params.scope,
                    search_filter,
                    attrlist=["certificateSerialNumber", "userCertificate;binary"],
                )
                all_results += results

                if len(results) == 20 and retry:
                    certs_to_exclude = ""
                    for result in results:
                        certs_to_exclude += f"(!({str(result.dn).split(',')[0]}))"
                    search_filter = "(&{}{})".format(search_filter, certs_to_exclude)
                    count += 1
                else:
                    count = LDAP_RETRIES + 1

            logger.debug("Ending: ldap search against: %s", ldap_server.hostname)
            # If we got 20 on our last search (of several),
            # there may be more certs out there...
            if len(results) == 20 and retry:
                logger.warning(
                    "Exceeded max count for search with filter %s against %s",
                    self.ldap_params.ldap_query,
                    ldap_server.hostname,
                )
                self.warnings.append("ERR-004")

        return await self._parse_ldap_results(all_results, ldap_server)
示例#9
0
    def check(self):
        import bonsai

        conn = None
        cur = None
        try:
            client = bonsai.LDAPClient(f"ldap://{self.host}:{self.get_port()}")

            try:
                con = client.connect()
            finally:
                pass
            return True
        except Exception:
            return False
示例#10
0
    async def _get_ldap_groups(self, uid: str) -> List[TokenGroup]:
        """Get groups for a user from LDAP.

        Parameters
        ----------
        uid : `str`
            Username of the user.

        Returns
        -------
        groups : List[`gafaelfawr.models.token.TokenGroup`]
            User's groups from LDAP.

        Raises
        ------
        gafaelfawr.exceptions.LDAPException
            One of the groups for the user in LDAP was not valid (missing
            cn or gidNumber attributes, or gidNumber is not an integer)
        """
        assert self._ldap_config
        group_class = self._ldap_config.group_object_class
        member_attr = self._ldap_config.group_member
        ldap_query = f"(&(objectClass={group_class})({member_attr}={uid}))"

        client = bonsai.LDAPClient(self._ldap_config.url)
        async with client.connect(is_async=True) as conn:
            results = await conn.search(
                self._ldap_config.base_dn,
                bonsai.LDAPSearchScope.SUB,
                ldap_query,
                attrlist=["cn", "gidNumber"],
            )

            # Parse the results into the group list.
            groups = []
            for result in results:
                name = None
                try:
                    name = result["cn"][0]
                    gid = int(result["gidNumber"][0])
                    groups.append(TokenGroup(name=name, id=gid))
                except Exception as e:
                    msg = f"LDAP group {name} for user {uid} invalid: {str(e)}"
                    raise LDAPException(msg)
            return groups
 async def _ldap_groups(self, user_attr: str, user_value: Any) -> AbstractSet[str]:
     client = bonsai.LDAPClient(self.url)
     client.set_credentials("SIMPLE", user=self.username, password=self.password)
     async with client.connect(is_async=True) as connection:
         results = await connection.search(
             self.base,
             bonsai.LDAPSearchScope.SUBTREE,
             f'({user_attr}={user_value})',
             ['memberOf'])
         members = [entry['memberOf'] for entry in results if len(entry['memberOf']) > 0]
         groups = set()
         for items in members:
             for item in items:
                 _, cn = next(
                     filter(lambda x: x[0].lower() == 'cn', (i.split('=', maxsplit=1) for i in item.split(','))),
                     [None, None])
                 groups.add(cn)
         return groups
示例#12
0
 def __init__(self, loop):
     self.loop = loop
     self.secret = fernet.Fernet.generate_key()
     self.key_signer = TimestampSigner(self.secret)
     self.client = bonsai.LDAPClient(self.settings['LDAP_SERVER'])