Authz: Only have two modes for authz client (#100803)

* Only have "inproc" and "clod" mode
This commit is contained in:
Karl Persson
2025-02-17 14:37:25 +01:00
committed by GitHub
parent 8edfff1bba
commit e9b2f69137
3 changed files with 71 additions and 119 deletions

View File

@@ -1,66 +0,0 @@
package authz
import (
"fmt"
"github.com/grafana/grafana/pkg/setting"
)
type Mode string
func (s Mode) IsValid() bool {
switch s {
case ModeGRPC, ModeInProc, ModeCloud:
return true
}
return false
}
const (
ModeCloud Mode = "cloud"
ModeGRPC Mode = "grpc"
ModeInProc Mode = "inproc"
)
type Cfg struct {
remoteAddress string
listen bool
mode Mode
token string
tokenExchangeURL string
tokenNamespace string
allowInsecure bool
}
func ReadCfg(cfg *setting.Cfg) (*Cfg, error) {
authzSection := cfg.SectionWithEnvOverrides("authorization")
grpcClientAuthSection := cfg.SectionWithEnvOverrides("grpc_client_authentication")
mode := Mode(authzSection.Key("mode").MustString(string(ModeInProc)))
if !mode.IsValid() {
return nil, fmt.Errorf("authorization: invalid mode %q", mode)
}
token := grpcClientAuthSection.Key("token").MustString("")
tokenExchangeURL := grpcClientAuthSection.Key("token_exchange_url").MustString("")
tokenNamespace := grpcClientAuthSection.Key("token_namespace").MustString("stacks-" + cfg.StackID)
// When running in cloud mode, the token and tokenExchangeURL are required.
if mode == ModeCloud {
if token == "" || tokenExchangeURL == "" {
return nil, fmt.Errorf("authorization: missing token or tokenExchangeUrl")
}
}
return &Cfg{
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
}

View File

@@ -48,21 +48,18 @@ func ProvideAuthZClient(
db db.DB,
acService accesscontrol.Service,
) (authlib.AccessClient, error) {
authCfg, err := ReadCfg(cfg)
authCfg, err := readAuthzClientSettings(cfg)
if err != nil {
return nil, err
}
isRemoteServer := authCfg.mode == ModeCloud || authCfg.mode == ModeGRPC
if !features.IsEnabledGlobally(featuremgmt.FlagAuthZGRPCServer) && isRemoteServer {
if !features.IsEnabledGlobally(featuremgmt.FlagAuthZGRPCServer) && authCfg.mode == clientModeCloud {
return nil, errors.New("authZGRPCServer feature toggle is required for cloud and grpc mode")
}
switch authCfg.mode {
case ModeGRPC:
return newGrpcLegacyClient(authCfg, tracer)
case ModeCloud:
return newCloudLegacyClient(authCfg, tracer)
case clientModeCloud:
return newRemoteLegacyClient(authCfg, tracer)
default:
sql := legacysql.NewDatabaseProvider(db)
@@ -96,15 +93,12 @@ func ProvideStandaloneAuthZClient(
return nil, nil
}
authCfg, err := ReadCfg(cfg)
authCfg, err := readAuthzClientSettings(cfg)
if err != nil {
return nil, err
}
if authCfg.mode == ModeGRPC {
return newGrpcLegacyClient(authCfg, tracer)
}
return newCloudLegacyClient(authCfg, tracer)
return newRemoteLegacyClient(authCfg, tracer)
}
func newInProcLegacyClient(server *rbac.Service, tracer tracing.Tracer) (authlib.AccessClient, error) {
@@ -131,7 +125,6 @@ func newInProcLegacyClient(server *rbac.Service, tracer tracing.Tracer) (authlib
return authzlib.NewClient(
&authzlib.ClientConfig{},
authzlib.WithGrpcConnectionClientOption(channel),
authzlib.WithDisableAccessTokenClientOption(),
authzlib.WithTracerClientOption(tracer),
authzlib.WithCacheClientOption(cache.NewLocalCache(cache.Config{
Expiry: 30 * time.Second,
@@ -140,48 +133,14 @@ func newInProcLegacyClient(server *rbac.Service, tracer tracing.Tracer) (authlib
)
}
func newGrpcLegacyClient(authCfg *Cfg, tracer tracing.Tracer) (authlib.AccessClient, error) {
// This client interceptor is a noop, as we don't send an access token
clientConfig := authnlib.GrpcClientConfig{}
clientInterceptor, err := authnlib.NewGrpcClientInterceptor(
&clientConfig,
authnlib.WithDisableAccessTokenOption(),
authnlib.WithTracerOption(tracer),
)
if err != nil {
return nil, err
}
cfg := authzlib.ClientConfig{RemoteAddress: authCfg.remoteAddress}
client, err := authzlib.NewClient(&cfg,
authzlib.WithGrpcDialOptionsClientOption(
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithUnaryInterceptor(clientInterceptor.UnaryClientInterceptor),
grpc.WithStreamInterceptor(clientInterceptor.StreamClientInterceptor),
),
authzlib.WithTracerClientOption(tracer),
authzlib.WithCacheClientOption(cache.NewLocalCache(cache.Config{
Expiry: 30 * time.Second,
CleanupInterval: 2 * time.Minute,
})),
// TODO: remove this once access tokens are supported on-prem
authzlib.WithDisableAccessTokenClientOption(),
)
if err != nil {
return nil, err
}
return client, nil
}
func newCloudLegacyClient(authCfg *Cfg, tracer tracing.Tracer) (authlib.AccessClient, error) {
func newRemoteLegacyClient(clientCfg *authzClientSettings, tracer tracing.Tracer) (authlib.AccessClient, error) {
grpcClientConfig := authnlib.GrpcClientConfig{
TokenClientConfig: &authnlib.TokenExchangeConfig{
Token: authCfg.token,
TokenExchangeURL: authCfg.tokenExchangeURL,
Token: clientCfg.token,
TokenExchangeURL: clientCfg.tokenExchangeURL,
},
TokenRequest: &authnlib.TokenExchangeRequest{
Namespace: authCfg.tokenNamespace,
Namespace: clientCfg.tokenNamespace,
Audiences: []string{authzServiceAudience},
},
}
@@ -191,8 +150,8 @@ func newCloudLegacyClient(authCfg *Cfg, tracer tracing.Tracer) (authlib.AccessCl
return nil, err
}
clientCfg := authzlib.ClientConfig{RemoteAddress: authCfg.remoteAddress}
client, err := authzlib.NewClient(&clientCfg,
client, err := authzlib.NewClient(
&authzlib.ClientConfig{RemoteAddress: clientCfg.remoteAddress},
authzlib.WithGrpcDialOptionsClientOption(
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithUnaryInterceptor(clientInterceptor.UnaryClientInterceptor),

View File

@@ -0,0 +1,59 @@
package authz
import (
"fmt"
"github.com/grafana/grafana/pkg/setting"
)
type clientMode string
func (s clientMode) IsValid() bool {
switch s {
case clientModeInproc, clientModeCloud:
return true
}
return false
}
const (
clientModeCloud clientMode = "cloud"
clientModeInproc clientMode = "inproc"
)
type authzClientSettings struct {
remoteAddress string
mode clientMode
token string
tokenExchangeURL string
tokenNamespace string
}
func readAuthzClientSettings(cfg *setting.Cfg) (*authzClientSettings, error) {
authzSection := cfg.SectionWithEnvOverrides("authorization")
grpcClientAuthSection := cfg.SectionWithEnvOverrides("grpc_client_authentication")
mode := clientMode(authzSection.Key("mode").MustString(string(clientModeInproc)))
if !mode.IsValid() {
return nil, fmt.Errorf("authorization: invalid mode %q", mode)
}
s := &authzClientSettings{}
s.mode = mode
if s.mode == clientModeInproc {
return s, nil
}
s.remoteAddress = authzSection.Key("remote_address").MustString("")
s.token = grpcClientAuthSection.Key("token").MustString("")
s.tokenNamespace = grpcClientAuthSection.Key("token_namespace").MustString("stacks-" + cfg.StackID)
s.tokenExchangeURL = grpcClientAuthSection.Key("token_exchange_url").MustString("")
// When running in cloud mode, the token and tokenExchangeURL are required.
if s.token == "" || s.tokenExchangeURL == "" {
return nil, fmt.Errorf("authorization: missing token or tokenExchangeUrl")
}
return s, nil
}