Replace the CoreDNS precursor with a purpose-built authoritative DNS server. Zones and records (A, AAAA, CNAME) are stored in SQLite and managed via synchronized gRPC + REST APIs authenticated through MCIAS. Non-authoritative queries are forwarded to upstream resolvers with in-memory caching. Key components: - DNS server (miekg/dns) with authoritative zone handling and forwarding - gRPC + REST management APIs with MCIAS auth (mcdsl integration) - SQLite storage with CNAME exclusivity enforcement and auto SOA serials - 30 tests covering database CRUD, DNS resolution, and caching Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
143 lines
3.8 KiB
Go
143 lines
3.8 KiB
Go
package dns
|
|
|
|
import (
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/miekg/dns"
|
|
|
|
"git.wntrmute.dev/kyle/mcns/internal/db"
|
|
"log/slog"
|
|
)
|
|
|
|
func openTestDB(t *testing.T) *db.DB {
|
|
t.Helper()
|
|
dir := t.TempDir()
|
|
database, err := db.Open(filepath.Join(dir, "test.db"))
|
|
if err != nil {
|
|
t.Fatalf("open db: %v", err)
|
|
}
|
|
if err := database.Migrate(); err != nil {
|
|
t.Fatalf("migrate: %v", err)
|
|
}
|
|
t.Cleanup(func() { _ = database.Close() })
|
|
return database
|
|
}
|
|
|
|
func setupTestServer(t *testing.T) (*Server, *db.DB) {
|
|
t.Helper()
|
|
database := openTestDB(t)
|
|
logger := slog.Default()
|
|
|
|
_, err := database.CreateZone("svc.mcp.metacircular.net", "ns.mcp.metacircular.net.", "admin.metacircular.net.", 3600, 600, 86400, 300)
|
|
if err != nil {
|
|
t.Fatalf("create zone: %v", err)
|
|
}
|
|
_, err = database.CreateRecord("svc.mcp.metacircular.net", "metacrypt", "A", "192.168.88.181", 300)
|
|
if err != nil {
|
|
t.Fatalf("create A record: %v", err)
|
|
}
|
|
_, err = database.CreateRecord("svc.mcp.metacircular.net", "metacrypt", "A", "100.95.252.120", 300)
|
|
if err != nil {
|
|
t.Fatalf("create A record 2: %v", err)
|
|
}
|
|
_, err = database.CreateRecord("svc.mcp.metacircular.net", "mcr", "AAAA", "2001:db8::1", 300)
|
|
if err != nil {
|
|
t.Fatalf("create AAAA record: %v", err)
|
|
}
|
|
_, err = database.CreateRecord("svc.mcp.metacircular.net", "alias", "CNAME", "metacrypt.svc.mcp.metacircular.net.", 300)
|
|
if err != nil {
|
|
t.Fatalf("create CNAME record: %v", err)
|
|
}
|
|
|
|
srv := New(database, []string{"1.1.1.1:53"}, logger)
|
|
return srv, database
|
|
}
|
|
|
|
func TestFindZone(t *testing.T) {
|
|
srv, _ := setupTestServer(t)
|
|
|
|
zone := srv.findZone("metacrypt.svc.mcp.metacircular.net.")
|
|
if zone == nil {
|
|
t.Fatal("expected to find zone")
|
|
}
|
|
if zone.Name != "svc.mcp.metacircular.net" {
|
|
t.Fatalf("got zone %q, want %q", zone.Name, "svc.mcp.metacircular.net")
|
|
}
|
|
|
|
zone = srv.findZone("nonexistent.com.")
|
|
if zone != nil {
|
|
t.Fatal("expected nil for nonexistent zone")
|
|
}
|
|
}
|
|
|
|
func TestBuildSOA(t *testing.T) {
|
|
srv, database := setupTestServer(t)
|
|
zone, err := database.GetZone("svc.mcp.metacircular.net")
|
|
if err != nil {
|
|
t.Fatalf("get zone: %v", err)
|
|
}
|
|
|
|
soa := srv.buildSOA(zone)
|
|
if soa.Ns != "ns.mcp.metacircular.net." {
|
|
t.Fatalf("got ns %q, want %q", soa.Ns, "ns.mcp.metacircular.net.")
|
|
}
|
|
if soa.Hdr.Name != "svc.mcp.metacircular.net." {
|
|
t.Fatalf("got name %q, want %q", soa.Hdr.Name, "svc.mcp.metacircular.net.")
|
|
}
|
|
}
|
|
|
|
func TestRecordToRR_A(t *testing.T) {
|
|
srv, _ := setupTestServer(t)
|
|
|
|
rec := db.Record{Name: "metacrypt", Type: "A", Value: "192.168.88.181", TTL: 300}
|
|
rr := srv.recordToRR("metacrypt.svc.mcp.metacircular.net.", rec)
|
|
if rr == nil {
|
|
t.Fatal("expected non-nil RR")
|
|
}
|
|
|
|
a, ok := rr.(*dns.A)
|
|
if !ok {
|
|
t.Fatalf("expected *dns.A, got %T", rr)
|
|
}
|
|
if a.A.String() != "192.168.88.181" {
|
|
t.Fatalf("got IP %q, want %q", a.A.String(), "192.168.88.181")
|
|
}
|
|
}
|
|
|
|
func TestRecordToRR_AAAA(t *testing.T) {
|
|
srv, _ := setupTestServer(t)
|
|
|
|
rec := db.Record{Name: "mcr", Type: "AAAA", Value: "2001:db8::1", TTL: 300}
|
|
rr := srv.recordToRR("mcr.svc.mcp.metacircular.net.", rec)
|
|
if rr == nil {
|
|
t.Fatal("expected non-nil RR")
|
|
}
|
|
|
|
aaaa, ok := rr.(*dns.AAAA)
|
|
if !ok {
|
|
t.Fatalf("expected *dns.AAAA, got %T", rr)
|
|
}
|
|
if aaaa.AAAA.String() != "2001:db8::1" {
|
|
t.Fatalf("got IP %q, want %q", aaaa.AAAA.String(), "2001:db8::1")
|
|
}
|
|
}
|
|
|
|
func TestRecordToRR_CNAME(t *testing.T) {
|
|
srv, _ := setupTestServer(t)
|
|
|
|
rec := db.Record{Name: "alias", Type: "CNAME", Value: "metacrypt.svc.mcp.metacircular.net.", TTL: 300}
|
|
rr := srv.recordToRR("alias.svc.mcp.metacircular.net.", rec)
|
|
if rr == nil {
|
|
t.Fatal("expected non-nil RR")
|
|
}
|
|
|
|
cname, ok := rr.(*dns.CNAME)
|
|
if !ok {
|
|
t.Fatalf("expected *dns.CNAME, got %T", rr)
|
|
}
|
|
if cname.Target != "metacrypt.svc.mcp.metacircular.net." {
|
|
t.Fatalf("got target %q, want %q", cname.Target, "metacrypt.svc.mcp.metacircular.net.")
|
|
}
|
|
}
|