mirror of
https://github.com/grafana/grafana.git
synced 2024-11-26 02:40:26 -06:00
authn: client side updates
Co-Authored-By: Gabriel MABILLE <gamab@users.noreply.github.com>
This commit is contained in:
parent
2e2ddc5c42
commit
92aba937a9
@ -288,7 +288,10 @@ func (s *service) start(ctx context.Context) error {
|
||||
}
|
||||
|
||||
// Create a client instance
|
||||
client := resource.NewResourceStoreClientGRPC(conn)
|
||||
client, err := resource.NewResourceStoreClientGRPC(conn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
serverConfig.Config.RESTOptionsGetter = apistore.NewRESTOptionsGetterForClient(client, o.RecommendedOptions.Etcd.StorageConfig)
|
||||
|
||||
case grafanaapiserveroptions.StorageTypeLegacy:
|
||||
|
21
pkg/services/authn/grpcutils/config.go
Normal file
21
pkg/services/authn/grpcutils/config.go
Normal file
@ -0,0 +1,21 @@
|
||||
package grpcutils
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
type GrpcClientConfig struct {
|
||||
Token string
|
||||
TokenExchangeURL string
|
||||
TokenNamespace string
|
||||
}
|
||||
|
||||
func ReadCfg(cfg *setting.Cfg) *GrpcClientConfig {
|
||||
section := cfg.SectionWithEnvOverrides("grpc_client_authentication")
|
||||
|
||||
return &GrpcClientConfig{
|
||||
Token: section.Key("token").MustString(""),
|
||||
TokenExchangeURL: section.Key("token_exchange_url").MustString(""),
|
||||
TokenNamespace: section.Key("token_namespace").MustString("stack-" + cfg.StackID),
|
||||
}
|
||||
}
|
@ -1,18 +1,29 @@
|
||||
package resource
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/fullstorydev/grpchan"
|
||||
"github.com/fullstorydev/grpchan/inprocgrpc"
|
||||
authnlib "github.com/grafana/authlib/authn"
|
||||
authzlib "github.com/grafana/authlib/authz"
|
||||
grpcAuth "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/auth"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||
"github.com/grafana/grafana/pkg/services/authn/grpcutils"
|
||||
grpcUtils "github.com/grafana/grafana/pkg/storage/unified/resource/grpc"
|
||||
)
|
||||
|
||||
// TODO: decide on the audience for the resource store
|
||||
const resourceStoreAudience = "resourceStore"
|
||||
|
||||
func NewLocalResourceStoreClient(server ResourceStoreServer) ResourceStoreClient {
|
||||
// scenario: local in-proc
|
||||
channel := &inprocgrpc.Channel{}
|
||||
|
||||
auth := &grpcUtils.Authenticator{}
|
||||
auth := &grpcUtils.InProcAuthenticator{}
|
||||
|
||||
channel.RegisterService(
|
||||
grpchan.InterceptServer(
|
||||
@ -25,6 +36,72 @@ func NewLocalResourceStoreClient(server ResourceStoreServer) ResourceStoreClient
|
||||
return NewResourceStoreClient(grpchan.InterceptClientConn(channel, grpcUtils.UnaryClientInterceptor, grpcUtils.StreamClientInterceptor))
|
||||
}
|
||||
|
||||
func NewResourceStoreClientGRPC(channel *grpc.ClientConn) ResourceStoreClient {
|
||||
return NewResourceStoreClient(grpchan.InterceptClientConn(channel, grpcUtils.UnaryClientInterceptor, grpcUtils.StreamClientInterceptor))
|
||||
func NewResourceStoreClientGRPC(conn *grpc.ClientConn) (ResourceStoreClient, error) {
|
||||
// scenario: remote on-prem
|
||||
clientInterceptor, err := authnlib.NewGrpcClientInterceptor(
|
||||
&authnlib.GrpcClientConfig{},
|
||||
authnlib.WithDisableAccessTokenOption(),
|
||||
authnlib.WithIDTokenExtractorOption(idTokenExtractor),
|
||||
authnlib.WithMetadataExtractorOption(orgIdExtractor),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewResourceStoreClient(
|
||||
grpchan.InterceptClientConn(
|
||||
conn,
|
||||
clientInterceptor.UnaryClientInterceptor,
|
||||
clientInterceptor.StreamClientInterceptor,
|
||||
)),
|
||||
nil
|
||||
}
|
||||
|
||||
func NewResourceStoreClientCloud(conn *grpc.ClientConn, cfg *grpcutils.GrpcClientConfig) (ResourceStoreClient, error) {
|
||||
// scenario: remote cloud
|
||||
grpcClientConfig := authnlib.GrpcClientConfig{
|
||||
TokenClientConfig: &authnlib.TokenExchangeConfig{
|
||||
Token: cfg.Token,
|
||||
TokenExchangeURL: cfg.TokenExchangeURL,
|
||||
},
|
||||
TokenRequest: &authnlib.TokenExchangeRequest{
|
||||
Namespace: cfg.TokenNamespace,
|
||||
Audiences: []string{resourceStoreAudience},
|
||||
},
|
||||
}
|
||||
|
||||
clientInterceptor, err := authnlib.NewGrpcClientInterceptor(
|
||||
&grpcClientConfig,
|
||||
authnlib.WithIDTokenExtractorOption(idTokenExtractor),
|
||||
authnlib.WithMetadataExtractorOption(orgIdExtractor),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewResourceStoreClient(
|
||||
grpchan.InterceptClientConn(
|
||||
conn,
|
||||
clientInterceptor.UnaryClientInterceptor,
|
||||
clientInterceptor.StreamClientInterceptor,
|
||||
)),
|
||||
nil
|
||||
}
|
||||
|
||||
func idTokenExtractor(ctx context.Context) (string, error) {
|
||||
requester, err := identity.GetRequester(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return requester.GetIDToken(), nil
|
||||
}
|
||||
|
||||
func orgIdExtractor(ctx context.Context) (key string, values []string, err error) {
|
||||
requester, err := identity.GetRequester(ctx)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
return authzlib.DefaultStackIDMetadataKey, []string{fmt.Sprintf("%d", requester.GetOrgID())}, nil
|
||||
}
|
||||
|
27
pkg/storage/unified/resource/grpc/inproc-authenticator.go
Normal file
27
pkg/storage/unified/resource/grpc/inproc-authenticator.go
Normal file
@ -0,0 +1,27 @@
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
authnlib "github.com/grafana/authlib/authn"
|
||||
|
||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||
)
|
||||
|
||||
type InProcAuthenticator struct{}
|
||||
|
||||
func (f *InProcAuthenticator) Authenticate(ctx context.Context) (context.Context, error) {
|
||||
r, err := identity.GetRequester(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
idClaims := r.GetIDClaims()
|
||||
if idClaims == nil {
|
||||
return nil, fmt.Errorf("no id claims found")
|
||||
}
|
||||
|
||||
callerAuthInfo := authnlib.CallerAuthInfo{IDTokenClaims: idClaims}
|
||||
return authnlib.AddCallerAuthInfoToContext(ctx, callerAuthInfo), nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user