Authn: Stat registration [9.4.x] (#63504)
Authn: Stat registration (#62934)
* reorganize auth usage stats
* usage stat privilege elevators
* stat count of modified role
* cfg related info
* add authn anon client
* kv store
* ensure anon enabled is collected even if client is not registered
* fix usage stats test
(cherry picked from commit 14a78b58e9)
This commit is contained in:
@@ -94,6 +94,13 @@ type ProxyClient interface {
|
||||
AuthenticateProxy(ctx context.Context, r *Request, username string, additional map[string]string) (*Identity, error)
|
||||
}
|
||||
|
||||
// UsageStatClient is an optional interface that auth clients can implement.
|
||||
// Clients that implements this interface can specify a usage stat collection hook
|
||||
type UsageStatClient interface {
|
||||
Client
|
||||
UsageStatFn(ctx context.Context) (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
type Request struct {
|
||||
// OrgID will be populated by authn.Service
|
||||
OrgID int64
|
||||
|
||||
@@ -8,9 +8,11 @@ import (
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/kvstore"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/infra/network"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/infra/usagestats"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/apikey"
|
||||
"github.com/grafana/grafana/pkg/services/auth"
|
||||
@@ -48,6 +50,8 @@ func ProvideService(
|
||||
accessControlService accesscontrol.Service,
|
||||
apikeyService apikey.Service, userService user.Service,
|
||||
jwtService auth.JWTVerifierService,
|
||||
usageStats usagestats.Service,
|
||||
kvstore kvstore.KVStore,
|
||||
userProtectionService login.UserProtectionService,
|
||||
loginAttempts loginattempt.Service, quotaService quota.Service,
|
||||
authInfoService login.AuthInfoService, renderService rendering.Service,
|
||||
@@ -64,6 +68,8 @@ func ProvideService(
|
||||
postLoginHooks: newQueue[authn.PostLoginHookFn](),
|
||||
}
|
||||
|
||||
usageStats.RegisterMetricsFunc(s.getUsageStats)
|
||||
|
||||
s.RegisterClient(clients.ProvideRender(userService, renderService))
|
||||
s.RegisterClient(clients.ProvideAPIKey(apikeyService, userService))
|
||||
|
||||
@@ -74,7 +80,7 @@ func ProvideService(
|
||||
}
|
||||
|
||||
if s.cfg.AnonymousEnabled {
|
||||
s.RegisterClient(clients.ProvideAnonymous(cfg, orgService))
|
||||
s.RegisterClient(clients.ProvideAnonymous(cfg, orgService, kvstore))
|
||||
}
|
||||
|
||||
var proxyClients []authn.ProxyClient
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package authnimpl
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/authn"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
func (s *Service) getUsageStats(ctx context.Context) (map[string]interface{}, error) {
|
||||
m := map[string]interface{}{}
|
||||
|
||||
// Add stats about auth configuration
|
||||
authTypes := map[string]bool{}
|
||||
authTypes["basic_auth"] = s.cfg.BasicAuthEnabled
|
||||
authTypes["ldap"] = s.cfg.LDAPEnabled
|
||||
authTypes["auth_proxy"] = s.cfg.AuthProxyEnabled
|
||||
authTypes["anonymous"] = s.cfg.AnonymousEnabled
|
||||
|
||||
for authType, enabled := range authTypes {
|
||||
enabledValue := 0
|
||||
if enabled {
|
||||
enabledValue = 1
|
||||
}
|
||||
m["stats.auth_enabled."+authType+".count"] = enabledValue
|
||||
}
|
||||
|
||||
// Add stats about privilege elevators.
|
||||
// FIXME: Move this to accesscontrol OSS.
|
||||
// FIXME: Access Control OSS usage stats is currently disabled if Enterprise is enabled.
|
||||
m["stats.authz.viewers_can_edit.count"] = 0
|
||||
if setting.ViewersCanEdit {
|
||||
m["stats.authz.viewers_can_edit.count"] = 1
|
||||
}
|
||||
|
||||
m["stats.authz.editors_can_admin.count"] = 0
|
||||
if s.cfg.EditorsCanAdmin {
|
||||
m["stats.authz.editors_can_admin.count"] = 1
|
||||
}
|
||||
|
||||
for _, client := range s.clients {
|
||||
if usac, ok := client.(authn.UsageStatClient); ok {
|
||||
clientStats, err := usac.UsageStatFn(ctx)
|
||||
if err != nil {
|
||||
s.log.Warn("Failed to get usage stats from client", "client", client.Name(), "error", err)
|
||||
}
|
||||
|
||||
for k, v := range clientStats {
|
||||
m[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return m, nil
|
||||
}
|
||||
@@ -2,7 +2,9 @@ package clients
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/kvstore"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/services/authn"
|
||||
"github.com/grafana/grafana/pkg/services/org"
|
||||
@@ -11,7 +13,7 @@ import (
|
||||
|
||||
var _ authn.ContextAwareClient = new(Anonymous)
|
||||
|
||||
func ProvideAnonymous(cfg *setting.Cfg, orgService org.Service) *Anonymous {
|
||||
func ProvideAnonymous(cfg *setting.Cfg, orgService org.Service, _ kvstore.KVStore) *Anonymous {
|
||||
return &Anonymous{
|
||||
cfg: cfg,
|
||||
log: log.New("authn.anonymous"),
|
||||
@@ -53,3 +55,15 @@ func (a *Anonymous) Test(ctx context.Context, r *authn.Request) bool {
|
||||
func (a *Anonymous) Priority() uint {
|
||||
return 100
|
||||
}
|
||||
|
||||
func (a *Anonymous) UsageStatFn(ctx context.Context) (map[string]interface{}, error) {
|
||||
m := map[string]interface{}{}
|
||||
|
||||
// Add stats about anonymous auth
|
||||
m["stats.anonymous.customized_role.count"] = 0
|
||||
if !strings.EqualFold(a.cfg.AnonymousOrgRole, "Viewer") {
|
||||
m["stats.anonymous.customized_role.count"] = 1
|
||||
}
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user