Skip to content

Instantly share code, notes, and snippets.

@nlowe
Created July 10, 2018 18:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nlowe/a745947416f3917a22ef8144ec0fbf4f to your computer and use it in GitHub Desktop.
Save nlowe/a745947416f3917a22ef8144ec0fbf4f to your computer and use it in GitHub Desktop.
Grafana LDAP Debugger
package main
import (
"bufio"
"crypto/tls"
"fmt"
"os"
"strings"
"github.com/go-ldap/ldap"
"github.com/howeyc/gopass"
)
const (
usernameAttr = "sAMAccountName"
surnameAttr = "sn"
emailAttr = "mail"
nameAttr = "givenName"
memberOfAttr = "memberOf"
groupSearchFilter = "(&(objectClass=user)(memberof:1.2.840.113556.1.4.1941:=CN=SEC - Cloud DevOps Support,OU=Security Groups,DC=MyDomain,DC=net))" //"(&(objectClass=user)(memberof:1.2.840.113556.1.4.1941:=%s))"
groupSearchAttr = "distinguishedName"
)
func main() {
fmt.Println("Connecting to ad.mydomain.net:636")
conn, err := ldap.DialTLS("tcp", "ad.mydomain.net:636", &tls.Config{
InsecureSkipVerify: true,
ServerName: "ad.mydomain.net",
})
defer conn.Close()
if err != nil {
panic(err)
}
scanner := bufio.NewReader(os.Stdin)
fmt.Printf("Username: ")
un, err := scanner.ReadString('\n')
if err != nil {
panic(err)
}
fmt.Printf("Password: ")
pw, err := gopass.GetPasswd()
if err != nil {
panic(err)
}
fmt.Println("Binding")
if err := conn.Bind(strings.TrimSpace(un), string(pw)); err != nil {
panic(err)
}
request := ldap.SearchRequest{
BaseDN: "dc=mydomain, dc=net",
Scope: ldap.ScopeWholeSubtree,
DerefAliases: ldap.NeverDerefAliases,
Attributes: []string{
nameAttr,
surnameAttr,
usernameAttr,
memberOfAttr,
emailAttr,
},
Filter: "(sAMAccountName=nlowe)",
}
fmt.Println("Searching")
result, err := conn.Search(&request)
if err != nil {
panic(err)
}
if len(result.Entries) != 1 {
panic(fmt.Sprintf("Expected exactly one entry but got %d", len(result.Entries)))
}
fmt.Println("Got it!\n\n")
fmt.Println("Groups from filter:")
for _, attr := range result.Entries[0].Attributes {
fmt.Printf("Found attr %s\n", attr.Name)
if attr.Name == "memberOf" {
for _, v := range attr.Values {
fmt.Printf(" * %s\n", v)
}
}
}
groupSearchReq := ldap.SearchRequest{
BaseDN: "dc=mydomain,dc=net",
Scope: ldap.ScopeWholeSubtree,
DerefAliases: ldap.NeverDerefAliases,
Attributes: []string{memberOfAttr},
Filter: strings.Replace(groupSearchFilter, "%s", ldap.EscapeFilter(getLdapAttr(groupSearchAttr, result)), -1),
}
if groups, err := conn.Search(&groupSearchReq); err != nil {
panic(err)
} else {
fmt.Println("Groups from secondary search:")
for i := range groups.Entries {
fmt.Printf(" * %s\n", getLdapAttrN(memberOfAttr, groups, i))
}
}
fmt.Printf("DN: %s\n", result.Entries[0].DN)
fmt.Printf("LastName: %s\n", getLdapAttr(surnameAttr, result))
fmt.Printf("FirstName: %s\n", getLdapAttr(nameAttr, result))
fmt.Printf("Username: %s\n", getLdapAttr(usernameAttr, result))
fmt.Printf("Email: %s\n", getLdapAttr(emailAttr, result))
}
func getLdapAttrN(name string, result *ldap.SearchResult, n int) string {
if strings.ToLower(name) == "dn" {
return result.Entries[n].DN
}
for _, attr := range result.Entries[n].Attributes {
if attr.Name == name {
if len(attr.Values) > 0 {
return attr.Values[0]
}
}
}
return ""
}
func getLdapAttr(name string, result *ldap.SearchResult) string {
return getLdapAttrN(name, result, 0)
}
Connecting to ad.mydomain.net:636
Username: mydomain\nlowe
Password:
Binding
Searching
Got it!
Groups from filter:
Found attr sn
Found attr givenName
Found attr memberOf
* CN=GRP - WaaS Pilot,OU=Distribution Groups,DC=MyDomain,DC=net
* CN=SEC - Cloud DevOps Support,OU=Security Groups,DC=MyDomain,DC=net
* // 20+ other groups
Found attr sAMAccountName
Found attr mail
Groups from secondary search:
* CN=GRP - WaaS Pilot,OU=Distribution Groups,DC=MyDomain,DC=net
DN: CN=Nathan Lowe,OU=Users,OU=Quality Assurance,OU=CTO,OU=Westlake,DC=MyDomain,DC=net
LastName: Lowe
FirstName: Nathan
Username: nlowe
Email: Nathan.Lowe@mydomain.com
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment