154 lines
4.5 KiB
Go
154 lines
4.5 KiB
Go
package config
|
|
|
|
import (
|
|
"errors"
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"sort"
|
|
"strings"
|
|
|
|
"github.com/ilyakaznacheev/cleanenv"
|
|
)
|
|
|
|
type Config struct {
|
|
Addr string `yaml:"addr" env:"ADDR" env-default:":8080"`
|
|
PDNSAPIURL string `yaml:"pdns_api_url" env:"PDNS_API_URL" env-default:"http://localhost:8081"`
|
|
PDNSAPIKey string `yaml:"pdns_api_key" env:"PDNS_API_KEY"`
|
|
PDNSServerID string `yaml:"pdns_server_id" env:"PDNS_SERVER_ID" env-default:"localhost"`
|
|
Auth AuthConfig `yaml:"auth"`
|
|
}
|
|
|
|
type AuthConfig struct {
|
|
Disabled bool `yaml:"disabled" env:"AUTH_DISABLED"`
|
|
LDAP LDAPConfig `yaml:"ldap"`
|
|
}
|
|
|
|
type LDAPConfig struct {
|
|
URL string `yaml:"url" env:"AUTH_LDAP_URL"`
|
|
StartTLS bool `yaml:"start_tls" env:"AUTH_LDAP_START_TLS"`
|
|
InsecureSkipVerify bool `yaml:"insecure_skip_verify" env:"AUTH_LDAP_INSECURE_SKIP_VERIFY"`
|
|
BindDN string `yaml:"bind_dn" env:"AUTH_LDAP_BIND_DN"`
|
|
BindPassword string `yaml:"bind_password" env:"AUTH_LDAP_BIND_PASSWORD"`
|
|
UserBaseDN string `yaml:"user_base_dn" env:"AUTH_LDAP_USER_BASE_DN"`
|
|
UsernameAttribute string `yaml:"username_attribute" env:"AUTH_LDAP_USERNAME_ATTRIBUTE" env-default:"uid"`
|
|
UserFilter string `yaml:"user_filter" env:"AUTH_LDAP_USER_FILTER" env-default:"({username_attribute}={username})"`
|
|
GroupBaseDN string `yaml:"group_base_dn" env:"AUTH_LDAP_GROUP_BASE_DN"`
|
|
GroupFilter string `yaml:"group_filter" env:"AUTH_LDAP_GROUP_FILTER"`
|
|
}
|
|
|
|
func Load() (Config, error) {
|
|
path := strings.TrimSpace(os.Getenv("CONFIG_FILE"))
|
|
if path == "" {
|
|
path = defaultConfigPath()
|
|
}
|
|
|
|
return LoadFile(path)
|
|
}
|
|
|
|
func LoadFile(path string) (Config, error) {
|
|
var cfg Config
|
|
|
|
var err error
|
|
if strings.TrimSpace(path) == "" {
|
|
err = cleanenv.ReadEnv(&cfg)
|
|
} else {
|
|
err = cleanenv.ReadConfig(path, &cfg)
|
|
}
|
|
if err != nil {
|
|
return Config{}, err
|
|
}
|
|
|
|
normalize(&cfg)
|
|
if cfg.PDNSAPIKey == "" {
|
|
return Config{}, errors.New("PDNS_API_KEY is required")
|
|
}
|
|
if err := validateAuth(cfg.Auth); err != nil {
|
|
return Config{}, err
|
|
}
|
|
|
|
return cfg, nil
|
|
}
|
|
|
|
func defaultConfigPath() string {
|
|
homeDir, err := os.UserHomeDir()
|
|
if err != nil {
|
|
homeDir = ""
|
|
}
|
|
|
|
return firstExistingConfigPath(configSearchPaths(homeDir, runtime.GOOS))
|
|
}
|
|
|
|
func configSearchPaths(homeDir, goos string) []string {
|
|
paths := make([]string, 0, 3)
|
|
if isUnixLike(goos) {
|
|
paths = append(paths, "/etc/pdns_admin/config.yaml")
|
|
}
|
|
if homeDir != "" {
|
|
paths = append(paths, filepath.Join(homeDir, "config.yaml"))
|
|
}
|
|
return append(paths, "config.yaml")
|
|
}
|
|
|
|
func isUnixLike(goos string) bool {
|
|
switch goos {
|
|
case "aix", "android", "darwin", "dragonfly", "freebsd", "hurd", "illumos", "ios", "linux", "netbsd", "openbsd", "solaris":
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
func firstExistingConfigPath(paths []string) string {
|
|
for _, path := range paths {
|
|
if _, err := os.Stat(path); err == nil {
|
|
return path
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func normalize(cfg *Config) {
|
|
cfg.Addr = strings.TrimSpace(cfg.Addr)
|
|
cfg.PDNSAPIURL = strings.TrimSpace(cfg.PDNSAPIURL)
|
|
cfg.PDNSAPIKey = strings.TrimSpace(cfg.PDNSAPIKey)
|
|
cfg.PDNSServerID = strings.TrimSpace(cfg.PDNSServerID)
|
|
cfg.Auth.LDAP.URL = strings.TrimSpace(cfg.Auth.LDAP.URL)
|
|
cfg.Auth.LDAP.BindDN = strings.TrimSpace(cfg.Auth.LDAP.BindDN)
|
|
cfg.Auth.LDAP.BindPassword = strings.TrimSpace(cfg.Auth.LDAP.BindPassword)
|
|
cfg.Auth.LDAP.UserBaseDN = strings.TrimSpace(cfg.Auth.LDAP.UserBaseDN)
|
|
cfg.Auth.LDAP.UsernameAttribute = strings.TrimSpace(cfg.Auth.LDAP.UsernameAttribute)
|
|
cfg.Auth.LDAP.UserFilter = strings.TrimSpace(cfg.Auth.LDAP.UserFilter)
|
|
cfg.Auth.LDAP.GroupBaseDN = strings.TrimSpace(cfg.Auth.LDAP.GroupBaseDN)
|
|
cfg.Auth.LDAP.GroupFilter = strings.TrimSpace(cfg.Auth.LDAP.GroupFilter)
|
|
}
|
|
|
|
func validateAuth(auth AuthConfig) error {
|
|
if auth.Disabled {
|
|
return nil
|
|
}
|
|
|
|
missing := make([]string, 0)
|
|
for field, value := range map[string]string{
|
|
"AUTH_LDAP_URL": auth.LDAP.URL,
|
|
"AUTH_LDAP_BIND_DN": auth.LDAP.BindDN,
|
|
"AUTH_LDAP_BIND_PASSWORD": auth.LDAP.BindPassword,
|
|
"AUTH_LDAP_USER_BASE_DN": auth.LDAP.UserBaseDN,
|
|
"AUTH_LDAP_USERNAME_ATTRIBUTE": auth.LDAP.UsernameAttribute,
|
|
"AUTH_LDAP_USER_FILTER": auth.LDAP.UserFilter,
|
|
} {
|
|
if value == "" {
|
|
missing = append(missing, field)
|
|
}
|
|
}
|
|
if auth.LDAP.GroupFilter != "" && auth.LDAP.GroupBaseDN == "" {
|
|
missing = append(missing, "AUTH_LDAP_GROUP_BASE_DN")
|
|
}
|
|
if len(missing) > 0 {
|
|
sort.Strings(missing)
|
|
return errors.New("LDAP auth is enabled; missing required configuration: " + strings.Join(missing, ", "))
|
|
}
|
|
|
|
return nil
|
|
}
|