2026-04-14 14:40:50 +00:00
|
|
|
package secretstore
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"errors"
|
|
|
|
|
"os"
|
|
|
|
|
"path/filepath"
|
|
|
|
|
"strings"
|
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
|
|
"github.com/99designs/keyring"
|
|
|
|
|
|
2026-05-05 10:23:14 +00:00
|
|
|
"forge.lclr.dev/AI/mcp-framework/manifest"
|
2026-04-14 14:40:50 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func TestOpenFromManifestUsesPolicyFromManifest(t *testing.T) {
|
|
|
|
|
var gotStartDir string
|
|
|
|
|
|
|
|
|
|
store, err := OpenFromManifest(OpenFromManifestOptions{
|
|
|
|
|
ServiceName: "email-mcp",
|
|
|
|
|
LookupEnv: func(name string) (string, bool) {
|
|
|
|
|
if name == "EMAIL_TOKEN" {
|
|
|
|
|
return "from-env", true
|
|
|
|
|
}
|
|
|
|
|
return "", false
|
|
|
|
|
},
|
|
|
|
|
ExecutableResolver: func() (string, error) {
|
|
|
|
|
return filepath.Join(string(filepath.Separator), "opt", "email-mcp", "bin", "email-mcp"), nil
|
|
|
|
|
},
|
|
|
|
|
ManifestLoader: func(startDir string) (manifest.File, string, error) {
|
|
|
|
|
gotStartDir = startDir
|
|
|
|
|
return manifest.File{
|
|
|
|
|
SecretStore: manifest.SecretStore{BackendPolicy: string(BackendEnvOnly)},
|
|
|
|
|
}, filepath.Join(startDir, manifest.DefaultFile), nil
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("OpenFromManifest returned error: %v", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wantDir := filepath.Join(string(filepath.Separator), "opt", "email-mcp", "bin")
|
|
|
|
|
if gotStartDir != wantDir {
|
|
|
|
|
t.Fatalf("manifest loader startDir = %q, want %q", gotStartDir, wantDir)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
value, err := store.GetSecret("EMAIL_TOKEN")
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("GetSecret returned error: %v", err)
|
|
|
|
|
}
|
|
|
|
|
if value != "from-env" {
|
|
|
|
|
t.Fatalf("GetSecret = %q, want from-env", value)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestOpenFromManifestFallsBackToAutoWhenManifestIsMissing(t *testing.T) {
|
|
|
|
|
withKeyringHooks(t, nil, func(cfg keyring.Config) (keyring.Keyring, error) {
|
|
|
|
|
t.Fatal("unexpected keyring open call")
|
|
|
|
|
return nil, nil
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
store, err := OpenFromManifest(OpenFromManifestOptions{
|
|
|
|
|
ServiceName: "email-mcp",
|
|
|
|
|
LookupEnv: func(name string) (string, bool) {
|
|
|
|
|
if name == "EMAIL_TOKEN" {
|
|
|
|
|
return "env-token", true
|
|
|
|
|
}
|
|
|
|
|
return "", false
|
|
|
|
|
},
|
|
|
|
|
ExecutableResolver: func() (string, error) {
|
|
|
|
|
return filepath.Join(string(filepath.Separator), "opt", "email-mcp", "bin", "email-mcp"), nil
|
|
|
|
|
},
|
|
|
|
|
ManifestLoader: func(string) (manifest.File, string, error) {
|
|
|
|
|
return manifest.File{}, "", os.ErrNotExist
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("OpenFromManifest returned error: %v", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
value, err := store.GetSecret("EMAIL_TOKEN")
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("GetSecret returned error: %v", err)
|
|
|
|
|
}
|
|
|
|
|
if value != "env-token" {
|
|
|
|
|
t.Fatalf("GetSecret = %q, want env-token", value)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestOpenFromManifestReturnsExplicitErrorForInvalidManifestPolicy(t *testing.T) {
|
|
|
|
|
_, err := OpenFromManifest(OpenFromManifestOptions{
|
|
|
|
|
ServiceName: "email-mcp",
|
|
|
|
|
ExecutableResolver: func() (string, error) {
|
|
|
|
|
return filepath.Join(string(filepath.Separator), "opt", "email-mcp", "bin", "email-mcp"), nil
|
|
|
|
|
},
|
|
|
|
|
ManifestLoader: func(startDir string) (manifest.File, string, error) {
|
|
|
|
|
return manifest.File{
|
|
|
|
|
SecretStore: manifest.SecretStore{BackendPolicy: "totally-invalid"},
|
|
|
|
|
}, filepath.Join(startDir, manifest.DefaultFile), nil
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
if err == nil {
|
|
|
|
|
t.Fatal("expected error")
|
|
|
|
|
}
|
|
|
|
|
if !errors.Is(err, ErrInvalidBackendPolicy) {
|
|
|
|
|
t.Fatalf("error = %v, want ErrInvalidBackendPolicy", err)
|
|
|
|
|
}
|
|
|
|
|
if !strings.Contains(err.Error(), "secret_store.backend_policy") {
|
|
|
|
|
t.Fatalf("error = %v, want manifest policy context", err)
|
|
|
|
|
}
|
|
|
|
|
if !strings.Contains(err.Error(), manifest.DefaultFile) {
|
|
|
|
|
t.Fatalf("error = %v, want manifest path", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-02 12:59:04 +00:00
|
|
|
func TestResolveManifestPolicyPreservesBitwardenCacheDisable(t *testing.T) {
|
|
|
|
|
cacheDisabled := false
|
|
|
|
|
resolution, err := resolveManifestPolicy(OpenFromManifestOptions{
|
|
|
|
|
ServiceName: "email-mcp",
|
|
|
|
|
ExecutableResolver: func() (string, error) {
|
|
|
|
|
return filepath.Join(string(filepath.Separator), "opt", "email-mcp", "bin", "email-mcp"), nil
|
|
|
|
|
},
|
|
|
|
|
ManifestLoader: func(startDir string) (manifest.File, string, error) {
|
|
|
|
|
return manifest.File{
|
|
|
|
|
SecretStore: manifest.SecretStore{
|
|
|
|
|
BackendPolicy: string(BackendBitwardenCLI),
|
|
|
|
|
BitwardenCache: &cacheDisabled,
|
|
|
|
|
},
|
|
|
|
|
}, filepath.Join(startDir, manifest.DefaultFile), nil
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("resolveManifestPolicy returned error: %v", err)
|
|
|
|
|
}
|
|
|
|
|
if resolution.BitwardenCache {
|
|
|
|
|
t.Fatal("resolution BitwardenCache = true, want false")
|
|
|
|
|
}
|
|
|
|
|
if resolution.Policy != BackendBitwardenCLI {
|
|
|
|
|
t.Fatalf("resolution policy = %q, want %q", resolution.Policy, BackendBitwardenCLI)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-02 13:03:35 +00:00
|
|
|
func TestOpenFromManifestAppliesBitwardenCacheDisable(t *testing.T) {
|
|
|
|
|
withBitwardenSession(t)
|
|
|
|
|
fakeCLI := newFakeBitwardenCLI("bw")
|
|
|
|
|
fakeCLI.itemsByID["item-1"] = fakeBitwardenItem{
|
|
|
|
|
ID: "item-1",
|
|
|
|
|
Name: "email-mcp/api-token",
|
|
|
|
|
Secret: "secret-v1",
|
|
|
|
|
MarkerService: "email-mcp",
|
|
|
|
|
MarkerSecretName: "api-token",
|
|
|
|
|
}
|
|
|
|
|
withBitwardenRunner(t, fakeCLI.run)
|
|
|
|
|
|
|
|
|
|
cacheDisabled := false
|
|
|
|
|
store, err := OpenFromManifest(OpenFromManifestOptions{
|
|
|
|
|
ServiceName: "email-mcp",
|
|
|
|
|
ExecutableResolver: func() (string, error) {
|
|
|
|
|
return filepath.Join(string(filepath.Separator), "opt", "email-mcp", "bin", "email-mcp"), nil
|
|
|
|
|
},
|
|
|
|
|
ManifestLoader: func(startDir string) (manifest.File, string, error) {
|
|
|
|
|
return manifest.File{
|
|
|
|
|
SecretStore: manifest.SecretStore{
|
|
|
|
|
BackendPolicy: string(BackendBitwardenCLI),
|
|
|
|
|
BitwardenCache: &cacheDisabled,
|
|
|
|
|
},
|
|
|
|
|
}, filepath.Join(startDir, manifest.DefaultFile), nil
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("OpenFromManifest returned error: %v", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for i := 0; i < 2; i++ {
|
|
|
|
|
value, err := store.GetSecret("api-token")
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("GetSecret #%d returned error: %v", i+1, err)
|
|
|
|
|
}
|
|
|
|
|
if value != "secret-v1" {
|
|
|
|
|
t.Fatalf("GetSecret #%d = %q, want secret-v1", i+1, value)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if fakeCLI.getItemCalls != 2 {
|
|
|
|
|
t.Fatalf("bw get item count = %d, want 2 when manifest disables cache", fakeCLI.getItemCalls)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-14 14:40:50 +00:00
|
|
|
func TestOpenFromManifestReturnsExecutableResolutionError(t *testing.T) {
|
|
|
|
|
execErr := errors.New("boom")
|
|
|
|
|
_, err := OpenFromManifest(OpenFromManifestOptions{
|
|
|
|
|
ExecutableResolver: func() (string, error) {
|
|
|
|
|
return "", execErr
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
if !errors.Is(err, execErr) {
|
|
|
|
|
t.Fatalf("error = %v, want wrapped executable resolver error", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestOpenFromManifestReturnsManifestLoaderError(t *testing.T) {
|
|
|
|
|
loadErr := errors.New("cannot parse manifest")
|
|
|
|
|
_, err := OpenFromManifest(OpenFromManifestOptions{
|
|
|
|
|
ExecutableResolver: func() (string, error) {
|
|
|
|
|
return filepath.Join(string(filepath.Separator), "opt", "email-mcp", "bin", "email-mcp"), nil
|
|
|
|
|
},
|
|
|
|
|
ManifestLoader: func(string) (manifest.File, string, error) {
|
|
|
|
|
return manifest.File{}, "", loadErr
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
if !errors.Is(err, loadErr) {
|
|
|
|
|
t.Fatalf("error = %v, want wrapped manifest loader error", err)
|
|
|
|
|
}
|
|
|
|
|
}
|