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
pull/33003/head
Owen Diehl 4 years ago committed by GitHub
parent b3ac63dad7
commit dadccdda06
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 33
      pkg/api/pluginproxy/ds_proxy.go
  2. 37
      pkg/api/pluginproxy/ds_proxy_test.go
  3. 43
      public/app/plugins/datasource/prometheus/plugin.json

@ -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…
Cancel
Save