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:
parent
7492c5712a
commit
7e39da2e67
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue