Attempt connection to LDAP server at login time.

Also switch to a LDAP library fork which fixes a panic when
shutting down a connection immediately.
This commit is contained in:
Giovanni Bajo 2015-05-07 00:39:02 +02:00
parent 7492c5712a
commit 7e39da2e67
2 changed files with 40 additions and 39 deletions

View File

@ -1,11 +1,14 @@
package ldap
import (
"fmt"
"net"
"net/url"
"strings"
"github.com/hashicorp/vault/logical"
"github.com/hashicorp/vault/logical/framework"
"github.com/vanackere/ldap"
)
func pathConfig(b *backend) *framework.Path {
@ -89,9 +92,14 @@ func (b *backend) pathConfigWrite(
cfg.Domain = domain
}
if !cfg.ValidateURL() {
return logical.ErrorResponse("LDAP URL is malformed"), nil
// Try to connect to the LDAP server, to validate the URL configuration
// We can also check the URL at this stage, as anything else would probably
// require authentication.
conn, cerr := cfg.DialLDAP()
if cerr != nil {
return logical.ErrorResponse(cerr.Error()), nil
}
conn.Close()
entry, err := logical.StorageEntryJSON("config", cfg)
if err != nil {
@ -110,18 +118,37 @@ type ConfigEntry struct {
UserAttr string
}
func (c *ConfigEntry) ValidateURL() bool {
func (c *ConfigEntry) DialLDAP() (*ldap.Conn, error) {
u, err := url.Parse(c.Url)
if err != nil {
return false
return nil, err
}
if u.Scheme != "ldap" && u.Scheme != "ldaps" {
return false
host, port, err := net.SplitHostPort(u.Host)
if err != nil {
host = u.Host
}
if u.Path != "" {
return false
var conn *ldap.Conn
switch u.Scheme {
case "ldap":
if port == "" {
port = "389"
}
conn, err = ldap.Dial("tcp", host+":"+port)
case "ldaps":
if port == "" {
port = "636"
}
conn, err = ldap.DialTLS("tcp", host+":"+port, nil)
default:
return nil, fmt.Errorf("invalid LDAP scheme")
}
return true
if err != nil {
return nil, fmt.Errorf("cannot connect to LDAP: %v", err)
}
return conn, nil
}
func (c *ConfigEntry) SetDefaults() {

View File

@ -2,12 +2,9 @@ package ldap
import (
"fmt"
"net"
"net/url"
"github.com/hashicorp/vault/logical"
"github.com/hashicorp/vault/logical/framework"
"github.com/mmitton/ldap"
)
func pathLogin(b *backend) *framework.Path {
@ -47,37 +44,14 @@ func (b *backend) pathLogin(
return logical.ErrorResponse("ldap backend not configured"), nil
}
u, err := url.Parse(cfg.Url)
c, err := cfg.DialLDAP()
if err != nil {
return nil, err
}
host, port, err := net.SplitHostPort(u.Host)
if err != nil {
host = u.Host
}
var c *ldap.Conn
var cerr *ldap.Error
switch u.Scheme {
case "ldap":
if port == "" {
port = "389"
}
c, cerr = ldap.Dial("tcp", host+":"+port)
case "ldaps":
if port == "" {
port = "636"
}
c, cerr = ldap.DialSSL("tcp", host+":"+port)
default:
return logical.ErrorResponse("invalid LDAP URL scheme"), nil
}
if cerr != nil {
return nil, cerr
return logical.ErrorResponse(err.Error()), nil
}
// Try to authenticate to the server using the provided credentials
binddn := fmt.Sprintf("%s=%s,%s", cfg.UserAttr, username, cfg.Domain)
cerr = c.Bind(binddn, password)
cerr := c.Bind(binddn, password)
if cerr != nil {
return logical.ErrorResponse(fmt.Sprintf("LDAP bind failed: %s", cerr.Error())), nil
}