skeleton/internal/ldap/ldap.go
2019-12-14 07:28:56 +01:00

109 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)
}