From ad3820c11cf0adb34db6ceae94c7d2f8da713516 Mon Sep 17 00:00:00 2001 From: "Jens L." Date: Thu, 19 Sep 2024 23:05:58 +0200 Subject: [PATCH] providers/proxy: fix panic, keep session storages open (#11439) * fix panic when redis connection fails Signed-off-by: Jens Langhammer * re-use session when refreshing apps Signed-off-by: Jens Langhammer --------- Signed-off-by: Jens Langhammer --- .../outpost/proxyv2/application/application.go | 18 ++++++++++++++---- .../outpost/proxyv2/application/session.go | 8 ++++---- internal/outpost/proxyv2/application/test.go | 1 + internal/outpost/proxyv2/refresh.go | 14 ++++++++++---- 4 files changed, 29 insertions(+), 12 deletions(-) diff --git a/internal/outpost/proxyv2/application/application.go b/internal/outpost/proxyv2/application/application.go index baeea30cf0d0..4196f052f55e 100644 --- a/internal/outpost/proxyv2/application/application.go +++ b/internal/outpost/proxyv2/application/application.go @@ -65,8 +65,11 @@ type Server interface { CryptoStore() *ak.CryptoStore } -func NewApplication(p api.ProxyOutpostConfig, c *http.Client, server Server) (*Application, error) { +func init() { gob.Register(Claims{}) +} + +func NewApplication(p api.ProxyOutpostConfig, c *http.Client, server Server, oldApp *Application) (*Application, error) { muxLogger := log.WithField("logger", "authentik.outpost.proxyv2.application").WithField("name", p.Name) externalHost, err := url.Parse(p.ExternalHost) @@ -137,7 +140,15 @@ func NewApplication(p api.ProxyOutpostConfig, c *http.Client, server Server) (*A isEmbedded: isEmbedded, } go a.authHeaderCache.Start() - a.sessions = a.getStore(p, externalHost) + if oldApp != nil && oldApp.sessions != nil { + a.sessions = oldApp.sessions + } else { + sess, err := a.getStore(p, externalHost) + if err != nil { + return nil, err + } + a.sessions = sess + } mux.Use(web.NewLoggingHandler(muxLogger, func(l *log.Entry, r *http.Request) *log.Entry { c := a.getClaimsFromSession(r) if c == nil { @@ -235,9 +246,8 @@ func NewApplication(p api.ProxyOutpostConfig, c *http.Client, server Server) (*A // TODO: maybe create event for this? a.log.WithError(err).Warning("failed to compile SkipPathRegex") continue - } else { - a.UnauthenticatedRegex = append(a.UnauthenticatedRegex, re) } + a.UnauthenticatedRegex = append(a.UnauthenticatedRegex, re) } } return a, nil diff --git a/internal/outpost/proxyv2/application/session.go b/internal/outpost/proxyv2/application/session.go index a332a7d505bb..9ce892954ce7 100644 --- a/internal/outpost/proxyv2/application/session.go +++ b/internal/outpost/proxyv2/application/session.go @@ -26,7 +26,7 @@ import ( const RedisKeyPrefix = "authentik_proxy_session_" -func (a *Application) getStore(p api.ProxyOutpostConfig, externalHost *url.URL) sessions.Store { +func (a *Application) getStore(p api.ProxyOutpostConfig, externalHost *url.URL) (sessions.Store, error) { maxAge := 0 if p.AccessTokenValidity.IsSet() { t := p.AccessTokenValidity.Get() @@ -73,7 +73,7 @@ func (a *Application) getStore(p api.ProxyOutpostConfig, externalHost *url.URL) // New default RedisStore rs, err := redisstore.NewRedisStore(context.Background(), client) if err != nil { - a.log.WithError(err).Panic("failed to connect to redis") + return nil, err } rs.KeyPrefix(RedisKeyPrefix) @@ -87,7 +87,7 @@ func (a *Application) getStore(p api.ProxyOutpostConfig, externalHost *url.URL) }) a.log.Trace("using redis session backend") - return rs + return rs, nil } dir := os.TempDir() cs := sessions.NewFilesystemStore(dir) @@ -106,7 +106,7 @@ func (a *Application) getStore(p api.ProxyOutpostConfig, externalHost *url.URL) cs.Options.MaxAge = maxAge cs.Options.Path = "/" a.log.WithField("dir", dir).Trace("using filesystem session backend") - return cs + return cs, nil } func (a *Application) SessionName() string { diff --git a/internal/outpost/proxyv2/application/test.go b/internal/outpost/proxyv2/application/test.go index f7970776c415..468a6441d00c 100644 --- a/internal/outpost/proxyv2/application/test.go +++ b/internal/outpost/proxyv2/application/test.go @@ -66,6 +66,7 @@ func newTestApplication() *Application { }, http.DefaultClient, ts, + nil, ) ts.apps = append(ts.apps, a) return a diff --git a/internal/outpost/proxyv2/refresh.go b/internal/outpost/proxyv2/refresh.go index b1d1a71164d1..cddd4363c14a 100644 --- a/internal/outpost/proxyv2/refresh.go +++ b/internal/outpost/proxyv2/refresh.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "net/http" + "net/url" "github.com/getsentry/sentry-go" "goauthentik.io/internal/constants" @@ -37,16 +38,21 @@ func (ps *ProxyServer) Refresh() error { ), ), } - a, err := application.NewApplication(provider, hc, ps) - existing, ok := ps.apps[a.Host] + externalHost, err := url.Parse(provider.ExternalHost) + if err != nil { + ps.log.WithError(err).Warning("failed to parse URL, skipping provider") + continue + } + existing, ok := ps.apps[externalHost.Host] + a, err := application.NewApplication(provider, hc, ps, existing) if ok { existing.Stop() } if err != nil { ps.log.WithError(err).Warning("failed to setup application") - } else { - apps[a.Host] = a + continue } + apps[externalHost.Host] = a } ps.apps = apps ps.log.Debug("Swapped maps")