Authenticator: Return gRPC errors (#99000)

pull/99099/head
Gabriel MABILLE 4 months ago committed by GitHub
parent 98e9f3a534
commit 70ddf9cb76
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 47
      pkg/storage/unified/resource/grpc/authenticator.go
  2. 6
      pkg/storage/unified/resource/grpc/authenticator_test.go
  3. 3
      pkg/storage/unified/sql/service.go

@ -2,16 +2,17 @@ package grpc
import (
"context"
"fmt"
"strconv"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
"github.com/grafana/authlib/authn"
authClaims "github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/infra/tracing"
)
const (
@ -27,10 +28,13 @@ const (
// var _ interceptors.Authenticator = (*Authenticator)(nil)
type Authenticator struct {
IDTokenVerifier authn.Verifier[authn.IDTokenClaims]
Tracer tracing.Tracer
}
func (f *Authenticator) Authenticate(ctx context.Context) (context.Context, error) {
ctx, span := f.Tracer.Start(ctx, "legacy.grpc.Authenticator.Authenticate")
defer span.End()
r, err := identity.GetRequester(ctx)
if err == nil && r != nil {
return ctx, nil // noop, requester exists
@ -38,16 +42,19 @@ func (f *Authenticator) Authenticate(ctx context.Context) (context.Context, erro
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
return nil, fmt.Errorf("no metadata found")
err := status.Error(codes.Unauthenticated, "no metadata found in grpc context")
span.RecordError(err)
return nil, err
}
user, err := f.decodeMetadata(ctx, md)
user, err := f.decodeMetadata(md)
if err != nil {
span.RecordError(err)
return nil, err
}
return identity.WithRequester(ctx, user), nil
}
func (f *Authenticator) decodeMetadata(ctx context.Context, meta metadata.MD) (identity.Requester, error) {
func (f *Authenticator) decodeMetadata(meta metadata.MD) (identity.Requester, error) {
// Avoid NPE/panic with getting keys
getter := func(key string) string {
v := meta.Get(key)
@ -57,20 +64,10 @@ func (f *Authenticator) decodeMetadata(ctx context.Context, meta metadata.MD) (i
return ""
}
// First try the token
token := getter(mdToken)
if token != "" && f.IDTokenVerifier != nil {
claims, err := f.IDTokenVerifier.Verify(ctx, token)
if err != nil {
return nil, err
}
fmt.Printf("TODO, convert CLAIMS to an identity %+v\n", claims)
}
user := &identity.StaticRequester{}
user.Login = getter(mdLogin)
if user.Login == "" {
return nil, fmt.Errorf("no login found in grpc metadata")
return nil, status.Error(codes.Unauthenticated, "no login found in grpc metadata")
}
// The namespaced versions have a "-" in the key
@ -80,34 +77,34 @@ func (f *Authenticator) decodeMetadata(ctx context.Context, meta metadata.MD) (i
user.Type = authClaims.TypeUser
user.UserID, err = strconv.ParseInt(getter("grafana-userid"), 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid user id: %w", err)
return nil, status.Error(codes.Unauthenticated, "invalid user id")
}
user.OrgID, err = strconv.ParseInt(getter("grafana-orgid"), 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid org id: %w", err)
return nil, status.Error(codes.Unauthenticated, "invalid org id")
}
return user, nil
}
typ, id, err := authClaims.ParseTypeID(getter(mdUserID))
if err != nil {
return nil, fmt.Errorf("invalid user id: %w", err)
return nil, status.Error(codes.Unauthenticated, "invalid user id")
}
user.Type = typ
user.UserID, err = strconv.ParseInt(id, 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid user id: %w", err)
return nil, status.Error(codes.Unauthenticated, "invalid user id")
}
_, id, err = authClaims.ParseTypeID(getter(mdUserUID))
_, uid, err := authClaims.ParseTypeID(getter(mdUserUID))
if err != nil {
return nil, fmt.Errorf("invalid user id: %w", err)
return nil, status.Error(codes.Unauthenticated, "invalid user uid")
}
user.UserUID = id
user.UserUID = uid
user.OrgID, err = strconv.ParseInt(getter(mdOrgID), 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid org id: %w", err)
return nil, status.Error(codes.Unauthenticated, "invalid org id")
}
user.OrgRole = identity.RoleType(getter(mdOrgRole))
return user, nil

@ -1,13 +1,13 @@
package grpc
import (
"context"
"testing"
"github.com/stretchr/testify/require"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/infra/tracing"
)
func TestBasicEncodeDecode(t *testing.T) {
@ -20,10 +20,10 @@ func TestBasicEncodeDecode(t *testing.T) {
OrgRole: identity.RoleAdmin,
}
auth := &Authenticator{}
auth := &Authenticator{Tracer: tracing.NewNoopTracerService()}
md := encodeIdentityInMetadata(before)
after, err := auth.decodeMetadata(context.Background(), md)
after, err := auth.decodeMetadata(md)
require.NoError(t, err)
require.Equal(t, before.GetID(), after.GetID())
require.Equal(t, before.GetUID(), after.GetUID())

@ -80,7 +80,8 @@ func ProvideUnifiedStorageGrpcService(
// FIXME: This is a temporary solution while we are migrating to the new authn interceptor
// grpcutils.NewGrpcAuthenticator should be used instead.
authn, err := grpcutils.NewGrpcAuthenticatorWithFallback(cfg, reg, tracing, &grpc.Authenticator{})
fallback := &grpc.Authenticator{Tracer: tracing}
authn, err := grpcutils.NewGrpcAuthenticatorWithFallback(cfg, reg, tracing, fallback)
if err != nil {
return nil, err
}

Loading…
Cancel
Save