mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
This reverts commit 88c11f1cc0.
This commit is contained in:
@@ -1,169 +0,0 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/provisioning"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type reloadProvisioningTestCase struct {
|
||||
desc string
|
||||
url string
|
||||
expectedCode int
|
||||
expectedBody string
|
||||
permissions []*accesscontrol.Permission
|
||||
exit bool
|
||||
checkCall func(mock provisioning.ProvisioningServiceMock)
|
||||
}
|
||||
|
||||
func TestAPI_AdminProvisioningReload_AccessControl(t *testing.T) {
|
||||
tests := []reloadProvisioningTestCase{
|
||||
{
|
||||
desc: "should work for dashboards with specific scope",
|
||||
expectedCode: http.StatusOK,
|
||||
expectedBody: `{"message":"Dashboards config reloaded"}`,
|
||||
permissions: []*accesscontrol.Permission{
|
||||
{
|
||||
Action: ActionProvisioningReload,
|
||||
Scope: ScopeProvisionersDashboards,
|
||||
},
|
||||
},
|
||||
url: "/api/admin/provisioning/dashboards/reload",
|
||||
checkCall: func(mock provisioning.ProvisioningServiceMock) {
|
||||
assert.Len(t, mock.Calls.ProvisionDashboards, 1)
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "should work for dashboards with broader scope",
|
||||
expectedCode: http.StatusOK,
|
||||
expectedBody: `{"message":"Dashboards config reloaded"}`,
|
||||
permissions: []*accesscontrol.Permission{
|
||||
{
|
||||
Action: ActionProvisioningReload,
|
||||
Scope: ScopeProvisionersAll,
|
||||
},
|
||||
},
|
||||
url: "/api/admin/provisioning/dashboards/reload",
|
||||
checkCall: func(mock provisioning.ProvisioningServiceMock) {
|
||||
assert.Len(t, mock.Calls.ProvisionDashboards, 1)
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "should fail for dashboard with wrong scope",
|
||||
expectedCode: http.StatusForbidden,
|
||||
permissions: []*accesscontrol.Permission{
|
||||
{
|
||||
Action: ActionProvisioningReload,
|
||||
Scope: "services:noservice",
|
||||
},
|
||||
},
|
||||
url: "/api/admin/provisioning/dashboards/reload",
|
||||
exit: true,
|
||||
},
|
||||
{
|
||||
desc: "should fail for dashboard with no permission",
|
||||
expectedCode: http.StatusForbidden,
|
||||
url: "/api/admin/provisioning/dashboards/reload",
|
||||
exit: true,
|
||||
},
|
||||
{
|
||||
desc: "should work for notifications with specific scope",
|
||||
expectedCode: http.StatusOK,
|
||||
expectedBody: `{"message":"Notifications config reloaded"}`,
|
||||
permissions: []*accesscontrol.Permission{
|
||||
{
|
||||
Action: ActionProvisioningReload,
|
||||
Scope: ScopeProvisionersNotifications,
|
||||
},
|
||||
},
|
||||
url: "/api/admin/provisioning/notifications/reload",
|
||||
checkCall: func(mock provisioning.ProvisioningServiceMock) {
|
||||
assert.Len(t, mock.Calls.ProvisionNotifications, 1)
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "should fail for notifications with no permission",
|
||||
expectedCode: http.StatusForbidden,
|
||||
url: "/api/admin/provisioning/notifications/reload",
|
||||
exit: true,
|
||||
},
|
||||
{
|
||||
desc: "should work for datasources with specific scope",
|
||||
expectedCode: http.StatusOK,
|
||||
expectedBody: `{"message":"Datasources config reloaded"}`,
|
||||
permissions: []*accesscontrol.Permission{
|
||||
{
|
||||
Action: ActionProvisioningReload,
|
||||
Scope: ScopeProvisionersDatasources,
|
||||
},
|
||||
},
|
||||
url: "/api/admin/provisioning/datasources/reload",
|
||||
checkCall: func(mock provisioning.ProvisioningServiceMock) {
|
||||
assert.Len(t, mock.Calls.ProvisionDatasources, 1)
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "should fail for datasources with no permission",
|
||||
expectedCode: http.StatusForbidden,
|
||||
url: "/api/admin/provisioning/datasources/reload",
|
||||
exit: true,
|
||||
},
|
||||
{
|
||||
desc: "should work for plugins with specific scope",
|
||||
expectedCode: http.StatusOK,
|
||||
expectedBody: `{"message":"Plugins config reloaded"}`,
|
||||
permissions: []*accesscontrol.Permission{
|
||||
{
|
||||
Action: ActionProvisioningReload,
|
||||
Scope: ScopeProvisionersPlugins,
|
||||
},
|
||||
},
|
||||
url: "/api/admin/provisioning/plugins/reload",
|
||||
checkCall: func(mock provisioning.ProvisioningServiceMock) {
|
||||
assert.Len(t, mock.Calls.ProvisionPlugins, 1)
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "should fail for plugins with no permission",
|
||||
expectedCode: http.StatusForbidden,
|
||||
url: "/api/admin/provisioning/plugins/reload",
|
||||
exit: true,
|
||||
},
|
||||
}
|
||||
|
||||
cfg := setting.NewCfg()
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
sc, hs := setupAccessControlScenarioContext(t, cfg, test.url, test.permissions)
|
||||
|
||||
// Setup the mock
|
||||
provisioningMock := provisioning.NewProvisioningServiceMock()
|
||||
hs.ProvisioningService = provisioningMock
|
||||
|
||||
sc.resp = httptest.NewRecorder()
|
||||
var err error
|
||||
sc.req, err = http.NewRequest(http.MethodPost, test.url, nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
sc.exec()
|
||||
|
||||
// Check return code
|
||||
assert.Equal(t, test.expectedCode, sc.resp.Code)
|
||||
if test.exit {
|
||||
return
|
||||
}
|
||||
|
||||
// Check body
|
||||
assert.Equal(t, test.expectedBody, sc.resp.Body.String())
|
||||
|
||||
// Check we actually called the provisioning service
|
||||
test.checkCall(*provisioningMock)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -445,11 +445,10 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
adminRoute.Get("/stats", authorize(reqGrafanaAdmin, accesscontrol.ActionServerStatsRead), routing.Wrap(AdminGetStats))
|
||||
adminRoute.Post("/pause-all-alerts", reqGrafanaAdmin, bind(dtos.PauseAllAlertsCommand{}), routing.Wrap(PauseAllAlerts))
|
||||
|
||||
adminRoute.Post("/provisioning/dashboards/reload", authorize(reqGrafanaAdmin, ActionProvisioningReload, ScopeProvisionersDashboards), routing.Wrap(hs.AdminProvisioningReloadDashboards))
|
||||
adminRoute.Post("/provisioning/plugins/reload", authorize(reqGrafanaAdmin, ActionProvisioningReload, ScopeProvisionersPlugins), routing.Wrap(hs.AdminProvisioningReloadPlugins))
|
||||
adminRoute.Post("/provisioning/datasources/reload", authorize(reqGrafanaAdmin, ActionProvisioningReload, ScopeProvisionersDatasources), routing.Wrap(hs.AdminProvisioningReloadDatasources))
|
||||
adminRoute.Post("/provisioning/notifications/reload", authorize(reqGrafanaAdmin, ActionProvisioningReload, ScopeProvisionersNotifications), routing.Wrap(hs.AdminProvisioningReloadNotifications))
|
||||
|
||||
adminRoute.Post("/provisioning/dashboards/reload", reqGrafanaAdmin, routing.Wrap(hs.AdminProvisioningReloadDashboards))
|
||||
adminRoute.Post("/provisioning/plugins/reload", reqGrafanaAdmin, routing.Wrap(hs.AdminProvisioningReloadPlugins))
|
||||
adminRoute.Post("/provisioning/datasources/reload", reqGrafanaAdmin, routing.Wrap(hs.AdminProvisioningReloadDatasources))
|
||||
adminRoute.Post("/provisioning/notifications/reload", reqGrafanaAdmin, routing.Wrap(hs.AdminProvisioningReloadNotifications))
|
||||
adminRoute.Post("/ldap/reload", authorize(reqGrafanaAdmin, accesscontrol.ActionLDAPConfigReload), routing.Wrap(hs.ReloadLDAPCfg))
|
||||
adminRoute.Post("/ldap/sync/:id", authorize(reqGrafanaAdmin, accesscontrol.ActionLDAPUsersSync), routing.Wrap(hs.PostSyncUserWithLDAP))
|
||||
adminRoute.Get("/ldap/:username", authorize(reqGrafanaAdmin, accesscontrol.ActionLDAPUsersRead), routing.Wrap(hs.GetUserFromLDAP))
|
||||
|
||||
@@ -253,10 +253,6 @@ func (f *fakeAccessControl) IsDisabled() bool {
|
||||
return f.isDisabled
|
||||
}
|
||||
|
||||
func (f *fakeAccessControl) DeclareFixedRoles(registrations ...accesscontrol.RoleRegistration) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func setupAccessControlScenarioContext(t *testing.T, cfg *setting.Cfg, url string, permissions []*accesscontrol.Permission) (*scenarioContext, *HTTPServer) {
|
||||
cfg.FeatureToggles = make(map[string]bool)
|
||||
cfg.FeatureToggles["accesscontrol"] = true
|
||||
|
||||
@@ -117,7 +117,8 @@ func (hs *HTTPServer) Init() error {
|
||||
|
||||
hs.macaron = hs.newMacaron()
|
||||
hs.registerRoutes()
|
||||
return hs.declareFixedRoles()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) AddMiddleware(middleware macaron.Handler) {
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
)
|
||||
|
||||
// API related actions
|
||||
const (
|
||||
ActionProvisioningReload = "provisioning:reload"
|
||||
)
|
||||
|
||||
// API related scopes
|
||||
const (
|
||||
ScopeProvisionersAll = "provisioners:*"
|
||||
ScopeProvisionersDashboards = "provisioners:dashboards"
|
||||
ScopeProvisionersPlugins = "provisioners:plugins"
|
||||
ScopeProvisionersDatasources = "provisioners:datasources"
|
||||
ScopeProvisionersNotifications = "provisioners:notifications"
|
||||
)
|
||||
|
||||
// declareFixedRoles declares to the AccessControl service fixed roles and their
|
||||
// grants to organization roles ("Viewer", "Editor", "Admin") or "Grafana Admin"
|
||||
// that HTTPServer needs
|
||||
func (hs *HTTPServer) declareFixedRoles() error {
|
||||
registration := accesscontrol.RoleRegistration{
|
||||
Role: accesscontrol.RoleDTO{
|
||||
Version: 1,
|
||||
Name: "fixed:provisioning:admin",
|
||||
Description: "Reload provisioning configurations",
|
||||
Permissions: []accesscontrol.Permission{
|
||||
{
|
||||
Action: ActionProvisioningReload,
|
||||
Scope: ScopeProvisionersAll,
|
||||
},
|
||||
},
|
||||
},
|
||||
Grants: []string{accesscontrol.RoleGrafanaAdmin},
|
||||
}
|
||||
|
||||
return hs.AccessControl.DeclareFixedRoles(registration)
|
||||
}
|
||||
Reference in New Issue
Block a user