package config import ( "os" "path/filepath" "strings" "testing" ) func noEnv(string) string { return "" } func writeConfig(t *testing.T, body string) string { t.Helper() dir := t.TempDir() p := filepath.Join(dir, "config.yaml") if err := os.WriteFile(p, []byte(body), 0o600); err != nil { t.Fatal(err) } if err := os.Chmod(p, 0o600); err != nil { t.Fatal(err) } return p } func TestLoadRejectsWorldReadableConfig(t *testing.T) { p := writeConfig(t, minimalYAML) if err := os.Chmod(p, 0o644); err != nil { t.Fatal(err) } if _, err := Load(p, noEnv); err == nil { t.Fatal("0644-Config muss den Start abbrechen") } } func TestLoadResolvesSecretFiles(t *testing.T) { dir := t.TempDir() secret := filepath.Join(dir, "apisecret") if err := os.WriteFile(secret, []byte(" FROM-FILE\n"), 0o600); err != nil { t.Fatal(err) } if err := os.Chmod(secret, 0o600); err != nil { t.Fatal(err) } body := strings.Replace(minimalYAML, ` api_secret: "SECRET"`, ` api_secret_file: "`+secret+`"`, 1) cfg, err := Load(writeConfig(t, body), noEnv) if err != nil { t.Fatalf("Load: %v", err) } if cfg.OPNsense.APISecret != "FROM-FILE" { t.Errorf("APISecret = %q, want FROM-FILE (getrimmt)", cfg.OPNsense.APISecret) } } func TestLoadRejectsLooseSecretFile(t *testing.T) { dir := t.TempDir() secret := filepath.Join(dir, "apisecret") if err := os.WriteFile(secret, []byte("x"), 0o644); err != nil { t.Fatal(err) } if err := os.Chmod(secret, 0o644); err != nil { t.Fatal(err) } body := strings.Replace(minimalYAML, ` api_secret: "SECRET"`, ` api_secret_file: "`+secret+`"`, 1) if _, err := Load(writeConfig(t, body), noEnv); err == nil { t.Fatal("Secret-Datei mit 0644 muss abgelehnt werden") } } func TestLoadEnvOverridesEverything(t *testing.T) { env := map[string]string{ "VPNPORTAL_OPNSENSE_API_SECRET": "FROM-ENV", "VPNPORTAL_AD_BIND_PASSWORD": "ENV-PW", } cfg, err := Load(writeConfig(t, minimalYAML), func(k string) string { return env[k] }) if err != nil { t.Fatalf("Load: %v", err) } if cfg.OPNsense.APISecret != "FROM-ENV" { t.Errorf("APISecret = %q, want FROM-ENV", cfg.OPNsense.APISecret) } if cfg.AD.BindPassword != "ENV-PW" { t.Errorf("BindPassword = %q, want ENV-PW", cfg.AD.BindPassword) } } func TestLoadRejectsBothInlineAndFile(t *testing.T) { body := strings.Replace(minimalYAML, ` api_secret: "SECRET"`, " api_secret: \"SECRET\"\n api_secret_file: \"/tmp/x\"", 1) _, err := Load(writeConfig(t, body), noEnv) if err == nil || !strings.Contains(err.Error(), "api_secret") { t.Fatalf("gleichzeitig gesetzte api_secret/api_secret_file müssen abgelehnt werden, got: %v", err) } }