Skip to content

Commit

Permalink
ldap: add group search (#430)
Browse files Browse the repository at this point in the history
* add group search

* populate groups now that we have a function for it, modify auth manager filter to userfilter to be consistant with user manager
  • Loading branch information
Michael D'Silva authored and labkode committed Dec 13, 2019
1 parent 27b41b9 commit 84b5f3b
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 21 deletions.
4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ require (
github.com/fatih/color v1.7.0 // indirect
github.com/go-openapi/strfmt v0.19.2 // indirect
github.com/gofrs/uuid v3.2.0+incompatible
github.com/gogo/protobuf v1.2.0 // indirect
github.com/golang/protobuf v1.3.2
github.com/gomodule/redigo v2.0.0+incompatible
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4
Expand All @@ -24,17 +25,20 @@ require (
github.com/pkg/errors v0.8.1
github.com/pkg/xattr v0.4.1
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829 // indirect
github.com/rs/cors v1.7.0
github.com/rs/zerolog v1.17.2
go.opencensus.io v0.22.1
golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3 // indirect
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 // indirect
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421
google.golang.org/grpc v1.25.1
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect
gopkg.in/cheggaaa/pb.v1 v1.0.27 // indirect
gopkg.in/ldap.v2 v2.5.1
gopkg.in/square/go-jose.v2 v2.2.2 // indirect
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc // indirect
)

go 1.13
4 changes: 2 additions & 2 deletions pkg/auth/manager/ldap/ldap.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ type config struct {
Hostname string `mapstructure:"hostname"`
Port int `mapstructure:"port"`
BaseDN string `mapstructure:"base_dn"`
Filter string `mapstructure:"filter"`
UserFilter string `mapstructure:"userfilter"`
BindUsername string `mapstructure:"bind_username"`
BindPassword string `mapstructure:"bind_password"`
Idp string `mapstructure:"idp"`
Expand Down Expand Up @@ -109,7 +109,7 @@ func (am *mgr) Authenticate(ctx context.Context, clientID, clientSecret string)
searchRequest := ldap.NewSearchRequest(
am.c.BaseDN,
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
fmt.Sprintf(am.c.Filter, clientID),
fmt.Sprintf(am.c.UserFilter, clientID),
// TODO(jfd): objectguid, entryuuid etc ... make configurable
[]string{am.c.Schema.DN, am.c.Schema.UID, am.c.Schema.Mail, am.c.Schema.DisplayName},
nil,
Expand Down
96 changes: 77 additions & 19 deletions pkg/user/manager/ldap/ldap.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ type manager struct {
hostname string
port int
baseDN string
filter string
userfilter string
groupfilter string
bindUsername string
bindPassword string
idp string
Expand All @@ -52,7 +53,8 @@ type config struct {
Hostname string `mapstructure:"hostname"`
Port int `mapstructure:"port"`
BaseDN string `mapstructure:"base_dn"`
Filter string `mapstructure:"filter"`
UserFilter string `mapstructure:"userfilter"`
GroupFilter string `mapstructure:"groupfilter"`
BindUsername string `mapstructure:"bind_username"`
BindPassword string `mapstructure:"bind_password"`
Idp string `mapstructure:"idp"`
Expand All @@ -64,6 +66,7 @@ type attributes struct {
UID string `mapstructure:"uid"`
DisplayName string `mapstructure:"displayName"`
DN string `mapstructure:"dn"`
CN string `mapstructure:"cn"`
}

// Default attributes (Active Directory)
Expand All @@ -72,6 +75,7 @@ var ldapDefaults = attributes{
UID: "objectGUID",
DisplayName: "displayName",
DN: "dn",
CN: "cn",
}

func parseConfig(m map[string]interface{}) (*config, error) {
Expand All @@ -97,7 +101,8 @@ func New(m map[string]interface{}) (user.Manager, error) {
hostname: c.Hostname,
port: c.Port,
baseDN: c.BaseDN,
filter: c.Filter,
userfilter: c.UserFilter,
groupfilter: c.GroupFilter,
bindUsername: c.BindUsername,
bindPassword: c.BindPassword,
idp: c.Idp,
Expand All @@ -123,7 +128,7 @@ func (m *manager) GetUser(ctx context.Context, uid *userpb.UserId) (*userpb.User
searchRequest := ldap.NewSearchRequest(
m.baseDN,
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
fmt.Sprintf(m.filter, uid.OpaqueId), // TODO this is screaming for errors if filter contains >1 %s
fmt.Sprintf(m.userfilter, uid.OpaqueId), // TODO this is screaming for errors if filter contains >1 %s
[]string{m.schema.DN, m.schema.UID, m.schema.Mail, m.schema.DisplayName},
nil,
)
Expand All @@ -139,13 +144,18 @@ func (m *manager) GetUser(ctx context.Context, uid *userpb.UserId) (*userpb.User

log.Debug().Interface("entries", sr.Entries).Msg("entries")

id := &userpb.UserId{
Idp: m.idp,
OpaqueId: sr.Entries[0].GetAttributeValue(m.schema.UID),
}
groups, err := m.GetUserGroups(ctx, id)
if err != nil {
return nil, err
}
u := &userpb.User{
Id: &userpb.UserId{
Idp: m.idp,
OpaqueId: uid.OpaqueId,
},
Id: id,
Username: sr.Entries[0].GetAttributeValue(m.schema.UID),
Groups: []string{},
Groups: groups,
Mail: sr.Entries[0].GetAttributeValue(m.schema.Mail),
DisplayName: sr.Entries[0].GetAttributeValue(m.schema.DisplayName),
}
Expand All @@ -170,7 +180,7 @@ func (m *manager) FindUsers(ctx context.Context, query string) ([]*userpb.User,
searchRequest := ldap.NewSearchRequest(
m.baseDN,
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
fmt.Sprintf(m.filter, query), // TODO this is screaming for errors if filter contains >1 %s
fmt.Sprintf(m.userfilter, query), // TODO this is screaming for errors if filter contains >1 %s
[]string{m.schema.DN, m.schema.UID, m.schema.Mail, m.schema.DisplayName},
nil,
)
Expand All @@ -183,15 +193,20 @@ func (m *manager) FindUsers(ctx context.Context, query string) ([]*userpb.User,
users := []*userpb.User{}

for _, entry := range sr.Entries {
id := &userpb.UserId{
Idp: m.idp,
OpaqueId: entry.GetAttributeValue(m.schema.UID),
}
groups, err := m.GetUserGroups(ctx, id)
if err != nil {
return nil, err
}
user := &userpb.User{
Id: &userpb.UserId{
Idp: m.idp,
OpaqueId: sr.Entries[0].GetAttributeValue(m.schema.UID),
},
Id: id,
Username: entry.GetAttributeValue(m.schema.UID),
Groups: []string{},
Mail: sr.Entries[0].GetAttributeValue(m.schema.Mail),
DisplayName: sr.Entries[0].GetAttributeValue(m.schema.DisplayName),
Groups: groups,
Mail: entry.GetAttributeValue(m.schema.Mail),
DisplayName: entry.GetAttributeValue(m.schema.DisplayName),
}
users = append(users, user)
}
Expand All @@ -200,9 +215,52 @@ func (m *manager) FindUsers(ctx context.Context, query string) ([]*userpb.User,
}

func (m *manager) GetUserGroups(ctx context.Context, uid *userpb.UserId) ([]string, error) {
return []string{}, nil // FIXME implement GetUserGroups for ldap user manager
l, err := ldap.DialTLS("tcp", fmt.Sprintf("%s:%d", m.hostname, m.port), &tls.Config{InsecureSkipVerify: true})
if err != nil {
return []string{}, err
}
defer l.Close()

// First bind with a read only user
err = l.Bind(m.bindUsername, m.bindPassword)
if err != nil {
return []string{}, err
}

// Search for the given clientID
searchRequest := ldap.NewSearchRequest(
m.baseDN,
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
fmt.Sprintf(m.groupfilter, uid.OpaqueId), // TODO this is screaming for errors if filter contains >1 %s
[]string{m.schema.CN},
nil,
)

sr, err := l.Search(searchRequest)
if err != nil {
return []string{}, err
}

groups := []string{}

for _, entry := range sr.Entries {
groups = append(groups, entry.GetAttributeValue(m.schema.CN))
}

return groups, nil
}

func (m *manager) IsInGroup(ctx context.Context, uid *userpb.UserId, group string) (bool, error) {
return false, nil // FIXME implement IsInGroup for ldap user manager
groups, err := m.GetUserGroups(ctx, uid)
if err != nil {
return false, err
}

for _, g := range groups {
if g == group {
return true, nil
}
}

return false, nil
}

0 comments on commit 84b5f3b

Please sign in to comment.