This repository has been archived by the owner on Sep 24, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathid_resolver.go
129 lines (112 loc) · 3.04 KB
/
id_resolver.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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package nfsv3driver
import (
"crypto/tls"
"crypto/x509"
"errors"
"fmt"
"time"
"code.cloudfoundry.org/dockerdriver"
"code.cloudfoundry.org/goshims/ldapshim"
"gopkg.in/ldap.v2"
)
//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate
//counterfeiter:generate -o nfsdriverfakes/fake_id_resolver.go . IdResolver
type IdResolver interface {
Resolve(env dockerdriver.Env, username string, password string) (uid string, gid string, err error)
}
type ldapIdResolver struct {
svcUser string
svcPass string
ldapHost string
ldapPort int
ldapProto string
ldapFqdn string // ldap domain to search for users .in, e.g. "cn=Users,dc=corp,dc=persi,dc=cf-app,dc=com"
ldapCACert string
ldap ldapshim.Ldap
ldapTimeout time.Duration
}
func NewLdapIdResolver(
svcUser string,
svcPass string,
ldapHost string,
ldapPort int,
ldapProto string,
ldapFqdn string,
ldapCACert string,
ldap ldapshim.Ldap,
ldapTimeout time.Duration,
) IdResolver {
return &ldapIdResolver{
svcUser: svcUser,
svcPass: svcPass,
ldapHost: ldapHost,
ldapPort: ldapPort,
ldapProto: ldapProto,
ldapFqdn: ldapFqdn,
ldapCACert: ldapCACert,
ldap: ldap,
ldapTimeout: ldapTimeout,
}
}
func (d *ldapIdResolver) Resolve(env dockerdriver.Env, username string, password string) (uid string, gid string, err error) {
addr := fmt.Sprintf("%s:%d", d.ldapHost, d.ldapPort)
var l ldapshim.LdapConnection
if d.ldapCACert != "" {
roots := x509.NewCertPool()
ok := roots.AppendCertsFromPEM([]byte(d.ldapCACert))
if !ok {
return "", "", errors.New("Failed to load CA certificate")
}
// #nosec G402
l, err = d.ldap.DialTLS(d.ldapProto, addr, &tls.Config{
ServerName: d.ldapHost,
RootCAs: roots,
})
} else {
l, err = d.ldap.Dial(d.ldapProto, addr)
}
if err != nil {
return "", "", dockerdriver.SafeError{SafeDescription: "LDAP server could not be reached, please contact your system administrator"}
}
l.SetTimeout(d.ldapTimeout)
defer l.Close()
// First bind with a read only user
err = l.Bind(d.svcUser, d.svcPass)
if err != nil {
return "", "", err
}
// Search for the given username
searchRequest := d.ldap.NewSearchRequest(
d.ldapFqdn,
ldap.ScopeWholeSubtree,
ldap.NeverDerefAliases,
0,
0,
false,
fmt.Sprintf("(&(objectClass=User)(cn=%s))", ldap.EscapeFilter(username)),
[]string{"dn", "uidNumber", "gidNumber"},
nil,
)
sr, err := l.Search(searchRequest)
if err != nil {
return "", "", err
}
if len(sr.Entries) == 0 {
return "", "", dockerdriver.SafeError{SafeDescription: "User does not exist"}
}
if len(sr.Entries) > 1 {
return "", "", dockerdriver.SafeError{SafeDescription: "Ambiguous search--too many results"}
}
userdn := sr.Entries[0].DN
uid = sr.Entries[0].GetAttributeValue("uidNumber")
gid = sr.Entries[0].GetAttributeValue("gidNumber")
if gid == "" {
gid = uid
}
// Bind as the user to verify their password
err = l.Bind(userdn, password)
if err != nil {
return "", "", dockerdriver.SafeError{SafeDescription: err.Error()}
}
return uid, gid, nil
}