grpc: wrapContext should not replace existing metadata, but append to it. (#107126)

* grpc: wrapContext should not replace existing metadata, but append to it.

* Add test for wrapContext if there's no previous metadata.

* Rename encodeIdentityInMetadata to encodeIdentityInMetadataPairs
This commit is contained in:
Peter Štibraný
2025-06-25 08:06:45 +00:00
committed by GitHub
parent c63a52958d
commit eeb01126b3
2 changed files with 40 additions and 9 deletions
@@ -11,8 +11,9 @@ import (
"google.golang.org/grpc/status"
"github.com/grafana/authlib/types"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"go.opentelemetry.io/otel/trace"
"github.com/grafana/grafana/pkg/apimachinery/identity"
)
const (
@@ -139,15 +140,16 @@ func wrapContext(ctx context.Context) (context.Context, error) {
}
// set grpc metadata into the context to pass to the grpc server
return metadata.NewOutgoingContext(ctx, encodeIdentityInMetadata(user)), nil
ctx = metadata.AppendToOutgoingContext(ctx, encodeIdentityInMetadataPairs(user)...)
return ctx, nil
}
func encodeIdentityInMetadata(user identity.Requester) metadata.MD {
func encodeIdentityInMetadataPairs(user identity.Requester) []string {
id, _ := user.GetInternalID()
logger.Debug("encodeIdentityInMetadata", "user.id", user.GetID(), "user.Login", user.GetLogin(), "user.Name", user.GetName())
logger.Debug("encodeIdentityInMetadataPairs", "user.id", user.GetID(), "user.Login", user.GetLogin(), "user.Name", user.GetName())
return metadata.Pairs(
return []string{
// This should be everything needed to recreate the user
mdToken, user.GetIDToken(),
@@ -161,5 +163,5 @@ func encodeIdentityInMetadata(user identity.Requester) metadata.MD {
// TODO, Remove after this is deployed to unified storage
"grafana-userid", strconv.FormatInt(id, 10),
"grafana-useruid", user.GetRawIdentifier(),
)
}
}
@@ -1,13 +1,16 @@
package grpc
import (
"context"
"testing"
"github.com/stretchr/testify/require"
"google.golang.org/grpc/metadata"
claims "github.com/grafana/authlib/types"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"go.opentelemetry.io/otel/trace/noop"
"github.com/grafana/grafana/pkg/apimachinery/identity"
)
func TestBasicEncodeDecode(t *testing.T) {
@@ -22,8 +25,8 @@ func TestBasicEncodeDecode(t *testing.T) {
auth := &Authenticator{Tracer: noop.NewTracerProvider().Tracer("")}
md := encodeIdentityInMetadata(before)
after, err := auth.decodeMetadata(md)
md := encodeIdentityInMetadataPairs(before)
after, err := auth.decodeMetadata(metadata.Pairs(md...))
require.NoError(t, err)
require.Equal(t, before.GetID(), after.GetID())
require.Equal(t, before.GetUID(), after.GetUID())
@@ -33,3 +36,29 @@ func TestBasicEncodeDecode(t *testing.T) {
require.Equal(t, before.GetOrgName(), after.GetOrgName())
require.Equal(t, before.GetOrgRole(), after.GetOrgRole())
}
func TestWrapContext(t *testing.T) {
const key = "some-random-metadata"
ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(key, "random-metadata"))
ctx, _ = identity.WithServiceIdentity(ctx, 12345)
var err error
ctx, err = wrapContext(ctx)
require.NoError(t, err)
outmd, ok := metadata.FromOutgoingContext(ctx)
require.True(t, ok)
val := outmd.Get(key)
require.Equal(t, []string{"random-metadata"}, val)
}
func TestWrapContextWithNoPreviousMetadata(t *testing.T) {
ctx, _ := identity.WithServiceIdentity(context.Background(), 12345)
ctx, err := wrapContext(ctx)
require.NoError(t, err)
outmd, ok := metadata.FromOutgoingContext(ctx)
require.True(t, ok)
val := outmd.Get(mdOrgID)
require.Equal(t, []string{"12345"}, val)
}