fetch_ml/tests/unit/security/manifest_filename_test.go
Jeremie Fraeys 8f9bcef754
test(phase-3): prerequisite security and reproducibility tests
Implement 4 prerequisite test requirements:

- TestConfigIntegrityVerification: Config signing, tamper detection, hash stability
- TestManifestFilenameNonce: Cryptographic nonce generation and filename patterns
- TestGPUDetectionAudit: Structured logging of GPU detection at startup
- TestResourceEnvVarParsing: Resource env var parsing and override behavior

Also update manifest run_manifest.go:
- Add nonce-based filename support to WriteToDir
- Add nonce-based file detection to LoadFromDir
2026-02-23 20:25:26 -05:00

140 lines
3.9 KiB
Go

package security
import (
"os"
"strings"
"testing"
"time"
"github.com/jfraeys/fetch_ml/internal/manifest"
)
// TestManifestFilenameNonce verifies that manifest filenames include a cryptographic nonce
// to prevent information disclosure in multi-tenant environments where predictable
// filenames could be enumerated.
func TestManifestFilenameNonce(t *testing.T) {
t.Run("FilenameIncludesNonce", func(t *testing.T) {
// Generate multiple filenames and verify they are unique
filenames := make(map[string]bool)
for i := 0; i < 10; i++ {
filename, err := manifest.GenerateManifestFilename()
if err != nil {
t.Fatalf("GenerateManifestFilename failed: %v", err)
}
// Verify format: run_manifest_<nonce>.json
if !strings.HasPrefix(filename, "run_manifest_") {
t.Errorf("filename %q missing required prefix 'run_manifest_'", filename)
}
if !strings.HasSuffix(filename, ".json") {
t.Errorf("filename %q missing required suffix '.json'", filename)
}
// Extract and verify nonce
nonce := manifest.ParseManifestFilename(filename)
if nonce == "" {
t.Errorf("failed to parse nonce from filename %q", filename)
}
if len(nonce) != 32 {
t.Errorf("nonce length = %d, want 32 hex chars", len(nonce))
}
// Verify uniqueness (no collisions in 10 generations)
if filenames[filename] {
t.Errorf("duplicate filename generated: %q", filename)
}
filenames[filename] = true
}
})
t.Run("ManifestWrittenWithNonce", func(t *testing.T) {
// Generate a nonce for the manifest
nonce, err := manifest.GenerateManifestNonce()
if err != nil {
t.Fatalf("GenerateManifestNonce failed: %v", err)
}
// Create a manifest with nonce in Environment
created := time.Now().UTC()
m := manifest.NewRunManifest("run-test-nonce", "task-nonce", "job-nonce", created)
m.CommitID = "deadbeef"
m.Environment = &manifest.ExecutionEnvironment{
ConfigHash: "abc123",
ManifestNonce: nonce,
}
dir := t.TempDir()
if err := m.WriteToDir(dir); err != nil {
t.Fatalf("WriteToDir failed: %v", err)
}
// List files in directory
entries, err := os.ReadDir(dir)
if err != nil {
t.Fatalf("ReadDir failed: %v", err)
}
// Find manifest file
var manifestFile string
for _, entry := range entries {
if strings.HasPrefix(entry.Name(), "run_manifest_") && strings.HasSuffix(entry.Name(), ".json") {
manifestFile = entry.Name()
break
}
}
if manifestFile == "" {
t.Fatal("no manifest file found with expected naming pattern")
}
// Verify nonce is present in filename
parsedNonce := manifest.ParseManifestFilename(manifestFile)
if parsedNonce == "" {
t.Errorf("manifest file %q does not contain a valid nonce", manifestFile)
}
if parsedNonce != nonce {
t.Errorf("nonce mismatch: got %q, want %q", parsedNonce, nonce)
}
if len(parsedNonce) != 32 {
t.Errorf("nonce length = %d, want 32 hex chars", len(parsedNonce))
}
// Verify file can be loaded back
loaded, err := manifest.LoadFromDir(dir)
if err != nil {
t.Fatalf("LoadFromDir failed: %v", err)
}
if loaded.RunID != m.RunID {
t.Errorf("loaded RunID = %q, want %q", loaded.RunID, m.RunID)
}
})
t.Run("NonceUniqueness", func(t *testing.T) {
// Generate many nonces to check for collisions (statistical test)
nonces := make(map[string]int)
iterations := 100
for i := 0; i < iterations; i++ {
nonce, err := manifest.GenerateManifestNonce()
if err != nil {
t.Fatalf("GenerateManifestNonce failed: %v", err)
}
nonces[nonce]++
}
// Check for any collisions
collisions := 0
for nonce, count := range nonces {
if count > 1 {
t.Errorf("nonce collision detected: %q appeared %d times", nonce, count)
collisions++
}
}
if collisions > 0 {
t.Fatalf("detected %d nonce collisions in %d iterations", collisions, iterations)
}
t.Logf("Generated %d unique nonces with no collisions", iterations)
})
}