Switch to go modules
This commit is contained in:
parent
cf455ba7d9
commit
007b2a375f
6 changed files with 261 additions and 5 deletions
internal
108
internal/ldap/ldap.go
Normal file
108
internal/ldap/ldap.go
Normal file
|
@ -0,0 +1,108 @@
|
|||
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)
|
||||
}
|
|
@ -4,7 +4,7 @@ import (
|
|||
"net/http"
|
||||
|
||||
"bitmask.me/skeleton/internal/app"
|
||||
"github.com/alexedwards/scs"
|
||||
scs "github.com/alexedwards/scs/v2"
|
||||
"github.com/gorilla/csrf"
|
||||
)
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"golang.org/x/crypto/bcrypt"
|
||||
|
||||
"bitmask.me/skeleton/internal/database"
|
||||
ldap "github.com/go-ldap/ldap/v3"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
@ -36,8 +37,15 @@ func (u UserRow) GetID() string {
|
|||
return strconv.FormatInt(u.ID, 10)
|
||||
}
|
||||
|
||||
// NewAuthenticator returns a authable function from a Database.
|
||||
func NewAuthenticator(db *sqlx.DB) func(user, pass string) (User, error) {
|
||||
// NewLDAPAuthenticator returns a authable function from a LDAP Database.
|
||||
func NewLDAPAuthenticator(lc *ldap.Conn) func(user, pass string) (User, error) {
|
||||
return func(user, pass string) (User, error) {
|
||||
return nil, ErrNotImplemented
|
||||
}
|
||||
}
|
||||
|
||||
// NewSQLAuthenticator returns a authable function from a Database.
|
||||
func NewSQLAuthenticator(db *sqlx.DB) func(user, pass string) (User, error) {
|
||||
return func(user, pass string) (User, error) {
|
||||
// Fetch email used for login
|
||||
email, err := database.EmailByAddress(db, user)
|
||||
|
@ -77,7 +85,7 @@ func (h *Handlers) LoginPageHandler(w http.ResponseWriter, r *http.Request) {
|
|||
Password: r.PostFormValue("password"),
|
||||
}
|
||||
|
||||
authenticate := NewAuthenticator(h.App.Database())
|
||||
authenticate := NewSQLAuthenticator(h.App.Database())
|
||||
|
||||
user, err := authenticate(loginForm.Login, loginForm.Password)
|
||||
if err != nil {
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"net/rpc"
|
||||
"strings"
|
||||
|
||||
"github.com/alexedwards/scs"
|
||||
scs "github.com/alexedwards/scs/v2"
|
||||
)
|
||||
|
||||
// GRPCMiddleware allows a HTTP2 Server to also serve GRPC at the same port.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue