Skip to content

Commit ef5e903

Browse files
committed
Support default SMTP TLS config
Fixes: #3709 Signed-off-by: Mathieu Parent <[email protected]>
1 parent efa801f commit ef5e903

File tree

6 files changed

+61
-47
lines changed

6 files changed

+61
-47
lines changed

config/config.go

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,9 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error {
365365
}
366366
}
367367
for _, ec := range rcv.EmailConfigs {
368+
if ec.TLSConfig == nil {
369+
ec.TLSConfig = c.Global.SMTPTLSConfig
370+
}
368371
if ec.Smarthost.String() == "" {
369372
if c.Global.SMTPSmarthost.String() == "" {
370373
return fmt.Errorf("no global SMTP smarthost set")
@@ -629,12 +632,14 @@ func checkTimeInterval(r *Route, timeIntervals map[string]struct{}) error {
629632
// DefaultGlobalConfig returns GlobalConfig with default values.
630633
func DefaultGlobalConfig() GlobalConfig {
631634
defaultHTTPConfig := commoncfg.DefaultHTTPClientConfig
632-
return GlobalConfig{
633-
ResolveTimeout: model.Duration(5 * time.Minute),
634-
HTTPConfig: &defaultHTTPConfig,
635+
defaultSMTPTLSConfig := commoncfg.TLSConfig{}
635636

637+
return GlobalConfig{
638+
ResolveTimeout: model.Duration(5 * time.Minute),
639+
HTTPConfig: &defaultHTTPConfig,
636640
SMTPHello: "localhost",
637641
SMTPRequireTLS: true,
642+
SMTPTLSConfig: &defaultSMTPTLSConfig,
638643
PagerdutyURL: mustParseURL("https://events.pagerduty.com/v2/enqueue"),
639644
OpsGenieAPIURL: mustParseURL("https://api.opsgenie.com/"),
640645
WeChatAPIURL: mustParseURL("https://qyapi.weixin.qq.com/cgi-bin/"),
@@ -742,29 +747,30 @@ type GlobalConfig struct {
742747

743748
HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"`
744749

745-
SMTPFrom string `yaml:"smtp_from,omitempty" json:"smtp_from,omitempty"`
746-
SMTPHello string `yaml:"smtp_hello,omitempty" json:"smtp_hello,omitempty"`
747-
SMTPSmarthost HostPort `yaml:"smtp_smarthost,omitempty" json:"smtp_smarthost,omitempty"`
748-
SMTPAuthUsername string `yaml:"smtp_auth_username,omitempty" json:"smtp_auth_username,omitempty"`
749-
SMTPAuthPassword Secret `yaml:"smtp_auth_password,omitempty" json:"smtp_auth_password,omitempty"`
750-
SMTPAuthPasswordFile string `yaml:"smtp_auth_password_file,omitempty" json:"smtp_auth_password_file,omitempty"`
751-
SMTPAuthSecret Secret `yaml:"smtp_auth_secret,omitempty" json:"smtp_auth_secret,omitempty"`
752-
SMTPAuthIdentity string `yaml:"smtp_auth_identity,omitempty" json:"smtp_auth_identity,omitempty"`
753-
SMTPRequireTLS bool `yaml:"smtp_require_tls" json:"smtp_require_tls,omitempty"`
754-
SlackAPIURL *SecretURL `yaml:"slack_api_url,omitempty" json:"slack_api_url,omitempty"`
755-
SlackAPIURLFile string `yaml:"slack_api_url_file,omitempty" json:"slack_api_url_file,omitempty"`
756-
PagerdutyURL *URL `yaml:"pagerduty_url,omitempty" json:"pagerduty_url,omitempty"`
757-
OpsGenieAPIURL *URL `yaml:"opsgenie_api_url,omitempty" json:"opsgenie_api_url,omitempty"`
758-
OpsGenieAPIKey Secret `yaml:"opsgenie_api_key,omitempty" json:"opsgenie_api_key,omitempty"`
759-
OpsGenieAPIKeyFile string `yaml:"opsgenie_api_key_file,omitempty" json:"opsgenie_api_key_file,omitempty"`
760-
WeChatAPIURL *URL `yaml:"wechat_api_url,omitempty" json:"wechat_api_url,omitempty"`
761-
WeChatAPISecret Secret `yaml:"wechat_api_secret,omitempty" json:"wechat_api_secret,omitempty"`
762-
WeChatAPICorpID string `yaml:"wechat_api_corp_id,omitempty" json:"wechat_api_corp_id,omitempty"`
763-
VictorOpsAPIURL *URL `yaml:"victorops_api_url,omitempty" json:"victorops_api_url,omitempty"`
764-
VictorOpsAPIKey Secret `yaml:"victorops_api_key,omitempty" json:"victorops_api_key,omitempty"`
765-
VictorOpsAPIKeyFile string `yaml:"victorops_api_key_file,omitempty" json:"victorops_api_key_file,omitempty"`
766-
TelegramAPIUrl *URL `yaml:"telegram_api_url,omitempty" json:"telegram_api_url,omitempty"`
767-
WebexAPIURL *URL `yaml:"webex_api_url,omitempty" json:"webex_api_url,omitempty"`
750+
SMTPFrom string `yaml:"smtp_from,omitempty" json:"smtp_from,omitempty"`
751+
SMTPHello string `yaml:"smtp_hello,omitempty" json:"smtp_hello,omitempty"`
752+
SMTPSmarthost HostPort `yaml:"smtp_smarthost,omitempty" json:"smtp_smarthost,omitempty"`
753+
SMTPAuthUsername string `yaml:"smtp_auth_username,omitempty" json:"smtp_auth_username,omitempty"`
754+
SMTPAuthPassword Secret `yaml:"smtp_auth_password,omitempty" json:"smtp_auth_password,omitempty"`
755+
SMTPAuthPasswordFile string `yaml:"smtp_auth_password_file,omitempty" json:"smtp_auth_password_file,omitempty"`
756+
SMTPAuthSecret Secret `yaml:"smtp_auth_secret,omitempty" json:"smtp_auth_secret,omitempty"`
757+
SMTPAuthIdentity string `yaml:"smtp_auth_identity,omitempty" json:"smtp_auth_identity,omitempty"`
758+
SMTPRequireTLS bool `yaml:"smtp_require_tls" json:"smtp_require_tls,omitempty"`
759+
SMTPTLSConfig *commoncfg.TLSConfig `yaml:"smtp_tls_config,omitempty" json:"smtp_tls_config,omitempty"`
760+
SlackAPIURL *SecretURL `yaml:"slack_api_url,omitempty" json:"slack_api_url,omitempty"`
761+
SlackAPIURLFile string `yaml:"slack_api_url_file,omitempty" json:"slack_api_url_file,omitempty"`
762+
PagerdutyURL *URL `yaml:"pagerduty_url,omitempty" json:"pagerduty_url,omitempty"`
763+
OpsGenieAPIURL *URL `yaml:"opsgenie_api_url,omitempty" json:"opsgenie_api_url,omitempty"`
764+
OpsGenieAPIKey Secret `yaml:"opsgenie_api_key,omitempty" json:"opsgenie_api_key,omitempty"`
765+
OpsGenieAPIKeyFile string `yaml:"opsgenie_api_key_file,omitempty" json:"opsgenie_api_key_file,omitempty"`
766+
WeChatAPIURL *URL `yaml:"wechat_api_url,omitempty" json:"wechat_api_url,omitempty"`
767+
WeChatAPISecret Secret `yaml:"wechat_api_secret,omitempty" json:"wechat_api_secret,omitempty"`
768+
WeChatAPICorpID string `yaml:"wechat_api_corp_id,omitempty" json:"wechat_api_corp_id,omitempty"`
769+
VictorOpsAPIURL *URL `yaml:"victorops_api_url,omitempty" json:"victorops_api_url,omitempty"`
770+
VictorOpsAPIKey Secret `yaml:"victorops_api_key,omitempty" json:"victorops_api_key,omitempty"`
771+
VictorOpsAPIKeyFile string `yaml:"victorops_api_key_file,omitempty" json:"victorops_api_key_file,omitempty"`
772+
TelegramAPIUrl *URL `yaml:"telegram_api_url,omitempty" json:"telegram_api_url,omitempty"`
773+
WebexAPIURL *URL `yaml:"webex_api_url,omitempty" json:"webex_api_url,omitempty"`
768774
}
769775

770776
// UnmarshalYAML implements the yaml.Unmarshaler interface for GlobalConfig.

config/config_test.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -857,9 +857,12 @@ func TestEmptyFieldsAndRegex(t *testing.T) {
857857
FollowRedirects: true,
858858
EnableHTTP2: true,
859859
},
860-
ResolveTimeout: model.Duration(5 * time.Minute),
861-
SMTPSmarthost: HostPort{Host: "localhost", Port: "25"},
862-
SMTPFrom: "[email protected]",
860+
ResolveTimeout: model.Duration(5 * time.Minute),
861+
SMTPSmarthost: HostPort{Host: "localhost", Port: "25"},
862+
SMTPFrom: "[email protected]",
863+
SMTPTLSConfig: &commoncfg.TLSConfig{
864+
InsecureSkipVerify: false,
865+
},
863866
SlackAPIURL: (*SecretURL)(mustParseURL("http://slack.example.com/")),
864867
SMTPRequireTLS: true,
865868
PagerdutyURL: mustParseURL("https://events.pagerduty.com/v2/enqueue"),
@@ -905,6 +908,9 @@ func TestEmptyFieldsAndRegex(t *testing.T) {
905908
Smarthost: HostPort{Host: "localhost", Port: "25"},
906909
HTML: "{{ template \"email.default.html\" . }}",
907910
RequireTLS: &boolFoo,
911+
TLSConfig: &commoncfg.TLSConfig{
912+
InsecureSkipVerify: false,
913+
},
908914
},
909915
},
910916
},

config/notifiers.go

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -248,20 +248,20 @@ type EmailConfig struct {
248248
NotifierConfig `yaml:",inline" json:",inline"`
249249

250250
// Email address to notify.
251-
To string `yaml:"to,omitempty" json:"to,omitempty"`
252-
From string `yaml:"from,omitempty" json:"from,omitempty"`
253-
Hello string `yaml:"hello,omitempty" json:"hello,omitempty"`
254-
Smarthost HostPort `yaml:"smarthost,omitempty" json:"smarthost,omitempty"`
255-
AuthUsername string `yaml:"auth_username,omitempty" json:"auth_username,omitempty"`
256-
AuthPassword Secret `yaml:"auth_password,omitempty" json:"auth_password,omitempty"`
257-
AuthPasswordFile string `yaml:"auth_password_file,omitempty" json:"auth_password_file,omitempty"`
258-
AuthSecret Secret `yaml:"auth_secret,omitempty" json:"auth_secret,omitempty"`
259-
AuthIdentity string `yaml:"auth_identity,omitempty" json:"auth_identity,omitempty"`
260-
Headers map[string]string `yaml:"headers,omitempty" json:"headers,omitempty"`
261-
HTML string `yaml:"html,omitempty" json:"html,omitempty"`
262-
Text string `yaml:"text,omitempty" json:"text,omitempty"`
263-
RequireTLS *bool `yaml:"require_tls,omitempty" json:"require_tls,omitempty"`
264-
TLSConfig commoncfg.TLSConfig `yaml:"tls_config,omitempty" json:"tls_config,omitempty"`
251+
To string `yaml:"to,omitempty" json:"to,omitempty"`
252+
From string `yaml:"from,omitempty" json:"from,omitempty"`
253+
Hello string `yaml:"hello,omitempty" json:"hello,omitempty"`
254+
Smarthost HostPort `yaml:"smarthost,omitempty" json:"smarthost,omitempty"`
255+
AuthUsername string `yaml:"auth_username,omitempty" json:"auth_username,omitempty"`
256+
AuthPassword Secret `yaml:"auth_password,omitempty" json:"auth_password,omitempty"`
257+
AuthPasswordFile string `yaml:"auth_password_file,omitempty" json:"auth_password_file,omitempty"`
258+
AuthSecret Secret `yaml:"auth_secret,omitempty" json:"auth_secret,omitempty"`
259+
AuthIdentity string `yaml:"auth_identity,omitempty" json:"auth_identity,omitempty"`
260+
Headers map[string]string `yaml:"headers,omitempty" json:"headers,omitempty"`
261+
HTML string `yaml:"html,omitempty" json:"html,omitempty"`
262+
Text string `yaml:"text,omitempty" json:"text,omitempty"`
263+
RequireTLS *bool `yaml:"require_tls,omitempty" json:"require_tls,omitempty"`
264+
TLSConfig *commoncfg.TLSConfig `yaml:"tls_config,omitempty" json:"tls_config,omitempty"`
265265
}
266266

267267
// UnmarshalYAML implements the yaml.Unmarshaler interface.

docs/configuration.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ global:
8383
# The default SMTP TLS requirement.
8484
# Note that Go does not support unencrypted connections to remote SMTP endpoints.
8585
[ smtp_require_tls: <bool> | default = true ]
86+
# The default TLS configuration for SMTP receivers
87+
[ smtp_tls_config: <tls_config> ]
8688

8789
# The API URL to use for Slack notifications.
8890
[ slack_api_url: <secret> ]
@@ -884,7 +886,7 @@ to: <tmpl_string>
884886
885887
# TLS configuration.
886888
tls_config:
887-
[ <tls_config> ]
889+
[ <tls_config> | default = global.smtp_tls_config ]
888890
889891
# The HTML body of the email notification.
890892
[ html: <tmpl_string> | default = '{{ template "email.default.html" . }}' ]

notify/email/email.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ func (n *Email) Notify(ctx context.Context, as ...*types.Alert) (bool, error) {
131131
success = false
132132
)
133133
if n.conf.Smarthost.Port == "465" {
134-
tlsConfig, err := commoncfg.NewTLSConfig(&n.conf.TLSConfig)
134+
tlsConfig, err := commoncfg.NewTLSConfig(n.conf.TLSConfig)
135135
if err != nil {
136136
return false, fmt.Errorf("parse TLS configuration: %w", err)
137137
}
@@ -178,7 +178,7 @@ func (n *Email) Notify(ctx context.Context, as ...*types.Alert) (bool, error) {
178178
return true, fmt.Errorf("'require_tls' is true (default) but %q does not advertise the STARTTLS extension", n.conf.Smarthost)
179179
}
180180

181-
tlsConf, err := commoncfg.NewTLSConfig(&n.conf.TLSConfig)
181+
tlsConf, err := commoncfg.NewTLSConfig(n.conf.TLSConfig)
182182
if err != nil {
183183
return false, fmt.Errorf("parse TLS configuration: %w", err)
184184
}

notify/email/email_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ func TestEmailNotifyWithSTARTTLS(t *testing.T) {
407407
Text: "Text body",
408408
RequireTLS: &trueVar,
409409
// MailDev embeds a self-signed certificate which can't be retrieved.
410-
TLSConfig: commoncfg.TLSConfig{InsecureSkipVerify: true},
410+
TLSConfig: &commoncfg.TLSConfig{InsecureSkipVerify: true},
411411
},
412412
c.Server,
413413
)

0 commit comments

Comments
 (0)