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:
		| @ -65,8 +65,11 @@ type Server interface { | |||||||
| 	CryptoStore() *ak.CryptoStore | 	CryptoStore() *ak.CryptoStore | ||||||
| } | } | ||||||
|  |  | ||||||
| func NewApplication(p api.ProxyOutpostConfig, c *http.Client, server Server) (*Application, error) { | func init() { | ||||||
| 	gob.Register(Claims{}) | 	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) | 	muxLogger := log.WithField("logger", "authentik.outpost.proxyv2.application").WithField("name", p.Name) | ||||||
|  |  | ||||||
| 	externalHost, err := url.Parse(p.ExternalHost) | 	externalHost, err := url.Parse(p.ExternalHost) | ||||||
| @ -137,7 +140,15 @@ func NewApplication(p api.ProxyOutpostConfig, c *http.Client, server Server) (*A | |||||||
| 		isEmbedded:           isEmbedded, | 		isEmbedded:           isEmbedded, | ||||||
| 	} | 	} | ||||||
| 	go a.authHeaderCache.Start() | 	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 { | 	mux.Use(web.NewLoggingHandler(muxLogger, func(l *log.Entry, r *http.Request) *log.Entry { | ||||||
| 		c := a.getClaimsFromSession(r) | 		c := a.getClaimsFromSession(r) | ||||||
| 		if c == nil { | 		if c == nil { | ||||||
| @ -235,9 +246,8 @@ func NewApplication(p api.ProxyOutpostConfig, c *http.Client, server Server) (*A | |||||||
| 				// TODO: maybe create event for this? | 				// TODO: maybe create event for this? | ||||||
| 				a.log.WithError(err).Warning("failed to compile SkipPathRegex") | 				a.log.WithError(err).Warning("failed to compile SkipPathRegex") | ||||||
| 				continue | 				continue | ||||||
| 			} else { |  | ||||||
| 				a.UnauthenticatedRegex = append(a.UnauthenticatedRegex, re) |  | ||||||
| 			} | 			} | ||||||
|  | 			a.UnauthenticatedRegex = append(a.UnauthenticatedRegex, re) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return a, nil | 	return a, nil | ||||||
|  | |||||||
| @ -26,7 +26,7 @@ import ( | |||||||
|  |  | ||||||
| const RedisKeyPrefix = "authentik_proxy_session_" | 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 | 	maxAge := 0 | ||||||
| 	if p.AccessTokenValidity.IsSet() { | 	if p.AccessTokenValidity.IsSet() { | ||||||
| 		t := p.AccessTokenValidity.Get() | 		t := p.AccessTokenValidity.Get() | ||||||
| @ -73,7 +73,7 @@ func (a *Application) getStore(p api.ProxyOutpostConfig, externalHost *url.URL) | |||||||
| 		// New default RedisStore | 		// New default RedisStore | ||||||
| 		rs, err := redisstore.NewRedisStore(context.Background(), client) | 		rs, err := redisstore.NewRedisStore(context.Background(), client) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			a.log.WithError(err).Panic("failed to connect to redis") | 			return nil, err | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		rs.KeyPrefix(RedisKeyPrefix) | 		rs.KeyPrefix(RedisKeyPrefix) | ||||||
| @ -87,7 +87,7 @@ func (a *Application) getStore(p api.ProxyOutpostConfig, externalHost *url.URL) | |||||||
| 		}) | 		}) | ||||||
|  |  | ||||||
| 		a.log.Trace("using redis session backend") | 		a.log.Trace("using redis session backend") | ||||||
| 		return rs | 		return rs, nil | ||||||
| 	} | 	} | ||||||
| 	dir := os.TempDir() | 	dir := os.TempDir() | ||||||
| 	cs := sessions.NewFilesystemStore(dir) | 	cs := sessions.NewFilesystemStore(dir) | ||||||
| @ -106,7 +106,7 @@ func (a *Application) getStore(p api.ProxyOutpostConfig, externalHost *url.URL) | |||||||
| 	cs.Options.MaxAge = maxAge | 	cs.Options.MaxAge = maxAge | ||||||
| 	cs.Options.Path = "/" | 	cs.Options.Path = "/" | ||||||
| 	a.log.WithField("dir", dir).Trace("using filesystem session backend") | 	a.log.WithField("dir", dir).Trace("using filesystem session backend") | ||||||
| 	return cs | 	return cs, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (a *Application) SessionName() string { | func (a *Application) SessionName() string { | ||||||
|  | |||||||
| @ -66,6 +66,7 @@ func newTestApplication() *Application { | |||||||
| 		}, | 		}, | ||||||
| 		http.DefaultClient, | 		http.DefaultClient, | ||||||
| 		ts, | 		ts, | ||||||
|  | 		nil, | ||||||
| 	) | 	) | ||||||
| 	ts.apps = append(ts.apps, a) | 	ts.apps = append(ts.apps, a) | ||||||
| 	return a | 	return a | ||||||
|  | |||||||
| @ -4,6 +4,7 @@ import ( | |||||||
| 	"context" | 	"context" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"net/http" | 	"net/http" | ||||||
|  | 	"net/url" | ||||||
|  |  | ||||||
| 	"github.com/getsentry/sentry-go" | 	"github.com/getsentry/sentry-go" | ||||||
| 	"goauthentik.io/internal/constants" | 	"goauthentik.io/internal/constants" | ||||||
| @ -37,16 +38,21 @@ func (ps *ProxyServer) Refresh() error { | |||||||
| 				), | 				), | ||||||
| 			), | 			), | ||||||
| 		} | 		} | ||||||
| 		a, err := application.NewApplication(provider, hc, ps) | 		externalHost, err := url.Parse(provider.ExternalHost) | ||||||
| 		existing, ok := ps.apps[a.Host] | 		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 { | 		if ok { | ||||||
| 			existing.Stop() | 			existing.Stop() | ||||||
| 		} | 		} | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			ps.log.WithError(err).Warning("failed to setup application") | 			ps.log.WithError(err).Warning("failed to setup application") | ||||||
| 		} else { | 			continue | ||||||
| 			apps[a.Host] = a |  | ||||||
| 		} | 		} | ||||||
|  | 		apps[externalHost.Host] = a | ||||||
| 	} | 	} | ||||||
| 	ps.apps = apps | 	ps.apps = apps | ||||||
| 	ps.log.Debug("Swapped maps") | 	ps.log.Debug("Swapped maps") | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 Jens L.
					Jens L.