Sources that always work (botvrij, disconnect, oisd, openphish, phishtank, quad9) drop their user-facing enable_* option; the rule's enabled/disabled state is now solely controlled by the SDK rule toggle. Sources that require credentials (criminalip, malwarebazaar, otx, pulsedive, safebrowsing, threatfox, urlhaus, virustotal) instead implement the new SourcePrecheck interface so the host UI can surface "not configured" before attempting a query.
88 lines
2.7 KiB
Go
88 lines
2.7 KiB
Go
package checker
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
sdk "git.happydns.org/checker-sdk-go/checker"
|
|
)
|
|
|
|
func TestThreatFoxSource_NoResult(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_, _ = w.Write([]byte(`{"query_status":"no_result","data":[]}`))
|
|
}))
|
|
defer srv.Close()
|
|
|
|
s := &threatFoxSource{endpoint: srv.URL}
|
|
results := s.Query(context.Background(), "example.com", "example.com", sdk.CheckerOptions{"threatfox_auth_key": "k"})
|
|
if len(results) != 1 {
|
|
t.Fatalf("expected 1 result, got %d", len(results))
|
|
}
|
|
r := results[0]
|
|
listed, _ := s.Evaluate(r)
|
|
if !r.Enabled || listed || r.Error != "" {
|
|
t.Fatalf("expected enabled+clean, got %+v, Evaluate listed=%v", r, listed)
|
|
}
|
|
}
|
|
|
|
func TestThreatFoxSource_Listed(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Header.Get("Auth-Key") == "" {
|
|
t.Errorf("missing Auth-Key header")
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_, _ = w.Write([]byte(`{
|
|
"query_status": "ok",
|
|
"data": [{
|
|
"ioc_value": "example.com:443",
|
|
"ioc_type": "domain",
|
|
"threat_type": "botnet_cc",
|
|
"malware_printable": "Emotet",
|
|
"confidence_level": 75,
|
|
"first_seen": "2024-01-01 00:00:00 UTC",
|
|
"last_seen": "2024-06-01 00:00:00 UTC"
|
|
}]
|
|
}`))
|
|
}))
|
|
defer srv.Close()
|
|
|
|
s := &threatFoxSource{endpoint: srv.URL}
|
|
r := s.Query(context.Background(), "example.com", "example.com", sdk.CheckerOptions{"threatfox_auth_key": "k"})[0]
|
|
if len(r.Evidence) != 1 {
|
|
t.Fatalf("expected 1 evidence item, got %+v", r)
|
|
}
|
|
if listed, severity := s.Evaluate(r); !listed || severity != SeverityCrit {
|
|
t.Errorf("expected Evaluate()=(true, crit), got (%v, %q)", listed, severity)
|
|
}
|
|
if r.Evidence[0].Value != "example.com:443" {
|
|
t.Errorf("evidence value = %q", r.Evidence[0].Value)
|
|
}
|
|
if len(r.Reasons) != 1 || r.Reasons[0] != "Emotet" {
|
|
t.Errorf("reasons = %v", r.Reasons)
|
|
}
|
|
}
|
|
|
|
func TestThreatFoxSource_HTTPError(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusUnauthorized)
|
|
_, _ = w.Write([]byte("unauthorized"))
|
|
}))
|
|
defer srv.Close()
|
|
|
|
s := &threatFoxSource{endpoint: srv.URL}
|
|
r := s.Query(context.Background(), "example.com", "example.com", sdk.CheckerOptions{"threatfox_auth_key": "k"})[0]
|
|
if r.Error == "" {
|
|
t.Errorf("expected error, got %+v", r)
|
|
}
|
|
}
|
|
|
|
func TestThreatFoxSource_NoAuthKey(t *testing.T) {
|
|
s := &threatFoxSource{endpoint: "http://nope"}
|
|
r := s.Query(context.Background(), "example.com", "example.com", nil)[0]
|
|
if r.Enabled {
|
|
t.Errorf("expected disabled when no auth key, got %+v", r)
|
|
}
|
|
}
|