137 lines
4.0 KiB
Go
137 lines
4.0 KiB
Go
package config
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestWithERPEnvironmentFileUsesApprovedFallbackValues(t *testing.T) {
|
|
path := writeERPEnvironmentFile(t, strings.Join([]string{
|
|
"OTHER_TOOL_TOKEN=ignored",
|
|
"CMROUBAO_SHUNYUNBAO_URL=https://erp.example.test",
|
|
"CMROUBAO_SHUNYUNBAO_USERNAME=dotenv-user",
|
|
"CMROUBAO_SHUNYUNBAO_PASSWORD='dotenv password #1'",
|
|
}, "\n"))
|
|
|
|
lookup, err := WithERPEnvironmentFile(path, func(string) (string, bool) {
|
|
return "", false
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("WithERPEnvironmentFile() error = %v", err)
|
|
}
|
|
cfg, err := Load(lookup)
|
|
if err != nil {
|
|
t.Fatalf("Load() error = %v", err)
|
|
}
|
|
if cfg.ShunyunbaoURL != "https://erp.example.test" ||
|
|
cfg.ShunyunbaoUsername != "dotenv-user" ||
|
|
cfg.ShunyunbaoPassword != "dotenv password #1" {
|
|
t.Fatalf(
|
|
"ERP config = %#v",
|
|
struct {
|
|
URL string
|
|
Username string
|
|
Password string
|
|
}{cfg.ShunyunbaoURL, cfg.ShunyunbaoUsername, cfg.ShunyunbaoPassword},
|
|
)
|
|
}
|
|
if _, exists := lookup("OTHER_TOOL_TOKEN"); exists {
|
|
t.Fatal("unapproved .env value was exposed")
|
|
}
|
|
}
|
|
|
|
func TestWithERPEnvironmentFileProcessEnvironmentTakesPriority(t *testing.T) {
|
|
path := writeERPEnvironmentFile(t, strings.Join([]string{
|
|
"CMROUBAO_SHUNYUNBAO_URL=https://dotenv.example.test",
|
|
"CMROUBAO_SHUNYUNBAO_USERNAME=dotenv-user",
|
|
"CMROUBAO_SHUNYUNBAO_PASSWORD=dotenv-password",
|
|
}, "\n"))
|
|
process := map[string]string{
|
|
ShunyunbaoURLEnvironment: "https://process.example.test",
|
|
ShunyunbaoUsernameEnvironment: "process-user",
|
|
ShunyunbaoPasswordEnvironment: "process-password",
|
|
}
|
|
lookup, err := WithERPEnvironmentFile(path, lookupMap(process))
|
|
if err != nil {
|
|
t.Fatalf("WithERPEnvironmentFile() error = %v", err)
|
|
}
|
|
cfg, err := Load(lookup)
|
|
if err != nil {
|
|
t.Fatalf("Load() error = %v", err)
|
|
}
|
|
if cfg.ShunyunbaoURL != process[ShunyunbaoURLEnvironment] ||
|
|
cfg.ShunyunbaoUsername != process[ShunyunbaoUsernameEnvironment] ||
|
|
cfg.ShunyunbaoPassword != process[ShunyunbaoPasswordEnvironment] {
|
|
t.Fatalf("process values did not override .env values")
|
|
}
|
|
}
|
|
|
|
func TestWithERPEnvironmentFileAllowsMissingFile(t *testing.T) {
|
|
lookup, err := WithERPEnvironmentFile(
|
|
filepath.Join(t.TempDir(), "missing.env"),
|
|
lookupMap(nil),
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("WithERPEnvironmentFile() error = %v", err)
|
|
}
|
|
if _, exists := lookup(ShunyunbaoUsernameEnvironment); exists {
|
|
t.Fatal("missing file provided a value")
|
|
}
|
|
}
|
|
|
|
func TestWithERPEnvironmentFileRejectsInvalidContentWithoutLeakingValues(t *testing.T) {
|
|
const secret = "must-not-appear-in-error"
|
|
testCases := map[string]string{
|
|
"invalid name": "not a name=" + secret,
|
|
"duplicate": strings.Join([]string{
|
|
"CMROUBAO_SHUNYUNBAO_USERNAME=" + secret,
|
|
"CMROUBAO_SHUNYUNBAO_USERNAME=another",
|
|
}, "\n"),
|
|
"unknown app config": "CMROUBAO_AUTH_PASSWORD=" + secret,
|
|
"unmatched quote": "CMROUBAO_SHUNYUNBAO_PASSWORD='" + secret,
|
|
"nul": "CMROUBAO_SHUNYUNBAO_PASSWORD=" + secret + "\x00",
|
|
}
|
|
for name, contents := range testCases {
|
|
t.Run(name, func(t *testing.T) {
|
|
path := writeERPEnvironmentFile(t, contents)
|
|
_, err := WithERPEnvironmentFile(path, lookupMap(nil))
|
|
if err == nil {
|
|
t.Fatal("WithERPEnvironmentFile() error = nil")
|
|
}
|
|
if strings.Contains(err.Error(), secret) {
|
|
t.Fatalf("error leaked .env content: %v", err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestWithERPEnvironmentFileRejectsOversizedFile(t *testing.T) {
|
|
path := writeERPEnvironmentFile(
|
|
t,
|
|
"CMROUBAO_SHUNYUNBAO_USERNAME="+
|
|
strings.Repeat("x", maximumERPEnvironmentFileBytes),
|
|
)
|
|
_, err := WithERPEnvironmentFile(path, lookupMap(nil))
|
|
if err == nil {
|
|
t.Fatal("WithERPEnvironmentFile() error = nil")
|
|
}
|
|
}
|
|
|
|
func writeERPEnvironmentFile(t *testing.T, contents string) string {
|
|
t.Helper()
|
|
path := filepath.Join(t.TempDir(), ".env")
|
|
if err := os.WriteFile(path, []byte(contents), 0o600); err != nil {
|
|
t.Fatalf("os.WriteFile() error = %v", err)
|
|
}
|
|
return path
|
|
}
|
|
|
|
func lookupMap(values map[string]string) LookupEnvironment {
|
|
return func(name string) (string, bool) {
|
|
value, exists := values[name]
|
|
return value, exists
|
|
}
|
|
}
|