Build: Use environment variables for credentials (elastic/x-pack-elasticsearch#4058)

The credentials now get injected via environment variables, so that
external services can pull those.

As soon as the specified environment variables are set, the tests are run. No need to check for the @Network annotation

This also introduces new secret store settings for the secure settings in order to be sure to not leak them in the configuration files, that get dumped.

Relates elastic/x-pack-elasticsearch#3800

Original commit: elastic/x-pack-elasticsearch@a2cfb9cb86
This commit is contained in:
Alexander Reelsen 2018-03-26 09:10:04 +02:00 committed by GitHub
parent e66072c09f
commit 6eeacf339c
22 changed files with 214 additions and 176 deletions

View File

@ -165,6 +165,10 @@ If you configure multiple HipChat accounts, you either need to set a default
HipChat account or specify which account the notification should be sent with HipChat account or specify which account the notification should be sent with
in the <<actions-hipchat, hipchat>> action. in the <<actions-hipchat, hipchat>> action.
deprecated[Storing the `auth_token` in the configuration file or using via updating the
settings now is deprecated, as you should use the keystore for this, see
<<secure-settings,secure settings>>]
[source,yaml] [source,yaml]
-------------------------------------------------- --------------------------------------------------
xpack.notification.hipchat: xpack.notification.hipchat:
@ -222,13 +226,17 @@ To configure a HipChat account that uses the `integration` profile:
For example, the following snippet configures an account called For example, the following snippet configures an account called
`notify-monitoring` that sends messages to the `monitoring` room: `notify-monitoring` that sends messages to the `monitoring` room:
[source,shell]
--------------------------------------------------
bin/elasticsearch-keystore add xpack.notification.hipchat.account.notify-monitoring.secure_auth_token
--------------------------------------------------
[source,yaml] [source,yaml]
-------------------------------------------------- --------------------------------------------------
xpack.notification.hipchat: xpack.notification.hipchat:
account: account:
notify-monitoring: notify-monitoring:
profile: integration profile: integration
auth_token: 3eLB803Nyp7UBmegJwP1rMdUmzk5HqnzJCgflrhv
room: monitoring room: monitoring
-------------------------------------------------- --------------------------------------------------
@ -241,7 +249,6 @@ xpack.notification.hipchat:
account: account:
notify-monitoring: notify-monitoring:
profile: integration profile: integration
auth_token: 3eLB803Nyp7UBmegJwP1rMdUmzk5HqnzJCgflrhv
room: monitoring room: monitoring
message: message:
format: text format: text
@ -285,25 +292,33 @@ To configure a HipChat account that uses the `user` profile:
For example, the following configuration creates an account called For example, the following configuration creates an account called
`notify-monitoring` that sends messages to the `monitoring` room: `notify-monitoring` that sends messages to the `monitoring` room:
[source,shell]
--------------------------------------------------
bin/elasticsearch-keystore add xpack.notification.hipchat.account.notify-monitoring.secure_auth_token
--------------------------------------------------
[source,yaml] [source,yaml]
-------------------------------------------------- --------------------------------------------------
xpack.notification.hipchat: xpack.notification.hipchat:
account: account:
notify-monitoring: notify-monitoring:
profile: user profile: user
auth_token: 3eLB803Nyp7UBmegJwP1rMdUmzk5HqnzJCgflrhv
-------------------------------------------------- --------------------------------------------------
You can also specify defaults for the <{ref}/notification-settings.html#hipchat-account-attributes[ You can also specify defaults for the <{ref}/notification-settings.html#hipchat-account-attributes[
message attributes]: message attributes]:
[source,shell]
--------------------------------------------------
bin/elasticsearch-keystore add xpack.notification.hipchat.account.notify-monitoring.secure_auth_token
--------------------------------------------------
[source,yaml] [source,yaml]
-------------------------------------------------- --------------------------------------------------
xpack.notification.hipchat: xpack.notification.hipchat:
account: account:
notify-monitoring: notify-monitoring:
profile: user profile: user
auth_token: 3eLB803Nyp7UBmegJwP1rMdUmzk5HqnzJCgflrhv
message: message:
format: text format: text
color: blue color: blue
@ -349,13 +364,17 @@ To configure a HipChat account that uses the `v1` profile:
For example, the following configuration creates an account called For example, the following configuration creates an account called
`notify-monitoring`: `notify-monitoring`:
[source,shell]
--------------------------------------------------
bin/elasticsearch-keystore add xpack.notification.hipchat.account.notify-monitoring.secure_auth_token
--------------------------------------------------
[source,yaml] [source,yaml]
-------------------------------------------------- --------------------------------------------------
xpack.notification.hipchat: xpack.notification.hipchat:
account: account:
notify-monitoring: notify-monitoring:
profile: v1 profile: v1
auth_token: 3eLB803Nyp7UBmegJwP1rMdUmzk5HqnzJCgflrhv
-------------------------------------------------- --------------------------------------------------
You can also specify defaults for the {ref}/notification-settings.html#hipchat-account-attributes[ You can also specify defaults for the {ref}/notification-settings.html#hipchat-account-attributes[
@ -367,7 +386,6 @@ xpack.notification.hipchat:
account: account:
notify-monitoring: notify-monitoring:
profile: v1 profile: v1
auth_token: 3eLB803Nyp7UBmegJwP1rMdUmzk5HqnzJCgflrhv
message: message:
format: text format: text
color: blue color: blue

View File

@ -106,22 +106,22 @@ You configure the accounts {watcher} can use to communicate with Jira in the
`xpack.notification.jira` namespace in `elasticsearch.yml`. `xpack.notification.jira` namespace in `elasticsearch.yml`.
{watcher} supports Basic Authentication for Jira Software. To configure a {watcher} supports Basic Authentication for Jira Software. To configure a
Jira account you need to specify: Jira account you need to specify (see <<secure-settings,secure settings>>):
[source,yaml] [source,yaml]
-------------------------------------------------- --------------------------------------------------
xpack.notification.jira: bin/elasticsearch-keystore xpack.notification.jira.account.monitoring.secure_url
account: bin/elasticsearch-keystore xpack.notification.jira.account.monitoring.secure_user
monitoring: bin/elasticsearch-keystore xpack.notification.jira.account.monitoring.secure_password
url: https://internal-jira.elastic.co:443
user: B0A6D1PRD
password: mslNSCnJR
-------------------------------------------------- --------------------------------------------------
deprecated[The insecure way of storing sensitive data (`url`, `user` and `password`)
in the configuration file or the cluster settings is deprecated]
To avoid credentials that transit in clear text over the network, {watcher} will To avoid credentials that transit in clear text over the network, {watcher} will
reject `url` settings like `http://internal-jira.elastic.co` that are based on reject `url` settings like `http://internal-jira.elastic.co` that are based on
plain text HTTP protocol. This default behavior can be disabled with the explicit plain text HTTP protocol. This default behavior can be disabled with the explicit
`allow_http setting`: `allow_http` setting:
NOTE: The `url` field can also contain a path, that is used to create an issue. By NOTE: The `url` field can also contain a path, that is used to create an issue. By
default this is `/rest/api/2/issue`. If you set this as well, make sure that this default this is `/rest/api/2/issue`. If you set this as well, make sure that this
@ -132,10 +132,7 @@ path is the full path to the endpoint to create an issue.
xpack.notification.jira: xpack.notification.jira:
account: account:
monitoring: monitoring:
url: http://unsecure-jira.elastic.co/
allow_http: true allow_http: true
user: B0A6D1PRD
password: mslNSCnJR
-------------------------------------------------- --------------------------------------------------
WARNING: It is strongly advised to use Basic Authentication with secured HTTPS WARNING: It is strongly advised to use Basic Authentication with secured HTTPS
@ -149,9 +146,6 @@ You can also specify defaults for the
xpack.notification.jira: xpack.notification.jira:
account: account:
monitoring: monitoring:
url: https://internal-jira.elastic.co:443
user: B0A6D1PRD
password: mslNSCnJR
issue_defaults: issue_defaults:
project: project:
key: proj key: proj

View File

@ -145,17 +145,17 @@ image::images/pagerduty-services.jpg[]
+ +
image::images/pagerduty-integrations.jpg[] image::images/pagerduty-integrations.jpg[]
To configure a PagerDuty account in `elasticsearch.yml`, at a minimum you To configure a PagerDuty account in the keystore, you
must specify an account name and integration key: must specify an account name and integration key, (see <<secure-settings,secure settings>>):
[source,yaml] [source,yaml]
-------------------------------------------------- --------------------------------------------------
xpack.notification.pagerduty: bin/elasticsearch-keystore add xpack.notification.pagerduty.account.my_pagerduty_account.secure_service_api_key
account:
my_pagerduty_account:
service_api_key: d3b07384d113edec49eaa6238ad5ff0
-------------------------------------------------- --------------------------------------------------
deprecated[Storing the service api key in the YAML file or via cluster
update settings is still supported, but the keystore setting should be used]
You can also specify defaults for the <<pagerduty-event-trigger-incident-attributes, You can also specify defaults for the <<pagerduty-event-trigger-incident-attributes,
PagerDuty event attributes>>: PagerDuty event attributes>>:
. .
@ -165,7 +165,6 @@ PagerDuty event attributes>>:
xpack.notification.pagerduty: xpack.notification.pagerduty:
account: account:
my_pagerduty_account: my_pagerduty_account:
service_api_key: d3b07384d113edec49eaa6238ad5ff0
event_defaults: event_defaults:
description: "Watch notification" description: "Watch notification"
incident_key: "my_incident_key" incident_key: "my_incident_key"

View File

@ -193,16 +193,16 @@ image::images/slack-add-webhook-integration.jpg[]
image::images/slack-copy-webhook-url.jpg[] image::images/slack-copy-webhook-url.jpg[]
To configure a Slack account, at a minimum you need to specify the account To configure a Slack account, at a minimum you need to specify the account
name and webhook URL: name and webhook URL in the elasticsearch keystore (<<secure-settings,secure settings>>):
[source,yaml] [source,shell]
-------------------------------------------------- --------------------------------------------------
xpack.notification.slack: bin/elasticsearch-keystore add xpack.notification.slack.account.monitoring.secure_url
account:
monitoring:
url: https://hooks.slack.com/services/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
-------------------------------------------------- --------------------------------------------------
deprecated[You can also configure this via settings in the `elasticsearch.yml` file,
using the keystore is the preferred and secure way of doign this]
You can also specify defaults for the {ref}/notification-settings.html#slack-account-attributes[Slack You can also specify defaults for the {ref}/notification-settings.html#slack-account-attributes[Slack
notification attributes]: notification attributes]:
@ -211,7 +211,6 @@ notification attributes]:
xpack.notification.slack: xpack.notification.slack:
account: account:
monitoring: monitoring:
url: https://hooks.slack.com/services/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
message_defaults: message_defaults:
from: x-pack from: x-pack
to: notifications to: notifications

View File

@ -7,6 +7,9 @@ package org.elasticsearch.xpack.watcher.notification.hipchat;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.elasticsearch.common.Nullable; import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.settings.SecureSetting;
import org.elasticsearch.common.settings.SecureString;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.settings.SettingsException; import org.elasticsearch.common.settings.SettingsException;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
@ -29,6 +32,8 @@ public abstract class HipChatAccount {
public static final String DEFAULT_COLOR_SETTING = "message_defaults." + HipChatMessage.Field.COLOR.getPreferredName(); public static final String DEFAULT_COLOR_SETTING = "message_defaults." + HipChatMessage.Field.COLOR.getPreferredName();
public static final String DEFAULT_NOTIFY_SETTING = "message_defaults." + HipChatMessage.Field.NOTIFY.getPreferredName(); public static final String DEFAULT_NOTIFY_SETTING = "message_defaults." + HipChatMessage.Field.NOTIFY.getPreferredName();
private static final Setting<SecureString> SECURE_AUTH_TOKEN_SETTING = SecureSetting.secureString("secure_" + AUTH_TOKEN_SETTING, null);
protected final Logger logger; protected final Logger logger;
protected final String name; protected final String name;
protected final Profile profile; protected final Profile profile;
@ -42,11 +47,21 @@ public abstract class HipChatAccount {
this.profile = profile; this.profile = profile;
this.server = new HipChatServer(settings, defaultServer); this.server = new HipChatServer(settings, defaultServer);
this.httpClient = httpClient; this.httpClient = httpClient;
this.authToken = settings.get(AUTH_TOKEN_SETTING); this.authToken = getAuthToken(name, settings);
if (this.authToken == null || this.authToken.length() == 0) { this.logger = logger;
}
private static String getAuthToken(String name, Settings settings) {
String authToken = settings.get(AUTH_TOKEN_SETTING);
if (authToken == null || authToken.length() == 0) {
SecureString secureString = SECURE_AUTH_TOKEN_SETTING.get(settings);
if (secureString == null || secureString.length() < 1) {
throw new SettingsException("hipchat account [" + name + "] missing required [" + AUTH_TOKEN_SETTING + "] setting"); throw new SettingsException("hipchat account [" + name + "] missing required [" + AUTH_TOKEN_SETTING + "] setting");
} }
this.logger = logger; authToken = secureString.toString();
}
return authToken;
} }
public abstract String type(); public abstract String type();

View File

@ -6,6 +6,7 @@
package org.elasticsearch.xpack.watcher.notification.hipchat; package org.elasticsearch.xpack.watcher.notification.hipchat;
import org.elasticsearch.common.settings.ClusterSettings; import org.elasticsearch.common.settings.ClusterSettings;
import org.elasticsearch.common.settings.SecureSetting;
import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.settings.SettingsException; import org.elasticsearch.common.settings.SettingsException;
@ -31,7 +32,13 @@ public class HipChatService extends NotificationService<HipChatAccount> {
private static final Setting.AffixSetting<String> SETTING_AUTH_TOKEN = private static final Setting.AffixSetting<String> SETTING_AUTH_TOKEN =
Setting.affixKeySetting("xpack.notification.hipchat.account.", "auth_token", Setting.affixKeySetting("xpack.notification.hipchat.account.", "auth_token",
(key) -> Setting.simpleString(key, Setting.Property.Dynamic, Setting.Property.NodeScope, Setting.Property.Filtered)); (key) -> Setting.simpleString(key, Setting.Property.Dynamic, Setting.Property.NodeScope, Setting.Property.Filtered,
Setting.Property.Deprecated));
private static final Setting.AffixSetting<String> SETTING_AUTH_TOKEN_SECURE =
Setting.affixKeySetting("xpack.notification.hipchat.account.", "secure_auth_token",
(key) -> SecureSetting.simpleString(key, Setting.Property.Dynamic, Setting.Property.NodeScope,
Setting.Property.Filtered));
private static final Setting.AffixSetting<String> SETTING_PROFILE = private static final Setting.AffixSetting<String> SETTING_PROFILE =
Setting.affixKeySetting("xpack.notification.hipchat.account.", "profile", Setting.affixKeySetting("xpack.notification.hipchat.account.", "profile",
@ -66,6 +73,7 @@ public class HipChatService extends NotificationService<HipChatAccount> {
clusterSettings.addSettingsUpdateConsumer(SETTING_DEFAULT_HOST, (s) -> {}); clusterSettings.addSettingsUpdateConsumer(SETTING_DEFAULT_HOST, (s) -> {});
clusterSettings.addSettingsUpdateConsumer(SETTING_DEFAULT_PORT, (s) -> {}); clusterSettings.addSettingsUpdateConsumer(SETTING_DEFAULT_PORT, (s) -> {});
clusterSettings.addAffixUpdateConsumer(SETTING_AUTH_TOKEN, (s, o) -> {}, (s, o) -> {}); clusterSettings.addAffixUpdateConsumer(SETTING_AUTH_TOKEN, (s, o) -> {}, (s, o) -> {});
clusterSettings.addAffixUpdateConsumer(SETTING_AUTH_TOKEN_SECURE, (s, o) -> {}, (s, o) -> {});
clusterSettings.addAffixUpdateConsumer(SETTING_PROFILE, (s, o) -> {}, (s, o) -> {}); clusterSettings.addAffixUpdateConsumer(SETTING_PROFILE, (s, o) -> {}, (s, o) -> {});
clusterSettings.addAffixUpdateConsumer(SETTING_ROOM, (s, o) -> {}, (s, o) -> {}); clusterSettings.addAffixUpdateConsumer(SETTING_ROOM, (s, o) -> {}, (s, o) -> {});
clusterSettings.addAffixUpdateConsumer(SETTING_HOST, (s, o) -> {}, (s, o) -> {}); clusterSettings.addAffixUpdateConsumer(SETTING_HOST, (s, o) -> {}, (s, o) -> {});
@ -91,7 +99,7 @@ public class HipChatService extends NotificationService<HipChatAccount> {
} }
public static List<Setting<?>> getSettings() { public static List<Setting<?>> getSettings() {
return Arrays.asList(SETTING_DEFAULT_ACCOUNT, SETTING_AUTH_TOKEN, SETTING_PROFILE, SETTING_ROOM, SETTING_MESSAGE_DEFAULTS, return Arrays.asList(SETTING_DEFAULT_ACCOUNT, SETTING_AUTH_TOKEN, SETTING_AUTH_TOKEN_SECURE, SETTING_PROFILE, SETTING_ROOM,
SETTING_DEFAULT_HOST, SETTING_DEFAULT_PORT, SETTING_HOST, SETTING_PORT); SETTING_MESSAGE_DEFAULTS, SETTING_DEFAULT_HOST, SETTING_DEFAULT_PORT, SETTING_HOST, SETTING_PORT);
} }
} }

View File

@ -8,6 +8,10 @@ package org.elasticsearch.xpack.watcher.notification.jira;
import org.elasticsearch.common.Booleans; import org.elasticsearch.common.Booleans;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.logging.ESLoggerFactory;
import org.elasticsearch.common.settings.SecureSetting;
import org.elasticsearch.common.settings.SecureString;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.settings.SettingsException; import org.elasticsearch.common.settings.SettingsException;
import org.elasticsearch.common.xcontent.LoggingDeprecationHandler; import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
@ -45,6 +49,10 @@ public class JiraAccount {
static final String ISSUE_DEFAULTS_SETTING = "issue_defaults"; static final String ISSUE_DEFAULTS_SETTING = "issue_defaults";
static final String ALLOW_HTTP_SETTING = "allow_http"; static final String ALLOW_HTTP_SETTING = "allow_http";
private static final Setting<SecureString> SECURE_USER_SETTING = SecureSetting.secureString("secure_" + USER_SETTING, null);
private static final Setting<SecureString> SECURE_PASSWORD_SETTING = SecureSetting.secureString("secure_" + PASSWORD_SETTING, null);
private static final Setting<SecureString> SECURE_URL_SETTING = SecureSetting.secureString("secure_" + URL_SETTING, null);
private final HttpClient httpClient; private final HttpClient httpClient;
private final String name; private final String name;
private final String user; private final String user;
@ -55,10 +63,8 @@ public class JiraAccount {
public JiraAccount(String name, Settings settings, HttpClient httpClient) { public JiraAccount(String name, Settings settings, HttpClient httpClient) {
this.httpClient = httpClient; this.httpClient = httpClient;
this.name = name; this.name = name;
String url = settings.get(URL_SETTING); String url = getSetting(name, URL_SETTING, settings, SECURE_URL_SETTING);
if (url == null) { ESLoggerFactory.getLogger(getClass()).error("THE URL WAS [{}]", url);
throw requiredSettingException(name, URL_SETTING);
}
try { try {
URI uri = new URI(url); URI uri = new URI(url);
Scheme protocol = Scheme.parse(uri.getScheme()); Scheme protocol = Scheme.parse(uri.getScheme());
@ -69,11 +75,11 @@ public class JiraAccount {
} catch (URISyntaxException | IllegalArgumentException e) { } catch (URISyntaxException | IllegalArgumentException e) {
throw new SettingsException("invalid jira [" + name + "] account settings. invalid [" + URL_SETTING + "] setting", e); throw new SettingsException("invalid jira [" + name + "] account settings. invalid [" + URL_SETTING + "] setting", e);
} }
this.user = settings.get(USER_SETTING); this.user = getSetting(name, USER_SETTING, settings, SECURE_USER_SETTING);
if (Strings.isEmpty(this.user)) { if (Strings.isEmpty(this.user)) {
throw requiredSettingException(name, USER_SETTING); throw requiredSettingException(name, USER_SETTING);
} }
this.password = settings.get(PASSWORD_SETTING); this.password = getSetting(name, PASSWORD_SETTING, settings, SECURE_PASSWORD_SETTING);
if (Strings.isEmpty(this.password)) { if (Strings.isEmpty(this.password)) {
throw requiredSettingException(name, PASSWORD_SETTING); throw requiredSettingException(name, PASSWORD_SETTING);
} }
@ -91,6 +97,19 @@ public class JiraAccount {
} }
} }
private static String getSetting(String accountName, String settingName, Settings settings, Setting<SecureString> secureSetting) {
String value = settings.get(settingName);
if (value == null) {
SecureString secureString = secureSetting.get(settings);
if (secureString == null || secureString.length() < 1) {
throw requiredSettingException(accountName, settingName);
}
value = secureString.toString();
}
return value;
}
public String getName() { public String getName() {
return name; return name;
} }

View File

@ -31,7 +31,7 @@ public class JiraService extends NotificationService<JiraAccount> {
private static final Setting.AffixSetting<String> SETTING_URL = private static final Setting.AffixSetting<String> SETTING_URL =
Setting.affixKeySetting("xpack.notification.jira.account.", "url", Setting.affixKeySetting("xpack.notification.jira.account.", "url",
(key) -> Setting.simpleString(key, Property.Dynamic, Property.NodeScope)); (key) -> Setting.simpleString(key, Property.Dynamic, Property.NodeScope, Property.Filtered));
private static final Setting.AffixSetting<String> SETTING_USER = private static final Setting.AffixSetting<String> SETTING_USER =
Setting.affixKeySetting("xpack.notification.jira.account.", "user", Setting.affixKeySetting("xpack.notification.jira.account.", "user",
@ -39,6 +39,18 @@ public class JiraService extends NotificationService<JiraAccount> {
private static final Setting.AffixSetting<String> SETTING_PASSWORD = private static final Setting.AffixSetting<String> SETTING_PASSWORD =
Setting.affixKeySetting("xpack.notification.jira.account.", "password", Setting.affixKeySetting("xpack.notification.jira.account.", "password",
(key) -> Setting.simpleString(key, Property.Dynamic, Property.NodeScope, Property.Filtered, Property.Deprecated));
private static final Setting.AffixSetting<String> SETTING_SECURE_USER =
Setting.affixKeySetting("xpack.notification.jira.account.", "secure_user",
(key) -> Setting.simpleString(key, Property.Dynamic, Property.NodeScope, Property.Filtered));
private static final Setting.AffixSetting<String> SETTING_SECURE_URL =
Setting.affixKeySetting("xpack.notification.jira.account.", "secure_url",
(key) -> Setting.simpleString(key, Property.Dynamic, Property.NodeScope, Property.Filtered));
private static final Setting.AffixSetting<String> SETTING_SECURE_PASSWORD =
Setting.affixKeySetting("xpack.notification.jira.account.", "secure_password",
(key) -> Setting.simpleString(key, Property.Dynamic, Property.NodeScope, Property.Filtered)); (key) -> Setting.simpleString(key, Property.Dynamic, Property.NodeScope, Property.Filtered));
private static final Setting.AffixSetting<Settings> SETTING_DEFAULTS = private static final Setting.AffixSetting<Settings> SETTING_DEFAULTS =
@ -57,6 +69,9 @@ public class JiraService extends NotificationService<JiraAccount> {
clusterSettings.addAffixUpdateConsumer(SETTING_URL, (s, o) -> {}, (s, o) -> {}); clusterSettings.addAffixUpdateConsumer(SETTING_URL, (s, o) -> {}, (s, o) -> {});
clusterSettings.addAffixUpdateConsumer(SETTING_USER, (s, o) -> {}, (s, o) -> {}); clusterSettings.addAffixUpdateConsumer(SETTING_USER, (s, o) -> {}, (s, o) -> {});
clusterSettings.addAffixUpdateConsumer(SETTING_PASSWORD, (s, o) -> {}, (s, o) -> {}); clusterSettings.addAffixUpdateConsumer(SETTING_PASSWORD, (s, o) -> {}, (s, o) -> {});
clusterSettings.addAffixUpdateConsumer(SETTING_SECURE_USER, (s, o) -> {}, (s, o) -> {});
clusterSettings.addAffixUpdateConsumer(SETTING_SECURE_URL, (s, o) -> {}, (s, o) -> {});
clusterSettings.addAffixUpdateConsumer(SETTING_SECURE_PASSWORD, (s, o) -> {}, (s, o) -> {});
clusterSettings.addAffixUpdateConsumer(SETTING_DEFAULTS, (s, o) -> {}, (s, o) -> {}); clusterSettings.addAffixUpdateConsumer(SETTING_DEFAULTS, (s, o) -> {}, (s, o) -> {});
// do an initial load // do an initial load
setAccountSetting(settings); setAccountSetting(settings);
@ -68,6 +83,7 @@ public class JiraService extends NotificationService<JiraAccount> {
} }
public static List<Setting<?>> getSettings() { public static List<Setting<?>> getSettings() {
return Arrays.asList(SETTING_ALLOW_HTTP, SETTING_URL, SETTING_USER, SETTING_PASSWORD, SETTING_DEFAULTS, SETTING_DEFAULT_ACCOUNT); return Arrays.asList(SETTING_ALLOW_HTTP, SETTING_URL, SETTING_USER, SETTING_PASSWORD, SETTING_SECURE_USER,
SETTING_SECURE_PASSWORD, SETTING_SECURE_URL, SETTING_DEFAULTS, SETTING_DEFAULT_ACCOUNT);
} }
} }

View File

@ -6,6 +6,9 @@
package org.elasticsearch.xpack.watcher.notification.pagerduty; package org.elasticsearch.xpack.watcher.notification.pagerduty;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.elasticsearch.common.settings.SecureSetting;
import org.elasticsearch.common.settings.SecureString;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.settings.SettingsException; import org.elasticsearch.common.settings.SettingsException;
import org.elasticsearch.xpack.core.watcher.watch.Payload; import org.elasticsearch.xpack.core.watcher.watch.Payload;
@ -17,21 +20,20 @@ import java.io.IOException;
public class PagerDutyAccount { public class PagerDutyAccount {
public static final String SERVICE_KEY_SETTING = "service_api_key"; private static final String SERVICE_KEY_SETTING = "service_api_key";
public static final String TRIGGER_DEFAULTS_SETTING = "event_defaults"; private static final String TRIGGER_DEFAULTS_SETTING = "event_defaults";
private static final Setting<SecureString> SECURE_SERVICE_API_KEY_SETTING =
SecureSetting.secureString("secure_" + SERVICE_KEY_SETTING, null);
final String name; private final String name;
final String serviceKey; private final String serviceKey;
final HttpClient httpClient; private final HttpClient httpClient;
final IncidentEventDefaults eventDefaults; private final IncidentEventDefaults eventDefaults;
final Logger logger; private final Logger logger;
public PagerDutyAccount(String name, Settings accountSettings, Settings serviceSettings, HttpClient httpClient, Logger logger) { PagerDutyAccount(String name, Settings accountSettings, Settings serviceSettings, HttpClient httpClient, Logger logger) {
this.name = name; this.name = name;
this.serviceKey = accountSettings.get(SERVICE_KEY_SETTING, serviceSettings.get(SERVICE_KEY_SETTING, null)); this.serviceKey = getServiceKey(name, accountSettings, serviceSettings);
if (this.serviceKey == null) {
throw new SettingsException("invalid pagerduty account [" + name + "]. missing required [" + SERVICE_KEY_SETTING + "] setting");
}
this.httpClient = httpClient; this.httpClient = httpClient;
this.eventDefaults = new IncidentEventDefaults(accountSettings.getAsSettings(TRIGGER_DEFAULTS_SETTING)); this.eventDefaults = new IncidentEventDefaults(accountSettings.getAsSettings(TRIGGER_DEFAULTS_SETTING));
@ -51,4 +53,18 @@ public class PagerDutyAccount {
HttpResponse response = httpClient.execute(request); HttpResponse response = httpClient.execute(request);
return SentEvent.responded(event, request, response); return SentEvent.responded(event, request, response);
} }
private static String getServiceKey(String name, Settings accountSettings, Settings serviceSettings) {
String serviceKey = accountSettings.get(SERVICE_KEY_SETTING, serviceSettings.get(SERVICE_KEY_SETTING, null));
if (serviceKey == null) {
SecureString secureString = SECURE_SERVICE_API_KEY_SETTING.get(accountSettings);
if (secureString == null || secureString.length() < 1) {
throw new SettingsException("invalid pagerduty account [" + name + "]. missing required [" + SERVICE_KEY_SETTING +
"] setting");
}
serviceKey = secureString.toString();
}
return serviceKey;
}
} }

View File

@ -6,6 +6,7 @@
package org.elasticsearch.xpack.watcher.notification.pagerduty; package org.elasticsearch.xpack.watcher.notification.pagerduty;
import org.elasticsearch.common.settings.ClusterSettings; import org.elasticsearch.common.settings.ClusterSettings;
import org.elasticsearch.common.settings.SecureSetting;
import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Setting.Property; import org.elasticsearch.common.settings.Setting.Property;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
@ -25,7 +26,11 @@ public class PagerDutyService extends NotificationService<PagerDutyAccount> {
private static final Setting.AffixSetting<String> SETTING_SERVICE_API_KEY = private static final Setting.AffixSetting<String> SETTING_SERVICE_API_KEY =
Setting.affixKeySetting("xpack.notification.pagerduty.account.", "service_api_key", Setting.affixKeySetting("xpack.notification.pagerduty.account.", "service_api_key",
(key) -> Setting.simpleString(key, Property.Dynamic, Property.NodeScope, Property.Filtered)); (key) -> Setting.simpleString(key, Property.Dynamic, Property.NodeScope, Property.Filtered, Property.Deprecated));
private static final Setting.AffixSetting<String> SETTING_SECURE_SERVICE_API_KEY =
Setting.affixKeySetting("xpack.notification.pagerduty.account.", "secure_service_api_key",
(key) -> SecureSetting.simpleString(key, Property.Dynamic, Property.NodeScope, Property.Filtered));
private static final Setting.AffixSetting<Settings> SETTING_DEFAULTS = private static final Setting.AffixSetting<Settings> SETTING_DEFAULTS =
Setting.affixKeySetting("xpack.notification.pagerduty.account.", "event_defaults", Setting.affixKeySetting("xpack.notification.pagerduty.account.", "event_defaults",
@ -38,6 +43,7 @@ public class PagerDutyService extends NotificationService<PagerDutyAccount> {
this.httpClient = httpClient; this.httpClient = httpClient;
clusterSettings.addSettingsUpdateConsumer(SETTING_DEFAULT_ACCOUNT, (s) -> {}); clusterSettings.addSettingsUpdateConsumer(SETTING_DEFAULT_ACCOUNT, (s) -> {});
clusterSettings.addAffixUpdateConsumer(SETTING_SERVICE_API_KEY, (s, o) -> {}, (s, o) -> {}); clusterSettings.addAffixUpdateConsumer(SETTING_SERVICE_API_KEY, (s, o) -> {}, (s, o) -> {});
clusterSettings.addAffixUpdateConsumer(SETTING_SECURE_SERVICE_API_KEY, (s, o) -> {}, (s, o) -> {});
clusterSettings.addAffixUpdateConsumer(SETTING_DEFAULTS, (s, o) -> {}, (s, o) -> {}); clusterSettings.addAffixUpdateConsumer(SETTING_DEFAULTS, (s, o) -> {}, (s, o) -> {});
setAccountSetting(settings); setAccountSetting(settings);
} }
@ -48,6 +54,6 @@ public class PagerDutyService extends NotificationService<PagerDutyAccount> {
} }
public static List<Setting<?>> getSettings() { public static List<Setting<?>> getSettings() {
return Arrays.asList(SETTING_SERVICE_API_KEY, SETTING_DEFAULTS, SETTING_DEFAULT_ACCOUNT); return Arrays.asList(SETTING_SERVICE_API_KEY, SETTING_SECURE_SERVICE_API_KEY, SETTING_DEFAULTS, SETTING_DEFAULT_ACCOUNT);
} }
} }

View File

@ -6,6 +6,9 @@
package org.elasticsearch.xpack.watcher.notification.slack; package org.elasticsearch.xpack.watcher.notification.slack;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.elasticsearch.common.settings.SecureSetting;
import org.elasticsearch.common.settings.SecureString;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.settings.SettingsException; import org.elasticsearch.common.settings.SettingsException;
import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.ToXContent;
@ -29,9 +32,12 @@ import java.util.List;
public class SlackAccount { public class SlackAccount {
public static final String URL_SETTING = "url"; public static final String URL_SETTING = "url";
public static final String MESSAGE_DEFAULTS_SETTING = "message_defaults"; public static final String MESSAGE_DEFAULTS_SETTING = "message_defaults";
private static final Setting<SecureString> SECURE_URL_SETTING = SecureSetting.secureString("secure_" + URL_SETTING, null);
final String name; final String name;
final URI url; final URI url;
final HttpClient httpClient; final HttpClient httpClient;
@ -116,6 +122,12 @@ public class SlackAccount {
static URI url(String name, Settings settings, Settings defaultSettings) { static URI url(String name, Settings settings, Settings defaultSettings) {
String url = settings.get(URL_SETTING, defaultSettings.get(URL_SETTING, null)); String url = settings.get(URL_SETTING, defaultSettings.get(URL_SETTING, null));
if (url == null) {
SecureString secureStringUrl = SECURE_URL_SETTING.get(settings);
if (secureStringUrl != null && secureStringUrl.length() > 0) {
url = secureStringUrl.toString();
}
}
if (url == null) { if (url == null) {
throw new SettingsException("invalid slack [" + name + "] account settings. missing required [" + URL_SETTING + "] setting"); throw new SettingsException("invalid slack [" + name + "] account settings. missing required [" + URL_SETTING + "] setting");
} }

View File

@ -6,6 +6,7 @@
package org.elasticsearch.xpack.watcher.notification.slack; package org.elasticsearch.xpack.watcher.notification.slack;
import org.elasticsearch.common.settings.ClusterSettings; import org.elasticsearch.common.settings.ClusterSettings;
import org.elasticsearch.common.settings.SecureSetting;
import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Setting.Property; import org.elasticsearch.common.settings.Setting.Property;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
@ -25,7 +26,11 @@ public class SlackService extends NotificationService<SlackAccount> {
private static final Setting.AffixSetting<String> SETTING_URL = private static final Setting.AffixSetting<String> SETTING_URL =
Setting.affixKeySetting("xpack.notification.slack.account.", "url", Setting.affixKeySetting("xpack.notification.slack.account.", "url",
(key) -> Setting.simpleString(key, Property.Dynamic, Property.NodeScope, Property.Filtered)); (key) -> Setting.simpleString(key, Property.Dynamic, Property.NodeScope, Property.Filtered, Property.Deprecated));
private static final Setting.AffixSetting<String> SETTING_URL_SECURE =
Setting.affixKeySetting("xpack.notification.slack.account.", "secure_url",
(key) -> SecureSetting.simpleString(key, Property.Dynamic, Property.NodeScope, Property.Filtered));
private static final Setting.AffixSetting<Settings> SETTING_DEFAULTS = private static final Setting.AffixSetting<Settings> SETTING_DEFAULTS =
Setting.affixKeySetting("xpack.notification.slack.account.", "message_defaults", Setting.affixKeySetting("xpack.notification.slack.account.", "message_defaults",
@ -39,6 +44,7 @@ public class SlackService extends NotificationService<SlackAccount> {
clusterSettings.addSettingsUpdateConsumer(this::setAccountSetting, getSettings()); clusterSettings.addSettingsUpdateConsumer(this::setAccountSetting, getSettings());
clusterSettings.addSettingsUpdateConsumer(SETTING_DEFAULT_ACCOUNT, (s) -> {}); clusterSettings.addSettingsUpdateConsumer(SETTING_DEFAULT_ACCOUNT, (s) -> {});
clusterSettings.addAffixUpdateConsumer(SETTING_URL, (s, o) -> {}, (s, o) -> {}); clusterSettings.addAffixUpdateConsumer(SETTING_URL, (s, o) -> {}, (s, o) -> {});
clusterSettings.addAffixUpdateConsumer(SETTING_URL_SECURE, (s, o) -> {}, (s, o) -> {});
clusterSettings.addAffixUpdateConsumer(SETTING_DEFAULTS, (s, o) -> {}, (s, o) -> {}); clusterSettings.addAffixUpdateConsumer(SETTING_DEFAULTS, (s, o) -> {}, (s, o) -> {});
setAccountSetting(settings); setAccountSetting(settings);
} }
@ -49,6 +55,6 @@ public class SlackService extends NotificationService<SlackAccount> {
} }
public static List<Setting<?>> getSettings() { public static List<Setting<?>> getSettings() {
return Arrays.asList(SETTING_URL, SETTING_DEFAULT_ACCOUNT, SETTING_DEFAULTS); return Arrays.asList(SETTING_URL, SETTING_URL_SECURE, SETTING_DEFAULT_ACCOUNT, SETTING_DEFAULTS);
} }
} }

View File

@ -108,25 +108,6 @@ public class ActiveDirectorySessionFactoryTests extends AbstractActiveDirectoryT
} }
} }
@AwaitsFix(bugUrl = "https://github.com/elastic/x-plugins/issues/2849")
public void testTcpReadTimeout() throws Exception {
Settings settings = Settings.builder()
.put(buildAdSettings(AD_LDAP_URL, AD_DOMAIN, false))
.put("group_search.filter", "(objectClass=*)")
.put("ssl.verification_mode", VerificationMode.CERTIFICATE)
.put(SessionFactorySettings.TIMEOUT_TCP_READ_SETTING, "1ms")
.build();
RealmConfig config = new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings),
new ThreadContext(globalSettings));
try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) {
PlainActionFuture<List<String>> groups = new PlainActionFuture<>();
session(sessionFactory, "ironman", SECURED_PASSWORD).groups(groups);
LDAPException expected = expectThrows(LDAPException.class, groups::actionGet);
assertThat(expected.getMessage(), containsString("A client-side timeout was encountered while waiting"));
}
}
public void testAdAuthAvengers() throws Exception { public void testAdAuthAvengers() throws Exception {
RealmConfig config = new RealmConfig("ad-test", buildAdSettings(AD_LDAP_URL, AD_DOMAIN, false), globalSettings, RealmConfig config = new RealmConfig("ad-test", buildAdSettings(AD_LDAP_URL, AD_DOMAIN, false), globalSettings,
TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings));

View File

@ -1,3 +1,5 @@
import org.elasticsearch.gradle.LoggedExec
apply plugin: 'elasticsearch.standalone-rest-test' apply plugin: 'elasticsearch.standalone-rest-test'
apply plugin: 'elasticsearch.rest-test' apply plugin: 'elasticsearch.rest-test'
@ -6,12 +8,9 @@ dependencies {
testCompile project(path: xpackModule('watcher'), configuration: 'runtime') testCompile project(path: xpackModule('watcher'), configuration: 'runtime')
} }
String integrationAccountPropertyName = 'xpack.notification.hipchat.auth_token_integration' String integrationAccount = System.getenv('hipchat_auth_token_integration')
System.setProperty(integrationAccountPropertyName, 'huuS9v7ccuOy3ZBWWWr1vt8Lqu3sQnLUE81nrLZU') String userAccount = System.getenv('hipchat_auth_token_user')
String userAccountPropertyName = 'xpack.notification.hipchat.auth_token_user' String v1Account = System.getenv('hipchat_auth_token_v1')
System.setProperty(userAccountPropertyName, '4UefsFLvKRw01EMN5vo3oyoY6BLiz7IQBQbGug8K')
String v1AccountPropertyName = 'xpack.notification.hipchat.auth_token_v1'
System.setProperty(v1AccountPropertyName, 'a734baf62df618b96dda55b323fc30')
integTestCluster { integTestCluster {
plugin xpackProject('plugin').path plugin xpackProject('plugin').path
@ -20,19 +19,15 @@ integTestCluster {
setting 'xpack.ml.enabled', 'false' setting 'xpack.ml.enabled', 'false'
setting 'xpack.license.self_generated.type', 'trial' setting 'xpack.license.self_generated.type', 'trial'
setting 'logger.org.elasticsearch.xpack.watcher', 'DEBUG' setting 'logger.org.elasticsearch.xpack.watcher', 'DEBUG'
// hipchat
setting 'xpack.notification.hipchat.account.integration_account.profile', 'integration' setting 'xpack.notification.hipchat.account.integration_account.profile', 'integration'
setting 'xpack.notification.hipchat.account.integration_account.room', 'test-watcher' setting 'xpack.notification.hipchat.account.integration_account.room', 'test-watcher'
setting 'xpack.notification.hipchat.account.integration_account.auth_token', System.getProperty(integrationAccountPropertyName)
setting 'xpack.notification.hipchat.account.user_account.profile', 'user' setting 'xpack.notification.hipchat.account.user_account.profile', 'user'
setting 'xpack.notification.hipchat.account.user_account.auth_token', System.getProperty(userAccountPropertyName)
setting 'xpack.notification.hipchat.account.v1_account.profile', 'v1' setting 'xpack.notification.hipchat.account.v1_account.profile', 'v1'
setting 'xpack.notification.hipchat.account.v1_account.auth_token', System.getProperty(v1AccountPropertyName) keystoreSetting 'xpack.notification.hipchat.account.integration_account.secure_auth_token', integrationAccount
keystoreSetting 'xpack.notification.hipchat.account.user_account.secure_auth_token', userAccount
keystoreSetting 'xpack.notification.hipchat.account.v1_account.secure_auth_token', v1Account
} }
if (!System.getProperty(integrationAccountPropertyName) || !System.getProperty(userAccountPropertyName) || if (!integrationAccount && !userAccount && !v1Account) {
!System.getProperty(v1AccountPropertyName) || !System.getProperty('tests.network')) {
integTest.enabled = false integTest.enabled = false
} }

View File

@ -7,8 +7,6 @@ package org.elasticsearch.smoketest;
import com.carrotsearch.randomizedtesting.annotations.Name; import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.junit.annotations.Network;
import org.elasticsearch.test.junit.annotations.TestLogging;
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate; import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
import org.elasticsearch.test.rest.yaml.ClientYamlTestResponse; import org.elasticsearch.test.rest.yaml.ClientYamlTestResponse;
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase; import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
@ -26,10 +24,9 @@ import static java.util.Collections.singletonMap;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
/** Runs rest tests against external cluster */ /** Runs rest tests against external cluster */
@Network // Needed to access to an external Jira server public class WatcherHipchatYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
public class SmokeTestWatcherClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
public SmokeTestWatcherClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) { public WatcherHipchatYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) {
super(testCandidate); super(testCandidate);
} }

View File

@ -12,17 +12,12 @@ dependencies {
} }
ext { ext {
jiraUrlPropertyName = 'xpack.notification.jira.url' jiraUrl = System.getenv('jira_url')
jiraUserPropertyName = 'xpack.notification.jira.user' jiraUser = System.getenv('jira_user')
jiraPasswordPropertyName = 'xpack.notification.jira.password' jiraPassword = System.getenv('jira_password')
jiraProjectPropertyName = 'xpack.notification.jira.project' jiraProject = System.getenv('jira_project')
} }
System.setProperty(jiraUrlPropertyName, 'https://elasticsearch.atlassian.net/')
System.setProperty(jiraUserPropertyName, 'xpack-user@elastic.co')
System.setProperty(jiraPasswordPropertyName, 'N9M4ea9rfy')
System.setProperty(jiraProjectPropertyName, 'XWT')
integTestCluster { integTestCluster {
plugin xpackProject('plugin').path plugin xpackProject('plugin').path
setting 'xpack.security.enabled', 'false' setting 'xpack.security.enabled', 'false'
@ -30,25 +25,17 @@ integTestCluster {
setting 'xpack.ml.enabled', 'false' setting 'xpack.ml.enabled', 'false'
setting 'xpack.license.self_generated.type', 'trial' setting 'xpack.license.self_generated.type', 'trial'
setting 'logger.org.elasticsearch.xpack.watcher', 'DEBUG' setting 'logger.org.elasticsearch.xpack.watcher', 'DEBUG'
keystoreSetting 'xpack.notification.jira.account.test.secure_url', jiraUrl
// keystoreSetting 'xpack.notification.jira.account.test.secure_user', jiraUser
// JIRA integration test settings keystoreSetting 'xpack.notification.jira.account.test.secure_password', jiraPassword
// setting 'xpack.notification.jira.account.test.issue_defaults.project.key', jiraProject
// The integration tests use a JIRA account on elasticsearch.atlassian.net. This account setting 'xpack.notification.jira.account.test.issue_defaults.issuetype.name', 'Bug'
// has been created by Edward Sy [edward@elastic.co]. It uses the "XPACK WATCHER TEST" setting 'xpack.notification.jira.account.test.issue_defaults.labels.0', 'integration-tests'
// Jira project available at https://elasticsearch.atlassian.net/projects/XWT/issues/?filter=allopenissues
// and the "xpack-user@elastic.co" username which is also an internal Google Group.
setting 'xpack.notification.jira.account.test.url', System.getProperty(jiraUrlPropertyName)
setting 'xpack.notification.jira.account.test.user', System.getProperty(jiraUserPropertyName)
setting 'xpack.notification.jira.account.test.password', System.getProperty(jiraPasswordPropertyName)
setting 'xpack.notification.jira.account.test.issue_defaults.project.key', System.getProperty(jiraProjectPropertyName)
setting 'xpack.notification.jira.account.test.issue_defaults.labels', ['integration-tests', project.version]
} }
/** Clean up JIRA after tests: delete all created issues **/
task cleanJira(type: DefaultTask) { task cleanJira(type: DefaultTask) {
doLast { doLast {
def issues = jiraIssues(System.getProperty(jiraProjectPropertyName)) List<String> issues = jiraIssues(jiraProject)
assert issues instanceof List assert issues instanceof List
issues.forEach { issues.forEach {
// See https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-deleteIssue // See https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-deleteIssue
@ -59,9 +46,7 @@ task cleanJira(type: DefaultTask) {
} }
// require network access for this one, exit early instead of starting up the cluster if we dont have network // require network access for this one, exit early instead of starting up the cluster if we dont have network
if (!System.getProperty(jiraUrlPropertyName) || !System.getProperty(jiraUserPropertyName) || if (!jiraUrl && !jiraUser && !jiraPassword && !jiraProject) {
!System.getProperty(jiraPasswordPropertyName) || !System.getProperty(jiraProjectPropertyName) ||
!System.getProperty('tests.network')) {
integTest.enabled = false integTest.enabled = false
} else { } else {
integTestRunner.finalizedBy cleanJira integTestRunner.finalizedBy cleanJira
@ -79,9 +64,6 @@ def jiraIssues(projectKey) {
def jiraHttpRequest(String endpoint, String method, int successCode) { def jiraHttpRequest(String endpoint, String method, int successCode) {
HttpsURLConnection connection = null; HttpsURLConnection connection = null;
try { try {
def jiraUser = System.getProperty(jiraUserPropertyName)
def jiraPassword = System.getProperty(jiraPasswordPropertyName)
def jiraUrl = System.getProperty(jiraUrlPropertyName)
byte[] credentials = "${jiraUser}:${jiraPassword}".getBytes(StandardCharsets.UTF_8); byte[] credentials = "${jiraUser}:${jiraPassword}".getBytes(StandardCharsets.UTF_8);
connection = (HttpsURLConnection) new URL("${jiraUrl}/rest/api/2/${endpoint}").openConnection(); connection = (HttpsURLConnection) new URL("${jiraUrl}/rest/api/2/${endpoint}").openConnection();
connection.setRequestProperty("Authorization", "Basic " + Base64.getEncoder().encodeToString(credentials)); connection.setRequestProperty("Authorization", "Basic " + Base64.getEncoder().encodeToString(credentials));

View File

@ -7,8 +7,6 @@ package org.elasticsearch.smoketest;
import com.carrotsearch.randomizedtesting.annotations.Name; import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.junit.annotations.Network;
import org.elasticsearch.test.junit.annotations.TestLogging;
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate; import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
import org.elasticsearch.test.rest.yaml.ClientYamlTestResponse; import org.elasticsearch.test.rest.yaml.ClientYamlTestResponse;
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase; import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
@ -26,10 +24,9 @@ import static java.util.Collections.singletonMap;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
/** Runs rest tests against external cluster */ /** Runs rest tests against external cluster */
@Network // Needed to access to an external Jira server public class WatcherJiraYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
public class SmokeTestWatcherClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
public SmokeTestWatcherClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) { public WatcherJiraYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) {
super(testCandidate); super(testCandidate);
} }

View File

@ -210,7 +210,7 @@
- match: { hits.hits.0._source.result.actions.0.jira.reason: "Bad Request - ThrottlerField [issuetype] has error [issue type is required]\n" } - match: { hits.hits.0._source.result.actions.0.jira.reason: "Bad Request - ThrottlerField [issuetype] has error [issue type is required]\n" }
- match: { hits.hits.0._source.result.actions.0.jira.request.method: "post" } - match: { hits.hits.0._source.result.actions.0.jira.request.method: "post" }
- match: { hits.hits.0._source.result.actions.0.jira.request.path: "/rest/api/2/issue" } - match: { hits.hits.0._source.result.actions.0.jira.request.path: "/rest/api/2/issue" }
- match: { hits.hits.0._source.result.actions.0.jira.request.auth.basic.username: "xpack-user@elastic.co" } - is_true: hits.hits.0._source.result.actions.0.jira.request.auth.basic.username
- match: { hits.hits.0._source.result.actions.0.jira.request.auth.basic.password: "::es_redacted::" } - match: { hits.hits.0._source.result.actions.0.jira.request.auth.basic.password: "::es_redacted::" }
- match: { hits.hits.0._source.result.actions.0.jira.response.body: "{\"errorMessages\":[],\"errors\":{\"issuetype\":\"issue type is required\"}}" } - match: { hits.hits.0._source.result.actions.0.jira.response.body: "{\"errorMessages\":[],\"errors\":{\"issuetype\":\"issue type is required\"}}" }

View File

@ -6,20 +6,7 @@ dependencies {
testCompile project(path: xpackModule('watcher'), configuration: 'runtime') testCompile project(path: xpackModule('watcher'), configuration: 'runtime')
} }
String pagerDutyPropertyName = 'xpack.notification.pagerduty.service_api_key' String pagerDutyServiceKey = System.getenv('pagerduty_service_api_key')
System.setProperty(pagerDutyPropertyName, 'fc082467005d4072a914e0bb041882d0')
ext {
jiraUrl = 'https://elasticsearch.atlassian.net/'
jiraUser = 'xpack-user@elastic.co'
jiraPassword = 'N9M4ea9rfy'
jiraProject = 'XWT'
slackUrl = 'https://hooks.slack.com/services/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'
pagerDutyUrl = 'fc082467005d4072a914e0bb041882d0'
hipchatUserAuthToken = '4UefsFLvKRw01EMN5vo3oyoY6BLiz7IQBQbGug8K'
hipchatIntegrationAuthToken = 'huuS9v7ccuOy3ZBWWWr1vt8Lqu3sQnLUE81nrLZU'
hipchatV1AuthToken = 'a734baf62df618b96dda55b323fc30'
}
integTestCluster { integTestCluster {
plugin xpackProject('plugin').path plugin xpackProject('plugin').path
@ -28,12 +15,9 @@ integTestCluster {
setting 'xpack.ml.enabled', 'false' setting 'xpack.ml.enabled', 'false'
setting 'xpack.license.self_generated.type', 'trial' setting 'xpack.license.self_generated.type', 'trial'
setting 'logger.org.elasticsearch.xpack.watcher', 'DEBUG' setting 'logger.org.elasticsearch.xpack.watcher', 'DEBUG'
keystoreSetting 'xpack.notification.pagerduty.account.test_account.secure_service_api_key', pagerDutyServiceKey
// pagerduty
setting 'xpack.notification.pagerduty.account.test_account.service_api_key', System.getProperty(pagerDutyPropertyName)
} }
// require network access for this one, exit early instead of starting up the cluster if we dont have network if (!pagerDutyServiceKey) {
if (!System.getProperty(pagerDutyPropertyName) || !System.getProperty('tests.network')) {
integTest.enabled = false integTest.enabled = false
} }

View File

@ -7,8 +7,6 @@ package org.elasticsearch.smoketest;
import com.carrotsearch.randomizedtesting.annotations.Name; import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.junit.annotations.Network;
import org.elasticsearch.test.junit.annotations.TestLogging;
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate; import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
import org.elasticsearch.test.rest.yaml.ClientYamlTestResponse; import org.elasticsearch.test.rest.yaml.ClientYamlTestResponse;
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase; import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
@ -26,10 +24,9 @@ import static java.util.Collections.singletonMap;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
/** Runs rest tests against external cluster */ /** Runs rest tests against external cluster */
@Network // Needed to access to an external Jira server public class WatcherPagerDutyYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
public class SmokeTestWatcherClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
public SmokeTestWatcherClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) { public WatcherPagerDutyYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) {
super(testCandidate); super(testCandidate);
} }

View File

@ -1,3 +1,6 @@
import org.elasticsearch.gradle.test.NodeInfo
import org.elasticsearch.gradle.LoggedExec
apply plugin: 'elasticsearch.standalone-rest-test' apply plugin: 'elasticsearch.standalone-rest-test'
apply plugin: 'elasticsearch.rest-test' apply plugin: 'elasticsearch.rest-test'
@ -6,8 +9,7 @@ dependencies {
testCompile project(path: xpackModule('watcher'), configuration: 'runtime') testCompile project(path: xpackModule('watcher'), configuration: 'runtime')
} }
String slackPropertyName = 'xpack.notification.slack.url' String slackUrl = System.getenv('slack_url')
System.setProperty(slackPropertyName, 'https://hooks.slack.com/services/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')
integTestCluster { integTestCluster {
plugin xpackProject('plugin').path plugin xpackProject('plugin').path
@ -16,11 +18,9 @@ integTestCluster {
setting 'xpack.ml.enabled', 'false' setting 'xpack.ml.enabled', 'false'
setting 'xpack.license.self_generated.type', 'trial' setting 'xpack.license.self_generated.type', 'trial'
setting 'logger.org.elasticsearch.xpack.watcher', 'DEBUG' setting 'logger.org.elasticsearch.xpack.watcher', 'DEBUG'
keystoreSetting 'xpack.notification.slack.account.test_account.secure_url', slackUrl
setting 'xpack.notification.slack.account.test_account.url', System.getProperty(slackPropertyName)
} }
// require network access for this one, exit early instead of starting up the cluster if we dont have network if (!slackUrl) {
if (!System.getProperty(slackPropertyName) || !System.getProperty('tests.network')) {
integTest.enabled = false integTest.enabled = false
} }

View File

@ -7,8 +7,6 @@ package org.elasticsearch.smoketest;
import com.carrotsearch.randomizedtesting.annotations.Name; import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.test.junit.annotations.Network;
import org.elasticsearch.test.junit.annotations.TestLogging;
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate; import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
import org.elasticsearch.test.rest.yaml.ClientYamlTestResponse; import org.elasticsearch.test.rest.yaml.ClientYamlTestResponse;
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase; import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
@ -26,10 +24,9 @@ import static java.util.Collections.singletonMap;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
/** Runs rest tests against external cluster */ /** Runs rest tests against external cluster */
@Network // Needed to access to an external Jira server public class WatcherSlackYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
public class SmokeTestWatcherClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
public SmokeTestWatcherClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) { public WatcherSlackYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) {
super(testCandidate); super(testCandidate);
} }