96 lines
2.6 KiB
Go
96 lines
2.6 KiB
Go
package shhh
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
type recordingSink struct {
|
|
events []AuditEvent
|
|
}
|
|
|
|
func (r *recordingSink) RecordRedaction(_ context.Context, event AuditEvent) {
|
|
r.events = append(r.events, event)
|
|
}
|
|
|
|
func TestRedactText_DefaultRules(t *testing.T) {
|
|
sentinel, err := NewSentinel(Config{})
|
|
require.NoError(t, err)
|
|
|
|
input := "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.secret"
|
|
redacted, findings := sentinel.RedactText(context.Background(), input, map[string]string{"source": "http.request.headers.authorization"})
|
|
|
|
require.Equal(t, "Authorization: Bearer [REDACTED]", redacted)
|
|
require.Len(t, findings, 1)
|
|
require.Equal(t, "bearer-token", findings[0].Rule)
|
|
require.Equal(t, 1, findings[0].Count)
|
|
require.NotEmpty(t, findings[0].Locations)
|
|
|
|
snapshot := sentinel.StatsSnapshot()
|
|
require.Equal(t, uint64(1), snapshot.TotalScans)
|
|
require.Equal(t, uint64(1), snapshot.TotalFindings)
|
|
require.Equal(t, uint64(1), snapshot.PerRuleFindings["bearer-token"])
|
|
}
|
|
|
|
func TestRedactMap_NestedStructures(t *testing.T) {
|
|
sentinel, err := NewSentinel(Config{})
|
|
require.NoError(t, err)
|
|
|
|
payload := map[string]any{
|
|
"config": map[string]any{
|
|
"api_key": "API_KEY=1234567890ABCDEFG",
|
|
},
|
|
"tokens": []any{
|
|
"sk-test1234567890ABCDEF",
|
|
map[string]any{"refresh": "refresh_token=abcdef12345"},
|
|
},
|
|
}
|
|
|
|
findings := sentinel.RedactMap(context.Background(), payload)
|
|
require.NotEmpty(t, findings)
|
|
|
|
config := payload["config"].(map[string]any)
|
|
require.Equal(t, "API_KEY=[REDACTED]", config["api_key"])
|
|
|
|
tokens := payload["tokens"].([]any)
|
|
require.Equal(t, "[REDACTED]", tokens[0])
|
|
|
|
inner := tokens[1].(map[string]any)
|
|
require.Equal(t, "refresh_token=[REDACTED]", inner["refresh"])
|
|
|
|
total := 0
|
|
for _, finding := range findings {
|
|
total += finding.Count
|
|
}
|
|
require.Equal(t, 3, total)
|
|
}
|
|
|
|
func TestAuditSinkReceivesEvents(t *testing.T) {
|
|
sink := &recordingSink{}
|
|
cfg := Config{
|
|
DisableDefaultRules: true,
|
|
CustomRules: []RuleConfig{
|
|
{
|
|
Name: "custom-secret",
|
|
Pattern: `(secret\s*=\s*)([A-Za-z0-9]{6,})`,
|
|
ReplacementTemplate: "$1[REDACTED]",
|
|
Severity: SeverityHigh,
|
|
},
|
|
},
|
|
}
|
|
|
|
sentinel, err := NewSentinel(cfg, WithAuditSink(sink))
|
|
require.NoError(t, err)
|
|
|
|
_, findings := sentinel.RedactText(context.Background(), "secret=mysecretvalue", map[string]string{"source": "test"})
|
|
require.Len(t, findings, 1)
|
|
require.Equal(t, 1, findings[0].Count)
|
|
|
|
require.Len(t, sink.events, 1)
|
|
require.Equal(t, "custom-secret", sink.events[0].Rule)
|
|
require.NotEmpty(t, sink.events[0].Hash)
|
|
require.Equal(t, "test", sink.events[0].Path)
|
|
}
|