Instrument tracing across accesscontrol (#91864)

Instrument tracing across accesscontrol 

---------

Co-authored-by: Dave Henderson <dave.henderson@grafana.com>
This commit is contained in:
Jeff Levin
2024-08-16 14:08:19 -08:00
committed by GitHub
co-authored by Dave Henderson
parent 68f545210d
commit 028e8ac59e
22 changed files with 301 additions and 51 deletions
@@ -7,6 +7,7 @@ import (
openfgav1 "github.com/openfga/api/proto/openfga/v1"
"github.com/prometheus/client_golang/prometheus"
"go.opentelemetry.io/otel"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/infra/log"
@@ -18,6 +19,7 @@ import (
var (
errAccessNotImplemented = errors.New("access control not implemented for resource")
tracer = otel.Tracer("github.com/grafana/grafana/pkg/services/accesscontrol/acimpl")
)
var _ accesscontrol.AccessControl = new(AccessControl)
@@ -52,6 +54,9 @@ type AccessControl struct {
}
func (a *AccessControl) Evaluate(ctx context.Context, user identity.Requester, evaluator accesscontrol.Evaluator) (bool, error) {
ctx, span := tracer.Start(ctx, "accesscontrol.acimpl.Evaluate")
defer span.End()
if a.features.IsEnabledGlobally(featuremgmt.FlagZanzana) {
return a.evaluateCompare(ctx, user, evaluator)
}
@@ -60,6 +65,9 @@ func (a *AccessControl) Evaluate(ctx context.Context, user identity.Requester, e
}
func (a *AccessControl) evaluate(ctx context.Context, user identity.Requester, evaluator accesscontrol.Evaluator) (bool, error) {
ctx, span := tracer.Start(ctx, "accesscontrol.acimpl.evaluate")
defer span.End()
timer := prometheus.NewTimer(metrics.MAccessEvaluationsSummary)
defer timer.ObserveDuration()
metrics.MAccessEvaluationCount.Inc()
@@ -98,6 +106,9 @@ func (a *AccessControl) evaluate(ctx context.Context, user identity.Requester, e
}
func (a *AccessControl) evaluateZanzana(ctx context.Context, user identity.Requester, evaluator accesscontrol.Evaluator) (bool, error) {
ctx, span := tracer.Start(ctx, "accesscontrol.acimpl.evaluateZanzana")
defer span.End()
eval, err := evaluator.MutateScopes(ctx, a.resolvers.GetScopeAttributeMutator(user.GetOrgID()))
if err != nil {
if !errors.Is(err, accesscontrol.ErrResolverNotFound) {
@@ -140,6 +151,9 @@ type evalResult struct {
// evaluateCompare run RBAC and zanzana checks in parallel and then compare result
func (a *AccessControl) evaluateCompare(ctx context.Context, user identity.Requester, evaluator accesscontrol.Evaluator) (bool, error) {
ctx, span := tracer.Start(ctx, "accesscontrol.acimpl.evaluateCompare")
defer span.End()
res := make(chan evalResult, 2)
go func() {
timer := prometheus.NewTimer(a.metrics.mAccessEngineEvaluationsSeconds.WithLabelValues("zanzana"))
@@ -192,5 +206,8 @@ func (a *AccessControl) RegisterScopeAttributeResolver(prefix string, resolver a
}
func (a *AccessControl) debug(ctx context.Context, ident identity.Requester, msg string, eval accesscontrol.Evaluator) {
ctx, span := tracer.Start(ctx, "accesscontrol.acimpl.debug")
defer span.End()
a.log.FromContext(ctx).Debug(msg, "id", ident.GetID(), "orgID", ident.GetOrgID(), "permissions", eval.GoString())
}
+22 -24
View File
@@ -85,7 +85,6 @@ func ProvideOSSService(
log: log.New("accesscontrol.service"),
roles: accesscontrol.BuildBasicRoleDefinitions(),
store: store,
tracer: tracer,
sync: migrator.NewZanzanaSynchroniser(zclient, db),
permRegistry: permRegistry,
}
@@ -103,7 +102,6 @@ type Service struct {
registrations accesscontrol.RegistrationList
roles map[string]*accesscontrol.RoleDTO
store accesscontrol.Store
tracer tracing.Tracer
sync *migrator.ZanzanaSynchroniser
permRegistry permreg.PermissionRegistry
}
@@ -116,7 +114,7 @@ func (s *Service) GetUsageStats(_ context.Context) map[string]any {
// GetUserPermissions returns user permissions based on built-in roles
func (s *Service) GetUserPermissions(ctx context.Context, user identity.Requester, options accesscontrol.Options) ([]accesscontrol.Permission, error) {
ctx, span := s.tracer.Start(ctx, "authz.GetUserPermissionsOSS")
ctx, span := tracer.Start(ctx, "accesscontrol.acimpl.GetUserPermissions")
defer span.End()
timer := prometheus.NewTimer(metrics.MAccessPermissionsSummary)
@@ -130,7 +128,7 @@ func (s *Service) GetUserPermissions(ctx context.Context, user identity.Requeste
}
func (s *Service) getUserPermissions(ctx context.Context, user identity.Requester, _ accesscontrol.Options) ([]accesscontrol.Permission, error) {
ctx, span := s.tracer.Start(ctx, "authz.getUserPermissions")
ctx, span := tracer.Start(ctx, "accesscontrol.acimpl.getUserPermissions")
defer span.End()
permissions := make([]accesscontrol.Permission, 0)
@@ -166,7 +164,7 @@ func (s *Service) getUserPermissions(ctx context.Context, user identity.Requeste
}
func (s *Service) getBasicRolePermissions(ctx context.Context, role string, orgID int64) ([]accesscontrol.Permission, error) {
ctx, span := s.tracer.Start(ctx, "authz.getBasicRolePermissions")
ctx, span := tracer.Start(ctx, "accesscontrol.acimpl.getBasicRolePermissions")
defer span.End()
var permissions []accesscontrol.Permission
@@ -188,7 +186,7 @@ func (s *Service) getBasicRolePermissions(ctx context.Context, role string, orgI
}
func (s *Service) getTeamsPermissions(ctx context.Context, teamIDs []int64, orgID int64) (map[int64][]accesscontrol.Permission, error) {
ctx, span := s.tracer.Start(ctx, "authz.getTeamsPermissions")
ctx, span := tracer.Start(ctx, "accesscontrol.acimpl.getTeamsPermissions")
defer span.End()
teamPermissions, err := s.store.GetTeamsPermissions(ctx, accesscontrol.GetUserPermissionsQuery{
@@ -208,7 +206,7 @@ func (s *Service) getTeamsPermissions(ctx context.Context, teamIDs []int64, orgI
// Returns only permissions directly assigned to user, without basic role and team permissions
func (s *Service) getUserDirectPermissions(ctx context.Context, user identity.Requester) ([]accesscontrol.Permission, error) {
ctx, span := s.tracer.Start(ctx, "authz.getUserDirectPermissions")
ctx, span := tracer.Start(ctx, "accesscontrol.acimpl.getUserDirectPermissions")
defer span.End()
var userID int64
@@ -240,7 +238,7 @@ func (s *Service) getUserDirectPermissions(ctx context.Context, user identity.Re
}
func (s *Service) getCachedUserPermissions(ctx context.Context, user identity.Requester, options accesscontrol.Options) ([]accesscontrol.Permission, error) {
ctx, span := s.tracer.Start(ctx, "authz.getCachedUserPermissions")
ctx, span := tracer.Start(ctx, "accesscontrol.acimpl.getCachedUserPermissions")
defer span.End()
permissions := []accesscontrol.Permission{}
@@ -266,7 +264,7 @@ func (s *Service) getCachedUserPermissions(ctx context.Context, user identity.Re
}
func (s *Service) getCachedBasicRolesPermissions(ctx context.Context, user identity.Requester, options accesscontrol.Options, permissions []accesscontrol.Permission) ([]accesscontrol.Permission, error) {
ctx, span := s.tracer.Start(ctx, "authz.getCachedBasicRolesPermissions")
ctx, span := tracer.Start(ctx, "accesscontrol.acimpl.getCachedBasicRolesPermissions")
defer span.End()
basicRoles := accesscontrol.GetOrgRoles(user)
@@ -283,7 +281,7 @@ func (s *Service) getCachedBasicRolesPermissions(ctx context.Context, user ident
}
func (s *Service) getCachedBasicRolePermissions(ctx context.Context, role string, orgID int64, options accesscontrol.Options) ([]accesscontrol.Permission, error) {
ctx, span := s.tracer.Start(ctx, "authz.getCachedBasicRolePermissions")
ctx, span := tracer.Start(ctx, "accesscontrol.acimpl.getCachedBasicRolePermissions")
defer span.End()
key := accesscontrol.GetBasicRolePermissionCacheKey(role, orgID)
@@ -294,7 +292,7 @@ func (s *Service) getCachedBasicRolePermissions(ctx context.Context, role string
}
func (s *Service) getCachedUserDirectPermissions(ctx context.Context, user identity.Requester, options accesscontrol.Options) ([]accesscontrol.Permission, error) {
ctx, span := s.tracer.Start(ctx, "authz.getCachedUserDirectPermissions")
ctx, span := tracer.Start(ctx, "accesscontrol.acimpl.getCachedUserDirectPermissions")
defer span.End()
key := accesscontrol.GetUserDirectPermissionCacheKey(user)
@@ -308,7 +306,7 @@ type getPermissionsFunc = func(ctx context.Context) ([]accesscontrol.Permission,
// Generic method for getting various permissions from cache
func (s *Service) getCachedPermissions(ctx context.Context, key string, getPermissionsFn getPermissionsFunc, options accesscontrol.Options) ([]accesscontrol.Permission, error) {
ctx, span := s.tracer.Start(ctx, "authz.getCachedPermissions")
ctx, span := tracer.Start(ctx, "accesscontrol.acimpl.getCachedPermissions")
defer span.End()
if !options.ReloadCache {
@@ -333,7 +331,7 @@ func (s *Service) getCachedPermissions(ctx context.Context, key string, getPermi
}
func (s *Service) getCachedTeamsPermissions(ctx context.Context, user identity.Requester, options accesscontrol.Options, permissions []accesscontrol.Permission) ([]accesscontrol.Permission, error) {
ctx, span := s.tracer.Start(ctx, "authz.getCachedTeamsPermissions")
ctx, span := tracer.Start(ctx, "accesscontrol.acimpl.getCachedTeamsPermissions")
defer span.End()
teams := user.GetTeams()
@@ -380,14 +378,14 @@ func (s *Service) ClearUserPermissionCache(user identity.Requester) {
}
func (s *Service) DeleteUserPermissions(ctx context.Context, orgID int64, userID int64) error {
ctx, span := s.tracer.Start(ctx, "authz.DeleteUserPermissions")
ctx, span := tracer.Start(ctx, "accesscontrol.acimpl.DeleteUserPermissions")
defer span.End()
return s.store.DeleteUserPermissions(ctx, orgID, userID)
}
func (s *Service) DeleteTeamPermissions(ctx context.Context, orgID int64, teamID int64) error {
ctx, span := s.tracer.Start(ctx, "authz.DeleteTeamPermissions")
ctx, span := tracer.Start(ctx, "accesscontrol.acimpl.DeleteTeamPermissions")
defer span.End()
return s.store.DeleteTeamPermissions(ctx, orgID, teamID)
@@ -419,7 +417,7 @@ func (s *Service) DeclareFixedRoles(registrations ...accesscontrol.RoleRegistrat
// RegisterFixedRoles registers all declared roles in RAM
func (s *Service) RegisterFixedRoles(ctx context.Context) error {
_, span := s.tracer.Start(ctx, "authz.RegisterFixedRoles")
_, span := tracer.Start(ctx, "accesscontrol.acimpl.RegisterFixedRoles")
defer span.End()
s.registrations.Range(func(registration accesscontrol.RoleRegistration) bool {
@@ -445,7 +443,7 @@ func (s *Service) RegisterFixedRoles(ctx context.Context) error {
// DeclarePluginRoles allow the caller to declare, to the service, plugin roles and their assignments
// to organization roles ("Viewer", "Editor", "Admin") or "Grafana Admin"
func (s *Service) DeclarePluginRoles(ctx context.Context, ID, name string, regs []plugins.RoleRegistration) error {
ctx, span := s.tracer.Start(ctx, "authz.DeclarePluginRoles")
ctx, span := tracer.Start(ctx, "accesscontrol.acimpl.DeclarePluginRoles")
defer span.End()
// Protect behind feature toggle
@@ -488,7 +486,7 @@ func GetActionFilter(options accesscontrol.SearchOptions) func(action string) bo
// SearchUsersPermissions returns all users' permissions filtered by action prefixes
func (s *Service) SearchUsersPermissions(ctx context.Context, usr identity.Requester, options accesscontrol.SearchOptions) (map[int64][]accesscontrol.Permission, error) {
ctx, span := s.tracer.Start(ctx, "authz.SearchUsersPermissions")
ctx, span := tracer.Start(ctx, "accesscontrol.acimpl.SearchUsersPermissions")
defer span.End()
// Limit roles to available in OSS
@@ -602,7 +600,7 @@ func (s *Service) SearchUsersPermissions(ctx context.Context, usr identity.Reque
}
func (s *Service) SearchUserPermissions(ctx context.Context, orgID int64, searchOptions accesscontrol.SearchOptions) ([]accesscontrol.Permission, error) {
ctx, span := s.tracer.Start(ctx, "authz.SearchUserPermissions")
ctx, span := tracer.Start(ctx, "accesscontrol.acimpl.SearchUserPermissions")
defer span.End()
timer := prometheus.NewTimer(metrics.MAccessPermissionsSummary)
@@ -619,7 +617,7 @@ func (s *Service) SearchUserPermissions(ctx context.Context, orgID int64, search
}
func (s *Service) searchUserPermissions(ctx context.Context, orgID int64, searchOptions accesscontrol.SearchOptions) ([]accesscontrol.Permission, error) {
ctx, span := s.tracer.Start(ctx, "authz.searchUserPermissions")
ctx, span := tracer.Start(ctx, "accesscontrol.acimpl.searchUserPermissions")
defer span.End()
userID, err := searchOptions.ComputeUserID()
@@ -672,7 +670,7 @@ func (s *Service) searchUserPermissions(ctx context.Context, orgID int64, search
}
func (s *Service) searchUserPermissionsFromCache(ctx context.Context, orgID int64, searchOptions accesscontrol.SearchOptions) ([]accesscontrol.Permission, bool) {
_, span := s.tracer.Start(ctx, "authz.searchUserPermissionsFromCache")
_, span := tracer.Start(ctx, "accesscontrol.acimpl.searchUserPermissionsFromCache")
defer span.End()
userID, err := searchOptions.ComputeUserID()
@@ -714,7 +712,7 @@ func PermissionMatchesSearchOptions(permission accesscontrol.Permission, searchO
}
func (s *Service) SaveExternalServiceRole(ctx context.Context, cmd accesscontrol.SaveExternalServiceRoleCommand) error {
ctx, span := s.tracer.Start(ctx, "authz.SaveExternalServiceRole")
ctx, span := tracer.Start(ctx, "accesscontrol.acimpl.SaveExternalServiceRole")
defer span.End()
if !s.features.IsEnabled(ctx, featuremgmt.FlagExternalServiceAccounts) {
@@ -730,7 +728,7 @@ func (s *Service) SaveExternalServiceRole(ctx context.Context, cmd accesscontrol
}
func (s *Service) DeleteExternalServiceRole(ctx context.Context, externalServiceID string) error {
ctx, span := s.tracer.Start(ctx, "authz.DeleteExternalServiceRole")
ctx, span := tracer.Start(ctx, "accesscontrol.acimpl.DeleteExternalServiceRole")
defer span.End()
if !s.features.IsEnabled(ctx, featuremgmt.FlagExternalServiceAccounts) {
@@ -748,7 +746,7 @@ func (*Service) SyncUserRoles(ctx context.Context, orgID int64, cmd accesscontro
}
func (s *Service) GetRoleByName(ctx context.Context, orgID int64, roleName string) (*accesscontrol.RoleDTO, error) {
_, span := s.tracer.Start(ctx, "authz.GetRoleByName")
_, span := tracer.Start(ctx, "accesscontrol.acimpl.GetRoleByName")
defer span.End()
err := accesscontrol.ErrRoleNotFound
@@ -42,7 +42,6 @@ func setupTestEnv(t testing.TB) *Service {
log: log.New("accesscontrol"),
registrations: accesscontrol.RegistrationList{},
roles: accesscontrol.BuildBasicRoleDefinitions(),
tracer: tracing.InitializeTracerForTest(),
store: database.ProvideService(db.InitTestReplDB(t)),
permRegistry: permreg.ProvidePermissionRegistry(),
}