Anonymous access: Allow setting org role in new authz service (#103669)
* Anonymous access: Allow setting org role in new authz service * back out change that is not needed; rename struct * cleanup * Fix tests --------- Co-authored-by: Gabriel Mabille <gabriel.mabille@grafana.com>
This commit is contained in:
co-authored by
Gabriel Mabille
parent
89c70fcdcf
commit
6eba5d74e1
@@ -70,6 +70,11 @@ func ProvideAuthZClient(
|
||||
default:
|
||||
sql := legacysql.NewDatabaseProvider(db)
|
||||
|
||||
rbacSettings := rbac.Settings{}
|
||||
if cfg != nil {
|
||||
rbacSettings.AnonOrgRole = cfg.Anonymous.OrgRole
|
||||
}
|
||||
|
||||
// Register the server
|
||||
server := rbac.NewService(
|
||||
sql,
|
||||
@@ -86,6 +91,7 @@ func ProvideAuthZClient(
|
||||
tracer,
|
||||
reg,
|
||||
cache.NewLocalCache(cache.Config{Expiry: 5 * time.Minute, CleanupInterval: 10 * time.Minute}),
|
||||
rbacSettings,
|
||||
)
|
||||
|
||||
channel := &inprocgrpc.Channel{}
|
||||
@@ -209,6 +215,7 @@ func RegisterRBACAuthZService(
|
||||
tracer,
|
||||
reg,
|
||||
cache,
|
||||
rbac.Settings{}, // anonymous org role can only be set in-proc
|
||||
)
|
||||
|
||||
srv := handler.GetServer()
|
||||
|
||||
@@ -42,6 +42,7 @@ type Service struct {
|
||||
folderStore store.FolderStore
|
||||
permissionStore store.PermissionStore
|
||||
identityStore legacy.LegacyIdentityStore
|
||||
settings Settings
|
||||
|
||||
mapper mapper
|
||||
|
||||
@@ -61,6 +62,10 @@ type Service struct {
|
||||
folderCache *cacheWrap[folderTree]
|
||||
}
|
||||
|
||||
type Settings struct {
|
||||
AnonOrgRole string
|
||||
}
|
||||
|
||||
func NewService(
|
||||
sql legacysql.LegacyDatabaseProvider,
|
||||
folderStore store.FolderStore,
|
||||
@@ -70,12 +75,17 @@ func NewService(
|
||||
tracer tracing.Tracer,
|
||||
reg prometheus.Registerer,
|
||||
cache cache.Cache,
|
||||
settings Settings,
|
||||
) *Service {
|
||||
if settings.AnonOrgRole == "" {
|
||||
settings.AnonOrgRole = "Viewer"
|
||||
}
|
||||
return &Service{
|
||||
store: store.NewStore(sql, tracer),
|
||||
folderStore: folderStore,
|
||||
permissionStore: permissionStore,
|
||||
identityStore: identityStore,
|
||||
settings: settings,
|
||||
logger: logger,
|
||||
tracer: tracer,
|
||||
metrics: newMetrics(reg),
|
||||
@@ -422,7 +432,7 @@ func (s *Service) getAnonymousPermissions(ctx context.Context, ns types.Namespac
|
||||
|
||||
anonPermKey := anonymousPermCacheKey(ns.Value, action)
|
||||
res, err, _ := s.sf.Do(anonPermKey+"_getAnonymousPermissions", func() (interface{}, error) {
|
||||
permissions, err := s.permissionStore.GetUserPermissions(ctx, ns, store.PermissionsQuery{Action: action, ActionSets: actionSets, Role: "Viewer"})
|
||||
permissions, err := s.permissionStore.GetUserPermissions(ctx, ns, store.PermissionsQuery{Action: action, ActionSets: actionSets, Role: s.settings.AnonOrgRole})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1288,6 +1288,89 @@ func TestService_List(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestService_getAnonymousPermissions(t *testing.T) {
|
||||
type testCase struct {
|
||||
name string
|
||||
permissions []accesscontrol.Permission
|
||||
action string
|
||||
expectedPerms map[string]bool
|
||||
expectedError bool
|
||||
anonRole string
|
||||
}
|
||||
|
||||
testCases := []testCase{
|
||||
{
|
||||
name: "should return permissions from store if not in cache",
|
||||
permissions: []accesscontrol.Permission{
|
||||
{Action: "dashboards:read", Scope: "dashboards:uid:some_dashboard"},
|
||||
},
|
||||
action: "dashboards:read",
|
||||
expectedPerms: map[string]bool{"dashboards:uid:some_dashboard": true},
|
||||
expectedError: false,
|
||||
anonRole: "Viewer",
|
||||
},
|
||||
{
|
||||
name: "should return error if store fails",
|
||||
permissions: nil,
|
||||
action: "dashboards:read",
|
||||
expectedPerms: nil,
|
||||
expectedError: true,
|
||||
anonRole: "Viewer",
|
||||
},
|
||||
{
|
||||
name: "should handle wildcard permissions",
|
||||
permissions: []accesscontrol.Permission{
|
||||
{Action: "dashboards:read", Scope: "*", Kind: "*"},
|
||||
},
|
||||
action: "dashboards:read",
|
||||
expectedPerms: map[string]bool{"*": true},
|
||||
expectedError: false,
|
||||
anonRole: "Viewer",
|
||||
},
|
||||
{
|
||||
name: "should use custom anonymous role when specified",
|
||||
permissions: []accesscontrol.Permission{
|
||||
{Action: "dashboards:read", Scope: "dashboards:uid:some_dashboard"},
|
||||
},
|
||||
action: "dashboards:read",
|
||||
expectedPerms: map[string]bool{"dashboards:uid:some_dashboard": true},
|
||||
expectedError: false,
|
||||
anonRole: "Editor",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
s := setupService()
|
||||
if tc.anonRole != "" {
|
||||
s.settings.AnonOrgRole = tc.anonRole
|
||||
}
|
||||
ns := types.NamespaceInfo{Value: "stacks-12", OrgID: 1, StackID: 12}
|
||||
store := &fakeStore{
|
||||
userPermissions: tc.permissions,
|
||||
err: tc.expectedError,
|
||||
disableNsCheck: true,
|
||||
}
|
||||
s.store = store
|
||||
s.permissionStore = store
|
||||
|
||||
perms, err := s.getAnonymousPermissions(ctx, ns, tc.action, []string{})
|
||||
if tc.expectedError {
|
||||
require.Error(t, err)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tc.expectedPerms, perms)
|
||||
|
||||
// cache should then be set
|
||||
cached, ok := s.permCache.Get(ctx, anonymousPermCacheKey(ns.Value, tc.action))
|
||||
require.True(t, ok)
|
||||
require.Equal(t, tc.expectedPerms, cached)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestService_CacheList(t *testing.T) {
|
||||
callingService := authn.NewAccessTokenAuthInfo(authn.Claims[authn.AccessTokenClaims]{
|
||||
Claims: jwt.Claims{
|
||||
@@ -1337,6 +1420,7 @@ func setupService() *Service {
|
||||
teamCache: newCacheWrap[[]int64](cache, logger, shortCacheTTL),
|
||||
basicRoleCache: newCacheWrap[store.BasicRole](cache, logger, longCacheTTL),
|
||||
folderCache: newCacheWrap[folderTree](cache, logger, shortCacheTTL),
|
||||
settings: Settings{AnonOrgRole: "Viewer"},
|
||||
store: fStore,
|
||||
permissionStore: fStore,
|
||||
folderStore: fStore,
|
||||
|
||||
Reference in New Issue
Block a user