fix(ldap): resolve posixGroup memberUid as bare usernames (#1408) (#1422)

This commit is contained in:
刘祺
2026-04-12 21:55:48 +08:00
committed by GitHub
parent fbdb93f1a7
commit 86152d996c
2 changed files with 49 additions and 1 deletions

View File

@@ -391,6 +391,12 @@ func (s *LdapService) resolveGroupMemberUsername(ctx context.Context, client lda
return norm.NFC.String(username) return norm.NFC.String(username)
} }
// posixGroup (and similar) stores bare usernames in memberUid, not DNs. Treat any value
// that is not a valid DN as the username directly — see https://github.com/pocket-id/pocket-id/issues/1408
if _, err := ldap.ParseDN(member); err != nil {
return norm.NFC.String(member)
}
// As a fallback, query LDAP for the referenced entry // As a fallback, query LDAP for the referenced entry
userSearchReq := ldap.NewSearchRequest( userSearchReq := ldap.NewSearchRequest(
member, member,

View File

@@ -141,6 +141,48 @@ func TestLdapServiceSyncAllReconcilesUsersAndGroups(t *testing.T) {
assert.ElementsMatch(t, []string{"alice", "bob"}, usernames(team.Users)) assert.ElementsMatch(t, []string{"alice", "bob"}, usernames(team.Users))
} }
// Regression: posixGroup uses memberUid (bare uid values), not member DNs — issue #1408.
func TestLdapServiceSyncAllMapsPosixGroupMemberUid(t *testing.T) {
appCfg := defaultTestLDAPAppConfig()
appCfg.LdapUserGroupSearchFilter = model.AppConfigVariable{Value: "(objectClass=posixGroup)"}
appCfg.LdapAttributeGroupMember = model.AppConfigVariable{Value: "memberUid"}
service, db := newTestLdapServiceWithAppConfig(t, appCfg, newFakeLDAPClient(
ldapSearchResult(
ldapEntry("uid=alice,ou=users,dc=example,dc=com", map[string][]string{
"entryUUID": {"u-alice"},
"uid": {"alice"},
"mail": {"alice@example.com"},
"givenName": {"Alice"},
"sn": {"Jones"},
"displayName": {""},
}),
ldapEntry("uid=bob,ou=users,dc=example,dc=com", map[string][]string{
"entryUUID": {"u-bob"},
"uid": {"bob"},
"mail": {"bob@example.com"},
"givenName": {"Bob"},
"sn": {"Brown"},
"displayName": {""},
}),
),
ldapSearchResult(
ldapEntry("cn=users,ou=groups,dc=example,dc=com", map[string][]string{
"entryUUID": {"g-users"},
"cn": {"users"},
"memberUid": {"alice", "bob", "unknown"},
}),
),
))
require.NoError(t, service.SyncAll(t.Context()))
var group model.UserGroup
require.NoError(t, db.Preload("Users").First(&group, "ldap_id = ?", "g-users").Error)
assert.Equal(t, "users", group.Name)
assert.ElementsMatch(t, []string{"alice", "bob"}, usernames(group.Users))
}
func TestLdapServiceSyncAllHandlesDuplicateLDAPIDsInSingleRun(t *testing.T) { func TestLdapServiceSyncAllHandlesDuplicateLDAPIDsInSingleRun(t *testing.T) {
service, db := newTestLdapService(t, newFakeLDAPClient( service, db := newTestLdapService(t, newFakeLDAPClient(
ldapSearchResult( ldapSearchResult(
@@ -325,7 +367,7 @@ func newFakeLDAPClient(userResult, groupResult *ldap.SearchResult) ldapClient {
switch searchRequest.Filter { switch searchRequest.Filter {
case "(objectClass=person)": case "(objectClass=person)":
return userResult, nil return userResult, nil
case "(objectClass=groupOfNames)": case "(objectClass=groupOfNames)", "(objectClass=posixGroup)":
return groupResult, nil return groupResult, nil
default: default:
return &ldap.SearchResult{}, nil return &ldap.SearchResult{}, nil