mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Auth: removes temporary cache of user session token (#62730)
Signed-off-by: bergquist <carl.bergquist@gmail.com>
This commit is contained in:
parent
9311085e5a
commit
64c2032c2b
@ -91,7 +91,6 @@ Alpha features might be changed or removed without prior notice.
|
|||||||
| `datasourceOnboarding` | Enable data source onboarding page |
|
| `datasourceOnboarding` | Enable data source onboarding page |
|
||||||
| `secureSocksDatasourceProxy` | Enable secure socks tunneling for supported core datasources |
|
| `secureSocksDatasourceProxy` | Enable secure socks tunneling for supported core datasources |
|
||||||
| `authnService` | Use new auth service to perform authentication |
|
| `authnService` | Use new auth service to perform authentication |
|
||||||
| `sessionRemoteCache` | Enable using remote cache for user sessions |
|
|
||||||
| `alertingBacktesting` | Rule backtesting API for alerting |
|
| `alertingBacktesting` | Rule backtesting API for alerting |
|
||||||
| `editPanelCSVDragAndDrop` | Enables drag and drop for CSV and Excel files |
|
| `editPanelCSVDragAndDrop` | Enables drag and drop for CSV and Excel files |
|
||||||
| `logsContextDatasourceUi` | Allow datasource to provide custom UI for context view |
|
| `logsContextDatasourceUi` | Allow datasource to provide custom UI for context view |
|
||||||
|
@ -80,7 +80,6 @@ export interface FeatureToggles {
|
|||||||
datasourceOnboarding?: boolean;
|
datasourceOnboarding?: boolean;
|
||||||
secureSocksDatasourceProxy?: boolean;
|
secureSocksDatasourceProxy?: boolean;
|
||||||
authnService?: boolean;
|
authnService?: boolean;
|
||||||
sessionRemoteCache?: boolean;
|
|
||||||
disablePrometheusExemplarSampling?: boolean;
|
disablePrometheusExemplarSampling?: boolean;
|
||||||
alertingBacktesting?: boolean;
|
alertingBacktesting?: boolean;
|
||||||
editPanelCSVDragAndDrop?: boolean;
|
editPanelCSVDragAndDrop?: boolean;
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
@ -14,27 +13,20 @@ import (
|
|||||||
|
|
||||||
"github.com/grafana/grafana/pkg/infra/db"
|
"github.com/grafana/grafana/pkg/infra/db"
|
||||||
"github.com/grafana/grafana/pkg/infra/log"
|
"github.com/grafana/grafana/pkg/infra/log"
|
||||||
"github.com/grafana/grafana/pkg/infra/remotecache"
|
|
||||||
"github.com/grafana/grafana/pkg/infra/serverlock"
|
"github.com/grafana/grafana/pkg/infra/serverlock"
|
||||||
"github.com/grafana/grafana/pkg/services/auth"
|
"github.com/grafana/grafana/pkg/services/auth"
|
||||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
|
||||||
"github.com/grafana/grafana/pkg/services/quota"
|
"github.com/grafana/grafana/pkg/services/quota"
|
||||||
"github.com/grafana/grafana/pkg/services/user"
|
"github.com/grafana/grafana/pkg/services/user"
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
"github.com/grafana/grafana/pkg/util"
|
"github.com/grafana/grafana/pkg/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const urgentRotateTime = 1 * time.Minute
|
||||||
ttl = 15 * time.Second
|
|
||||||
urgentRotateTime = 1 * time.Minute
|
|
||||||
)
|
|
||||||
|
|
||||||
var getTime = time.Now
|
var getTime = time.Now
|
||||||
|
|
||||||
func ProvideUserAuthTokenService(sqlStore db.DB,
|
func ProvideUserAuthTokenService(sqlStore db.DB,
|
||||||
serverLockService *serverlock.ServerLockService,
|
serverLockService *serverlock.ServerLockService,
|
||||||
remoteCache *remotecache.RemoteCache,
|
|
||||||
features *featuremgmt.FeatureManager,
|
|
||||||
quotaService quota.Service,
|
quotaService quota.Service,
|
||||||
cfg *setting.Cfg) (*UserAuthTokenService, error) {
|
cfg *setting.Cfg) (*UserAuthTokenService, error) {
|
||||||
s := &UserAuthTokenService{
|
s := &UserAuthTokenService{
|
||||||
@ -42,8 +34,6 @@ func ProvideUserAuthTokenService(sqlStore db.DB,
|
|||||||
serverLockService: serverLockService,
|
serverLockService: serverLockService,
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
log: log.New("auth"),
|
log: log.New("auth"),
|
||||||
remoteCache: remoteCache,
|
|
||||||
features: features,
|
|
||||||
singleflight: new(singleflight.Group),
|
singleflight: new(singleflight.Group),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,8 +50,6 @@ func ProvideUserAuthTokenService(sqlStore db.DB,
|
|||||||
return s, err
|
return s, err
|
||||||
}
|
}
|
||||||
|
|
||||||
remotecache.Register(auth.UserToken{})
|
|
||||||
|
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,8 +58,6 @@ type UserAuthTokenService struct {
|
|||||||
serverLockService *serverlock.ServerLockService
|
serverLockService *serverlock.ServerLockService
|
||||||
cfg *setting.Cfg
|
cfg *setting.Cfg
|
||||||
log log.Logger
|
log log.Logger
|
||||||
remoteCache *remotecache.RemoteCache
|
|
||||||
features *featuremgmt.FeatureManager
|
|
||||||
singleflight *singleflight.Group
|
singleflight *singleflight.Group
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,52 +109,7 @@ func (s *UserAuthTokenService) CreateToken(ctx context.Context, user *user.User,
|
|||||||
return &userToken, err
|
return &userToken, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *UserAuthTokenService) lookupTokenWithCache(ctx context.Context, unhashedToken string) (*auth.UserToken, error) {
|
|
||||||
hashedToken := hashToken(unhashedToken)
|
|
||||||
cacheKey := "auth_token:" + hashedToken
|
|
||||||
|
|
||||||
session, errCache := s.remoteCache.Get(ctx, cacheKey)
|
|
||||||
if errCache == nil {
|
|
||||||
token := session.(auth.UserToken)
|
|
||||||
return &token, nil
|
|
||||||
} else {
|
|
||||||
if errors.Is(errCache, remotecache.ErrCacheItemNotFound) {
|
|
||||||
s.log.Debug("user auth token not found in cache",
|
|
||||||
"cacheKey", cacheKey)
|
|
||||||
} else {
|
|
||||||
s.log.Warn("failed to get user auth token from cache",
|
|
||||||
"cacheKey", cacheKey, "error", errCache)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
token, err := s.lookupToken(ctx, unhashedToken)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// only cache tokens until their near rotation time
|
|
||||||
// Near rotation time = tokens last rotation plus the rotation interval minus 2 ttl (=30s by default)
|
|
||||||
nextRotation := time.Unix(token.RotatedAt, 0).
|
|
||||||
Add(-2 * ttl). // subtract 2 ttl to make sure we don't cache tokens that are about to expire
|
|
||||||
Add(time.Duration(s.cfg.TokenRotationIntervalMinutes) * time.Minute)
|
|
||||||
if now := getTime(); now.Before(nextRotation) {
|
|
||||||
if err := s.remoteCache.Set(ctx, cacheKey, *token, ttl); err != nil {
|
|
||||||
s.log.Warn("could not cache token", "error", err, "cacheKey", cacheKey, "userId", token.UserId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return token, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *UserAuthTokenService) LookupToken(ctx context.Context, unhashedToken string) (*auth.UserToken, error) {
|
func (s *UserAuthTokenService) LookupToken(ctx context.Context, unhashedToken string) (*auth.UserToken, error) {
|
||||||
if s.features != nil && s.features.IsEnabled(featuremgmt.FlagSessionRemoteCache) {
|
|
||||||
return s.lookupTokenWithCache(ctx, unhashedToken)
|
|
||||||
}
|
|
||||||
|
|
||||||
return s.lookupToken(ctx, unhashedToken)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *UserAuthTokenService) lookupToken(ctx context.Context, unhashedToken string) (*auth.UserToken, error) {
|
|
||||||
hashedToken := hashToken(unhashedToken)
|
hashedToken := hashToken(unhashedToken)
|
||||||
var model userAuthToken
|
var model userAuthToken
|
||||||
var exists bool
|
var exists bool
|
||||||
|
@ -357,11 +357,6 @@ var (
|
|||||||
Description: "Use new auth service to perform authentication",
|
Description: "Use new auth service to perform authentication",
|
||||||
State: FeatureStateAlpha,
|
State: FeatureStateAlpha,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Name: "sessionRemoteCache",
|
|
||||||
Description: "Enable using remote cache for user sessions",
|
|
||||||
State: FeatureStateAlpha,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
Name: "disablePrometheusExemplarSampling",
|
Name: "disablePrometheusExemplarSampling",
|
||||||
Description: "Disable Prometheus examplar sampling",
|
Description: "Disable Prometheus examplar sampling",
|
||||||
|
@ -263,10 +263,6 @@ const (
|
|||||||
// Use new auth service to perform authentication
|
// Use new auth service to perform authentication
|
||||||
FlagAuthnService = "authnService"
|
FlagAuthnService = "authnService"
|
||||||
|
|
||||||
// FlagSessionRemoteCache
|
|
||||||
// Enable using remote cache for user sessions
|
|
||||||
FlagSessionRemoteCache = "sessionRemoteCache"
|
|
||||||
|
|
||||||
// FlagDisablePrometheusExemplarSampling
|
// FlagDisablePrometheusExemplarSampling
|
||||||
// Disable Prometheus examplar sampling
|
// Disable Prometheus examplar sampling
|
||||||
FlagDisablePrometheusExemplarSampling = "disablePrometheusExemplarSampling"
|
FlagDisablePrometheusExemplarSampling = "disablePrometheusExemplarSampling"
|
||||||
|
@ -467,7 +467,7 @@ func setupEnv(t *testing.T, sqlStore *sqlstore.SQLStore, b bus.Bus, quotaService
|
|||||||
tracer := tracing.InitializeTracerForTest()
|
tracer := tracing.InitializeTracerForTest()
|
||||||
_, err := apikeyimpl.ProvideService(sqlStore, sqlStore.Cfg, quotaService)
|
_, err := apikeyimpl.ProvideService(sqlStore, sqlStore.Cfg, quotaService)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
_, err = authimpl.ProvideUserAuthTokenService(sqlStore, nil, nil, featuremgmt.WithFeatures(), quotaService, sqlStore.Cfg)
|
_, err = authimpl.ProvideUserAuthTokenService(sqlStore, nil, quotaService, sqlStore.Cfg)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
_, err = dashboardStore.ProvideDashboardStore(sqlStore, sqlStore.Cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, sqlStore.Cfg), quotaService)
|
_, err = dashboardStore.ProvideDashboardStore(sqlStore, sqlStore.Cfg, featuremgmt.WithFeatures(), tagimpl.ProvideService(sqlStore, sqlStore.Cfg), quotaService)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
Loading…
Reference in New Issue
Block a user