Refactor caches
Signed-off-by: Christian Richter <crichter@owncloud.com>
This commit is contained in:
@@ -43,13 +43,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type StaticRouteHandler struct {
|
type StaticRouteHandler struct {
|
||||||
prefix string
|
prefix string
|
||||||
proxy http.Handler
|
proxy http.Handler
|
||||||
sidCache microstore.Store
|
userInfoCache microstore.Store
|
||||||
accessTokenCache microstore.Store
|
sessionLookupCache microstore.Store
|
||||||
logger log.Logger
|
logger log.Logger
|
||||||
config config.Config
|
config config.Config
|
||||||
oidcClient oidc.OIDCProvider
|
oidcClient oidc.OIDCProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
// Server is the entrypoint for the server command.
|
// Server is the entrypoint for the server command.
|
||||||
@@ -62,7 +62,7 @@ func Server(cfg *config.Config) *cli.Command {
|
|||||||
return configlog.ReturnFatal(parser.ParseConfig(cfg))
|
return configlog.ReturnFatal(parser.ParseConfig(cfg))
|
||||||
},
|
},
|
||||||
Action: func(c *cli.Context) error {
|
Action: func(c *cli.Context) error {
|
||||||
cache := store.Create(
|
userInfoCache := store.Create(
|
||||||
store.Store(cfg.OIDC.UserinfoCache.Store),
|
store.Store(cfg.OIDC.UserinfoCache.Store),
|
||||||
store.TTL(cfg.OIDC.UserinfoCache.TTL),
|
store.TTL(cfg.OIDC.UserinfoCache.TTL),
|
||||||
store.Size(cfg.OIDC.UserinfoCache.Size),
|
store.Size(cfg.OIDC.UserinfoCache.Size),
|
||||||
@@ -71,6 +71,15 @@ func Server(cfg *config.Config) *cli.Command {
|
|||||||
microstore.Table(cfg.OIDC.UserinfoCache.Table),
|
microstore.Table(cfg.OIDC.UserinfoCache.Table),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
sessionLookupCache := store.Create(
|
||||||
|
store.Store(cfg.OIDC.SessionLookupCache.Store),
|
||||||
|
store.TTL(cfg.OIDC.SessionLookupCache.TTL),
|
||||||
|
store.Size(cfg.OIDC.SessionLookupCache.Size),
|
||||||
|
microstore.Nodes(cfg.OIDC.SessionLookupCache.Nodes...),
|
||||||
|
microstore.Database(cfg.OIDC.SessionLookupCache.Database),
|
||||||
|
microstore.Table(cfg.OIDC.SessionLookupCache.Table),
|
||||||
|
)
|
||||||
|
|
||||||
logger := logging.Configure(cfg.Service.Name, cfg.Log)
|
logger := logging.Configure(cfg.Service.Name, cfg.Log)
|
||||||
err := tracing.Configure(cfg)
|
err := tracing.Configure(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -122,20 +131,20 @@ func Server(cfg *config.Config) *cli.Command {
|
|||||||
)
|
)
|
||||||
|
|
||||||
lh := StaticRouteHandler{
|
lh := StaticRouteHandler{
|
||||||
prefix: cfg.HTTP.Root,
|
prefix: cfg.HTTP.Root,
|
||||||
sidCache: cache, // FIXME use correct cache
|
userInfoCache: userInfoCache,
|
||||||
accessTokenCache: cache, // FIXME use correct cache
|
sessionLookupCache: sessionLookupCache,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
config: *cfg,
|
config: *cfg,
|
||||||
oidcClient: oidcClient,
|
oidcClient: oidcClient,
|
||||||
proxy: rp,
|
proxy: rp,
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to initialize reverse proxy: %w", err)
|
return fmt.Errorf("failed to initialize reverse proxy: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
middlewares := loadMiddlewares(ctx, logger, cfg, cache)
|
middlewares := loadMiddlewares(ctx, logger, cfg, userInfoCache, sessionLookupCache)
|
||||||
server, err := proxyHTTP.Server(
|
server, err := proxyHTTP.Server(
|
||||||
proxyHTTP.Handler(lh.handler()),
|
proxyHTTP.Handler(lh.handler()),
|
||||||
proxyHTTP.Logger(logger),
|
proxyHTTP.Logger(logger),
|
||||||
@@ -222,14 +231,14 @@ func (h *StaticRouteHandler) backchannelLogout(w http.ResponseWriter, r *http.Re
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
records, err := h.sidCache.Read(logoutToken.SessionId)
|
records, err := h.userInfoCache.Read(logoutToken.SessionId)
|
||||||
if errors.Is(err, microstore.ErrNotFound) || len(records) == 0 {
|
if errors.Is(err, microstore.ErrNotFound) || len(records) == 0 {
|
||||||
render.Status(r, http.StatusOK)
|
render.Status(r, http.StatusOK)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, record := range records {
|
for _, record := range records {
|
||||||
err = h.accessTokenCache.Delete(string(record.Value))
|
err = h.sessionLookupCache.Delete(string(record.Value))
|
||||||
if errors.Is(err, microstore.ErrNotFound) {
|
if errors.Is(err, microstore.ErrNotFound) {
|
||||||
render.Status(r, http.StatusOK)
|
render.Status(r, http.StatusOK)
|
||||||
return
|
return
|
||||||
@@ -239,7 +248,7 @@ func (h *StaticRouteHandler) backchannelLogout(w http.ResponseWriter, r *http.Re
|
|||||||
render.Status(r, http.StatusOK)
|
render.Status(r, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadMiddlewares(ctx context.Context, logger log.Logger, cfg *config.Config, cache microstore.Store) alice.Chain {
|
func loadMiddlewares(ctx context.Context, logger log.Logger, cfg *config.Config, userInfoCache microstore.Store, sessionLookupCache microstore.Store) alice.Chain {
|
||||||
rolesClient := settingssvc.NewRoleService("com.owncloud.api.settings", grpc.DefaultClient())
|
rolesClient := settingssvc.NewRoleService("com.owncloud.api.settings", grpc.DefaultClient())
|
||||||
revaClient, err := pool.GetGatewayServiceClient(cfg.Reva.Address, cfg.Reva.GetRevaOptions()...)
|
revaClient, err := pool.GetGatewayServiceClient(cfg.Reva.Address, cfg.Reva.GetRevaOptions()...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -316,7 +325,8 @@ func loadMiddlewares(ctx context.Context, logger log.Logger, cfg *config.Config,
|
|||||||
|
|
||||||
authenticators = append(authenticators, middleware.NewOIDCAuthenticator(
|
authenticators = append(authenticators, middleware.NewOIDCAuthenticator(
|
||||||
middleware.Logger(logger),
|
middleware.Logger(logger),
|
||||||
middleware.Cache(cache),
|
middleware.UserInfoCache(userInfoCache),
|
||||||
|
middleware.SessionLookupCache(sessionLookupCache),
|
||||||
middleware.DefaultAccessTokenTTL(cfg.OIDC.UserinfoCache.TTL),
|
middleware.DefaultAccessTokenTTL(cfg.OIDC.UserinfoCache.TTL),
|
||||||
middleware.HTTPClient(oidcHTTPClient),
|
middleware.HTTPClient(oidcHTTPClient),
|
||||||
middleware.OIDCIss(cfg.OIDC.Issuer),
|
middleware.OIDCIss(cfg.OIDC.Issuer),
|
||||||
|
|||||||
@@ -106,6 +106,7 @@ type OIDC struct {
|
|||||||
Insecure bool `yaml:"insecure" env:"OCIS_INSECURE;PROXY_OIDC_INSECURE" desc:"Disable TLS certificate validation for connections to the IDP. Note that this is not recommended for production environments."`
|
Insecure bool `yaml:"insecure" env:"OCIS_INSECURE;PROXY_OIDC_INSECURE" desc:"Disable TLS certificate validation for connections to the IDP. Note that this is not recommended for production environments."`
|
||||||
AccessTokenVerifyMethod string `yaml:"access_token_verify_method" env:"PROXY_OIDC_ACCESS_TOKEN_VERIFY_METHOD" desc:"Sets how OIDC access tokens should be verified. Possible values are 'none' and 'jwt'. When using 'none', no special validation apart from using it for accessing the IPD's userinfo endpoint will be done. When using 'jwt', it tries to parse the access token as a jwt token and verifies the signature using the keys published on the IDP's 'jwks_uri'."`
|
AccessTokenVerifyMethod string `yaml:"access_token_verify_method" env:"PROXY_OIDC_ACCESS_TOKEN_VERIFY_METHOD" desc:"Sets how OIDC access tokens should be verified. Possible values are 'none' and 'jwt'. When using 'none', no special validation apart from using it for accessing the IPD's userinfo endpoint will be done. When using 'jwt', it tries to parse the access token as a jwt token and verifies the signature using the keys published on the IDP's 'jwks_uri'."`
|
||||||
UserinfoCache *Cache `yaml:"user_info_cache"`
|
UserinfoCache *Cache `yaml:"user_info_cache"`
|
||||||
|
SessionLookupCache *Cache `yaml:"session_lookup_cache"`
|
||||||
JWKS JWKS `yaml:"jwks"`
|
JWKS JWKS `yaml:"jwks"`
|
||||||
RewriteWellKnown bool `yaml:"rewrite_well_known" env:"PROXY_OIDC_REWRITE_WELLKNOWN" desc:"Enables rewriting the /.well-known/openid-configuration to the configured OIDC issuer. Needed by the Desktop Client, Android Client and iOS Client to discover the OIDC provider."`
|
RewriteWellKnown bool `yaml:"rewrite_well_known" env:"PROXY_OIDC_REWRITE_WELLKNOWN" desc:"Enables rewriting the /.well-known/openid-configuration to the configured OIDC issuer. Needed by the Desktop Client, Android Client and iOS Client to discover the OIDC provider."`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ func NewOIDCAuthenticator(opts ...Option) *OIDCAuthenticator {
|
|||||||
|
|
||||||
return &OIDCAuthenticator{
|
return &OIDCAuthenticator{
|
||||||
Logger: options.Logger,
|
Logger: options.Logger,
|
||||||
userInfoCache: options.Cache,
|
userInfoCache: options.UserInfoCache,
|
||||||
sessionLookupCache: options.Cache,
|
sessionLookupCache: options.SessionLookupCache,
|
||||||
DefaultTokenCacheTTL: options.DefaultAccessTokenTTL,
|
DefaultTokenCacheTTL: options.DefaultAccessTokenTTL,
|
||||||
HTTPClient: options.HTTPClient,
|
HTTPClient: options.HTTPClient,
|
||||||
OIDCIss: options.OIDCIss,
|
OIDCIss: options.OIDCIss,
|
||||||
|
|||||||
@@ -54,8 +54,10 @@ type Options struct {
|
|||||||
EnableBasicAuth bool
|
EnableBasicAuth bool
|
||||||
// DefaultAccessTokenTTL is used to calculate the expiration when an access token has no expiration set
|
// DefaultAccessTokenTTL is used to calculate the expiration when an access token has no expiration set
|
||||||
DefaultAccessTokenTTL time.Duration
|
DefaultAccessTokenTTL time.Duration
|
||||||
// Cache sets the access token cache store
|
// UserInfoCache sets the access token cache store
|
||||||
Cache store.Store
|
UserInfoCache store.Store
|
||||||
|
// SessionLookupCache maps the session to a hashed jwt token
|
||||||
|
SessionLookupCache store.Store
|
||||||
// CredentialsByUserAgent sets the auth challenges on a per user-agent basis
|
// CredentialsByUserAgent sets the auth challenges on a per user-agent basis
|
||||||
CredentialsByUserAgent map[string]string
|
CredentialsByUserAgent map[string]string
|
||||||
// AccessTokenVerifyMethod configures how access_tokens should be verified but the oidc_auth middleware.
|
// AccessTokenVerifyMethod configures how access_tokens should be verified but the oidc_auth middleware.
|
||||||
@@ -191,10 +193,17 @@ func DefaultAccessTokenTTL(ttl time.Duration) Option {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache provides a function to set the Cache
|
// UserInfoCache provides a function to set the UserInfoCache
|
||||||
func Cache(val store.Store) Option {
|
func UserInfoCache(val store.Store) Option {
|
||||||
return func(o *Options) {
|
return func(o *Options) {
|
||||||
o.Cache = val
|
o.UserInfoCache = val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SessionLookupCache provides a function to set the SessionLookupCache
|
||||||
|
func SessionLookupCache(val store.Store) Option {
|
||||||
|
return func(o *Options) {
|
||||||
|
o.SessionLookupCache = val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user