package backend import ( "context" "os" "path/filepath" "strings" "testing" ) const testMaterial = "sk-live-supersecret-material-0123456789" // writeEnvFile writes an env file with the given permission mask. func writeEnvFile(t *testing.T, dir, name, content string, mode os.FileMode) string { t.Helper() path := filepath.Join(dir, name) if err := os.WriteFile(path, []byte(content), mode); err != nil { t.Fatal(err) } if err := os.Chmod(path, mode); err != nil { t.Fatal(err) } return path } func TestFileResolve(t *testing.T) { dir := t.TempDir() secretFile := writeEnvFile(t, dir, "creds.env", "API_KEY="+testMaterial+"\nOTHER=x\n", 0o600) emptyFile := writeEnvFile(t, dir, "empty.env", "API_KEY=\n", 0o600) looseFile := writeEnvFile(t, dir, "loose.env", "API_KEY="+testMaterial+"\n", 0o644) strictFile := writeEnvFile(t, dir, "strict.env", "API_KEY="+testMaterial+"\n", 0o400) groupFile := writeEnvFile(t, dir, "group.env", "API_KEY="+testMaterial+"\n", 0o640) brokenFile := writeEnvFile(t, dir, "broken.env", "this line has no equals\n", 0o600) tests := []struct { name string ref Ref wantValue string wantErr string // substring of the ResolveError message }{ { name: "0600 file resolves", ref: Ref{Name: "mpk-test", Backend: "file", Source: secretFile, Key: "API_KEY"}, wantValue: testMaterial, }, { name: "0400 stricter than mask passes", ref: Ref{Name: "mpk-test", Backend: "file", Source: strictFile, Key: "API_KEY"}, wantValue: testMaterial, }, { name: "0644 refused insecure mode", ref: Ref{Name: "mpk-test", Backend: "file", Source: looseFile, Key: "API_KEY"}, wantErr: "insecure_source_mode", }, { name: "0640 refused under default 0600 mask", ref: Ref{Name: "mpk-test", Backend: "file", Source: groupFile, Key: "API_KEY"}, wantErr: "insecure_source_mode", }, { name: "0640 passes when mask says 0640", ref: Ref{Name: "mpk-test", Backend: "file", Source: groupFile, Key: "API_KEY", Mode: "0640"}, wantValue: testMaterial, }, { name: "missing file", ref: Ref{Name: "mpk-test", Backend: "file", Source: filepath.Join(dir, "nope.env"), Key: "API_KEY"}, wantErr: "unreadable_source", }, { name: "directory as source", ref: Ref{Name: "mpk-test", Backend: "file", Source: dir, Key: "API_KEY"}, wantErr: "unreadable_source", }, { name: "missing key", ref: Ref{Name: "mpk-test", Backend: "file", Source: secretFile, Key: "NOT_THERE"}, wantErr: "missing_key", }, { name: "empty value", ref: Ref{Name: "mpk-test", Backend: "file", Source: emptyFile, Key: "API_KEY"}, wantErr: "empty_value", }, { name: "malformed file", ref: Ref{Name: "mpk-test", Backend: "file", Source: brokenFile, Key: "API_KEY"}, wantErr: "malformed_source", }, { name: "mode mask fails closed on junk", ref: Ref{Name: "mpk-test", Backend: "file", Source: secretFile, Key: "API_KEY", Mode: "junk"}, wantErr: "insecure_source_mode", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { f := NewFile() got, err := f.Resolve(context.Background(), tt.ref) if tt.wantErr != "" { if err == nil { t.Fatalf("want error %q, got value", tt.wantErr) } msg := err.Error() if !strings.Contains(msg, tt.wantErr) { t.Fatalf("error %q does not contain %q", msg, tt.wantErr) } assertRedactedError(t, msg, tt.ref.Name, "file", testMaterial) return } if err != nil { t.Fatalf("unexpected error: %v", err) } if got != tt.wantValue { t.Fatalf("got %q, want %q", got, tt.wantValue) } }) } } // TestFileHomeExpansion covers ~/ expansion (generic home indirection, // not an org-specific path). func TestFileHomeExpansion(t *testing.T) { t.Setenv("HOME", t.TempDir()) dir, _ := os.LookupEnv("HOME") path := writeEnvFile(t, dir, "creds.env", "API_KEY="+testMaterial+"\n", 0o600) f := NewFile() got, err := f.Resolve(context.Background(), Ref{Name: "mpk-home", Backend: "file", Source: "~/creds.env", Key: "API_KEY"}) if err != nil { t.Fatalf("unexpected error: %v", err) } if got != testMaterial { t.Fatalf("got %q, want the material", got) } _ = path } // assertRedactedError enforces the house rule: resolution failures name // the ref and the backend, NEVER material. func assertRedactedError(t *testing.T, msg, refName, backendName, material string) { t.Helper() if !strings.Contains(msg, refName) || !strings.Contains(msg, backendName) { t.Fatalf("error %q must name ref %q and backend %q", msg, refName, backendName) } if strings.Contains(msg, material) { t.Fatalf("ERROR LEAKS MATERIAL: %q", msg) } }