286 lines
6.9 KiB
Go
286 lines
6.9 KiB
Go
package config
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
func TestLoadFileReadsYAML(t *testing.T) {
|
|
clearConfigEnv(t)
|
|
path := writeConfig(t, `
|
|
addr: ":9000"
|
|
pdns_api_url: "http://pdns.example.test:8081"
|
|
pdns_api_key: "from-file"
|
|
pdns_server_id: "authoritative"
|
|
auth:
|
|
disabled: true
|
|
`)
|
|
|
|
cfg, err := LoadFile(path)
|
|
if err != nil {
|
|
t.Fatalf("LoadFile returned error: %v", err)
|
|
}
|
|
|
|
if cfg.Addr != ":9000" {
|
|
t.Fatalf("unexpected addr: %q", cfg.Addr)
|
|
}
|
|
if cfg.PDNSAPIURL != "http://pdns.example.test:8081" {
|
|
t.Fatalf("unexpected api url: %q", cfg.PDNSAPIURL)
|
|
}
|
|
if cfg.PDNSAPIKey != "from-file" {
|
|
t.Fatalf("unexpected api key: %q", cfg.PDNSAPIKey)
|
|
}
|
|
if cfg.PDNSServerID != "authoritative" {
|
|
t.Fatalf("unexpected server id: %q", cfg.PDNSServerID)
|
|
}
|
|
}
|
|
|
|
func TestLoadFileEnvironmentOverridesYAML(t *testing.T) {
|
|
clearConfigEnv(t)
|
|
t.Setenv("PDNS_API_KEY", "from-env")
|
|
t.Setenv("PDNS_API_URL", "http://env.example.test:8081")
|
|
path := writeConfig(t, `
|
|
pdns_api_url: "http://file.example.test:8081"
|
|
pdns_api_key: "from-file"
|
|
pdns_server_id: "from-file"
|
|
auth:
|
|
disabled: true
|
|
`)
|
|
|
|
cfg, err := LoadFile(path)
|
|
if err != nil {
|
|
t.Fatalf("LoadFile returned error: %v", err)
|
|
}
|
|
|
|
if cfg.PDNSAPIKey != "from-env" {
|
|
t.Fatalf("expected env api key to win, got %q", cfg.PDNSAPIKey)
|
|
}
|
|
if cfg.PDNSAPIURL != "http://env.example.test:8081" {
|
|
t.Fatalf("expected env api url to win, got %q", cfg.PDNSAPIURL)
|
|
}
|
|
if cfg.PDNSServerID != "from-file" {
|
|
t.Fatalf("expected yaml server id, got %q", cfg.PDNSServerID)
|
|
}
|
|
}
|
|
|
|
func TestLoadFileUsesDefaultsWithoutYAML(t *testing.T) {
|
|
clearConfigEnv(t)
|
|
t.Setenv("PDNS_API_KEY", "secret")
|
|
t.Setenv("AUTH_DISABLED", "true")
|
|
|
|
cfg, err := LoadFile("")
|
|
if err != nil {
|
|
t.Fatalf("LoadFile returned error: %v", err)
|
|
}
|
|
|
|
if cfg.Addr != ":8080" {
|
|
t.Fatalf("unexpected default addr: %q", cfg.Addr)
|
|
}
|
|
if cfg.PDNSAPIURL != "http://localhost:8081" {
|
|
t.Fatalf("unexpected default api url: %q", cfg.PDNSAPIURL)
|
|
}
|
|
if cfg.PDNSServerID != "localhost" {
|
|
t.Fatalf("unexpected default server id: %q", cfg.PDNSServerID)
|
|
}
|
|
}
|
|
|
|
func TestLoadFileRequiresAPIKey(t *testing.T) {
|
|
clearConfigEnv(t)
|
|
|
|
_, err := LoadFile("")
|
|
if err == nil {
|
|
t.Fatal("expected missing api key error")
|
|
}
|
|
}
|
|
|
|
func TestLoadFileReadsLDAPConfig(t *testing.T) {
|
|
clearConfigEnv(t)
|
|
path := writeConfig(t, `
|
|
pdns_api_key: "secret"
|
|
auth:
|
|
ldap:
|
|
url: ldap://ldap.example.com:389
|
|
start_tls: true
|
|
insecure_skip_verify: true
|
|
bind_dn: cn=dashboard-reader,ou=service,dc=example,dc=com
|
|
bind_password: change-me
|
|
user_base_dn: ou=users,dc=example,dc=com
|
|
username_attribute: uid
|
|
user_filter: "({username_attribute}={username})"
|
|
group_base_dn: ou=groups,dc=example,dc=com
|
|
group_filter: "(&(objectClass=groupOfNames)(cn=media-admins)(member={user_dn}))"
|
|
`)
|
|
|
|
cfg, err := LoadFile(path)
|
|
if err != nil {
|
|
t.Fatalf("LoadFile returned error: %v", err)
|
|
}
|
|
if cfg.Auth.Disabled {
|
|
t.Fatal("auth should be enabled")
|
|
}
|
|
if cfg.Auth.LDAP.URL != "ldap://ldap.example.com:389" {
|
|
t.Fatalf("unexpected ldap url: %q", cfg.Auth.LDAP.URL)
|
|
}
|
|
if !cfg.Auth.LDAP.StartTLS {
|
|
t.Fatal("expected start_tls to be true")
|
|
}
|
|
if !cfg.Auth.LDAP.InsecureSkipVerify {
|
|
t.Fatal("expected insecure_skip_verify to be true")
|
|
}
|
|
if cfg.Auth.LDAP.GroupFilter == "" {
|
|
t.Fatal("expected group filter")
|
|
}
|
|
}
|
|
|
|
func TestLoadFileLDAPEnvironmentOverridesYAML(t *testing.T) {
|
|
clearConfigEnv(t)
|
|
t.Setenv("AUTH_LDAP_URL", "ldap://env.example.com:389")
|
|
t.Setenv("AUTH_LDAP_BIND_PASSWORD", "from-env")
|
|
path := writeConfig(t, `
|
|
pdns_api_key: "secret"
|
|
auth:
|
|
ldap:
|
|
url: ldap://file.example.com:389
|
|
bind_dn: cn=dashboard-reader,ou=service,dc=example,dc=com
|
|
bind_password: from-file
|
|
user_base_dn: ou=users,dc=example,dc=com
|
|
`)
|
|
|
|
cfg, err := LoadFile(path)
|
|
if err != nil {
|
|
t.Fatalf("LoadFile returned error: %v", err)
|
|
}
|
|
if cfg.Auth.LDAP.URL != "ldap://env.example.com:389" {
|
|
t.Fatalf("expected env ldap url, got %q", cfg.Auth.LDAP.URL)
|
|
}
|
|
if cfg.Auth.LDAP.BindPassword != "from-env" {
|
|
t.Fatalf("expected env bind password, got %q", cfg.Auth.LDAP.BindPassword)
|
|
}
|
|
}
|
|
|
|
func TestLoadFileRequiresLDAPUnlessAuthDisabled(t *testing.T) {
|
|
clearConfigEnv(t)
|
|
t.Setenv("PDNS_API_KEY", "secret")
|
|
|
|
_, err := LoadFile("")
|
|
if err == nil {
|
|
t.Fatal("expected missing ldap configuration error")
|
|
}
|
|
}
|
|
|
|
func TestConfigSearchPathsOrderOnUnix(t *testing.T) {
|
|
paths := configSearchPaths("/home/tester", "linux")
|
|
want := []string{
|
|
"/etc/pdns_admin/config.yaml",
|
|
filepath.Join("/home/tester", "config.yaml"),
|
|
"config.yaml",
|
|
}
|
|
|
|
if len(paths) != len(want) {
|
|
t.Fatalf("unexpected path count: %#v", paths)
|
|
}
|
|
for i := range want {
|
|
if paths[i] != want[i] {
|
|
t.Fatalf("path %d = %q, want %q", i, paths[i], want[i])
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestConfigSearchPathsOrderOnNonUnix(t *testing.T) {
|
|
paths := configSearchPaths(`C:\Users\tester`, "windows")
|
|
want := []string{
|
|
filepath.Join(`C:\Users\tester`, "config.yaml"),
|
|
"config.yaml",
|
|
}
|
|
|
|
if len(paths) != len(want) {
|
|
t.Fatalf("unexpected path count: %#v", paths)
|
|
}
|
|
for i := range want {
|
|
if paths[i] != want[i] {
|
|
t.Fatalf("path %d = %q, want %q", i, paths[i], want[i])
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestConfigSearchPathsWithoutHome(t *testing.T) {
|
|
paths := configSearchPaths("", "windows")
|
|
want := []string{"config.yaml"}
|
|
|
|
if len(paths) != len(want) {
|
|
t.Fatalf("unexpected path count: %#v", paths)
|
|
}
|
|
if paths[0] != want[0] {
|
|
t.Fatalf("path = %q, want %q", paths[0], want[0])
|
|
}
|
|
}
|
|
|
|
func TestFirstExistingConfigPathUsesOrder(t *testing.T) {
|
|
root := t.TempDir()
|
|
first := filepath.Join(root, "first.yaml")
|
|
second := filepath.Join(root, "second.yaml")
|
|
if err := os.WriteFile(second, []byte("pdns_api_key: second"), 0o600); err != nil {
|
|
t.Fatalf("write second config: %v", err)
|
|
}
|
|
if err := os.WriteFile(first, []byte("pdns_api_key: first"), 0o600); err != nil {
|
|
t.Fatalf("write first config: %v", err)
|
|
}
|
|
|
|
got := firstExistingConfigPath([]string{first, second})
|
|
if got != first {
|
|
t.Fatalf("got %q, want %q", got, first)
|
|
}
|
|
}
|
|
|
|
func writeConfig(t *testing.T, contents string) string {
|
|
t.Helper()
|
|
|
|
path := filepath.Join(t.TempDir(), "config.yaml")
|
|
if err := os.WriteFile(path, []byte(contents), 0o600); err != nil {
|
|
t.Fatalf("write config: %v", err)
|
|
}
|
|
return path
|
|
}
|
|
|
|
func clearConfigEnv(t *testing.T) {
|
|
t.Helper()
|
|
|
|
for _, key := range []string{
|
|
"CONFIG_FILE",
|
|
"ADDR",
|
|
"PDNS_API_URL",
|
|
"PDNS_API_KEY",
|
|
"PDNS_SERVER_ID",
|
|
"AUTH_DISABLED",
|
|
"AUTH_LDAP_URL",
|
|
"AUTH_LDAP_START_TLS",
|
|
"AUTH_LDAP_INSECURE_SKIP_VERIFY",
|
|
"AUTH_LDAP_BIND_DN",
|
|
"AUTH_LDAP_BIND_PASSWORD",
|
|
"AUTH_LDAP_USER_BASE_DN",
|
|
"AUTH_LDAP_USERNAME_ATTRIBUTE",
|
|
"AUTH_LDAP_USER_FILTER",
|
|
"AUTH_LDAP_GROUP_BASE_DN",
|
|
"AUTH_LDAP_GROUP_FILTER",
|
|
} {
|
|
unsetEnv(t, key)
|
|
}
|
|
}
|
|
|
|
func unsetEnv(t *testing.T, key string) {
|
|
t.Helper()
|
|
|
|
oldValue, hadValue := os.LookupEnv(key)
|
|
if err := os.Unsetenv(key); err != nil {
|
|
t.Fatalf("unset %s: %v", key, err)
|
|
}
|
|
t.Cleanup(func() {
|
|
if hadValue {
|
|
_ = os.Setenv(key, oldValue)
|
|
return
|
|
}
|
|
_ = os.Unsetenv(key)
|
|
})
|
|
}
|