diff --git a/pkg/api/accesscontrol.go b/pkg/api/accesscontrol.go index 3fd170c6b70..035cf4ac315 100644 --- a/pkg/api/accesscontrol.go +++ b/pkg/api/accesscontrol.go @@ -114,7 +114,7 @@ func (hs *HTTPServer) declareFixedRoles() error { } // when running oss or enterprise without a license all users should be able to query data sources - if !hs.License.FeatureEnabled("accesscontrol.enforcement") { + if !hs.License.FeatureEnabled("dspermissions.enforcement") { datasourcesReaderRole.Grants = []string{string(org.RoleViewer)} } diff --git a/pkg/services/accesscontrol/acimpl/service.go b/pkg/services/accesscontrol/acimpl/service.go index d5d479c64ac..b915a1b3123 100644 --- a/pkg/services/accesscontrol/acimpl/service.go +++ b/pkg/services/accesscontrol/acimpl/service.go @@ -18,7 +18,6 @@ import ( "github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol/api" "github.com/grafana/grafana/pkg/services/accesscontrol/database" - "github.com/grafana/grafana/pkg/services/accesscontrol/ossaccesscontrol" "github.com/grafana/grafana/pkg/services/accesscontrol/pluginutils" "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/user" @@ -87,10 +86,6 @@ func (s *Service) GetUsageStats(_ context.Context) map[string]interface{} { } } -var actionsToFetch = append( - ossaccesscontrol.TeamAdminActions, append(ossaccesscontrol.DashboardAdminActions, append(ossaccesscontrol.FolderAdminActions, ossaccesscontrol.ServiceAccountAdminActions...)...)..., -) - // GetUserPermissions returns user permissions based on built-in roles func (s *Service) GetUserPermissions(ctx context.Context, user *user.SignedInUser, options accesscontrol.Options) ([]accesscontrol.Permission, error) { timer := prometheus.NewTimer(metrics.MAccessPermissionsSummary) @@ -112,11 +107,11 @@ func (s *Service) getUserPermissions(ctx context.Context, user *user.SignedInUse } dbPermissions, err := s.store.GetUserPermissions(ctx, accesscontrol.GetUserPermissionsQuery{ - OrgID: user.OrgID, - UserID: user.UserID, - Roles: accesscontrol.GetOrgRoles(user), - TeamIDs: user.Teams, - Actions: actionsToFetch, + OrgID: user.OrgID, + UserID: user.UserID, + Roles: accesscontrol.GetOrgRoles(user), + TeamIDs: user.Teams, + RolePrefix: accesscontrol.ManagedRolePrefix, }) if err != nil { return nil, err diff --git a/pkg/services/accesscontrol/database/database.go b/pkg/services/accesscontrol/database/database.go index eed62580b2b..99508e51c16 100644 --- a/pkg/services/accesscontrol/database/database.go +++ b/pkg/services/accesscontrol/database/database.go @@ -35,16 +35,11 @@ func (s *AccessControlStore) GetUserPermissions(ctx context.Context, query acces INNER JOIN role ON role.id = permission.role_id ` + filter - if len(query.Actions) > 0 { - q += " WHERE permission.action IN(" - if len(query.Actions) > 0 { - q += "?" + strings.Repeat(",?", len(query.Actions)-1) - } - q += ")" - for _, a := range query.Actions { - params = append(params, a) - } + if query.RolePrefix != "" { + q += " WHERE role.name LIKE ?" + params = append(params, query.RolePrefix+"%") } + if err := sess.SQL(q, params...).Find(&result); err != nil { return err } diff --git a/pkg/services/accesscontrol/database/database_test.go b/pkg/services/accesscontrol/database/database_test.go index 57c482c0f91..f45dc2d389e 100644 --- a/pkg/services/accesscontrol/database/database_test.go +++ b/pkg/services/accesscontrol/database/database_test.go @@ -30,7 +30,6 @@ type getUserPermissionsTestCase struct { userPermissions []string teamPermissions []string builtinPermissions []string - actions []string expected int } @@ -63,16 +62,6 @@ func TestAccessControlStore_GetUserPermissions(t *testing.T) { builtinPermissions: []string{"5", "6"}, expected: 5, }, - { - desc: "Should filter on actions", - orgID: 1, - role: "", - userPermissions: []string{"1", "2", "10"}, - teamPermissions: []string{"100", "2"}, - builtinPermissions: []string{"5", "6"}, - expected: 3, - actions: []string{"dashboards:write"}, - }, { desc: "should only get br permissions for anonymous user", anonymousUser: true, @@ -137,7 +126,6 @@ func TestAccessControlStore_GetUserPermissions(t *testing.T) { OrgID: tt.orgID, UserID: userID, Roles: roles, - Actions: tt.actions, TeamIDs: teamIDs, }) diff --git a/pkg/services/accesscontrol/models.go b/pkg/services/accesscontrol/models.go index e32bb26a2b7..aed3173e305 100644 --- a/pkg/services/accesscontrol/models.go +++ b/pkg/services/accesscontrol/models.go @@ -215,11 +215,11 @@ func (p Permission) OSSPermission() Permission { } type GetUserPermissionsQuery struct { - OrgID int64 `json:"-"` - UserID int64 `json:"userId"` - Roles []string - Actions []string - TeamIDs []int64 + OrgID int64 + UserID int64 + Roles []string + TeamIDs []int64 + RolePrefix string } // ResourcePermission is structure that holds all actions that either a team / user / builtin-role diff --git a/pkg/services/accesscontrol/resourcepermissions/api.go b/pkg/services/accesscontrol/resourcepermissions/api.go index 2343915203e..094221df7e6 100644 --- a/pkg/services/accesscontrol/resourcepermissions/api.go +++ b/pkg/services/accesscontrol/resourcepermissions/api.go @@ -33,6 +33,10 @@ func newApi(ac accesscontrol.AccessControl, router routing.RouteRegister, manage func (a *api) registerEndpoints() { auth := accesscontrol.Middleware(a.ac) disable := disableMiddleware(a.ac.IsDisabled()) + licenseMW := a.service.options.LicenseMW + if licenseMW == nil { + licenseMW = nopMiddleware + } a.router.Group(fmt.Sprintf("/api/access-control/%s", a.service.options.Resource), func(r routing.RouteRegister) { actionRead := fmt.Sprintf("%s.permissions:read", a.service.options.Resource) @@ -40,15 +44,15 @@ func (a *api) registerEndpoints() { scope := accesscontrol.Scope(a.service.options.Resource, a.service.options.ResourceAttribute, accesscontrol.Parameter(":resourceID")) r.Get("/description", auth(disable, accesscontrol.EvalPermission(actionRead)), routing.Wrap(a.getDescription)) r.Get("/:resourceID", auth(disable, accesscontrol.EvalPermission(actionRead, scope)), routing.Wrap(a.getPermissions)) - r.Post("/:resourceID", auth(disable, accesscontrol.EvalPermission(actionWrite, scope)), routing.Wrap(a.setPermissions)) + r.Post("/:resourceID", licenseMW, auth(disable, accesscontrol.EvalPermission(actionWrite, scope)), routing.Wrap(a.setPermissions)) if a.service.options.Assignments.Users { - r.Post("/:resourceID/users/:userID", auth(disable, accesscontrol.EvalPermission(actionWrite, scope)), routing.Wrap(a.setUserPermission)) + r.Post("/:resourceID/users/:userID", licenseMW, auth(disable, accesscontrol.EvalPermission(actionWrite, scope)), routing.Wrap(a.setUserPermission)) } if a.service.options.Assignments.Teams { - r.Post("/:resourceID/teams/:teamID", auth(disable, accesscontrol.EvalPermission(actionWrite, scope)), routing.Wrap(a.setTeamPermission)) + r.Post("/:resourceID/teams/:teamID", licenseMW, auth(disable, accesscontrol.EvalPermission(actionWrite, scope)), routing.Wrap(a.setTeamPermission)) } if a.service.options.Assignments.BuiltInRoles { - r.Post("/:resourceID/builtInRoles/:builtInRole", auth(disable, accesscontrol.EvalPermission(actionWrite, scope)), routing.Wrap(a.setBuiltinRolePermission)) + r.Post("/:resourceID/builtInRoles/:builtInRole", licenseMW, auth(disable, accesscontrol.EvalPermission(actionWrite, scope)), routing.Wrap(a.setBuiltinRolePermission)) } }) } diff --git a/pkg/services/accesscontrol/resourcepermissions/middleware.go b/pkg/services/accesscontrol/resourcepermissions/middleware.go index 7619a661eb3..fead18fb9b8 100644 --- a/pkg/services/accesscontrol/resourcepermissions/middleware.go +++ b/pkg/services/accesscontrol/resourcepermissions/middleware.go @@ -15,3 +15,5 @@ func disableMiddleware(shouldDisable bool) web.Handler { } } } + +func nopMiddleware(c *models.ReqContext) {} diff --git a/pkg/services/accesscontrol/resourcepermissions/options.go b/pkg/services/accesscontrol/resourcepermissions/options.go index 736bf2edfdc..cea4888a911 100644 --- a/pkg/services/accesscontrol/resourcepermissions/options.go +++ b/pkg/services/accesscontrol/resourcepermissions/options.go @@ -5,6 +5,7 @@ import ( "github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/services/accesscontrol" + "github.com/grafana/grafana/pkg/web" ) type ResourceValidator func(ctx context.Context, orgID int64, resourceID string) error @@ -39,4 +40,6 @@ type Options struct { OnSetBuiltInRole func(session *db.Session, orgID int64, builtInRole, resourceID, permission string) error // InheritedScopesSolver if configured can generate additional scopes that will be used when fetching permissions for a resource InheritedScopesSolver InheritedScopesSolver + // LicenseMV if configured is applied to endpoints that can modify permissions + LicenseMW web.Handler } diff --git a/public/app/features/datasources/state/navModel.ts b/public/app/features/datasources/state/navModel.ts index 9a037c74119..50226da0013 100644 --- a/public/app/features/datasources/state/navModel.ts +++ b/public/app/features/datasources/state/navModel.ts @@ -68,7 +68,7 @@ export function buildNavModel(dataSource: DataSourceSettings, plugin: GenericDat dsPermissions.tabSuffix = () => ProBadge({ experimentId: permissionsExperimentId, eventVariant: 'trial' }); } - if (featureEnabled('dspermissions')) { + if (featureEnabled('dspermissions.enforcement')) { if (contextSrv.hasPermission(AccessControlAction.DataSourcesPermissionsRead)) { navModel.children!.push(dsPermissions); }