mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
LDAP: Allow specifying LDAP timeout (#48870)
* Allow specifying LDAP timeout * Update docs/sources/auth/ldap.md Co-authored-by: brendamuir <100768211+brendamuir@users.noreply.github.com> * LDAP timeout: Add annotations; Make functions "private" * Setting the default timeout if unspecified * fix goimports lint issue Co-authored-by: brendamuir <100768211+brendamuir@users.noreply.github.com> Co-authored-by: Gabriel MABILLE <gamab@users.noreply.github.com> Co-authored-by: jguer <joao.guerreiro@grafana.com>
This commit is contained in:
parent
cff763ca1d
commit
62b0a8bae6
@ -25,6 +25,9 @@ bind_dn = "cn=admin,dc=grafana,dc=org"
|
||||
# If the password contains # or ; you have to wrap it with triple quotes. Ex """#password;"""
|
||||
bind_password = 'grafana'
|
||||
|
||||
# Timeout in seconds (applies to each host specified in the 'host' entry (space separated))
|
||||
timeout = 10
|
||||
|
||||
# User search filter, for example "(cn=%s)" or "(sAMAccountName=%s)" or "(uid=%s)"
|
||||
search_filter = "(cn=%s)"
|
||||
|
||||
|
@ -72,6 +72,9 @@ bind_dn = "cn=admin,dc=grafana,dc=org"
|
||||
# If the password contains # or ; you have to wrap it with triple quotes. Ex """#password;"""
|
||||
bind_password = "grafana"
|
||||
|
||||
# Timeout in seconds. Applies to each host specified in the 'host' entry (space separated).
|
||||
timeout = 10
|
||||
|
||||
# User search filter, for example "(cn=%s)" or "(sAMAccountName=%s)" or "(uid=%s)"
|
||||
# Allow login from email or username, example "(|(sAMAccountName=%s)(userPrincipalName=%s))"
|
||||
search_filter = "(cn=%s)"
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"gopkg.in/ldap.v3"
|
||||
@ -114,6 +115,9 @@ func (server *Server) Dial() error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
timeout := time.Duration(server.Config.Timeout) * time.Second
|
||||
|
||||
for _, host := range strings.Split(server.Config.Host, " ") {
|
||||
// Remove any square brackets enclosing IPv6 addresses, a format we support for backwards compatibility
|
||||
host = strings.TrimSuffix(strings.TrimPrefix(host, "["), "]")
|
||||
@ -128,17 +132,17 @@ func (server *Server) Dial() error {
|
||||
tlsCfg.Certificates = append(tlsCfg.Certificates, clientCert)
|
||||
}
|
||||
if server.Config.StartTLS {
|
||||
server.Connection, err = ldap.Dial("tcp", address)
|
||||
server.Connection, err = dialWithTimeout("tcp", address, timeout)
|
||||
if err == nil {
|
||||
if err = server.Connection.StartTLS(tlsCfg); err == nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
} else {
|
||||
server.Connection, err = ldap.DialTLS("tcp", address, tlsCfg)
|
||||
server.Connection, err = dialTLSWithTimeout("tcp", address, tlsCfg, timeout)
|
||||
}
|
||||
} else {
|
||||
server.Connection, err = ldap.Dial("tcp", address)
|
||||
server.Connection, err = dialWithTimeout("tcp", address, timeout)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
@ -148,6 +152,30 @@ func (server *Server) Dial() error {
|
||||
return err
|
||||
}
|
||||
|
||||
// dialWithTimeout applies the specified timeout
|
||||
// and connects to the given address on the given network using net.Dial
|
||||
func dialWithTimeout(network, addr string, timeout time.Duration) (*ldap.Conn, error) {
|
||||
c, err := net.DialTimeout(network, addr, timeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conn := ldap.NewConn(c, false)
|
||||
conn.Start()
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
// dialTLSWithTimeout applies the specified timeout
|
||||
// connects to the given address on the given network using tls.Dial
|
||||
func dialTLSWithTimeout(network, addr string, config *tls.Config, timeout time.Duration) (*ldap.Conn, error) {
|
||||
c, err := tls.DialWithDialer(&net.Dialer{Timeout: timeout}, network, addr, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conn := ldap.NewConn(c, true)
|
||||
conn.Start()
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
// Close closes the LDAP connection
|
||||
// Dial() sets the connection with the server for this Struct. Therefore, we require a
|
||||
// call to Dial() before being able to execute this function.
|
||||
|
@ -12,6 +12,8 @@ import (
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
const defaultTimeout = 10
|
||||
|
||||
// Config holds list of connections to LDAP
|
||||
type Config struct {
|
||||
Servers []*ServerConfig `toml:"servers"`
|
||||
@ -29,6 +31,7 @@ type ServerConfig struct {
|
||||
ClientKey string `toml:"client_key"`
|
||||
BindDN string `toml:"bind_dn"`
|
||||
BindPassword string `toml:"bind_password"`
|
||||
Timeout int `toml:"timeout"`
|
||||
Attr AttributeMap `toml:"attributes"`
|
||||
|
||||
SearchFilter string `toml:"search_filter"`
|
||||
@ -140,8 +143,8 @@ func readConfig(configFile string) (*Config, error) {
|
||||
return nil, fmt.Errorf("LDAP enabled but no LDAP servers defined in config file")
|
||||
}
|
||||
|
||||
// set default org id
|
||||
for _, server := range result.Servers {
|
||||
// set default org id
|
||||
err = assertNotEmptyCfg(server.SearchFilter, "search_filter")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%v: %w", "Failed to validate SearchFilter section", err)
|
||||
@ -160,6 +163,11 @@ func readConfig(configFile string) (*Config, error) {
|
||||
groupMap.OrgId = 1
|
||||
}
|
||||
}
|
||||
|
||||
// set default timeout if unspecified
|
||||
if server.Timeout == 0 {
|
||||
server.Timeout = defaultTimeout
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
|
Loading…
Reference in New Issue
Block a user