Uploaded image for project: 'Project Quay'
  1. Project Quay
  2. PROJQUAY-226

Add ability to use LDAP filters in Quay

XMLWordPrintable

    • LDAP filters in Quay
    • Documentation (Ref Guide, User Guide, etc.), Release Notes, Migration, Interactive Demo/Tutorial
    • 0% To Do, 0% In Progress, 100% Done

      Requested by several customers who are using AD. As of today they can't limit / filter the access to particular groups or users within a (potentially huge) LDAP tree. The result is that all users in this tree (entire company) have access to Quay which is not the desired behavior.

      User Stories:

      As a Quay admin I have more fine granular control on which users in my LDAP / AD are allowed to login to Quay. I can apply (multiple) filters to select the users and groups allowed to login.

      There are probably multiple options to achieve this goal.

      Customer fro 02433683 is having issues integrating Quay with their AD. They would like to select users based on the memberOf filter rather than specifying a specific subtree. They proposed the following diff that acomplishes that in ther environment:

       

      diff -uar quay-registry.orig/data/users/externalldap.py quay-registry/data/users/externalldap.py
       — quay-registry.orig/data/users/externalldap.py 2019-06-17 14:36:01.260953482 +0200
       +++ quay-registry/data/users/externalldap.py 2019-06-28 14:11:32.627694728 +0200
       @@ -67,7 +67,7 @@
      def _init_(self, ldap_uri, base_dn, admin_dn, admin_passwd, user_rdn, uid_attr, email_attr,
       allow_tls_fallback=False, secondary_user_rdns=None, requires_email=True,
      
      timeout=None, network_timeout=None, force_no_pagination=False):
       + timeout=None, network_timeout=None, force_no_pagination=False, ldap_user_filter=None):
       super(LDAPUsers, self)._init_('ldap', requires_email)
      self._ldap = LDAPConnectionBuilder(ldap_uri, admin_dn, admin_passwd, allow_tls_fallback,
       @@ -78,6 +78,7 @@
       self._allow_tls_fallback = allow_tls_fallback
       self._requires_email = requires_email
       self._force_no_pagination = force_no_pagination
       + self._user_filter = ldap_user_filter
      
      Note: user_rdn is a list of RDN pieces (for historical reasons), and secondary_user_rds is a list of RDN strings.
       @@ -114,6 +115,9 @@
       query = u'(|( {0}={2}{3})({1}={2}{3}))'.format(self._uid_attr, self._email_attr,
       escape_filter_chars(username_or_email),
       suffix)
       + if self._user_filter is not None:
       + query = u'(&({0}
      )
      
      {1})'.format(self._user_filter, query)
       +
       logger.debug('Conducting user search: %s under %s', query, user_search_dn)
       try:
       return (conn.search_s(user_search_dn, ldap.SCOPE_SUBTREE, query.encode('utf-8')), None)
       @@ -124,6 +128,8 @@
       
       try:
       subquery = u'(%s=%s)' % (self._uid_attr, username_or_email)
       + if self._user_filter is not None:
       + subquery = u'(&({0}){1}
      )'.format(self._user_filter, subquery)
       return (conn.search_s(referral_dn, ldap.SCOPE_BASE, subquery), None)
       except ldap.LDAPError:
       logger.debug('LDAP referral search exception')
       @@ -332,6 +338,8 @@
       has_pagination = not(self._force_no_pagination or disable_pagination)
       with self._ldap.get_connection() as conn:
       search_flt = filter_format('(memberOf=%s,%s)', (group_dn, self._base_dn))
       + if self._user_filter is not None:
       + search_flt = u'(&(
      
      {0}
      )
      
      {1}
      )'.format(self._user_filter, search_flt)
       attributes = [self._uid_attr, self._email_attr]
      for user_search_dn in self._user_dns:
       diff -uar quay-registry.orig/data/users/_init.py quay-registry/data/users/init_.py
       — quay-registry.orig/data/users/_init_.py 2019-06-17 14:35:19.041969425 +0200
       +++ quay-registry/data/users/_init_.py 2019-06-17 14:55:04.450570798 +0200
       @@ -54,12 +54,13 @@
       secondary_user_rdns = config.get('LDAP_SECONDARY_USER_RDNS', [])
       timeout = config.get('LDAP_TIMEOUT')
       network_timeout = config.get('LDAP_NETWORK_TIMEOUT')
       + ldap_user_filter = config.get('LDAP_USER_FILTER', None)
      allow_tls_fallback = config.get('LDAP_ALLOW_INSECURE_FALLBACK', False)
       return LDAPUsers(ldap_uri, base_dn, admin_dn, admin_passwd, user_rdn, uid_attr, email_attr,
       allow_tls_fallback, secondary_user_rdns=secondary_user_rdns,
       requires_email=features.MAILING, timeout=timeout,
      
      network_timeout=network_timeout)
       + network_timeout=network_timeout, ldap_user_filter=ldap_user_filter)
      if authentication_type == 'JWT':
       verify_url = config.get('JWT_VERIFY_ENDPOINT'

       

       

      Thanks!

              jschorr Joseph Schorr (Inactive)
              rhn-support-ibazulic Ivan Bazulic
              Votes:
              1 Vote for this issue
              Watchers:
              7 Start watching this issue

                Created:
                Updated:
                Resolved: