Split the console from the resolver: fancy-dns-console writes the cluster
fancy-dns-console is a second binary holding the web UI, authentication and every edit. It writes ClientGroup, BlockList and DNSZone objects through the new kubeedit package and forwards all other /api routes to a running resolver with its own key, dropping the browser's credentials, so it can run in the cluster or on a workstation with a kubeconfig and nothing about the resolver's placement matters. The resolver never imports kubeedit and the console is not on the DNS path. kubeedit validates every spec with the runtime's own converters (kubesource.CheckGroup/CheckList/CheckZone) before writing, so the console cannot store an object the resolver would reject. Zone edits keep the file-based writer's behaviour: duplicate and below-a-delegation records are refused, a delegation in a new zone also gives the zone its servers, and a zone with no apex NS is never stored. Each object records the editing user in an annotation; updates retry on conflict. The resolver reports groups from ClientGroup objects as source "kubernetes" and counter-only rows (the "(default)" bucket, or a group removed since) as "history", and lists DNSZone zones as the editable ones. The console uses that to leave the YAML's groups alone and to drop history rows, which the UI would otherwise send back on save. Its GET /api/clients overlays the cluster's current objects on the resolver's list, because the resolver only sees an edit after its watch fires and a save made just after another would delete the first. An end-to-end test runs both halves against one fake apiserver: a group saved through the console refuses queries, a zone built record by record answers authoritatively, and a request with the resolver's own key is rejected by the console. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4d38945d94
commit
1a536e7d0e
25 files changed
+1950
-8
No files matched your search
@@ -32,6 +32,8 @@ internal/
|
||||
qlog/ bbolt query-log ring + live in-memory ring + SSE fanout
|
||||
metrics/ Prometheus collectors + rolling time-series rings
|
||||
cluster/ Valkey pub/sub, leader lease, divergence detection
|
||||
kubeedit/ the console's writes to ClientGroup/BlockList/DNSZone objects
|
||||
console/ the UI/edit half: auth, cluster writes, proxy to the resolver
|
||||
kubesource/ read-only watch of the fancydns.k6n.net CRDs (DNSZone,
|
||||
ClientGroup, BlockList) -> Snapshot -> config overlay
|
||||
api/ admin REST + SSE, auth, CORS, rate limiting
|
||||
@@ -115,6 +117,17 @@ Break these and you break the design, not just the test.
|
||||
skipped and keeps its last good version, it never fails the merge. A BlockList
|
||||
has no `path` and refuses `file://`, because a namespaced object must not
|
||||
choose a file the runtime reads or writes.
|
||||
- **The resolver and the console are separate binaries and only the console
|
||||
writes the cluster.** `cmd/fancy-dns-console` serves the UI, authenticates,
|
||||
writes objects through `kubeedit` (validated with the runtime's own
|
||||
`kubesource.Check*`, so it cannot store what the runtime would reject) and
|
||||
proxies every other `/api` route to the resolver with its own key, dropping
|
||||
the browser's credentials. `kubeedit` is never imported by the resolver and
|
||||
`kubesource` never writes. Reads that mix the two views (`/api/clients`) are
|
||||
made consistent with the cluster in the console, because the resolver only
|
||||
sees an edit after its watch fires: a save made just after another would
|
||||
otherwise delete the first. `source` on a group says where it is defined;
|
||||
`history` rows are counters, never groups, and are not sent to the UI.
|
||||
- **API keys are compared by SHA-256 hash, constant-time**, and
|
||||
`X-Forwarded-For` is honoured *only* from `trusted_proxies`. Honouring it from
|
||||
anyone lets a client spoof its identity past the ACL and the rate limiter.
|
||||
|
||||
Reference in new issue
Block a user