Skip to content

Commit 4a12446

Browse files
authored
Check is config is default by comparing hashes (grafana#92296)
1 parent a990b77 commit 4a12446

File tree

2 files changed

+65
-3
lines changed

2 files changed

+65
-3
lines changed

pkg/services/ngalert/remote/alertmanager.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,24 @@ func (am *Alertmanager) CompareAndSendConfiguration(ctx context.Context, config
263263
if !am.shouldSendConfig(ctx, decrypted) {
264264
return nil
265265
}
266-
return am.sendConfiguration(ctx, decrypted, config.ConfigurationHash, config.CreatedAt, config.Default)
266+
267+
isDefault, err := am.isDefaultConfiguration(decrypted)
268+
if err != nil {
269+
return err
270+
}
271+
272+
return am.sendConfiguration(ctx, decrypted, config.ConfigurationHash, config.CreatedAt, isDefault)
273+
}
274+
275+
func (am *Alertmanager) isDefaultConfiguration(cfg *apimodels.PostableUserConfig) (bool, error) {
276+
rawCfg, err := json.Marshal(cfg)
277+
if err != nil {
278+
return false, err
279+
}
280+
281+
configHash := fmt.Sprintf("%x", md5.Sum(rawCfg))
282+
283+
return configHash == am.defaultConfigHash, nil
267284
}
268285

269286
func (am *Alertmanager) decryptConfiguration(ctx context.Context, cfg *apimodels.PostableUserConfig) (*apimodels.PostableUserConfig, error) {

pkg/services/ngalert/remote/alertmanager_test.go

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,9 @@ import (
4444

4545
const (
4646
// Valid Grafana Alertmanager configurations.
47-
testGrafanaConfig = `{"template_files":{},"alertmanager_config":{"route":{"receiver":"grafana-default-email","group_by":["grafana_folder","alertname"]},"receivers":[{"name":"grafana-default-email","grafana_managed_receiver_configs":[{"uid":"","name":"some other name","type":"email","disableResolveMessage":false,"settings":{"addresses":"\[email protected]\u003e"}}]}]}}`
48-
testGrafanaConfigWithSecret = `{"template_files":{},"alertmanager_config":{"route":{"receiver":"grafana-default-email","group_by":["grafana_folder","alertname"]},"receivers":[{"name":"grafana-default-email","grafana_managed_receiver_configs":[{"uid":"dde6ntuob69dtf","name":"WH","type":"webhook","disableResolveMessage":false,"settings":{"url":"http://localhost:8080","username":"test"},"secureSettings":{"password":"test"}}]}]}}`
47+
testGrafanaConfig = `{"template_files":{},"alertmanager_config":{"route":{"receiver":"grafana-default-email","group_by":["grafana_folder","alertname"]},"receivers":[{"name":"grafana-default-email","grafana_managed_receiver_configs":[{"uid":"","name":"some other name","type":"email","disableResolveMessage":false,"settings":{"addresses":"\[email protected]\u003e"}}]}]}}`
48+
testGrafanaConfigWithSecret = `{"template_files":{},"alertmanager_config":{"route":{"receiver":"grafana-default-email","group_by":["grafana_folder","alertname"]},"receivers":[{"name":"grafana-default-email","grafana_managed_receiver_configs":[{"uid":"dde6ntuob69dtf","name":"WH","type":"webhook","disableResolveMessage":false,"settings":{"url":"http://localhost:8080","username":"test"},"secureSettings":{"password":"test"}}]}]}}`
49+
testGrafanaDefaultConfigWithDifferentFieldOrder = `{"alertmanager_config":{"route":{"group_by":["alertname","grafana_folder"],"receiver":"grafana-default-email"},"receivers":[{"grafana_managed_receiver_configs":[{"uid":"","name":"email receiver","type":"email","settings":{"addresses":"<[email protected]>"}}],"name":"grafana-default-email"}]}}`
4950

5051
// Valid Alertmanager state base64 encoded.
5152
testSilence1 = "lwEKhgEKATESFxIJYWxlcnRuYW1lGgp0ZXN0X2FsZXJ0EiMSDmdyYWZhbmFfZm9sZGVyGhF0ZXN0X2FsZXJ0X2ZvbGRlchoMCN2CkbAGEJbKrMsDIgwI7Z6RsAYQlsqsywMqCwiAkrjDmP7///8BQgxHcmFmYW5hIFRlc3RKDFRlc3QgU2lsZW5jZRIMCO2ekbAGEJbKrMsD"
@@ -334,6 +335,50 @@ func TestCompareAndSendConfiguration(t *testing.T) {
334335
}
335336
}
336337

338+
func Test_isDefaultConfiguration(t *testing.T) {
339+
parsedDefaultConfig, _ := notifier.Load([]byte(defaultGrafanaConfig))
340+
parsedTestConfig, _ := notifier.Load([]byte(testGrafanaConfig))
341+
parsedDefaultConfigWithDifferentFieldOrder, _ := notifier.Load([]byte(testGrafanaDefaultConfigWithDifferentFieldOrder))
342+
rawDefaultCfg, _ := json.Marshal(parsedDefaultConfig)
343+
344+
tests := []struct {
345+
name string
346+
config *apimodels.PostableUserConfig
347+
expected bool
348+
}{
349+
{
350+
"empty configuration",
351+
nil,
352+
false,
353+
},
354+
{
355+
"valid configuration",
356+
parsedTestConfig,
357+
false,
358+
},
359+
{
360+
"default configuration",
361+
parsedDefaultConfig,
362+
true,
363+
},
364+
{
365+
"default configuration with different field order",
366+
parsedDefaultConfigWithDifferentFieldOrder,
367+
false,
368+
},
369+
}
370+
for _, test := range tests {
371+
t.Run(test.name, func(tt *testing.T) {
372+
am := &Alertmanager{
373+
defaultConfig: string(rawDefaultCfg),
374+
defaultConfigHash: fmt.Sprintf("%x", md5.Sum(rawDefaultCfg)),
375+
}
376+
isDefault, _ := am.isDefaultConfiguration(test.config)
377+
require.Equal(tt, test.expected, isDefault)
378+
})
379+
}
380+
}
381+
337382
func TestIntegrationRemoteAlertmanagerConfiguration(t *testing.T) {
338383
if testing.Short() {
339384
t.Skip("skipping integration test")

0 commit comments

Comments
 (0)