providers/proxy: fix panic, keep session storages open (#11439)

* fix panic when redis connection fails

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* re-use session when refreshing apps

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens L.
2024-09-19 23:05:58 +02:00
committed by GitHub
parent 20f555ebb6
commit ad3820c11c
4 changed files with 29 additions and 12 deletions

View File

@ -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

View File

@ -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 {

View File

@ -66,6 +66,7 @@ func newTestApplication() *Application {
},
http.DefaultClient,
ts,
nil,
)
ts.apps = append(ts.apps, a)
return a

View File

@ -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")