/
activedirectory.go
92 lines (78 loc) · 2.38 KB
/
activedirectory.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package ldapclients
import (
"fmt"
"github.com/go-ldap/ldap"
log "github.com/golang/glog"
)
const (
AD_USER_FILTER = "(objectClass=user)"
AD_USER_ATTRIBUTE = "sAMAccountName"
AD_GROUP_ATTRIBUTE = "memberOf"
AD_GROUP_OBJECT_CLASS = "group"
)
type ActiveDirectoryClient struct {
*LDAPClient
// cache (if enabled)
cache *CredentialsCache
}
func NewActiveDirectoryClient(ldapUri, bindDn, bindPass string, searchBase ...string) (ad *ActiveDirectoryClient, err error) {
ad = &ActiveDirectoryClient{}
ad.LDAPClient, err = NewLDAPClient(ldapUri, bindDn, bindPass, searchBase...)
return
}
func (ad *ActiveDirectoryClient) Authenticate(username, password string) (err error) {
if ad.cache != nil && ad.cache.CheckCreds(username, password) {
log.V(10).Infof("Cache hit: %s\n", username)
return
}
log.V(10).Infof("Cache miss: %s\n", username)
var (
userDn string
userAD *ActiveDirectoryClient
)
if userDn, err = ad.GetUserDN(username); err != nil {
return
}
if userAD, err = NewActiveDirectoryClient(ad.URI, userDn, password); err == nil && ad.cache != nil {
// cache
ad.cache.CacheCreds(NewCredentials(username, userDn, password))
}
userAD.Close()
return
}
func (ad *ActiveDirectoryClient) EnableCaching(ttl int64) {
if ad.cache == nil {
ad.cache = NewCredentialsCache(ttl)
}
log.V(11).Infof("Caching enabled!\n")
}
func (ad *ActiveDirectoryClient) GetUserDN(username string) (userDN string, err error) {
log.V(11).Infof("Search base: %s\n", ad.DefaultSearchBase)
searchReq := &ldap.SearchRequest{
BaseDN: ad.DefaultSearchBase,
Filter: ad.getUserSearchFilter(username),
Scope: ldap.ScopeWholeSubtree,
Attributes: []string{"distinguishedName"},
}
var rslt *ldap.SearchResult
if rslt, err = ad.Search(searchReq); err != nil {
return
}
if len(rslt.Entries) < 1 {
err = fmt.Errorf("User not found: %s", username)
return
}
// Double check user dn is actually returned
if len(rslt.Entries[0].Attributes) < 1 || len(rslt.Entries[0].Attributes[0].Values) < 1 {
err = fmt.Errorf("User DN attribute not found!")
return
}
userDN = rslt.Entries[0].Attributes[0].Values[0]
return
}
func (ad *ActiveDirectoryClient) getUserSearchFilter(samAccountName string) string {
userFilter := fmt.Sprintf("(&(%s=%s)%s)",
AD_USER_ATTRIBUTE, ldap.EscapeFilter(samAccountName), AD_USER_FILTER)
log.V(11).Infof("Filter: %s\n", userFilter)
return userFilter
}