Authz: Sync authlib and update authz client setup code (#100817)
* Sync authlib and update setup code for authz client
This commit is contained in:
@@ -72,7 +72,7 @@ require (
|
||||
github.com/gorilla/mux v1.8.1 // @grafana/grafana-backend-group
|
||||
github.com/gorilla/websocket v1.5.3 // @grafana/grafana-app-platform-squad
|
||||
github.com/grafana/alerting v0.0.0-20250207161551-04c87cf39038 // @grafana/alerting-backend
|
||||
github.com/grafana/authlib v0.0.0-20250206063954-bf4600a17569 // @grafana/identity-access-team
|
||||
github.com/grafana/authlib v0.0.0-20250217135712-106ec5baf6bc // @grafana/identity-access-team
|
||||
github.com/grafana/authlib/types v0.0.0-20250120145936-5f0e28e7a87c // @grafana/identity-access-team
|
||||
github.com/grafana/dataplane/examples v0.0.1 // @grafana/observability-metrics
|
||||
github.com/grafana/dataplane/sdata v0.0.9 // @grafana/observability-metrics
|
||||
|
||||
@@ -1513,8 +1513,8 @@ github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aN
|
||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grafana/alerting v0.0.0-20250207161551-04c87cf39038 h1:dG/UKAjY/KlKp9fY8aEm+gSQHHRmPm5q+9cea3hRSu8=
|
||||
github.com/grafana/alerting v0.0.0-20250207161551-04c87cf39038/go.mod h1:QsnoKX/iYZxA4Cv+H+wC7uxutBD8qi8ZW5UJvD2TYmU=
|
||||
github.com/grafana/authlib v0.0.0-20250206063954-bf4600a17569 h1:bQw6fdcxVdZ6xmZVhMtRgGEKIT1Zc6y+i1PWF8tMX4Q=
|
||||
github.com/grafana/authlib v0.0.0-20250206063954-bf4600a17569/go.mod h1:/gYfphsNu9v1qYWXxpv1NSvMEMSwvdf8qb8YlgwIRl8=
|
||||
github.com/grafana/authlib v0.0.0-20250217135712-106ec5baf6bc h1:qx8avmRi3wx+SuAn6UV0pKma1fJ0/4POUYNc+2rxZkg=
|
||||
github.com/grafana/authlib v0.0.0-20250217135712-106ec5baf6bc/go.mod h1:HamgITzYqErFp8qLwYM/JwwE3z6fXft0Z+5n0Dx1rUM=
|
||||
github.com/grafana/authlib/types v0.0.0-20250120145936-5f0e28e7a87c h1:b0sPDtt33uFdmvUJjSCld3kwE2E49dUvevuUDSJsEuo=
|
||||
github.com/grafana/authlib/types v0.0.0-20250120145936-5f0e28e7a87c/go.mod h1:qYjSd1tmJiuVoSICp7Py9/zD54O9uQQA3wuM6Gg4DFM=
|
||||
github.com/grafana/dataplane/examples v0.0.1 h1:K9M5glueWyLoL4//H+EtTQq16lXuHLmOhb6DjSCahzA=
|
||||
|
||||
@@ -3,7 +3,7 @@ module github.com/grafana/grafana/pkg/apimachinery
|
||||
go 1.23.1
|
||||
|
||||
require (
|
||||
github.com/grafana/authlib v0.0.0-20250206063954-bf4600a17569 // @grafana/identity-access-team
|
||||
github.com/grafana/authlib v0.0.0-20250217135712-106ec5baf6bc // @grafana/identity-access-team
|
||||
github.com/grafana/authlib/types v0.0.0-20250120145936-5f0e28e7a87c // @grafana/identity-access-team
|
||||
github.com/stretchr/testify v1.10.0
|
||||
k8s.io/apimachinery v0.32.1
|
||||
|
||||
@@ -32,8 +32,8 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/grafana/authlib v0.0.0-20250206063954-bf4600a17569 h1:bQw6fdcxVdZ6xmZVhMtRgGEKIT1Zc6y+i1PWF8tMX4Q=
|
||||
github.com/grafana/authlib v0.0.0-20250206063954-bf4600a17569/go.mod h1:/gYfphsNu9v1qYWXxpv1NSvMEMSwvdf8qb8YlgwIRl8=
|
||||
github.com/grafana/authlib v0.0.0-20250217135712-106ec5baf6bc h1:qx8avmRi3wx+SuAn6UV0pKma1fJ0/4POUYNc+2rxZkg=
|
||||
github.com/grafana/authlib v0.0.0-20250217135712-106ec5baf6bc/go.mod h1:HamgITzYqErFp8qLwYM/JwwE3z6fXft0Z+5n0Dx1rUM=
|
||||
github.com/grafana/authlib/types v0.0.0-20250120145936-5f0e28e7a87c h1:b0sPDtt33uFdmvUJjSCld3kwE2E49dUvevuUDSJsEuo=
|
||||
github.com/grafana/authlib/types v0.0.0-20250120145936-5f0e28e7a87c/go.mod h1:qYjSd1tmJiuVoSICp7Py9/zD54O9uQQA3wuM6Gg4DFM=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
|
||||
+34
-61
@@ -7,7 +7,6 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/fullstorydev/grpchan"
|
||||
"github.com/fullstorydev/grpchan/inprocgrpc"
|
||||
grpcAuth "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/auth"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
@@ -26,7 +25,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/registry/apis/iam/legacy"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/apiserver"
|
||||
authzextv1 "github.com/grafana/grafana/pkg/services/authz/proto/v1"
|
||||
"github.com/grafana/grafana/pkg/services/authz/rbac"
|
||||
"github.com/grafana/grafana/pkg/services/authz/rbac/store"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
@@ -59,7 +57,7 @@ func ProvideAuthZClient(
|
||||
|
||||
switch authCfg.mode {
|
||||
case clientModeCloud:
|
||||
return newRemoteLegacyClient(authCfg, tracer)
|
||||
return newRemoteRBACClient(authCfg, tracer)
|
||||
default:
|
||||
sql := legacysql.NewDatabaseProvider(db)
|
||||
|
||||
@@ -80,7 +78,18 @@ func ProvideAuthZClient(
|
||||
reg,
|
||||
cache.NewLocalCache(cache.Config{Expiry: 5 * time.Minute, CleanupInterval: 10 * time.Minute}),
|
||||
)
|
||||
return newInProcLegacyClient(server, tracer)
|
||||
|
||||
channel := &inprocgrpc.Channel{}
|
||||
channel.WithServerUnaryInterceptor(grpcAuth.UnaryServerInterceptor(func(ctx context.Context) (context.Context, error) {
|
||||
ctx = authlib.WithAuthInfo(ctx, authnlib.NewAccessTokenAuthInfo(authnlib.Claims[authnlib.AccessTokenClaims]{
|
||||
Rest: authnlib.AccessTokenClaims{
|
||||
Namespace: "*",
|
||||
},
|
||||
}))
|
||||
return ctx, nil
|
||||
}))
|
||||
authzv1.RegisterAuthzServiceServer(channel, server)
|
||||
return newRBACClient(channel, tracer), nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,76 +107,41 @@ func ProvideStandaloneAuthZClient(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return newRemoteLegacyClient(authCfg, tracer)
|
||||
return newRemoteRBACClient(authCfg, tracer)
|
||||
}
|
||||
|
||||
func newInProcLegacyClient(server *rbac.Service, tracer tracing.Tracer) (authlib.AccessClient, error) {
|
||||
// For in-proc use-case authorize add fake service claims - it should be able to access every namespace, as there is only one
|
||||
staticAuth := func(ctx context.Context) (context.Context, error) {
|
||||
ctx = authlib.WithAuthInfo(ctx, authnlib.NewAccessTokenAuthInfo(authnlib.Claims[authnlib.AccessTokenClaims]{
|
||||
Rest: authnlib.AccessTokenClaims{
|
||||
Namespace: "*",
|
||||
},
|
||||
}))
|
||||
return ctx, nil
|
||||
func newRemoteRBACClient(clientCfg *authzClientSettings, tracer tracing.Tracer) (authlib.AccessClient, error) {
|
||||
tokenClient, err := authnlib.NewTokenExchangeClient(authnlib.TokenExchangeConfig{
|
||||
Token: clientCfg.token,
|
||||
TokenExchangeURL: clientCfg.tokenExchangeURL,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to initialize token exchange client: %w", err)
|
||||
}
|
||||
|
||||
channel := &inprocgrpc.Channel{}
|
||||
channel.RegisterService(
|
||||
grpchan.InterceptServer(
|
||||
&authzv1.AuthzService_ServiceDesc,
|
||||
grpcAuth.UnaryServerInterceptor(staticAuth),
|
||||
grpcAuth.StreamServerInterceptor(staticAuth),
|
||||
conn, err := grpc.NewClient(
|
||||
clientCfg.remoteAddress,
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
grpc.WithPerRPCCredentials(
|
||||
newGRPCTokenAuth(authzServiceAudience, clientCfg.tokenNamespace, tokenClient),
|
||||
),
|
||||
server,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create authz client to remote server: %w", err)
|
||||
}
|
||||
|
||||
return newRBACClient(conn, tracer), nil
|
||||
}
|
||||
|
||||
func newRBACClient(conn grpc.ClientConnInterface, tracer tracing.Tracer) authlib.AccessClient {
|
||||
return authzlib.NewClient(
|
||||
&authzlib.ClientConfig{},
|
||||
authzlib.WithGrpcConnectionClientOption(channel),
|
||||
authzlib.WithTracerClientOption(tracer),
|
||||
authzlib.WithCacheClientOption(cache.NewLocalCache(cache.Config{
|
||||
Expiry: 30 * time.Second,
|
||||
CleanupInterval: 2 * time.Minute,
|
||||
})),
|
||||
)
|
||||
}
|
||||
|
||||
func newRemoteLegacyClient(clientCfg *authzClientSettings, tracer tracing.Tracer) (authlib.AccessClient, error) {
|
||||
grpcClientConfig := authnlib.GrpcClientConfig{
|
||||
TokenClientConfig: &authnlib.TokenExchangeConfig{
|
||||
Token: clientCfg.token,
|
||||
TokenExchangeURL: clientCfg.tokenExchangeURL,
|
||||
},
|
||||
TokenRequest: &authnlib.TokenExchangeRequest{
|
||||
Namespace: clientCfg.tokenNamespace,
|
||||
Audiences: []string{authzServiceAudience},
|
||||
},
|
||||
}
|
||||
|
||||
clientInterceptor, err := authnlib.NewGrpcClientInterceptor(&grpcClientConfig, authnlib.WithTracerOption(tracer))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client, err := authzlib.NewClient(
|
||||
&authzlib.ClientConfig{RemoteAddress: clientCfg.remoteAddress},
|
||||
authzlib.WithGrpcDialOptionsClientOption(
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
grpc.WithUnaryInterceptor(clientInterceptor.UnaryClientInterceptor),
|
||||
grpc.WithStreamInterceptor(clientInterceptor.StreamClientInterceptor),
|
||||
),
|
||||
conn,
|
||||
authzlib.WithCacheClientOption(cache.NewLocalCache(cache.Config{
|
||||
Expiry: 30 * time.Second,
|
||||
CleanupInterval: 2 * time.Minute,
|
||||
})),
|
||||
authzlib.WithTracerClientOption(tracer),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func RegisterRBACAuthZService(
|
||||
@@ -210,7 +184,6 @@ func RegisterRBACAuthZService(
|
||||
|
||||
srv := handler.GetServer()
|
||||
authzv1.RegisterAuthzServiceServer(srv, server)
|
||||
authzextv1.RegisterAuthzExtentionServiceServer(srv, server)
|
||||
}
|
||||
|
||||
var _ http.RoundTripper = tokenExhangeRoundTripper{}
|
||||
|
||||
@@ -24,7 +24,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/registry/apis/iam/common"
|
||||
"github.com/grafana/grafana/pkg/registry/apis/iam/legacy"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
authzextv1 "github.com/grafana/grafana/pkg/services/authz/proto/v1"
|
||||
"github.com/grafana/grafana/pkg/services/authz/rbac/store"
|
||||
"github.com/grafana/grafana/pkg/storage/legacysql"
|
||||
)
|
||||
@@ -38,7 +37,6 @@ const (
|
||||
|
||||
type Service struct {
|
||||
authzv1.UnimplementedAuthzServiceServer
|
||||
authzextv1.UnimplementedAuthzExtentionServiceServer
|
||||
|
||||
store store.Store
|
||||
folderStore store.FolderStore
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package authz
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/authlib/authn"
|
||||
)
|
||||
|
||||
func newGRPCTokenAuth(audience, namespace string, tc authn.TokenExchanger) *tokenAuth {
|
||||
return &tokenAuth{audience, namespace, tc}
|
||||
}
|
||||
|
||||
type tokenAuth struct {
|
||||
audience string
|
||||
namespace string
|
||||
tokenClient authn.TokenExchanger
|
||||
}
|
||||
|
||||
func (t *tokenAuth) GetRequestMetadata(ctx context.Context, _ ...string) (map[string]string, error) {
|
||||
token, err := t.tokenClient.Exchange(ctx, authn.TokenExchangeRequest{
|
||||
Namespace: t.namespace,
|
||||
Audiences: []string{t.audience},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return map[string]string{authn.DefaultAccessTokenMetadataKey: token.Token}, nil
|
||||
}
|
||||
|
||||
func (t *tokenAuth) RequireTransportSecurity() bool { return false }
|
||||
@@ -53,18 +53,13 @@ func ProvideZanzana(cfg *setting.Cfg, db db.DB, features featuremgmt.FeatureTogg
|
||||
if cfg.StackID == "" {
|
||||
return nil, fmt.Errorf("missing stack ID")
|
||||
}
|
||||
namespace := fmt.Sprintf("stacks-%s", cfg.StackID)
|
||||
|
||||
tokenAuthCred := &tokenAuth{
|
||||
cfg: cfg,
|
||||
namespace: namespace,
|
||||
tokenClient: tokenClient,
|
||||
}
|
||||
|
||||
dialOptions := []grpc.DialOption{
|
||||
// TODO: add TLS support
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
grpc.WithPerRPCCredentials(tokenAuthCred),
|
||||
grpc.WithPerRPCCredentials(
|
||||
newGRPCTokenAuth(authzServiceAudience, fmt.Sprintf("stacks-%s", cfg.StackID), tokenClient),
|
||||
),
|
||||
}
|
||||
|
||||
conn, err := grpc.NewClient(cfg.ZanzanaClient.Addr, dialOptions...)
|
||||
@@ -244,27 +239,3 @@ func (z *Zanzana) stopping(err error) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type tokenAuth struct {
|
||||
cfg *setting.Cfg
|
||||
namespace string
|
||||
tokenClient *authnlib.TokenExchangeClient
|
||||
}
|
||||
|
||||
func (t *tokenAuth) GetRequestMetadata(ctx context.Context, _ ...string) (map[string]string, error) {
|
||||
token, err := t.tokenClient.Exchange(ctx, authnlib.TokenExchangeRequest{
|
||||
Namespace: t.namespace,
|
||||
Audiences: []string{authzServiceAudience},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return map[string]string{
|
||||
authnlib.DefaultAccessTokenMetadataKey: token.Token,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (t *tokenAuth) RequireTransportSecurity() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ require (
|
||||
github.com/gorilla/mux v1.8.1 // indirect
|
||||
github.com/gorilla/websocket v1.5.3 // indirect
|
||||
github.com/grafana/alerting v0.0.0-20250207161551-04c87cf39038 // indirect
|
||||
github.com/grafana/authlib v0.0.0-20250206063954-bf4600a17569 // indirect
|
||||
github.com/grafana/authlib v0.0.0-20250217135712-106ec5baf6bc // indirect
|
||||
github.com/grafana/dataplane/sdata v0.0.9 // indirect
|
||||
github.com/grafana/dskit v0.0.0-20241105154643-a6b453a88040 // indirect
|
||||
github.com/grafana/grafana-app-sdk/logging v0.30.0 // indirect
|
||||
|
||||
@@ -568,8 +568,8 @@ github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aN
|
||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grafana/alerting v0.0.0-20250207161551-04c87cf39038 h1:dG/UKAjY/KlKp9fY8aEm+gSQHHRmPm5q+9cea3hRSu8=
|
||||
github.com/grafana/alerting v0.0.0-20250207161551-04c87cf39038/go.mod h1:QsnoKX/iYZxA4Cv+H+wC7uxutBD8qi8ZW5UJvD2TYmU=
|
||||
github.com/grafana/authlib v0.0.0-20250206063954-bf4600a17569 h1:bQw6fdcxVdZ6xmZVhMtRgGEKIT1Zc6y+i1PWF8tMX4Q=
|
||||
github.com/grafana/authlib v0.0.0-20250206063954-bf4600a17569/go.mod h1:/gYfphsNu9v1qYWXxpv1NSvMEMSwvdf8qb8YlgwIRl8=
|
||||
github.com/grafana/authlib v0.0.0-20250217135712-106ec5baf6bc h1:qx8avmRi3wx+SuAn6UV0pKma1fJ0/4POUYNc+2rxZkg=
|
||||
github.com/grafana/authlib v0.0.0-20250217135712-106ec5baf6bc/go.mod h1:HamgITzYqErFp8qLwYM/JwwE3z6fXft0Z+5n0Dx1rUM=
|
||||
github.com/grafana/authlib/types v0.0.0-20250120145936-5f0e28e7a87c h1:b0sPDtt33uFdmvUJjSCld3kwE2E49dUvevuUDSJsEuo=
|
||||
github.com/grafana/authlib/types v0.0.0-20250120145936-5f0e28e7a87c/go.mod h1:qYjSd1tmJiuVoSICp7Py9/zD54O9uQQA3wuM6Gg4DFM=
|
||||
github.com/grafana/dataplane/examples v0.0.1 h1:K9M5glueWyLoL4//H+EtTQq16lXuHLmOhb6DjSCahzA=
|
||||
|
||||
@@ -11,7 +11,7 @@ replace (
|
||||
require (
|
||||
github.com/fullstorydev/grpchan v1.1.1
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/grafana/authlib v0.0.0-20250206063954-bf4600a17569
|
||||
github.com/grafana/authlib v0.0.0-20250217135712-106ec5baf6bc
|
||||
github.com/grafana/authlib/types v0.0.0-20250120145936-5f0e28e7a87c
|
||||
github.com/grafana/dskit v0.0.0-20241105154643-a6b453a88040
|
||||
github.com/grafana/grafana v11.4.0-00010101000000-000000000000+incompatible
|
||||
|
||||
@@ -399,8 +399,8 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||
github.com/grafana/alerting v0.0.0-20250207161551-04c87cf39038 h1:dG/UKAjY/KlKp9fY8aEm+gSQHHRmPm5q+9cea3hRSu8=
|
||||
github.com/grafana/alerting v0.0.0-20250207161551-04c87cf39038/go.mod h1:QsnoKX/iYZxA4Cv+H+wC7uxutBD8qi8ZW5UJvD2TYmU=
|
||||
github.com/grafana/authlib v0.0.0-20250206063954-bf4600a17569 h1:bQw6fdcxVdZ6xmZVhMtRgGEKIT1Zc6y+i1PWF8tMX4Q=
|
||||
github.com/grafana/authlib v0.0.0-20250206063954-bf4600a17569/go.mod h1:/gYfphsNu9v1qYWXxpv1NSvMEMSwvdf8qb8YlgwIRl8=
|
||||
github.com/grafana/authlib v0.0.0-20250217135712-106ec5baf6bc h1:qx8avmRi3wx+SuAn6UV0pKma1fJ0/4POUYNc+2rxZkg=
|
||||
github.com/grafana/authlib v0.0.0-20250217135712-106ec5baf6bc/go.mod h1:HamgITzYqErFp8qLwYM/JwwE3z6fXft0Z+5n0Dx1rUM=
|
||||
github.com/grafana/authlib/types v0.0.0-20250120145936-5f0e28e7a87c h1:b0sPDtt33uFdmvUJjSCld3kwE2E49dUvevuUDSJsEuo=
|
||||
github.com/grafana/authlib/types v0.0.0-20250120145936-5f0e28e7a87c/go.mod h1:qYjSd1tmJiuVoSICp7Py9/zD54O9uQQA3wuM6Gg4DFM=
|
||||
github.com/grafana/dataplane/sdata v0.0.9 h1:AGL1LZnCUG4MnQtnWpBPbQ8ZpptaZs14w6kE/MWfg7s=
|
||||
|
||||
Reference in New Issue
Block a user