mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Allows posting to prom rules endpoints via ds_proxy (#32946)
* allows posting to prom rules endpoints via ds_proxy * prom proxy routes via plugin and fix proxy route matching bug * bump ci
This commit is contained in:
parent
b3ac63dad7
commit
dadccdda06
@ -246,18 +246,6 @@ func (proxy *DataSourceProxy) validateRequest() error {
|
||||
return errors.New("target URL is not a valid target")
|
||||
}
|
||||
|
||||
if proxy.ds.Type == models.DS_PROMETHEUS {
|
||||
if proxy.ctx.Req.Request.Method == "DELETE" {
|
||||
return errors.New("deletes not allowed on proxied Prometheus datasource")
|
||||
}
|
||||
if proxy.ctx.Req.Request.Method == "PUT" {
|
||||
return errors.New("puts not allowed on proxied Prometheus datasource")
|
||||
}
|
||||
if proxy.ctx.Req.Request.Method == "POST" && !(proxy.proxyPath == "api/v1/query" || proxy.proxyPath == "api/v1/query_range" || proxy.proxyPath == "api/v1/series" || proxy.proxyPath == "api/v1/labels" || proxy.proxyPath == "api/v1/query_exemplars") {
|
||||
return errors.New("posts not allowed on proxied Prometheus datasource except on /query, /query_range, /series and /labels")
|
||||
}
|
||||
}
|
||||
|
||||
if proxy.ds.Type == models.DS_ES {
|
||||
if proxy.ctx.Req.Request.Method == "DELETE" {
|
||||
return errors.New("deletes not allowed on proxied Elasticsearch datasource")
|
||||
@ -278,16 +266,29 @@ func (proxy *DataSourceProxy) validateRequest() error {
|
||||
continue
|
||||
}
|
||||
|
||||
// route match
|
||||
if !strings.HasPrefix(proxy.proxyPath, route.Path) {
|
||||
continue
|
||||
}
|
||||
|
||||
if route.ReqRole.IsValid() {
|
||||
if !proxy.ctx.HasUserRole(route.ReqRole) {
|
||||
return errors.New("plugin proxy route access denied")
|
||||
}
|
||||
}
|
||||
|
||||
if strings.HasPrefix(proxy.proxyPath, route.Path) {
|
||||
proxy.route = route
|
||||
break
|
||||
}
|
||||
proxy.route = route
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Trailing validation below this point for routes that were not matched
|
||||
if proxy.ds.Type == models.DS_PROMETHEUS {
|
||||
if proxy.ctx.Req.Request.Method == "DELETE" {
|
||||
return errors.New("non allow-listed DELETEs not allowed on proxied Prometheus datasource")
|
||||
}
|
||||
if proxy.ctx.Req.Request.Method == "PUT" {
|
||||
return errors.New("non allow-listed PUTs not allowed on proxied Prometheus datasource")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -895,3 +895,40 @@ func runDatasourceAuthTest(t *testing.T, test *testCase) {
|
||||
|
||||
test.checkReq(req)
|
||||
}
|
||||
|
||||
func Test_PathCheck(t *testing.T) {
|
||||
// Ensure that we test routes appropriately. This test reproduces a historical bug where two routes were defined with different role requirements but the same method and the more privileged route was tested first. Here we ensure auth checks are applied based on the correct route, not just the method.
|
||||
plugin := &plugins.DataSourcePlugin{
|
||||
Routes: []*plugins.AppPluginRoute{
|
||||
{
|
||||
Path: "a",
|
||||
URL: "https://www.google.com",
|
||||
ReqRole: models.ROLE_EDITOR,
|
||||
Method: http.MethodGet,
|
||||
},
|
||||
{
|
||||
Path: "b",
|
||||
URL: "https://www.google.com",
|
||||
ReqRole: models.ROLE_VIEWER,
|
||||
Method: http.MethodGet,
|
||||
},
|
||||
},
|
||||
}
|
||||
setUp := func() (*models.ReqContext, *http.Request) {
|
||||
req, err := http.NewRequest("GET", "http://localhost/asd", nil)
|
||||
require.NoError(t, err)
|
||||
ctx := &models.ReqContext{
|
||||
Context: &macaron.Context{
|
||||
Req: macaron.Request{Request: req},
|
||||
},
|
||||
SignedInUser: &models.SignedInUser{OrgRole: models.ROLE_VIEWER},
|
||||
}
|
||||
return ctx, req
|
||||
}
|
||||
ctx, _ := setUp()
|
||||
proxy, err := NewDataSourceProxy(&models.DataSource{}, plugin, ctx, "b", &setting.Cfg{})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Nil(t, proxy.validateRequest())
|
||||
require.Equal(t, plugin.Routes[1], proxy.route)
|
||||
}
|
||||
|
@ -3,7 +3,48 @@
|
||||
"name": "Prometheus",
|
||||
"id": "prometheus",
|
||||
"category": "tsdb",
|
||||
|
||||
"routes": [
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "api/v1/query",
|
||||
"reqRole": "Viewer"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "api/v1/query_range",
|
||||
"reqRole": "Viewer"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "api/v1/series",
|
||||
"reqRole": "Viewer"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "api/v1/labels",
|
||||
"reqRole": "Viewer"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "api/v1/query_exemplars",
|
||||
"reqRole": "Viewer"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "api/v1/rules",
|
||||
"reqRole": "Viewer"
|
||||
},
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "api/v1/rules",
|
||||
"reqRole": "Editor"
|
||||
},
|
||||
{
|
||||
"method": "DELETE",
|
||||
"path": "api/v1/rules",
|
||||
"reqRole": "Editor"
|
||||
}
|
||||
],
|
||||
"includes": [
|
||||
{
|
||||
"type": "dashboard",
|
||||
|
Loading…
Reference in New Issue
Block a user