mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: fix bug where user is able to access rules from namespaces user is not part of (#41403)
* Add fix * Add tests Co-authored-by: Yuriy Tseretyan <yuriy.tseretyan@grafana.com> Co-authored-by: Armand Grillet <2117580+armandgrillet@users.noreply.github.com> Co-authored-by: Jean-Philippe Quéméner <JohnnyQQQQ@users.noreply.github.com> Co-authored-by: George Robinson <george.robinson@grafana.com>
This commit is contained in:
@@ -76,6 +76,11 @@ func (srv PrometheusSrv) RouteGetRuleStatuses(c *models.ReqContext) response.Res
|
|||||||
return ErrResp(http.StatusInternalServerError, err, "failed to get namespaces visible to the user")
|
return ErrResp(http.StatusInternalServerError, err, "failed to get namespaces visible to the user")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(namespaceMap) == 0 {
|
||||||
|
srv.log.Debug("User does not have access to any namespaces")
|
||||||
|
return response.JSON(http.StatusOK, ruleResponse)
|
||||||
|
}
|
||||||
|
|
||||||
namespaceUIDs := make([]string, len(namespaceMap))
|
namespaceUIDs := make([]string, len(namespaceMap))
|
||||||
for k := range namespaceMap {
|
for k := range namespaceMap {
|
||||||
namespaceUIDs = append(namespaceUIDs, k)
|
namespaceUIDs = append(namespaceUIDs, k)
|
||||||
|
|||||||
@@ -151,6 +151,12 @@ func (srv RulerSrv) RouteGetRulesConfig(c *models.ReqContext) response.Response
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return ErrResp(http.StatusInternalServerError, err, "failed to get namespaces visible to the user")
|
return ErrResp(http.StatusInternalServerError, err, "failed to get namespaces visible to the user")
|
||||||
}
|
}
|
||||||
|
result := apimodels.NamespaceConfigResponse{}
|
||||||
|
|
||||||
|
if len(namespaceMap) == 0 {
|
||||||
|
srv.log.Debug("User has no access to any namespaces")
|
||||||
|
return response.JSON(http.StatusOK, result)
|
||||||
|
}
|
||||||
|
|
||||||
namespaceUIDs := make([]string, len(namespaceMap))
|
namespaceUIDs := make([]string, len(namespaceMap))
|
||||||
for k := range namespaceMap {
|
for k := range namespaceMap {
|
||||||
@@ -214,7 +220,6 @@ func (srv RulerSrv) RouteGetRulesConfig(c *models.ReqContext) response.Response
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result := apimodels.NamespaceConfigResponse{}
|
|
||||||
for namespace, m := range configs {
|
for namespace, m := range configs {
|
||||||
for _, ruleGroupConfig := range m {
|
for _, ruleGroupConfig := range m {
|
||||||
result[namespace] = append(result[namespace], ruleGroupConfig)
|
result[namespace] = append(result[namespace], ruleGroupConfig)
|
||||||
|
|||||||
@@ -761,6 +761,32 @@ func TestPrometheusRulesPermissions(t *testing.T) {
|
|||||||
"evaluationTime": 0
|
"evaluationTime": 0
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
}`, string(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove permissions from _ALL_ folders
|
||||||
|
require.NoError(t, store.UpdateDashboardACL(1, nil))
|
||||||
|
|
||||||
|
// make sure that no folders are included in the response
|
||||||
|
{
|
||||||
|
promRulesURL := fmt.Sprintf("http://grafana:password@%s/api/prometheus/grafana/api/v1/rules", grafanaListedAddr)
|
||||||
|
// nolint:gosec
|
||||||
|
resp, err := http.Get(promRulesURL)
|
||||||
|
require.NoError(t, err)
|
||||||
|
t.Cleanup(func() {
|
||||||
|
err := resp.Body.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
})
|
||||||
|
b, err := ioutil.ReadAll(resp.Body)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 200, resp.StatusCode)
|
||||||
|
|
||||||
|
require.JSONEq(t, `
|
||||||
|
{
|
||||||
|
"status": "success",
|
||||||
|
"data": {
|
||||||
|
"groups": []
|
||||||
|
}
|
||||||
}`, string(b))
|
}`, string(b))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -245,6 +245,24 @@ func TestAlertRulePermissions(t *testing.T) {
|
|||||||
}`
|
}`
|
||||||
assert.JSONEq(t, expectedGetNamespaceResponseBody, body)
|
assert.JSONEq(t, expectedGetNamespaceResponseBody, body)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove permissions from ALL folders.
|
||||||
|
require.NoError(t, store.UpdateDashboardACL(1, nil))
|
||||||
|
{
|
||||||
|
u := fmt.Sprintf("http://grafana:password@%s/api/ruler/grafana/api/v1/rules", grafanaListedAddr)
|
||||||
|
// nolint:gosec
|
||||||
|
resp, err := http.Get(u)
|
||||||
|
require.NoError(t, err)
|
||||||
|
t.Cleanup(func() {
|
||||||
|
err := resp.Body.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
})
|
||||||
|
b, err := ioutil.ReadAll(resp.Body)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, resp.StatusCode, 200)
|
||||||
|
require.JSONEq(t, `{}`, string(b))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func createRule(t *testing.T, grafanaListedAddr string, folder string, user, password string) {
|
func createRule(t *testing.T, grafanaListedAddr string, folder string, user, password string) {
|
||||||
|
|||||||
Reference in New Issue
Block a user