mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: Stop returning autogen routes for non-admin on api/v2/status (#84864)
* Alerting: Stop returning autogen routes for non-admin on api/v2/status * Improve api/v2/status integration tests for user roles
This commit is contained in:
parent
7eee34311d
commit
fbd057b258
@ -50,7 +50,12 @@ func (srv AlertmanagerSrv) RouteGetAMStatus(c *contextmodel.ReqContext) response
|
|||||||
return errResp
|
return errResp
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.JSON(http.StatusOK, am.GetStatus())
|
status := am.GetStatus()
|
||||||
|
if !c.SignedInUser.HasRole(org.RoleAdmin) {
|
||||||
|
notifier.RemoveAutogenConfigIfExists(status.Config.Route)
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.JSON(http.StatusOK, status)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (srv AlertmanagerSrv) RouteCreateSilence(c *contextmodel.ReqContext, postableSilence apimodels.PostableSilence) response.Response {
|
func (srv AlertmanagerSrv) RouteCreateSilence(c *contextmodel.ReqContext, postableSilence apimodels.PostableSilence) response.Response {
|
||||||
|
@ -405,6 +405,53 @@ func TestAlertmanagerAutogenConfig(t *testing.T) {
|
|||||||
compare(t, validConfigWithoutAutogen, string(response.Body()))
|
compare(t, validConfigWithoutAutogen, string(response.Body()))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("route GET status", func(t *testing.T) {
|
||||||
|
t.Run("when admin return autogen routes", func(t *testing.T) {
|
||||||
|
sut, _ := createSutForAutogen(t)
|
||||||
|
|
||||||
|
rc := createRequestCtxInOrg(2)
|
||||||
|
rc.SignedInUser.OrgRole = org.RoleAdmin
|
||||||
|
|
||||||
|
response := sut.RouteGetAMStatus(rc)
|
||||||
|
require.Equal(t, 200, response.Status())
|
||||||
|
|
||||||
|
var status struct {
|
||||||
|
Config apimodels.PostableApiAlertingConfig `json:"config"`
|
||||||
|
}
|
||||||
|
err := json.Unmarshal(response.Body(), &status)
|
||||||
|
require.NoError(t, err)
|
||||||
|
configBody, err := json.Marshal(apimodels.PostableUserConfig{
|
||||||
|
TemplateFiles: map[string]string{"a": "template"},
|
||||||
|
AlertmanagerConfig: status.Config,
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
compare(t, validConfigWithAutogen, string(configBody))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("when not admin return no autogen routes", func(t *testing.T) {
|
||||||
|
sut, _ := createSutForAutogen(t)
|
||||||
|
|
||||||
|
rc := createRequestCtxInOrg(2)
|
||||||
|
|
||||||
|
response := sut.RouteGetAMStatus(rc)
|
||||||
|
require.Equal(t, 200, response.Status())
|
||||||
|
|
||||||
|
var status struct {
|
||||||
|
Config apimodels.PostableApiAlertingConfig `json:"config"`
|
||||||
|
}
|
||||||
|
err := json.Unmarshal(response.Body(), &status)
|
||||||
|
require.NoError(t, err)
|
||||||
|
configBody, err := json.Marshal(apimodels.PostableUserConfig{
|
||||||
|
TemplateFiles: map[string]string{"a": "template"},
|
||||||
|
AlertmanagerConfig: status.Config,
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
compare(t, validConfigWithoutAutogen, string(configBody))
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRouteGetAlertingConfigHistory(t *testing.T) {
|
func TestRouteGetAlertingConfigHistory(t *testing.T) {
|
||||||
|
@ -2000,25 +2000,37 @@ func TestIntegrationAlertmanagerStatus(t *testing.T) {
|
|||||||
dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
|
dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
|
||||||
DisableLegacyAlerting: true,
|
DisableLegacyAlerting: true,
|
||||||
EnableUnifiedAlerting: true,
|
EnableUnifiedAlerting: true,
|
||||||
|
DisableAnonymous: true,
|
||||||
AppModeProduction: true,
|
AppModeProduction: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
grafanaListedAddr, _ := testinfra.StartGrafana(t, dir, path)
|
grafanaListedAddr, store := testinfra.StartGrafana(t, dir, path)
|
||||||
|
|
||||||
// Get the Alertmanager current status.
|
// Create a users to make authenticated requests
|
||||||
{
|
createUser(t, store, user.CreateUserCommand{
|
||||||
alertsURL := fmt.Sprintf("http://%s/api/alertmanager/grafana/api/v2/status", grafanaListedAddr)
|
DefaultOrgRole: string(org.RoleViewer),
|
||||||
// nolint:gosec
|
Password: "viewer",
|
||||||
resp, err := http.Get(alertsURL)
|
Login: "viewer",
|
||||||
require.NoError(t, err)
|
})
|
||||||
t.Cleanup(func() {
|
createUser(t, store, user.CreateUserCommand{
|
||||||
err := resp.Body.Close()
|
DefaultOrgRole: string(org.RoleEditor),
|
||||||
require.NoError(t, err)
|
Password: "editor",
|
||||||
})
|
Login: "editor",
|
||||||
b, err := io.ReadAll(resp.Body)
|
})
|
||||||
require.NoError(t, err)
|
createUser(t, store, user.CreateUserCommand{
|
||||||
require.Equal(t, 200, resp.StatusCode)
|
DefaultOrgRole: string(org.RoleAdmin),
|
||||||
require.JSONEq(t, `
|
Password: "admin",
|
||||||
|
Login: "admin",
|
||||||
|
})
|
||||||
|
|
||||||
|
type testCase struct {
|
||||||
|
desc string
|
||||||
|
url string
|
||||||
|
expStatus int
|
||||||
|
expBody string
|
||||||
|
}
|
||||||
|
|
||||||
|
cfgBody := `
|
||||||
{
|
{
|
||||||
"cluster": {
|
"cluster": {
|
||||||
"peers": [],
|
"peers": [],
|
||||||
@ -2054,7 +2066,51 @@ func TestIntegrationAlertmanagerStatus(t *testing.T) {
|
|||||||
"version": "N/A"
|
"version": "N/A"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`, string(b))
|
`
|
||||||
|
|
||||||
|
testCases := []testCase{
|
||||||
|
{
|
||||||
|
desc: "un-authenticated request should fail",
|
||||||
|
url: "http://%s/api/alertmanager/grafana/api/v2/status",
|
||||||
|
expStatus: http.StatusUnauthorized,
|
||||||
|
expBody: `{"extra":null,"message":"Unauthorized","messageId":"auth.unauthorized","statusCode":401,"traceID":""}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "viewer request should succeed",
|
||||||
|
url: "http://viewer:viewer@%s/api/alertmanager/grafana/api/v2/status",
|
||||||
|
expStatus: http.StatusOK,
|
||||||
|
expBody: cfgBody,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "editor request should succeed",
|
||||||
|
url: "http://editor:editor@%s/api/alertmanager/grafana/api/v2/status",
|
||||||
|
expStatus: http.StatusOK,
|
||||||
|
expBody: cfgBody,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "admin request should succeed",
|
||||||
|
url: "http://admin:admin@%s/api/alertmanager/grafana/api/v2/status",
|
||||||
|
expStatus: http.StatusOK,
|
||||||
|
expBody: cfgBody,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.desc, func(t *testing.T) {
|
||||||
|
resp, err := http.Get(fmt.Sprintf(tc.url, grafanaListedAddr))
|
||||||
|
t.Cleanup(func() {
|
||||||
|
require.NoError(t, resp.Body.Close())
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, tc.expStatus, resp.StatusCode)
|
||||||
|
b, err := io.ReadAll(resp.Body)
|
||||||
|
if tc.expStatus == http.StatusOK {
|
||||||
|
re := regexp.MustCompile(`"uid":"([\w|-]+)"`)
|
||||||
|
b = re.ReplaceAll(b, []byte(`"uid":""`))
|
||||||
|
}
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.JSONEq(t, tc.expBody, string(b))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user