[GH-ISSUE #1324] [BUG] LLDAP 0.6.2 "invalid attribute memberof" #462

Closed
opened 2026-02-27 08:17:25 +03:00 by kerem · 2 comments
Owner

Originally created by @Mindar on GitHub (Oct 11, 2025).
Original GitHub issue: https://github.com/lldap/lldap/issues/1324

Describe the bug
I have a dockerized setup with lldap, postgres and pgadmin. Pgadmin uses lldap as its account source. Recently I set up a new server with a newer version of lldap (previously 0.6.1, now 0.6.2) (also updated pgadmin from 9.2 to 9.8) and now the setup no longer works.

When I try to log into pgadmin using ldap authentication, pgadmin will fail to log me into my account and show this error message:

Image

Additionally a error message is printed to docker logs by pgadmin (see below).

I have tested several configurations and versions:

  • Error happens with lldap v0.6.2 with pgadmin 9.8 or pgadmin 9.2
  • No issue with lldap v0.6.1 with pgadmin 9.8 or pgadmin 9.2 with otherwise same config

It works correctly with the same config and docker compose file for lldap v0.6.1

To Reproduce

Set up dockerized lldap:stable, pgadmin and postgresql with the following pgadmin ldap config:

environment:
      # LDAP
      PGADMIN_CONFIG_LDAP_SERVER_URI:         '"ldap://lldap:3890"'
      PGADMIN_CONFIG_AUTHENTICATION_SOURCES:  '["internal", "ldap"]'
      PGADMIN_CONFIG_LDAP_USERNAME_ATTRIBUTE: '"uid"'
      PGADMIN_CONFIG_LDAP_BASE_DN: '"ou=people,dc=example,dc=com"'
      PGADMIN_CONFIG_LDAP_SEARCH_BASE_DN: '"ou=people,dc=example,dc=com"'
      PGADMIN_CONFIG_LDAP_BIND_USER: '"uid=admin,ou=people,dc=example,dc=com"'
      PGADMIN_CONFIG_LDAP_BIND_PASSWORD: '"password"'
      PGADMIN_CONFIG_LDAP_SEARCH_FILTER: '"(memberof=cn=postgres_admin,ou=groups,dc=example,dc=com)"'

Expected behavior
pgadmin is able to use memberof.

Logs
lldap:

lldap-1  | 2025-10-11T13:48:04.419243969+00:00  INFO     LDAP request [ 134ms | 0.09% / 100.00% ] session_id: 1e62cc95-8721-4cf8-a78c-6d2e7f4303dd
lldap-1  | 2025-10-11T13:48:04.419259112+00:00  DEBUG    ┝━ 🐛 [debug]:  | msg: LdapMsg { msgid: 9, op: BindRequest(LdapBindRequest { dn: "uid=admin,ou=people,dc=example,dc=com", cred: LdapBindCred::Simple }), ctrl: [] }
lldap-1  | 2025-10-11T13:48:04.419268334+00:00  DEBUG    ┝━ do_bind [ 134ms | 0.08% / 99.91% ] dn: uid=admin,ou=people,dc=example,dc=com
lldap-1  | 2025-10-11T13:48:04.419301112+00:00  DEBUG    │  ┝━ bind [ 133ms | 0.05% / 99.04% ]
lldap-1  | 2025-10-11T13:48:04.419327501+00:00  DEBUG    │  │  ┝━ get_password_file_for_user [ 1.29ms | 0.96% ] user_id: "admin"
lldap-1  | 2025-10-11T13:48:04.422220465+00:00  INFO     │  │  ┝━ i [info]: Login attempt for "admin"
lldap-1  | 2025-10-11T13:48:04.422227056+00:00  DEBUG    │  │  ┕━ passwords_match [ 132ms | 98.04% ] username: admin
lldap-1  | 2025-10-11T13:48:04.553973821+00:00  DEBUG    │  ┝━ get_user_groups [ 1.06ms | 0.79% ] user_id: "admin"
lldap-1  | 2025-10-11T13:48:04.557943985+00:00  DEBUG    │  │  ┕━ 🐛 [debug]:  | return: {GroupDetails { group_id: 1, display_name: "lldap_admin", creation_date: 2025-10-10T20:31:14.939907, uuid: "8b6b4962-0ee5-3f9d-a1a3-9d8357430a62", attributes: [] }}
lldap-1  | 2025-10-11T13:48:04.557968468+00:00  DEBUG    │  ┕━ 🐛 [debug]: Success!
lldap-1  | 2025-10-11T13:48:04.557980402+00:00  DEBUG    ┕━ 🐛 [debug]:  | response: BindResponse(LdapBindResponse { res: LdapResult { code: Success, matcheddn: "", message: "", referral: [] }, saslcreds: None })
lldap-1  | 2025-10-11T13:48:04.561135880+00:00  INFO     LDAP request [ 155µs | 100.00% ] session_id: 1e62cc95-8721-4cf8-a78c-6d2e7f4303dd
lldap-1  | 2025-10-11T13:48:04.561148668+00:00  DEBUG    ┝━ 🐛 [debug]:  | msg: LdapMsg { msgid: 10, op: SearchRequest(LdapSearchRequest { base: "", scope: Base, aliases: Always, sizelimit: 0, timelimit: 0, typesonly: false, filter: Present("objectClass"), attrs: ["altServer", "namingContexts", "supportedControl", "supportedExtension", "supportedFeatures", "supportedCapabilities", "supportedLdapVersion", "supportedSASLMechanisms", "vendorName", "vendorVersion", "subschemaSubentry", "*", "+", "+"] }), ctrl: [] }
lldap-1  | 2025-10-11T13:48:04.561151283+00:00  DEBUG    ┝━ 🐛 [debug]: rootDSE request
lldap-1  | 2025-10-11T13:48:04.561203957+00:00  DEBUG    ┝━ 🐛 [debug]:  | response: SearchResultEntry(LdapSearchResultEntry { dn: "", attributes: [LdapPartialAttribute { atype: "objectClass", vals: ["top"] }, LdapPartialAttribute { atype: "vendorName", vals: ["LLDAP"] }, LdapPartialAttribute { atype: "vendorVersion", vals: ["lldap_0.1.0"] }, LdapPartialAttribute { atype: "supportedLDAPVersion", vals: ["3"] }, LdapPartialAttribute { atype: "supportedExtension", vals: ["1.3.6.1.4.1.4203.1.11.1", "1.3.6.1.4.1.4203.1.11.3"] }, LdapPartialAttribute { atype: "supportedControl", vals: [] }, LdapPartialAttribute { atype: "supportedFeatures", vals: ["1.3.6.1.4.1.4203.1.5.1"] }, LdapPartialAttribute { atype: "defaultNamingContext", vals: ["dc=example,dc=com"] }, LdapPartialAttribute { atype: "namingContexts", vals: ["dc=example,dc=com"] }, LdapPartialAttribute { atype: "isGlobalCatalogReady", vals: ["false"] }, LdapPartialAttribute { atype: "subschemaSubentry", vals: ["cn=Subschema"] }] })
lldap-1  | 2025-10-11T13:48:04.561279682+00:00  DEBUG    ┕━ 🐛 [debug]:  | response: SearchResultDone(LdapResult { code: Success, matcheddn: "", message: "", referral: [] })
lldap-1  | 2025-10-11T13:48:04.606368290+00:00  INFO     LDAP request [ 1.95ms | 100.00% ] session_id: 1e62cc95-8721-4cf8-a78c-6d2e7f4303dd
lldap-1  | 2025-10-11T13:48:04.606397050+00:00  DEBUG    ┝━ 🐛 [debug]:  | msg: LdapMsg { msgid: 11, op: SearchRequest(LdapSearchRequest { base: "cn=Subschema", scope: Base, aliases: Always, sizelimit: 0, timelimit: 0, typesonly: false, filter: Equality("objectClass", "subschema"), attrs: ["objectClasses", "attributeTypes", "ldapSyntaxes", "matchingRules", "matchingRuleUse", "dITContentRules", "dITStructureRules", "nameForms", "createTimestamp", "modifyTimestamp", "*", "+"] }), ctrl: [] }
lldap-1  | 2025-10-11T13:48:04.606402827+00:00  DEBUG    ┝━ 🐛 [debug]: Schema request
lldap-1  | 2025-10-11T13:48:04.609121823+00:00  DEBUG    ┝━ 🐛 [debug]:  | response: SearchResultEntry(LdapSearchResultEntry { dn: "cn=Subschema", attributes: [LdapPartialAttribute { atype: "structuralObjectClass", vals: ["subentry"] }, LdapPartialAttribute { atype: "objectClass", vals: ["top", "subentry", "subschema", "extensibleObject"] }, LdapPartialAttribute { atype: "cn", vals: ["Subschema"] }, LdapPartialAttribute { atype: "createTimestamp", vals: ["20251011134804Z"] }, LdapPartialAttribute { atype: "modifyTimestamp", vals: ["20251011134804Z"] }, LdapPartialAttribute { atype: "ldapSyntaxes", vals: ["( 1.3.6.1.1.16.1 DESC 'UUID' )", "( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )", "( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )", "( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )", "( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )", "( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )", "( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' X-NOT-HUMAN-READABLE 'TRUE' )", "( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )", "( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )", "( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )", "( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )", "( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )"] }, LdapPartialAttribute { atype: "matchingRules", vals: ["( 1.3.6.1.1.16.2 NAME 'UUIDMatch' SYNTAX 1.3.6.1.1.16.1 )", "( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' SYNTAX 1.3.6.1.1.16.1 )", "( 2.5.13.0 NAME 'objectIdentifierMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )", "( 2.5.13.1 NAME 'distinguishedNameMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )", "( 2.5.13.2 NAME 'caseIgnoreMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", "( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", "( 2.5.13.23 NAME 'uniqueMemberMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )", "( 2.5.13.27 NAME 'generalizedTimeMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )", "( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )", "( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )"] }, LdapPartialAttribute { atype: "attributeTypes", vals: ["( 0.9.2342.19200300.100.1.1 NAME ( 'uid' 'userid' 'user_id' ) DESC 'RFC4519: user identifier' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} SINGLE-VALUE NO-USER-MODIFICATION )", "( 1.3.6.1.1.16.4 NAME ( 'entryUUID' 'uuid' ) DESC 'UUID of the entry' EQUALITY UUIDMatch ORDERING UUIDOrderingMatch SYNTAX 1.3.6.1.1.16.1 SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )", "( 1.3.6.1.4.1.1466.101.120.16 NAME 'ldapSyntaxes' DESC 'RFC4512: LDAP syntaxes' EQUALITY objectIdentifierFirstComponentMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.54 USAGE directoryOperation )", "( 2.5.4.0 NAME 'objectClass' DESC 'RFC4512: object classes of the entity' EQUALITY objectIdentifierMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )", "( 2.5.4.3 NAME ( 'cn' 'commonName' 'display_name' ) DESC 'RFC4519: common name(s) for which the entity is known by' SUP name SINGLE-VALUE )", "( 2.5.4.4 NAME ( 'sn' 'surname' 'last_name' ) DESC 'RFC2256: last (family) name(s) for which the entity is known by' SUP name SINGLE-VALUE )", "( 2.5.4.11 NAME ( 'ou' 'organizationalUnitName' ) DESC 'RFC2256: organizational unit this object belongs to' SUP name )", "( 2.5.4.41 NAME 'name' DESC 'RFC4519: common supertype of name attributes' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )", "( 2.5.4.49 NAME 'distinguishedName' DESC 'RFC4519: common supertype of DN attributes' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )", "( 2.5.4.50 NAME ( 'uniqueMember' 'member' ) DESC 'RFC2256: unique member of a group' EQUALITY uniqueMemberMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )", "( 2.5.18.1 NAME ( 'createTimestamp' 'creation_date' ) DESC 'RFC4512: time which object was created' EQUALITY generalizedTimeMatch ORDERING generalizedTimeOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )", "( 2.5.18.2 NAME 'modifyTimestamp' DESC 'RFC4512: time which object was last modified' EQUALITY generalizedTimeMatch ORDERING generalizedTimeOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )", "( 2.5.21.5 NAME 'attributeTypes' DESC 'RFC4512: attribute types' EQUALITY objectIdentifierFirstComponentMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.3 USAGE directoryOperation )", "( 2.5.21.6 NAME 'objectClasses' DESC 'RFC4512: object classes' EQUALITY objectIdentifierFirstComponentMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.37 USAGE directoryOperation )", "( 2.5.21.9 NAME 'structuralObjectClass' DESC 'RFC4512: structural object class of entry' EQUALITY objectIdentifierMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )", "( 10.0 NAME 'String' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", "( 10.1 NAME 'Integer' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", "( 10.2 NAME 'JpegPhoto' SYNTAX 1.3.6.1.4.1.1466.115.121.1.28 )", "( 10.3 NAME 'DateTime' SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )", "( 10.19 NAME 'avatar' DESC 'LLDAP: builtin attribute' SUP JpegPhoto )", "( 10.20 NAME 'first_name' DESC 'LLDAP: builtin attribute' SUP String )", "( 10.21 NAME 'mail' DESC 'LLDAP: builtin attribute' SUP String )", "( 10.22 NAME 'group_id' DESC 'LLDAP: builtin attribute' SUP Integer )"] }, LdapPartialAttribute { atype: "objectClasses", vals: ["( 3.0 NAME ( 'inetOrgPerson' 'posixAccount' 'mailAccount' 'person' ) DESC 'LLDAP builtin: a person' STRUCTURAL MUST ( mail $ user_id ) MAY ( avatar $ creation_date $ display_name $ first_name $ last_name $ uuid ) )", "( 3.1 NAME ( 'groupOfUniqueNames' 'groupOfNames' ) DESC 'LLDAP builtin: a group' STRUCTURAL MUST ( display_name ) MAY ( creation_date $ group_id $ uuid ) )"] }, LdapPartialAttribute { atype: "subschemaSubentry", vals: ["cn=Subschema"] }] })
lldap-1  | 2025-10-11T13:48:04.609467039+00:00  DEBUG    ┕━ 🐛 [debug]:  | response: SearchResultDone(LdapResult { code: Success, matcheddn: "", message: "", referral: [] })
lldap-1  | 2025-10-11T13:48:25.372657532+00:00  INFO     i [info]: LDAP session start: aa95cb9a-a6ce-422f-b87d-21edcf21ac92
lldap-1  | 2025-10-11T13:48:25.372971832+00:00  INFO     LDAP request [ 1.72ms | 100.00% ] session_id: aa95cb9a-a6ce-422f-b87d-21edcf21ac92
lldap-1  | 2025-10-11T13:48:25.374448428+00:00  DEBUG    ┝━ 🐛 [debug]:  | msg: LdapMsg { msgid: 0, op: SearchRequest(LdapSearchRequest { base: "", scope: Base, aliases: Never, sizelimit: 0, timelimit: 0, typesonly: false, filter: Present("objectClass"), attrs: ["supportedExtension"] }), ctrl: [] }
lldap-1  | 2025-10-11T13:48:25.374455132+00:00  DEBUG    ┝━ 🐛 [debug]: rootDSE request
lldap-1  | 2025-10-11T13:48:25.374556233+00:00  DEBUG    ┝━ 🐛 [debug]:  | response: SearchResultEntry(LdapSearchResultEntry { dn: "", attributes: [LdapPartialAttribute { atype: "objectClass", vals: ["top"] }, LdapPartialAttribute { atype: "vendorName", vals: ["LLDAP"] }, LdapPartialAttribute { atype: "vendorVersion", vals: ["lldap_0.1.0"] }, LdapPartialAttribute { atype: "supportedLDAPVersion", vals: ["3"] }, LdapPartialAttribute { atype: "supportedExtension", vals: ["1.3.6.1.4.1.4203.1.11.1", "1.3.6.1.4.1.4203.1.11.3"] }, LdapPartialAttribute { atype: "supportedControl", vals: [] }, LdapPartialAttribute { atype: "supportedFeatures", vals: ["1.3.6.1.4.1.4203.1.5.1"] }, LdapPartialAttribute { atype: "defaultNamingContext", vals: ["dc=example,dc=com"] }, LdapPartialAttribute { atype: "namingContexts", vals: ["dc=example,dc=com"] }, LdapPartialAttribute { atype: "isGlobalCatalogReady", vals: ["false"] }, LdapPartialAttribute { atype: "subschemaSubentry", vals: ["cn=Subschema"] }] })
lldap-1  | 2025-10-11T13:48:25.374659764+00:00  DEBUG    ┕━ 🐛 [debug]:  | response: SearchResultDone(LdapResult { code: Success, matcheddn: "", message: "", referral: [] })
lldap-1  | 2025-10-11T13:48:25.374988166+00:00  INFO     i [info]: LDAP session end: aa95cb9a-a6ce-422f-b87d-21edcf21ac92
lldap-1  | 2025-10-11T13:48:25.375180257+00:00  DEBUG    HTTP request [ 23.5µs | 100.00% ] method: "GET" | uri: "/health"
lldap-1  | 2025-10-11T13:48:25.375205181+00:00  DEBUG    ┕━ 🐛 [debug]:  | status_code: 200


pgadmin:

pgadmin_container  | 2025-10-10 20:49:42,566: ERROR	pgadmin:	Error searching the LDAP directory: invalid attribute memberof
pgadmin_container  | Traceback (most recent call last):
pgadmin_container  |   File "/pgadmin4/pgadmin/authenticate/ldap.py", line 287, in search_ldap_user
pgadmin_container  |     self.conn.search(search_base=search_base_dn,
pgadmin_container  |   File "/venv/lib/python3.12/site-packages/ldap3/core/connection.py", line 838, in search
pgadmin_container  |     request = search_operation(search_base,
pgadmin_container  |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pgadmin_container  |   File "/venv/lib/python3.12/site-packages/ldap3/operation/search.py", line 371, in search_operation
pgadmin_container  |     request['filter'] = compile_filter(parse_filter(search_filter, schema, auto_escape, auto_encode, validator, check_names).elements[0])  # parse the searchFilter string and compile it starting from the root node
pgadmin_container  |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pgadmin_container  |   File "/venv/lib/python3.12/site-packages/ldap3/operation/search.py", line 205, in parse_filter
pgadmin_container  |     current_node.append(evaluate_match(search_filter[start_pos:end_pos], schema, auto_escape, auto_encode, validator, check_names))
pgadmin_container  |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pgadmin_container  |   File "/venv/lib/python3.12/site-packages/ldap3/operation/search.py", line 165, in evaluate_match
pgadmin_container  |     assertion = {'attr': left_part, 'value': validate_assertion_value(schema, left_part, right_part, auto_escape, auto_encode, validator, check_names)}
pgadmin_container  |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pgadmin_container  |   File "/venv/lib/python3.12/site-packages/ldap3/protocol/convert.py", line 159, in validate_assertion_value
pgadmin_container  |     value = validate_attribute_value(schema, name, value, auto_encode, validator=validator, check_names=check_names)
pgadmin_container  |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pgadmin_container  |   File "/venv/lib/python3.12/site-packages/ldap3/protocol/convert.py", line 175, in validate_attribute_value
pgadmin_container  |     raise LDAPAttributeError('invalid attribute ' + name)
pgadmin_container  | ldap3.core.exceptions.LDAPAttributeError: invalid attribute memberof

Additional context
No additional context.

Originally created by @Mindar on GitHub (Oct 11, 2025). Original GitHub issue: https://github.com/lldap/lldap/issues/1324 **Describe the bug** I have a dockerized setup with lldap, postgres and pgadmin. Pgadmin uses lldap as its account source. Recently I set up a new server with a newer version of lldap (previously 0.6.1, now 0.6.2) (also updated pgadmin from 9.2 to 9.8) and now the setup no longer works. When I try to log into pgadmin using ldap authentication, pgadmin will fail to log me into my account and show this error message: <img width="441" height="73" alt="Image" src="https://github.com/user-attachments/assets/72c41d96-f835-45d4-9490-47ec3e249392" /> Additionally a error message is printed to docker logs by pgadmin (see below). I have tested several configurations and versions: - **Error happens with lldap v0.6.2** with pgadmin 9.8 or pgadmin 9.2 - **No issue with lldap v0.6.1** with pgadmin 9.8 or pgadmin 9.2 with otherwise same config It works correctly with the same config and docker compose file for lldap v0.6.1 **To Reproduce** Set up dockerized lldap:stable, pgadmin and postgresql with the following pgadmin ldap config: ```yaml environment: # LDAP PGADMIN_CONFIG_LDAP_SERVER_URI: '"ldap://lldap:3890"' PGADMIN_CONFIG_AUTHENTICATION_SOURCES: '["internal", "ldap"]' PGADMIN_CONFIG_LDAP_USERNAME_ATTRIBUTE: '"uid"' PGADMIN_CONFIG_LDAP_BASE_DN: '"ou=people,dc=example,dc=com"' PGADMIN_CONFIG_LDAP_SEARCH_BASE_DN: '"ou=people,dc=example,dc=com"' PGADMIN_CONFIG_LDAP_BIND_USER: '"uid=admin,ou=people,dc=example,dc=com"' PGADMIN_CONFIG_LDAP_BIND_PASSWORD: '"password"' PGADMIN_CONFIG_LDAP_SEARCH_FILTER: '"(memberof=cn=postgres_admin,ou=groups,dc=example,dc=com)"' ``` **Expected behavior** pgadmin is able to use `memberof`. **Logs** lldap: ```lldap-1 | 2025-10-11T13:48:04.416818135+00:00 INFO i [info]: LDAP session start: 1e62cc95-8721-4cf8-a78c-6d2e7f4303dd lldap-1 | 2025-10-11T13:48:04.419243969+00:00 INFO LDAP request [ 134ms | 0.09% / 100.00% ] session_id: 1e62cc95-8721-4cf8-a78c-6d2e7f4303dd lldap-1 | 2025-10-11T13:48:04.419259112+00:00 DEBUG ┝━ 🐛 [debug]: | msg: LdapMsg { msgid: 9, op: BindRequest(LdapBindRequest { dn: "uid=admin,ou=people,dc=example,dc=com", cred: LdapBindCred::Simple }), ctrl: [] } lldap-1 | 2025-10-11T13:48:04.419268334+00:00 DEBUG ┝━ do_bind [ 134ms | 0.08% / 99.91% ] dn: uid=admin,ou=people,dc=example,dc=com lldap-1 | 2025-10-11T13:48:04.419301112+00:00 DEBUG │ ┝━ bind [ 133ms | 0.05% / 99.04% ] lldap-1 | 2025-10-11T13:48:04.419327501+00:00 DEBUG │ │ ┝━ get_password_file_for_user [ 1.29ms | 0.96% ] user_id: "admin" lldap-1 | 2025-10-11T13:48:04.422220465+00:00 INFO │ │ ┝━ i [info]: Login attempt for "admin" lldap-1 | 2025-10-11T13:48:04.422227056+00:00 DEBUG │ │ ┕━ passwords_match [ 132ms | 98.04% ] username: admin lldap-1 | 2025-10-11T13:48:04.553973821+00:00 DEBUG │ ┝━ get_user_groups [ 1.06ms | 0.79% ] user_id: "admin" lldap-1 | 2025-10-11T13:48:04.557943985+00:00 DEBUG │ │ ┕━ 🐛 [debug]: | return: {GroupDetails { group_id: 1, display_name: "lldap_admin", creation_date: 2025-10-10T20:31:14.939907, uuid: "8b6b4962-0ee5-3f9d-a1a3-9d8357430a62", attributes: [] }} lldap-1 | 2025-10-11T13:48:04.557968468+00:00 DEBUG │ ┕━ 🐛 [debug]: Success! lldap-1 | 2025-10-11T13:48:04.557980402+00:00 DEBUG ┕━ 🐛 [debug]: | response: BindResponse(LdapBindResponse { res: LdapResult { code: Success, matcheddn: "", message: "", referral: [] }, saslcreds: None }) lldap-1 | 2025-10-11T13:48:04.561135880+00:00 INFO LDAP request [ 155µs | 100.00% ] session_id: 1e62cc95-8721-4cf8-a78c-6d2e7f4303dd lldap-1 | 2025-10-11T13:48:04.561148668+00:00 DEBUG ┝━ 🐛 [debug]: | msg: LdapMsg { msgid: 10, op: SearchRequest(LdapSearchRequest { base: "", scope: Base, aliases: Always, sizelimit: 0, timelimit: 0, typesonly: false, filter: Present("objectClass"), attrs: ["altServer", "namingContexts", "supportedControl", "supportedExtension", "supportedFeatures", "supportedCapabilities", "supportedLdapVersion", "supportedSASLMechanisms", "vendorName", "vendorVersion", "subschemaSubentry", "*", "+", "+"] }), ctrl: [] } lldap-1 | 2025-10-11T13:48:04.561151283+00:00 DEBUG ┝━ 🐛 [debug]: rootDSE request lldap-1 | 2025-10-11T13:48:04.561203957+00:00 DEBUG ┝━ 🐛 [debug]: | response: SearchResultEntry(LdapSearchResultEntry { dn: "", attributes: [LdapPartialAttribute { atype: "objectClass", vals: ["top"] }, LdapPartialAttribute { atype: "vendorName", vals: ["LLDAP"] }, LdapPartialAttribute { atype: "vendorVersion", vals: ["lldap_0.1.0"] }, LdapPartialAttribute { atype: "supportedLDAPVersion", vals: ["3"] }, LdapPartialAttribute { atype: "supportedExtension", vals: ["1.3.6.1.4.1.4203.1.11.1", "1.3.6.1.4.1.4203.1.11.3"] }, LdapPartialAttribute { atype: "supportedControl", vals: [] }, LdapPartialAttribute { atype: "supportedFeatures", vals: ["1.3.6.1.4.1.4203.1.5.1"] }, LdapPartialAttribute { atype: "defaultNamingContext", vals: ["dc=example,dc=com"] }, LdapPartialAttribute { atype: "namingContexts", vals: ["dc=example,dc=com"] }, LdapPartialAttribute { atype: "isGlobalCatalogReady", vals: ["false"] }, LdapPartialAttribute { atype: "subschemaSubentry", vals: ["cn=Subschema"] }] }) lldap-1 | 2025-10-11T13:48:04.561279682+00:00 DEBUG ┕━ 🐛 [debug]: | response: SearchResultDone(LdapResult { code: Success, matcheddn: "", message: "", referral: [] }) lldap-1 | 2025-10-11T13:48:04.606368290+00:00 INFO LDAP request [ 1.95ms | 100.00% ] session_id: 1e62cc95-8721-4cf8-a78c-6d2e7f4303dd lldap-1 | 2025-10-11T13:48:04.606397050+00:00 DEBUG ┝━ 🐛 [debug]: | msg: LdapMsg { msgid: 11, op: SearchRequest(LdapSearchRequest { base: "cn=Subschema", scope: Base, aliases: Always, sizelimit: 0, timelimit: 0, typesonly: false, filter: Equality("objectClass", "subschema"), attrs: ["objectClasses", "attributeTypes", "ldapSyntaxes", "matchingRules", "matchingRuleUse", "dITContentRules", "dITStructureRules", "nameForms", "createTimestamp", "modifyTimestamp", "*", "+"] }), ctrl: [] } lldap-1 | 2025-10-11T13:48:04.606402827+00:00 DEBUG ┝━ 🐛 [debug]: Schema request lldap-1 | 2025-10-11T13:48:04.609121823+00:00 DEBUG ┝━ 🐛 [debug]: | response: SearchResultEntry(LdapSearchResultEntry { dn: "cn=Subschema", attributes: [LdapPartialAttribute { atype: "structuralObjectClass", vals: ["subentry"] }, LdapPartialAttribute { atype: "objectClass", vals: ["top", "subentry", "subschema", "extensibleObject"] }, LdapPartialAttribute { atype: "cn", vals: ["Subschema"] }, LdapPartialAttribute { atype: "createTimestamp", vals: ["20251011134804Z"] }, LdapPartialAttribute { atype: "modifyTimestamp", vals: ["20251011134804Z"] }, LdapPartialAttribute { atype: "ldapSyntaxes", vals: ["( 1.3.6.1.1.16.1 DESC 'UUID' )", "( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )", "( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )", "( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )", "( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )", "( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )", "( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' X-NOT-HUMAN-READABLE 'TRUE' )", "( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )", "( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )", "( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )", "( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )", "( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )"] }, LdapPartialAttribute { atype: "matchingRules", vals: ["( 1.3.6.1.1.16.2 NAME 'UUIDMatch' SYNTAX 1.3.6.1.1.16.1 )", "( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' SYNTAX 1.3.6.1.1.16.1 )", "( 2.5.13.0 NAME 'objectIdentifierMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )", "( 2.5.13.1 NAME 'distinguishedNameMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )", "( 2.5.13.2 NAME 'caseIgnoreMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", "( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", "( 2.5.13.23 NAME 'uniqueMemberMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )", "( 2.5.13.27 NAME 'generalizedTimeMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )", "( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )", "( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )"] }, LdapPartialAttribute { atype: "attributeTypes", vals: ["( 0.9.2342.19200300.100.1.1 NAME ( 'uid' 'userid' 'user_id' ) DESC 'RFC4519: user identifier' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} SINGLE-VALUE NO-USER-MODIFICATION )", "( 1.3.6.1.1.16.4 NAME ( 'entryUUID' 'uuid' ) DESC 'UUID of the entry' EQUALITY UUIDMatch ORDERING UUIDOrderingMatch SYNTAX 1.3.6.1.1.16.1 SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )", "( 1.3.6.1.4.1.1466.101.120.16 NAME 'ldapSyntaxes' DESC 'RFC4512: LDAP syntaxes' EQUALITY objectIdentifierFirstComponentMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.54 USAGE directoryOperation )", "( 2.5.4.0 NAME 'objectClass' DESC 'RFC4512: object classes of the entity' EQUALITY objectIdentifierMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )", "( 2.5.4.3 NAME ( 'cn' 'commonName' 'display_name' ) DESC 'RFC4519: common name(s) for which the entity is known by' SUP name SINGLE-VALUE )", "( 2.5.4.4 NAME ( 'sn' 'surname' 'last_name' ) DESC 'RFC2256: last (family) name(s) for which the entity is known by' SUP name SINGLE-VALUE )", "( 2.5.4.11 NAME ( 'ou' 'organizationalUnitName' ) DESC 'RFC2256: organizational unit this object belongs to' SUP name )", "( 2.5.4.41 NAME 'name' DESC 'RFC4519: common supertype of name attributes' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )", "( 2.5.4.49 NAME 'distinguishedName' DESC 'RFC4519: common supertype of DN attributes' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )", "( 2.5.4.50 NAME ( 'uniqueMember' 'member' ) DESC 'RFC2256: unique member of a group' EQUALITY uniqueMemberMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )", "( 2.5.18.1 NAME ( 'createTimestamp' 'creation_date' ) DESC 'RFC4512: time which object was created' EQUALITY generalizedTimeMatch ORDERING generalizedTimeOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )", "( 2.5.18.2 NAME 'modifyTimestamp' DESC 'RFC4512: time which object was last modified' EQUALITY generalizedTimeMatch ORDERING generalizedTimeOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )", "( 2.5.21.5 NAME 'attributeTypes' DESC 'RFC4512: attribute types' EQUALITY objectIdentifierFirstComponentMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.3 USAGE directoryOperation )", "( 2.5.21.6 NAME 'objectClasses' DESC 'RFC4512: object classes' EQUALITY objectIdentifierFirstComponentMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.37 USAGE directoryOperation )", "( 2.5.21.9 NAME 'structuralObjectClass' DESC 'RFC4512: structural object class of entry' EQUALITY objectIdentifierMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )", "( 10.0 NAME 'String' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", "( 10.1 NAME 'Integer' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", "( 10.2 NAME 'JpegPhoto' SYNTAX 1.3.6.1.4.1.1466.115.121.1.28 )", "( 10.3 NAME 'DateTime' SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )", "( 10.19 NAME 'avatar' DESC 'LLDAP: builtin attribute' SUP JpegPhoto )", "( 10.20 NAME 'first_name' DESC 'LLDAP: builtin attribute' SUP String )", "( 10.21 NAME 'mail' DESC 'LLDAP: builtin attribute' SUP String )", "( 10.22 NAME 'group_id' DESC 'LLDAP: builtin attribute' SUP Integer )"] }, LdapPartialAttribute { atype: "objectClasses", vals: ["( 3.0 NAME ( 'inetOrgPerson' 'posixAccount' 'mailAccount' 'person' ) DESC 'LLDAP builtin: a person' STRUCTURAL MUST ( mail $ user_id ) MAY ( avatar $ creation_date $ display_name $ first_name $ last_name $ uuid ) )", "( 3.1 NAME ( 'groupOfUniqueNames' 'groupOfNames' ) DESC 'LLDAP builtin: a group' STRUCTURAL MUST ( display_name ) MAY ( creation_date $ group_id $ uuid ) )"] }, LdapPartialAttribute { atype: "subschemaSubentry", vals: ["cn=Subschema"] }] }) lldap-1 | 2025-10-11T13:48:04.609467039+00:00 DEBUG ┕━ 🐛 [debug]: | response: SearchResultDone(LdapResult { code: Success, matcheddn: "", message: "", referral: [] }) lldap-1 | 2025-10-11T13:48:25.372657532+00:00 INFO i [info]: LDAP session start: aa95cb9a-a6ce-422f-b87d-21edcf21ac92 lldap-1 | 2025-10-11T13:48:25.372971832+00:00 INFO LDAP request [ 1.72ms | 100.00% ] session_id: aa95cb9a-a6ce-422f-b87d-21edcf21ac92 lldap-1 | 2025-10-11T13:48:25.374448428+00:00 DEBUG ┝━ 🐛 [debug]: | msg: LdapMsg { msgid: 0, op: SearchRequest(LdapSearchRequest { base: "", scope: Base, aliases: Never, sizelimit: 0, timelimit: 0, typesonly: false, filter: Present("objectClass"), attrs: ["supportedExtension"] }), ctrl: [] } lldap-1 | 2025-10-11T13:48:25.374455132+00:00 DEBUG ┝━ 🐛 [debug]: rootDSE request lldap-1 | 2025-10-11T13:48:25.374556233+00:00 DEBUG ┝━ 🐛 [debug]: | response: SearchResultEntry(LdapSearchResultEntry { dn: "", attributes: [LdapPartialAttribute { atype: "objectClass", vals: ["top"] }, LdapPartialAttribute { atype: "vendorName", vals: ["LLDAP"] }, LdapPartialAttribute { atype: "vendorVersion", vals: ["lldap_0.1.0"] }, LdapPartialAttribute { atype: "supportedLDAPVersion", vals: ["3"] }, LdapPartialAttribute { atype: "supportedExtension", vals: ["1.3.6.1.4.1.4203.1.11.1", "1.3.6.1.4.1.4203.1.11.3"] }, LdapPartialAttribute { atype: "supportedControl", vals: [] }, LdapPartialAttribute { atype: "supportedFeatures", vals: ["1.3.6.1.4.1.4203.1.5.1"] }, LdapPartialAttribute { atype: "defaultNamingContext", vals: ["dc=example,dc=com"] }, LdapPartialAttribute { atype: "namingContexts", vals: ["dc=example,dc=com"] }, LdapPartialAttribute { atype: "isGlobalCatalogReady", vals: ["false"] }, LdapPartialAttribute { atype: "subschemaSubentry", vals: ["cn=Subschema"] }] }) lldap-1 | 2025-10-11T13:48:25.374659764+00:00 DEBUG ┕━ 🐛 [debug]: | response: SearchResultDone(LdapResult { code: Success, matcheddn: "", message: "", referral: [] }) lldap-1 | 2025-10-11T13:48:25.374988166+00:00 INFO i [info]: LDAP session end: aa95cb9a-a6ce-422f-b87d-21edcf21ac92 lldap-1 | 2025-10-11T13:48:25.375180257+00:00 DEBUG HTTP request [ 23.5µs | 100.00% ] method: "GET" | uri: "/health" lldap-1 | 2025-10-11T13:48:25.375205181+00:00 DEBUG ┕━ 🐛 [debug]: | status_code: 200 ``` pgadmin: ``` pgadmin_container | 2025-10-10 20:49:42,566: ERROR pgadmin: Error searching the LDAP directory: invalid attribute memberof pgadmin_container | Traceback (most recent call last): pgadmin_container | File "/pgadmin4/pgadmin/authenticate/ldap.py", line 287, in search_ldap_user pgadmin_container | self.conn.search(search_base=search_base_dn, pgadmin_container | File "/venv/lib/python3.12/site-packages/ldap3/core/connection.py", line 838, in search pgadmin_container | request = search_operation(search_base, pgadmin_container | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pgadmin_container | File "/venv/lib/python3.12/site-packages/ldap3/operation/search.py", line 371, in search_operation pgadmin_container | request['filter'] = compile_filter(parse_filter(search_filter, schema, auto_escape, auto_encode, validator, check_names).elements[0]) # parse the searchFilter string and compile it starting from the root node pgadmin_container | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pgadmin_container | File "/venv/lib/python3.12/site-packages/ldap3/operation/search.py", line 205, in parse_filter pgadmin_container | current_node.append(evaluate_match(search_filter[start_pos:end_pos], schema, auto_escape, auto_encode, validator, check_names)) pgadmin_container | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pgadmin_container | File "/venv/lib/python3.12/site-packages/ldap3/operation/search.py", line 165, in evaluate_match pgadmin_container | assertion = {'attr': left_part, 'value': validate_assertion_value(schema, left_part, right_part, auto_escape, auto_encode, validator, check_names)} pgadmin_container | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pgadmin_container | File "/venv/lib/python3.12/site-packages/ldap3/protocol/convert.py", line 159, in validate_assertion_value pgadmin_container | value = validate_attribute_value(schema, name, value, auto_encode, validator=validator, check_names=check_names) pgadmin_container | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pgadmin_container | File "/venv/lib/python3.12/site-packages/ldap3/protocol/convert.py", line 175, in validate_attribute_value pgadmin_container | raise LDAPAttributeError('invalid attribute ' + name) pgadmin_container | ldap3.core.exceptions.LDAPAttributeError: invalid attribute memberof ``` **Additional context** No additional context.
kerem 2026-02-27 08:17:25 +03:00
  • closed this issue
  • added the
    bug
    label
Author
Owner

@nitnelave commented on GitHub (Oct 11, 2025):

Can you try upgrading to the nightly build? I think we fixed that already

<!-- gh-comment-id:3393365730 --> @nitnelave commented on GitHub (Oct 11, 2025): Can you try upgrading to the nightly build? I think we fixed that already
Author
Owner

@Mindar commented on GitHub (Oct 11, 2025):

yep, lldap/lldap:latest works

<!-- gh-comment-id:3393416574 --> @Mindar commented on GitHub (Oct 11, 2025): yep, `lldap/lldap:latest` works
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/lldap-lldap#462
No description provided.