RBAC: remove simple RBAC disabled checks (#71137)

* remove simple RBAC disabled checks

* fixing tests

* remove old AC tests
This commit is contained in:
Ieva 2023-07-10 15:14:21 +03:00 committed by GitHub
parent 8f2f6d63eb
commit a65cb4d808
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 64 additions and 720 deletions

View File

@ -158,11 +158,8 @@ func (hs *HTTPServer) GetDashboard(c *contextmodel.ReqContext) response.Response
}
annotationPermissions := &dtos.AnnotationPermission{}
if !hs.AccessControl.IsDisabled() {
hs.getAnnotationPermissionsByScope(c, &annotationPermissions.Dashboard, accesscontrol.ScopeAnnotationsTypeDashboard)
hs.getAnnotationPermissionsByScope(c, &annotationPermissions.Organization, accesscontrol.ScopeAnnotationsTypeOrganization)
}
hs.getAnnotationPermissionsByScope(c, &annotationPermissions.Dashboard, accesscontrol.ScopeAnnotationsTypeDashboard)
hs.getAnnotationPermissionsByScope(c, &annotationPermissions.Organization, accesscontrol.ScopeAnnotationsTypeOrganization)
meta := dtos.DashboardMeta{
IsStarred: isStarred,
@ -488,7 +485,7 @@ func (hs *HTTPServer) postDashboard(c *contextmodel.ReqContext, cmd dashboards.S
// Clear permission cache for the user who's created the dashboard, so that new permissions are fetched for their next call
// Required for cases when caller wants to immediately interact with the newly created object
if newDashboard && !hs.accesscontrolService.IsDisabled() {
if newDashboard {
hs.accesscontrolService.ClearUserPermissionCache(c.SignedInUser)
}

View File

@ -158,9 +158,7 @@ func (hs *HTTPServer) CreateFolder(c *contextmodel.ReqContext) response.Response
// Clear permission cache for the user who's created the folder, so that new permissions are fetched for their next call
// Required for cases when caller wants to immediately interact with the newly created object
if !hs.AccessControl.IsDisabled() {
hs.accesscontrolService.ClearUserPermissionCache(c.SignedInUser)
}
hs.accesscontrolService.ClearUserPermissionCache(c.SignedInUser)
g, err := guardian.NewByUID(c.Req.Context(), folder.UID, c.OrgID, c.SignedInUser)
if err != nil {
@ -172,29 +170,23 @@ func (hs *HTTPServer) CreateFolder(c *contextmodel.ReqContext) response.Response
}
func (hs *HTTPServer) setDefaultFolderPermissions(ctx context.Context, orgID int64, user *user.SignedInUser, folder *folder.Folder) error {
isNested := folder.ParentUID != ""
var permissionErr error
if !accesscontrol.IsDisabled(hs.Cfg) {
var permissions []accesscontrol.SetResourcePermissionCommand
if user.IsRealUser() && !user.IsAnonymous {
permissions = append(permissions, accesscontrol.SetResourcePermissionCommand{
UserID: user.UserID, Permission: dashboards.PERMISSION_ADMIN.String(),
})
}
if !isNested || !hs.Features.IsEnabled(featuremgmt.FlagNestedFolders) {
permissions = append(permissions, []accesscontrol.SetResourcePermissionCommand{
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_EDIT.String()},
{BuiltinRole: string(org.RoleViewer), Permission: dashboards.PERMISSION_VIEW.String()},
}...)
}
_, permissionErr = hs.folderPermissionsService.SetPermissions(ctx, orgID, folder.UID, permissions...)
return permissionErr
} else if hs.Cfg.EditorsCanAdmin && user.IsRealUser() && !user.IsAnonymous {
return hs.folderService.MakeUserAdmin(ctx, orgID, user.UserID, folder.ID, !isNested)
var permissions []accesscontrol.SetResourcePermissionCommand
if user.IsRealUser() && !user.IsAnonymous {
permissions = append(permissions, accesscontrol.SetResourcePermissionCommand{
UserID: user.UserID, Permission: dashboards.PERMISSION_ADMIN.String(),
})
}
return nil
isNested := folder.ParentUID != ""
if !isNested || !hs.Features.IsEnabled(featuremgmt.FlagNestedFolders) {
permissions = append(permissions, []accesscontrol.SetResourcePermissionCommand{
{BuiltinRole: string(org.RoleEditor), Permission: dashboards.PERMISSION_EDIT.String()},
{BuiltinRole: string(org.RoleViewer), Permission: dashboards.PERMISSION_VIEW.String()},
}...)
}
_, err := hs.folderPermissionsService.SetPermissions(ctx, orgID, folder.UID, permissions...)
return err
}
// swagger:route POST /folders/{folder_uid}/move folders moveFolder
@ -378,7 +370,7 @@ func (hs *HTTPServer) newToFolderDto(c *contextmodel.ReqContext, g guardian.Dash
}
func (hs *HTTPServer) getFolderACMetadata(c *contextmodel.ReqContext, f *folder.Folder) (accesscontrol.Metadata, error) {
if hs.AccessControl.IsDisabled() || !c.QueryBool("accesscontrol") {
if !c.QueryBool("accesscontrol") {
return nil, nil
}

View File

@ -412,12 +412,10 @@ func (hs *HTTPServer) updateOrgUserHelper(c *contextmodel.ReqContext, cmd org.Up
return response.Error(http.StatusInternalServerError, "Failed update org user", err)
}
if !hs.accesscontrolService.IsDisabled() {
hs.accesscontrolService.ClearUserPermissionCache(&user.SignedInUser{
UserID: cmd.UserID,
OrgID: cmd.OrgID,
})
}
hs.accesscontrolService.ClearUserPermissionCache(&user.SignedInUser{
UserID: cmd.UserID,
OrgID: cmd.OrgID,
})
return response.Success("Organization user updated")
}

View File

@ -3,7 +3,6 @@ package db
import (
"bytes"
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
@ -67,19 +66,10 @@ func (sb *SQLBuilder) WriteDashboardPermissionFilter(user *user.SignedInUser, pe
recQry string
recQryParams []interface{}
)
if !ac.IsDisabled(sb.cfg) {
filterRBAC := permissions.NewAccessControlDashboardPermissionFilter(user, permission, queryType, sb.features, sb.recursiveQueriesAreSupported)
sql, params = filterRBAC.Where()
recQry, recQryParams = filterRBAC.With()
} else {
sql, params = permissions.DashboardPermissionFilter{
OrgRole: user.OrgRole,
Dialect: sb.dialect,
UserId: user.UserID,
OrgId: user.OrgID,
PermissionLevel: permission,
}.Where()
}
filterRBAC := permissions.NewAccessControlDashboardPermissionFilter(user, permission, queryType, sb.features, sb.recursiveQueriesAreSupported)
sql, params = filterRBAC.Where()
recQry, recQryParams = filterRBAC.With()
sb.sql.WriteString(" AND " + sql)
sb.params = append(sb.params, params...)

View File

@ -1,580 +0,0 @@
package db
import (
"context"
"fmt"
"math/rand"
"strconv"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/services/dashboards"
dashver "github.com/grafana/grafana/pkg/services/dashboardversion"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/util"
)
func TestIntegrationSQLBuilder(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
t.Run("WriteDashboardPermissionFilter", func(t *testing.T) {
t.Run("user ACL", func(t *testing.T) {
test(t,
DashboardProps{},
&DashboardPermission{User: true, Permission: dashboards.PERMISSION_VIEW},
Search{UserFromACL: true, RequiredPermission: dashboards.PERMISSION_VIEW},
shouldFind,
featuremgmt.WithFeatures(),
)
test(t,
DashboardProps{},
&DashboardPermission{User: true, Permission: dashboards.PERMISSION_VIEW},
Search{UserFromACL: true, RequiredPermission: dashboards.PERMISSION_EDIT},
shouldNotFind,
featuremgmt.WithFeatures(),
)
test(t,
DashboardProps{},
&DashboardPermission{User: true, Permission: dashboards.PERMISSION_EDIT},
Search{UserFromACL: true, RequiredPermission: dashboards.PERMISSION_EDIT},
shouldFind,
featuremgmt.WithFeatures(),
)
test(t,
DashboardProps{},
&DashboardPermission{User: true, Permission: dashboards.PERMISSION_VIEW},
Search{RequiredPermission: dashboards.PERMISSION_VIEW},
shouldNotFind,
featuremgmt.WithFeatures(),
)
})
t.Run("user ACL with nested folders", func(t *testing.T) {
test(t,
DashboardProps{},
&DashboardPermission{User: true, Permission: dashboards.PERMISSION_VIEW},
Search{UserFromACL: true, RequiredPermission: dashboards.PERMISSION_VIEW},
shouldFind,
featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)),
)
test(t,
DashboardProps{},
&DashboardPermission{User: true, Permission: dashboards.PERMISSION_VIEW},
Search{UserFromACL: true, RequiredPermission: dashboards.PERMISSION_EDIT},
shouldNotFind,
featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)),
)
test(t,
DashboardProps{},
&DashboardPermission{User: true, Permission: dashboards.PERMISSION_EDIT},
Search{UserFromACL: true, RequiredPermission: dashboards.PERMISSION_EDIT},
shouldFind,
featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)),
)
test(t,
DashboardProps{},
&DashboardPermission{User: true, Permission: dashboards.PERMISSION_VIEW},
Search{RequiredPermission: dashboards.PERMISSION_VIEW},
shouldNotFind,
featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)),
)
})
t.Run("role ACL", func(t *testing.T) {
test(t,
DashboardProps{},
&DashboardPermission{Role: org.RoleViewer, Permission: dashboards.PERMISSION_VIEW},
Search{UsersOrgRole: org.RoleViewer, RequiredPermission: dashboards.PERMISSION_VIEW},
shouldFind,
featuremgmt.WithFeatures(),
)
test(t,
DashboardProps{},
&DashboardPermission{Role: org.RoleViewer, Permission: dashboards.PERMISSION_VIEW},
Search{UsersOrgRole: org.RoleViewer, RequiredPermission: dashboards.PERMISSION_EDIT},
shouldNotFind,
featuremgmt.WithFeatures(),
)
test(t,
DashboardProps{},
&DashboardPermission{Role: org.RoleEditor, Permission: dashboards.PERMISSION_VIEW},
Search{UsersOrgRole: org.RoleViewer, RequiredPermission: dashboards.PERMISSION_VIEW},
shouldNotFind,
featuremgmt.WithFeatures(),
)
test(t,
DashboardProps{},
&DashboardPermission{Role: org.RoleEditor, Permission: dashboards.PERMISSION_VIEW},
Search{UsersOrgRole: org.RoleViewer, RequiredPermission: dashboards.PERMISSION_VIEW},
shouldNotFind,
featuremgmt.WithFeatures(),
)
})
t.Run("role ACL with nested folders", func(t *testing.T) {
test(t,
DashboardProps{},
&DashboardPermission{Role: org.RoleViewer, Permission: dashboards.PERMISSION_VIEW},
Search{UsersOrgRole: org.RoleViewer, RequiredPermission: dashboards.PERMISSION_VIEW},
shouldFind,
featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)),
)
test(t,
DashboardProps{},
&DashboardPermission{Role: org.RoleViewer, Permission: dashboards.PERMISSION_VIEW},
Search{UsersOrgRole: org.RoleViewer, RequiredPermission: dashboards.PERMISSION_EDIT},
shouldNotFind,
featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)),
)
test(t,
DashboardProps{},
&DashboardPermission{Role: org.RoleEditor, Permission: dashboards.PERMISSION_VIEW},
Search{UsersOrgRole: org.RoleViewer, RequiredPermission: dashboards.PERMISSION_VIEW},
shouldNotFind,
featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)),
)
test(t,
DashboardProps{},
&DashboardPermission{Role: org.RoleEditor, Permission: dashboards.PERMISSION_VIEW},
Search{UsersOrgRole: org.RoleViewer, RequiredPermission: dashboards.PERMISSION_VIEW},
shouldNotFind,
featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)),
)
})
t.Run("team ACL", func(t *testing.T) {
test(t,
DashboardProps{},
&DashboardPermission{Team: true, Permission: dashboards.PERMISSION_VIEW},
Search{UserFromACL: true, RequiredPermission: dashboards.PERMISSION_VIEW},
shouldFind,
featuremgmt.WithFeatures(),
)
test(t,
DashboardProps{},
&DashboardPermission{Team: true, Permission: dashboards.PERMISSION_VIEW},
Search{UserFromACL: true, RequiredPermission: dashboards.PERMISSION_EDIT},
shouldNotFind,
featuremgmt.WithFeatures(),
)
test(t,
DashboardProps{},
&DashboardPermission{Team: true, Permission: dashboards.PERMISSION_EDIT},
Search{UserFromACL: true, RequiredPermission: dashboards.PERMISSION_EDIT},
shouldFind,
featuremgmt.WithFeatures(),
)
test(t,
DashboardProps{},
&DashboardPermission{Team: true, Permission: dashboards.PERMISSION_EDIT},
Search{UserFromACL: false, RequiredPermission: dashboards.PERMISSION_EDIT},
shouldNotFind,
featuremgmt.WithFeatures(),
)
})
t.Run("team ACL with nested folders", func(t *testing.T) {
test(t,
DashboardProps{},
&DashboardPermission{Team: true, Permission: dashboards.PERMISSION_VIEW},
Search{UserFromACL: true, RequiredPermission: dashboards.PERMISSION_VIEW},
shouldFind,
featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)),
)
test(t,
DashboardProps{},
&DashboardPermission{Team: true, Permission: dashboards.PERMISSION_VIEW},
Search{UserFromACL: true, RequiredPermission: dashboards.PERMISSION_EDIT},
shouldNotFind,
featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)),
)
test(t,
DashboardProps{},
&DashboardPermission{Team: true, Permission: dashboards.PERMISSION_EDIT},
Search{UserFromACL: true, RequiredPermission: dashboards.PERMISSION_EDIT},
shouldFind,
featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)),
)
test(t,
DashboardProps{},
&DashboardPermission{Team: true, Permission: dashboards.PERMISSION_EDIT},
Search{UserFromACL: false, RequiredPermission: dashboards.PERMISSION_EDIT},
shouldNotFind,
featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)),
)
})
t.Run("defaults for user ACL", func(t *testing.T) {
test(t,
DashboardProps{},
nil,
Search{OrgId: -1, UsersOrgRole: org.RoleViewer, RequiredPermission: dashboards.PERMISSION_VIEW},
shouldNotFind,
featuremgmt.WithFeatures(),
)
test(t,
DashboardProps{OrgId: -1},
nil,
Search{OrgId: -1, UsersOrgRole: org.RoleViewer, RequiredPermission: dashboards.PERMISSION_VIEW},
shouldFind,
featuremgmt.WithFeatures(),
)
test(t,
DashboardProps{OrgId: -1},
nil,
Search{OrgId: -1, UsersOrgRole: org.RoleEditor, RequiredPermission: dashboards.PERMISSION_EDIT},
shouldFind,
featuremgmt.WithFeatures(),
)
test(t,
DashboardProps{OrgId: -1},
nil,
Search{OrgId: -1, UsersOrgRole: org.RoleViewer, RequiredPermission: dashboards.PERMISSION_EDIT},
shouldNotFind,
featuremgmt.WithFeatures(),
)
})
t.Run("defaults for user ACL with nested folders", func(t *testing.T) {
test(t,
DashboardProps{},
nil,
Search{OrgId: -1, UsersOrgRole: org.RoleViewer, RequiredPermission: dashboards.PERMISSION_VIEW},
shouldNotFind,
featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)),
)
test(t,
DashboardProps{OrgId: -1},
nil,
Search{OrgId: -1, UsersOrgRole: org.RoleViewer, RequiredPermission: dashboards.PERMISSION_VIEW},
shouldFind,
featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)),
)
test(t,
DashboardProps{OrgId: -1},
nil,
Search{OrgId: -1, UsersOrgRole: org.RoleEditor, RequiredPermission: dashboards.PERMISSION_EDIT},
shouldFind,
featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)),
)
test(t,
DashboardProps{OrgId: -1},
nil,
Search{OrgId: -1, UsersOrgRole: org.RoleViewer, RequiredPermission: dashboards.PERMISSION_EDIT},
shouldNotFind,
featuremgmt.WithFeatures(featuremgmt.WithFeatures(featuremgmt.FlagNestedFolders)),
)
})
})
}
const shouldFind = true
const shouldNotFind = false
type DashboardProps struct {
OrgId int64
}
type DashboardPermission struct {
User bool
Team bool
Role org.RoleType
Permission dashboards.PermissionType
}
type Search struct {
UsersOrgRole org.RoleType
UserFromACL bool
RequiredPermission dashboards.PermissionType
OrgId int64
}
type dashboardResponse struct {
Id int64
}
func test(t *testing.T, dashboardProps DashboardProps, dashboardPermission *DashboardPermission, search Search, shouldFind bool, features featuremgmt.FeatureToggles) {
t.Helper()
t.Run("", func(t *testing.T) {
// Will also cleanup the db
sqlStore := InitTestDB(t)
dashboard := createDummyDashboard(t, sqlStore, dashboardProps)
var aclUserID int64
if dashboardPermission != nil {
aclUserID = createDummyACL(t, sqlStore, dashboardPermission, search, dashboard.ID)
t.Logf("Created ACL with user ID %d\n", aclUserID)
}
dashboards := getDashboards(t, sqlStore, search, aclUserID, features)
if shouldFind {
require.Len(t, dashboards, 1, "Should return one dashboard")
assert.Equal(t, dashboard.ID, dashboards[0].Id, "Should return created dashboard")
} else {
assert.Empty(t, dashboards, "Should not return any dashboard")
}
})
}
func createDummyUser(t *testing.T, sqlStore DB) *user.User {
t.Helper()
uid := strconv.Itoa(rand.Intn(9999999))
usr := &user.User{
Email: uid + "@example.com",
Login: uid,
Name: uid,
Company: "",
Password: uid,
EmailVerified: true,
IsAdmin: false,
Created: time.Now(),
Updated: time.Now(),
}
var id int64
err := sqlStore.WithDbSession(context.Background(), func(sess *Session) error {
sess.UseBool("is_admin")
var err error
_, err = sess.Insert(usr)
id = usr.ID
return err
})
require.NoError(t, err)
usr.ID = id
return usr
}
func createDummyDashboard(t *testing.T, sqlStore *sqlstore.SQLStore, dashboardProps DashboardProps) *dashboards.Dashboard {
t.Helper()
json, err := simplejson.NewJson([]byte(`{"schemaVersion":17,"title":"gdev dashboards","uid":"","version":1}`))
require.NoError(t, err)
saveDashboardCmd := dashboards.SaveDashboardCommand{
Dashboard: json,
UserID: 0,
Overwrite: false,
Message: "",
RestoredFrom: 0,
PluginID: "",
FolderID: 0,
IsFolder: false,
UpdatedAt: time.Time{},
}
if dashboardProps.OrgId != 0 {
saveDashboardCmd.OrgID = dashboardProps.OrgId
} else {
saveDashboardCmd.OrgID = 1
}
dash := insertTestDashboard(t, sqlStore, "", saveDashboardCmd.OrgID, 0, false, nil)
require.NoError(t, err)
t.Logf("Created dashboard with ID %d and org ID %d\n", dash.ID, dash.OrgID)
return dash
}
func createDummyACL(t *testing.T, sqlStore *sqlstore.SQLStore, dashboardPermission *DashboardPermission, search Search, dashboardID int64) int64 {
t.Helper()
acl := &dashboards.DashboardACL{
OrgID: 1,
Created: time.Now(),
Updated: time.Now(),
Permission: dashboardPermission.Permission,
DashboardID: dashboardID,
}
var user *user.User
if dashboardPermission.User {
t.Logf("Creating user")
user = createDummyUser(t, sqlStore)
acl.UserID = user.ID
}
if dashboardPermission.Team {
// TODO: Restore/refactor sqlBuilder tests after user, org and team services are split
t.Skip("Creating team: skip, team service is moved")
}
if len(string(dashboardPermission.Role)) > 0 {
acl.Role = &dashboardPermission.Role
}
err := updateDashboardACL(t, sqlStore, dashboardID, acl)
require.NoError(t, err)
if user != nil {
return user.ID
}
return 0
}
func getDashboards(t *testing.T, sqlStore *sqlstore.SQLStore, search Search, aclUserID int64, features featuremgmt.FeatureToggles) []*dashboardResponse {
t.Helper()
old := sqlStore.Cfg.RBACEnabled
sqlStore.Cfg.RBACEnabled = false
defer func() {
sqlStore.Cfg.RBACEnabled = old
}()
recursiveQueriesAreSupported, err := sqlStore.RecursiveQueriesAreSupported()
require.NoError(t, err)
builder := NewSqlBuilder(sqlStore.Cfg, features, sqlStore.GetDialect(), recursiveQueriesAreSupported)
signedInUser := &user.SignedInUser{
UserID: 9999999999,
}
if search.OrgId == 0 {
signedInUser.OrgID = 1
} else {
signedInUser.OrgID = search.OrgId
}
if len(string(search.UsersOrgRole)) > 0 {
signedInUser.OrgRole = search.UsersOrgRole
} else {
signedInUser.OrgRole = org.RoleViewer
}
if search.UserFromACL {
signedInUser.UserID = aclUserID
}
var res []*dashboardResponse
builder.Write("SELECT * FROM dashboard WHERE true")
builder.WriteDashboardPermissionFilter(signedInUser, search.RequiredPermission, "")
t.Logf("Searching for dashboards, SQL: %q\n", builder.GetSQLString())
err = sqlStore.GetEngine().SQL(builder.GetSQLString(), builder.params...).Find(&res)
require.NoError(t, err)
return res
}
// TODO: Use FakeDashboardStore when org has its own service
func insertTestDashboard(t *testing.T, sqlStore *sqlstore.SQLStore, title string, orgId int64,
folderId int64, isFolder bool, tags ...interface{}) *dashboards.Dashboard {
t.Helper()
cmd := dashboards.SaveDashboardCommand{
OrgID: orgId,
FolderID: folderId,
IsFolder: isFolder,
Dashboard: simplejson.NewFromAny(map[string]interface{}{
"id": nil,
"title": title,
"tags": tags,
}),
}
var dash *dashboards.Dashboard
err := sqlStore.WithDbSession(context.Background(), func(sess *Session) error {
dash = cmd.GetDashboardModel()
dash.SetVersion(1)
dash.Created = time.Now()
dash.Updated = time.Now()
dash.UID = util.GenerateShortUID()
_, err := sess.Insert(dash)
return err
})
require.NoError(t, err)
require.NotNil(t, dash)
dash.Data.Set("id", dash.ID)
dash.Data.Set("uid", dash.UID)
err = sqlStore.WithDbSession(context.Background(), func(sess *Session) error {
dashVersion := &dashver.DashboardVersion{
DashboardID: dash.ID,
ParentVersion: dash.Version,
RestoredFrom: cmd.RestoredFrom,
Version: dash.Version,
Created: time.Now(),
CreatedBy: dash.UpdatedBy,
Message: cmd.Message,
Data: dash.Data,
}
require.NoError(t, err)
if affectedRows, err := sess.Insert(dashVersion); err != nil {
return err
} else if affectedRows == 0 {
return dashboards.ErrDashboardNotFound
}
return nil
})
require.NoError(t, err)
return dash
}
// TODO: Use FakeDashboardStore when org has its own service
func updateDashboardACL(t *testing.T, sqlStore *sqlstore.SQLStore, dashboardID int64, items ...*dashboards.DashboardACL) error {
t.Helper()
err := sqlStore.WithDbSession(context.Background(), func(sess *Session) error {
_, err := sess.Exec("DELETE FROM dashboard_acl WHERE dashboard_id=?", dashboardID)
if err != nil {
return fmt.Errorf("deleting from dashboard_acl failed: %w", err)
}
for _, item := range items {
item.Created = time.Now()
item.Updated = time.Now()
if item.UserID == 0 && item.TeamID == 0 && (item.Role == nil || !item.Role.IsValid()) {
return dashboards.ErrDashboardACLInfoMissing
}
if item.DashboardID == 0 {
return dashboards.ErrDashboardPermissionDashboardEmpty
}
sess.Nullable("user_id", "team_id")
if _, err := sess.Insert(item); err != nil {
return err
}
}
// Update dashboard HasACL flag
dashboard := dashboards.Dashboard{HasACL: true}
_, err = sess.Cols("has_acl").Where("id=?", dashboardID).Update(&dashboard)
return err
})
return err
}

View File

@ -80,13 +80,8 @@ type Service struct {
}
func (s *Service) GetUsageStats(_ context.Context) map[string]interface{} {
enabled := 0
if !accesscontrol.IsDisabled(s.cfg) {
enabled = 1
}
return map[string]interface{}{
"stats.oss.accesscontrol.enabled.count": enabled,
"stats.oss.accesscontrol.enabled.count": 1,
}
}
@ -165,11 +160,6 @@ func (s *Service) DeleteUserPermissions(ctx context.Context, orgID int64, userID
// DeclareFixedRoles allow the caller to declare, to the service, fixed roles and their assignments
// to organization roles ("Viewer", "Editor", "Admin") or "Grafana Admin"
func (s *Service) DeclareFixedRoles(registrations ...accesscontrol.RoleRegistration) error {
// If accesscontrol is disabled no need to register roles
if accesscontrol.IsDisabled(s.cfg) {
return nil
}
for _, r := range registrations {
err := accesscontrol.ValidateFixedRole(r.Role)
if err != nil {

View File

@ -45,11 +45,6 @@ func TestUsageMetrics(t *testing.T) {
enabled bool
expectedValue int
}{
{
name: "Expecting metric with value 0",
enabled: false,
expectedValue: 0,
},
{
name: "Expecting metric with value 1",
enabled: true,

View File

@ -239,10 +239,6 @@ func UseGlobalOrg(c *contextmodel.ReqContext) (int64, error) {
func LoadPermissionsMiddleware(service Service) web.Handler {
return func(c *contextmodel.ReqContext) {
if service.IsDisabled() {
return
}
permissions, err := service.GetUserPermissions(c.Req.Context(), c.SignedInUser,
Options{ReloadCache: false})
if err != nil {

View File

@ -34,19 +34,17 @@ func (ss *sqlxStore) GetAPIKeys(ctx context.Context, query *apikey.GetApiKeysQue
where = append(where, "service_account_id IS NULL")
if !accesscontrol.IsDisabled(ss.cfg) {
filter, err := accesscontrol.Filter(query.User, "id", "apikeys:id:", accesscontrol.ActionAPIKeyRead)
if err != nil {
return nil, err
}
where = append(where, filter.Where)
args = append(args, filter.Args...)
filter, err := accesscontrol.Filter(query.User, "id", "apikeys:id:", accesscontrol.ActionAPIKeyRead)
if err != nil {
return nil, err
}
where = append(where, filter.Where)
args = append(args, filter.Args...)
ws := fmt.Sprint(strings.Join(where[:], " AND "))
qr := fmt.Sprintf(`SELECT * FROM api_key WHERE %s ORDER BY name ASC LIMIT 100`, ws)
keys := make([]*apikey.APIKey, 0)
err := ss.sess.Select(ctx, &keys, qr, args...)
err = ss.sess.Select(ctx, &keys, qr, args...)
return keys, err
}

View File

@ -39,13 +39,11 @@ func (ss *sqlStore) GetAPIKeys(ctx context.Context, query *apikey.GetApiKeysQuer
sess = sess.Where("service_account_id IS NULL")
if !accesscontrol.IsDisabled(ss.cfg) {
filter, err := accesscontrol.Filter(query.User, "id", "apikeys:id:", accesscontrol.ActionAPIKeyRead)
if err != nil {
return err
}
sess.And(filter.Where, filter.Args...)
filter, err := accesscontrol.Filter(query.User, "id", "apikeys:id:", accesscontrol.ActionAPIKeyRead)
if err != nil {
return err
}
sess.And(filter.Where, filter.Args...)
res = make([]*apikey.APIKey, 0)
return sess.Find(&res)

View File

@ -26,7 +26,7 @@ type PermissionsSync struct {
}
func (s *PermissionsSync) SyncPermissionsHook(ctx context.Context, identity *authn.Identity, _ *authn.Request) error {
if s.ac.IsDisabled() || !identity.ClientParams.SyncPermissions {
if !identity.ClientParams.SyncPermissions {
return nil
}

View File

@ -17,56 +17,40 @@ func TestPermissionsSync_SyncPermission(t *testing.T) {
type testCase struct {
name string
identity *authn.Identity
rbacDisabled bool
expectedPermissions []accesscontrol.Permission
}
testCases := []testCase{
{
name: "enriches the identity successfully when SyncPermissions is true",
identity: &authn.Identity{ID: "user:2", OrgID: 1, ClientParams: authn.ClientParams{SyncPermissions: true}},
rbacDisabled: false,
name: "enriches the identity successfully when SyncPermissions is true",
identity: &authn.Identity{ID: "user:2", OrgID: 1, ClientParams: authn.ClientParams{SyncPermissions: true}},
expectedPermissions: []accesscontrol.Permission{
{Action: accesscontrol.ActionUsersRead},
},
},
{
name: "does not load the permissions when SyncPermissions is false",
identity: &authn.Identity{ID: "user:2", OrgID: 1, ClientParams: authn.ClientParams{SyncPermissions: true}},
rbacDisabled: false,
name: "does not load the permissions when SyncPermissions is false",
identity: &authn.Identity{ID: "user:2", OrgID: 1, ClientParams: authn.ClientParams{SyncPermissions: true}},
expectedPermissions: []accesscontrol.Permission{
{Action: accesscontrol.ActionUsersRead},
},
},
{
name: "does not load the permissions when RBAC is disabled",
rbacDisabled: true,
identity: &authn.Identity{ID: "user:2", OrgID: 1, ClientParams: authn.ClientParams{SyncPermissions: true}},
expectedPermissions: []accesscontrol.Permission{},
},
}
for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
s := setupTestEnv(tt.rbacDisabled)
s := setupTestEnv()
err := s.SyncPermissionsHook(context.Background(), tt.identity, &authn.Request{})
require.NoError(t, err)
if !tt.rbacDisabled {
assert.Equal(t, 1, len(tt.identity.Permissions))
assert.Equal(t, accesscontrol.GroupScopesByAction(tt.expectedPermissions), tt.identity.Permissions[tt.identity.OrgID])
} else {
assert.Equal(t, 0, len(tt.identity.Permissions))
}
assert.Equal(t, 1, len(tt.identity.Permissions))
assert.Equal(t, accesscontrol.GroupScopesByAction(tt.expectedPermissions), tt.identity.Permissions[tt.identity.OrgID])
})
}
}
func setupTestEnv(rbacDisabled bool) *PermissionsSync {
func setupTestEnv() *PermissionsSync {
acMock := &acmock.Mock{
IsDisabledFunc: func() bool {
return rbacDisabled
},
GetUserPermissionsFunc: func(ctx context.Context, siu *user.SignedInUser, o accesscontrol.Options) ([]accesscontrol.Permission, error) {
return []accesscontrol.Permission{
{Action: accesscontrol.ActionUsersRead},

View File

@ -250,7 +250,7 @@ func (s *Service) Create(ctx context.Context, cmd *folder.CreateFolderCommand) (
return nil, folder.ErrBadRequest.Errorf("missing signed in user")
}
if !s.accessControl.IsDisabled() && s.features.IsEnabled(featuremgmt.FlagNestedFolders) && cmd.ParentUID != "" {
if s.features.IsEnabled(featuremgmt.FlagNestedFolders) && cmd.ParentUID != "" {
// Check that the user is allowed to create a subfolder in this folder
evaluator := accesscontrol.EvalPermission(dashboards.ActionFoldersWrite, dashboards.ScopeFoldersProvider.GetResourceScopeUID(cmd.ParentUID))
hasAccess, evalErr := s.accessControl.Evaluate(ctx, cmd.SignedInUser, evaluator)
@ -549,32 +549,19 @@ func (s *Service) Move(ctx context.Context, cmd *folder.MoveFolderCommand) (*fol
}
// Check that the user is allowed to move the folder to the destination folder
if !s.accessControl.IsDisabled() {
var evaluator accesscontrol.Evaluator
if cmd.NewParentUID != "" {
evaluator = accesscontrol.EvalPermission(dashboards.ActionFoldersWrite, dashboards.ScopeFoldersProvider.GetResourceScopeUID(cmd.NewParentUID))
} else {
// Evaluate folder creation permission when moving folder to the root level
evaluator = accesscontrol.EvalPermission(dashboards.ActionFoldersCreate)
}
hasAccess, evalErr := s.accessControl.Evaluate(ctx, cmd.SignedInUser, evaluator)
if evalErr != nil {
return nil, evalErr
}
if !hasAccess {
return nil, dashboards.ErrFolderAccessDenied
}
var evaluator accesscontrol.Evaluator
if cmd.NewParentUID != "" {
evaluator = accesscontrol.EvalPermission(dashboards.ActionFoldersWrite, dashboards.ScopeFoldersProvider.GetResourceScopeUID(cmd.NewParentUID))
} else {
g, err := guardian.NewByUID(ctx, cmd.UID, cmd.OrgID, cmd.SignedInUser)
if err != nil {
return nil, err
}
if canSave, err := g.CanSave(); err != nil || !canSave {
if err != nil {
return nil, toFolderError(err)
}
return nil, dashboards.ErrFolderAccessDenied
}
// Evaluate folder creation permission when moving folder to the root level
evaluator = accesscontrol.EvalPermission(dashboards.ActionFoldersCreate)
}
hasAccess, evalErr := s.accessControl.Evaluate(ctx, cmd.SignedInUser, evaluator)
if evalErr != nil {
return nil, evalErr
}
if !hasAccess {
return nil, dashboards.ErrFolderAccessDenied
}
// here we get the folder, we need to get the height of current folder

View File

@ -26,7 +26,7 @@ var userAdmin = &user.SignedInUser{UserID: 1, OrgID: 1, OrgRole: org.RoleAdmin,
var userAdminRBAC = &user.SignedInUser{UserID: 2, OrgID: 1, OrgRole: org.RoleAdmin, Login: "testAdminUserRBAC", Permissions: map[int64]map[string][]string{1: {dashboards.ActionDashboardsPublicWrite: {dashboards.ScopeDashboardsAll}}}}
var userViewer = &user.SignedInUser{UserID: 3, OrgID: 1, OrgRole: org.RoleViewer, Login: "testViewerUser"}
var userViewerRBAC = &user.SignedInUser{UserID: 4, OrgID: 1, OrgRole: org.RoleViewer, Login: "testViewerUserRBAC", Permissions: map[int64]map[string][]string{1: {dashboards.ActionDashboardsRead: {dashboards.ScopeDashboardsAll}}}}
var anonymousUser *user.SignedInUser
var anonymousUser = &user.SignedInUser{IsAnonymous: true}
type JsonErrResponse struct {
Error string `json:"error"`

View File

@ -84,7 +84,7 @@ type testContext struct {
func contextProvider(tc *testContext) web.Handler {
return func(c *web.Context) {
signedIn := tc.user != nil
signedIn := tc.user != nil && !tc.user.IsAnonymous
reqCtx := &contextmodel.ReqContext{
Context: c,
SignedInUser: tc.user,

View File

@ -189,7 +189,6 @@ func TestAPIQueryPublicDashboard(t *testing.T) {
setup := func(enabled bool) (*web.Mux, *publicdashboards.FakePublicDashboardService) {
service := publicdashboards.NewFakePublicDashboardService(t)
cfg := setting.NewCfg()
cfg.RBACEnabled = false
testServer := setupTestServer(
t,