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)
 | |
| }
 | 
