root: fix config loading for outposts (#6640)

* root: fix config loading for outposts

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

* fix error handling

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

* improve check to see if outpost is embedded or not

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

* also fix oauth url fetching

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens L 2023-08-26 19:40:48 +02:00 committed by GitHub
parent 04f46c1d18
commit 9e29789c09
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 47 additions and 13 deletions

10
authentik/lib/config.go Normal file
View File

@ -0,0 +1,10 @@
package lib
import _ "embed"
//go:embed default.yml
var defaultConfig []byte
func DefaultConfig() []byte {
return defaultConfig
}

View File

@ -62,7 +62,8 @@ class OAuthSourceSerializer(SourceSerializer):
well_known_config = session.get(well_known) well_known_config = session.get(well_known)
well_known_config.raise_for_status() well_known_config.raise_for_status()
except RequestException as exc: 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() config = well_known_config.json()
try: try:
attrs["authorization_url"] = config["authorization_endpoint"] attrs["authorization_url"] = config["authorization_endpoint"]
@ -78,7 +79,8 @@ class OAuthSourceSerializer(SourceSerializer):
jwks_config = session.get(jwks_url) jwks_config = session.get(jwks_url)
jwks_config.raise_for_status() jwks_config.raise_for_status()
except RequestException as exc: 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() config = jwks_config.json()
attrs["oidc_jwks"] = config attrs["oidc_jwks"] = config

View File

@ -1,6 +1,7 @@
package config package config
import ( import (
_ "embed"
"errors" "errors"
"fmt" "fmt"
"net/url" "net/url"
@ -11,13 +12,16 @@ import (
env "github.com/Netflix/go-env" env "github.com/Netflix/go-env"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"goauthentik.io/authentik/lib"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
) )
var cfg *Config var cfg *Config
const defaultConfigPath = "./authentik/lib/default.yml"
func getConfigPaths() []string { 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") globConfigPaths, _ := filepath.Glob("/etc/authentik/config.d/*.yml")
configPaths = append(configPaths, globConfigPaths...) configPaths = append(configPaths, globConfigPaths...)
@ -63,20 +67,36 @@ func Get() *Config {
} }
func (c *Config) Setup(paths ...string) { 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 { for _, path := range paths {
err := c.LoadConfig(path) err := c.LoadConfigFromFile(path)
if err != nil { if err != nil {
log.WithError(err).Info("failed to load config, skipping") log.WithError(err).Info("failed to load config, skipping")
} }
} }
err := c.fromEnv() err = c.fromEnv()
if err != nil { if err != nil {
log.WithError(err).Info("failed to load env vars") log.WithError(err).Info("failed to load env vars")
} }
c.configureLogger() 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) raw, err := os.ReadFile(path)
if err != nil { if err != nil {
if errors.Is(err, os.ErrNotExist) { 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) return fmt.Errorf("failed to load config file: %w", err)
} }
err = yaml.Unmarshal(raw, c) err = c.LoadConfig(raw)
if err != nil { if err != nil {
return fmt.Errorf("failed to parse YAML: %w", err) return err
} }
c.walkScheme(c)
log.WithField("path", path).Debug("Loaded config") log.WithField("path", path).Debug("Loaded config")
return nil return nil
} }

View File

@ -55,6 +55,8 @@ type Application struct {
errorTemplates *template.Template errorTemplates *template.Template
authHeaderCache *ttlcache.Cache[string, Claims] authHeaderCache *ttlcache.Cache[string, Claims]
isEmbedded bool
} }
type Server interface { type Server interface {
@ -86,15 +88,15 @@ func NewApplication(p api.ProxyOutpostConfig, c *http.Client, server Server) (*A
CallbackSignature: []string{"true"}, CallbackSignature: []string{"true"},
}.Encode() }.Encode()
managed := false isEmbedded := false
if m := server.API().Outpost.Managed.Get(); m != nil { 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. // Configure an OpenID Connect aware OAuth2 client.
endpoint := GetOIDCEndpoint( endpoint := GetOIDCEndpoint(
p, p,
server.API().Outpost.Config["authentik_host"].(string), server.API().Outpost.Config["authentik_host"].(string),
managed, isEmbedded,
) )
verifier := oidc.NewVerifier(endpoint.Issuer, ks, &oidc.Config{ 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(), ak: server.API(),
authHeaderCache: ttlcache.New(ttlcache.WithDisableTouchOnHit[string, Claims]()), authHeaderCache: ttlcache.New(ttlcache.WithDisableTouchOnHit[string, Claims]()),
srv: server, srv: server,
isEmbedded: isEmbedded,
} }
go a.authHeaderCache.Start() go a.authHeaderCache.Start()
a.sessions = a.getStore(p, externalHost) a.sessions = a.getStore(p, externalHost)

View File

@ -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 // Add one to the validity to ensure we don't have a session with indefinite length
maxAge = int(*t) + 1 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)) 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 { if err != nil {
panic(err) panic(err)