go-ldap-client icon indicating copy to clipboard operation
go-ldap-client copied to clipboard

GetGroupsOfUser() for Active Directory database

Open PlkMarudny opened this issue 6 years ago • 9 comments

What would be the GroupFilter in that case? User filter is "(sAMAccountName=%s)", BTW

PlkMarudny avatar May 28 '18 08:05 PlkMarudny

Using this in a project I'm working on with AD and this took me a bit to find out.

"(&(member=%s)(objectClass=group))" where "%s" is the user distinguished name -- I just grabbed the user dn from the attributes once they were authenticated. Hope this helps.

arpachuilo avatar Jul 03 '18 15:07 arpachuilo

I'm trying to use AD for authorization only.. I bind as a read-only user to query the list of groups a user is in, and I'm having a heck of a time getting the GroupFilter written properly to get anything but an empty set of groups. If you have a code example of how you're making this work, I would be very grateful, @arpachuilo!

eklein avatar Jan 18 '19 22:01 eklein

@eklein I've changed jobs since then, so I don't have access to the codebase to share a snippet -- nor do I remember what I did.

I hazily remember using "(&(member=%s)(objectClass=group))" as the GroupFilter. Then I guess beyond that when calling GetGroupsOfUser I passed in the user distinguished name of the user. Do not remember how I was getting a hold of the user DN beyond recreating it because I don't think I was doing Authentication either. I just remember the DN being essential to getting groups properly.

Not much, but hope this helps.

arpachuilo avatar Jan 20 '19 02:01 arpachuilo

I thought I had cracked this with (&(member=%s)(objectCategory=group)) then passing the sAMAccount name but then I noticed I was using the DN.

Time to create a quick helper function to grab the DN I guess

Joffcom avatar Jan 21 '19 14:01 Joffcom

@eklein My GetGroupsOfUser is now working using the modified version below, Give it a go and see if it works for you. It could do with a bit of cleanup but should get you started.

// GetGroupsOfUser returns the group for a user.
func (lc *LDAPClient) GetGroupsOfUser(username string) ([]string, error) {
	err := lc.Connect()
	if err != nil {
		return nil, err
	}
	defer lc.Close()

	// First Bind with read only user
	if lc.BindDN != "" && lc.BindPassword != "" {
		err = lc.Conn.Bind(lc.BindDN, lc.BindPassword)
		if err != nil {
			return nil, err
		}
	}

	// Get the users DN
	// Search for the given username
	searchRequest := ldap.NewSearchRequest(
		lc.Base,
		ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
		fmt.Sprintf(lc.UserFilter, username),
		[]string{"dn"},
		nil,
	)

	sr, err := lc.Conn.Search(searchRequest)
	if err != nil {
		return nil, err
	}

	if len(sr.Entries) != 1 {
		return nil, errors.New("User does not exist")
	}

	userdn := sr.Entries[0].DN

	searchRequest = ldap.NewSearchRequest(
		lc.Base,
		ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
		fmt.Sprintf(lc.GroupFilter, userdn),
		[]string{"cn"}, // can it be something else than "cn"?
		nil,
	)
	sr, err = lc.Conn.Search(searchRequest)
	if err != nil {
		return nil, err
	}

	groups := []string{}
	for _, entry := range sr.Entries {
		groups = append(groups, entry.GetAttributeValue("cn"))
	}

	return groups, nil
}

Joffcom avatar Jan 21 '19 14:01 Joffcom

Wish I would have seen this about 10 minutes ago 😂. I just sat down and wrote a helper function to do the same. This indeed did work for me, though I wonder if this breaks things when using openldap. Need to look into that since I have a need to authenticate against both. Thank you both very much for your help! @arpachuilo @Joffcom

eklein avatar Jan 22 '19 14:01 eklein

To follow-up, it does indeed break when trying to authenticate against openldap. I'll need to rewrite things to support both based on whether it's openldap or AD.

eklein avatar Jan 24 '19 14:01 eklein

Hi @Joffcom your example don't return the primary groups, like "Users" or "Domain Users". Any way to return all groups of a specific user including Primary Groups? Best regards

abolinhas avatar Sep 29 '22 23:09 abolinhas

Good question @abolinhas, I have not really played with this for a couple of years now but I would have expected it to work with the primary group as well as the user would still be a member 🤔

I don't have an AD server to test against anymore either.

Joffcom avatar Sep 29 '22 23:09 Joffcom