mirror of
https://github.com/grafana/grafana.git
synced 2025-02-10 23:55:47 -06:00
AuthZ: GRPC client init and config options (#89161)
This commit is contained in:
parent
3776c44c33
commit
5f83fdef2c
@ -1,3 +1,51 @@
|
||||
# Authorization
|
||||
|
||||
This package contains the authorization server implementation.
|
||||
|
||||
## Feature toggles
|
||||
|
||||
The following feature toggles need to be activated:
|
||||
|
||||
```ini
|
||||
[feature_toggles]
|
||||
authZGRPCServer = true
|
||||
grpcServer = true
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
To configure the authorization server and client, use the "authorization" section of the configuration ini file.
|
||||
|
||||
The `remote_address` setting, specifies the address where the authorization server is located (ex: `server.example.org:10000`).
|
||||
|
||||
The `mode` setting can be set to either `grpc` or `inproc`. When set to `grpc`, the client will connect to the specified address. When set to `inproc` the client will use inprocgrpc (relying on go channels) to wrap a local instantiation of the server.
|
||||
|
||||
The `listen` setting determines whether the authorization server should listen for incoming requests. When set to `true`, the authorization service will be registered to the Grafana GRPC server.
|
||||
|
||||
The default configuration does not register the authorization service on the Grafana GRPC server and binds the client to it `inproc`:
|
||||
|
||||
```ini
|
||||
[authorization]
|
||||
remote_address = ""
|
||||
listen = false
|
||||
mode = "inproc"
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
Here is an example to connect the authorization client to a remote grpc server.
|
||||
|
||||
```ini
|
||||
[authorization]
|
||||
remote_address = "server.example.org:10000"
|
||||
mode = "grpc"
|
||||
```
|
||||
|
||||
Here is an example to register the authorization service on the Grafana GRPC server and connect the client to it through grpc
|
||||
|
||||
```ini
|
||||
[authorization]
|
||||
remote_address = "localhost:10000"
|
||||
listen = true
|
||||
mode = "grpc"
|
||||
```
|
||||
|
@ -1,10 +1,21 @@
|
||||
package authz
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/fullstorydev/grpchan"
|
||||
"github.com/fullstorydev/grpchan/inprocgrpc"
|
||||
grpcAuth "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/auth"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
|
||||
authzv1 "github.com/grafana/authlib/authz/proto/v1"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/grpcserver"
|
||||
grpcUtils "github.com/grafana/grafana/pkg/services/store/entity/grpc"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
@ -13,8 +24,10 @@ type Client interface {
|
||||
}
|
||||
|
||||
type LegacyClient struct {
|
||||
clientV1 authzv1.AuthzServiceClient
|
||||
}
|
||||
|
||||
// ProvideAuthZClient provides an AuthZ client and creates the AuthZ service.
|
||||
func ProvideAuthZClient(
|
||||
cfg *setting.Cfg, features featuremgmt.FeatureToggles, acSvc accesscontrol.Service,
|
||||
grpcServer grpcserver.Provider, tracer tracing.Tracer,
|
||||
@ -23,11 +36,90 @@ func ProvideAuthZClient(
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
_, err := newLegacyServer(acSvc, features, grpcServer, tracer)
|
||||
authCfg, err := ReadCfg(cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO differentiate run local from run remote grpc
|
||||
return &LegacyClient{}, nil
|
||||
var client *LegacyClient
|
||||
|
||||
// Register the server
|
||||
server, err := newLegacyServer(acSvc, features, grpcServer, tracer, authCfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch authCfg.mode {
|
||||
case ModeInProc:
|
||||
client = newInProcLegacyClient(server)
|
||||
case ModeGRPC:
|
||||
client, err = newGrpcLegacyClient(authCfg.remoteAddress)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return client, err
|
||||
}
|
||||
|
||||
// ProvideStandaloneAuthZClient provides a standalone AuthZ client, without registering the AuthZ service.
|
||||
// You need to provide a remote address in the configuration
|
||||
func ProvideStandaloneAuthZClient(
|
||||
cfg *setting.Cfg, features featuremgmt.FeatureToggles, tracer tracing.Tracer,
|
||||
) (Client, error) {
|
||||
if !features.IsEnabledGlobally(featuremgmt.FlagAuthZGRPCServer) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
authCfg, err := ReadCfg(cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return newGrpcLegacyClient(authCfg.remoteAddress)
|
||||
}
|
||||
|
||||
func newInProcLegacyClient(server *legacyServer) *LegacyClient {
|
||||
channel := &inprocgrpc.Channel{}
|
||||
|
||||
// TODO (gamab): change this once it's clear how to authenticate the client
|
||||
// Choices are:
|
||||
// - noAuth given it's in proc and we don't need the user
|
||||
// - access_token verif only as it's consistent with when it's remote (we check the service is allowed to call the authz service)
|
||||
// - access_token and id_token ? the id_token being only necessary when the user is trying to access the service straight away
|
||||
// auth := grpcUtils.ProvideAuthenticator(cfg)
|
||||
noAuth := func(ctx context.Context) (context.Context, error) {
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
channel.RegisterService(
|
||||
grpchan.InterceptServer(
|
||||
&authzv1.AuthzService_ServiceDesc,
|
||||
grpcAuth.UnaryServerInterceptor(noAuth),
|
||||
grpcAuth.StreamServerInterceptor(noAuth),
|
||||
),
|
||||
server,
|
||||
)
|
||||
|
||||
conn := grpchan.InterceptClientConn(channel, grpcUtils.UnaryClientInterceptor, grpcUtils.StreamClientInterceptor)
|
||||
|
||||
client := authzv1.NewAuthzServiceClient(conn)
|
||||
|
||||
return &LegacyClient{
|
||||
clientV1: client,
|
||||
}
|
||||
}
|
||||
|
||||
func newGrpcLegacyClient(address string) (*LegacyClient, error) {
|
||||
// Create a connection to the gRPC server
|
||||
conn, err := grpc.NewClient(address, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client := authzv1.NewAuthzServiceClient(conn)
|
||||
|
||||
return &LegacyClient{
|
||||
clientV1: client,
|
||||
}, nil
|
||||
}
|
||||
|
43
pkg/services/authz/config.go
Normal file
43
pkg/services/authz/config.go
Normal file
@ -0,0 +1,43 @@
|
||||
package authz
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
type Mode string
|
||||
|
||||
func (s Mode) IsValid() bool {
|
||||
switch s {
|
||||
case ModeGRPC, ModeInProc:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
const (
|
||||
ModeGRPC Mode = "grpc"
|
||||
ModeInProc Mode = "inproc"
|
||||
)
|
||||
|
||||
type Cfg struct {
|
||||
remoteAddress string
|
||||
listen bool
|
||||
mode Mode
|
||||
}
|
||||
|
||||
func ReadCfg(cfg *setting.Cfg) (*Cfg, error) {
|
||||
section := cfg.SectionWithEnvOverrides("authorization")
|
||||
|
||||
mode := Mode(section.Key("mode").MustString(string(ModeInProc)))
|
||||
if !mode.IsValid() {
|
||||
return nil, fmt.Errorf("authorization: invalid mode %q", mode)
|
||||
}
|
||||
|
||||
return &Cfg{
|
||||
remoteAddress: section.Key("remote_address").MustString(""),
|
||||
listen: section.Key("listen").MustBool(false),
|
||||
mode: mode,
|
||||
}, nil
|
||||
}
|
@ -24,7 +24,7 @@ type legacyServer struct {
|
||||
|
||||
func newLegacyServer(
|
||||
acSvc accesscontrol.Service, features featuremgmt.FeatureToggles,
|
||||
grpcServer grpcserver.Provider, tracer tracing.Tracer,
|
||||
grpcServer grpcserver.Provider, tracer tracing.Tracer, cfg *Cfg,
|
||||
) (*legacyServer, error) {
|
||||
if !features.IsEnabledGlobally(featuremgmt.FlagAuthZGRPCServer) {
|
||||
return nil, nil
|
||||
@ -36,7 +36,9 @@ func newLegacyServer(
|
||||
tracer: tracer,
|
||||
}
|
||||
|
||||
grpcServer.GetServer().RegisterService(&authzv1.AuthzService_ServiceDesc, s)
|
||||
if cfg.listen {
|
||||
grpcServer.GetServer().RegisterService(&authzv1.AuthzService_ServiceDesc, s)
|
||||
}
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user