|
|
|
|
@ -2,9 +2,11 @@ package ldap |
|
|
|
|
|
|
|
|
|
import ( |
|
|
|
|
"fmt" |
|
|
|
|
"os" |
|
|
|
|
"sync" |
|
|
|
|
|
|
|
|
|
"github.com/BurntSushi/toml" |
|
|
|
|
"github.com/grafana/grafana/pkg/util/errutil" |
|
|
|
|
"golang.org/x/xerrors" |
|
|
|
|
|
|
|
|
|
"github.com/grafana/grafana/pkg/log" |
|
|
|
|
m "github.com/grafana/grafana/pkg/models" |
|
|
|
|
@ -56,47 +58,72 @@ type GroupToOrgRole struct { |
|
|
|
|
var config *Config |
|
|
|
|
var logger = log.New("ldap") |
|
|
|
|
|
|
|
|
|
// loadingMutex locks the reading of the config so multiple requests for reloading are sequential.
|
|
|
|
|
var loadingMutex = &sync.Mutex{} |
|
|
|
|
|
|
|
|
|
// IsEnabled checks if ldap is enabled
|
|
|
|
|
func IsEnabled() bool { |
|
|
|
|
return setting.LdapEnabled |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// ReadConfig reads the config if
|
|
|
|
|
// ldap is enabled otherwise it will return nil
|
|
|
|
|
func ReadConfig() *Config { |
|
|
|
|
// ReloadConfig reads the config from the disc and caches it.
|
|
|
|
|
func ReloadConfig() error { |
|
|
|
|
if IsEnabled() == false { |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
loadingMutex.Lock() |
|
|
|
|
defer loadingMutex.Unlock() |
|
|
|
|
|
|
|
|
|
var err error |
|
|
|
|
config, err = readConfig(setting.LdapConfigFile) |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// GetConfig returns the LDAP config if LDAP is enabled otherwise it returns nil. It returns either cached value of
|
|
|
|
|
// the config or it reads it and caches it first.
|
|
|
|
|
func GetConfig() (*Config, error) { |
|
|
|
|
if IsEnabled() == false { |
|
|
|
|
return nil, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Make it a singleton
|
|
|
|
|
if config != nil { |
|
|
|
|
return config |
|
|
|
|
return config, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
config = getConfig(setting.LdapConfigFile) |
|
|
|
|
loadingMutex.Lock() |
|
|
|
|
defer loadingMutex.Unlock() |
|
|
|
|
|
|
|
|
|
var err error |
|
|
|
|
config, err = readConfig(setting.LdapConfigFile) |
|
|
|
|
|
|
|
|
|
return config |
|
|
|
|
return config, err |
|
|
|
|
} |
|
|
|
|
func getConfig(configFile string) *Config { |
|
|
|
|
|
|
|
|
|
func readConfig(configFile string) (*Config, error) { |
|
|
|
|
result := &Config{} |
|
|
|
|
|
|
|
|
|
logger.Info("Ldap enabled, reading config file", "file", configFile) |
|
|
|
|
|
|
|
|
|
_, err := toml.DecodeFile(configFile, result) |
|
|
|
|
if err != nil { |
|
|
|
|
logger.Crit("Failed to load ldap config file", "error", err) |
|
|
|
|
os.Exit(1) |
|
|
|
|
return nil, errutil.Wrap("Failed to load ldap config file", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if len(result.Servers) == 0 { |
|
|
|
|
logger.Crit("ldap enabled but no ldap servers defined in config file") |
|
|
|
|
os.Exit(1) |
|
|
|
|
return nil, xerrors.New("ldap enabled but no ldap servers defined in config file") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// set default org id
|
|
|
|
|
for _, server := range result.Servers { |
|
|
|
|
assertNotEmptyCfg(server.SearchFilter, "search_filter") |
|
|
|
|
assertNotEmptyCfg(server.SearchBaseDNs, "search_base_dns") |
|
|
|
|
err = assertNotEmptyCfg(server.SearchFilter, "search_filter") |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, errutil.Wrap("Failed to validate SearchFilter section", err) |
|
|
|
|
} |
|
|
|
|
err = assertNotEmptyCfg(server.SearchBaseDNs, "search_base_dns") |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, errutil.Wrap("Failed to validate SearchBaseDNs section", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for _, groupMap := range server.Groups { |
|
|
|
|
if groupMap.OrgId == 0 { |
|
|
|
|
@ -105,22 +132,21 @@ func getConfig(configFile string) *Config { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return result |
|
|
|
|
return result, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func assertNotEmptyCfg(val interface{}, propName string) { |
|
|
|
|
func assertNotEmptyCfg(val interface{}, propName string) error { |
|
|
|
|
switch v := val.(type) { |
|
|
|
|
case string: |
|
|
|
|
if v == "" { |
|
|
|
|
logger.Crit("LDAP config file is missing option", "option", propName) |
|
|
|
|
os.Exit(1) |
|
|
|
|
return xerrors.Errorf("LDAP config file is missing option: %v", propName) |
|
|
|
|
} |
|
|
|
|
case []string: |
|
|
|
|
if len(v) == 0 { |
|
|
|
|
logger.Crit("LDAP config file is missing option", "option", propName) |
|
|
|
|
os.Exit(1) |
|
|
|
|
return xerrors.Errorf("LDAP config file is missing option: %v", propName) |
|
|
|
|
} |
|
|
|
|
default: |
|
|
|
|
fmt.Println("unknown") |
|
|
|
|
} |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|