Authz: Remove use of SignedInUser copy for permission evaluation (#78448)

* remove use of SignedInUserCopies

* add extra safety to not cross assign permissions

unwind circular dependency

dashboardacl->dashboardaccess

fix missing import

* correctly set teams for permissions

* fix missing inits

* nit: check err

* exit early for api keys
This commit is contained in:
Jo
2023-11-22 14:20:22 +01:00
committed by GitHub
parent 392a4342a8
commit 0de66a8099
44 changed files with 422 additions and 337 deletions
+2 -1
View File
@@ -13,6 +13,7 @@ import (
alertmodels "github.com/grafana/grafana/pkg/services/alerting/models"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/guardian"
"github.com/grafana/grafana/pkg/services/ngalert/notifier/channels_config"
@@ -113,7 +114,7 @@ func (hs *HTTPServer) GetAlerts(c *contextmodel.ReqContext) response.Response {
DashboardIds: dashboardIDs,
Type: string(model.DashHitDB),
FolderIds: folderIDs, // nolint:staticcheck
Permission: dashboards.PERMISSION_VIEW,
Permission: dashboardaccess.PERMISSION_VIEW,
}
hits, err := hs.SearchService.SearchHandler(c.Req.Context(), &searchQuery)
+1 -1
View File
@@ -64,7 +64,7 @@ func (hs *HTTPServer) registerRoutes() {
reqSnapshotPublicModeOrSignedIn := middleware.SnapshotPublicModeOrSignedIn(hs.Cfg)
redirectFromLegacyPanelEditURL := middleware.RedirectFromLegacyPanelEditURL(hs.Cfg)
authorize := ac.Middleware(hs.AccessControl)
authorizeInOrg := ac.AuthorizeInOrgMiddleware(hs.AccessControl, hs.accesscontrolService, hs.userService)
authorizeInOrg := ac.AuthorizeInOrgMiddleware(hs.AccessControl, hs.accesscontrolService, hs.userService, hs.teamService)
quota := middleware.Quota(hs.QuotaService)
r := hs.RouteRegister
+7 -6
View File
@@ -12,6 +12,7 @@ import (
"github.com/grafana/grafana/pkg/services/auth/identity"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/web"
)
@@ -166,10 +167,10 @@ func (hs *HTTPServer) UpdateDashboardPermissions(c *contextmodel.ReqContext) res
return response.Success("Dashboard permissions updated")
}
var dashboardPermissionMap = map[string]dashboards.PermissionType{
"View": dashboards.PERMISSION_VIEW,
"Edit": dashboards.PERMISSION_EDIT,
"Admin": dashboards.PERMISSION_ADMIN,
var dashboardPermissionMap = map[string]dashboardaccess.PermissionType{
"View": dashboardaccess.PERMISSION_VIEW,
"Edit": dashboardaccess.PERMISSION_EDIT,
"Admin": dashboardaccess.PERMISSION_ADMIN,
}
func (hs *HTTPServer) getDashboardACL(ctx context.Context, user identity.Requester, dashboard *dashboards.Dashboard) ([]*dashboards.DashboardACLInfoDTO, error) {
@@ -313,11 +314,11 @@ func (hs *HTTPServer) updateDashboardAccessControl(ctx context.Context, orgID in
func validatePermissionsUpdate(apiCmd dtos.UpdateDashboardACLCommand) error {
for _, item := range apiCmd.Items {
if item.UserID > 0 && item.TeamID > 0 {
return dashboards.ErrPermissionsWithUserAndTeamNotAllowed
return dashboardaccess.ErrPermissionsWithUserAndTeamNotAllowed
}
if (item.UserID > 0 || item.TeamID > 0) && item.Role != nil {
return dashboards.ErrPermissionsWithRoleNotAllowed
return dashboardaccess.ErrPermissionsWithRoleNotAllowed
}
}
return nil
+2 -2
View File
@@ -1,7 +1,7 @@
package dtos
import (
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
"github.com/grafana/grafana/pkg/services/org"
)
@@ -21,5 +21,5 @@ type DashboardACLUpdateItem struct {
// * `2` - Edit
// * `4` - Admin
// Enum: 1,2,4
Permission dashboards.PermissionType `json:"permission"`
Permission dashboardaccess.PermissionType `json:"permission"`
}
+5 -4
View File
@@ -13,6 +13,7 @@ import (
"github.com/grafana/grafana/pkg/services/auth/identity"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/folder"
"github.com/grafana/grafana/pkg/services/guardian"
@@ -186,15 +187,15 @@ func (hs *HTTPServer) setDefaultFolderPermissions(ctx context.Context, orgID int
}
permissions = append(permissions, accesscontrol.SetResourcePermissionCommand{
UserID: userID, Permission: dashboards.PERMISSION_ADMIN.String(),
UserID: userID, Permission: dashboardaccess.PERMISSION_ADMIN.String(),
})
}
isNested := folder.ParentUID != ""
if !isNested || !hs.Features.IsEnabled(ctx, 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()},
{BuiltinRole: string(org.RoleEditor), Permission: dashboardaccess.PERMISSION_EDIT.String()},
{BuiltinRole: string(org.RoleViewer), Permission: dashboardaccess.PERMISSION_VIEW.String()},
}...)
}
@@ -449,7 +450,7 @@ func (hs *HTTPServer) searchFolders(c *contextmodel.ReqContext) ([]*folder.Folde
Limit: c.QueryInt64("limit"),
OrgId: c.SignedInUser.GetOrgID(),
Type: "dash-folder",
Permission: dashboards.PERMISSION_VIEW,
Permission: dashboardaccess.PERMISSION_VIEW,
Page: c.QueryInt64("page"),
}
+2 -1
View File
@@ -27,6 +27,7 @@ import (
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
"github.com/grafana/grafana/pkg/services/dashboards/database"
dashboardservice "github.com/grafana/grafana/pkg/services/dashboards/service"
"github.com/grafana/grafana/pkg/services/featuremgmt"
@@ -270,7 +271,7 @@ func setupDB(b testing.TB) benchScenario {
UserID: userID,
TeamID: teamID,
OrgID: orgID,
Permission: dashboards.PERMISSION_VIEW,
Permission: dashboardaccess.PERMISSION_VIEW,
Created: now,
Updated: now,
})
+5 -4
View File
@@ -11,6 +11,7 @@ import (
"github.com/grafana/grafana/pkg/services/auth/identity"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
"github.com/grafana/grafana/pkg/services/folder"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/web"
@@ -118,10 +119,10 @@ func (hs *HTTPServer) UpdateFolderPermissions(c *contextmodel.ReqContext) respon
return response.Success("Folder permissions updated")
}
var folderPermissionMap = map[string]dashboards.PermissionType{
"View": dashboards.PERMISSION_VIEW,
"Edit": dashboards.PERMISSION_EDIT,
"Admin": dashboards.PERMISSION_ADMIN,
var folderPermissionMap = map[string]dashboardaccess.PermissionType{
"View": dashboardaccess.PERMISSION_VIEW,
"Edit": dashboardaccess.PERMISSION_EDIT,
"Admin": dashboardaccess.PERMISSION_ADMIN,
}
func (hs *HTTPServer) getFolderACL(ctx context.Context, user identity.Requester, folder *folder.Folder) ([]*dashboards.DashboardACLInfoDTO, error) {
+2
View File
@@ -437,6 +437,7 @@ func TestGetOrgUsersAPIEndpoint_AccessControl(t *testing.T) {
}
hs.authInfoService = &authinfotest.FakeService{}
hs.userService = &usertest.FakeUserService{ExpectedSignedInUser: userWithPermissions(1, tc.permissions)}
hs.accesscontrolService = &actest.FakeService{}
})
u := userWithPermissions(1, tc.permissions)
@@ -482,6 +483,7 @@ func TestPostOrgUsersAPIEndpoint_AccessControl(t *testing.T) {
ExpectedUser: &user.User{},
ExpectedSignedInUser: userWithPermissions(1, tt.permissions),
}
hs.accesscontrolService = &actest.FakeService{}
})
u := userWithPermissions(1, tt.permissions)
+3 -3
View File
@@ -7,7 +7,7 @@ import (
"github.com/grafana/grafana/pkg/api/response"
"github.com/grafana/grafana/pkg/infra/metrics"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess"
"github.com/grafana/grafana/pkg/services/search"
"github.com/grafana/grafana/pkg/services/search/model"
"github.com/grafana/grafana/pkg/util"
@@ -28,14 +28,14 @@ func (hs *HTTPServer) Search(c *contextmodel.ReqContext) response.Response {
page := c.QueryInt64("page")
dashboardType := c.Query("type")
sort := c.Query("sort")
permission := dashboards.PERMISSION_VIEW
permission := dashboardaccess.PERMISSION_VIEW
if limit > 5000 {
return response.Error(422, "Limit is above maximum allowed (5000), use page parameter to access hits beyond limit", nil)
}
if c.Query("permission") == "Edit" {
permission = dashboards.PERMISSION_EDIT
permission = dashboardaccess.PERMISSION_EDIT
}
dbIDs := make([]int64, 0)