Skip to content

feat(xtcp2): listener model, authenticated socket by default (FP-3) - #295

Merged
randomizedcoder merged 6 commits into
mainfrom
sec/fp3-listener-model
Nov 12, 2026
Merged

randomizedcoder merged 6 commits into
mainfrom
sec/fp3-listener-model

Conversation

@randomizedcoder

Copy link
Copy Markdown
Owner

Phase F1, FP-3 of the focused container hardening plan (#291). Based on FP-2. Breaking: see CHANGELOG.

  • New listener model: -listener (repeatable) / LISTENERS, each with an endpoint, auth, admin auth and the endpoint classes it serves (health, metrics, metrics-detail, ip, debug, grpc-read, grpc-admin). Rules live in the new pkg/listeners.
  • Default with no listener config: one Unix socket, /run/xtcp2/metrics.sock, mode 0600, raw token from LISTENER_RAW_TOKEN_FILE, serving health and metrics. No TCP listener. A missing token exits 64.
  • Every listener is bound before any is served, and config is validated before anything binds; a bind error fails startup.
  • pprof only on a listener serving debug; /debug/pprof/cmdline is never registered.
  • grpc-read registers read-only service adapters, so admin RPCs are not reachable on it at all.
  • The -prom*, -grpc* and -linkMonitorIPListen flags still work, expanded into listeners with a DEPRECATED line; mixing them with -listener exits 64. An unset auth mode is inferred from the credential given.
  • -healthcheck probes whichever listener serves health. ConfigService.Set validates listeners. Gauge xtcp2_listener_active{name,network,class}.
  • xtcp2ctl and xtcp2client dial unix:/run/xtcp2/grpc.sock by default; -network tcp for TCP.
  • NixOS module: listeners and listenerTokenFile options; with no token file, one is generated once under /var/lib/xtcp2. OCI daemon images expose no ports.
  • MicroVMs use explicit TCP listeners with a test token; uds-security keeps the socket-only shape.
  • Not here: go-link-monitor keeps its listeners (FP-3b).

Verified: Go tests and race on cmd/xtcp2, pkg/xtcp, pkg/listeners; golangci-lint, go-sec, flavor checks; microVMs uds-security lifecycle, scrape-auth, linkmonitor, ip-listen.

🤖 Generated with Claude Code

randomizedcoder and others added 6 commits November 11, 2026 20:10
First of three FP-3 commits: config and package, no daemon wiring yet.

- proto: EndpointClass (health, metrics, metrics-detail, ip, debug,
  grpc-read, grpc-admin), Listener{name, endpoint, auth, admin_auth,
  serves}, repeated listeners = 162; ListenerAuth gains raw_token_file and
  hmac_shared_key_file so per-listener credentials are paths, never
  secrets in the config; grpc_port no longer required (legacy only)
- pkg/listeners: Default (one UDS /run/xtcp2/metrics.sock 0600, raw auth,
  health+metrics+metrics-detail), Validate (class on one listener, no
  gRPC/HTTP mix, TCP must be typed, disabled auth only on UDS, loopback or
  health-only, debug/grpc-admin need an admin credential, ip needs
  ip_paths, no inline credentials), Resolve (endpoint, TTL 1 + loopback
  accept filter on loopback TCP, token files), ParseSpec/ParseList for
  -listener and LISTENERS; errors wrap ErrConfig (exit 64)
- pkg/secretfile: the FP-2 _FILE reader, shared by cmd and listeners
- RedactSecrets also blanks listener credentials; the redaction test now
  walks repeated fields and allow-lists the *_file path fields

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Wire the listener model into the daemon:

- Validate the config and resolve every listener and its credentials
  before anything binds; a bad listener config or token file exits 64.
- With no listener configured, serve health, metrics and metrics-detail
  on /run/xtcp2/metrics.sock (0600, raw bearer token). gRPC, pprof and
  /ip are served only by a listener that names them.
- -listener (repeatable) / LISTENERS describe listeners. The -prom*,
  -grpc* and -linkMonitorIPListen settings still work, expanded with a
  deprecation line; giving both forms exits 64. The expanded Prometheus
  listener no longer serves pprof.
- One HTTP mux per listener from the classes it serves; pprof only on a
  debug listener, /debug/pprof/cmdline never.
- gRPC servers start per listener; grpc-read registers no admin
  services.
- -healthcheck finds the health listener from the same config.
- An empty -listenerAuthMode / LISTENER_AUTH_MODE is unset, not
  disabled, so the raw default cannot be switched off by accident.
- ConfigService.Set refuses a listener config startup would refuse.
- xtcp2_listener_active{name,network,class}.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The daemon no longer listens on :8889 unless told to, so the clients
dial unix:/run/xtcp2/grpc.sock (listeners.DefaultGRPCSocketPath), the
documented place for a gRPC listener. -network tcp with -target/-port
still reaches a TCP listener.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
- pkg/listeners: an unset auth mode is inferred from the credential given
  (an hmac file means hmac, a token means raw), for admin auth too.
- NixOS module: `listeners` and `listenerTokenFile` options; with no token
  file a token is generated once under /var/lib/xtcp2. linkMonitor.ipListen
  becomes a loopback ip listener.
- microVMs: explicit TCP listeners with a fixed test token; the self-test,
  scrape-auth, linkmonitor and ip-listen tests send it. uds-security keeps
  the socket-only shape.
- OCI daemon images expose no ports.
- Docs and CHANGELOG for the listener model, the deprecated flags and the
  client defaults.
- Lint fixes in the listener wiring; a short socket dir for
  TestProbeReadyUnix (sun_path is 108 bytes).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Set validated the listeners before restoring the redacted credentials and
never read the per-listener token files. A Get -> Set round trip with an
inferred admin auth was refused, and a missing or open token file was
accepted, the restart scheduled, then startup failed with the daemon down.

Set now runs listeners.Resolve, as startup does, after the secret
preservation and on a clone so file contents never reach the response.
The table covers both failures.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Named constants for repeated strings, explicit UNSPECIFIED network cases,
and preallocated slices.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@randomizedcoder

Copy link
Copy Markdown
Owner Author
  • Addressed in a11b335: Set runs listeners.Resolve (reads credential files, builds policies) after secret restoration, on a clone; refused configs never restart.
  • Regression table covers missing/open/missing-admin token files and inferred-admin Get→Set round trips.
  • bc73a8e clears the seven comprehensive-lint findings.

@randomizedcoder
randomizedcoder changed the base branch from sec/fp2-secrets-s3-tls to main November 12, 2026 06:18
@randomizedcoder
randomizedcoder merged commit 5ae4121 into main Nov 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant