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

LDAP detected super user are rejected from creating organizations unless explicitly defined in SUPER_USERS

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: Major Major
    • None
    • None
    • quay, quay-ui
    • False
    • Hide

      None

      Show
      None
    • False
    • Management Announcements

      A Super User (detected by LDAP_SUPERUSER_FILTER), that is not part of LDAP_RESTRICTED_USER_FILTER result set is rejected from creating organization, when he is not explicitly set in SUPER_USERS lists. Super user is corrently identified in UI and logs as super user.

      Defining static users in SUPER_USERS makes management of Quay cumbersome, that's why the LDAP filters were introduced. In this case it is ignored.

      Prerequisites:

      • Enable debug log possitibilities (DEBUGLOG + USERS_DEBUG) for analysis
      • LDAP super user is matching LDAP_USER_FILTER + LDAP_SUPERUSER_FILTER (jdoe)
      • config-bundle configuration
        • AUTHENTICATION_TYPE is LDAP
        • FEATURE_RESTRICTED_USERS is true
        • FEATURE_SUPER_USERS is true
        • LDAP_USER_FILTER contains jdoe (super user) in resultset (checks for super user + restricted group memberships)
          • (|(memberOf=CN=System-Admins,OU=Users,OU=Groups,OU=Lab,DC=domain,DC=redacted)(memberOf=CN=Admins-Quay,OU=Administrators,OU=Groups,OU=Lab,DC=domain,DC=redacted)(memberOf=CN=Openshift-ReadOnly,OU=Services,OU=Groups,OU=Lab,DC=domain,DC=redacted))
        • LDAP_SUPERUSER_FILTER contains jdoe in resultset (checks for super user group memberships)
          • (|(memberOf=CN=System-Admins,OU=Users,OU=Groups,OU=Lab,DC=domain,DC=redacted)(memberOf=CN=Admins-Quay,OU=Administrators,OU=Groups,OU=Lab,DC=domain,DC=redacted))
        • LDAP_RESTRICTED_USER_FILTER does not contain jdoe in resultset (checks for restricted group memberships)
          • (|(memberOf=CN=Openshift-ReadOnly,OU=Services,OU=Groups,OU=Lab,DC=domain,DC=redacted))
        • SUPER_USERS is explicitly *NOT * used

      Reproduction:

      • Login with jdoe (super user) into UI
      • Create new organization
      • User is rejected with 403 response
        {
            "detail": "Unauthorized",
            "error_message": "Unauthorized",
            "error_type": "insufficient_scope",
            "title": "insufficient_scope",
            "type": "https://registry.apps.lab.acp.domain.redacted/api/v1/error/insufficient_scope",
            "status": 403
        }
        

      Log analysis (redacted logs attached):

      • Organization request detected (735079e0-6d80-4c07-8c9a-e2fa4d3378d9)
        gunicorn-web stdout | 2025-11-05 06:48:45,495 [258] [DEBUG] [app] Starting request: urn:request:735079e0-6d80-4c07-8c9a-e2fa4d3378d9 (/api/v1/organization/) {'X-Forwarded-For': 'y.y.y.1, x.x.x.2'}
        ...
        gunicorn-web stdout | 2025-11-05 06:48:45,517 [258] [DEBUG] [auth.permissions] Identity loaded: <QuayDeferredPermissionUser id="f35b563d-9bb2-4d3d-919f-158e2d10ed02" auth_type="user_uuid" provides=set()>
        gunicorn-web stdout | 2025-11-05 06:48:45,517 [258] [DEBUG] [auth.permissions] Deferring permissions for user with uuid: f35b563d-9bb2-4d3d-919f-158e2d10ed02
        ...
        
      • Check for restricted user does not provide resultset (as it does not match LDAP_RESTRICTED_USER_FILTER) > OK
        gunicorn-web stdout | 2025-11-05 06:48:45,535 [258] [DEBUG] [data.users.externalldap] Looking up LDAP restricted user username or email jdoe
        gunicorn-web stdout | 2025-11-05 06:48:45,647 [258] [DEBUG] [data.users.externalldap] Incoming username or email param: 'jdoe'
        gunicorn-web stdout | 2025-11-05 06:48:45,648 [258] [DEBUG] [data.users.externalldap] Conducting user search: (&(&(|(sAMAccountName=jdoe)(mail=jdoe))(|(memberOf=CN=System-Admins,OU=Users,OU=Groups,OU=Lab,DC=domain,DC=redacted)(memberOf=CN=Admins-Quay,OU=Administrators,OU=Groups,OU=Lab,DC=domain,DC=redacted)(memberOf=CN=Openshift-ReadOnly,OU=Services,OU=Groups,OU=Lab,DC=domain,DC=redacted)))(|(memberOf=CN=Openshift-ReadOnly,OU=Services,OU=Groups,OU=Lab,DC=domain,DC=redacted))) under OU=Users,OU=Lab,DC=domain,DC=redacted
        gunicorn-web stdout | 2025-11-05 06:48:45,650 [258] [DEBUG] [data.users.externalldap] Found matching DNs: []
        gunicorn-web stdout | 2025-11-05 06:48:45,652 [258] [DEBUG] [data.users.externalldap] LDAP user jdoe not found: Invalid username or password.
        gunicorn-web stdout | 2025-11-05 06:48:45,654 [258] [DEBUG] [auth.permissions] Loading user permissions after deferring for: f35b563d-9bb2-4d3d-919f-158e2d10ed02
        gunicorn-web stdout | 2025-11-05 06:48:45,654 [258] [DEBUG] [auth.permissions] User permission: _UserTypeNeed(type='user', username='jdoe', role='admin')
        gunicorn-web stdout | 2025-11-05 06:48:45,654 [258] [DEBUG] [auth.permissions] User namespace permission: _NamespaceWideNeed(type='organization', namespace='jdoe', role='admin')
        gunicorn-web stdout | 2025-11-05 06:48:45,654 [258] [DEBUG] [auth.permissions] User namespace repo permission: _NamespaceWideNeed(type='organizationrepo', namespace='jdoe', role='admin')
        
      • Check for super provides logged in user (as it matches LDAP_SUPERUSER_FILTER) > OK
        gunicorn-web stdout | 2025-11-05 06:48:45,664 [258] [DEBUG] [data.users.externalldap] Looking up LDAP superuser username or email jdoe
        gunicorn-web stdout | 2025-11-05 06:48:45,757 [258] [DEBUG] [data.users.externalldap] Incoming username or email param: 'jdoe'
        gunicorn-web stdout | 2025-11-05 06:48:45,757 [258] [DEBUG] [data.users.externalldap] Conducting user search: (&(&(|(sAMAccountName=jdoe)(mail=jdoe))(|(memberOf=CN=System-Admins,OU=Users,OU=Groups,OU=Lab,DC=domain,DC=redacted)(memberOf=CN=Admins-Quay,OU=Administrators,OU=Groups,OU=Lab,DC=domain,DC=redacted)(memberOf=CN=Openshift-ReadOnly,OU=Services,OU=Groups,OU=Lab,DC=domain,DC=redacted)))(|(memberOf=CN=System-Admins,OU=Users,OU=Groups,OU=Lab,DC=domain,DC=redacted)(memberOf=CN=Admins-Quay,OU=Administrators,OU=Groups,OU=Lab,DC=domain,DC=redacted))) under OU=Users,OU=Lab,DC=domain,DC=redacted
        gunicorn-web stdout | 2025-11-05 06:48:45,763 [258] [DEBUG] [data.users.externalldap] Found matching DNs: ['CN=john doe,OU=Operations,OU=People,OU=Users,OU=Lab,DC=domain,DC=redacted']
        gunicorn-web stdout | 2025-11-05 06:48:45,766 [258] [DEBUG] [data.users.externalldap] Found superuser for LDAP username or email jdoe
        gunicorn-web stdout | 2025-11-05 06:48:45,767 [258] [DEBUG] [auth.permissions] Adding superuser to user: jdoe
        
      • Check for global read only super user provides empty resultset (LDAP_GLOBAL_READONLY_SUPERUSER_FILTER is unconfigured) > OK
        gunicorn-web stdout | 2025-11-05 06:48:45,780 [258] [DEBUG] [data.users.externalldap] Looking up LDAP global readonly superuser username or email jdoe
        gunicorn-web stdout | 2025-11-05 06:48:45,860 [258] [DEBUG] [data.users.externalldap] Incoming username or email param: 'jdoe'
        gunicorn-web stdout | 2025-11-05 06:48:45,862 [258] [DEBUG] [data.users.externalldap] LDAP global readonly superuser jdoe not found: Global readonly superuser username not found
        gunicorn-web stdout | 2025-11-05 06:48:45,863 [258] [DEBUG] [endpoints.api] Checking permission <class 'auth.permissions.UserAdminPermission'> for user jdoe
        gunicorn-web stdout | 2025-11-05 06:48:45,863 [258] [DEBUG] [auth.permissions] Loading user permissions after deferring for: f35b563d-9bb2-4d3d-919f-158e2d10ed02
        
      • Another check for restricted user does not provide resultset (as it does not match LDAP_RESTRICTED_USER_FILTER) > OK
        gunicorn-web stdout | 2025-11-05 06:48:45,871 [258] [DEBUG] [data.users.externalldap] Looking up LDAP restricted user username or email jdoe
        gunicorn-web stdout | 2025-11-05 06:48:45,949 [258] [DEBUG] [data.users.externalldap] Incoming username or email param: 'jdoe'
        gunicorn-web stdout | 2025-11-05 06:48:45,949 [258] [DEBUG] [data.users.externalldap] Conducting user search: (&(&(|(sAMAccountName=jdoe)(mail=jdoe))(|(memberOf=CN=System-Admins,OU=Users,OU=Groups,OU=Lab,DC=domain,DC=redacted)(memberOf=CN=Admins-Quay,OU=Administrators,OU=Groups,OU=Lab,DC=domain,DC=redacted)(memberOf=CN=Openshift-ReadOnly,OU=Services,OU=Groups,OU=Lab,DC=domain,DC=redacted)))(|(memberOf=CN=Openshift-ReadOnly,OU=Services,OU=Groups,OU=Lab,DC=domain,DC=redacted))) under OU=Users,OU=Lab,DC=domain,DC=redacted
        gunicorn-web stdout | 2025-11-05 06:48:45,951 [258] [DEBUG] [data.users.externalldap] Found matching DNs: []
        gunicorn-web stdout | 2025-11-05 06:48:45,954 [258] [DEBUG] [data.users.externalldap] LDAP user jdoe not found: Invalid username or password.
        
      • Directly after the last restricted user check is performed the request is rejected with 403 and missing permissions > NOK
        gunicorn-web stdout | 2025-11-05 06:48:45,955 [258] [DEBUG] [app] Ending request: urn:request:735079e0-6d80-4c07-8c9a-e2fa4d3378d9 (/api/v1/organization/) {'endpoint': 'api.organizationlist', 'request_id': 'urn:request:735079e0-6d80-4c07-8c9a-e2fa4d3378d9', 'remote_addr': 'x.x.x.2', 'http_method': 'POST', 'original_url': 'https://registry.apps.lab.acp.domain.redacted/api/v1/organization/', 'path': '/api/v1/organization/', 'parameters': {}, 'json_body': {'name': 'new_org'}, 'confsha': 'b3cb3175', 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0'}
        

      Files:

              Unassigned Unassigned
              p.chlebicki@bacher.at Philipp Chlebicki
              Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

                Created:
                Updated: