mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Access control: Move data source actions and scopes to datasource package (#46594)
* Add permission actions and id scope * Remove scope and actions variable prefix * Move page evaluators and rename them
This commit is contained in:
@@ -83,12 +83,12 @@ func (hs *HTTPServer) declareFixedRoles() error {
|
|||||||
Group: "Data sources",
|
Group: "Data sources",
|
||||||
Permissions: []ac.Permission{
|
Permissions: []ac.Permission{
|
||||||
{
|
{
|
||||||
Action: datasources.ActionDatasourcesRead,
|
Action: datasources.ActionRead,
|
||||||
Scope: datasources.ScopeDatasourcesProvider.GetResourceAllScope(),
|
Scope: datasources.ScopeAll,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Action: datasources.ActionDatasourcesQuery,
|
Action: datasources.ActionQuery,
|
||||||
Scope: datasources.ScopeDatasourcesAll,
|
Scope: datasources.ScopeAll,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -104,15 +104,15 @@ func (hs *HTTPServer) declareFixedRoles() error {
|
|||||||
Group: "Data sources",
|
Group: "Data sources",
|
||||||
Permissions: ac.ConcatPermissions(datasourcesReaderRole.Role.Permissions, []ac.Permission{
|
Permissions: ac.ConcatPermissions(datasourcesReaderRole.Role.Permissions, []ac.Permission{
|
||||||
{
|
{
|
||||||
Action: datasources.ActionDatasourcesWrite,
|
Action: datasources.ActionWrite,
|
||||||
Scope: datasources.ScopeDatasourcesAll,
|
Scope: datasources.ScopeAll,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Action: datasources.ActionDatasourcesCreate,
|
Action: datasources.ActionCreate,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Action: datasources.ActionDatasourcesDelete,
|
Action: datasources.ActionDelete,
|
||||||
Scope: datasources.ScopeDatasourcesAll,
|
Scope: datasources.ScopeAll,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
@@ -128,8 +128,8 @@ func (hs *HTTPServer) declareFixedRoles() error {
|
|||||||
Group: "Infrequently used",
|
Group: "Infrequently used",
|
||||||
Permissions: []ac.Permission{
|
Permissions: []ac.Permission{
|
||||||
{
|
{
|
||||||
Action: datasources.ActionDatasourcesIDRead,
|
Action: datasources.ActionIDRead,
|
||||||
Scope: datasources.ScopeDatasourcesAll,
|
Scope: datasources.ScopeAll,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -144,8 +144,8 @@ func (hs *HTTPServer) declareFixedRoles() error {
|
|||||||
Description: "Only used for open source compatibility. Query data sources.",
|
Description: "Only used for open source compatibility. Query data sources.",
|
||||||
Group: "Infrequently used",
|
Group: "Infrequently used",
|
||||||
Permissions: []ac.Permission{
|
Permissions: []ac.Permission{
|
||||||
{Action: datasources.ActionDatasourcesQuery},
|
{Action: datasources.ActionQuery},
|
||||||
{Action: datasources.ActionDatasourcesRead},
|
{Action: datasources.ActionRead},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Grants: []string{string(models.ROLE_VIEWER)},
|
Grants: []string{string(models.ROLE_VIEWER)},
|
||||||
@@ -387,29 +387,6 @@ func (hs *HTTPServer) declareFixedRoles() error {
|
|||||||
// Evaluators
|
// Evaluators
|
||||||
// here is the list of complex evaluators we use in this package
|
// here is the list of complex evaluators we use in this package
|
||||||
|
|
||||||
// dataSourcesConfigurationAccessEvaluator is used to protect the "Configure > Data sources" tab access
|
|
||||||
var dataSourcesConfigurationAccessEvaluator = ac.EvalAll(
|
|
||||||
ac.EvalPermission(datasources.ActionDatasourcesRead),
|
|
||||||
ac.EvalAny(
|
|
||||||
ac.EvalPermission(datasources.ActionDatasourcesCreate),
|
|
||||||
ac.EvalPermission(datasources.ActionDatasourcesDelete),
|
|
||||||
ac.EvalPermission(datasources.ActionDatasourcesWrite),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
// dataSourcesNewAccessEvaluator is used to protect the "Configure > Data sources > New" page access
|
|
||||||
var dataSourcesNewAccessEvaluator = ac.EvalAll(
|
|
||||||
ac.EvalPermission(datasources.ActionDatasourcesRead),
|
|
||||||
ac.EvalPermission(datasources.ActionDatasourcesCreate),
|
|
||||||
ac.EvalPermission(datasources.ActionDatasourcesWrite),
|
|
||||||
)
|
|
||||||
|
|
||||||
// dataSourcesEditAccessEvaluator is used to protect the "Configure > Data sources > Edit" page access
|
|
||||||
var dataSourcesEditAccessEvaluator = ac.EvalAll(
|
|
||||||
ac.EvalPermission(datasources.ActionDatasourcesRead),
|
|
||||||
ac.EvalPermission(datasources.ActionDatasourcesWrite),
|
|
||||||
)
|
|
||||||
|
|
||||||
// orgPreferencesAccessEvaluator is used to protect the "Configure > Preferences" page access
|
// orgPreferencesAccessEvaluator is used to protect the "Configure > Preferences" page access
|
||||||
var orgPreferencesAccessEvaluator = ac.EvalAny(
|
var orgPreferencesAccessEvaluator = ac.EvalAny(
|
||||||
ac.EvalAll(
|
ac.EvalAll(
|
||||||
|
@@ -53,9 +53,9 @@ func (hs *HTTPServer) registerRoutes() {
|
|||||||
r.Get("/profile/switch-org/:id", reqSignedInNoAnonymous, hs.ChangeActiveOrgAndRedirectToHome)
|
r.Get("/profile/switch-org/:id", reqSignedInNoAnonymous, hs.ChangeActiveOrgAndRedirectToHome)
|
||||||
r.Get("/org/", authorize(reqOrgAdmin, orgPreferencesAccessEvaluator), hs.Index)
|
r.Get("/org/", authorize(reqOrgAdmin, orgPreferencesAccessEvaluator), hs.Index)
|
||||||
r.Get("/org/new", authorizeInOrg(reqGrafanaAdmin, acmiddleware.UseGlobalOrg, orgsCreateAccessEvaluator), hs.Index)
|
r.Get("/org/new", authorizeInOrg(reqGrafanaAdmin, acmiddleware.UseGlobalOrg, orgsCreateAccessEvaluator), hs.Index)
|
||||||
r.Get("/datasources/", authorize(reqOrgAdmin, dataSourcesConfigurationAccessEvaluator), hs.Index)
|
r.Get("/datasources/", authorize(reqOrgAdmin, datasources.ConfigurationPageAccess), hs.Index)
|
||||||
r.Get("/datasources/new", authorize(reqOrgAdmin, dataSourcesNewAccessEvaluator), hs.Index)
|
r.Get("/datasources/new", authorize(reqOrgAdmin, datasources.NewPageAccess), hs.Index)
|
||||||
r.Get("/datasources/edit/*", authorize(reqOrgAdmin, dataSourcesEditAccessEvaluator), hs.Index)
|
r.Get("/datasources/edit/*", authorize(reqOrgAdmin, datasources.EditPageAccess), hs.Index)
|
||||||
r.Get("/org/users", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersRead)), 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/new", reqOrgAdmin, hs.Index)
|
||||||
r.Get("/org/users/invite", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionUsersCreate)), hs.Index)
|
r.Get("/org/users/invite", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionUsersCreate)), hs.Index)
|
||||||
@@ -275,18 +275,18 @@ func (hs *HTTPServer) registerRoutes() {
|
|||||||
|
|
||||||
// Data sources
|
// Data sources
|
||||||
apiRoute.Group("/datasources", func(datasourceRoute routing.RouteRegister) {
|
apiRoute.Group("/datasources", func(datasourceRoute routing.RouteRegister) {
|
||||||
datasourceRoute.Get("/", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionDatasourcesRead)), routing.Wrap(hs.GetDataSources))
|
datasourceRoute.Get("/", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionRead)), routing.Wrap(hs.GetDataSources))
|
||||||
datasourceRoute.Post("/", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionDatasourcesCreate)), quota("data_source"), routing.Wrap(hs.AddDataSource))
|
datasourceRoute.Post("/", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionCreate)), quota("data_source"), routing.Wrap(hs.AddDataSource))
|
||||||
datasourceRoute.Put("/:id", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionDatasourcesWrite, datasources.ScopeDatasourcesProvider.GetResourceScope(ac.Parameter(":id")))), routing.Wrap(hs.UpdateDataSource))
|
datasourceRoute.Put("/:id", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionWrite, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":id")))), routing.Wrap(hs.UpdateDataSource))
|
||||||
datasourceRoute.Delete("/:id", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionDatasourcesDelete, datasources.ScopeDatasourcesProvider.GetResourceScope(ac.Parameter(":id")))), routing.Wrap(hs.DeleteDataSourceById))
|
datasourceRoute.Delete("/:id", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionDelete, datasources.ScopeProvider.GetResourceScope(ac.Parameter(":id")))), routing.Wrap(hs.DeleteDataSourceById))
|
||||||
datasourceRoute.Delete("/uid/:uid", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionDatasourcesDelete, datasources.ScopeDatasourcesProvider.GetResourceScopeUID(ac.Parameter(":uid")))), routing.Wrap(hs.DeleteDataSourceByUID))
|
datasourceRoute.Delete("/uid/:uid", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionDelete, datasources.ScopeProvider.GetResourceScopeUID(ac.Parameter(":uid")))), routing.Wrap(hs.DeleteDataSourceByUID))
|
||||||
datasourceRoute.Delete("/name/:name", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionDatasourcesDelete, datasources.ScopeDatasourcesProvider.GetResourceScopeName(ac.Parameter(":name")))), routing.Wrap(hs.DeleteDataSourceByName))
|
datasourceRoute.Delete("/name/:name", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionDelete, datasources.ScopeProvider.GetResourceScopeName(ac.Parameter(":name")))), routing.Wrap(hs.DeleteDataSourceByName))
|
||||||
datasourceRoute.Get("/:id", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionDatasourcesRead)), routing.Wrap(hs.GetDataSourceById))
|
datasourceRoute.Get("/:id", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionRead)), routing.Wrap(hs.GetDataSourceById))
|
||||||
datasourceRoute.Get("/uid/:uid", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionDatasourcesRead)), routing.Wrap(hs.GetDataSourceByUID))
|
datasourceRoute.Get("/uid/:uid", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionRead)), routing.Wrap(hs.GetDataSourceByUID))
|
||||||
datasourceRoute.Get("/name/:name", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionDatasourcesRead)), routing.Wrap(hs.GetDataSourceByName))
|
datasourceRoute.Get("/name/:name", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionRead)), routing.Wrap(hs.GetDataSourceByName))
|
||||||
})
|
})
|
||||||
|
|
||||||
apiRoute.Get("/datasources/id/:name", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionDatasourcesIDRead, datasources.ScopeDatasourcesProvider.GetResourceScopeName(ac.Parameter(":name")))), routing.Wrap(hs.GetDataSourceIdByName))
|
apiRoute.Get("/datasources/id/:name", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionIDRead, datasources.ScopeProvider.GetResourceScopeName(ac.Parameter(":name")))), routing.Wrap(hs.GetDataSourceIdByName))
|
||||||
|
|
||||||
apiRoute.Get("/plugins", routing.Wrap(hs.GetPluginList))
|
apiRoute.Get("/plugins", routing.Wrap(hs.GetPluginList))
|
||||||
apiRoute.Get("/plugins/:pluginId/settings", routing.Wrap(hs.GetPluginSettingByID))
|
apiRoute.Get("/plugins/:pluginId/settings", routing.Wrap(hs.GetPluginSettingByID))
|
||||||
@@ -308,11 +308,11 @@ func (hs *HTTPServer) registerRoutes() {
|
|||||||
}, reqOrgAdmin)
|
}, reqOrgAdmin)
|
||||||
|
|
||||||
apiRoute.Get("/frontend/settings/", hs.GetFrontendSettings)
|
apiRoute.Get("/frontend/settings/", hs.GetFrontendSettings)
|
||||||
apiRoute.Any("/datasources/proxy/:id/*", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionDatasourcesQuery)), hs.ProxyDataSourceRequest)
|
apiRoute.Any("/datasources/proxy/:id/*", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionQuery)), hs.ProxyDataSourceRequest)
|
||||||
apiRoute.Any("/datasources/proxy/:id", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionDatasourcesQuery)), hs.ProxyDataSourceRequest)
|
apiRoute.Any("/datasources/proxy/:id", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionQuery)), hs.ProxyDataSourceRequest)
|
||||||
apiRoute.Any("/datasources/:id/resources", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionDatasourcesQuery)), hs.CallDatasourceResource)
|
apiRoute.Any("/datasources/:id/resources", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionQuery)), hs.CallDatasourceResource)
|
||||||
apiRoute.Any("/datasources/:id/resources/*", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionDatasourcesQuery)), hs.CallDatasourceResource)
|
apiRoute.Any("/datasources/:id/resources/*", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionQuery)), hs.CallDatasourceResource)
|
||||||
apiRoute.Any("/datasources/:id/health", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionDatasourcesQuery)), routing.Wrap(hs.CheckDatasourceHealth))
|
apiRoute.Any("/datasources/:id/health", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionQuery)), routing.Wrap(hs.CheckDatasourceHealth))
|
||||||
|
|
||||||
// Folders
|
// Folders
|
||||||
apiRoute.Group("/folders", func(folderRoute routing.RouteRegister) {
|
apiRoute.Group("/folders", func(folderRoute routing.RouteRegister) {
|
||||||
@@ -386,13 +386,13 @@ func (hs *HTTPServer) registerRoutes() {
|
|||||||
apiRoute.Get("/search/", routing.Wrap(hs.Search))
|
apiRoute.Get("/search/", routing.Wrap(hs.Search))
|
||||||
|
|
||||||
// metrics
|
// metrics
|
||||||
apiRoute.Post("/tsdb/query", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionDatasourcesQuery)), routing.Wrap(hs.QueryMetrics))
|
apiRoute.Post("/tsdb/query", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionQuery)), routing.Wrap(hs.QueryMetrics))
|
||||||
|
|
||||||
// DataSource w/ expressions
|
// DataSource w/ expressions
|
||||||
apiRoute.Post("/ds/query", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionDatasourcesQuery)), routing.Wrap(hs.QueryMetricsV2))
|
apiRoute.Post("/ds/query", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionQuery)), routing.Wrap(hs.QueryMetricsV2))
|
||||||
|
|
||||||
// Validated query
|
// Validated query
|
||||||
apiRoute.Post("/dashboards/org/:orgId/uid/:dashboardUid/panels/:panelId/query", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionDatasourcesQuery)), routing.Wrap(hs.QueryMetricsFromDashboard))
|
apiRoute.Post("/dashboards/org/:orgId/uid/:dashboardUid/panels/:panelId/query", authorize(reqSignedIn, ac.EvalPermission(datasources.ActionQuery)), routing.Wrap(hs.QueryMetricsFromDashboard))
|
||||||
|
|
||||||
apiRoute.Group("/alerts", func(alertsRoute routing.RouteRegister) {
|
apiRoute.Group("/alerts", func(alertsRoute routing.RouteRegister) {
|
||||||
alertsRoute.Post("/test", routing.Wrap(hs.AlertTest))
|
alertsRoute.Post("/test", routing.Wrap(hs.AlertTest))
|
||||||
|
@@ -241,8 +241,8 @@ func TestAPI_Datasources_AccessControl(t *testing.T) {
|
|||||||
method: http.MethodPut,
|
method: http.MethodPut,
|
||||||
permissions: []*ac.Permission{
|
permissions: []*ac.Permission{
|
||||||
{
|
{
|
||||||
Action: datasources.ActionDatasourcesWrite,
|
Action: datasources.ActionWrite,
|
||||||
Scope: datasources.ScopeDatasourcesAll,
|
Scope: datasources.ScopeAll,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -254,7 +254,7 @@ func TestAPI_Datasources_AccessControl(t *testing.T) {
|
|||||||
desc: "DatasourcesGet should return 200 for user with correct permissions",
|
desc: "DatasourcesGet should return 200 for user with correct permissions",
|
||||||
url: "/api/datasources/",
|
url: "/api/datasources/",
|
||||||
method: http.MethodGet,
|
method: http.MethodGet,
|
||||||
permissions: []*ac.Permission{{Action: datasources.ActionDatasourcesRead, Scope: datasources.ScopeDatasourcesAll}},
|
permissions: []*ac.Permission{{Action: datasources.ActionRead, Scope: datasources.ScopeAll}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -273,7 +273,7 @@ func TestAPI_Datasources_AccessControl(t *testing.T) {
|
|||||||
desc: "DatasourcesPost should return 200 for user with correct permissions",
|
desc: "DatasourcesPost should return 200 for user with correct permissions",
|
||||||
url: "/api/datasources/",
|
url: "/api/datasources/",
|
||||||
method: http.MethodPost,
|
method: http.MethodPost,
|
||||||
permissions: []*ac.Permission{{Action: datasources.ActionDatasourcesCreate}},
|
permissions: []*ac.Permission{{Action: datasources.ActionCreate}},
|
||||||
},
|
},
|
||||||
expectedDS: &testDatasource,
|
expectedDS: &testDatasource,
|
||||||
},
|
},
|
||||||
@@ -295,7 +295,7 @@ func TestAPI_Datasources_AccessControl(t *testing.T) {
|
|||||||
method: http.MethodPut,
|
method: http.MethodPut,
|
||||||
permissions: []*ac.Permission{
|
permissions: []*ac.Permission{
|
||||||
{
|
{
|
||||||
Action: datasources.ActionDatasourcesWrite,
|
Action: datasources.ActionWrite,
|
||||||
Scope: fmt.Sprintf("datasources:id:%v", testDatasource.Id),
|
Scope: fmt.Sprintf("datasources:id:%v", testDatasource.Id),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -320,7 +320,7 @@ func TestAPI_Datasources_AccessControl(t *testing.T) {
|
|||||||
method: http.MethodPut,
|
method: http.MethodPut,
|
||||||
permissions: []*ac.Permission{
|
permissions: []*ac.Permission{
|
||||||
{
|
{
|
||||||
Action: datasources.ActionDatasourcesWrite,
|
Action: datasources.ActionWrite,
|
||||||
Scope: fmt.Sprintf("datasources:id:%v", testDatasourceReadOnly.Id),
|
Scope: fmt.Sprintf("datasources:id:%v", testDatasourceReadOnly.Id),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -335,7 +335,7 @@ func TestAPI_Datasources_AccessControl(t *testing.T) {
|
|||||||
method: http.MethodDelete,
|
method: http.MethodDelete,
|
||||||
permissions: []*ac.Permission{
|
permissions: []*ac.Permission{
|
||||||
{
|
{
|
||||||
Action: datasources.ActionDatasourcesDelete,
|
Action: datasources.ActionDelete,
|
||||||
Scope: fmt.Sprintf("datasources:id:%v", testDatasource.Id),
|
Scope: fmt.Sprintf("datasources:id:%v", testDatasource.Id),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -359,7 +359,7 @@ func TestAPI_Datasources_AccessControl(t *testing.T) {
|
|||||||
method: http.MethodDelete,
|
method: http.MethodDelete,
|
||||||
permissions: []*ac.Permission{
|
permissions: []*ac.Permission{
|
||||||
{
|
{
|
||||||
Action: datasources.ActionDatasourcesDelete,
|
Action: datasources.ActionDelete,
|
||||||
Scope: fmt.Sprintf("datasources:uid:%v", testDatasource.Uid),
|
Scope: fmt.Sprintf("datasources:uid:%v", testDatasource.Uid),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -383,7 +383,7 @@ func TestAPI_Datasources_AccessControl(t *testing.T) {
|
|||||||
method: http.MethodDelete,
|
method: http.MethodDelete,
|
||||||
permissions: []*ac.Permission{
|
permissions: []*ac.Permission{
|
||||||
{
|
{
|
||||||
Action: datasources.ActionDatasourcesDelete,
|
Action: datasources.ActionDelete,
|
||||||
Scope: fmt.Sprintf("datasources:name:%v", testDatasource.Name),
|
Scope: fmt.Sprintf("datasources:name:%v", testDatasource.Name),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -407,7 +407,7 @@ func TestAPI_Datasources_AccessControl(t *testing.T) {
|
|||||||
method: http.MethodGet,
|
method: http.MethodGet,
|
||||||
permissions: []*ac.Permission{
|
permissions: []*ac.Permission{
|
||||||
{
|
{
|
||||||
Action: datasources.ActionDatasourcesRead,
|
Action: datasources.ActionRead,
|
||||||
Scope: fmt.Sprintf("datasources:id:%v", testDatasource.Id),
|
Scope: fmt.Sprintf("datasources:id:%v", testDatasource.Id),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -431,7 +431,7 @@ func TestAPI_Datasources_AccessControl(t *testing.T) {
|
|||||||
method: http.MethodGet,
|
method: http.MethodGet,
|
||||||
permissions: []*ac.Permission{
|
permissions: []*ac.Permission{
|
||||||
{
|
{
|
||||||
Action: datasources.ActionDatasourcesRead,
|
Action: datasources.ActionRead,
|
||||||
Scope: fmt.Sprintf("datasources:uid:%v", testDatasource.Uid),
|
Scope: fmt.Sprintf("datasources:uid:%v", testDatasource.Uid),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -455,7 +455,7 @@ func TestAPI_Datasources_AccessControl(t *testing.T) {
|
|||||||
method: http.MethodGet,
|
method: http.MethodGet,
|
||||||
permissions: []*ac.Permission{
|
permissions: []*ac.Permission{
|
||||||
{
|
{
|
||||||
Action: datasources.ActionDatasourcesRead,
|
Action: datasources.ActionRead,
|
||||||
Scope: fmt.Sprintf("datasources:name:%v", testDatasource.Name),
|
Scope: fmt.Sprintf("datasources:name:%v", testDatasource.Name),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -480,7 +480,7 @@ func TestAPI_Datasources_AccessControl(t *testing.T) {
|
|||||||
method: http.MethodGet,
|
method: http.MethodGet,
|
||||||
permissions: []*ac.Permission{
|
permissions: []*ac.Permission{
|
||||||
{
|
{
|
||||||
Action: datasources.ActionDatasourcesIDRead,
|
Action: datasources.ActionIDRead,
|
||||||
Scope: fmt.Sprintf("datasources:name:%v", testDatasource.Name),
|
Scope: fmt.Sprintf("datasources:name:%v", testDatasource.Name),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/plugins"
|
"github.com/grafana/grafana/pkg/plugins"
|
||||||
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
|
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||||
|
"github.com/grafana/grafana/pkg/services/datasources"
|
||||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
)
|
)
|
||||||
@@ -244,7 +245,7 @@ func (hs *HTTPServer) getNavTree(c *models.ReqContext, hasEditPerm bool) ([]*dto
|
|||||||
|
|
||||||
configNodes := []*dtos.NavLink{}
|
configNodes := []*dtos.NavLink{}
|
||||||
|
|
||||||
if hasAccess(ac.ReqOrgAdmin, dataSourcesConfigurationAccessEvaluator) {
|
if hasAccess(ac.ReqOrgAdmin, datasources.ConfigurationPageAccess) {
|
||||||
configNodes = append(configNodes, &dtos.NavLink{
|
configNodes = append(configNodes, &dtos.NavLink{
|
||||||
Text: "Data sources",
|
Text: "Data sources",
|
||||||
Icon: "database",
|
Icon: "database",
|
||||||
|
@@ -3,17 +3,45 @@ package datasources
|
|||||||
import "github.com/grafana/grafana/pkg/services/accesscontrol"
|
import "github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ActionDatasourcesRead = "datasources:read"
|
ScopeRoot = "datasources"
|
||||||
ActionDatasourcesQuery = "datasources:query"
|
|
||||||
ActionDatasourcesCreate = "datasources:create"
|
|
||||||
ActionDatasourcesWrite = "datasources:write"
|
|
||||||
ActionDatasourcesDelete = "datasources:delete"
|
|
||||||
ActionDatasourcesIDRead = "datasources.id:read"
|
|
||||||
|
|
||||||
ScopeDatasourcesRoot = "datasources"
|
ActionRead = "datasources:read"
|
||||||
|
ActionQuery = "datasources:query"
|
||||||
|
ActionCreate = "datasources:create"
|
||||||
|
ActionWrite = "datasources:write"
|
||||||
|
ActionDelete = "datasources:delete"
|
||||||
|
ActionIDRead = "datasources.id:read"
|
||||||
|
ActionPermissionsRead = "datasources.permissions:read"
|
||||||
|
ActionPermissionsWrite = "datasources.permissions:write"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ScopeDatasourcesAll = accesscontrol.GetResourceAllScope(ScopeDatasourcesRoot)
|
ScopeID = accesscontrol.Scope("datasources", "id", accesscontrol.Parameter(":datasourceId"))
|
||||||
ScopeDatasourcesProvider = accesscontrol.NewScopeProvider(ScopeDatasourcesRoot)
|
ScopeAll = accesscontrol.GetResourceAllScope(ScopeRoot)
|
||||||
|
ScopeProvider = accesscontrol.NewScopeProvider(ScopeRoot)
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ConfigurationPageAccess is used to protect the "Configure > Data sources" tab access
|
||||||
|
ConfigurationPageAccess = accesscontrol.EvalAll(
|
||||||
|
accesscontrol.EvalPermission(ActionRead),
|
||||||
|
accesscontrol.EvalAny(
|
||||||
|
accesscontrol.EvalPermission(ActionCreate),
|
||||||
|
accesscontrol.EvalPermission(ActionDelete),
|
||||||
|
accesscontrol.EvalPermission(ActionWrite),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewPageAccess is used to protect the "Configure > Data sources > New" page access
|
||||||
|
NewPageAccess = accesscontrol.EvalAll(
|
||||||
|
accesscontrol.EvalPermission(ActionRead),
|
||||||
|
accesscontrol.EvalPermission(ActionCreate),
|
||||||
|
accesscontrol.EvalPermission(ActionWrite),
|
||||||
|
)
|
||||||
|
|
||||||
|
// EditPageAccess is used to protect the "Configure > Data sources > Edit" page access
|
||||||
|
EditPageAccess = accesscontrol.EvalAll(
|
||||||
|
accesscontrol.EvalPermission(ActionRead),
|
||||||
|
accesscontrol.EvalPermission(ActionWrite),
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
@@ -97,7 +97,7 @@ type DataSourceRetriever interface {
|
|||||||
// NewNameScopeResolver provides an AttributeScopeResolver able to
|
// NewNameScopeResolver provides an AttributeScopeResolver able to
|
||||||
// translate a scope prefixed with "datasources:name:" into an id based scope.
|
// translate a scope prefixed with "datasources:name:" into an id based scope.
|
||||||
func NewNameScopeResolver(db DataSourceRetriever) (string, accesscontrol.AttributeScopeResolveFunc) {
|
func NewNameScopeResolver(db DataSourceRetriever) (string, accesscontrol.AttributeScopeResolveFunc) {
|
||||||
prefix := datasources.ScopeDatasourcesProvider.GetResourceScopeName("")
|
prefix := datasources.ScopeProvider.GetResourceScopeName("")
|
||||||
dsNameResolver := func(ctx context.Context, orgID int64, initialScope string) (string, error) {
|
dsNameResolver := func(ctx context.Context, orgID int64, initialScope string) (string, error) {
|
||||||
if !strings.HasPrefix(initialScope, prefix) {
|
if !strings.HasPrefix(initialScope, prefix) {
|
||||||
return "", accesscontrol.ErrInvalidScope
|
return "", accesscontrol.ErrInvalidScope
|
||||||
@@ -113,7 +113,7 @@ func NewNameScopeResolver(db DataSourceRetriever) (string, accesscontrol.Attribu
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return datasources.ScopeDatasourcesProvider.GetResourceScope(strconv.FormatInt(query.Result.Id, 10)), nil
|
return datasources.ScopeProvider.GetResourceScope(strconv.FormatInt(query.Result.Id, 10)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return prefix, dsNameResolver
|
return prefix, dsNameResolver
|
||||||
@@ -122,7 +122,7 @@ func NewNameScopeResolver(db DataSourceRetriever) (string, accesscontrol.Attribu
|
|||||||
// NewUidScopeResolver provides an AttributeScopeResolver able to
|
// NewUidScopeResolver provides an AttributeScopeResolver able to
|
||||||
// translate a scope prefixed with "datasources:uid:" into an id based scope.
|
// translate a scope prefixed with "datasources:uid:" into an id based scope.
|
||||||
func NewUidScopeResolver(db DataSourceRetriever) (string, accesscontrol.AttributeScopeResolveFunc) {
|
func NewUidScopeResolver(db DataSourceRetriever) (string, accesscontrol.AttributeScopeResolveFunc) {
|
||||||
prefix := datasources.ScopeDatasourcesProvider.GetResourceScopeUID("")
|
prefix := datasources.ScopeProvider.GetResourceScopeUID("")
|
||||||
dsUIDResolver := func(ctx context.Context, orgID int64, initialScope string) (string, error) {
|
dsUIDResolver := func(ctx context.Context, orgID int64, initialScope string) (string, error) {
|
||||||
if !strings.HasPrefix(initialScope, prefix) {
|
if !strings.HasPrefix(initialScope, prefix) {
|
||||||
return "", accesscontrol.ErrInvalidScope
|
return "", accesscontrol.ErrInvalidScope
|
||||||
@@ -138,7 +138,7 @@ func NewUidScopeResolver(db DataSourceRetriever) (string, accesscontrol.Attribut
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return datasources.ScopeDatasourcesProvider.GetResourceScope(strconv.FormatInt(query.Result.Id, 10)), nil
|
return datasources.ScopeProvider.GetResourceScope(strconv.FormatInt(query.Result.Id, 10)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return prefix, dsUIDResolver
|
return prefix, dsUIDResolver
|
||||||
|
Reference in New Issue
Block a user