From 3140823c2ed0766bad96232200acddcf9476672d Mon Sep 17 00:00:00 2001 From: Friedrich Gonzalez <1517449+friedrichg@users.noreply.github.com> Date: Thu, 6 Nov 2025 20:17:51 -0800 Subject: [PATCH] Add receiver validation (discord and email) (#7097) Signed-off-by: Friedrich Gonzalez <1517449+friedrichg@users.noreply.github.com> --- CHANGELOG.md | 1 + pkg/alertmanager/api.go | 28 ++++++++++++++++++++++++++++ pkg/alertmanager/api_test.go | 29 +++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41e115de021..b2b859c7519 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -111,6 +111,7 @@ * [BUGFIX] Scheduler: Avoid all queriers reserved for prioritized requests. #7057 * [BUGFIX] Fix bug where validating metric names uses the wrong validation logic. #7086 * [BUGFIX] Compactor: Avoid race condition which allow a grouper to not compact all partitions. #7082 +* [BUGFIX] Add alertmanager receiver validation for discord and email. #7097 ## 1.19.1 2025-09-20 diff --git a/pkg/alertmanager/api.go b/pkg/alertmanager/api.go index cbac5bd89c9..64c68d7e509 100644 --- a/pkg/alertmanager/api.go +++ b/pkg/alertmanager/api.go @@ -56,6 +56,8 @@ var ( errMSTeamsV2WebhookUrlFileNotAllowed = errors.New("setting MSTeamsV2 webhook_url_file is not allowed") errRocketChatTokenIdFileNotAllowed = errors.New("setting RocketChat token_id_file is not allowed") errRocketChatTokenFileNotAllowed = errors.New("setting RocketChat token_file is not allowed") + errDiscordWebhookUrlFileNotAllowed = errors.New("setting Discord webhook_url_file is not allowed") + errEmailAuthPasswordFileNotAllowed = errors.New("setting Email auth_password_file is not allowed") ) // UserConfig is used to communicate a users alertmanager configs @@ -399,6 +401,14 @@ func validateAlertmanagerConfig(cfg any) error { if err := validateRocketChatConfig(v.Interface().(config.RocketchatConfig)); err != nil { return err } + case reflect.TypeOf(config.DiscordConfig{}): + if err := validateDiscordConfig(v.Interface().(config.DiscordConfig)); err != nil { + return err + } + case reflect.TypeOf(config.EmailConfig{}): + if err := validateEmailConfig(v.Interface().(config.EmailConfig)); err != nil { + return err + } } // If the input config is a struct, recursively iterate on all fields. @@ -588,3 +598,21 @@ func validateRocketChatConfig(cfg config.RocketchatConfig) error { return nil } + +// validateDiscordConfig validates the Discord Config and returns an error if it contains +// settings not allowed by Cortex. +func validateDiscordConfig(cfg config.DiscordConfig) error { + if cfg.WebhookURLFile != "" { + return errDiscordWebhookUrlFileNotAllowed + } + return nil +} + +// validateEmailConfig validates the Email Config and returns an error if it contains +// settings not allowed by Cortex. +func validateEmailConfig(cfg config.EmailConfig) error { + if cfg.AuthPasswordFile != "" { + return errEmailAuthPasswordFileNotAllowed + } + return nil +} diff --git a/pkg/alertmanager/api_test.go b/pkg/alertmanager/api_test.go index 8c0a097d84c..12a52895cb0 100644 --- a/pkg/alertmanager/api_test.go +++ b/pkg/alertmanager/api_test.go @@ -703,6 +703,35 @@ alertmanager_config: | `, err: errors.Wrap(errRocketChatTokenFileNotAllowed, "error validating Alertmanager config"), }, + { + name: "Should return error if Discord webhook_url_file is set", + cfg: ` +alertmanager_config: | + receivers: + - name: default-receiver + discord_configs: + - webhook_url_file: /urlFile + route: + receiver: 'default-receiver' +`, + err: errors.Wrap(errDiscordWebhookUrlFileNotAllowed, "error validating Alertmanager config"), + }, + { + name: "Should return error if Email auth_password_file is set", + cfg: ` +alertmanager_config: | + receivers: + - name: default-receiver + email_configs: + - to: user@example.com + from: admin@example.com + smarthost: example.com:25 + auth_password_file: /passwordFile + route: + receiver: 'default-receiver' +`, + err: errors.Wrap(errEmailAuthPasswordFileNotAllowed, "error validating Alertmanager config"), + }, } limits := &mockAlertManagerLimits{}