From a410d401665d0f3cc277c99a3736eb433df93345 Mon Sep 17 00:00:00 2001 From: Benedikt Kulmann Date: Wed, 18 Nov 2020 11:14:29 +0100 Subject: [PATCH] Make userinfo cache configurable --- proxy/pkg/command/server.go | 4 ++-- proxy/pkg/config/config.go | 11 +++++++-- proxy/pkg/flagset/flagset.go | 14 +++++++++++ proxy/pkg/middleware/oidc_auth.go | 40 ++++++++++++++++++------------- proxy/pkg/middleware/options.go | 12 +++++----- 5 files changed, 55 insertions(+), 26 deletions(-) diff --git a/proxy/pkg/command/server.go b/proxy/pkg/command/server.go index 092c85e3f7..dad51e2497 100644 --- a/proxy/pkg/command/server.go +++ b/proxy/pkg/command/server.go @@ -281,8 +281,8 @@ func loadMiddlewares(ctx context.Context, l log.Logger, cfg *config.Config) alic }), middleware.HTTPClient(oidcHTTPClient), middleware.OIDCIss(cfg.OIDC.Issuer), - middleware.TokenCacheSize(1024), - middleware.TokenCacheTTL(time.Second*10), + middleware.TokenCacheSize(cfg.OIDC.UserinfoCache.Size), + middleware.TokenCacheTTL(time.Second*time.Duration(cfg.OIDC.UserinfoCache.TTL)), ), middleware.BasicAuth( middleware.Logger(l), diff --git a/proxy/pkg/config/config.go b/proxy/pkg/config/config.go index 681d0abe03..b1f33510f7 100644 --- a/proxy/pkg/config/config.go +++ b/proxy/pkg/config/config.go @@ -83,6 +83,12 @@ type Reva struct { Address string } +// Cache is a TTL cache configuration. +type Cache struct { + Size int + TTL int +} + // Config combines all available configuration parts. type Config struct { File string @@ -105,8 +111,9 @@ type Config struct { // OIDC is the config for the OpenID-Connect middleware. If set the proxy will try to authenticate every request // with the configured oidc-provider type OIDC struct { - Issuer string - Insecure bool + Issuer string + Insecure bool + UserinfoCache Cache } // PolicySelector is the toplevel-configuration for different selectors diff --git a/proxy/pkg/flagset/flagset.go b/proxy/pkg/flagset/flagset.go index 078d9cec8a..9aff3f3645 100644 --- a/proxy/pkg/flagset/flagset.go +++ b/proxy/pkg/flagset/flagset.go @@ -202,6 +202,20 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag { EnvVars: []string{"PROXY_OIDC_INSECURE"}, Destination: &cfg.OIDC.Insecure, }, + &cli.IntFlag{ + Name: "oidc-userinfo-cache-tll", + Value: 10, + Usage: "Fallback TTL in seconds for caching userinfo, when no token lifetime can be identified", + EnvVars: []string{"PROXY_OIDC_USERINFO_CACHE_TTL"}, + Destination: &cfg.OIDC.UserinfoCache.TTL, + }, + &cli.IntFlag{ + Name: "oidc-userinfo-cache-size", + Value: 1024, + Usage: "Max entries for caching userinfo", + EnvVars: []string{"PROXY_OIDC_USERINFO_CACHE_SIZE"}, + Destination: &cfg.OIDC.UserinfoCache.Size, + }, &cli.BoolFlag{ Name: "autoprovision-accounts", diff --git a/proxy/pkg/middleware/oidc_auth.go b/proxy/pkg/middleware/oidc_auth.go index 1396d7e921..ec9aad884e 100644 --- a/proxy/pkg/middleware/oidc_auth.go +++ b/proxy/pkg/middleware/oidc_auth.go @@ -21,8 +21,8 @@ type OIDCProvider interface { func OIDCAuth(optionSetters ...Option) func(next http.Handler) http.Handler { options := newOptions(optionSetters...) tokenCache := cache.NewCache( - cache.Size(options.TokenCacheSize), - cache.TTL(options.TokenCacheTTL), + cache.Size(options.UserinfoCacheSize), + cache.TTL(options.UserinfoCacheTTL), ) return func(next http.Handler) http.Handler { @@ -54,20 +54,9 @@ func (m oidcAuth) ServeHTTP(w http.ResponseWriter, req *http.Request) { return } - if m.provider == nil { - // Lazily initialize a provider - - // provider needs to be cached as when it is created - // it will fetch the keys from the issuer using the .well-known - // endpoint - provider, err := m.providerFunc() - if err != nil { - m.logger.Error().Err(err).Msg("could not initialize oidcAuth provider") - w.WriteHeader(http.StatusInternalServerError) - return - } - - m.provider = provider + if m.getProvider() == nil { + w.WriteHeader(http.StatusInternalServerError) + return } token := strings.TrimPrefix(req.Header.Get("Authorization"), "Bearer ") @@ -136,6 +125,7 @@ func (m oidcAuth) shouldServe(req *http.Request) bool { } // todo: looks dirty, check later + // TODO: make a PR to coreos/go-oidc for exposing userinfo endpoint on provider, see https://github.com/coreos/go-oidc/issues/248 for _, ignoringPath := range []string{"/konnect/v1/userinfo"} { if req.URL.Path == ignoringPath { return false @@ -144,3 +134,21 @@ func (m oidcAuth) shouldServe(req *http.Request) bool { return strings.HasPrefix(header, "Bearer ") } + +func (m oidcAuth) getProvider() OIDCProvider { + if m.provider == nil { + // Lazily initialize a provider + + // provider needs to be cached as when it is created + // it will fetch the keys from the issuer using the .well-known + // endpoint + provider, err := m.providerFunc() + if err != nil { + m.logger.Error().Err(err).Msg("could not initialize oidcAuth provider") + return nil + } + + m.provider = provider + } + return m.provider +} diff --git a/proxy/pkg/middleware/options.go b/proxy/pkg/middleware/options.go index ca480d78e0..9d5d0c1ca9 100644 --- a/proxy/pkg/middleware/options.go +++ b/proxy/pkg/middleware/options.go @@ -42,10 +42,10 @@ type Options struct { AutoprovisionAccounts bool // EnableBasicAuth to allow basic auth EnableBasicAuth bool - // TokenCacheSize defines the max number of entries in the token cache, intended for the oidc_auth middleware - TokenCacheSize int - // TokenCacheTTL sets the max cache duration for the token cache, intended for the oidc_auth middleware - TokenCacheTTL time.Duration + // UserinfoCacheSize defines the max number of entries in the userinfo cache, intended for the oidc_auth middleware + UserinfoCacheSize int + // UserinfoCacheTTL sets the max cache duration for the userinfo cache, intended for the oidc_auth middleware + UserinfoCacheTTL time.Duration } // newOptions initializes the available default options. @@ -146,13 +146,13 @@ func EnableBasicAuth(enableBasicAuth bool) Option { // TokenCacheSize provides a function to set the TokenCacheSize func TokenCacheSize(size int) Option { return func(o *Options) { - o.TokenCacheSize = size + o.UserinfoCacheSize = size } } // TokenCacheTTL provides a function to set the TokenCacheTTL func TokenCacheTTL(ttl time.Duration) Option { return func(o *Options) { - o.TokenCacheTTL = ttl + o.UserinfoCacheTTL = ttl } }