diff --git a/pkg/services/authz/config.go b/pkg/services/authz/config.go deleted file mode 100644 index a6c8943be55..00000000000 --- a/pkg/services/authz/config.go +++ /dev/null @@ -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 -} diff --git a/pkg/services/authz/rbac.go b/pkg/services/authz/rbac.go index cd0465886d3..4e9daa6f744 100644 --- a/pkg/services/authz/rbac.go +++ b/pkg/services/authz/rbac.go @@ -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), diff --git a/pkg/services/authz/rbac_settings.go b/pkg/services/authz/rbac_settings.go new file mode 100644 index 00000000000..0ee661c2b50 --- /dev/null +++ b/pkg/services/authz/rbac_settings.go @@ -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 +}