From 9e29789c09be066817b3c57043480c2018ffa4c9 Mon Sep 17 00:00:00 2001 From: Jens L Date: Sat, 26 Aug 2023 19:40:48 +0200 Subject: [PATCH] root: fix config loading for outposts (#6640) * root: fix config loading for outposts Signed-off-by: Jens Langhammer * fix error handling Signed-off-by: Jens Langhammer * improve check to see if outpost is embedded or not Signed-off-by: Jens Langhammer * also fix oauth url fetching Signed-off-by: Jens Langhammer --------- Signed-off-by: Jens Langhammer --- authentik/lib/config.go | 10 ++++++ authentik/sources/oauth/api/source.py | 6 ++-- internal/config/config.go | 33 +++++++++++++++---- .../proxyv2/application/application.go | 9 +++-- .../outpost/proxyv2/application/session.go | 2 +- 5 files changed, 47 insertions(+), 13 deletions(-) create mode 100644 authentik/lib/config.go diff --git a/authentik/lib/config.go b/authentik/lib/config.go new file mode 100644 index 000000000..f595f2423 --- /dev/null +++ b/authentik/lib/config.go @@ -0,0 +1,10 @@ +package lib + +import _ "embed" + +//go:embed default.yml +var defaultConfig []byte + +func DefaultConfig() []byte { + return defaultConfig +} diff --git a/authentik/sources/oauth/api/source.py b/authentik/sources/oauth/api/source.py index 6c9399f95..4b1785a54 100644 --- a/authentik/sources/oauth/api/source.py +++ b/authentik/sources/oauth/api/source.py @@ -62,7 +62,8 @@ class OAuthSourceSerializer(SourceSerializer): well_known_config = session.get(well_known) well_known_config.raise_for_status() except RequestException as exc: - raise ValidationError(exc.response.text) + text = exc.response.text if exc.response else str(exc) + raise ValidationError(text) config = well_known_config.json() try: attrs["authorization_url"] = config["authorization_endpoint"] @@ -78,7 +79,8 @@ class OAuthSourceSerializer(SourceSerializer): jwks_config = session.get(jwks_url) jwks_config.raise_for_status() except RequestException as exc: - raise ValidationError(exc.response.text) + text = exc.response.text if exc.response else str(exc) + raise ValidationError(text) config = jwks_config.json() attrs["oidc_jwks"] = config diff --git a/internal/config/config.go b/internal/config/config.go index 4a1013e4a..ac37d277e 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -1,6 +1,7 @@ package config import ( + _ "embed" "errors" "fmt" "net/url" @@ -11,13 +12,16 @@ import ( env "github.com/Netflix/go-env" log "github.com/sirupsen/logrus" + "goauthentik.io/authentik/lib" "gopkg.in/yaml.v2" ) var cfg *Config +const defaultConfigPath = "./authentik/lib/default.yml" + func getConfigPaths() []string { - configPaths := []string{"./authentik/lib/default.yml", "/etc/authentik/config.yml", ""} + configPaths := []string{defaultConfigPath, "/etc/authentik/config.yml", ""} globConfigPaths, _ := filepath.Glob("/etc/authentik/config.d/*.yml") configPaths = append(configPaths, globConfigPaths...) @@ -63,20 +67,36 @@ func Get() *Config { } func (c *Config) Setup(paths ...string) { + // initially try to load the default config which is compiled in + err := c.LoadConfig(lib.DefaultConfig()) + // this should never fail + if err != nil { + panic(fmt.Errorf("failed to load inbuilt config: %v", err)) + } + log.WithField("path", "inbuilt-default").Debug("Loaded config") for _, path := range paths { - err := c.LoadConfig(path) + err := c.LoadConfigFromFile(path) if err != nil { log.WithError(err).Info("failed to load config, skipping") } } - err := c.fromEnv() + err = c.fromEnv() if err != nil { log.WithError(err).Info("failed to load env vars") } c.configureLogger() } -func (c *Config) LoadConfig(path string) error { +func (c *Config) LoadConfig(raw []byte) error { + err := yaml.Unmarshal(raw, c) + if err != nil { + return fmt.Errorf("failed to parse YAML: %w", err) + } + c.walkScheme(c) + return nil +} + +func (c *Config) LoadConfigFromFile(path string) error { raw, err := os.ReadFile(path) if err != nil { if errors.Is(err, os.ErrNotExist) { @@ -84,11 +104,10 @@ func (c *Config) LoadConfig(path string) error { } return fmt.Errorf("failed to load config file: %w", err) } - err = yaml.Unmarshal(raw, c) + err = c.LoadConfig(raw) if err != nil { - return fmt.Errorf("failed to parse YAML: %w", err) + return err } - c.walkScheme(c) log.WithField("path", path).Debug("Loaded config") return nil } diff --git a/internal/outpost/proxyv2/application/application.go b/internal/outpost/proxyv2/application/application.go index 324909562..3c8af5af3 100644 --- a/internal/outpost/proxyv2/application/application.go +++ b/internal/outpost/proxyv2/application/application.go @@ -55,6 +55,8 @@ type Application struct { errorTemplates *template.Template authHeaderCache *ttlcache.Cache[string, Claims] + + isEmbedded bool } type Server interface { @@ -86,15 +88,15 @@ func NewApplication(p api.ProxyOutpostConfig, c *http.Client, server Server) (*A CallbackSignature: []string{"true"}, }.Encode() - managed := false + isEmbedded := false if m := server.API().Outpost.Managed.Get(); m != nil { - managed = *m == "goauthentik.io/outposts/embedded" + isEmbedded = *m == "goauthentik.io/outposts/embedded" } // Configure an OpenID Connect aware OAuth2 client. endpoint := GetOIDCEndpoint( p, server.API().Outpost.Config["authentik_host"].(string), - managed, + isEmbedded, ) verifier := oidc.NewVerifier(endpoint.Issuer, ks, &oidc.Config{ @@ -132,6 +134,7 @@ func NewApplication(p api.ProxyOutpostConfig, c *http.Client, server Server) (*A ak: server.API(), authHeaderCache: ttlcache.New(ttlcache.WithDisableTouchOnHit[string, Claims]()), srv: server, + isEmbedded: isEmbedded, } go a.authHeaderCache.Start() a.sessions = a.getStore(p, externalHost) diff --git a/internal/outpost/proxyv2/application/session.go b/internal/outpost/proxyv2/application/session.go index a6c36ae73..bf426c10e 100644 --- a/internal/outpost/proxyv2/application/session.go +++ b/internal/outpost/proxyv2/application/session.go @@ -29,7 +29,7 @@ func (a *Application) getStore(p api.ProxyOutpostConfig, externalHost *url.URL) // Add one to the validity to ensure we don't have a session with indefinite length maxAge = int(*t) + 1 } - if config.Get().Redis.Host != "" { + if a.isEmbedded { rs, err := redistore.NewRediStoreWithDB(10, "tcp", fmt.Sprintf("%s:%d", config.Get().Redis.Host, config.Get().Redis.Port), config.Get().Redis.Password, strconv.Itoa(config.Get().Redis.DB)) if err != nil { panic(err)