108 lines
2.7 KiB
Go
108 lines
2.7 KiB
Go
package ldap
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
|
|
ldap "github.com/go-ldap/ldap/v3"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
var (
|
|
// TimeLimitSeconds is the maximal time that LDAP will spend on a single
|
|
// request.
|
|
TimeLimitSeconds = 5
|
|
// SizeLimitEntries is the biggest number of results that is returned from a
|
|
// search request.
|
|
SizeLimitEntries = 100
|
|
// UserAttributes is the list of LDAP-Attributes that will be used for user
|
|
// accounts.
|
|
UserAttributes = []string{
|
|
"dn", // distinguished name, the unique "path" to a LDAP entry.
|
|
"cn", // common name, human readable e.g. "Max Powers".
|
|
"uid", // user identified, same as the username/login name.
|
|
"uidNumber", // unique user ID, integer.
|
|
"createTimestamp", // LDAP timestamp of when this entry was created.
|
|
"modifyTimestamp", // LDAP timestemp of when this entry was last modified.
|
|
}
|
|
)
|
|
|
|
type Server struct {
|
|
Host string
|
|
Port int
|
|
|
|
bindDN string
|
|
bindPW string
|
|
|
|
userBaseDN string
|
|
}
|
|
|
|
func (s *Server) newConn() (*ldap.Conn, error) {
|
|
lc, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", s.Host, s.Port))
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "Failed to dial LDAP")
|
|
}
|
|
|
|
err = lc.Bind(s.bindDN, s.bindPW)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "Failed to bind service account to LDAP")
|
|
}
|
|
|
|
return lc, nil
|
|
}
|
|
|
|
// buildFilterForID builds an LDAP filter that searches for a user with a
|
|
// specific uidNumber.
|
|
func (s *Server) buildFilterForUserID(id int) string {
|
|
return fmt.Sprintf("(&(objectClass=inetOrgPerson)(uidNumber=%d))", id)
|
|
}
|
|
|
|
func (s *Server) buildFilterForEmail(email string) string {
|
|
reg := regexp.MustCompile("[^a-zA-Z0-9-+._@]+")
|
|
email = reg.ReplaceAllString(email, "")
|
|
return fmt.Sprintf("(&(objectClass=)())")
|
|
|
|
// Conn is an LDAP connection.
|
|
type Conn struct {
|
|
*ldap.Conn
|
|
}
|
|
|
|
type User struct {
|
|
Entry *ldap.Entry
|
|
}
|
|
|
|
// GetDisplayName implements User interface by returning the display name.
|
|
func (u User) GetDisplayName() string {
|
|
display := u.Entry.GetAttributeValue("displayName")
|
|
|
|
if display == "" {
|
|
display = u.Entry.GetAttributeValue("givenName")
|
|
}
|
|
|
|
if display == "" {
|
|
display = u.Entry.GetAttributeValue("cn")
|
|
}
|
|
|
|
if display == "" {
|
|
display = u.GetID()
|
|
}
|
|
return display
|
|
}
|
|
|
|
// GetID implements the User interface by returning the user ID.
|
|
func (u User) GetID() string {
|
|
id := u.Entry.GetAttributeValue("uid")
|
|
return id
|
|
}
|
|
|
|
func (lc *Conn) UserByID(ID string) (User, error) {
|
|
ldap.NewSearchRequest()
|
|
}
|
|
|
|
func (s *Server) UserByEmail(email string) (User, error) {
|
|
lc, err := s.newConn()
|
|
ldap.NewSearchRequest(
|
|
s.userBaseDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases,
|
|
SizeLimitEntries, TimeLimitSeconds, false,
|
|
s.buildFilterForEmail(email), UserAttributes, nil)
|
|
}
|