[release-11.6.9] Alerting: Fix contacts point issues (#115409)
* Alerting: Protect sensitive fields of contact points from unauthorized modification - Introduce a new permission alert.notifications.receivers.protected:write. The permission is granted to contact point administrators. - Introduce field Protected to NotifierOption - Introduce DiffReport for models.Integrations with focus on Settings. The diff report is extended with methods that return all keys that are different between two settings. - Add new annotation 'grafana.com/access/CanModifyProtected' to Receiver model - Update receiver service to enforce the permission and return status 403 if unauthorized user modifies protected field - Update legacy configuration post API and receiver testing API to enforce permission and return status 403 if unauthorized user modifies protected field. - Update UI to disable protected fields if user cannot modify them NOTE: the legacy configuration POST API now prohibits Editor role from modifying protected fields. After creating a new integration the protected fields (mostly URLs) effectively become read-only and can be changed by Admininstrators only. Co-authored-by: Sonia Aguilar <soniaaguilarpeiron@gmail.com> * fix linter error * prettier:write --------- Co-authored-by: Yuri Tseretyan <yuriy.tseretyan@grafana.com> Co-authored-by: Sonia Aguilar <soniaaguilarpeiron@gmail.com>
This commit is contained in:
@@ -552,3 +552,113 @@ func TestIntegrationAlertmanagerConfigurationPersistSecrets(t *testing.T) {
|
||||
`, generatedUID), getBody(t, resp.Body))
|
||||
}
|
||||
}
|
||||
|
||||
func TestIntegrationAlertmanagerConfiguration_ProtectedFields(t *testing.T) {
|
||||
testinfra.SQLiteIntegrationTest(t)
|
||||
|
||||
dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{
|
||||
DisableLegacyAlerting: true,
|
||||
EnableUnifiedAlerting: true,
|
||||
DisableAnonymous: true,
|
||||
AppModeProduction: true,
|
||||
DisableFeatureToggles: []string{featuremgmt.FlagAlertingApiServer},
|
||||
})
|
||||
|
||||
grafanaListedAddr, env := testinfra.StartGrafanaEnv(t, dir, path)
|
||||
|
||||
createUser(t, env.SQLStore, env.Cfg, user.CreateUserCommand{
|
||||
DefaultOrgRole: string(org.RoleAdmin),
|
||||
Password: "admin",
|
||||
Login: "admin",
|
||||
})
|
||||
|
||||
createUser(t, env.SQLStore, env.Cfg, user.CreateUserCommand{
|
||||
DefaultOrgRole: string(org.RoleEditor),
|
||||
Password: "editor",
|
||||
Login: "editor",
|
||||
})
|
||||
|
||||
adminClient := newAlertingApiClient(grafanaListedAddr, "admin", "admin")
|
||||
editorClient := newAlertingApiClient(grafanaListedAddr, "editor", "editor")
|
||||
|
||||
payload := `
|
||||
{
|
||||
"template_files": {},
|
||||
"alertmanager_config": {
|
||||
"route": {
|
||||
"receiver": "webhook.receiver"
|
||||
},
|
||||
"receivers": [{
|
||||
"name": "webhook.receiver",
|
||||
"grafana_managed_receiver_configs": [{
|
||||
"settings": {
|
||||
"url": "http://localhost:9000"
|
||||
},
|
||||
"type": "webhook",
|
||||
"name": "webhook.receiver",
|
||||
"disableResolveMessage": false
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
`
|
||||
var cfg apimodels.PostableUserConfig
|
||||
err := json.Unmarshal([]byte(payload), &cfg)
|
||||
require.NoError(t, err)
|
||||
|
||||
// create a new configuration that has protected fields, one is a secret
|
||||
_, err = adminClient.PostConfiguration(t, cfg)
|
||||
require.NoError(t, err)
|
||||
|
||||
patchUIDs := func(t *testing.T) {
|
||||
t.Helper()
|
||||
gCfg, _, _ := adminClient.GetAlertmanagerConfigWithStatus(t)
|
||||
patched := 0
|
||||
for i, gr := range gCfg.AlertmanagerConfig.GetReceivers() {
|
||||
for j, gi := range gr.GrafanaManagedReceivers {
|
||||
assert.Equal(t,
|
||||
cfg.AlertmanagerConfig.Receivers[i].GrafanaManagedReceivers[j].Name,
|
||||
gi.Name,
|
||||
)
|
||||
cfg.AlertmanagerConfig.Receivers[i].GrafanaManagedReceivers[j].UID = gi.UID
|
||||
patched++
|
||||
}
|
||||
}
|
||||
}
|
||||
patchUIDs(t)
|
||||
|
||||
// Now check that editor can update non-protected fields and add new integrations to existing receivers
|
||||
cfg.AlertmanagerConfig.Receivers[0].GrafanaManagedReceivers[0].Settings = apimodels.RawMessage(`
|
||||
{
|
||||
"url":"http://localhost:9000",
|
||||
"httpMethod": "PUT"
|
||||
}
|
||||
`)
|
||||
cfg.AlertmanagerConfig.Receivers[0].GrafanaManagedReceivers = append(cfg.AlertmanagerConfig.Receivers[0].GrafanaManagedReceivers,
|
||||
&apimodels.PostableGrafanaReceiver{
|
||||
Name: cfg.AlertmanagerConfig.Receivers[0].Name,
|
||||
Type: "webhook",
|
||||
DisableResolveMessage: false,
|
||||
Settings: apimodels.RawMessage(`{"url":"http://new-localhost:9000"}`),
|
||||
SecureSettings: nil,
|
||||
},
|
||||
)
|
||||
|
||||
_, err = editorClient.PostConfiguration(t, cfg)
|
||||
require.NoError(t, err)
|
||||
|
||||
patchUIDs(t)
|
||||
|
||||
// Now editor tries to update protected field and fails
|
||||
cfg.AlertmanagerConfig.Receivers[0].GrafanaManagedReceivers[1].Settings = apimodels.RawMessage(`{"url":"http://very-localhost:9001"}`)
|
||||
|
||||
// Editor can add new integrations to existing receivers
|
||||
success, err := editorClient.PostConfiguration(t, cfg)
|
||||
require.Falsef(t, success, "the request should have failed")
|
||||
t.Log(err)
|
||||
require.Error(t, err)
|
||||
|
||||
// but Admin should still be able to update protected fields
|
||||
_, err = adminClient.PostConfiguration(t, cfg)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user