2

Add background IP intel and restore dashboard stats

This commit is contained in:
2026-03-12 11:10:59 +01:00
parent 14a711038b
commit 1822e2148a
9 changed files with 506 additions and 31 deletions

View File

@@ -159,6 +159,87 @@ sources:
}
}
func TestServiceBackgroundInvestigationEnrichesRecentIPs(t *testing.T) {
t.Parallel()
tempDir := t.TempDir()
logPath := filepath.Join(tempDir, "access.log")
if err := os.WriteFile(logPath, nil, 0o600); err != nil {
t.Fatalf("create log: %v", err)
}
configPath := filepath.Join(tempDir, "config.yaml")
payload := fmt.Sprintf(`storage:
path: %s/blocker.db
investigation:
enabled: true
refresh_after: 24h
timeout: 500ms
background_workers: 1
background_poll_interval: 50ms
background_lookback: 24h
background_batch_size: 32
profiles:
main:
auto_block: false
block_unexpected_posts: true
suspicious_path_prefixes:
- /wp-login.php
sources:
- name: main
path: %s
profile: main
initial_position: beginning
poll_interval: 20ms
batch_size: 128
`, tempDir, logPath)
if err := os.WriteFile(configPath, []byte(payload), 0o600); err != nil {
t.Fatalf("write config: %v", err)
}
cfg, err := config.Load(configPath)
if err != nil {
t.Fatalf("load config: %v", err)
}
database, err := store.Open(cfg.Storage.Path)
if err != nil {
t.Fatalf("open store: %v", err)
}
defer database.Close()
investigator := &fakeInvestigator{}
svc := New(cfg, database, nil, investigator, log.New(os.Stderr, "", 0))
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go func() { _ = svc.Run(ctx) }()
appendLine(t, logPath, caddyJSONLine("203.0.113.33", "198.51.100.33", "example.test", "GET", "/wp-login.php", 404, "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)", time.Now().UTC()))
waitFor(t, 3*time.Second, func() bool {
recentRows, err := svc.ListRecentIPs(context.Background(), time.Now().UTC().Add(-time.Hour), 10)
if err != nil {
return false
}
row, found := findRecentIPRow(recentRows, "203.0.113.33")
return found && row.Bot != nil && row.Bot.Name == "Googlebot"
})
recentRows, err := svc.ListRecentIPs(context.Background(), time.Now().UTC().Add(-time.Hour), 10)
if err != nil {
t.Fatalf("list recent ips: %v", err)
}
row, found := findRecentIPRow(recentRows, "203.0.113.33")
if !found {
t.Fatalf("expected recent row for investigated ip: %+v", recentRows)
}
if row.Bot == nil || row.Bot.Name != "Googlebot" {
t.Fatalf("expected background investigation bot on recent row, got %+v", row)
}
if investigator.callCount() == 0 {
t.Fatalf("expected background investigator to be called")
}
}
type fakeOPNsenseServer struct {
*httptest.Server
mu sync.Mutex
@@ -269,3 +350,30 @@ func findRecentIPRow(items []model.RecentIPRow, ip string) (model.RecentIPRow, b
}
return model.RecentIPRow{}, false
}
type fakeInvestigator struct {
mu sync.Mutex
count int
}
func (f *fakeInvestigator) Investigate(_ context.Context, ip string, _ []string) (model.IPInvestigation, error) {
f.mu.Lock()
f.count++
f.mu.Unlock()
return model.IPInvestigation{
IP: ip,
UpdatedAt: time.Now().UTC(),
Bot: &model.BotMatch{
ProviderID: "google_official",
Name: "Googlebot",
Method: "test",
Verified: true,
},
}, nil
}
func (f *fakeInvestigator) callCount() int {
f.mu.Lock()
defer f.mu.Unlock()
return f.count
}