Add EmailSettingsService to hold global email settings.
This change adds a service to hold the dynamically updateable email settings. Added logging and made inner settings holding class static. Original commit: elastic/x-pack-elasticsearch@e1690fa292
This commit is contained in:
parent
da1f446b49
commit
0470fdf6af
|
@ -6,6 +6,7 @@
|
|||
package org.elasticsearch.alerts.actions;
|
||||
|
||||
import org.elasticsearch.alerts.actions.email.EmailAction;
|
||||
import org.elasticsearch.alerts.actions.email.EmailSettingsService;
|
||||
import org.elasticsearch.alerts.actions.index.IndexAction;
|
||||
import org.elasticsearch.alerts.actions.webhook.HttpClient;
|
||||
import org.elasticsearch.alerts.actions.webhook.WebhookAction;
|
||||
|
@ -46,6 +47,7 @@ public class ActionModule extends AbstractModule {
|
|||
|
||||
bind(ActionRegistry.class).asEagerSingleton();
|
||||
bind(HttpClient.class).asEagerSingleton();
|
||||
bind(EmailSettingsService.class).asEagerSingleton();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -9,8 +9,6 @@ import org.elasticsearch.alerts.Alert;
|
|||
import org.elasticsearch.alerts.actions.Action;
|
||||
import org.elasticsearch.alerts.actions.ActionException;
|
||||
import org.elasticsearch.alerts.support.StringTemplateUtils;
|
||||
import org.elasticsearch.cluster.settings.DynamicSettings;
|
||||
import org.elasticsearch.cluster.settings.Validator;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.component.AbstractComponent;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
|
@ -19,7 +17,6 @@ import org.elasticsearch.common.logging.ESLogger;
|
|||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.node.settings.NodeSettingsService;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
|
||||
import javax.mail.*;
|
||||
|
@ -31,16 +28,10 @@ import java.util.*;
|
|||
|
||||
/**
|
||||
*/
|
||||
public class EmailAction extends Action<EmailAction.Result> implements NodeSettingsService.Listener {
|
||||
public class EmailAction extends Action<EmailAction.Result> {
|
||||
|
||||
public static final String TYPE = "email";
|
||||
|
||||
static final String PORT_SETTING = "alerts.action.email.server.port";
|
||||
static final String SERVER_SETTING = "alerts.action.email.server.name";
|
||||
static final String FROM_SETTING = "alerts.action.email.from.address";
|
||||
static final String USERNAME_SETTING = "alerts.action.email.from.username";
|
||||
static final String PASSWORD_SETTING = "alerts.action.email.from.password";
|
||||
|
||||
private final List<Address> emailAddresses;
|
||||
|
||||
//Optional, can be null, will use defaults from emailSettings (EmailServiceConfig)
|
||||
|
@ -48,9 +39,6 @@ public class EmailAction extends Action<EmailAction.Result> implements NodeSetti
|
|||
private final StringTemplateUtils.Template subjectTemplate;
|
||||
private final StringTemplateUtils.Template messageTemplate;
|
||||
|
||||
private static final String DEFAULT_SERVER = "smtp.gmail.com";
|
||||
private static final int DEFAULT_PORT = 578;
|
||||
|
||||
private static final StringTemplateUtils.Template DEFAULT_SUBJECT_TEMPLATE = new StringTemplateUtils.Template(
|
||||
"Elasticsearch Alert {{alert_name}} triggered", null, "mustache", ScriptService.ScriptType.INLINE);
|
||||
|
||||
|
@ -59,24 +47,22 @@ public class EmailAction extends Action<EmailAction.Result> implements NodeSetti
|
|||
|
||||
|
||||
private final StringTemplateUtils templateUtils;
|
||||
private volatile EmailServiceConfig emailSettings = new EmailServiceConfig(DEFAULT_SERVER, DEFAULT_PORT, null, null, null);
|
||||
private final EmailSettingsService emailSettingsService;
|
||||
|
||||
|
||||
protected EmailAction(ESLogger logger, Settings settings, NodeSettingsService nodeSettingsService,
|
||||
protected EmailAction(ESLogger logger, EmailSettingsService emailSettingsService,
|
||||
StringTemplateUtils templateUtils, @Nullable StringTemplateUtils.Template subjectTemplate,
|
||||
@Nullable StringTemplateUtils.Template messageTemplate, @Nullable String fromAddress,
|
||||
List<Address> emailAddresses) {
|
||||
super(logger);
|
||||
|
||||
this.templateUtils = templateUtils;
|
||||
this.emailSettingsService = emailSettingsService;
|
||||
|
||||
this.emailAddresses = new ArrayList<>();
|
||||
this.emailAddresses.addAll(emailAddresses);
|
||||
this.subjectTemplate = subjectTemplate;
|
||||
this.messageTemplate = messageTemplate;
|
||||
this.fromAddress = fromAddress;
|
||||
|
||||
nodeSettingsService.addListener(this);
|
||||
updateSettings(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -87,19 +73,21 @@ public class EmailAction extends Action<EmailAction.Result> implements NodeSetti
|
|||
@Override
|
||||
public Result execute(Alert alert, Map<String, Object> data) throws IOException {
|
||||
|
||||
final EmailSettingsService.EmailServiceConfig emailSettings = emailSettingsService.emailServiceConfig();
|
||||
|
||||
Properties props = new Properties();
|
||||
props.put("mail.smtp.auth", "true");
|
||||
props.put("mail.smtp.starttls.enable", "true");
|
||||
props.put("mail.smtp.host", emailSettings.host);
|
||||
props.put("mail.smtp.port", emailSettings.port);
|
||||
props.put("mail.smtp.host", emailSettings.host());
|
||||
props.put("mail.smtp.port", emailSettings.port());
|
||||
final Session session;
|
||||
|
||||
if (emailSettings.password != null) {
|
||||
if (emailSettings.password() != null) {
|
||||
final String username;
|
||||
if (emailSettings.username != null) {
|
||||
username = emailSettings.username;
|
||||
if (emailSettings.username() != null) {
|
||||
username = emailSettings.username();
|
||||
} else {
|
||||
username = emailSettings.defaultFromAddress;
|
||||
username = emailSettings.defaultFromAddress();
|
||||
}
|
||||
|
||||
if (username == null) {
|
||||
|
@ -109,7 +97,7 @@ public class EmailAction extends Action<EmailAction.Result> implements NodeSetti
|
|||
session = Session.getInstance(props,
|
||||
new javax.mail.Authenticator() {
|
||||
protected PasswordAuthentication getPasswordAuthentication() {
|
||||
return new PasswordAuthentication(username, emailSettings.password);
|
||||
return new PasswordAuthentication(username, emailSettings.password());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
@ -119,7 +107,7 @@ public class EmailAction extends Action<EmailAction.Result> implements NodeSetti
|
|||
try {
|
||||
Message email = new MimeMessage(session);
|
||||
|
||||
String fromAddressToUse = emailSettings.defaultFromAddress;
|
||||
String fromAddressToUse = emailSettings.defaultFromAddress();
|
||||
if (fromAddress != null) {
|
||||
fromAddressToUse = fromAddress;
|
||||
}
|
||||
|
@ -179,11 +167,6 @@ public class EmailAction extends Action<EmailAction.Result> implements NodeSetti
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefreshSettings(Settings settings) {
|
||||
updateSettings(settings);
|
||||
}
|
||||
|
||||
public static class Parser extends AbstractComponent implements Action.Parser<EmailAction> {
|
||||
|
||||
public static final ParseField FROM_FIELD = new ParseField("from");
|
||||
|
@ -191,20 +174,14 @@ public class EmailAction extends Action<EmailAction.Result> implements NodeSetti
|
|||
public static final ParseField MESSAGE_TEMPLATE_FIELD = new ParseField("message_template");
|
||||
public static final ParseField SUBJECT_TEMPLATE_FIELD = new ParseField("subject_template");
|
||||
|
||||
private final NodeSettingsService nodeSettingsService;
|
||||
private final StringTemplateUtils templateUtils;
|
||||
private final EmailSettingsService emailSettingsService;
|
||||
|
||||
@Inject
|
||||
public Parser(Settings settings, DynamicSettings dynamicSettings, NodeSettingsService nodeSettingsService, StringTemplateUtils templateUtils) {
|
||||
public Parser(Settings settings, EmailSettingsService emailSettingsService, StringTemplateUtils templateUtils) {
|
||||
super(settings);
|
||||
this.nodeSettingsService = nodeSettingsService;
|
||||
this.templateUtils = templateUtils;
|
||||
|
||||
dynamicSettings.addDynamicSetting(PORT_SETTING, Validator.POSITIVE_INTEGER);
|
||||
dynamicSettings.addDynamicSetting(SERVER_SETTING);
|
||||
dynamicSettings.addDynamicSetting(FROM_SETTING);
|
||||
dynamicSettings.addDynamicSetting(USERNAME_SETTING);
|
||||
dynamicSettings.addDynamicSetting(PASSWORD_SETTING);
|
||||
this.emailSettingsService = emailSettingsService;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -256,8 +233,8 @@ public class EmailAction extends Action<EmailAction.Result> implements NodeSetti
|
|||
throw new ActionException("could not parse email action. [addresses] was not found or was empty");
|
||||
}
|
||||
|
||||
return new EmailAction(logger, settings, nodeSettingsService,
|
||||
templateUtils, subjectTemplate, messageTemplate, fromAddress, addresses);
|
||||
return new EmailAction(logger, emailSettingsService, templateUtils, subjectTemplate,
|
||||
messageTemplate, fromAddress, addresses);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -306,66 +283,4 @@ public class EmailAction extends Action<EmailAction.Result> implements NodeSetti
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// This is useful to change all settings at the same time. Otherwise we may change the username then email gets send
|
||||
// and then change the password and then the email sending fails.
|
||||
//
|
||||
// Also this reduces the number of volatile writes
|
||||
private class EmailServiceConfig {
|
||||
|
||||
private String host;
|
||||
private int port;
|
||||
private String username;
|
||||
private String password;
|
||||
|
||||
private String defaultFromAddress;
|
||||
|
||||
private EmailServiceConfig(String host, int port, String userName, String password, String defaultFromAddress) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.username = userName;
|
||||
this.password = password;
|
||||
this.defaultFromAddress = defaultFromAddress;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSettings(Settings settings) {
|
||||
boolean changed = false;
|
||||
String host = emailSettings.host;
|
||||
String newHost = settings.get(SERVER_SETTING);
|
||||
if (newHost != null && !newHost.equals(host)) {
|
||||
host = newHost;
|
||||
changed = true;
|
||||
}
|
||||
int port = emailSettings.port;
|
||||
int newPort = settings.getAsInt(PORT_SETTING, -1);
|
||||
if (newPort != -1) {
|
||||
port = newPort;
|
||||
changed = true;
|
||||
}
|
||||
String fromAddress = emailSettings.defaultFromAddress;
|
||||
String newFromAddress = settings.get(FROM_SETTING);
|
||||
if (newFromAddress != null && !newFromAddress.equals(fromAddress)) {
|
||||
fromAddress = newFromAddress;
|
||||
changed = true;
|
||||
}
|
||||
String userName = emailSettings.username;
|
||||
String newUserName = settings.get(USERNAME_SETTING);
|
||||
if (newUserName != null && !newUserName.equals(userName)) {
|
||||
userName = newFromAddress;
|
||||
changed = true;
|
||||
}
|
||||
String password = emailSettings.password;
|
||||
String newPassword = settings.get(PASSWORD_SETTING);
|
||||
if (newPassword != null && !newPassword.equals(password)) {
|
||||
password = newPassword;
|
||||
changed = true;
|
||||
}
|
||||
if (changed) {
|
||||
emailSettings = new EmailServiceConfig(host, port, fromAddress, userName, password);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.alerts.actions.email;
|
||||
|
||||
import org.elasticsearch.cluster.settings.DynamicSettings;
|
||||
import org.elasticsearch.cluster.settings.Validator;
|
||||
import org.elasticsearch.common.component.AbstractComponent;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.node.settings.NodeSettingsService;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class EmailSettingsService extends AbstractComponent implements NodeSettingsService.Listener {
|
||||
|
||||
static final String PORT_SETTING = "alerts.action.email.server.port";
|
||||
static final String SERVER_SETTING = "alerts.action.email.server.name";
|
||||
static final String FROM_SETTING = "alerts.action.email.from.address";
|
||||
static final String USERNAME_SETTING = "alerts.action.email.from.username";
|
||||
static final String PASSWORD_SETTING = "alerts.action.email.from.password";
|
||||
|
||||
private static final String DEFAULT_SERVER = "smtp.gmail.com";
|
||||
private static final int DEFAULT_PORT = 578;
|
||||
|
||||
private volatile EmailServiceConfig emailServiceConfig = new EmailServiceConfig(DEFAULT_SERVER, DEFAULT_PORT, null, null, null);
|
||||
|
||||
@Inject
|
||||
public EmailSettingsService(Settings settings, DynamicSettings dynamicSettings, NodeSettingsService nodeSettingsService) {
|
||||
super(settings);
|
||||
//TODO Add validators for hosts and email addresses
|
||||
dynamicSettings.addDynamicSetting(PORT_SETTING, Validator.POSITIVE_INTEGER);
|
||||
dynamicSettings.addDynamicSetting(SERVER_SETTING);
|
||||
dynamicSettings.addDynamicSetting(FROM_SETTING);
|
||||
dynamicSettings.addDynamicSetting(USERNAME_SETTING);
|
||||
dynamicSettings.addDynamicSetting(PASSWORD_SETTING);
|
||||
|
||||
nodeSettingsService.addListener(this);
|
||||
|
||||
updateSettings(settings);
|
||||
|
||||
}
|
||||
|
||||
public EmailServiceConfig emailServiceConfig() {
|
||||
return emailServiceConfig;
|
||||
}
|
||||
|
||||
// This is useful to change all settings at the same time. Otherwise we may change the username then email gets send
|
||||
// and then change the password and then the email sending fails.
|
||||
//
|
||||
// Also this reduces the number of volatile writes
|
||||
static class EmailServiceConfig {
|
||||
|
||||
private String host;
|
||||
private int port;
|
||||
private String username;
|
||||
private String password;
|
||||
private String defaultFromAddress;
|
||||
|
||||
public String host() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public int port() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public String username() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public String password() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public String defaultFromAddress() {
|
||||
return defaultFromAddress;
|
||||
}
|
||||
|
||||
private EmailServiceConfig(String host, int port, String userName, String password, String defaultFromAddress) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.username = userName;
|
||||
this.password = password;
|
||||
this.defaultFromAddress = defaultFromAddress;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefreshSettings(Settings settings) {
|
||||
updateSettings(settings);
|
||||
}
|
||||
|
||||
private void updateSettings(Settings settings) {
|
||||
boolean changed = false;
|
||||
String host = emailServiceConfig.host;
|
||||
String newHost = settings.get(SERVER_SETTING);
|
||||
if (newHost != null && !newHost.equals(host)) {
|
||||
logger.info("host changed from [{}] to [{}]", host, newHost);
|
||||
host = newHost;
|
||||
changed = true;
|
||||
}
|
||||
int port = emailServiceConfig.port;
|
||||
int newPort = settings.getAsInt(PORT_SETTING, -1);
|
||||
if (newPort != -1) {
|
||||
logger.info("port changed from [{}] to [{}]", port, newPort);
|
||||
port = newPort;
|
||||
changed = true;
|
||||
}
|
||||
String fromAddress = emailServiceConfig.defaultFromAddress;
|
||||
String newFromAddress = settings.get(FROM_SETTING);
|
||||
if (newFromAddress != null && !newFromAddress.equals(fromAddress)) {
|
||||
logger.info("from changed from [{}] to [{}]", fromAddress, newFromAddress);
|
||||
fromAddress = newFromAddress;
|
||||
changed = true;
|
||||
}
|
||||
String userName = emailServiceConfig.username;
|
||||
String newUserName = settings.get(USERNAME_SETTING);
|
||||
if (newUserName != null && !newUserName.equals(userName)) {
|
||||
logger.info("username changed from [{}] to [{}]", userName, newUserName);
|
||||
userName = newFromAddress;
|
||||
changed = true;
|
||||
}
|
||||
String password = emailServiceConfig.password;
|
||||
String newPassword = settings.get(PASSWORD_SETTING);
|
||||
if (newPassword != null && !newPassword.equals(password)) {
|
||||
logger.info("password changed");
|
||||
password = newPassword;
|
||||
changed = true;
|
||||
}
|
||||
if (changed) {
|
||||
logger.info("one or more settings have changed, updating the email service config");
|
||||
emailServiceConfig = new EmailServiceConfig(host, port, fromAddress, userName, password);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue