Skip to content

Commit

Permalink
Add LDAP user driver
Browse files Browse the repository at this point in the history
  • Loading branch information
labkode committed Jan 18, 2017
1 parent 12a31df commit 1a12fa4
Show file tree
Hide file tree
Showing 4 changed files with 192 additions and 6 deletions.
13 changes: 13 additions & 0 deletions cmd/clawiod/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/clawio/clawiod/root/fsdatadriver"
"github.com/clawio/clawiod/root/fsmdatadriver"
"github.com/clawio/clawiod/root/jwttokendriver"
"github.com/clawio/clawiod/root/ldapuserdriver"
"github.com/clawio/clawiod/root/loggermiddleware"
"github.com/clawio/clawiod/root/memuserdriver"
"github.com/clawio/clawiod/root/metadatawebservice"
Expand Down Expand Up @@ -89,6 +90,18 @@ func getUserDriver(config root.Configuration) (root.UserDriver, error) {
switch config.GetUserDriver() {
case "memuserdriver":
return memuserdriver.New(config.GetMemUserDriverUsers()), nil
case "ldapuserdriver":
logger, err := getLogger(config)
if err != nil {
return nil, err
}
return ldapuserdriver.New(logger,
config.GetLDAPUserDriverBindUsername(),
config.GetLDAPUserDriverBindPassword(),
config.GetLDAPUserDriverHostname(),
config.GetLDAPUserDriverPort(),
config.GetLDAPUserDriverBaseDN(),
config.GetLDAPUserDriverFilter())
default:
return nil, errors.New("configured user driver does not exist")
}
Expand Down
40 changes: 34 additions & 6 deletions root/fileconfigurationsource/fileconfigurationsource.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,14 @@ type configuration struct {
TLSCertificate string `json:"tls_certificate"`
TLSPrivateKey string `json:"tls_private_key"`

UserDriver string `json:"user_driver"`
MemUserDriverUsers string `json:"mem_user_driver_users"`
UserDriver string `json:"user_driver"`
MemUserDriverUsers string `json:"mem_user_driver_users"`
LDAPUserDriverBindUsername string `json:"ldap_user_driver_bind_username"`
LDAPUserDriverBindPassword string `json:"ldap_user_driver_bind_password"`
LDAPUserDriverHostname string `json:"ldap_user_driver_hostname"`
LDAPUserDriverPort int `json:"ldap_user_driver_port"`
LDAPUserDriverBaseDN string `json:"ldap_user_driver_base_dn"`
LDAPUserDriverFilter string `json:"ldap_user_driver_filter"`

DataDriver string `json:"data_driver"`
FSDataDriverDataFolder string `json:"fs_data_driver_data_folder"`
Expand Down Expand Up @@ -118,11 +124,33 @@ func (c *configuration) GetTLSPrivateKey() string { return c.TLSPrivateKey }

func (c *configuration) GetUserDriver() string { return c.UserDriver }
func (c *configuration) GetMemUserDriverUsers() string { return c.MemUserDriverUsers }
func (c *configuration) GetLDAPUserDriverBindUsername() string {
return c.LDAPUserDriverBindUsername
}
func (c *configuration) GetLDAPUserDriverBindPassword() string {
return c.LDAPUserDriverBindPassword

func (c *configuration) GetDataDriver() string { return c.DataDriver }
func (c *configuration) GetFSDataDriverDataFolder() string { return c.FSDataDriverDataFolder }
func (c *configuration) GetFSDataDriverTemporaryFolder() string { return c.FSDataDriverTemporaryFolder }
func (c *configuration) GetFSDataDriverChecksum() string { return c.FSDataDriverChecksum }
}
func (c *configuration) GetLDAPUserDriverHostname() string {
return c.LDAPUserDriverHostname
}
func (c *configuration) GetLDAPUserDriverPort() int {
return c.LDAPUserDriverPort
}
func (c *configuration) GetLDAPUserDriverBaseDN() string {
return c.LDAPUserDriverBaseDN
}
func (c *configuration) GetLDAPUserDriverFilter() string {
return c.LDAPUserDriverFilter
}
func (c *configuration) GetDataDriver() string {
return c.DataDriver
}
func (c *configuration) GetFSDataDriverDataFolder() string { return c.FSDataDriverDataFolder }
func (c *configuration) GetFSDataDriverTemporaryFolder() string {
return c.FSDataDriverTemporaryFolder
}
func (c *configuration) GetFSDataDriverChecksum() string { return c.FSDataDriverChecksum }
func (c *configuration) GetFSDataDriverVerifyClientChecksum() bool {
return c.FSDataDriverVerifyClientChecksum
}
Expand Down
139 changes: 139 additions & 0 deletions root/ldapuserdriver/ldapuserdriver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package ldapuserdriver

import (
"fmt"
)

import (
"github.com/clawio/clawiod/root"
"github.com/go-kit/kit/log/levels"
"gopkg.in/ldap.v2"
)

type driver struct {
logger levels.Levels
bindUsername string
bindPassword string
hostname string
port int
baseDN string
filter string
}

func New(logger levels.Levels,
bindUsername,
bindPassword,
hostname string,
port int,
baseDN string,
filter string) (root.UserDriver, error) {

logger.Info().Log("msg", "ldap configuration", "hostname", hostname, "port", port, "bindusername", bindUsername, "basedn", baseDN, "filter", filter)
return &driver{
logger: logger,
bindUsername: bindUsername,
bindPassword: bindPassword,
hostname: hostname,
port: port,
baseDN: baseDN,
filter: filter,
}, nil
}

func (c *driver) GetByCredentials(username, password string) (root.User, error) {
l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", c.hostname, c.port))
if err != nil {
c.logger.Error().Log("error", err)
return nil, err
}
defer l.Close()
c.logger.Info().Log("msg", "connection stablished")

// Reconnect with TLS
/*
err = l.StartTLS(&tls.Config{InsecureSkipVerify: true})
if err != nil {
c.logger.Error().Log("error", err)
return nil, err
}
*/

// First bind with a read only user
err = l.Bind(c.bindUsername, c.bindPassword)
if err != nil {
c.logger.Error().Log("error", err)
return nil, err
}

// Search for the given username
searchRequest := ldap.NewSearchRequest(
c.baseDN,
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
//fmt.Sprintf("(&(objectClass=user)&(samaccountname=%s))", username),
fmt.Sprintf(c.filter, username),
[]string{"dn"},
nil,
)

sr, err := l.Search(searchRequest)
if err != nil {
c.logger.Error().Log("error", err)
return nil, err
}

if len(sr.Entries) != 1 {
err := userNotFoundError("user " + username + " not found")
c.logger.Error().Log("error", err)
return nil, err
}

userdn := sr.Entries[0].DN
c.logger.Info().Log("msg", "user exists", "dn", userdn)

// Bind as the user to verify their password
err = l.Bind(userdn, password)
if err != nil {
c.logger.Error().Log("error", err)
return nil, err
}

// TODO(labkode) Get more attrs from LDAP query like email and displayName at least
u := &user{
username: username,
}
return u, nil
}

type user struct {
username string
email string
displayName string
}

func (u *user) Username() string {
return u.username
}

func (u *user) Email() string {
return u.email
}

func (u *user) DisplayName() string {
return u.displayName
}

func (u *user) ExtraAttributes() map[string]interface{} {
return nil
}

type userNotFoundError string

func (e userNotFoundError) Error() string {
return string(e)
}
func (e userNotFoundError) Code() root.Code {
return root.Code(root.CodeUserNotFound)
}
func (e userNotFoundError) Message() string {
return string(e)
}
6 changes: 6 additions & 0 deletions root/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,12 @@ type (

GetUserDriver() string
GetMemUserDriverUsers() string
GetLDAPUserDriverBindUsername() string
GetLDAPUserDriverBindPassword() string
GetLDAPUserDriverHostname() string
GetLDAPUserDriverPort() int
GetLDAPUserDriverBaseDN() string
GetLDAPUserDriverFilter() string

GetDataDriver() string
GetFSDataDriverDataFolder() string
Expand Down

0 comments on commit 1a12fa4

Please sign in to comment.