package honeypot import ( "net/http" "net/http/httptest" "strings" "testing" "time" ) func TestPromotesAfterThresholdAndExpires(t *testing.T) { tracker := New(Config{Threshold: 2, Window: time.Minute, TTL: time.Millisecond, Token: "secret"}) for i := 0; i < 3; i++ { req := httptest.NewRequest(http.MethodGet, "https://example.test/.env", nil) req.RemoteAddr = "192.0.2.10:1234" tracker.Middleware(http.HandlerFunc(http.NotFound)).ServeHTTP(httptest.NewRecorder(), req) } if got := len(tracker.PromotedIPs()); got != 1 { t.Fatalf("got %d promoted IPs, want 1", got) } time.Sleep(2 * time.Millisecond) if got := len(tracker.PromotedIPs()); got != 0 { t.Fatalf("got %d expired IPs, want 0", got) } } func TestHandleIPsRequiresToken(t *testing.T) { tracker := New(Config{Threshold: 1, Token: "secret"}) recorder := httptest.NewRecorder() tracker.HandleIPs(recorder, httptest.NewRequest(http.MethodGet, "https://example.test/internal/honeypot/ips", nil)) if recorder.Code != http.StatusUnauthorized { t.Fatalf("got %d, want 401", recorder.Code) } recorder = httptest.NewRecorder() req := httptest.NewRequest(http.MethodGet, "https://example.test/internal/honeypot/ips", nil) req.Header.Set("Authorization", "Bearer secret") tracker.HandleIPs(recorder, req) if recorder.Code != http.StatusOK || !strings.HasPrefix(recorder.Body.String(), "[]") { t.Fatalf("got %d and %q", recorder.Code, recorder.Body.String()) } } func TestRecordTelemetryPromotesTheObservedSourceIP(t *testing.T) { tracker := New(Config{Threshold: 2, TTL: time.Minute}) if tracker.RecordTelemetry("203.0.113.20", "/mail.php") { t.Fatal("must not promote before threshold") } if !tracker.RecordTelemetry("203.0.113.20", "/settings.php") { t.Fatal("must promote at threshold") } if tracker.RecordTelemetry("203.0.113.20", "/index.html") { t.Fatal("normal paths must not be tracked") } ips := tracker.PromotedIPs() if len(ips) != 1 || ips[0].Address != "203.0.113.20" { t.Fatalf("unexpected promoted IPs: %+v", ips) } }