Access control: Add access control sql filter to org user queries (#43961)

* Add access control SQL filter to org user queries
This commit is contained in:
Karl Persson
2022-01-13 14:40:32 +01:00
committed by GitHub
parent ccd9e46dda
commit f999910dc6
11 changed files with 266 additions and 36 deletions
+4 -4
View File
@@ -54,7 +54,7 @@ func (hs *HTTPServer) registerRoutes() {
r.Get("/datasources/", authorize(reqOrgAdmin, dataSourcesConfigurationAccessEvaluator), hs.Index)
r.Get("/datasources/new", authorize(reqOrgAdmin, dataSourcesNewAccessEvaluator), hs.Index)
r.Get("/datasources/edit/*", authorize(reqOrgAdmin, dataSourcesEditAccessEvaluator), hs.Index)
r.Get("/org/users", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersRead, ac.ScopeUsersAll)), hs.Index)
r.Get("/org/users", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersRead)), hs.Index)
r.Get("/org/users/new", reqOrgAdmin, hs.Index)
r.Get("/org/users/invite", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionUsersCreate)), hs.Index)
r.Get("/org/teams", reqCanAccessTeams, hs.Index)
@@ -206,8 +206,8 @@ func (hs *HTTPServer) registerRoutes() {
userIDScope := ac.Scope("users", "id", ac.Parameter(":userId"))
orgRoute.Put("/", authorize(reqOrgAdmin, ac.EvalPermission(ActionOrgsWrite)), routing.Wrap(UpdateCurrentOrg))
orgRoute.Put("/address", authorize(reqOrgAdmin, ac.EvalPermission(ActionOrgsWrite)), routing.Wrap(UpdateCurrentOrgAddress))
orgRoute.Get("/users", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersRead, ac.ScopeUsersAll)), routing.Wrap(hs.GetOrgUsersForCurrentOrg))
orgRoute.Get("/users/search", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersRead, ac.ScopeUsersAll)), routing.Wrap(hs.SearchOrgUsersWithPaging))
orgRoute.Get("/users", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersRead)), routing.Wrap(hs.GetOrgUsersForCurrentOrg))
orgRoute.Get("/users/search", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersRead)), routing.Wrap(hs.SearchOrgUsersWithPaging))
orgRoute.Post("/users", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersAdd, ac.ScopeUsersAll)), quota("user"), routing.Wrap(hs.AddOrgUserToCurrentOrg))
orgRoute.Patch("/users/:userId", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersRoleUpdate, userIDScope)), routing.Wrap(hs.UpdateOrgUserForCurrentOrg))
orgRoute.Delete("/users/:userId", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersRemove, userIDScope)), routing.Wrap(hs.RemoveOrgUserForCurrentOrg))
@@ -224,7 +224,7 @@ func (hs *HTTPServer) registerRoutes() {
// current org without requirement of user to be org admin
apiRoute.Group("/org", func(orgRoute routing.RouteRegister) {
orgRoute.Get("/users/lookup", authorize(reqOrgAdminFolderAdminOrTeamAdmin, ac.EvalPermission(ac.ActionOrgUsersRead, ac.ScopeUsersAll)), routing.Wrap(hs.GetOrgUsersForCurrentOrgLookup))
orgRoute.Get("/users/lookup", authorize(reqOrgAdminFolderAdminOrTeamAdmin, ac.EvalPermission(ac.ActionOrgUsersRead)), routing.Wrap(hs.GetOrgUsersForCurrentOrgLookup))
})
// create new org
+3
View File
@@ -22,6 +22,7 @@ import (
"github.com/grafana/grafana/pkg/infra/usagestats"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/accesscontrol"
acmiddleware "github.com/grafana/grafana/pkg/services/accesscontrol/middleware"
accesscontrolmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
"github.com/grafana/grafana/pkg/services/accesscontrol/ossaccesscontrol"
"github.com/grafana/grafana/pkg/services/auth"
@@ -355,6 +356,8 @@ func setupHTTPServerWithCfg(t *testing.T, useFakeAccessControl, enableAccessCont
c.Map(initCtx)
})
m.Use(acmiddleware.LoadPermissionsMiddleware(hs.AccessControl))
// Register all routes
hs.registerRoutes()
hs.RouteRegister.Register(m.Router)
+1 -1
View File
@@ -251,7 +251,7 @@ func (hs *HTTPServer) getNavTree(c *models.ReqContext, hasEditPerm bool) ([]*dto
})
}
if hasAccess(ac.ReqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersRead, ac.ScopeUsersAll)) {
if hasAccess(ac.ReqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersRead)) {
configNodes = append(configNodes, &dtos.NavLink{
Text: "Users",
Id: "users",
+5 -1
View File
@@ -71,6 +71,7 @@ func (hs *HTTPServer) GetOrgUsersForCurrentOrg(c *models.ReqContext) response.Re
OrgId: c.OrgId,
Query: c.Query("query"),
Limit: c.QueryInt("limit"),
User: c.SignedInUser,
}, c.SignedInUser)
if err != nil {
@@ -86,6 +87,7 @@ func (hs *HTTPServer) GetOrgUsersForCurrentOrgLookup(c *models.ReqContext) respo
OrgId: c.OrgId,
Query: c.Query("query"),
Limit: c.QueryInt("limit"),
User: c.SignedInUser,
}, c.SignedInUser)
if err != nil {
@@ -124,6 +126,7 @@ func (hs *HTTPServer) GetOrgUsers(c *models.ReqContext) response.Response {
OrgId: c.ParamsInt64(":orgId"),
Query: "",
Limit: 0,
User: c.SignedInUser,
}, c.SignedInUser)
if err != nil {
@@ -183,8 +186,9 @@ func (hs *HTTPServer) SearchOrgUsersWithPaging(c *models.ReqContext) response.Re
query := &models.SearchOrgUsersQuery{
OrgID: c.OrgId,
Query: c.Query("query"),
Limit: perPage,
Page: page,
Limit: perPage,
User: c.SignedInUser,
}
if err := hs.SQLStore.SearchOrgUsers(ctx, query); err != nil {
+12 -2
View File
@@ -38,6 +38,7 @@ func TestOrgUsersAPIEndpoint_userLoggedIn(t *testing.T) {
hs := &HTTPServer{Cfg: settings}
sqlStore := sqlstore.InitTestDB(t)
sqlStore.Cfg = settings
hs.SQLStore = sqlStore
loggedInUserScenario(t, "When calling GET on", "api/org/users", func(sc *scenarioContext) {
@@ -556,7 +557,10 @@ func TestPostOrgUsersAPIEndpoint_AccessControl(t *testing.T) {
require.NoError(t, err)
assert.EqualValuesf(t, tc.expectedMessage, message, "server did not answer expected message")
getUsersQuery := models.GetOrgUsersQuery{OrgId: tc.targetOrg}
getUsersQuery := models.GetOrgUsersQuery{OrgId: tc.targetOrg, User: &models.SignedInUser{
OrgId: tc.targetOrg,
Permissions: map[int64]map[string][]string{tc.targetOrg: {"org.users:read": {"users:*"}}},
}}
err = sc.db.GetOrgUsers(context.Background(), &getUsersQuery)
require.NoError(t, err)
assert.Len(t, getUsersQuery.Result, tc.expectedUserCount)
@@ -799,7 +803,13 @@ func TestDeleteOrgUsersAPIEndpoint_AccessControl(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, tc.expectedMessage, message)
getUsersQuery := models.GetOrgUsersQuery{OrgId: tc.targetOrg}
getUsersQuery := models.GetOrgUsersQuery{
OrgId: tc.targetOrg,
User: &models.SignedInUser{
OrgId: tc.targetOrg,
Permissions: map[int64]map[string][]string{tc.targetOrg: {accesscontrol.ActionOrgUsersRead: {accesscontrol.ScopeUsersAll}}},
},
}
err = sc.db.GetOrgUsers(context.Background(), &getUsersQuery)
require.NoError(t, err)
assert.Len(t, getUsersQuery.Result, tc.expectedUserCount)