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:
Jo
2023-02-21 16:21:09 +01:00
committed by GitHub
parent b6dc902ec0
commit 4ddc76f73e
9 changed files with 114 additions and 48 deletions
+7
View File
@@ -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
+7 -1
View File
@@ -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
}
+15 -1
View File
@@ -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
}