Single stateless Go process that consumes CT logs via embedded (patched) CertSpotter internals, classifies cloud/database/storage DNS identifiers in-process with a zero-allocation classifier, enriches via round-robin DNS resolvers with CNAME following, and batch-writes useful findings to PostgreSQL. - third_party/certspotter: 2-hunk IdentifierSink patch, no stdout/JSON/files - internal/classify: AWS/Azure/GCP/Firebase/Cloudflare R2/DigitalOcean/Supabase/OCI - internal/dns: sharded bounded TTL cache, multi-resolver load balancing + failover - internal/pipeline: bounded queues, dedup, direct-priority load shedding - internal/store: pgx batch writer, Postgres CT checkpoints (no cert contents) - internal/probe: optional non-destructive reachability checks (off by default) - Docker: distroless non-root, read-only rootfs, no app volume, resource limits - tests enforce 0 allocs/op on the classifier and sink hot path
69 lines
1.7 KiB
Go
69 lines
1.7 KiB
Go
package dns
|
|
|
|
import (
|
|
"context"
|
|
"net"
|
|
"sync/atomic"
|
|
"testing"
|
|
)
|
|
|
|
type fakeLookup struct {
|
|
calls atomic.Int32
|
|
cnameErr error
|
|
ipErr error
|
|
}
|
|
|
|
func (f *fakeLookup) LookupCNAME(ctx context.Context, host string) (string, error) {
|
|
f.calls.Add(1)
|
|
if f.cnameErr != nil {
|
|
return "", f.cnameErr
|
|
}
|
|
return host, nil
|
|
}
|
|
|
|
func (f *fakeLookup) LookupIP(ctx context.Context, host string) ([]net.IP, error) {
|
|
f.calls.Add(1)
|
|
if f.ipErr != nil {
|
|
return nil, f.ipErr
|
|
}
|
|
return []net.IP{net.ParseIP("1.2.3.4")}, nil
|
|
}
|
|
|
|
func TestServerPoolRoundRobin(t *testing.T) {
|
|
a, b := &fakeLookup{}, &fakeLookup{}
|
|
p := &ServerPool{resolvers: []Resolver{a, b}}
|
|
for i := 0; i < 4; i++ {
|
|
if _, err := p.LookupIP(context.Background(), "example.com"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
if a.calls.Load() != 2 || b.calls.Load() != 2 {
|
|
t.Fatalf("round robin calls: a=%d b=%d, want 2/2", a.calls.Load(), b.calls.Load())
|
|
}
|
|
}
|
|
|
|
func TestServerPoolFailover(t *testing.T) {
|
|
a := &fakeLookup{ipErr: &net.DNSError{Err: "timeout", IsTimeout: true}}
|
|
b := &fakeLookup{}
|
|
p := &ServerPool{resolvers: []Resolver{a, b}}
|
|
ips, err := p.LookupIP(context.Background(), "example.com")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(ips) != 1 || a.calls.Load() != 1 {
|
|
t.Fatalf("expected failover to second server, a.calls=%d", a.calls.Load())
|
|
}
|
|
}
|
|
|
|
func TestServerPoolNoFailoverOnNXDOMAIN(t *testing.T) {
|
|
a := &fakeLookup{ipErr: &net.DNSError{Err: "no such host", IsNotFound: true}}
|
|
b := &fakeLookup{}
|
|
p := &ServerPool{resolvers: []Resolver{a, b}}
|
|
if _, err := p.LookupIP(context.Background(), "missing.example.com"); err == nil {
|
|
t.Fatal("expected error")
|
|
}
|
|
if b.calls.Load() != 0 {
|
|
t.Fatalf("NXDOMAIN must not fail over; b.calls=%d", b.calls.Load())
|
|
}
|
|
}
|