mirror of
https://github.com/grafana/grafana.git
synced 2024-11-24 09:50:29 -06:00
DataSourcePermissions: Handle licensing properly for ds permissions (#59694)
* RBAC: add viewer grand if dspermissions enforcement is not enabled * RBAC: Change permissions based on role prefix * RBAC: Add option to for permission service to add a license middleware * RBAC: Remove actions from query struct
This commit is contained in:
parent
a7d4bbf024
commit
6d1bcd9f40
@ -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)}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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,
|
||||
})
|
||||
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -15,3 +15,5 @@ func disableMiddleware(shouldDisable bool) web.Handler {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func nopMiddleware(c *models.ReqContext) {}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user