mirror of
https://github.com/grafana/grafana.git
synced 2024-11-22 08:56:43 -06:00
AuthZ: Refactor authentication modes for the Authz package (#95120)
* AuthZ: Fix authentication modes for the Authz package Co-Authored-By: Claudiu Dragalina-Paraipan <drclau@users.noreply.github.com>
This commit is contained in:
parent
229658ad83
commit
0704ae734f
@ -38,14 +38,33 @@ Here is an example to connect the authorization client to a remote grpc server.
|
||||
```ini
|
||||
[authorization]
|
||||
remote_address = "server.example.org:10000"
|
||||
listen = false
|
||||
mode = "grpc"
|
||||
```
|
||||
|
||||
Here is an example to register the authorization service on the Grafana GRPC server and connect the client to it through grpc
|
||||
Here is an example to register the authorization service on the Grafana GRPC server and connect the client to it through grpc.
|
||||
|
||||
```ini
|
||||
app_mode = development
|
||||
|
||||
[authorization]
|
||||
remote_address = "localhost:10000"
|
||||
listen = true
|
||||
mode = "grpc"
|
||||
```
|
||||
|
||||
Here is an example to connect the authorization client to a remote grpc server and use access token authentication.
|
||||
```ini
|
||||
[environment]
|
||||
stack_id = 11
|
||||
|
||||
[authorization]
|
||||
remote_address = "server.example.org:10000"
|
||||
mode = "grpc"
|
||||
listen = false
|
||||
|
||||
[grpc_client_authentication]
|
||||
token = "ReplaceWithToken"
|
||||
token_exchange_url = "signing-server.example.org/path/to/signing"
|
||||
token_namespace = "stacks-11"
|
||||
```
|
@ -55,14 +55,16 @@ func ProvideAuthZClient(
|
||||
return nil, err
|
||||
}
|
||||
case ModeGRPC:
|
||||
client, err = newGrpcLegacyClient(authCfg.remoteAddress)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case ModeCloud:
|
||||
client, err = newCloudLegacyClient(authCfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if cfg.StackID == "" {
|
||||
client, err = newGrpcLegacyClient(authCfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
client, err = newCloudLegacyClient(authCfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,7 +85,7 @@ func ProvideStandaloneAuthZClient(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return newGrpcLegacyClient(authCfg.remoteAddress)
|
||||
return newGrpcLegacyClient(authCfg)
|
||||
}
|
||||
|
||||
func newInProcLegacyClient(server *legacyServer) (authzlib.AccessChecker, error) {
|
||||
@ -108,25 +110,20 @@ func newInProcLegacyClient(server *legacyServer) (authzlib.AccessChecker, error)
|
||||
)
|
||||
}
|
||||
|
||||
func newGrpcLegacyClient(address string) (authzlib.AccessChecker, error) {
|
||||
func newGrpcLegacyClient(authCfg *Cfg) (authzlib.AccessChecker, error) {
|
||||
// This client interceptor is a noop, as we don't send an access token
|
||||
grpcClientConfig := authnlib.GrpcClientConfig{}
|
||||
clientInterceptor, err := authnlib.NewGrpcClientInterceptor(&grpcClientConfig,
|
||||
authnlib.WithDisableAccessTokenOption(),
|
||||
)
|
||||
clientConfig := authnlib.GrpcClientConfig{}
|
||||
clientInterceptor, err := authnlib.NewGrpcClientInterceptor(&clientConfig, authnlib.WithDisableAccessTokenOption())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cfg := authzlib.ClientConfig{RemoteAddress: address}
|
||||
cfg := authzlib.ClientConfig{RemoteAddress: authCfg.remoteAddress}
|
||||
client, err := authzlib.NewClient(&cfg,
|
||||
// TODO(drclau): make this configurable (e.g. allow to use insecure connections)
|
||||
authzlib.WithGrpcDialOptionsClientOption(
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
grpc.WithUnaryInterceptor(clientInterceptor.UnaryClientInterceptor),
|
||||
grpc.WithStreamInterceptor(clientInterceptor.StreamClientInterceptor),
|
||||
getDialOpts(clientInterceptor, authCfg.allowInsecure)...,
|
||||
),
|
||||
// TODO(drclau): remove this once we have access token support on-prem
|
||||
// TODO: remove this once access tokens are supported on-prem
|
||||
authzlib.WithDisableAccessTokenClientOption(),
|
||||
)
|
||||
if err != nil {
|
||||
@ -155,11 +152,8 @@ func newCloudLegacyClient(authCfg *Cfg) (authzlib.AccessChecker, error) {
|
||||
|
||||
clientCfg := authzlib.ClientConfig{RemoteAddress: authCfg.remoteAddress}
|
||||
client, err := authzlib.NewClient(&clientCfg,
|
||||
// TODO(drclau): make this configurable (e.g. allow to use insecure connections)
|
||||
authzlib.WithGrpcDialOptionsClientOption(
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
grpc.WithUnaryInterceptor(clientInterceptor.UnaryClientInterceptor),
|
||||
grpc.WithStreamInterceptor(clientInterceptor.StreamClientInterceptor),
|
||||
getDialOpts(clientInterceptor, authCfg.allowInsecure)...,
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
@ -168,3 +162,16 @@ func newCloudLegacyClient(authCfg *Cfg) (authzlib.AccessChecker, error) {
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func getDialOpts(interceptor *authnlib.GrpcClientInterceptor, allowInsecure bool) []grpc.DialOption {
|
||||
dialOpts := []grpc.DialOption{
|
||||
grpc.WithUnaryInterceptor(interceptor.UnaryClientInterceptor),
|
||||
grpc.WithStreamInterceptor(interceptor.StreamClientInterceptor),
|
||||
}
|
||||
if allowInsecure {
|
||||
// allow insecure connections in development mode to facilitate testing
|
||||
dialOpts = append(dialOpts, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
}
|
||||
|
||||
return dialOpts
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ type Mode string
|
||||
|
||||
func (s Mode) IsValid() bool {
|
||||
switch s {
|
||||
case ModeGRPC, ModeInProc, ModeCloud:
|
||||
case ModeGRPC, ModeInProc:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@ -19,7 +19,6 @@ func (s Mode) IsValid() bool {
|
||||
const (
|
||||
ModeGRPC Mode = "grpc"
|
||||
ModeInProc Mode = "inproc"
|
||||
ModeCloud Mode = "cloud"
|
||||
)
|
||||
|
||||
type Cfg struct {
|
||||
@ -30,30 +29,37 @@ type Cfg struct {
|
||||
token string
|
||||
tokenExchangeURL string
|
||||
tokenNamespace string
|
||||
|
||||
allowInsecure bool
|
||||
}
|
||||
|
||||
func ReadCfg(cfg *setting.Cfg) (*Cfg, error) {
|
||||
section := cfg.SectionWithEnvOverrides("authorization")
|
||||
authzSection := cfg.SectionWithEnvOverrides("authorization")
|
||||
grpcClientAuthSection := cfg.SectionWithEnvOverrides("grpc_client_authentication")
|
||||
|
||||
mode := Mode(section.Key("mode").MustString(string(ModeInProc)))
|
||||
mode := Mode(authzSection.Key("mode").MustString(string(ModeInProc)))
|
||||
if !mode.IsValid() {
|
||||
return nil, fmt.Errorf("authorization: invalid mode %q", mode)
|
||||
}
|
||||
|
||||
token := section.Key("token").MustString("")
|
||||
tokenExchangeURL := section.Key("token_exchange_url").MustString("")
|
||||
tokenNamespace := section.Key("token_namespace").MustString("stack-" + cfg.StackID)
|
||||
token := grpcClientAuthSection.Key("token").MustString("")
|
||||
tokenExchangeURL := grpcClientAuthSection.Key("token_exchange_url").MustString("")
|
||||
tokenNamespace := grpcClientAuthSection.Key("token_namespace").MustString("stacks-" + cfg.StackID)
|
||||
|
||||
if mode == ModeCloud && token == "" && tokenExchangeURL == "" {
|
||||
return nil, fmt.Errorf("authorization: missing token or tokenExchangeUrl")
|
||||
// When running in cloud mode, the token and tokenExchangeURL are required.
|
||||
if mode == ModeGRPC && cfg.StackID != "" {
|
||||
if token == "" || tokenExchangeURL == "" {
|
||||
return nil, fmt.Errorf("authorization: missing token or tokenExchangeUrl")
|
||||
}
|
||||
}
|
||||
|
||||
return &Cfg{
|
||||
remoteAddress: section.Key("remote_address").MustString(""),
|
||||
listen: section.Key("listen").MustBool(false),
|
||||
remoteAddress: authzSection.Key("remote_address").MustString(""),
|
||||
listen: authzSection.Key("listen").MustBool(false),
|
||||
mode: mode,
|
||||
token: token,
|
||||
tokenExchangeURL: tokenExchangeURL,
|
||||
tokenNamespace: tokenNamespace,
|
||||
allowInsecure: cfg.Env == setting.Dev,
|
||||
}, nil
|
||||
}
|
||||
|
@ -4,7 +4,9 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/grafana/authlib/authz"
|
||||
authzv1 "github.com/grafana/authlib/authz/proto/v1"
|
||||
grpc_auth "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/auth"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
@ -14,6 +16,8 @@ import (
|
||||
)
|
||||
|
||||
var _ authzv1.AuthzServiceServer = (*legacyServer)(nil)
|
||||
var _ grpc_auth.ServiceAuthFuncOverride = (*legacyServer)(nil)
|
||||
var _ authz.ServiceAuthorizeFuncOverride = (*legacyServer)(nil)
|
||||
|
||||
func newLegacyServer(
|
||||
acSvc accesscontrol.Service, features featuremgmt.FeatureToggles,
|
||||
@ -23,17 +27,21 @@ func newLegacyServer(
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
s := &legacyServer{
|
||||
l := &legacyServer{
|
||||
acSvc: acSvc,
|
||||
logger: log.New("authz-grpc-server"),
|
||||
tracer: tracer,
|
||||
}
|
||||
|
||||
if cfg.listen {
|
||||
grpcServer.GetServer().RegisterService(&authzv1.AuthzService_ServiceDesc, s)
|
||||
if !cfg.allowInsecure {
|
||||
l.logger.Error("Not allowing the authz service to run in insecure mode as Auth is skipped")
|
||||
} else {
|
||||
grpcServer.GetServer().RegisterService(&authzv1.AuthzService_ServiceDesc, l)
|
||||
}
|
||||
}
|
||||
|
||||
return s, nil
|
||||
return l, nil
|
||||
}
|
||||
|
||||
type legacyServer struct {
|
||||
@ -44,6 +52,24 @@ type legacyServer struct {
|
||||
tracer tracing.Tracer
|
||||
}
|
||||
|
||||
// AuthFuncOverride is a function that allows to override the default auth function.
|
||||
// This is ok for now since we don't have on-prem access token support.
|
||||
func (l *legacyServer) AuthFuncOverride(ctx context.Context, _ string) (context.Context, error) {
|
||||
ctx, span := l.tracer.Start(ctx, "authz.AuthFuncOverride")
|
||||
defer span.End()
|
||||
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
// AuthorizeFuncOverride is a function that allows to override the default authorize function that checks the namespace of the caller.
|
||||
// This is ok for now since we don't have on-prem access token support.
|
||||
func (l *legacyServer) AuthorizeFuncOverride(ctx context.Context) error {
|
||||
_, span := l.tracer.Start(ctx, "authz.AuthorizeFuncOverride")
|
||||
defer span.End()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *legacyServer) Check(context.Context, *authzv1.CheckRequest) (*authzv1.CheckResponse, error) {
|
||||
// FIXME: implement for legacy access control
|
||||
return nil, errors.New("unimplemented")
|
||||
|
Loading…
Reference in New Issue
Block a user