Cleanup: Move tests calling external services into QA projects (elastic/x-pack-elasticsearch#3869)

This also moves the hipchat/pagerduty/slack tests to REST tests which put real watches and also check the history.

Relates elastic/x-pack-elasticsearch#3800


Original commit: elastic/x-pack-elasticsearch@fce08d9cb7
This commit is contained in:
Alexander Reelsen 2018-02-23 13:31:28 +01:00 committed by GitHub
parent 9624788c17
commit 7f166e1927
29 changed files with 1215 additions and 649 deletions

View File

@ -81,33 +81,6 @@ public class LdapSessionFactoryTests extends LdapTestCase {
} }
} }
@Network
@AwaitsFix(bugUrl = "https://github.com/elastic/x-plugins/issues/2849")
public void testConnectTimeout() {
// Local sockets connect too fast...
String ldapUrl = "ldap://54.200.235.244:389";
String groupSearchBase = "o=sevenSeas";
String userTemplates = "cn={0},ou=people,o=sevenSeas";
Settings settings = Settings.builder()
.put(buildLdapSettings(ldapUrl, userTemplates, groupSearchBase, LdapSearchScope.SUB_TREE))
.put(SessionFactorySettings.TIMEOUT_TCP_CONNECTION_SETTING, "1ms") //1 millisecond
.build();
RealmConfig config = new RealmConfig("ldap_realm", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings));
LdapSessionFactory sessionFactory = new LdapSessionFactory(config, sslService, threadPool);
String user = "Horatio Hornblower";
SecureString userPass = new SecureString("pass");
long start = System.currentTimeMillis();
LDAPException expected = expectThrows(LDAPException.class, () -> session(sessionFactory, user, userPass));
long time = System.currentTimeMillis() - start;
assertThat(time, lessThan(10000L));
assertThat(expected, instanceOf(LDAPException.class));
assertThat(expected.getCause().getMessage(),
anyOf(containsString("within the configured timeout of"), containsString("connect timed out")));
}
public void testBindWithTemplates() throws Exception { public void testBindWithTemplates() throws Exception {
String groupSearchBase = "o=sevenSeas"; String groupSearchBase = "o=sevenSeas";
String[] userTemplates = new String[] { String[] userTemplates = new String[] {

View File

@ -403,62 +403,6 @@ public class LdapUserSearchSessionFactoryTests extends LdapTestCase {
} }
} }
@Network
public void testUserSearchWithActiveDirectory() throws Exception {
String groupSearchBase = "DC=ad,DC=test,DC=elasticsearch,DC=com";
String userSearchBase = "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com";
Settings settings = Settings.builder()
.put(LdapTestCase.buildLdapSettings(
new String[] { ActiveDirectorySessionFactoryTests.AD_LDAP_URL },
Strings.EMPTY_ARRAY, groupSearchBase, LdapSearchScope.SUB_TREE, null,
true))
.put("user_search.base_dn", userSearchBase)
.put("bind_dn", "ironman@ad.test.elasticsearch.com")
.put("bind_password", ActiveDirectorySessionFactoryTests.PASSWORD)
.put("user_search.filter", "(cn={0})")
.put("user_search.pool.enabled", randomBoolean())
.build();
Settings.Builder builder = Settings.builder()
.put(globalSettings);
settings.keySet().forEach(k -> {
builder.copy("xpack.security.authc.realms.ldap." + k, k, settings);
});
Settings fullSettings = builder.build();
sslService = new SSLService(fullSettings, TestEnvironment.newEnvironment(fullSettings));
RealmConfig config = new RealmConfig("ad-as-ldap-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings));
LdapUserSearchSessionFactory sessionFactory = getLdapUserSearchSessionFactory(config, sslService, threadPool);
String user = "Bruce Banner";
try {
//auth
try (LdapSession ldap = session(sessionFactory, user, new SecureString(ActiveDirectorySessionFactoryTests.PASSWORD))) {
assertConnectionCanReconnect(ldap.getConnection());
List<String> groups = groups(ldap);
assertThat(groups, containsInAnyOrder(
containsString("Avengers"),
containsString("SHIELD"),
containsString("Geniuses"),
containsString("Philanthropists")));
}
//lookup
try (LdapSession ldap = unauthenticatedSession(sessionFactory, user)) {
assertConnectionCanReconnect(ldap.getConnection());
List<String> groups = groups(ldap);
assertThat(groups, containsInAnyOrder(
containsString("Avengers"),
containsString("SHIELD"),
containsString("Geniuses"),
containsString("Philanthropists")));
}
} finally {
sessionFactory.close();
}
}
public void testConnectionPoolDefaultSettings() throws Exception { public void testConnectionPoolDefaultSettings() throws Exception {
String groupSearchBase = "o=sevenSeas"; String groupSearchBase = "o=sevenSeas";
String userSearchBase = "o=sevenSeas"; String userSearchBase = "o=sevenSeas";
@ -586,7 +530,7 @@ public class LdapUserSearchSessionFactoryTests extends LdapTestCase {
groupSearchBase, LdapSearchScope.SUB_TREE)) groupSearchBase, LdapSearchScope.SUB_TREE))
.put("user_search.base_dn", userSearchBase) .put("user_search.base_dn", userSearchBase)
.put("bind_dn", "ironman@ad.test.elasticsearch.com") .put("bind_dn", "ironman@ad.test.elasticsearch.com")
.put("bind_password", ActiveDirectorySessionFactoryTests.PASSWORD) .put("bind_password", "password")
.put("user_search.attribute", "cn") .put("user_search.attribute", "cn")
.put("timeout.tcp_connect", "500ms") .put("timeout.tcp_connect", "500ms")
.put("type", "ldap") .put("type", "ldap")

View File

@ -1,226 +0,0 @@
/*
* 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.xpack.watcher.test.integration;
import org.elasticsearch.ExceptionsHelper;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.LicenseService;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.script.MockMustacheScriptEngine;
import org.elasticsearch.test.ESSingleNodeTestCase;
import org.elasticsearch.test.junit.annotations.Network;
import org.elasticsearch.test.junit.annotations.TestLogging;
import org.elasticsearch.xpack.core.XPackSettings;
import org.elasticsearch.xpack.core.watcher.WatcherState;
import org.elasticsearch.xpack.core.watcher.client.WatcherClient;
import org.elasticsearch.xpack.core.watcher.history.HistoryStoreField;
import org.elasticsearch.xpack.core.watcher.transport.actions.put.PutWatchResponse;
import org.elasticsearch.xpack.watcher.WatcherService;
import org.elasticsearch.xpack.watcher.actions.hipchat.HipChatAction;
import org.elasticsearch.xpack.watcher.condition.InternalAlwaysCondition;
import org.elasticsearch.xpack.watcher.notification.hipchat.HipChatAccount;
import org.elasticsearch.xpack.watcher.notification.hipchat.HipChatMessage;
import org.elasticsearch.xpack.watcher.notification.hipchat.HipChatService;
import org.elasticsearch.xpack.watcher.notification.hipchat.SentMessages;
import org.elasticsearch.xpack.watcher.test.LocalStateWatcher;
import java.util.Arrays;
import java.util.Collection;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.search.builder.SearchSourceBuilder.searchSource;
import static org.elasticsearch.xpack.watcher.actions.ActionBuilders.hipchatAction;
import static org.elasticsearch.xpack.watcher.client.WatchSourceBuilders.watchBuilder;
import static org.elasticsearch.xpack.watcher.input.InputBuilders.simpleInput;
import static org.elasticsearch.xpack.watcher.trigger.TriggerBuilders.schedule;
import static org.elasticsearch.xpack.watcher.trigger.schedule.Schedules.interval;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.lessThan;
import static org.hamcrest.Matchers.notNullValue;
@Network
@TestLogging("org.elasticsearch.xpack.watcher.common.http:TRACE")
public class HipChatServiceTests extends ESSingleNodeTestCase {
@Override
protected Collection<Class<? extends Plugin>> getPlugins() {
return Arrays.asList(LocalStateWatcher.class, MockMustacheScriptEngine.TestPlugin.class);
}
@Override
protected Settings nodeSettings() {
return Settings.builder()
.put(super.nodeSettings())
.put(XPackSettings.WATCHER_ENABLED.getKey(), true)
.put(LicenseService.SELF_GENERATED_LICENSE_TYPE.getKey(), "trial")
// this is for the `test-watcher-integration` group level integration in HipChat
.put("xpack.notification.hipchat.account.integration_account.profile", "integration")
.put("xpack.notification.hipchat.account.integration_account.auth_token",
"huuS9v7ccuOy3ZBWWWr1vt8Lqu3sQnLUE81nrLZU")
.put("xpack.notification.hipchat.account.integration_account.room", "test-watcher")
// this is for the Watcher Test account in HipChat
.put("xpack.notification.hipchat.account.user_account.profile", "user")
.put("xpack.notification.hipchat.account.user_account.auth_token", "4UefsFLvKRw01EMN5vo3oyoY6BLiz7IQBQbGug8K")
// this is for the `test-watcher-v1` notification token
.put("xpack.notification.hipchat.account.v1_account.profile", "v1")
.put("xpack.notification.hipchat.account.v1_account.auth_token", "a734baf62df618b96dda55b323fc30")
.build();
}
public void testSendMessageV1Account() throws Exception {
HipChatService service = getInstanceFromNode(HipChatService.class);
HipChatMessage hipChatMessage = new HipChatMessage(
"HipChatServiceTests#testSendMessage_V1Account",
new String[] { "test-watcher", "test-watcher-2", "test watcher with spaces" },
null, // users are unsupported in v1
"watcher-tests",
HipChatMessage.Format.TEXT,
randomFrom(HipChatMessage.Color.values()),
true);
HipChatAccount account = service.getAccount("v1_account");
assertThat(account, notNullValue());
SentMessages messages = account.send(hipChatMessage, null);
assertSentMessagesAreValid(3, messages);
}
public void testSendMessageIntegrationAccount() throws Exception {
HipChatService service = getInstanceFromNode(HipChatService.class);
HipChatMessage.Color color = randomFrom(HipChatMessage.Color.values());
HipChatMessage hipChatMessage = new HipChatMessage(
"HipChatServiceTests#testSendMessage_IntegrationAccount colored " + color.value(),
null, // custom rooms are unsupported by integration profiles
null, // users are unsupported by integration profiles
null, // custom "from" is not supported by integration profiles
HipChatMessage.Format.TEXT,
color,
true);
HipChatAccount account = service.getAccount("integration_account");
assertThat(account, notNullValue());
SentMessages messages = account.send(hipChatMessage, null);
assertSentMessagesAreValid(1, messages);
}
public void testSendMessageUserAccount() throws Exception {
HipChatService service = getInstanceFromNode(HipChatService.class);
HipChatMessage.Color color = randomFrom(HipChatMessage.Color.values());
HipChatMessage hipChatMessage = new HipChatMessage(
"HipChatServiceTests#testSendMessage_UserAccount colored " + color.value(),
new String[] { "test-watcher", "test-watcher-2", "test watcher with spaces" },
new String[] { "watcher@elastic.co" },
null,
HipChatMessage.Format.TEXT,
color,
false);
HipChatAccount account = service.getAccount("user_account");
assertThat(account, notNullValue());
SentMessages messages = account.send(hipChatMessage, null);
assertSentMessagesAreValid(4, messages);
}
public void testWatchWithHipChatAction() throws Exception {
assertBusy(() -> assertThat(getInstanceFromNode(WatcherService.class).state(), is(WatcherState.STARTED)));
HipChatAccount.Profile profile = randomFrom(HipChatAccount.Profile.values());
HipChatMessage.Color color = randomFrom(HipChatMessage.Color.values());
String account;
HipChatAction.Builder actionBuilder;
switch (profile) {
case USER:
account = "user_account";
actionBuilder = hipchatAction(account, "_message")
.addRooms("test-watcher", "test-watcher-2", "test watcher with spaces")
.addUsers("watcher@elastic.co")
.setFormat(HipChatMessage.Format.TEXT)
.setColor(color)
.setNotify(false);
break;
case INTEGRATION:
account = "integration_account";
actionBuilder = hipchatAction(account, "_message")
.setFormat(HipChatMessage.Format.TEXT)
.setColor(color)
.setNotify(false);
break;
default:
assertThat(profile, is(HipChatAccount.Profile.V1));
account = "v1_account";
actionBuilder = hipchatAction(account, "_message")
.addRooms("test-watcher", "test-watcher-2", "test watcher with spaces")
.setFrom("watcher-test")
.setFormat(HipChatMessage.Format.TEXT)
.setColor(color)
.setNotify(false);
}
String id = randomAlphaOfLength(10);
WatcherClient watcherClient = new WatcherClient(client());
PutWatchResponse putWatchResponse = watcherClient.preparePutWatch(id).setSource(watchBuilder()
.trigger(schedule(interval("10m")))
.input(simpleInput("ref", "HipChatServiceTests#testWatchWithHipChatAction"))
.condition(InternalAlwaysCondition.INSTANCE)
.addAction("hipchat", actionBuilder))
.execute().get();
assertThat(putWatchResponse.isCreated(), is(true));
watcherClient.prepareExecuteWatch(id).setRecordExecution(true).execute().actionGet();
client().admin().indices().prepareRefresh(HistoryStoreField.INDEX_PREFIX_WITH_TEMPLATE + "*").execute().actionGet();
SearchResponse response = client().prepareSearch(HistoryStoreField.INDEX_PREFIX_WITH_TEMPLATE + "*")
.setSource(searchSource().query(boolQuery()
.must(termQuery("result.actions.id", "hipchat"))
.must(termQuery("result.actions.type", "hipchat"))
.must(termQuery("result.actions.status", "success"))
.must(termQuery("result.actions.hipchat.account", account))
.must(termQuery("result.actions.hipchat.sent_messages.status", "success"))))
.get();
assertThat(response, notNullValue());
assertThat(response.getHits().getTotalHits(), is(1L));
}
public void testDefaultValuesForColorAndFormatWorks() {
HipChatService service = getInstanceFromNode(HipChatService.class);
HipChatMessage hipChatMessage = new HipChatMessage(
"HipChatServiceTests#testSendMessage_UserAccount with default Color and text",
new String[] { "test-watcher", "test-watcher-2", "test watcher with spaces" },
new String[] { "watcher@elastic.co" },
null, // custom "from" is not supported by integration profiles
null,
null,
false);
HipChatAccount account = service.getAccount("user_account");
assertThat(account, notNullValue());
SentMessages messages = account.send(hipChatMessage, null);
assertSentMessagesAreValid(4, messages);
}
private void assertSentMessagesAreValid(int expectedMessageSize, SentMessages messages) {
assertThat(messages.count(), is(expectedMessageSize));
for (SentMessages.SentMessage message : messages) {
logger.info("Request: [{}]", message.getRequest());
logger.info("Response: [{}]", message.getResponse());
if (message.getException() != null) {
logger.info("Exception stacktrace: [{}]", ExceptionsHelper.stackTrace(message.getException()));
}
assertThat(message.isSuccess(), is(true));
assertThat(message.getRequest(), notNullValue());
assertThat(message.getResponse(), notNullValue());
assertThat(message.getResponse().status(), lessThan(300));
}
}
}

View File

@ -1,96 +0,0 @@
/*
* 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.xpack.watcher.test.integration;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.test.junit.annotations.Network;
import org.elasticsearch.xpack.core.watcher.transport.actions.put.PutWatchResponse;
import org.elasticsearch.xpack.core.watcher.watch.Payload;
import org.elasticsearch.xpack.watcher.actions.pagerduty.PagerDutyAction;
import org.elasticsearch.xpack.watcher.condition.InternalAlwaysCondition;
import org.elasticsearch.xpack.watcher.notification.pagerduty.IncidentEvent;
import org.elasticsearch.xpack.watcher.notification.pagerduty.IncidentEventContext;
import org.elasticsearch.xpack.watcher.notification.pagerduty.PagerDutyAccount;
import org.elasticsearch.xpack.watcher.notification.pagerduty.PagerDutyService;
import org.elasticsearch.xpack.watcher.notification.pagerduty.SentEvent;
import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.search.builder.SearchSourceBuilder.searchSource;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount;
import static org.elasticsearch.xpack.watcher.actions.ActionBuilders.pagerDutyAction;
import static org.elasticsearch.xpack.watcher.client.WatchSourceBuilders.watchBuilder;
import static org.elasticsearch.xpack.watcher.input.InputBuilders.simpleInput;
import static org.elasticsearch.xpack.watcher.trigger.TriggerBuilders.schedule;
import static org.elasticsearch.xpack.watcher.trigger.schedule.Schedules.interval;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.lessThan;
import static org.hamcrest.Matchers.notNullValue;
@Network
public class PagerDutyServiceTests extends AbstractWatcherIntegrationTestCase {
@Override
protected Settings nodeSettings(int nodeOrdinal) {
return Settings.builder()
.put(super.nodeSettings(nodeOrdinal))
.put("xpack.notification.pagerduty.account.test_account.service_api_key", "fc082467005d4072a914e0bb041882d0")
.build();
}
public void testSendTriggerEvent() throws Exception {
PagerDutyService service = getInstanceFromMaster(PagerDutyService.class);
IncidentEvent event = new IncidentEvent("#testIncidentEvent()", null, null, "PagerDutyServiceTests", "_client_url", "_account",
true, new IncidentEventContext[] {
IncidentEventContext.link("https://www.elastic.co/products/x-pack/alerting", "Go to the Elastic.co Alerting website"),
IncidentEventContext.image("https://www.elastic.co/assets/blte5d899fd0b0e6808/icon-alerting-bb.svg",
"https://www.elastic.co/products/x-pack/alerting", "X-Pack-Alerting website link with log")
}, null);
Payload payload = new Payload.Simple("_key", "_val");
PagerDutyAccount account = service.getAccount("test_account");
assertThat(account, notNullValue());
SentEvent sentEvent = account.send(event, payload);
assertThat(sentEvent, notNullValue());
assertThat(sentEvent.successful(), is(true));
assertThat(sentEvent.getRequest(), notNullValue());
assertThat(sentEvent.getResponse(), notNullValue());
assertThat(sentEvent.getResponse().status(), lessThan(300));
}
public void testWatchWithPagerDutyAction() throws Exception {
String account = "test_account";
PagerDutyAction.Builder actionBuilder = pagerDutyAction(IncidentEvent
.templateBuilder("pager duty integration test").setAccount(account));
PutWatchResponse putWatchResponse = watcherClient().preparePutWatch("1").setSource(watchBuilder()
.trigger(schedule(interval("10m")))
.input(simpleInput("ref", "testWatchWithPagerDutyAction()"))
.condition(InternalAlwaysCondition.INSTANCE)
.addAction("pd", actionBuilder))
.execute().get();
assertThat(putWatchResponse.isCreated(), is(true));
timeWarp().trigger("1");
flush();
refresh();
assertWatchWithMinimumPerformedActionsCount("1", 1L, false);
SearchResponse response = searchHistory(searchSource().query(boolQuery()
.must(termQuery("result.actions.id", "pd"))
.must(termQuery("result.actions.type", "pagerduty"))
.must(termQuery("result.actions.status", "success"))
.must(termQuery("result.actions.pagerduty.sent_event.event.account", account))));
assertThat(response, notNullValue());
assertHitCount(response, 1L);
}
}

View File

@ -1,136 +0,0 @@
/*
* 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.xpack.watcher.test.integration;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.test.junit.annotations.Network;
import org.elasticsearch.xpack.core.watcher.support.xcontent.XContentSource;
import org.elasticsearch.xpack.core.watcher.transport.actions.put.PutWatchResponse;
import org.elasticsearch.xpack.watcher.actions.slack.SlackAction;
import org.elasticsearch.xpack.watcher.condition.InternalAlwaysCondition;
import org.elasticsearch.xpack.watcher.notification.slack.SentMessages;
import org.elasticsearch.xpack.watcher.notification.slack.SlackAccount;
import org.elasticsearch.xpack.watcher.notification.slack.SlackService;
import org.elasticsearch.xpack.watcher.notification.slack.message.Action;
import org.elasticsearch.xpack.watcher.notification.slack.message.Attachment;
import org.elasticsearch.xpack.watcher.notification.slack.message.SlackMessage;
import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase;
import org.joda.time.DateTime;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import static org.elasticsearch.common.xcontent.ToXContent.EMPTY_PARAMS;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.search.builder.SearchSourceBuilder.searchSource;
import static org.elasticsearch.xpack.watcher.actions.ActionBuilders.slackAction;
import static org.elasticsearch.xpack.watcher.client.WatchSourceBuilders.watchBuilder;
import static org.elasticsearch.xpack.watcher.input.InputBuilders.simpleInput;
import static org.elasticsearch.xpack.watcher.trigger.TriggerBuilders.schedule;
import static org.elasticsearch.xpack.watcher.trigger.schedule.Schedules.interval;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.lessThan;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
@Network
public class SlackServiceTests extends AbstractWatcherIntegrationTestCase {
@Override
protected Settings nodeSettings(int nodeOrdinal) {
return Settings.builder()
.put(super.nodeSettings(nodeOrdinal))
.put("xpack.notification.slack.account.test_account.url",
"https://hooks.slack.com/services/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")
.build();
}
public void testSendMessage() throws Exception {
SlackService service = getInstanceFromMaster(SlackService.class);
// String style, String name, String type, String text, String url
Action action = new Action(randomFrom("primary", "danger"), "action name", "button", "Click here to visit Elastic Homepage",
"https://elastic.co");
List<Action> actions = randomBoolean() ? null : Collections.singletonList(action);
Attachment[] attachments = new Attachment[] {
new Attachment("fallback", randomFrom("good", "warning", "danger"), "pretext `code` *bold*", "author_name", null, null,
"title あいうえお", null, "_text `code` *bold*", null, null, null, new String[] { "text", "pretext" }, actions)
};
SlackMessage message = new SlackMessage(
"SlackServiceTests",
new String[] { "#watcher-test", "#watcher-test-2"}, // TODO once we have a dedicated test user in slack, add it here
null,
"slack integration test `testSendMessage()` " + DateTime.now(), attachments);
SlackAccount account = service.getAccount("test_account");
assertThat(account, notNullValue());
SentMessages messages = account.send(message, null);
assertThat(messages.count(), is(2));
for (SentMessages.SentMessage sentMessage : messages) {
try {
assertThat(sentMessage.getException(), is(nullValue()));
assertThat(sentMessage.getRequest(), notNullValue());
assertThat(sentMessage.getResponse(), notNullValue());
assertThat(sentMessage.getResponse().status(), lessThan(300));
} catch (AssertionError e) {
XContentBuilder builder = XContentFactory.jsonBuilder();
builder.prettyPrint();
sentMessage.toXContent(builder, EMPTY_PARAMS);
final String messageDescription = builder.string();
logger.warn("failed to send message. full message description: \n" + messageDescription, e);
throw e;
}
}
}
public void testWatchWithSlackAction() throws Exception {
String account = "test_account";
SlackAction.Builder actionBuilder = slackAction(account, SlackMessage.Template.builder()
.setText("slack integration test `testWatchWithSlackAction()` " + DateTime.now())
.addTo("#watcher-test", "#watcher-test-2"));
PutWatchResponse putWatchResponse = watcherClient().preparePutWatch("1").setSource(watchBuilder()
.trigger(schedule(interval("10m")))
.input(simpleInput("ref", "testWatchWithSlackAction()"))
.condition(InternalAlwaysCondition.INSTANCE)
.addAction("slack", actionBuilder))
.execute().get();
assertThat(putWatchResponse.isCreated(), is(true));
timeWarp().trigger("1");
flush();
refresh();
assertWatchWithMinimumPerformedActionsCount("1", 1L, false);
SearchResponse response = searchHistory(searchSource().query(boolQuery()
.must(termQuery("result.actions.id", "slack"))
.must(termQuery("result.actions.type", "slack"))
.must(termQuery("result.actions.slack.account", account))));
assertThat(response.getHits().getTotalHits(), is(1L));
SearchHit hit = response.getHits().getAt(0);
assertSuccess(hit, "result.actions.0.slack.sent_messages.0.status");
assertSuccess(hit, "result.actions.0.slack.sent_messages.1.status");
assertSuccess(hit, "result.actions.0.status");
}
private void assertSuccess(SearchHit hit, String path) {
XContentSource source = new XContentSource(hit.getSourceRef(), XContentType.JSON);
String json = hit.getSourceAsString();
String message = String.format(Locale.ROOT, "Expected path [%s] to be [success], json is %s", path, json);
assertThat(message, source.getValue(path), is("success"));
}
}

View File

@ -8,13 +8,7 @@ apply plugin: 'elasticsearch.rest-test'
dependencies { dependencies {
testCompile project(path: xpackModule('core'), configuration: 'runtime') testCompile project(path: xpackModule('core'), configuration: 'runtime')
} testCompile project(path: xpackModule('watcher'), configuration: 'runtime')
ext {
jiraUrl = 'https://elasticsearch.atlassian.net/'
jiraUser = 'xpack-user@elastic.co'
jiraPassword = 'N9M4ea9rfy'
jiraProject = 'XWT'
} }
integTestCluster { integTestCluster {
@ -24,67 +18,4 @@ 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'
//
// JIRA integration test settings
//
// The integration tests use a JIRA account on elasticsearch.atlassian.net. This account
// has been created by Edward Sy [edward@elastic.co]. It uses the "XPACK WATCHER TEST"
// 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', jiraUrl
setting 'xpack.notification.jira.account.test.user', jiraUser
setting 'xpack.notification.jira.account.test.password', jiraPassword
setting 'xpack.notification.jira.account.test.issue_defaults.project.key', jiraProject
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) {
doLast {
def issues = jiraIssues(jiraProject)
assert issues instanceof List
issues.forEach {
// See https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-deleteIssue
logger.debug("Deleting JIRA issue [${it}]")
jiraHttpRequest("issue/${it}", "DELETE", 204)
}
}
}
integTestRunner.finalizedBy cleanJira
/** List all issues associated to a given Jira project **/
def jiraIssues(String projectKey) {
// See https://docs.atlassian.com/jira/REST/cloud/#api/2/search-search
def response = jiraHttpRequest("search?maxResults=100&fields=id,self,key&jql=project%3D${projectKey}", "GET", 200)
assert response.issues instanceof List
return response.issues.findAll {it.key.startsWith(projectKey)}.collect {it.key}
}
/** Execute a HTTP request against the Jira server instance **/
def jiraHttpRequest(String endpoint, String method, int successCode) {
HttpsURLConnection connection = null;
try {
byte[] credentials = "${jiraUser}:${jiraPassword}".getBytes(StandardCharsets.UTF_8);
connection = (HttpsURLConnection) new URL("${jiraUrl}/rest/api/2/${endpoint}").openConnection();
connection.setRequestProperty("Authorization", "Basic " + Base64.getEncoder().encodeToString(credentials));
connection.setRequestMethod(method);
connection.connect();
if (connection.getResponseCode() == successCode) {
String response = connection.getInputStream().getText(StandardCharsets.UTF_8.name());
if (response != null && response.length() > 0) {
return new JsonSlurper().parseText(response)
}
} else {
throw new GradleException("Unexpected response code for [${endpoint}]: got ${connection.getResponseCode()} but expected ${successCode}")
}
} catch (Exception e) {
logger.error("Failed to delete JIRA issues after test execution", e)
} finally {
if (connection != null) {
connection.disconnect();
}
}
return null
} }

View File

@ -1,19 +0,0 @@
/*
* 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.smoketest;
import org.elasticsearch.test.ESIntegTestCase;
public class PreventFailingBuildIT extends ESIntegTestCase {
public void testSoThatTestsDoNotFail() {
// Noop
// This is required because SmokeTestWatcherClientYamlTestSuiteIT
// requires network access, so if network tests are not enable no
// tests will be run in the entire project and all tests will fail.
}
}

View File

@ -7,7 +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.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;
@ -25,8 +24,6 @@ import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
/** Runs rest tests against external cluster */
@Network // Needed to access to an external Jira server
public class SmokeTestWatcherClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase { public class SmokeTestWatcherClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
public SmokeTestWatcherClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) { public SmokeTestWatcherClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) {

View File

@ -0,0 +1,27 @@
apply plugin: 'elasticsearch.standalone-test'
dependencies {
testCompile project(xpackModule('security'))
testCompile project(path: xpackModule('security'), configuration: 'testArtifacts')
}
// add test resources from security, so certificate tool tests can use example certs
sourceSets.test.resources.srcDirs(project(xpackModule('security')).sourceSets.test.resources.srcDirs)
// we have to repeate these patterns because the security test resources are effectively in the src of this project
forbiddenPatterns {
exclude '**/*.key'
exclude '**/*.p12'
exclude '**/*.der'
}
test {
/*
* We have to disable setting the number of available processors as tests in the same JVM randomize processors and will step on each
* other if we allow them to set the number of available processors as it's set-once in Netty.
*/
systemProperty 'es.set.netty.runtime.available.processors', 'false'
}
// these are just tests, no need to audit
thirdPartyAudit.enabled = false

View File

@ -29,7 +29,7 @@ import static org.elasticsearch.xpack.core.security.authc.support.UsernamePasswo
* This tests that "run-as" works on LDAP/AD realms * This tests that "run-as" works on LDAP/AD realms
*/ */
@Network @Network
public class ActiveDirectoryRunAsTests extends AbstractAdLdapRealmTestCase { public class ActiveDirectoryRunAsIT extends AbstractAdLdapRealmTestCase {
@BeforeClass @BeforeClass
public static void selectRealmConfig() { public static void selectRealmConfig() {

View File

@ -27,6 +27,7 @@ public class ActiveDirectoryGroupsResolverTests extends GroupsResolverTestCase {
private static final String BRUCE_BANNER_DN = private static final String BRUCE_BANNER_DN =
"cn=Bruce Banner,CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com"; "cn=Bruce Banner,CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com";
@SuppressWarnings("unchecked")
public void testResolveSubTree() throws Exception { public void testResolveSubTree() throws Exception {
Settings settings = Settings.builder() Settings settings = Settings.builder()
.put("group_search.scope", LdapSearchScope.SUB_TREE) .put("group_search.scope", LdapSearchScope.SUB_TREE)

View File

@ -85,6 +85,7 @@ public class ActiveDirectorySessionFactoryTests extends AbstractActiveDirectoryI
} }
} }
@SuppressWarnings("unchecked")
public void testNetbiosAuth() throws Exception { public void testNetbiosAuth() throws Exception {
final String adUrl = randomFrom("ldap://54.213.145.20:3268", "ldaps://54.213.145.20:3269", AD_LDAP_URL); final String adUrl = randomFrom("ldap://54.213.145.20:3268", "ldaps://54.213.145.20:3269", AD_LDAP_URL);
RealmConfig config = new RealmConfig("ad-test", buildAdSettings(adUrl, AD_DOMAIN, false), globalSettings, RealmConfig config = new RealmConfig("ad-test", buildAdSettings(adUrl, AD_DOMAIN, false), globalSettings,
@ -117,8 +118,8 @@ public class ActiveDirectorySessionFactoryTests extends AbstractActiveDirectoryI
.put("ssl.verification_mode", VerificationMode.CERTIFICATE) .put("ssl.verification_mode", VerificationMode.CERTIFICATE)
.put(SessionFactorySettings.TIMEOUT_TCP_READ_SETTING, "1ms") .put(SessionFactorySettings.TIMEOUT_TCP_READ_SETTING, "1ms")
.build(); .build();
RealmConfig config = RealmConfig config = new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings),
new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); new ThreadContext(globalSettings));
try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) { try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) {
PlainActionFuture<List<String>> groups = new PlainActionFuture<>(); PlainActionFuture<List<String>> groups = new PlainActionFuture<>();
@ -147,8 +148,8 @@ public class ActiveDirectorySessionFactoryTests extends AbstractActiveDirectoryI
public void testAuthenticate() throws Exception { public void testAuthenticate() throws Exception {
Settings settings = buildAdSettings(AD_LDAP_URL, AD_DOMAIN, "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com", Settings settings = buildAdSettings(AD_LDAP_URL, AD_DOMAIN, "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com",
LdapSearchScope.ONE_LEVEL, false); LdapSearchScope.ONE_LEVEL, false);
RealmConfig config = RealmConfig config = new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings),
new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); new ThreadContext(globalSettings));
try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) { try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) {
String userName = "hulk"; String userName = "hulk";
@ -201,8 +202,8 @@ public class ActiveDirectorySessionFactoryTests extends AbstractActiveDirectoryI
"CN=Avengers,CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com") "CN=Avengers,CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com")
.put(ActiveDirectorySessionFactorySettings.AD_GROUP_SEARCH_SCOPE_SETTING, LdapSearchScope.BASE) .put(ActiveDirectorySessionFactorySettings.AD_GROUP_SEARCH_SCOPE_SETTING, LdapSearchScope.BASE)
.build(); .build();
RealmConfig config = RealmConfig config = new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings),
new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); new ThreadContext(globalSettings));
try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) { try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) {
String userName = "hulk"; String userName = "hulk";
@ -219,8 +220,8 @@ public class ActiveDirectorySessionFactoryTests extends AbstractActiveDirectoryI
public void testAuthenticateWithUserPrincipalName() throws Exception { public void testAuthenticateWithUserPrincipalName() throws Exception {
Settings settings = buildAdSettings(AD_LDAP_URL, AD_DOMAIN, "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com", Settings settings = buildAdSettings(AD_LDAP_URL, AD_DOMAIN, "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com",
LdapSearchScope.ONE_LEVEL, false); LdapSearchScope.ONE_LEVEL, false);
RealmConfig config = RealmConfig config = new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings),
new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); new ThreadContext(globalSettings));
try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) { try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) {
//Login with the UserPrincipalName //Login with the UserPrincipalName
@ -237,11 +238,12 @@ public class ActiveDirectorySessionFactoryTests extends AbstractActiveDirectoryI
} }
} }
@SuppressWarnings("unchecked")
public void testAuthenticateWithSAMAccountName() throws Exception { public void testAuthenticateWithSAMAccountName() throws Exception {
Settings settings = buildAdSettings(AD_LDAP_URL, AD_DOMAIN, "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com", Settings settings = buildAdSettings(AD_LDAP_URL, AD_DOMAIN, "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com",
LdapSearchScope.ONE_LEVEL, false); LdapSearchScope.ONE_LEVEL, false);
RealmConfig config = RealmConfig config = new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings),
new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); new ThreadContext(globalSettings));
try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) { try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) {
//login with sAMAccountName //login with sAMAccountName
@ -267,8 +269,8 @@ public class ActiveDirectorySessionFactoryTests extends AbstractActiveDirectoryI
.put(ActiveDirectorySessionFactorySettings.AD_USER_SEARCH_FILTER_SETTING, .put(ActiveDirectorySessionFactorySettings.AD_USER_SEARCH_FILTER_SETTING,
"(&(objectclass=user)(userPrincipalName={0}@ad.test.elasticsearch.com))") "(&(objectclass=user)(userPrincipalName={0}@ad.test.elasticsearch.com))")
.build(); .build();
RealmConfig config = RealmConfig config = new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings),
new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); new ThreadContext(globalSettings));
try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) { try (ActiveDirectorySessionFactory sessionFactory = getActiveDirectorySessionFactory(config, sslService, threadPool)) {
//Login with the UserPrincipalName //Login with the UserPrincipalName
@ -408,8 +410,8 @@ public class ActiveDirectorySessionFactoryTests extends AbstractActiveDirectoryI
.put(LdapTestCase.buildLdapSettings(AD_LDAP_URL, userTemplate, groupSearchBase, LdapSearchScope.SUB_TREE)) .put(LdapTestCase.buildLdapSettings(AD_LDAP_URL, userTemplate, groupSearchBase, LdapSearchScope.SUB_TREE))
.put("ssl.verification_mode", VerificationMode.FULL) .put("ssl.verification_mode", VerificationMode.FULL)
.build(); .build();
RealmConfig config = RealmConfig config = new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings),
new RealmConfig("ad-test", settings, globalSettings, TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings)); new ThreadContext(globalSettings));
LdapSessionFactory sessionFactory = new LdapSessionFactory(config, sslService, threadPool); LdapSessionFactory sessionFactory = new LdapSessionFactory(config, sslService, threadPool);
String user = "Bruce Banner"; String user = "Bruce Banner";

View File

@ -0,0 +1,138 @@
/*
* 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.xpack.security.authc.ldap;
import com.unboundid.ldap.sdk.LDAPException;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.MockSecureSettings;
import org.elasticsearch.common.settings.SecureString;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.env.Environment;
import org.elasticsearch.env.TestEnvironment;
import org.elasticsearch.test.junit.annotations.Network;
import org.elasticsearch.threadpool.TestThreadPool;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.xpack.core.security.authc.RealmConfig;
import org.elasticsearch.xpack.core.security.authc.ldap.support.LdapSearchScope;
import org.elasticsearch.xpack.core.ssl.SSLService;
import org.elasticsearch.xpack.security.authc.ldap.support.LdapSession;
import org.elasticsearch.xpack.security.authc.ldap.support.LdapTestCase;
import org.junit.After;
import org.junit.Before;
import java.nio.file.Path;
import java.util.List;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.hasItems;
public class ActiveDirectoryUserSearchSessionFactoryTests extends LdapTestCase {
private SSLService sslService;
private Settings globalSettings;
private ThreadPool threadPool;
@Before
public void init() throws Exception {
Path keystore = getDataPath("support/ADtrust.jks");
Environment env = TestEnvironment.newEnvironment(Settings.builder().put("path.home", createTempDir()).build());
/*
* Prior to each test we reinitialize the socket factory with a new SSLService so that we get a new SSLContext.
* If we re-use a SSLContext, previously connected sessions can get re-established which breaks hostname
* verification tests since a re-established connection does not perform hostname verification.
*/
globalSettings = Settings.builder()
.put("path.home", createTempDir())
.put("xpack.ssl.truststore.path", keystore)
.setSecureSettings(newSecureSettings("xpack.ssl.truststore.secure_password", "changeit"))
.build();
sslService = new SSLService(globalSettings, env);
threadPool = new TestThreadPool("LdapUserSearchSessionFactoryTests");
}
@After
public void shutdown() throws InterruptedException {
terminate(threadPool);
}
@Network
@SuppressWarnings("unchecked")
public void testUserSearchWithActiveDirectory() throws Exception {
String groupSearchBase = "DC=ad,DC=test,DC=elasticsearch,DC=com";
String userSearchBase = "CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com";
Settings settings = Settings.builder()
.put(LdapTestCase.buildLdapSettings(
new String[] { ActiveDirectorySessionFactoryTests.AD_LDAP_URL },
Strings.EMPTY_ARRAY, groupSearchBase, LdapSearchScope.SUB_TREE, null,
true))
.put("user_search.base_dn", userSearchBase)
.put("bind_dn", "ironman@ad.test.elasticsearch.com")
.put("bind_password", ActiveDirectorySessionFactoryTests.PASSWORD)
.put("user_search.filter", "(cn={0})")
.put("user_search.pool.enabled", randomBoolean())
.build();
Settings.Builder builder = Settings.builder()
.put(globalSettings);
settings.keySet().forEach(k -> {
builder.copy("xpack.security.authc.realms.ldap." + k, k, settings);
});
Settings fullSettings = builder.build();
sslService = new SSLService(fullSettings, TestEnvironment.newEnvironment(fullSettings));
RealmConfig config = new RealmConfig("ad-as-ldap-test", settings, globalSettings,
TestEnvironment.newEnvironment(globalSettings), new ThreadContext(globalSettings));
LdapUserSearchSessionFactory sessionFactory = getLdapUserSearchSessionFactory(config, sslService, threadPool);
String user = "Bruce Banner";
try {
//auth
try (LdapSession ldap = session(sessionFactory, user, new SecureString(ActiveDirectorySessionFactoryTests.PASSWORD))) {
assertConnectionCanReconnect(ldap.getConnection());
List<String> groups = groups(ldap);
assertThat(groups, containsInAnyOrder(
containsString("Avengers"),
containsString("SHIELD"),
containsString("Geniuses"),
containsString("Philanthropists")));
}
//lookup
try (LdapSession ldap = unauthenticatedSession(sessionFactory, user)) {
assertConnectionCanReconnect(ldap.getConnection());
List<String> groups = groups(ldap);
assertThat(groups, containsInAnyOrder(
containsString("Avengers"),
containsString("SHIELD"),
containsString("Geniuses"),
containsString("Philanthropists")));
}
} finally {
sessionFactory.close();
}
}
static LdapUserSearchSessionFactory getLdapUserSearchSessionFactory(RealmConfig config, SSLService sslService, ThreadPool threadPool)
throws LDAPException {
LdapUserSearchSessionFactory sessionFactory = new LdapUserSearchSessionFactory(config, sslService, threadPool);
if (sessionFactory.getConnectionPool() != null) {
// don't use this in production
// used here to catch bugs that might get masked by an automatic retry
sessionFactory.getConnectionPool().setRetryFailedOperationsDueToInvalidConnections(false);
}
return sessionFactory;
}
private MockSecureSettings newSecureSettings(String key, String value) {
MockSecureSettings secureSettings = new MockSecureSettings();
secureSettings.setString(key, value);
return secureSettings;
}
}

View File

@ -0,0 +1,17 @@
/*
* 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.xpack.security.authc.ldap;
import org.elasticsearch.test.ESTestCase;
public class PreventFailingTests extends ESTestCase {
public void testPreventFailingWithNetworkingDisabled() {
// Noop
// This is required because if network tests are not enabled no tests will be run in the entire project and all tests will fail.
}
}

View File

@ -27,6 +27,7 @@ public class UserAttributeGroupsResolverTests extends GroupsResolverTestCase {
public static final String BRUCE_BANNER_DN = "cn=Bruce Banner,CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com"; public static final String BRUCE_BANNER_DN = "cn=Bruce Banner,CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com";
@SuppressWarnings("unchecked")
public void testResolve() throws Exception { public void testResolve() throws Exception {
//falling back on the 'memberOf' attribute //falling back on the 'memberOf' attribute
UserAttributeGroupsResolver resolver = new UserAttributeGroupsResolver(Settings.EMPTY); UserAttributeGroupsResolver resolver = new UserAttributeGroupsResolver(Settings.EMPTY);
@ -39,6 +40,7 @@ public class UserAttributeGroupsResolverTests extends GroupsResolverTestCase {
containsString("Philanthropists"))); containsString("Philanthropists")));
} }
@SuppressWarnings("unchecked")
public void testResolveFromPreloadedAttributes() throws Exception { public void testResolveFromPreloadedAttributes() throws Exception {
SearchRequest preSearch = new SearchRequest(BRUCE_BANNER_DN, SearchScope.BASE, LdapUtils.OBJECT_CLASS_PRESENCE_FILTER, "memberOf"); SearchRequest preSearch = new SearchRequest(BRUCE_BANNER_DN, SearchScope.BASE, LdapUtils.OBJECT_CLASS_PRESENCE_FILTER, "memberOf");
final Collection<Attribute> attributes = ldapConnection.searchForEntry(preSearch).getAttributes(); final Collection<Attribute> attributes = ldapConnection.searchForEntry(preSearch).getAttributes();
@ -53,6 +55,7 @@ public class UserAttributeGroupsResolverTests extends GroupsResolverTestCase {
containsString("Philanthropists"))); containsString("Philanthropists")));
} }
@SuppressWarnings("unchecked")
public void testResolveCustomGroupAttribute() throws Exception { public void testResolveCustomGroupAttribute() throws Exception {
Settings settings = Settings.builder() Settings settings = Settings.builder()
.put("user_group_attribute", "seeAlso") .put("user_group_attribute", "seeAlso")

0
qa/third-party/build.gradle vendored Normal file
View File

38
qa/third-party/hipchat/build.gradle vendored Normal file
View File

@ -0,0 +1,38 @@
apply plugin: 'elasticsearch.standalone-rest-test'
apply plugin: 'elasticsearch.rest-test'
dependencies {
testCompile project(path: xpackModule('core'), configuration: 'runtime')
testCompile project(path: xpackModule('watcher'), configuration: 'runtime')
}
String integrationAccountPropertyName = 'xpack.notification.hipchat.auth_token_integration'
System.setProperty(integrationAccountPropertyName, 'huuS9v7ccuOy3ZBWWWr1vt8Lqu3sQnLUE81nrLZU')
String userAccountPropertyName = 'xpack.notification.hipchat.auth_token_user'
System.setProperty(userAccountPropertyName, '4UefsFLvKRw01EMN5vo3oyoY6BLiz7IQBQbGug8K')
String v1AccountPropertyName = 'xpack.notification.hipchat.auth_token_v1'
System.setProperty(v1AccountPropertyName, 'a734baf62df618b96dda55b323fc30')
integTestCluster {
plugin xpackProject('plugin').path
setting 'xpack.security.enabled', 'false'
setting 'xpack.monitoring.enabled', 'false'
setting 'xpack.ml.enabled', 'false'
setting 'xpack.license.self_generated.type', 'trial'
setting 'logger.org.elasticsearch.xpack.watcher', 'DEBUG'
// hipchat
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.auth_token', System.getProperty(integrationAccountPropertyName)
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.auth_token', System.getProperty(v1AccountPropertyName)
}
if (!System.getProperty(integrationAccountPropertyName) || !System.getProperty(userAccountPropertyName) ||
!System.getProperty(v1AccountPropertyName) || !System.getProperty('tests.network')) {
integTest.enabled = false
}

View File

@ -0,0 +1,78 @@
/*
* 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.smoketest;
import com.carrotsearch.randomizedtesting.annotations.Name;
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.ClientYamlTestResponse;
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
import org.elasticsearch.xpack.core.watcher.support.WatcherIndexTemplateRegistryField;
import org.junit.After;
import org.junit.Before;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonMap;
import static org.hamcrest.Matchers.is;
/** Runs rest tests against external cluster */
@Network // Needed to access to an external Jira server
public class SmokeTestWatcherClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
public SmokeTestWatcherClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) {
super(testCandidate);
}
@ParametersFactory
public static Iterable<Object[]> parameters() throws Exception {
return ESClientYamlSuiteTestCase.createParameters();
}
@Before
public void startWatcher() throws Exception {
final List<String> watcherTemplates = Arrays.asList(WatcherIndexTemplateRegistryField.TEMPLATE_NAMES);
assertBusy(() -> {
try {
getAdminExecutionContext().callApi("xpack.watcher.start", emptyMap(), emptyList(), emptyMap());
for (String template : watcherTemplates) {
ClientYamlTestResponse templateExistsResponse = getAdminExecutionContext().callApi("indices.exists_template",
singletonMap("name", template), emptyList(), emptyMap());
assertThat(templateExistsResponse.getStatusCode(), is(200));
}
ClientYamlTestResponse response =
getAdminExecutionContext().callApi("xpack.watcher.stats", emptyMap(), emptyList(), emptyMap());
String state = (String) response.evaluate("stats.0.watcher_state");
assertThat(state, is("started"));
} catch (IOException e) {
throw new AssertionError(e);
}
});
}
@After
public void stopWatcher() throws Exception {
assertBusy(() -> {
try {
getAdminExecutionContext().callApi("xpack.watcher.stop", emptyMap(), emptyList(), emptyMap());
ClientYamlTestResponse response =
getAdminExecutionContext().callApi("xpack.watcher.stats", emptyMap(), emptyList(), emptyMap());
String state = (String) response.evaluate("stats.0.watcher_state");
assertThat(state, is("stopped"));
} catch (IOException e) {
throw new AssertionError(e);
}
});
}
}

View File

@ -0,0 +1,276 @@
---
"Test Hipchat v1 account Action":
- do:
cluster.health:
wait_for_status: yellow
- do:
xpack.watcher.put_watch:
id: "hipchat_v1_watch"
body: >
{
"trigger": {
"schedule": {
"interval": "1d"
}
},
"input": {
"simple": {
"foo": "something from input"
}
},
"actions": {
"my_hipchat_action": {
"hipchat": {
"account": "v1_account",
"message": {
"from" : "watcher-tests",
"room" : ["test-watcher", "test-watcher-2", "test watcher with spaces"],
"body": "From input {{ctx.payload.foo}}, and some tests (facepalm) in the v1 account",
"format": "text",
"color": "red",
"notify": true
}
}
}
}
}
- do:
xpack.watcher.execute_watch:
id: "hipchat_v1_watch"
body: >
{
"record_execution": true
}
- match: { watch_record.trigger_event.type: "manual" }
- match: { watch_record.state: "executed" }
- match: { watch_record.result.actions.0.id: "my_hipchat_action" }
- match: { watch_record.result.actions.0.type: "hipchat" }
- match: { watch_record.result.actions.0.status: "success" }
- match: { watch_record.result.actions.0.hipchat.account: "v1_account" }
- match: { watch_record.result.actions.0.hipchat.sent_messages.0.room: "test-watcher" }
- match: { watch_record.result.actions.0.hipchat.sent_messages.1.room: "test-watcher-2" }
- match: { watch_record.result.actions.0.hipchat.sent_messages.2.room: "test watcher with spaces" }
- match: { watch_record.result.actions.0.hipchat.sent_messages.0.status: "success" }
- match: { watch_record.result.actions.0.hipchat.sent_messages.1.status: "success" }
- match: { watch_record.result.actions.0.hipchat.sent_messages.2.status: "success" }
# Waits for the watcher history index to be available
- do:
cluster.health:
index: ".watcher-history-*"
wait_for_no_relocating_shards: true
timeout: 60s
- do:
indices.refresh: {}
- do:
search:
index: ".watcher-history-*"
body: >
{
"query" : {
"term" : {
"watch_id" : "hipchat_v1_watch"
}
}
}
- match: { hits.total: 1 }
- match: { hits.hits.0._source.state: "executed" }
- match: { hits.hits.0._source.result.actions.0.id: "my_hipchat_action" }
- match: { hits.hits.0._source.result.actions.0.type: "hipchat" }
- match: { hits.hits.0._source.result.actions.0.status: "success" }
- match: { hits.hits.0._source.result.actions.0.hipchat.account: "v1_account" }
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.0.room: "test-watcher" }
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.1.room: "test-watcher-2" }
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.2.room: "test watcher with spaces" }
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.0.status: "success" }
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.1.status: "success" }
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.2.status: "success" }
---
"Test Hipchat integration account Action":
- do:
cluster.health:
wait_for_status: yellow
# custom rooms, custom users and custom from are not allowed for this account type to be configured
- do:
xpack.watcher.put_watch:
id: "hipchat_integration_account_watch"
body: >
{
"trigger": {
"schedule": {
"interval": "1d"
}
},
"input": {
"simple": {
"foo": "something from input"
}
},
"actions": {
"my_hipchat_action": {
"hipchat": {
"account": "integration_account",
"message": {
"body": "From input {{ctx.payload.foo}}, and some tests (facepalm) in the integration account",
"format": "text",
"color": "red",
"notify": true
}
}
}
}
}
- do:
xpack.watcher.execute_watch:
id: "hipchat_integration_account_watch"
body: >
{
"record_execution": true
}
- match: { watch_record.trigger_event.type: "manual" }
- match: { watch_record.state: "executed" }
- match: { watch_record.result.actions.0.id: "my_hipchat_action" }
- match: { watch_record.result.actions.0.type: "hipchat" }
- match: { watch_record.result.actions.0.status: "success" }
- match: { watch_record.result.actions.0.hipchat.account: "integration_account" }
- match: { watch_record.result.actions.0.hipchat.sent_messages.0.status: "success" }
- match: { watch_record.result.actions.0.hipchat.sent_messages.0.room: "test-watcher" }
# Waits for the watcher history index to be available
- do:
cluster.health:
index: ".watcher-history-*"
wait_for_no_relocating_shards: true
timeout: 60s
- do:
indices.refresh: {}
- do:
search:
index: ".watcher-history-*"
body: >
{
"query" : {
"term" : {
"watch_id" : "hipchat_integration_account_watch"
}
}
}
- match: { hits.total: 1 }
- match: { hits.hits.0._source.state: "executed" }
- match: { hits.hits.0._source.result.actions.0.id: "my_hipchat_action" }
- match: { hits.hits.0._source.result.actions.0.type: "hipchat" }
- match: { hits.hits.0._source.result.actions.0.status: "success" }
- match: { hits.hits.0._source.result.actions.0.hipchat.account: "integration_account" }
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.0.room: "test-watcher" }
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.0.status: "success" }
---
"Test Hipchat user account Action":
- do:
cluster.health:
wait_for_status: yellow
- do:
xpack.watcher.put_watch:
id: "hipchat_user_account_watch"
body: >
{
"trigger": {
"schedule": {
"interval": "1d"
}
},
"input": {
"simple": {
"foo": "something from input"
}
},
"actions": {
"my_hipchat_action": {
"hipchat": {
"account": "user_account",
"message": {
"user" : [ "watcher@elastic.co" ],
"room" : ["test-watcher", "test-watcher-2", "test watcher with spaces"],
"body": "From input {{ctx.payload.foo}}, and some tests (facepalm) in the user_account test. <b>bold</b>",
"format": "html"
}
}
}
}
}
- do:
xpack.watcher.execute_watch:
id: "hipchat_user_account_watch"
body: >
{
"record_execution": true
}
- match: { watch_record.trigger_event.type: "manual" }
- match: { watch_record.state: "executed" }
- match: { watch_record.result.actions.0.id: "my_hipchat_action" }
- match: { watch_record.result.actions.0.type: "hipchat" }
- match: { watch_record.result.actions.0.status: "success" }
- match: { watch_record.result.actions.0.hipchat.account: "user_account" }
- match: { watch_record.result.actions.0.hipchat.sent_messages.0.room: "test-watcher" }
- match: { watch_record.result.actions.0.hipchat.sent_messages.1.room: "test-watcher-2" }
- match: { watch_record.result.actions.0.hipchat.sent_messages.2.room: "test watcher with spaces" }
- match: { watch_record.result.actions.0.hipchat.sent_messages.3.user: "watcher@elastic.co" }
- match: { watch_record.result.actions.0.hipchat.sent_messages.0.status: "success" }
- match: { watch_record.result.actions.0.hipchat.sent_messages.1.status: "success" }
- match: { watch_record.result.actions.0.hipchat.sent_messages.2.status: "success" }
- match: { watch_record.result.actions.0.hipchat.sent_messages.3.status: "success" }
# Waits for the watcher history index to be available
- do:
cluster.health:
index: ".watcher-history-*"
wait_for_no_relocating_shards: true
timeout: 60s
- do:
indices.refresh: {}
- do:
search:
index: ".watcher-history-*"
body: >
{
"query" : {
"term" : {
"watch_id" : "hipchat_user_account_watch"
}
}
}
- match: { hits.total: 1 }
- match: { hits.hits.0._source.state: "executed" }
- match: { hits.hits.0._source.result.actions.0.id: "my_hipchat_action" }
- match: { hits.hits.0._source.result.actions.0.type: "hipchat" }
- match: { hits.hits.0._source.result.actions.0.status: "success" }
- match: { hits.hits.0._source.result.actions.0.hipchat.account: "user_account" }
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.0.room: "test-watcher" }
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.1.room: "test-watcher-2" }
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.2.room: "test watcher with spaces" }
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.3.user: "watcher@elastic.co" }
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.0.status: "success" }
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.1.status: "success" }
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.2.status: "success" }
- match: { hits.hits.0._source.result.actions.0.hipchat.sent_messages.1.status: "success" }

107
qa/third-party/jira/build.gradle vendored Normal file
View File

@ -0,0 +1,107 @@
import groovy.json.JsonSlurper
import javax.net.ssl.HttpsURLConnection
import java.nio.charset.StandardCharsets
apply plugin: 'elasticsearch.standalone-rest-test'
apply plugin: 'elasticsearch.rest-test'
dependencies {
testCompile project(path: xpackModule('core'), configuration: 'runtime')
testCompile project(path: xpackModule('watcher'), configuration: 'runtime')
}
ext {
jiraUrlPropertyName = 'xpack.notification.jira.url'
jiraUserPropertyName = 'xpack.notification.jira.user'
jiraPasswordPropertyName = 'xpack.notification.jira.password'
jiraProjectPropertyName = 'xpack.notification.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 {
plugin xpackProject('plugin').path
setting 'xpack.security.enabled', 'false'
setting 'xpack.monitoring.enabled', 'false'
setting 'xpack.ml.enabled', 'false'
setting 'xpack.license.self_generated.type', 'trial'
setting 'logger.org.elasticsearch.xpack.watcher', 'DEBUG'
//
// JIRA integration test settings
//
// The integration tests use a JIRA account on elasticsearch.atlassian.net. This account
// has been created by Edward Sy [edward@elastic.co]. It uses the "XPACK WATCHER TEST"
// 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) {
doLast {
def issues = jiraIssues(System.getProperty(jiraProjectPropertyName))
assert issues instanceof List
issues.forEach {
// See https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-deleteIssue
logger.debug("Deleting JIRA issue [${it}]")
jiraHttpRequest("issue/${it}", "DELETE", 204)
}
}
}
// 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) ||
!System.getProperty(jiraPasswordPropertyName) || !System.getProperty(jiraProjectPropertyName) ||
!System.getProperty('tests.network')) {
integTest.enabled = false
} else {
integTestRunner.finalizedBy cleanJira
}
/** List all issues associated to a given Jira project **/
def jiraIssues(projectKey) {
// See https://docs.atlassian.com/jira/REST/cloud/#api/2/search-search
def response = jiraHttpRequest("search?maxResults=100&fields=id,self,key&jql=project%3D${projectKey}", "GET", 200)
assert response.issues instanceof List
return response.issues.findAll {it.key.startsWith(projectKey)}.collect {it.key}
}
/** Execute a HTTP request against the Jira server instance **/
def jiraHttpRequest(String endpoint, String method, int successCode) {
HttpsURLConnection connection = null;
try {
def jiraUser = System.getProperty(jiraUserPropertyName)
def jiraPassword = System.getProperty(jiraPasswordPropertyName)
def jiraUrl = System.getProperty(jiraUrlPropertyName)
byte[] credentials = "${jiraUser}:${jiraPassword}".getBytes(StandardCharsets.UTF_8);
connection = (HttpsURLConnection) new URL("${jiraUrl}/rest/api/2/${endpoint}").openConnection();
connection.setRequestProperty("Authorization", "Basic " + Base64.getEncoder().encodeToString(credentials));
connection.setRequestMethod(method);
connection.connect();
if (connection.getResponseCode() == successCode) {
String response = connection.getInputStream().getText(StandardCharsets.UTF_8.name());
if (response != null && response.length() > 0) {
return new JsonSlurper().parseText(response)
}
} else {
throw new GradleException("Unexpected response code for [${endpoint}]: got ${connection.getResponseCode()} but expected ${successCode}")
}
} catch (Exception e) {
logger.error("Failed to delete JIRA issues after test execution", e)
} finally {
if (connection != null) {
connection.disconnect();
}
}
return null
}

View File

@ -0,0 +1,78 @@
/*
* 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.smoketest;
import com.carrotsearch.randomizedtesting.annotations.Name;
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.ClientYamlTestResponse;
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
import org.elasticsearch.xpack.core.watcher.support.WatcherIndexTemplateRegistryField;
import org.junit.After;
import org.junit.Before;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonMap;
import static org.hamcrest.Matchers.is;
/** Runs rest tests against external cluster */
@Network // Needed to access to an external Jira server
public class SmokeTestWatcherClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
public SmokeTestWatcherClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) {
super(testCandidate);
}
@ParametersFactory
public static Iterable<Object[]> parameters() throws Exception {
return ESClientYamlSuiteTestCase.createParameters();
}
@Before
public void startWatcher() throws Exception {
final List<String> watcherTemplates = Arrays.asList(WatcherIndexTemplateRegistryField.TEMPLATE_NAMES);
assertBusy(() -> {
try {
getAdminExecutionContext().callApi("xpack.watcher.start", emptyMap(), emptyList(), emptyMap());
for (String template : watcherTemplates) {
ClientYamlTestResponse templateExistsResponse = getAdminExecutionContext().callApi("indices.exists_template",
singletonMap("name", template), emptyList(), emptyMap());
assertThat(templateExistsResponse.getStatusCode(), is(200));
}
ClientYamlTestResponse response =
getAdminExecutionContext().callApi("xpack.watcher.stats", emptyMap(), emptyList(), emptyMap());
String state = (String) response.evaluate("stats.0.watcher_state");
assertThat(state, is("started"));
} catch (IOException e) {
throw new AssertionError(e);
}
});
}
@After
public void stopWatcher() throws Exception {
assertBusy(() -> {
try {
getAdminExecutionContext().callApi("xpack.watcher.stop", emptyMap(), emptyList(), emptyMap());
ClientYamlTestResponse response =
getAdminExecutionContext().callApi("xpack.watcher.stats", emptyMap(), emptyList(), emptyMap());
String state = (String) response.evaluate("stats.0.watcher_state");
assertThat(state, is("stopped"));
} catch (IOException e) {
throw new AssertionError(e);
}
});
}
}

39
qa/third-party/pagerduty/build.gradle vendored Normal file
View File

@ -0,0 +1,39 @@
apply plugin: 'elasticsearch.standalone-rest-test'
apply plugin: 'elasticsearch.rest-test'
dependencies {
testCompile project(path: xpackModule('core'), configuration: 'runtime')
testCompile project(path: xpackModule('watcher'), configuration: 'runtime')
}
String pagerDutyPropertyName = 'xpack.notification.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 {
plugin xpackProject('plugin').path
setting 'xpack.security.enabled', 'false'
setting 'xpack.monitoring.enabled', 'false'
setting 'xpack.ml.enabled', 'false'
setting 'xpack.license.self_generated.type', 'trial'
setting 'logger.org.elasticsearch.xpack.watcher', 'DEBUG'
// 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 (!System.getProperty(pagerDutyPropertyName) || !System.getProperty('tests.network')) {
integTest.enabled = false
}

View File

@ -0,0 +1,78 @@
/*
* 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.smoketest;
import com.carrotsearch.randomizedtesting.annotations.Name;
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.ClientYamlTestResponse;
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
import org.elasticsearch.xpack.core.watcher.support.WatcherIndexTemplateRegistryField;
import org.junit.After;
import org.junit.Before;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonMap;
import static org.hamcrest.Matchers.is;
/** Runs rest tests against external cluster */
@Network // Needed to access to an external Jira server
public class SmokeTestWatcherClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
public SmokeTestWatcherClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) {
super(testCandidate);
}
@ParametersFactory
public static Iterable<Object[]> parameters() throws Exception {
return ESClientYamlSuiteTestCase.createParameters();
}
@Before
public void startWatcher() throws Exception {
final List<String> watcherTemplates = Arrays.asList(WatcherIndexTemplateRegistryField.TEMPLATE_NAMES);
assertBusy(() -> {
try {
getAdminExecutionContext().callApi("xpack.watcher.start", emptyMap(), emptyList(), emptyMap());
for (String template : watcherTemplates) {
ClientYamlTestResponse templateExistsResponse = getAdminExecutionContext().callApi("indices.exists_template",
singletonMap("name", template), emptyList(), emptyMap());
assertThat(templateExistsResponse.getStatusCode(), is(200));
}
ClientYamlTestResponse response =
getAdminExecutionContext().callApi("xpack.watcher.stats", emptyMap(), emptyList(), emptyMap());
String state = (String) response.evaluate("stats.0.watcher_state");
assertThat(state, is("started"));
} catch (IOException e) {
throw new AssertionError(e);
}
});
}
@After
public void stopWatcher() throws Exception {
assertBusy(() -> {
try {
getAdminExecutionContext().callApi("xpack.watcher.stop", emptyMap(), emptyList(), emptyMap());
ClientYamlTestResponse response =
getAdminExecutionContext().callApi("xpack.watcher.stats", emptyMap(), emptyList(), emptyMap());
String state = (String) response.evaluate("stats.0.watcher_state");
assertThat(state, is("stopped"));
} catch (IOException e) {
throw new AssertionError(e);
}
});
}
}

View File

@ -0,0 +1,103 @@
---
"Test PagerDuty Action":
- do:
cluster.health:
wait_for_status: yellow
- do:
xpack.watcher.put_watch:
id: "pagerduty_watch"
body: >
{
"trigger": {
"schedule": {
"interval": "1d"
}
},
"input": {
"simple": {
}
},
"actions": {
"my_pagerduty_action": {
"pagerduty": {
"description": "#testIncidentEvent()",
"client": "PagerDutyServiceTests",
"client_url": "_client_url",
"account" : "_account",
"contexts" : [
{
"type": "link",
"href": "https://www.elastic.co/products/x-pack/alerting",
"text": "Go to the Elastic.co Alerting website"
},
{
"type": "image",
"src": "https://www.elastic.co/assets/blte5d899fd0b0e6808/icon-alerting-bb.svg",
"href": "https://www.elastic.co/assets/blte5d899fd0b0e6808/icon-alerting-bb.svg",
"alt": "X-Pack-Alerting website link with log"
}
]
}
}
}
}
- do:
xpack.watcher.execute_watch:
id: "pagerduty_watch"
body: >
{
"record_execution": true
}
- match: { watch_record.trigger_event.type: "manual" }
- match: { watch_record.state: "executed" }
- match: { watch_record.result.actions.0.id: "my_pagerduty_action" }
- match: { watch_record.result.actions.0.type: "pagerduty" }
- match: { watch_record.result.actions.0.status: "success" }
- match: { watch_record.result.actions.0.pagerduty.sent_event.event.account: "_account" }
- match: { watch_record.result.actions.0.pagerduty.sent_event.event.incident_key: "pagerduty_watch" }
- match: { watch_record.result.actions.0.pagerduty.sent_event.event.description: "#testIncidentEvent()" }
- match: { watch_record.result.actions.0.pagerduty.sent_event.event.client: "PagerDutyServiceTests" }
- match: { watch_record.result.actions.0.pagerduty.sent_event.event.client_url: "_client_url" }
- match: { watch_record.result.actions.0.pagerduty.sent_event.event.attach_payload: false }
- match: { watch_record.result.actions.0.pagerduty.sent_event.event.contexts.0.type: "link" }
- match: { watch_record.result.actions.0.pagerduty.sent_event.event.contexts.1.type: "image" }
# Waits for the watcher history index to be available
- do:
cluster.health:
index: ".watcher-history-*"
wait_for_no_relocating_shards: true
timeout: 60s
- do:
indices.refresh: {}
- do:
search:
index: ".watcher-history-*"
body: >
{
"query" : {
"term" : {
"watch_id" : "pagerduty_watch"
}
}
}
- match: { hits.total: 1 }
- match: { hits.hits.0._source.state: "executed" }
- match: { hits.hits.0._source.result.actions.0.id: "my_pagerduty_action" }
- match: { hits.hits.0._source.result.actions.0.type: "pagerduty" }
- match: { hits.hits.0._source.result.actions.0.status: "success" }
- match: { hits.hits.0._source.result.actions.0.pagerduty.sent_event.event.account: "_account" }
- match: { hits.hits.0._source.result.actions.0.pagerduty.sent_event.event.incident_key: "pagerduty_watch" }
- match: { hits.hits.0._source.result.actions.0.pagerduty.sent_event.event.description: "#testIncidentEvent()" }
- match: { hits.hits.0._source.result.actions.0.pagerduty.sent_event.event.client: "PagerDutyServiceTests" }
- match: { hits.hits.0._source.result.actions.0.pagerduty.sent_event.event.client_url: "_client_url" }
- match: { hits.hits.0._source.result.actions.0.pagerduty.sent_event.event.attach_payload: false }
- match: { hits.hits.0._source.result.actions.0.pagerduty.sent_event.event.contexts.0.type: "link" }
- match: { hits.hits.0._source.result.actions.0.pagerduty.sent_event.event.contexts.1.type: "image" }

26
qa/third-party/slack/build.gradle vendored Normal file
View File

@ -0,0 +1,26 @@
apply plugin: 'elasticsearch.standalone-rest-test'
apply plugin: 'elasticsearch.rest-test'
dependencies {
testCompile project(path: xpackModule('core'), configuration: 'runtime')
testCompile project(path: xpackModule('watcher'), configuration: 'runtime')
}
String slackPropertyName = 'xpack.notification.slack.url'
System.setProperty(slackPropertyName, 'https://hooks.slack.com/services/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')
integTestCluster {
plugin xpackProject('plugin').path
setting 'xpack.security.enabled', 'false'
setting 'xpack.monitoring.enabled', 'false'
setting 'xpack.ml.enabled', 'false'
setting 'xpack.license.self_generated.type', 'trial'
setting 'logger.org.elasticsearch.xpack.watcher', 'DEBUG'
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 (!System.getProperty(slackPropertyName) || !System.getProperty('tests.network')) {
integTest.enabled = false
}

View File

@ -0,0 +1,78 @@
/*
* 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.smoketest;
import com.carrotsearch.randomizedtesting.annotations.Name;
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.ClientYamlTestResponse;
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
import org.elasticsearch.xpack.core.watcher.support.WatcherIndexTemplateRegistryField;
import org.junit.After;
import org.junit.Before;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonMap;
import static org.hamcrest.Matchers.is;
/** Runs rest tests against external cluster */
@Network // Needed to access to an external Jira server
public class SmokeTestWatcherClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
public SmokeTestWatcherClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) {
super(testCandidate);
}
@ParametersFactory
public static Iterable<Object[]> parameters() throws Exception {
return ESClientYamlSuiteTestCase.createParameters();
}
@Before
public void startWatcher() throws Exception {
final List<String> watcherTemplates = Arrays.asList(WatcherIndexTemplateRegistryField.TEMPLATE_NAMES);
assertBusy(() -> {
try {
getAdminExecutionContext().callApi("xpack.watcher.start", emptyMap(), emptyList(), emptyMap());
for (String template : watcherTemplates) {
ClientYamlTestResponse templateExistsResponse = getAdminExecutionContext().callApi("indices.exists_template",
singletonMap("name", template), emptyList(), emptyMap());
assertThat(templateExistsResponse.getStatusCode(), is(200));
}
ClientYamlTestResponse response =
getAdminExecutionContext().callApi("xpack.watcher.stats", emptyMap(), emptyList(), emptyMap());
String state = (String) response.evaluate("stats.0.watcher_state");
assertThat(state, is("started"));
} catch (IOException e) {
throw new AssertionError(e);
}
});
}
@After
public void stopWatcher() throws Exception {
assertBusy(() -> {
try {
getAdminExecutionContext().callApi("xpack.watcher.stop", emptyMap(), emptyList(), emptyMap());
ClientYamlTestResponse response =
getAdminExecutionContext().callApi("xpack.watcher.stats", emptyMap(), emptyList(), emptyMap());
String state = (String) response.evaluate("stats.0.watcher_state");
assertThat(state, is("stopped"));
} catch (IOException e) {
throw new AssertionError(e);
}
});
}
}

View File

@ -0,0 +1,109 @@
---
"Test Slack Action":
- do:
cluster.health:
wait_for_status: yellow
- do:
xpack.watcher.put_watch:
id: "slack_watch"
body: >
{
"trigger": {
"schedule": {
"interval": "1d"
}
},
"input": {
"simple": {
"foo" : "something from input"
}
},
"actions": {
"my_slack_action": {
"slack": {
"account": "test_account",
"message": {
"from": "SlackServiceTests",
"to": [
"#watcher-test", "#watcher-test-2"
],
"text": "slack integration test {{ctx.trigger.triggered_time}}",
"attachments": [
{
"title": "title あいうえお",
"text": "From input: {{ctx.payload.foo}} - other testing: :facepalm: also `code` and *bold*",
"color": "warning",
"author_name" : "your friendly slack integration test"
},
{
"title" : "attachment with action",
"text" : "button test",
"actions" : [
{
"name" : "action name",
"style" : "danger",
"type" : "button",
"text" : "Button to go to elastic.co",
"url" : "https://elastic.co"
}
]
}
]
}
}
}
}
}
- do:
xpack.watcher.execute_watch:
id: "slack_watch"
body: >
{
"record_execution": true
}
- match: { watch_record.trigger_event.type: "manual" }
- match: { watch_record.state: "executed" }
- match: { watch_record.result.actions.0.id: "my_slack_action" }
- match: { watch_record.result.actions.0.type: "slack" }
- match: { watch_record.result.actions.0.status: "success" }
- match: { watch_record.result.actions.0.slack.account: "test_account" }
- match: { watch_record.result.actions.0.slack.sent_messages.0.to: "#watcher-test" }
- match: { watch_record.result.actions.0.slack.sent_messages.1.to: "#watcher-test-2" }
- match: { watch_record.result.actions.0.slack.sent_messages.0.status: "success" }
- match: { watch_record.result.actions.0.slack.sent_messages.1.status: "success" }
# Waits for the watcher history index to be available
- do:
cluster.health:
index: ".watcher-history-*"
wait_for_no_relocating_shards: true
timeout: 60s
- do:
indices.refresh: {}
- do:
search:
index: ".watcher-history-*"
body: >
{
"query" : {
"term" : {
"watch_id" : "slack_watch"
}
}
}
- match: { hits.total: 1 }
- match: { hits.hits.0._source.state: "executed" }
- match: { hits.hits.0._source.result.actions.0.id: "my_slack_action" }
- match: { hits.hits.0._source.result.actions.0.type: "slack" }
- match: { hits.hits.0._source.result.actions.0.status: "success" }
- match: { hits.hits.0._source.result.actions.0.slack.account: "test_account" }
- match: { hits.hits.0._source.result.actions.0.slack.sent_messages.0.to: "#watcher-test" }
- match: { hits.hits.0._source.result.actions.0.slack.sent_messages.1.to: "#watcher-test-2" }
- match: { hits.hits.0._source.result.actions.0.slack.sent_messages.0.status: "success" }
- match: { hits.hits.0._source.result.actions.0.slack.sent_messages.1.status: "success" }