mirror of
https://github.com/grafana/grafana.git
synced 2025-08-02 04:09:50 +08:00
Use authlib repo. Use otel (#103178)
* Use authlib repo. Use otel * Use interceptors on the provider level * Create a new wire set with otel * Lint * Fix test * make update-workflow * make update-workspace * make update-workspace. Try to add authlib as enterprise imports * make update-workspace
This commit is contained in:
@ -2,17 +2,21 @@ package sql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"google.golang.org/grpc/health/grpc_health_v1"
|
||||
|
||||
"github.com/grafana/authlib/grpcutils"
|
||||
"github.com/grafana/dskit/services"
|
||||
|
||||
infraDB "github.com/grafana/grafana/pkg/infra/db"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/modules"
|
||||
"github.com/grafana/grafana/pkg/services/authn/grpcutils"
|
||||
"github.com/grafana/grafana/pkg/services/authz"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/grpcserver"
|
||||
@ -45,9 +49,9 @@ type service struct {
|
||||
|
||||
handler grpcserver.Provider
|
||||
|
||||
tracing *tracing.TracingService
|
||||
tracing trace.Tracer
|
||||
|
||||
authenticator interceptors.Authenticator
|
||||
authenticator func(ctx context.Context) (context.Context, error)
|
||||
|
||||
log log.Logger
|
||||
reg prometheus.Registerer
|
||||
@ -67,16 +71,7 @@ func ProvideUnifiedStorageGrpcService(
|
||||
storageMetrics *resource.StorageMetrics,
|
||||
indexMetrics *resource.BleveIndexMetrics,
|
||||
) (UnifiedStorageGrpcService, error) {
|
||||
tracingCfg, err := tracing.ProvideTracingConfig(cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tracingCfg.ServiceName = "unified-storage"
|
||||
|
||||
tracing, err := tracing.ProvideService(tracingCfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tracer := otel.Tracer("unified-storage")
|
||||
|
||||
// reg can be nil when running unified storage in standalone mode
|
||||
if reg == nil {
|
||||
@ -85,14 +80,17 @@ func ProvideUnifiedStorageGrpcService(
|
||||
|
||||
// FIXME: This is a temporary solution while we are migrating to the new authn interceptor
|
||||
// grpcutils.NewGrpcAuthenticator should be used instead.
|
||||
authn := grpcutils.NewAuthenticatorWithFallback(cfg, reg, tracing, &grpc.Authenticator{Tracer: tracing})
|
||||
authn := NewAuthenticatorWithFallback(cfg, reg, tracer, func(ctx context.Context) (context.Context, error) {
|
||||
auth := grpc.Authenticator{Tracer: tracer}
|
||||
return auth.Authenticate(ctx)
|
||||
})
|
||||
|
||||
s := &service{
|
||||
cfg: cfg,
|
||||
features: features,
|
||||
stopCh: make(chan struct{}),
|
||||
authenticator: authn,
|
||||
tracing: tracing,
|
||||
tracing: tracer,
|
||||
db: db,
|
||||
log: log,
|
||||
reg: reg,
|
||||
@ -122,7 +120,7 @@ func (s *service) start(ctx context.Context) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.handler, err = grpcserver.ProvideService(s.cfg, s.features, s.authenticator, s.tracing, prometheus.DefaultRegisterer)
|
||||
s.handler, err = grpcserver.ProvideService(s.cfg, s.features, interceptors.AuthenticatorFunc(s.authenticator), s.tracing, prometheus.DefaultRegisterer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -175,3 +173,88 @@ func (s *service) running(ctx context.Context) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type authenticatorWithFallback struct {
|
||||
authenticator func(ctx context.Context) (context.Context, error)
|
||||
fallback func(ctx context.Context) (context.Context, error)
|
||||
metrics *metrics
|
||||
tracer trace.Tracer
|
||||
}
|
||||
|
||||
type metrics struct {
|
||||
requestsTotal *prometheus.CounterVec
|
||||
}
|
||||
|
||||
func (f *authenticatorWithFallback) Authenticate(ctx context.Context) (context.Context, error) {
|
||||
ctx, span := f.tracer.Start(ctx, "grpcutils.AuthenticatorWithFallback.Authenticate")
|
||||
defer span.End()
|
||||
|
||||
// Try to authenticate with the new authenticator first
|
||||
span.SetAttributes(attribute.Bool("fallback_used", false))
|
||||
newCtx, err := f.authenticator(ctx)
|
||||
if err == nil {
|
||||
// fallback not used, authentication successful
|
||||
f.metrics.requestsTotal.WithLabelValues("false", "true").Inc()
|
||||
return newCtx, nil
|
||||
}
|
||||
|
||||
// In case of error, fallback to the legacy authenticator
|
||||
span.SetAttributes(attribute.Bool("fallback_used", true))
|
||||
newCtx, err = f.fallback(ctx)
|
||||
if newCtx != nil {
|
||||
newCtx = resource.WithFallback(newCtx)
|
||||
}
|
||||
f.metrics.requestsTotal.WithLabelValues("true", fmt.Sprintf("%t", err == nil)).Inc()
|
||||
return newCtx, err
|
||||
}
|
||||
|
||||
const (
|
||||
metricsNamespace = "grafana"
|
||||
metricsSubSystem = "grpc_authenticator_with_fallback"
|
||||
)
|
||||
|
||||
var once sync.Once
|
||||
|
||||
func newMetrics(reg prometheus.Registerer) *metrics {
|
||||
m := &metrics{
|
||||
requestsTotal: prometheus.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Namespace: metricsNamespace,
|
||||
Subsystem: metricsSubSystem,
|
||||
Name: "requests_total",
|
||||
Help: "Number requests using the authenticator with fallback",
|
||||
}, []string{"fallback_used", "result"}),
|
||||
}
|
||||
|
||||
if reg != nil {
|
||||
once.Do(func() {
|
||||
reg.MustRegister(m.requestsTotal)
|
||||
})
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func ReadGrpcServerConfig(cfg *setting.Cfg) *grpcutils.AuthenticatorConfig {
|
||||
section := cfg.SectionWithEnvOverrides("grpc_server_authentication")
|
||||
|
||||
return &grpcutils.AuthenticatorConfig{
|
||||
SigningKeysURL: section.Key("signing_keys_url").MustString(""),
|
||||
AllowedAudiences: section.Key("allowed_audiences").Strings(","),
|
||||
AllowInsecure: cfg.Env == setting.Dev,
|
||||
}
|
||||
}
|
||||
|
||||
func NewAuthenticatorWithFallback(cfg *setting.Cfg, reg prometheus.Registerer, tracer trace.Tracer, fallback func(context.Context) (context.Context, error)) func(context.Context) (context.Context, error) {
|
||||
authCfg := ReadGrpcServerConfig(cfg)
|
||||
authenticator := grpcutils.NewAuthenticator(authCfg, tracer)
|
||||
return func(ctx context.Context) (context.Context, error) {
|
||||
a := &authenticatorWithFallback{
|
||||
authenticator: authenticator,
|
||||
fallback: fallback,
|
||||
tracer: tracer,
|
||||
metrics: newMetrics(reg),
|
||||
}
|
||||
return a.Authenticate(ctx)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user