From 667436b3b69fcb8e58994e4fbec0ea016fbc927d Mon Sep 17 00:00:00 2001 From: Paul Lorenz Date: Tue, 22 Sep 2026 01:04:37 -0400 Subject: [PATCH] Stop the controller panicking on a tunnel v2 dial to an unknown service. Fixes #4442 - uses the nil-safe getApiSessionId() in loadServiceForName, matching loadServiceForId; the v2 tunnel circuit handler never establishes an api session, so the lookup-failure branch dereferenced a nil apiSession and took the controller down on any unresolvable service name - makes the default admin check log a read failure and return instead of panicking; the check is advisory and runs in a goroutine that can observe a datastore the shutdown path has closed, turning a controlled exit into exit 2 - adds godoc for checkEdgeInitialized covering the advisory contract and the remaining fatal case - notes both in the changelog --- CHANGELOG.md | 1 + controller/handler_edge_ctrl/common_tunnel.go | 2 +- controller/server/controller.go | 6 +++++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 39f98324a..da5d314b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -794,6 +794,7 @@ Thanks to the community members who contributed to this release. * github.com/openziti/xweb/v3: [v3.0.4 -> v3.0.5](https://github.com/openziti/xweb/compare/v3.0.4...v3.0.5) * github.com/openziti/ziti/v2: [v2.0.0 -> v2.1.0](https://github.com/openziti/ziti/compare/v2.0.0...v2.1.0) + * [Issue #4442](https://github.com/openziti/ziti/issues/4442) - Controller panics on tunnel v2 dial to an unknown service and on the default admin check when the db is not open * [Issue #4378](https://github.com/openziti/ziti/issues/4378) - Api session enforcer delete meter only marks when the batch delete fails * [Issue #4434](https://github.com/openziti/ziti/issues/4434) - Update to Go 1.27 * [Issue #4413](https://github.com/openziti/ziti/issues/4413) - debian controller & router packages hang on post-install script when installed via ansible diff --git a/controller/handler_edge_ctrl/common_tunnel.go b/controller/handler_edge_ctrl/common_tunnel.go index 501967e63..f1872c0df 100644 --- a/controller/handler_edge_ctrl/common_tunnel.go +++ b/controller/handler_edge_ctrl/common_tunnel.go @@ -219,7 +219,7 @@ func (self *baseTunnelRequestContext) loadServiceForName(name string) { } logrus. - WithField("apiSessionId", self.apiSession.Id). + WithField("apiSessionId", self.getApiSessionId()). WithField("operation", self.handler.Label()). WithField("router", self.sourceRouter.Name). WithField("serviceName", name). diff --git a/controller/server/controller.go b/controller/server/controller.go index 3d3ab8f91..c6eb8feb8 100644 --- a/controller/server/controller.go +++ b/controller/server/controller.go @@ -254,13 +254,17 @@ func (c *Controller) Run() { } } +// checkEdgeInitialized warns when no default admin exists, so that an uninitialized cluster member is +// diagnosable. It is advisory and runs concurrently with the rest of startup: a read failure is logged +// and the check abandoned. On a controller without raft, the absence of a default admin is fatal. func (c *Controller) checkEdgeInitialized() { log := pfxlog.Logger() admin, err := c.AppEnv.Managers.Identity.ReadDefaultAdmin() if err != nil { - log.WithError(err).Panic("could not check if a default admin exists") + log.WithError(err).Error("could not check if a default admin exists") + return } if admin == nil {