Bladeren bron

feat(ldap): added support for binding initially with an admin user searching for user and then binding again to authenticate current user, #1450

Torkel Ödegaard 10 jaren geleden
bovenliggende
commit
262a09bb2d
2 gewijzigde bestanden met toevoegingen van 29 en 2 verwijderingen
  1. 28 2
      pkg/auth/ldap.go
  2. 1 0
      pkg/auth/ldap_user.go

+ 28 - 2
pkg/auth/ldap.go

@@ -3,6 +3,7 @@ package auth
 import (
 	"errors"
 	"fmt"
+	"strings"
 
 	"github.com/go-ldap/ldap"
 	"github.com/grafana/grafana/pkg/bus"
@@ -18,7 +19,8 @@ func init() {
 			UseSSL:        false,
 			Host:          "127.0.0.1",
 			Port:          "389",
-			BindDN:        "cn=%s,dc=grafana,dc=org",
+			BindDN:        "cn=admin,dc=grafana,dc=org",
+			BindPassword:  "grafana",
 			AttrName:      "givenName",
 			AttrSurname:   "sn",
 			AttrUsername:  "cn",
@@ -74,6 +76,13 @@ func (a *ldapAuther) login(query *AuthenticateUserQuery) error {
 		log.Info("email: %s", ldapUser.Email)
 		log.Info("memberOf: %s", ldapUser.MemberOf)
 
+		// check if a second user bind is needed
+		if a.server.BindPassword != "" {
+			if err := a.secondBind(ldapUser, query.Password); err != nil {
+				return err
+			}
+		}
+
 		if grafanaUser, err := a.getGrafanaUserFor(ldapUser); err != nil {
 			return err
 		} else {
@@ -190,12 +199,28 @@ func (a *ldapAuther) syncOrgRoles(user *m.User, ldapUser *ldapUserInfo) error {
 	return nil
 }
 
+func (a *ldapAuther) secondBind(ldapUser *ldapUserInfo, userPassword string) error {
+	if err := a.conn.Bind(ldapUser.DN, userPassword); err != nil {
+		if ldapErr, ok := err.(*ldap.Error); ok {
+			if ldapErr.ResultCode == 49 {
+				return ErrInvalidCredentials
+			}
+		}
+		return err
+	}
+
+	return nil
+}
+
 func (a *ldapAuther) initialBind(username, userPassword string) error {
 	if a.server.BindPassword != "" {
 		userPassword = a.server.BindPassword
 	}
 
-	bindPath := fmt.Sprintf(a.server.BindDN, username)
+	bindPath := a.server.BindDN
+	if strings.Contains(bindPath, "%s") {
+		bindPath = fmt.Sprintf(a.server.BindDN, username)
+	}
 
 	if err := a.conn.Bind(bindPath, userPassword); err != nil {
 		if ldapErr, ok := err.(*ldap.Error); ok {
@@ -247,6 +272,7 @@ func (a *ldapAuther) searchForUser(username string) (*ldapUserInfo, error) {
 	}
 
 	return &ldapUserInfo{
+		DN:        searchResult.Entries[0].DN,
 		LastName:  getLdapAttr(a.server.AttrSurname, searchResult),
 		FirstName: getLdapAttr(a.server.AttrName, searchResult),
 		Username:  getLdapAttr(a.server.AttrUsername, searchResult),

+ 1 - 0
pkg/auth/ldap_user.go

@@ -1,6 +1,7 @@
 package auth
 
 type ldapUserInfo struct {
+	DN        string
 	FirstName string
 	LastName  string
 	Username  string