authnz: Fix panic in the authenticator and rename metric (#97150)

* Fix: panic

* suggestion
This commit is contained in:
Georges Chaudy
2024-11-28 14:03:54 +02:00
committed by GitHub
parent 5e5fa86b8b
commit f6124344ba
2 changed files with 26 additions and 19 deletions
@@ -107,42 +107,49 @@ func FallbackUsed(ctx context.Context) bool {
func (f *AuthenticatorWithFallback) Authenticate(ctx context.Context) (context.Context, error) { func (f *AuthenticatorWithFallback) Authenticate(ctx context.Context) (context.Context, error) {
ctx, span := f.tracer.Start(ctx, "grpcutils.AuthenticatorWithFallback.Authenticate") ctx, span := f.tracer.Start(ctx, "grpcutils.AuthenticatorWithFallback.Authenticate")
defer span.End() defer span.End()
span.SetAttributes(attribute.Bool("fallback_used", false))
// Try to authenticate with the new authenticator first // Try to authenticate with the new authenticator first
span.SetAttributes(attribute.Bool("fallback_used", false))
newCtx, err := f.authenticator.Authenticate(ctx) newCtx, err := f.authenticator.Authenticate(ctx)
if err != nil { if err == nil {
// In case of error, fallback to the legacy authenticator // fallback not used, authentication successful
newCtx, err = f.fallback.Authenticate(ctx) f.metrics.requestsTotal.WithLabelValues("false", "true").Inc()
f.metrics.fallbackCounter.WithLabelValues(fmt.Sprintf("%t", err == nil)).Inc() return newCtx, nil
span.SetAttributes(attribute.Bool("fallback_used", true)) }
// In case of error, fallback to the legacy authenticator
span.SetAttributes(attribute.Bool("fallback_used", true))
newCtx, err = f.fallback.Authenticate(ctx)
if newCtx != nil {
newCtx = context.WithValue(newCtx, contextFallbackKey{}, true) newCtx = context.WithValue(newCtx, contextFallbackKey{}, true)
} }
f.metrics.requestsTotal.WithLabelValues("true", fmt.Sprintf("%t", err == nil)).Inc()
return newCtx, err return newCtx, err
} }
const ( const (
metricsNamespace = "grafana" metricsNamespace = "grafana"
metricsSubSystem = "grpc_authenticator" metricsSubSystem = "grpc_authenticator_with_fallback"
) )
type metrics struct { type metrics struct {
fallbackCounter *prometheus.CounterVec requestsTotal *prometheus.CounterVec
} }
func newMetrics(reg prometheus.Registerer) *metrics { func newMetrics(reg prometheus.Registerer) *metrics {
m := &metrics{ m := &metrics{
fallbackCounter: prometheus.NewCounterVec( requestsTotal: prometheus.NewCounterVec(
prometheus.CounterOpts{ prometheus.CounterOpts{
Namespace: metricsNamespace, Namespace: metricsNamespace,
Subsystem: metricsSubSystem, Subsystem: metricsSubSystem,
Name: "fallback_total", Name: "requests_total",
Help: "Number of times the fallback authenticator was used", Help: "Number requests using the authenticator with fallback",
}, []string{"result"}), }, []string{"fallback_used", "result"}),
} }
if reg != nil { if reg != nil {
once.Do(func() { once.Do(func() {
reg.MustRegister(m.fallbackCounter) reg.MustRegister(m.requestsTotal)
}) })
} }
+6 -6
View File
@@ -39,8 +39,8 @@ type groupResource map[string]map[string]interface{}
// For now, it makes one call to the authz service for each list items. This is known to be inefficient. // For now, it makes one call to the authz service for each list items. This is known to be inefficient.
type authzLimitedClient struct { type authzLimitedClient struct {
client authz.AccessChecker client authz.AccessChecker
// whitelist is a map of group to resources that are compatible with RBAC. // allowlist is a map of group to resources that are compatible with RBAC.
whitelist groupResource allowlist groupResource
logger *slog.Logger logger *slog.Logger
tracer trace.Tracer tracer trace.Tracer
} }
@@ -57,7 +57,7 @@ func NewAuthzLimitedClient(client authz.AccessChecker, opts AuthzOptions) authz.
} }
return &authzLimitedClient{ return &authzLimitedClient{
client: client, client: client,
whitelist: groupResource{ allowlist: groupResource{
"dashboard.grafana.app": map[string]interface{}{"dashboards": nil}, "dashboard.grafana.app": map[string]interface{}{"dashboards": nil},
"folder.grafana.app": map[string]interface{}{"folders": nil}, "folder.grafana.app": map[string]interface{}{"folders": nil},
}, },
@@ -107,7 +107,7 @@ func (c authzLimitedClient) Compile(ctx context.Context, id claims.AuthInfo, req
)) ))
defer span.End() defer span.End()
if grpcutils.FallbackUsed(ctx) { if grpcutils.FallbackUsed(ctx) {
c.logger.Debug("Check", "group", req.Group, "resource", req.Resource, "fallback", true, "rbac", false, "allowed", true) c.logger.Debug("Compile.Check", "group", req.Group, "resource", req.Resource, "fallback", true, "rbac", false, "allowed", true)
return true return true
} }
// TODO: Implement For now we perform the check for each item. // TODO: Implement For now we perform the check for each item.
@@ -134,8 +134,8 @@ func (c authzLimitedClient) Compile(ctx context.Context, id claims.AuthInfo, req
} }
func (c authzLimitedClient) IsCompatibleWithRBAC(group, resource string) bool { func (c authzLimitedClient) IsCompatibleWithRBAC(group, resource string) bool {
if _, ok := c.whitelist[group]; ok { if _, ok := c.allowlist[group]; ok {
if _, ok := c.whitelist[group][resource]; ok { if _, ok := c.allowlist[group][resource]; ok {
return true return true
} }
} }