mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
IDForwarding: Use single flight for SignIdentity (#76530)
* IDForwarding: Use single flight for SignIdentity * Update cache inside single flight call
This commit is contained in:
@@ -6,6 +6,9 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-jose/go-jose/v3/jwt"
|
"github.com/go-jose/go-jose/v3/jwt"
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
"golang.org/x/sync/singleflight"
|
||||||
|
|
||||||
"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/remotecache"
|
||||||
"github.com/grafana/grafana/pkg/services/auth"
|
"github.com/grafana/grafana/pkg/services/auth"
|
||||||
@@ -13,7 +16,6 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/services/authn"
|
"github.com/grafana/grafana/pkg/services/authn"
|
||||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -28,7 +30,7 @@ func ProvideService(
|
|||||||
cfg *setting.Cfg, signer auth.IDSigner, cache remotecache.CacheStorage,
|
cfg *setting.Cfg, signer auth.IDSigner, cache remotecache.CacheStorage,
|
||||||
features featuremgmt.FeatureToggles, authnService authn.Service, reg prometheus.Registerer,
|
features featuremgmt.FeatureToggles, authnService authn.Service, reg prometheus.Registerer,
|
||||||
) *Service {
|
) *Service {
|
||||||
s := &Service{cfg, log.New("id-service"), signer, cache, newMetrics(reg)}
|
s := &Service{cfg: cfg, logger: log.New("id-service"), signer: signer, cache: cache, metrics: newMetrics(reg)}
|
||||||
|
|
||||||
if features.IsEnabled(featuremgmt.FlagIdForwarding) {
|
if features.IsEnabled(featuremgmt.FlagIdForwarding) {
|
||||||
authnService.RegisterPostAuthHook(s.hook, 140)
|
authnService.RegisterPostAuthHook(s.hook, 140)
|
||||||
@@ -42,6 +44,7 @@ type Service struct {
|
|||||||
logger log.Logger
|
logger log.Logger
|
||||||
signer auth.IDSigner
|
signer auth.IDSigner
|
||||||
cache remotecache.CacheStorage
|
cache remotecache.CacheStorage
|
||||||
|
si singleflight.Group
|
||||||
metrics *metrics
|
metrics *metrics
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,40 +53,49 @@ func (s *Service) SignIdentity(ctx context.Context, id identity.Requester) (stri
|
|||||||
s.metrics.tokenSigningDurationHistogram.Observe(time.Since(t).Seconds())
|
s.metrics.tokenSigningDurationHistogram.Observe(time.Since(t).Seconds())
|
||||||
}(time.Now())
|
}(time.Now())
|
||||||
|
|
||||||
namespace, identifier := id.GetNamespacedID()
|
|
||||||
|
|
||||||
cacheKey := prefixCacheKey(id.GetCacheKey())
|
cacheKey := prefixCacheKey(id.GetCacheKey())
|
||||||
cachedToken, err := s.cache.Get(ctx, cacheKey)
|
|
||||||
if err == nil {
|
|
||||||
s.metrics.tokenSigningFromCacheCounter.Inc()
|
|
||||||
s.logger.Debug("Cached token found", "namespace", namespace, "id", identifier)
|
|
||||||
return string(cachedToken), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
s.metrics.tokenSigningCounter.Inc()
|
result, err, _ := s.si.Do(cacheKey, func() (interface{}, error) {
|
||||||
s.logger.Debug("Sign new id token", "namespace", namespace, "id", identifier)
|
namespace, identifier := id.GetNamespacedID()
|
||||||
|
|
||||||
now := time.Now()
|
cachedToken, err := s.cache.Get(ctx, cacheKey)
|
||||||
token, err := s.signer.SignIDToken(ctx, &auth.IDClaims{
|
if err == nil {
|
||||||
Claims: jwt.Claims{
|
s.metrics.tokenSigningFromCacheCounter.Inc()
|
||||||
Issuer: s.cfg.AppURL,
|
s.logger.Debug("Cached token found", "namespace", namespace, "id", identifier)
|
||||||
Audience: getAudience(id.GetOrgID()),
|
return string(cachedToken), nil
|
||||||
Subject: getSubject(namespace, identifier),
|
}
|
||||||
Expiry: jwt.NewNumericDate(now.Add(tokenTTL)),
|
|
||||||
IssuedAt: jwt.NewNumericDate(now),
|
s.metrics.tokenSigningCounter.Inc()
|
||||||
},
|
s.logger.Debug("Sign new id token", "namespace", namespace, "id", identifier)
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
token, err := s.signer.SignIDToken(ctx, &auth.IDClaims{
|
||||||
|
Claims: jwt.Claims{
|
||||||
|
Issuer: s.cfg.AppURL,
|
||||||
|
Audience: getAudience(id.GetOrgID()),
|
||||||
|
Subject: getSubject(namespace, identifier),
|
||||||
|
Expiry: jwt.NewNumericDate(now.Add(tokenTTL)),
|
||||||
|
IssuedAt: jwt.NewNumericDate(now),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
s.metrics.failedTokenSigningCounter.Inc()
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.cache.Set(ctx, cacheKey, []byte(token), cacheTTL); err != nil {
|
||||||
|
s.logger.Error("Failed to add id token to cache", "error", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return token, nil
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.metrics.failedTokenSigningCounter.Inc()
|
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.cache.Set(ctx, cacheKey, []byte(token), cacheTTL); err != nil {
|
return result.(string), nil
|
||||||
s.logger.Error("Failed to add id token to cache", "error", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return token, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) hook(ctx context.Context, identity *authn.Identity, _ *authn.Request) error {
|
func (s *Service) hook(ctx context.Context, identity *authn.Identity, _ *authn.Request) error {
|
||||||
|
|||||||
Reference in New Issue
Block a user