Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add example for paging search result attributes, maybe? #342

Open
naikrovek opened this issue Sep 30, 2021 · 2 comments
Open

Add example for paging search result attributes, maybe? #342

naikrovek opened this issue Sep 30, 2021 · 2 comments

Comments

@naikrovek
Copy link

Hi, I need to page the attribute results of a search with a single result; it's a large group and I need all members ("member" attribute, though I think this gets appended with an offset and count if you want to page; something like member;range=0-499.)

I can't figure this out for the life of me, so maybe an example is needed to help anyone else with this need, if the library supports this. otherwise I can just do the paging myself and loop over the query over and over until no more results are returned.

@bhaswanth88
Copy link

@naikrovek : i am also looking for same, have you found an answer for this? if so, can you please share ?

@naikrovek
Copy link
Author

Here's an example program. This uses recursion to get nested group members as well. if you have a circularly nested groups underneath the group specified in main then this will run for a very long time, and eventually fail.

package main

import (
	"fmt"
	"log"
	"strconv"
	"strings"

	"github.com/go-ldap/ldap/v3"
)

func main() {
	// this will get members of nested groups as well.  beware circular nesting.
	members := getLdapGroupMembers("groupname")

	results := make(map[string]bool)

	for _, member := range members {
		results[member] = true
	}

	for key := range results {
		fmt.Println(key)
	}
}

func check(e error) {
	if e != nil {
		log.Panic(e)
	}
}

func getLdapGroupMembers(group string) []string {
	l, err := ldap.DialURL("ldaps://adcontroller.domain:636")
	check(err)

	defer l.Close()

	bindpass := "asdfasdf" 

	err = l.Bind("CN=asdf,OU=asdf,OU=asdf,DC=asdf,DC=asdf,DC=asdf", bindpass)
	check(err)

	stepSize := 500
	lowNumber := 0
	highNumber := lowNumber + stepSize - 1

	keepGoing := true

	searchBase := "OU=asdf,OU=asdf,DC=asdf,DC=asdf,DC=asdf"
	filter := "(&(objectClass=group)(cn=" + ldap.EscapeFilter(group) + "))"
	pagingControl := ldap.NewControlPaging(uint32(stepSize))
	controls := []ldap.Control{pagingControl}

	results := []string{}

	for keepGoing {
		attributeString := "member;range=" + strconv.Itoa(lowNumber) + "-" + strconv.Itoa(highNumber)
		attributes := []string{"cn", attributeString}

		lowNumber += stepSize
		highNumber += stepSize

		searchRequest := ldap.NewSearchRequest(
			searchBase,
			ldap.ScopeWholeSubtree, ldap.DerefAlways, 0, 0, false,
			filter,
			attributes,
			controls,
		)

		response, err := l.Search(searchRequest)
		check(err)

		for _, entry := range response.Entries {
			if len(entry.Attributes) < 2 {
				keepGoing = false
				continue
			}

			for _, attribute := range entry.Attributes {
				if strings.HasPrefix(attribute.Name, "memb") {
					members := entry.GetAttributeValues(attribute.Name)
					// walk the results and add them to results.  if any are
					// groups, get the users in that group.
					for _, result := range members {
						if strings.Contains(result, "OU=asdf") {
							groupName := strings.Replace(result, "CN=", "", -1)
							groupName = strings.Replace(groupName, ",OU=asdf,OU=asdf,DC=asdf,DC=asdf,DC=asdf", "", -1)
							groupUsers := getLdapGroupMembers(groupName)
							results = append(results, groupUsers...)
						} else {
							// a normal user
							results = append(results, result)
						}
					}

					if len(members) < int(stepSize) {
						keepGoing = false
					}
				}
			}
		}
	}

	return results
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants