Implement MCNS v1: custom Go DNS server replacing CoreDNS
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>
This commit is contained in:
142
internal/dns/server_test.go
Normal file
142
internal/dns/server_test.go
Normal file
@@ -0,0 +1,142 @@
|
||||
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.")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user