diff --git a/pkg/alertmanager/api.go b/pkg/alertmanager/api.go index daf517feec0..793adbcbba7 100644 --- a/pkg/alertmanager/api.go +++ b/pkg/alertmanager/api.go @@ -147,7 +147,7 @@ func (am *MultitenantAlertmanager) SetUserConfig(w http.ResponseWriter, r *http. } cfgDesc := alertspb.ToProto(cfg.AlertmanagerConfig, cfg.TemplateFiles, userID) - if err := validateUserConfig(logger, cfgDesc, am.limits, userID); err != nil { + if err := validateUserConfig(logger, cfgDesc, am.limits, userID, am.cfg.UTF8StrictMode); err != nil { level.Warn(logger).Log("msg", errValidatingConfig, "err", err.Error()) http.Error(w, fmt.Sprintf("%s: %s", errValidatingConfig, err.Error()), http.StatusBadRequest) return @@ -185,8 +185,10 @@ func (am *MultitenantAlertmanager) DeleteUserConfig(w http.ResponseWriter, r *ht } // Partially copied from: https://github.com/prometheus/alertmanager/blob/8e861c646bf67599a1704fc843c6a94d519ce312/cli/check_config.go#L65-L96 -func validateUserConfig(logger log.Logger, cfg alertspb.AlertConfigDesc, limits Limits, user string) error { - validateMatchersInConfigDesc(logger, "api", cfg) +func validateUserConfig(logger log.Logger, cfg alertspb.AlertConfigDesc, limits Limits, user string, utf8StrictMode bool) error { + if !utf8StrictMode { + validateMatchersInConfigDesc(logger, "api", cfg) + } // We don't have a valid use case for empty configurations. If a tenant does not have a // configuration set and issue a request to the Alertmanager, we'll a) upload an empty diff --git a/pkg/alertmanager/api_test.go b/pkg/alertmanager/api_test.go index f4cdefcce30..6948161bfb6 100644 --- a/pkg/alertmanager/api_test.go +++ b/pkg/alertmanager/api_test.go @@ -881,6 +881,7 @@ alertmanager_config: | limits := &mockAlertManagerLimits{} am := &MultitenantAlertmanager{ + cfg: &MultitenantAlertmanagerConfig{}, store: prepareInMemoryAlertStore(), logger: test.NewTestingLogger(t), limits: limits, diff --git a/pkg/alertmanager/multitenant.go b/pkg/alertmanager/multitenant.go index ab79594e425..b63b244f613 100644 --- a/pkg/alertmanager/multitenant.go +++ b/pkg/alertmanager/multitenant.go @@ -806,12 +806,14 @@ type amConfig struct { // setConfig applies the given configuration to the alertmanager for `userID`, // creating an alertmanager if it doesn't already exist. func (am *MultitenantAlertmanager) setConfig(cfg amConfig) error { - // Instead of using "config" as the origin, as in Prometheus Alertmanager, we use "tenant". - // The reason for this that the config.Load function uses the origin "config", - // which is correct, but Mimir uses config.Load to validate both API requests and tenant - // configurations. This means metrics from API requests are confused with metrics from - // tenant configurations. To avoid this confusion, we use a different origin. - validateMatchersInConfigDesc(am.logger, "tenant", cfg.AlertConfigDesc) + if !am.cfg.UTF8StrictMode { + // Instead of using "config" as the origin, as in Prometheus Alertmanager, we use "tenant". + // The reason for this that the config.Load function uses the origin "config", + // which is correct, but Mimir uses config.Load to validate both API requests and tenant + // configurations. This means metrics from API requests are confused with metrics from + // tenant configurations. To avoid this confusion, we use a different origin. + validateMatchersInConfigDesc(am.logger, "tenant", cfg.AlertConfigDesc) + } level.Debug(am.logger).Log("msg", "setting config", "user", cfg.User)