From 36243927c0afd4aa2b0dd533d66ac214c26d6232 Mon Sep 17 00:00:00 2001 From: Paul Lorenz Date: Thu, 22 Feb 2024 09:03:46 -0500 Subject: [PATCH 1/3] Improve session management when hosting services. Fixes #501 --- ziti/ziti.go | 182 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 131 insertions(+), 51 deletions(-) diff --git a/ziti/ziti.go b/ziti/ziti.go index b8d31fb2..2a64e728 100644 --- a/ziti/ziti.go +++ b/ziti/ziti.go @@ -27,9 +27,11 @@ import ( rest_session "github.com/openziti/edge-api/rest_client_api_client/session" "github.com/openziti/foundation/v2/concurrenz" "github.com/openziti/foundation/v2/errorz" + "github.com/openziti/foundation/v2/stringz" apis "github.com/openziti/sdk-golang/edge-apis" "github.com/openziti/secretstream/kx" "math" + "math/rand" "net" "reflect" "strconv" @@ -187,6 +189,8 @@ type ContextImpl struct { authQueryHandlers map[string]func(query *rest_model.AuthQueryDetail, response MfaCodeResponse) error events.EventEmmiter + apiSessionLock sync.Mutex + lastSuccessfulApiSessionRefresh time.Time } func (context *ContextImpl) AddServiceAddedListener(handler func(Context, *rest_model.ServiceDetail)) func() { @@ -844,10 +848,17 @@ func (context *ContextImpl) Reauthenticate() error { } func (context *ContextImpl) Authenticate() error { + context.apiSessionLock.Lock() + defer context.apiSessionLock.Unlock() + if context.CtrlClt.GetCurrentApiSession() != nil { + if time.Since(context.lastSuccessfulApiSessionRefresh) < 5*time.Second { + return nil + } logrus.Debug("previous apiSession detected, checking if valid") - if _, err := context.CtrlClt.Refresh(); err == nil { + if err := context.RefreshApiSessionWithBackoff(); err == nil { logrus.Info("previous apiSession refreshed") + context.lastSuccessfulApiSessionRefresh = time.Now() return nil } else { logrus.WithError(err).Info("previous apiSession failed to refresh, attempting to authenticate") @@ -857,6 +868,31 @@ func (context *ContextImpl) Authenticate() error { return context.authenticate() } +func (context *ContextImpl) RefreshApiSessionWithBackoff() error { + expBackoff := backoff.NewExponentialBackOff() + + expBackoff.InitialInterval = 5 * time.Second + expBackoff.MaxInterval = 5 * time.Minute + expBackoff.MaxElapsedTime = 24 * time.Hour + + operation := func() error { + _, err := context.CtrlClt.Refresh() + if err == nil { + return nil + } + + unauthorizedErr := ¤t_api_session.GetCurrentAPISessionUnauthorized{} + if errors.As(err, &unauthorizedErr) { + logrus.Info("previous apiSession expired") + return backoff.Permanent(err) + } + logrus.WithError(err).Info("unable to refresh apiSession, will retry") + return err + } + + return backoff.Retry(operation, expBackoff) +} + func (context *ContextImpl) CloseAllEdgeRouterConns() { for entry := range context.routerConnections.IterBuffered() { key, val := entry.Key, entry.Val @@ -1240,7 +1276,7 @@ func (context *ContextImpl) connectEdgeRouter(routerName, ingressUrl string, ret return } - pfxlog.Logger().Debugf("connection to edge router using api session token %v", currentApiSession.GetToken()) + pfxlog.Logger().Debugf("connection to edge router using api session token %s", string(currentApiSession.GetToken())) id, err := context.CtrlClt.GetIdentity() if err != nil { @@ -1616,18 +1652,20 @@ func newListenerManager(service *rest_model.ServiceDetail, context *ContextImpl, } type listenerManager struct { - service *rest_model.ServiceDetail - context *ContextImpl - session *rest_model.SessionDetail - options *edge.ListenOptions - routerConnections map[string]edge.RouterConn - connects map[string]time.Time - listener network.MultiListener - connectChan chan *edgeRouterConnResult - eventChan chan listenerEvent - sessionRefreshTime time.Time - disconnectedTime *time.Time - observers concurrenz.CopyOnWriteSlice[ListenEventObserver] + service *rest_model.ServiceDetail + context *ContextImpl + session *rest_model.SessionDetail + options *edge.ListenOptions + routerConnections map[string]edge.RouterConn + connects map[string]time.Time + listener network.MultiListener + connectChan chan *edgeRouterConnResult + eventChan chan listenerEvent + sessionRefreshInterval time.Duration + restartSessionRefresh bool + lastSessionRefresh time.Time + disconnectedTime *time.Time + observers concurrenz.CopyOnWriteSlice[ListenEventObserver] } func (mgr *listenerManager) AddObserver(observer ListenEventObserver) { @@ -1645,6 +1683,7 @@ func (mgr *listenerManager) notify(eventType ListenEventType) { } func (mgr *listenerManager) run() { + log := pfxlog.Logger().WithField("service", stringz.OrEmpty(mgr.service.Name)) // need to either establish a session, or fail if we can't create one for mgr.session == nil { mgr.createSessionWithBackoff() @@ -1665,41 +1704,21 @@ func (mgr *listenerManager) run() { identitySecret, err := signing.AssertIdentityWithSecret(id.Cert().PrivateKey) if err != nil { - pfxlog.Logger().Errorf("failed to sign identity: %v", err) + log.WithError(err).Error("failed to sign identity") } else { mgr.options.IdentitySecret = string(identitySecret) } } - ticker := time.NewTicker(250 * time.Millisecond) - + ticker := time.NewTicker(time.Second) defer ticker.Stop() - refreshSessionTimerInterval := 10 * time.Second + var refreshSessionChan <-chan time.Time for !mgr.listener.IsClosed() { - var refreshSessionTimer *time.Timer - if len(mgr.session.EdgeRouters) == 0 { - refreshSessionTimer = time.NewTimer(refreshSessionTimerInterval) - } else if len(mgr.session.EdgeRouters) < mgr.options.MaxTerminators { - if refreshSessionTimerInterval < 5*time.Minute { - refreshSessionTimerInterval = 5 * time.Minute - } - refreshSessionTimer = time.NewTimer(refreshSessionTimerInterval) - } - - if refreshSessionTimer != nil { - refreshSessionTimerInterval *= 2 - if refreshSessionTimerInterval > 30*time.Minute { - refreshSessionTimerInterval = 30 * time.Minute - } - } else { - refreshSessionTimerInterval = 10 * time.Second - } - - var refreshSessionTimerC <-chan time.Time - if refreshSessionTimer != nil { - refreshSessionTimerC = refreshSessionTimer.C + if mgr.restartSessionRefresh { + refreshSessionChan = time.After(mgr.sessionRefreshInterval) + mgr.restartSessionRefresh = false } //goland:noinspection GoNilness @@ -1708,8 +1727,14 @@ func (mgr *listenerManager) run() { mgr.handleRouterConnectResult(routerConnectionResult) case event := <-mgr.eventChan: event.handle(mgr) - case <-refreshSessionTimerC: + case <-refreshSessionChan: mgr.refreshSession() + log.Debugf("next refresh in %s", mgr.sessionRefreshInterval.String()) + refreshSessionChan = time.After(mgr.sessionRefreshInterval) + mgr.sessionRefreshInterval *= 2 + if mgr.sessionRefreshInterval > 30*time.Minute { + mgr.sessionRefreshInterval = 30 * time.Minute + } case <-ticker.C: mgr.makeMoreListeners() case <-mgr.options.GetEventChannel(): @@ -1717,11 +1742,47 @@ func (mgr *listenerManager) run() { case <-mgr.context.closeNotify: mgr.listener.CloseWithError(errors.New("context closed")) } + } +} + +func (mgr *listenerManager) sessionRefreshed(session *rest_model.SessionDetail) { + oldUsableCount := mgr.getUsableEndpointCount(mgr.session) + newUsableCount := mgr.getUsableEndpointCount(session) + + if oldUsableCount >= 0 && newUsableCount == 0 { + mgr.sessionRefreshInterval = time.Duration(5+rand.Intn(10)) * time.Second + } else if newUsableCount == 0 || newUsableCount < mgr.options.MaxTerminators { + mgr.sessionRefreshInterval = time.Duration(5+rand.Intn(5)) * time.Minute + } else { + mgr.sessionRefreshInterval = 30 * time.Minute + } + + mgr.session = session + mgr.restartSessionRefresh = true + mgr.lastSessionRefresh = time.Now() - if refreshSessionTimer != nil { - refreshSessionTimer.Stop() + log := pfxlog.Logger(). + WithField("service", stringz.OrEmpty(mgr.service.Name)). + WithField("sessionId", stringz.OrEmpty(mgr.session.ID)). + WithField("usableEndpoints", newUsableCount). + WithField("nextRefresh", mgr.sessionRefreshInterval.String()) + log.Debug("session refreshed") +} + +func (mgr *listenerManager) getUsableEndpointCount(session *rest_model.SessionDetail) int { + if session == nil { + return 0 + } + + count := 0 + for _, edgeRouter := range session.EdgeRouters { + for _, routerUrl := range edgeRouter.Urls { + if mgr.context.options.isEdgeRouterUrlAccepted(routerUrl) { + count++ + } } } + return count } func (mgr *listenerManager) handleRouterConnectResult(result *edgeRouterConnResult) { @@ -1779,26 +1840,35 @@ func (mgr *listenerManager) createListener(routerConnection edge.RouterConn, ses } func (mgr *listenerManager) makeMoreListeners() { + log := pfxlog.Logger().WithField("service", *mgr.service.Name).WithField("erCount", len(mgr.session.EdgeRouters)) if mgr.listener.IsClosed() || len(mgr.routerConnections) >= mgr.options.MaxTerminators || len(mgr.session.EdgeRouters) <= len(mgr.routerConnections) { + log.Trace("not trying to make more connections") return } for _, edgeRouter := range mgr.session.EdgeRouters { if _, ok := mgr.routerConnections[*edgeRouter.Name]; ok { + log.WithField("router", *edgeRouter.Name).Trace("already connected") // already connected to this router continue } for _, routerUrl := range edgeRouter.Urls { if !mgr.context.options.isEdgeRouterUrlAccepted(routerUrl) { + log.WithField("router", *edgeRouter.Name).WithField("url", routerUrl). + Trace("skipping unusable url") continue } if _, ok := mgr.connects[routerUrl]; ok { // this url already has a connect in progress + log.WithField("router", *edgeRouter.Name).WithField("url", routerUrl). + Trace("connect already in progress") continue } + log.WithField("router", *edgeRouter.Name).WithField("url", routerUrl). + Trace("attempting to connect to router") mgr.connects[routerUrl] = time.Now() go mgr.context.connectEdgeRouter(*edgeRouter.Name, routerUrl, mgr.connectChan) } @@ -1806,11 +1876,19 @@ func (mgr *listenerManager) makeMoreListeners() { } func (mgr *listenerManager) refreshSession() { + if time.Since(mgr.lastSessionRefresh) < 30*time.Second { + return + } + + log := pfxlog.Logger().WithField("service", stringz.OrEmpty(mgr.service.Name)) if mgr.session == nil { + log.Debug("establishing initial session") mgr.createSessionWithBackoff() return } + log = log.WithField("sessionId", stringz.OrEmpty(mgr.session.ID)).WithField("erCount", len(mgr.session.EdgeRouters)) + log.Info("starting session refresh") session, err := mgr.context.refreshSession(mgr.session) if err != nil { @@ -1823,7 +1901,7 @@ func (mgr *listenerManager) refreshSession() { target = &rest_session.DetailSessionUnauthorized{} if errors.As(err, &target) { - pfxlog.Logger().WithError(err).Debugf("failure refreshing bind session for service %v", mgr.listener.GetServiceName()) + log.WithError(err).Debugf("failure refreshing bind session for service %v", mgr.listener.GetServiceName()) if err := mgr.context.EnsureAuthenticated(mgr.options); err != nil { err := fmt.Errorf("unable to establish API session (%w)", err) if len(mgr.routerConnections) == 0 { @@ -1837,7 +1915,7 @@ func (mgr *listenerManager) refreshSession() { if err != nil { target = &rest_session.DetailSessionUnauthorized{} if errors.As(err, &target) { - pfxlog.Logger().WithError(err).Errorf( + log.WithError(err).Errorf( "failure refreshing bind session even after re-authenticating api session. service %v", mgr.listener.GetServiceName()) if len(mgr.routerConnections) == 0 { @@ -1846,7 +1924,7 @@ func (mgr *listenerManager) refreshSession() { return } - pfxlog.Logger().WithError(err).Errorf("failed to to refresh session %v", *mgr.session.ID) + log.WithError(err).Errorf("failed to to refresh session %v", *mgr.session.ID) // try to create new session mgr.createSessionWithBackoff() @@ -1856,8 +1934,7 @@ func (mgr *listenerManager) refreshSession() { // token only returned on created, so if we refreshed the session (as opposed to creating a new one) we have to back-fill it on lookups if session != nil { session.Token = mgr.session.Token - mgr.session = session - mgr.sessionRefreshTime = time.Now() + mgr.sessionRefreshed(session) } } @@ -1874,8 +1951,7 @@ func (mgr *listenerManager) createSessionWithBackoff() { session, err := mgr.context.createSessionWithBackoff(mgr.service, SessionType(SessionBind), mgr.options) if session != nil { - mgr.session = session - mgr.sessionRefreshTime = time.Now() + mgr.sessionRefreshed(session) pfxlog.Logger().WithField("session token", *session.Token).Info("new service session") } else { pfxlog.Logger().WithError(err).Errorf("failed to create bind session for service %v", mgr.service.Name) @@ -1923,7 +1999,11 @@ func (event *routerConnectionListenFailedEvent) handle(mgr *listenerManager) { mgr.disconnectedTime = &now } mgr.notify(ListenerRemoved) - mgr.refreshSession() // if a listener failed, ensure our session is valid + if mgr.sessionRefreshInterval > 10*time.Second && time.Since(mgr.lastSessionRefresh) > 10*time.Second { + mgr.sessionRefreshInterval = time.Duration(100+(rand.Intn(10)*1000)) * time.Millisecond + mgr.restartSessionRefresh = true + } + mgr.refreshSession() mgr.makeMoreListeners() } From aa17b707e1309ee0c5fac6002f21a10a6287580e Mon Sep 17 00:00:00 2001 From: Paul Lorenz Date: Thu, 22 Feb 2024 10:09:59 -0500 Subject: [PATCH 2/3] Update changelog --- CHANGELOG.md | 12 ++++++++++++ ziti/ziti.go | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a261e18..a6973867 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +# Release 0.22.29 + +- Improve session refresh behavior. + +## Changes to API session refresh +* Limit refreshes of both api and sessions to at most every 30 seconds. +* Base faster refreshes not on number of available ERs but on usable ER endpoints, since some ERs may not have usable endpoints +* Only refresh API sessions if session is no longer valid, as opposed if an api session refresh fails, which can happen if the + controller is down or busy. +* Only allow one api session refresh at a time +* Use exponential backoff for api session refresh retries + # Release 0.22.12 - Deprecate ListenOptions.MaxConnections in favor of ListenOptions.MaxTerminators diff --git a/ziti/ziti.go b/ziti/ziti.go index 2a64e728..129fdb76 100644 --- a/ziti/ziti.go +++ b/ziti/ziti.go @@ -1888,7 +1888,7 @@ func (mgr *listenerManager) refreshSession() { } log = log.WithField("sessionId", stringz.OrEmpty(mgr.session.ID)).WithField("erCount", len(mgr.session.EdgeRouters)) - log.Info("starting session refresh") + log.Debug("starting session refresh") session, err := mgr.context.refreshSession(mgr.session) if err != nil { From 8a50a3f758abc765b025faeabce41928a1bdf24a Mon Sep 17 00:00:00 2001 From: ziti-ci Date: Thu, 22 Feb 2024 18:27:49 +0000 Subject: [PATCH 3/3] Updating dependency github.com/openziti/edge-api@v0.26.11 --- go.mod | 18 +++++++++--------- go.sum | 48 ++++++++++++++++++------------------------------ 2 files changed, 27 insertions(+), 39 deletions(-) diff --git a/go.mod b/go.mod index 5cbfe3c6..dd83d4af 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/mitchellh/go-ps v1.0.0 github.com/mitchellh/mapstructure v1.5.0 github.com/openziti/channel/v2 v2.0.119 - github.com/openziti/edge-api v0.26.10 + github.com/openziti/edge-api v0.26.11 github.com/openziti/foundation/v2 v2.0.37 github.com/openziti/identity v1.0.70 github.com/openziti/metrics v1.2.45 @@ -52,7 +52,7 @@ require ( github.com/go-openapi/loads v0.21.5 // indirect github.com/go-openapi/spec v0.20.14 // indirect github.com/go-openapi/swag v0.22.9 // indirect - github.com/go-openapi/validate v0.22.6 // indirect + github.com/go-openapi/validate v0.23.0 // indirect github.com/gorilla/mux v1.8.1 // indirect github.com/gorilla/schema v1.2.0 // indirect github.com/gorilla/securecookie v1.1.1 // indirect @@ -75,13 +75,13 @@ require ( github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect - go.mongodb.org/mongo-driver v1.13.1 // indirect - go.opentelemetry.io/otel v1.21.0 // indirect - go.opentelemetry.io/otel/metric v1.21.0 // indirect - go.opentelemetry.io/otel/trace v1.21.0 // indirect - golang.org/x/crypto v0.18.0 // indirect - golang.org/x/net v0.20.0 // indirect - golang.org/x/sync v0.5.0 // indirect + go.mongodb.org/mongo-driver v1.14.0 // indirect + go.opentelemetry.io/otel v1.23.1 // indirect + go.opentelemetry.io/otel/metric v1.23.1 // indirect + go.opentelemetry.io/otel/trace v1.23.1 // indirect + golang.org/x/crypto v0.19.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sync v0.6.0 // indirect golang.org/x/term v0.17.0 // indirect golang.org/x/text v0.14.0 // indirect google.golang.org/appengine v1.6.7 // indirect diff --git a/go.sum b/go.sum index cf1d3f0b..d1427bcc 100644 --- a/go.sum +++ b/go.sum @@ -110,8 +110,8 @@ github.com/go-openapi/strfmt v0.22.0 h1:Ew9PnEYc246TwrEspvBdDHS4BVKXy/AOVsfqGDgA github.com/go-openapi/strfmt v0.22.0/go.mod h1:HzJ9kokGIju3/K6ap8jL+OlGAbjpSv27135Yr9OivU4= github.com/go-openapi/swag v0.22.9 h1:XX2DssF+mQKM2DHsbgZK74y/zj4mo9I99+89xUmuZCE= github.com/go-openapi/swag v0.22.9/go.mod h1:3/OXnFfnMAwBD099SwYRk7GD3xOrr1iL7d/XNLXVVwE= -github.com/go-openapi/validate v0.22.6 h1:+NhuwcEYpWdO5Nm4bmvhGLW0rt1Fcc532Mu3wpypXfo= -github.com/go-openapi/validate v0.22.6/go.mod h1:eaddXSqKeTg5XpSmj1dYyFTK/95n/XHwcOY+BMxKMyM= +github.com/go-openapi/validate v0.23.0 h1:2l7PJLzCis4YUGEoW6eoQw3WhyM65WSIcjX6SQnlfDw= +github.com/go-openapi/validate v0.23.0/go.mod h1:EeiAZ5bmpSIOJV1WLfyYF9qp/B1ZgSaEpHTJHtN5cbE= github.com/go-resty/resty/v2 v2.11.0 h1:i7jMfNOJYMp69lq7qozJP+bjgzfAzeOhuGlyDrqxT/8= github.com/go-resty/resty/v2 v2.11.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -149,7 +149,6 @@ github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -233,7 +232,6 @@ github.com/kataras/go-events v0.0.3 h1:o5YK53uURXtrlg7qE/vovxd/yKOJcLuFtPQbf1rYM github.com/kataras/go-events v0.0.3/go.mod h1:bFBgtzwwzrag7kQmGuU1ZaVxhK2qseYPQomXoVEMsj4= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -278,7 +276,6 @@ github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/muhlemmer/gu v0.3.1 h1:7EAqmFrW7n3hETvuAdmFmn4hS8W+z3LgKtrnow+YzNM= github.com/muhlemmer/gu v0.3.1/go.mod h1:YHtHR+gxM+bKEIIs7Hmi9sPT3ZDUvTN/i88wQpZkrdM= github.com/muhlemmer/httpforwarded v0.1.0 h1:x4DLrzXdliq8mprgUMR0olDvHGkou5BJsK/vWUetyzY= @@ -299,8 +296,8 @@ github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+ github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/openziti/channel/v2 v2.0.119 h1:stfSrnDqoTi78LMvQA3+NSivHjQnRrYKrgij5NaOENI= github.com/openziti/channel/v2 v2.0.119/go.mod h1:lSRJwqmbkE34DgXYEmUhVCzwcQcx65vZGE8nuBNK458= -github.com/openziti/edge-api v0.26.10 h1:LEDuJHZsExi0PBVO9iVuIdZWJ7eFo/i4TJhXoSFmfOU= -github.com/openziti/edge-api v0.26.10/go.mod h1:FQLjav9AfqxQYSL0xKPDZ/JWTSZXApkk7jM2/iczGXM= +github.com/openziti/edge-api v0.26.11 h1:qINsfGpPBTnbuDrOq+qcMZuBdlXosqvHX7sQhLA+cM4= +github.com/openziti/edge-api v0.26.11/go.mod h1:30SiUmR+9gOBi9HUZgXLpCO2nNCbNFVx2jwXV2Dh4Og= github.com/openziti/foundation/v2 v2.0.37 h1:7pa4vWrlwllEoLXaK2rx91AffLQJ8k5pvc92oWANavA= github.com/openziti/foundation/v2 v2.0.37/go.mod h1:2NxzCnJbMw35U9RrFcdEaiXdxIMfBHOUNPngpyhvKeY= github.com/openziti/identity v1.0.70 h1:JNwtJHmIS0DcXookm2xuXyh4z92T1O21GQvuO8PmHWs= @@ -374,10 +371,6 @@ github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFA github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= -github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= -github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= -github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= -github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -391,8 +384,8 @@ github.com/zitadel/oidc/v2 v2.12.0/go.mod h1:LrRav74IiThHGapQgCHZOUNtnqJG0tcZKHr go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= -go.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/vk= -go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo= +go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80= +go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 h1:A/5uWzF44DlIgdm/PQFwfMkW0JX+cIcQi/SwLAmZP5M= go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -402,13 +395,13 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= -go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= -go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= -go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= +go.opentelemetry.io/otel v1.23.1 h1:Za4UzOqJYS+MUczKI320AtqZHZb7EqxO00jAHE0jmQY= +go.opentelemetry.io/otel v1.23.1/go.mod h1:Td0134eafDLcTS4y+zQ26GE8u3dEuRBiBCTUIRHaikA= +go.opentelemetry.io/otel/metric v1.23.1 h1:PQJmqJ9u2QaJLBOELl1cxIdPcpbwzbkjfEyelTl2rlo= +go.opentelemetry.io/otel/metric v1.23.1/go.mod h1:mpG2QPlAfnK8yNhNJAxDZruU9Y1/HubbC+KyH8FaCWI= go.opentelemetry.io/otel/sdk v1.17.0 h1:FLN2X66Ke/k5Sg3V623Q7h7nt3cHXaW1FOvKKrW0IpE= -go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= -go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= +go.opentelemetry.io/otel/trace v1.23.1 h1:4LrmmEd8AU2rFvU1zegmvqW7+kWarxtNOPyeL6HmYY8= +go.opentelemetry.io/otel/trace v1.23.1/go.mod h1:4IpnpJFwr1mo/6HL8XIPJaE9y0+u1KcVmuW7dwFSVrI= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= @@ -420,11 +413,10 @@ golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -503,14 +495,13 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -538,8 +529,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -588,7 +579,6 @@ golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -619,9 +609,7 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=