feat(07-01): Importer interface and TruffleHog v3 JSON adapter
- pkg/importer/importer.go: shared Importer interface (Name, Import) - pkg/importer/trufflehog.go: TruffleHogImporter with v3 JSON decoding, detector-name normalization (OpenAI/GithubV2/AWS -> canonical ids), SourceMetadata path+line extraction for Git/Filesystem/Github - pkg/importer/testdata/trufflehog-sample.json: 3-record fixture - pkg/importer/trufflehog_test.go: Name, Import, NormalizeName, EmptyArray, InvalidJSON tests -- all passing
This commit is contained in:
128
pkg/importer/trufflehog_test.go
Normal file
128
pkg/importer/trufflehog_test.go
Normal file
@@ -0,0 +1,128 @@
|
||||
package importer
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTruffleHogImporter_Name(t *testing.T) {
|
||||
var imp TruffleHogImporter
|
||||
if got := imp.Name(); got != "trufflehog" {
|
||||
t.Fatalf("Name() = %q, want %q", got, "trufflehog")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTruffleHogImporter_Import(t *testing.T) {
|
||||
f, err := os.Open("testdata/trufflehog-sample.json")
|
||||
if err != nil {
|
||||
t.Fatalf("open fixture: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
var imp TruffleHogImporter
|
||||
findings, err := imp.Import(f)
|
||||
if err != nil {
|
||||
t.Fatalf("Import returned error: %v", err)
|
||||
}
|
||||
if len(findings) != 3 {
|
||||
t.Fatalf("expected 3 findings, got %d", len(findings))
|
||||
}
|
||||
|
||||
// Record 1: OpenAI / Git / verified.
|
||||
f0 := findings[0]
|
||||
if f0.ProviderName != "openai" {
|
||||
t.Errorf("findings[0].ProviderName = %q, want openai", f0.ProviderName)
|
||||
}
|
||||
if f0.Confidence != "high" {
|
||||
t.Errorf("findings[0].Confidence = %q, want high", f0.Confidence)
|
||||
}
|
||||
if !f0.Verified {
|
||||
t.Error("findings[0].Verified = false, want true")
|
||||
}
|
||||
if f0.VerifyStatus != "live" {
|
||||
t.Errorf("findings[0].VerifyStatus = %q, want live", f0.VerifyStatus)
|
||||
}
|
||||
if f0.Source != "src/config.py" {
|
||||
t.Errorf("findings[0].Source = %q, want src/config.py", f0.Source)
|
||||
}
|
||||
if f0.LineNumber != 42 {
|
||||
t.Errorf("findings[0].LineNumber = %d, want 42", f0.LineNumber)
|
||||
}
|
||||
if f0.SourceType != "import:trufflehog" {
|
||||
t.Errorf("findings[0].SourceType = %q, want import:trufflehog", f0.SourceType)
|
||||
}
|
||||
if f0.KeyValue != "sk-proj-abcdef1234567890abcdef" {
|
||||
t.Errorf("findings[0].KeyValue unexpected: %q", f0.KeyValue)
|
||||
}
|
||||
if f0.KeyMasked == "" || f0.KeyMasked == f0.KeyValue {
|
||||
t.Errorf("findings[0].KeyMasked not populated: %q", f0.KeyMasked)
|
||||
}
|
||||
|
||||
// Record 2: AnthropicV2 / Filesystem / unverified.
|
||||
f1 := findings[1]
|
||||
if f1.ProviderName != "anthropic" {
|
||||
t.Errorf("findings[1].ProviderName = %q, want anthropic", f1.ProviderName)
|
||||
}
|
||||
if f1.Confidence != "medium" {
|
||||
t.Errorf("findings[1].Confidence = %q, want medium", f1.Confidence)
|
||||
}
|
||||
if f1.Verified {
|
||||
t.Error("findings[1].Verified = true, want false")
|
||||
}
|
||||
if f1.VerifyStatus != "unverified" {
|
||||
t.Errorf("findings[1].VerifyStatus = %q, want unverified", f1.VerifyStatus)
|
||||
}
|
||||
if f1.Source != "/tmp/leaked.env" {
|
||||
t.Errorf("findings[1].Source = %q, want /tmp/leaked.env", f1.Source)
|
||||
}
|
||||
|
||||
// Record 3: AWS / Github link.
|
||||
f2 := findings[2]
|
||||
if f2.ProviderName != "aws" {
|
||||
t.Errorf("findings[2].ProviderName = %q, want aws", f2.ProviderName)
|
||||
}
|
||||
if !f2.Verified {
|
||||
t.Error("findings[2].Verified = false, want true")
|
||||
}
|
||||
if f2.Source != "https://github.com/foo/bar/blob/main/a.yml" {
|
||||
t.Errorf("findings[2].Source = %q, want github link", f2.Source)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTruffleHogImporter_NormalizeName(t *testing.T) {
|
||||
cases := []struct {
|
||||
in, want string
|
||||
}{
|
||||
{"OpenAI", "openai"},
|
||||
{"GithubV2", "github"},
|
||||
{"AnthropicV2", "anthropic"},
|
||||
{"AWS", "aws"},
|
||||
{"GCP", "gcp"},
|
||||
{"HuggingFace", "huggingface"},
|
||||
{"UnknownDetector", "unknowndetector"},
|
||||
}
|
||||
for _, c := range cases {
|
||||
if got := normalizeTruffleHogName(c.in); got != c.want {
|
||||
t.Errorf("normalizeTruffleHogName(%q) = %q, want %q", c.in, got, c.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTruffleHogImporter_EmptyArray(t *testing.T) {
|
||||
var imp TruffleHogImporter
|
||||
findings, err := imp.Import(strings.NewReader("[]"))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if len(findings) != 0 {
|
||||
t.Fatalf("expected 0 findings, got %d", len(findings))
|
||||
}
|
||||
}
|
||||
|
||||
func TestTruffleHogImporter_InvalidJSON(t *testing.T) {
|
||||
var imp TruffleHogImporter
|
||||
if _, err := imp.Import(strings.NewReader("not json")); err == nil {
|
||||
t.Fatal("expected error for invalid JSON, got nil")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user