mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-03-02 00:49:11 +00:00
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;
|
package org.elasticsearch.alerts.actions;
|
||||||
|
|
||||||
import org.elasticsearch.alerts.actions.email.EmailAction;
|
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.index.IndexAction;
|
||||||
import org.elasticsearch.alerts.actions.webhook.HttpClient;
|
import org.elasticsearch.alerts.actions.webhook.HttpClient;
|
||||||
import org.elasticsearch.alerts.actions.webhook.WebhookAction;
|
import org.elasticsearch.alerts.actions.webhook.WebhookAction;
|
||||||
@ -46,6 +47,7 @@ public class ActionModule extends AbstractModule {
|
|||||||
|
|
||||||
bind(ActionRegistry.class).asEagerSingleton();
|
bind(ActionRegistry.class).asEagerSingleton();
|
||||||
bind(HttpClient.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.Action;
|
||||||
import org.elasticsearch.alerts.actions.ActionException;
|
import org.elasticsearch.alerts.actions.ActionException;
|
||||||
import org.elasticsearch.alerts.support.StringTemplateUtils;
|
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.ParseField;
|
||||||
import org.elasticsearch.common.component.AbstractComponent;
|
import org.elasticsearch.common.component.AbstractComponent;
|
||||||
import org.elasticsearch.common.inject.Inject;
|
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.settings.Settings;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.elasticsearch.common.xcontent.XContentParser;
|
import org.elasticsearch.common.xcontent.XContentParser;
|
||||||
import org.elasticsearch.node.settings.NodeSettingsService;
|
|
||||||
import org.elasticsearch.script.ScriptService;
|
import org.elasticsearch.script.ScriptService;
|
||||||
|
|
||||||
import javax.mail.*;
|
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";
|
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;
|
private final List<Address> emailAddresses;
|
||||||
|
|
||||||
//Optional, can be null, will use defaults from emailSettings (EmailServiceConfig)
|
//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 subjectTemplate;
|
||||||
private final StringTemplateUtils.Template messageTemplate;
|
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(
|
private static final StringTemplateUtils.Template DEFAULT_SUBJECT_TEMPLATE = new StringTemplateUtils.Template(
|
||||||
"Elasticsearch Alert {{alert_name}} triggered", null, "mustache", ScriptService.ScriptType.INLINE);
|
"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 final StringTemplateUtils templateUtils;
|
||||||
private volatile EmailServiceConfig emailSettings = new EmailServiceConfig(DEFAULT_SERVER, DEFAULT_PORT, null, null, null);
|
private final EmailSettingsService emailSettingsService;
|
||||||
|
|
||||||
|
protected EmailAction(ESLogger logger, EmailSettingsService emailSettingsService,
|
||||||
protected EmailAction(ESLogger logger, Settings settings, NodeSettingsService nodeSettingsService,
|
|
||||||
StringTemplateUtils templateUtils, @Nullable StringTemplateUtils.Template subjectTemplate,
|
StringTemplateUtils templateUtils, @Nullable StringTemplateUtils.Template subjectTemplate,
|
||||||
@Nullable StringTemplateUtils.Template messageTemplate, @Nullable String fromAddress,
|
@Nullable StringTemplateUtils.Template messageTemplate, @Nullable String fromAddress,
|
||||||
List<Address> emailAddresses) {
|
List<Address> emailAddresses) {
|
||||||
super(logger);
|
super(logger);
|
||||||
|
|
||||||
this.templateUtils = templateUtils;
|
this.templateUtils = templateUtils;
|
||||||
|
this.emailSettingsService = emailSettingsService;
|
||||||
|
|
||||||
this.emailAddresses = new ArrayList<>();
|
this.emailAddresses = new ArrayList<>();
|
||||||
this.emailAddresses.addAll(emailAddresses);
|
this.emailAddresses.addAll(emailAddresses);
|
||||||
this.subjectTemplate = subjectTemplate;
|
this.subjectTemplate = subjectTemplate;
|
||||||
this.messageTemplate = messageTemplate;
|
this.messageTemplate = messageTemplate;
|
||||||
this.fromAddress = fromAddress;
|
this.fromAddress = fromAddress;
|
||||||
|
|
||||||
nodeSettingsService.addListener(this);
|
|
||||||
updateSettings(settings);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -87,19 +73,21 @@ public class EmailAction extends Action<EmailAction.Result> implements NodeSetti
|
|||||||
@Override
|
@Override
|
||||||
public Result execute(Alert alert, Map<String, Object> data) throws IOException {
|
public Result execute(Alert alert, Map<String, Object> data) throws IOException {
|
||||||
|
|
||||||
|
final EmailSettingsService.EmailServiceConfig emailSettings = emailSettingsService.emailServiceConfig();
|
||||||
|
|
||||||
Properties props = new Properties();
|
Properties props = new Properties();
|
||||||
props.put("mail.smtp.auth", "true");
|
props.put("mail.smtp.auth", "true");
|
||||||
props.put("mail.smtp.starttls.enable", "true");
|
props.put("mail.smtp.starttls.enable", "true");
|
||||||
props.put("mail.smtp.host", emailSettings.host);
|
props.put("mail.smtp.host", emailSettings.host());
|
||||||
props.put("mail.smtp.port", emailSettings.port);
|
props.put("mail.smtp.port", emailSettings.port());
|
||||||
final Session session;
|
final Session session;
|
||||||
|
|
||||||
if (emailSettings.password != null) {
|
if (emailSettings.password() != null) {
|
||||||
final String username;
|
final String username;
|
||||||
if (emailSettings.username != null) {
|
if (emailSettings.username() != null) {
|
||||||
username = emailSettings.username;
|
username = emailSettings.username();
|
||||||
} else {
|
} else {
|
||||||
username = emailSettings.defaultFromAddress;
|
username = emailSettings.defaultFromAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (username == null) {
|
if (username == null) {
|
||||||
@ -109,7 +97,7 @@ public class EmailAction extends Action<EmailAction.Result> implements NodeSetti
|
|||||||
session = Session.getInstance(props,
|
session = Session.getInstance(props,
|
||||||
new javax.mail.Authenticator() {
|
new javax.mail.Authenticator() {
|
||||||
protected PasswordAuthentication getPasswordAuthentication() {
|
protected PasswordAuthentication getPasswordAuthentication() {
|
||||||
return new PasswordAuthentication(username, emailSettings.password);
|
return new PasswordAuthentication(username, emailSettings.password());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@ -119,7 +107,7 @@ public class EmailAction extends Action<EmailAction.Result> implements NodeSetti
|
|||||||
try {
|
try {
|
||||||
Message email = new MimeMessage(session);
|
Message email = new MimeMessage(session);
|
||||||
|
|
||||||
String fromAddressToUse = emailSettings.defaultFromAddress;
|
String fromAddressToUse = emailSettings.defaultFromAddress();
|
||||||
if (fromAddress != null) {
|
if (fromAddress != null) {
|
||||||
fromAddressToUse = fromAddress;
|
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 class Parser extends AbstractComponent implements Action.Parser<EmailAction> {
|
||||||
|
|
||||||
public static final ParseField FROM_FIELD = new ParseField("from");
|
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 MESSAGE_TEMPLATE_FIELD = new ParseField("message_template");
|
||||||
public static final ParseField SUBJECT_TEMPLATE_FIELD = new ParseField("subject_template");
|
public static final ParseField SUBJECT_TEMPLATE_FIELD = new ParseField("subject_template");
|
||||||
|
|
||||||
private final NodeSettingsService nodeSettingsService;
|
|
||||||
private final StringTemplateUtils templateUtils;
|
private final StringTemplateUtils templateUtils;
|
||||||
|
private final EmailSettingsService emailSettingsService;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public Parser(Settings settings, DynamicSettings dynamicSettings, NodeSettingsService nodeSettingsService, StringTemplateUtils templateUtils) {
|
public Parser(Settings settings, EmailSettingsService emailSettingsService, StringTemplateUtils templateUtils) {
|
||||||
super(settings);
|
super(settings);
|
||||||
this.nodeSettingsService = nodeSettingsService;
|
|
||||||
this.templateUtils = templateUtils;
|
this.templateUtils = templateUtils;
|
||||||
|
this.emailSettingsService = emailSettingsService;
|
||||||
dynamicSettings.addDynamicSetting(PORT_SETTING, Validator.POSITIVE_INTEGER);
|
|
||||||
dynamicSettings.addDynamicSetting(SERVER_SETTING);
|
|
||||||
dynamicSettings.addDynamicSetting(FROM_SETTING);
|
|
||||||
dynamicSettings.addDynamicSetting(USERNAME_SETTING);
|
|
||||||
dynamicSettings.addDynamicSetting(PASSWORD_SETTING);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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");
|
throw new ActionException("could not parse email action. [addresses] was not found or was empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
return new EmailAction(logger, settings, nodeSettingsService,
|
return new EmailAction(logger, emailSettingsService, templateUtils, subjectTemplate,
|
||||||
templateUtils, subjectTemplate, messageTemplate, fromAddress, addresses);
|
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…
x
Reference in New Issue
Block a user