Commit 3b9f0e6e by Marcus Efraimsson

fix allow anonymous initial bind for ldap search

parent 744bf6a7
......@@ -18,6 +18,7 @@ import (
type ILdapConn interface {
Bind(username, password string) error
UnauthenticatedBind(username string) error
Search(*ldap.SearchRequest) (*ldap.SearchResult, error)
StartTLS(*tls.Config) error
Close()
......@@ -259,7 +260,17 @@ func (a *ldapAuther) initialBind(username, userPassword string) error {
bindPath = fmt.Sprintf(a.server.BindDN, username)
}
if err := a.conn.Bind(bindPath, userPassword); err != nil {
bindFn := func() error {
return a.conn.Bind(bindPath, userPassword)
}
if userPassword == "" {
bindFn = func() error {
return a.conn.UnauthenticatedBind(bindPath)
}
}
if err := bindFn(); err != nil {
a.log.Info("Initial bind failed", "error", err)
if ldapErr, ok := err.(*ldap.Error); ok {
......
......@@ -13,6 +13,70 @@ import (
)
func TestLdapAuther(t *testing.T) {
Convey("initialBind", t, func() {
Convey("Given bind dn and password configured", func() {
conn := &mockLdapConn{}
var actualUsername, actualPassword string
conn.bindProvider = func(username, password string) error {
actualUsername = username
actualPassword = password
return nil
}
ldapAuther := &ldapAuther{
conn: conn,
server: &LdapServerConf{
BindDN: "cn=%s,o=users,dc=grafana,dc=org",
BindPassword: "bindpwd",
},
}
err := ldapAuther.initialBind("user", "pwd")
So(err, ShouldBeNil)
So(ldapAuther.requireSecondBind, ShouldBeTrue)
So(actualUsername, ShouldEqual, "cn=user,o=users,dc=grafana,dc=org")
So(actualPassword, ShouldEqual, "bindpwd")
})
Convey("Given bind dn configured", func() {
conn := &mockLdapConn{}
var actualUsername, actualPassword string
conn.bindProvider = func(username, password string) error {
actualUsername = username
actualPassword = password
return nil
}
ldapAuther := &ldapAuther{
conn: conn,
server: &LdapServerConf{
BindDN: "cn=%s,o=users,dc=grafana,dc=org",
},
}
err := ldapAuther.initialBind("user", "pwd")
So(err, ShouldBeNil)
So(ldapAuther.requireSecondBind, ShouldBeFalse)
So(actualUsername, ShouldEqual, "cn=user,o=users,dc=grafana,dc=org")
So(actualPassword, ShouldEqual, "pwd")
})
Convey("Given empty bind dn and password", func() {
conn := &mockLdapConn{}
unauthenticatedBindWasCalled := false
var actualUsername string
conn.unauthenticatedBindProvider = func(username string) error {
unauthenticatedBindWasCalled = true
actualUsername = username
return nil
}
ldapAuther := &ldapAuther{
conn: conn,
server: &LdapServerConf{},
}
err := ldapAuther.initialBind("user", "pwd")
So(err, ShouldBeNil)
So(ldapAuther.requireSecondBind, ShouldBeTrue)
So(unauthenticatedBindWasCalled, ShouldBeTrue)
So(actualUsername, ShouldBeEmpty)
})
})
Convey("When translating ldap user to grafana user", t, func() {
......@@ -368,9 +432,23 @@ type mockLdapConn struct {
result *ldap.SearchResult
searchCalled bool
searchAttributes []string
bindProvider func(username, password string) error
unauthenticatedBindProvider func(username string) error
}
func (c *mockLdapConn) Bind(username, password string) error {
if c.bindProvider != nil {
return c.bindProvider(username, password)
}
return nil
}
func (c *mockLdapConn) UnauthenticatedBind(username string) error {
if c.unauthenticatedBindProvider != nil {
return c.unauthenticatedBindProvider(username)
}
return nil
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment