Files
ARTEX/db/asset_intercept_match_test.go
BaaRai e233c02314 Translate all Chinese text to English
Comments, doc comments, UI labels, log and error messages, LLM prompt
strings, markdown docs, test data and assertions. Identifiers, enum
keys, routes, placeholders and code structure are unchanged.

Notes:
- docs/漏洞流量证据.md renamed to docs/vulnerability-traffic-evidence.md
- tests that exercised CJK specific handling (GBK zip names, Chinese
  full text search) now use ASCII equivalents; go build passes and the
  test suite matches the pre translation baseline (remaining failures
  need a PostgreSQL DSN and fail identically on the original)
- frontend mention syntax now uses English kinds (finding, asset, ...)
  matching the backend, chat mentions tests pass
2026-10-08 23:14:34 +02:00

131 lines
5.5 KiB
Go

package db
import "testing"
func rule(kind, pattern string, enabled bool) AssetInterceptRule {
return AssetInterceptRule{Kind: kind, Pattern: pattern, Enabled: enabled}
}
func TestMatchAssetInterceptRules(t *testing.T) {
cases := []struct {
name string
rules []AssetInterceptRule
domains []string
ips []string
urls []string
want bool
wantVal string
}{
{"built-in fuzzy government domain hit", []AssetInterceptRule{rule("fuzzy_domain", ".gov.cn", true)},
[]string{"www.beijing.gov.cn"}, nil, nil, true, "www.beijing.gov.cn"},
{"fuzzy education domain hit", []AssetInterceptRule{rule("fuzzy_domain", ".edu", true)},
[]string{"mit.edu"}, nil, nil, true, "mit.edu"},
{"exact domain hit is case-insensitive", []AssetInterceptRule{rule("exact_domain", "Example.com", true)},
[]string{"example.com"}, nil, nil, true, "example.com"},
{"exact domain does not hit subdomain", []AssetInterceptRule{rule("exact_domain", "example.com", true)},
[]string{"a.example.com"}, nil, nil, false, ""},
{"exact IP hit", []AssetInterceptRule{rule("exact_ip", "203.0.113.5", true)},
nil, []string{"203.0.113.5"}, nil, true, "203.0.113.5"},
{"fuzzy IP prefix hit", []AssetInterceptRule{rule("fuzzy_ip", "203.0.113.", true)},
nil, []string{"203.0.113.99"}, nil, true, "203.0.113.99"},
{"CIDR hit", []AssetInterceptRule{rule("cidr", "192.168.0.0/16", true)},
nil, []string{"192.168.5.20"}, nil, true, "192.168.5.20"},
{"CIDR no hit", []AssetInterceptRule{rule("cidr", "192.168.0.0/16", true)},
nil, []string{"10.0.0.1"}, nil, false, ""},
{"exact URL hit", []AssetInterceptRule{rule("exact_url", "https://a.gov.cn/login", true)},
nil, nil, []string{"https://a.gov.cn/login"}, true, "https://a.gov.cn/login"},
{"fuzzy URL hits path", []AssetInterceptRule{rule("fuzzy_url", "/admin", true)},
nil, nil, []string{"https://x.com/admin/panel"}, true, "https://x.com/admin/panel"},
{"disabled rule does not hit", []AssetInterceptRule{rule("fuzzy_domain", ".gov.cn", false)},
[]string{"www.gov.cn"}, nil, nil, false, ""},
{"no rules no hit", nil, []string{"www.gov.cn"}, nil, nil, false, ""},
{"empty pattern no hit", []AssetInterceptRule{rule("fuzzy_domain", " ", true)},
[]string{"www.gov.cn"}, nil, nil, false, ""},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
r, val, ok := MatchAssetInterceptRules(c.rules, c.domains, c.ips, c.urls)
if ok != c.want {
t.Fatalf("hit = %v, want %v (rule=%+v)", ok, c.want, r)
}
if ok && val != c.wantVal {
t.Fatalf("matched value = %q, want %q", val, c.wantVal)
}
})
}
}
func TestEvaluateAssetGate(t *testing.T) {
block := []AssetInterceptRule{rule("fuzzy_domain", ".gov.cn", true)}
allow := []AssetInterceptRule{rule("fuzzy_domain", "example.com", true)}
// 1. Interception rule hit → reject (interception reason takes priority).
if d := EvaluateAssetGate(block, allow, []string{"www.gov.cn"}, nil, nil); d.Allowed {
t.Fatal("hitting an interception rule should be rejected")
}
// 2. No interception hit, allow rules exist but do not match → reject (not allowed).
d := EvaluateAssetGate(block, allow, []string{"foo.other.com"}, nil, nil)
if d.Allowed {
t.Fatal("having a whitelist without a match should be rejected")
}
if d.Reason == "" {
t.Fatal("rejection should carry a reason")
}
// 3. No interception hit, allow rule hit → allow.
if d := EvaluateAssetGate(block, allow, []string{"api.example.com"}, nil, nil); !d.Allowed {
t.Fatal("hitting the whitelist should be allowed")
}
// 4. No allow rules (whitelist not enabled) → no interception hit means allow.
if d := EvaluateAssetGate(block, nil, []string{"foo.other.com"}, nil, nil); !d.Allowed {
t.Fatal("with no whitelist, missing the interception rules should be allowed")
}
// 5. All allow rules disabled → treated as whitelist not enabled, allow.
disabledAllow := []AssetInterceptRule{rule("fuzzy_domain", "example.com", false)}
if d := EvaluateAssetGate(nil, disabledAllow, []string{"foo.other.com"}, nil, nil); !d.Allowed {
t.Fatal("with the whitelist fully disabled, should be allowed")
}
// 6. Interception beats allow: the same target hits both → reject.
if d := EvaluateAssetGate(
[]AssetInterceptRule{rule("fuzzy_domain", ".gov.cn", true)},
[]AssetInterceptRule{rule("fuzzy_domain", ".gov.cn", true)},
[]string{"www.gov.cn"}, nil, nil,
); d.Allowed {
t.Fatal("interception should take priority over allow")
}
}
func TestAssetInterceptCandidates(t *testing.T) {
// Service asset carrying only a URL: the host should be split out into the
// domain candidates, so it can be hit by fuzzy_domain.
a := &Asset{Type: "service", URL: "https://portal.beijing.gov.cn:8443/app"}
domains, _, urls := a.interceptCandidates()
if len(urls) != 1 || urls[0] != a.URL {
t.Fatalf("urls = %v", urls)
}
found := false
for _, d := range domains {
if d == "portal.beijing.gov.cn" {
found = true
}
}
if !found {
t.Fatalf("URL host was not split into domain candidates: %v", domains)
}
r, _, ok := MatchAssetInterceptRules([]AssetInterceptRule{rule("fuzzy_domain", ".gov.cn", true)}, domains, nil, urls)
if !ok {
t.Fatalf("a government service asset with only a URL should be hit by fuzzy_domain, rule=%+v", r)
}
// When the URL host is an IP it should go into the IP candidates, matchable by CIDR.
b := &Asset{Type: "service", URL: "http://10.1.2.3/x"}
_, ips, _ := b.interceptCandidates()
if r, _, ok := MatchAssetInterceptRules([]AssetInterceptRule{rule("cidr", "10.0.0.0/8", true)}, nil, ips, nil); !ok {
t.Fatalf("an IP in a URL should be hit by CIDR, ips=%v rule=%+v", ips, r)
}
}