diff --git a/pkg/manifests/amcfg.go b/pkg/manifests/amcfg.go index 7d2c6868e8..e4204db5e7 100644 --- a/pkg/manifests/amcfg.go +++ b/pkg/manifests/amcfg.go @@ -5,6 +5,7 @@ import ( "net/url" "golang.org/x/net/http/httpproxy" + yaml2 "gopkg.in/yaml.v2" v1 "k8s.io/api/core/v1" ) @@ -13,10 +14,19 @@ type PrometheusAdditionalAlertmanagerConfigs []AdditionalAlertmanagerConfig // MarshalYAML implements the yaml.Marshaler interface. func (a PrometheusAdditionalAlertmanagerConfigs) MarshalYAML() (interface{}, error) { + return a.MarshalYAMLWithTLSConfig(nil, "") +} + +// MarshalYAMLWithTLSConfig marshals the configs with the provided TLS configuration +func (a PrometheusAdditionalAlertmanagerConfigs) MarshalYAMLWithTLSConfig(cipherSuites []string, minTLSVersion string) (interface{}, error) { result := make([]interface{}, len(a)) for i, item := range a { - promAmCfg := prometheusAdditionalAlertmanagerConfig(item) + promAmCfg := prometheusAdditionalAlertmanagerConfigWithTLS{ + AdditionalAlertmanagerConfig: item, + CipherSuites: cipherSuites, + MinTLSVersion: minTLSVersion, + } y, err := promAmCfg.MarshalYAML() if err != nil { @@ -29,6 +39,20 @@ func (a PrometheusAdditionalAlertmanagerConfigs) MarshalYAML() (interface{}, err return result, nil } +// MarshalPrometheusAdditionalAlertmanagerConfigs marshals the configs with secure TLS settings +func (f *Factory) MarshalPrometheusAdditionalAlertmanagerConfigs(amConfigs []AdditionalAlertmanagerConfig) ([]byte, error) { + prometheusAmConfigs := PrometheusAdditionalAlertmanagerConfigs(amConfigs) + cipherSuites := f.APIServerConfig.TLSCiphers() + minTLSVersion := f.APIServerConfig.MinTLSVersion() + + result, err := prometheusAmConfigs.MarshalYAMLWithTLSConfig(cipherSuites, minTLSVersion) + if err != nil { + return nil, err + } + + return yaml2.Marshal(result) +} + // amConfigPrometheus is our internal representation of the Prometheus alerting configuration. type amConfigPrometheus struct { Scheme string `yaml:"scheme,omitempty"` @@ -46,26 +70,29 @@ type amConfigAuthorization struct { } type amConfigTLS struct { - CA string `yaml:"ca_file,omitempty"` - Cert string `yaml:"cert_file,omitempty"` - Key string `yaml:"key_file,omitempty"` - ServerName string `yaml:"server_name,omitempty"` - InsecureSkipVerify bool `yaml:"insecure_skip_verify,omitempty"` + CA string `yaml:"ca_file,omitempty"` + Cert string `yaml:"cert_file,omitempty"` + Key string `yaml:"key_file,omitempty"` + ServerName string `yaml:"server_name,omitempty"` + InsecureSkipVerify bool `yaml:"insecure_skip_verify,omitempty"` + MinVersion string `yaml:"min_version,omitempty"` + CipherSuites []string `yaml:"cipher_suites,omitempty"` } type amConfigStaticConfigs struct { Targets []string `yaml:"targets"` } -// prometheusAdditionalAlertmanagerConfig is an AdditionalAlertmanagerConfig -// which can be marshaled into a yaml string, compatible with the Prometheus -// configuration format -type prometheusAdditionalAlertmanagerConfig AdditionalAlertmanagerConfig +// prometheusAdditionalAlertmanagerConfigWithTLS is an AdditionalAlertmanagerConfig +// with TLS configuration that can be marshaled with secure cipher suites and min TLS version +type prometheusAdditionalAlertmanagerConfigWithTLS struct { + AdditionalAlertmanagerConfig + CipherSuites []string + MinTLSVersion string +} // MarshalYAML implements the yaml.Marshaler interface. -// It marshals a PrometheusAdditionalAlertmanagerConfig into a format -// compatible with the Prometheus configuration. -func (a prometheusAdditionalAlertmanagerConfig) MarshalYAML() (interface{}, error) { +func (a prometheusAdditionalAlertmanagerConfigWithTLS) MarshalYAML() (interface{}, error) { cfg := amConfigPrometheus{ Scheme: a.Scheme, PathPrefix: a.PathPrefix, @@ -84,6 +111,20 @@ func (a prometheusAdditionalAlertmanagerConfig) MarshalYAML() (interface{}, erro }, } + // Check if this configuration needs TLS security settings + // Apply strict TLS only for HTTPS connections WITHOUT explicit TLS config + // If explicit TLS config is provided, respect user's choices + hasExplicitTLSConfig := a.TLSConfig.CA != nil || a.TLSConfig.Cert != nil || a.TLSConfig.Key != nil || + a.TLSConfig.ServerName != "" || a.TLSConfig.InsecureSkipVerify + + needsTLSSecuritySettings := a.Scheme == "https" && !hasExplicitTLSConfig + + // Apply TLS security settings only for HTTPS connections without explicit TLS config + if needsTLSSecuritySettings { + cfg.TLSConfig.MinVersion = a.MinTLSVersion + cfg.TLSConfig.CipherSuites = a.CipherSuites + } + caPath, err := secretPath(a.TLSConfig.CA) if err != nil { return nil, err @@ -141,6 +182,9 @@ type amHTTPConfig struct { func (f *Factory) ConvertToThanosAlertmanagerConfiguration(ta []AdditionalAlertmanagerConfig) ([]thanosAlertmanagerConfiguration, error) { result := make([]thanosAlertmanagerConfiguration, len(ta)) + cipherSuites := f.APIServerConfig.TLSCiphers() + minTLSVersion := f.APIServerConfig.MinTLSVersion() + for i, a := range ta { cfg := thanosAlertmanagerConfiguration{ Scheme: a.Scheme, @@ -159,6 +203,20 @@ func (f *Factory) ConvertToThanosAlertmanagerConfiguration(ta []AdditionalAlertm }, } + // Check if this configuration needs TLS security settings + // Apply strict TLS only for HTTPS connections WITHOUT explicit TLS config + // If explicit TLS config is provided, respect user's choices + hasExplicitTLSConfig := a.TLSConfig.CA != nil || a.TLSConfig.Cert != nil || a.TLSConfig.Key != nil || + a.TLSConfig.ServerName != "" || a.TLSConfig.InsecureSkipVerify + + needsTLSSecuritySettings := a.Scheme == "https" && !hasExplicitTLSConfig + + // Apply TLS security settings only for HTTPS connections without explicit TLS config + if needsTLSSecuritySettings { + cfg.HTTPConfig.TLSConfig.MinVersion = minTLSVersion + cfg.HTTPConfig.TLSConfig.CipherSuites = cipherSuites + } + caPath, err := secretPath(a.TLSConfig.CA) if err != nil { return nil, err diff --git a/pkg/manifests/manifests.go b/pkg/manifests/manifests.go index 4e023c9346..30ac2637cc 100644 --- a/pkg/manifests/manifests.go +++ b/pkg/manifests/manifests.go @@ -1634,9 +1634,8 @@ func (f *Factory) setupPrometheusRemoteWriteProxy(p *monv1.Prometheus) { func (f *Factory) PrometheusK8sAdditionalAlertManagerConfigsSecret() (*v1.Secret, error) { amConfigs := f.config.ClusterMonitoringConfiguration.PrometheusK8sConfig.AlertmanagerConfigs - prometheusAmConfigs := PrometheusAdditionalAlertmanagerConfigs(amConfigs) - config, err := yaml2.Marshal(prometheusAmConfigs) + config, err := f.MarshalPrometheusAdditionalAlertmanagerConfigs(amConfigs) if err != nil { return nil, err } @@ -1654,8 +1653,8 @@ func (f *Factory) PrometheusK8sAdditionalAlertManagerConfigsSecret() (*v1.Secret func (f *Factory) PrometheusUserWorkloadAdditionalAlertManagerConfigsSecret() (*v1.Secret, error) { amConfigs := f.config.AdditionalAlertmanagerConfigsForPrometheusUserWorkload() - prometheusAmConfigs := PrometheusAdditionalAlertmanagerConfigs(amConfigs) - config, err := yaml2.Marshal(prometheusAmConfigs) + + config, err := f.MarshalPrometheusAdditionalAlertmanagerConfigs(amConfigs) if err != nil { return nil, err } diff --git a/pkg/manifests/manifests_test.go b/pkg/manifests/manifests_test.go index a6858f08d2..46591a013f 100644 --- a/pkg/manifests/manifests_test.go +++ b/pkg/manifests/manifests_test.go @@ -2058,6 +2058,20 @@ func TestPrometheusK8sAdditionalAlertManagerConfigsSecret(t *testing.T) { api_version: v2 authorization: credentials_file: /etc/prometheus/secrets/alertmanager1-bearer-token/token + tls_config: + min_version: VersionTLS12 + cipher_suites: + - TLS_AES_128_GCM_SHA256 + - TLS_AES_256_GCM_SHA384 + - TLS_CHACHA20_POLY1305_SHA256 + - ECDHE-ECDSA-AES128-GCM-SHA256 + - ECDHE-RSA-AES128-GCM-SHA256 + - ECDHE-ECDSA-AES256-GCM-SHA384 + - ECDHE-RSA-AES256-GCM-SHA384 + - ECDHE-ECDSA-CHACHA20-POLY1305 + - ECDHE-RSA-CHACHA20-POLY1305 + - DHE-RSA-AES128-GCM-SHA256 + - DHE-RSA-AES256-GCM-SHA384 static_configs: - targets: - alertmanager1-remote.com @@ -2353,6 +2367,21 @@ func TestThanosRulerAdditionalAlertManagerConfigsSecret(t *testing.T) { - scheme: https path_prefix: /path-prefix api_version: v2 + http_config: + tls_config: + min_version: VersionTLS12 + cipher_suites: + - TLS_AES_128_GCM_SHA256 + - TLS_AES_256_GCM_SHA384 + - TLS_CHACHA20_POLY1305_SHA256 + - ECDHE-ECDSA-AES128-GCM-SHA256 + - ECDHE-RSA-AES128-GCM-SHA256 + - ECDHE-ECDSA-AES256-GCM-SHA384 + - ECDHE-RSA-AES256-GCM-SHA384 + - ECDHE-ECDSA-CHACHA20-POLY1305 + - ECDHE-RSA-CHACHA20-POLY1305 + - DHE-RSA-AES128-GCM-SHA256 + - DHE-RSA-AES256-GCM-SHA384 static_configs: - alertmanager1-remote.com - alertmanager1-remotex.com