LDAP: Allow setting minimum TLS version and accepted ciphers (#63646)
* update ldap library and use go module path * add TLS min version and accepted min TLS version * set default min ver to library default * set default min ver to library default * add cipher list to toml * Update pkg/services/ldap/settings.go Co-authored-by: Karl Persson <kalle.persson@grafana.com> * Apply suggestions from code review Co-authored-by: Christopher Moyer <35463610+chri2547@users.noreply.github.com> * lint --------- Co-authored-by: Karl Persson <kalle.persson@grafana.com> Co-authored-by: Christopher Moyer <35463610+chri2547@users.noreply.github.com>
This commit is contained in:
co-authored by
Karl Persson
Christopher Moyer
parent
2ee73ad7f9
commit
7e97dbde65
@@ -1,8 +1,10 @@
|
||||
package ldap
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
@@ -21,18 +23,24 @@ type Config struct {
|
||||
|
||||
// ServerConfig holds connection data to LDAP
|
||||
type ServerConfig struct {
|
||||
Host string `toml:"host"`
|
||||
Port int `toml:"port"`
|
||||
UseSSL bool `toml:"use_ssl"`
|
||||
StartTLS bool `toml:"start_tls"`
|
||||
SkipVerifySSL bool `toml:"ssl_skip_verify"`
|
||||
RootCACert string `toml:"root_ca_cert"`
|
||||
ClientCert string `toml:"client_cert"`
|
||||
ClientKey string `toml:"client_key"`
|
||||
BindDN string `toml:"bind_dn"`
|
||||
BindPassword string `toml:"bind_password"`
|
||||
Timeout int `toml:"timeout"`
|
||||
Attr AttributeMap `toml:"attributes"`
|
||||
Host string `toml:"host"`
|
||||
Port int `toml:"port"`
|
||||
|
||||
UseSSL bool `toml:"use_ssl"`
|
||||
StartTLS bool `toml:"start_tls"`
|
||||
SkipVerifySSL bool `toml:"ssl_skip_verify"`
|
||||
MinTLSVersion string `toml:"min_tls_version"`
|
||||
minTLSVersion uint16 `toml:"-"`
|
||||
TLSCiphers []string `toml:"tls_ciphers"`
|
||||
tlsCiphers []uint16 `toml:"-"`
|
||||
|
||||
RootCACert string `toml:"root_ca_cert"`
|
||||
ClientCert string `toml:"client_cert"`
|
||||
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"`
|
||||
SearchBaseDNs []string `toml:"search_base_dns"`
|
||||
@@ -135,6 +143,20 @@ func readConfig(configFile string) (*Config, error) {
|
||||
return nil, fmt.Errorf("%v: %w", "Failed to validate SearchBaseDNs section", err)
|
||||
}
|
||||
|
||||
if server.MinTLSVersion != "" {
|
||||
server.minTLSVersion, err = tlsNameToVersion(server.MinTLSVersion)
|
||||
if err != nil {
|
||||
logger.Error("Failed to set min TLS version. Ignoring", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(server.TLSCiphers) > 0 {
|
||||
server.tlsCiphers, err = tlsCiphersToIDs(server.TLSCiphers)
|
||||
if err != nil {
|
||||
logger.Error("Unrecognized TLS Cipher(s). Ignoring", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, groupMap := range server.Groups {
|
||||
if groupMap.OrgRole == "" && groupMap.IsGrafanaAdmin == nil {
|
||||
return nil, fmt.Errorf("LDAP group mapping: organization role or grafana admin status is required")
|
||||
@@ -169,3 +191,53 @@ func assertNotEmptyCfg(val interface{}, propName string) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// tlsNameToVersion converts a string to a tls version
|
||||
func tlsNameToVersion(name string) (uint16, error) {
|
||||
name = strings.ToUpper(name)
|
||||
switch name {
|
||||
case "TLS1.0":
|
||||
return tls.VersionTLS10, nil
|
||||
case "TLS1.1":
|
||||
return tls.VersionTLS11, nil
|
||||
case "TLS1.2":
|
||||
return tls.VersionTLS12, nil
|
||||
case "TLS1.3":
|
||||
return tls.VersionTLS13, nil
|
||||
}
|
||||
|
||||
return 0, fmt.Errorf("unknown tls version: %q", name)
|
||||
}
|
||||
|
||||
// Cipher strings https://go.dev/src/crypto/tls/cipher_suites.go
|
||||
// Ex: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" or "TLS_RSA_WITH_AES_128_CBC_SHA"
|
||||
func tlsCiphersToIDs(names []string) ([]uint16, error) {
|
||||
if len(names) == 0 || names == nil {
|
||||
// no ciphers specified, use defaults
|
||||
return nil, nil
|
||||
}
|
||||
var ids []uint16
|
||||
var missing []string
|
||||
|
||||
ciphers := tls.CipherSuites()
|
||||
var cipherMap = make(map[string]uint16, len(ciphers))
|
||||
for _, cipher := range ciphers {
|
||||
cipherMap[cipher.Name] = cipher.ID
|
||||
}
|
||||
|
||||
for _, name := range names {
|
||||
name = strings.ToUpper(name)
|
||||
id, ok := cipherMap[name]
|
||||
if !ok {
|
||||
missing = append(missing, name)
|
||||
continue
|
||||
}
|
||||
ids = append(ids, id)
|
||||
}
|
||||
|
||||
if len(missing) > 0 {
|
||||
return ids, fmt.Errorf("unknown ciphers: %v", missing)
|
||||
}
|
||||
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user