added watcher+shield qa rest tests

only run watcher rest tests during verify phase
never run the rest tests with shield enabled, because that is now tested in the new qa module
removed the disabled license watcher rest tests, because the disabled license use case is already tested by the LicenseIntegrationTests
enabled the getting started rest test

Closes elastic/elasticsearch#403

Original commit: elastic/x-pack-elasticsearch@67f0f7f596
This commit is contained in:
Martijn van Groningen 2015-08-12 00:09:05 +02:00
parent 9479569b02
commit ca8a7bb262
13 changed files with 728 additions and 298 deletions

View File

@ -320,5 +320,6 @@
<modules>
<module>smoke-test-plugins</module>
<module>smoke-test-plugins-ssl</module>
<module>smoke-test-watcher-with-shield</module>
</modules>
</project>

View File

@ -0,0 +1,168 @@
<?xml version="1.0"?>
<!--
~ ELASTICSEARCH CONFIDENTIAL
~ __________________
~
~ [2014] Elasticsearch Incorporated. All Rights Reserved.
~
~ NOTICE: All information contained herein is, and remains
~ the property of Elasticsearch Incorporated and its suppliers,
~ if any. The intellectual and technical concepts contained
~ herein are proprietary to Elasticsearch Incorporated
~ and its suppliers and may be covered by U.S. and Foreign Patents,
~ patents in process, and are protected by trade secret or copyright law.
~ Dissemination of this information or reproduction of this material
~ is strictly forbidden unless prior written permission is obtained
~ from Elasticsearch Incorporated.
-->
<project name="smoke-test-watcher-and-shield"
xmlns:ac="antlib:net.sf.antcontrib">
<import file="${elasticsearch.integ.antfile.default}"/>
<!-- redefined to work with auth -->
<macrodef name="waitfor-elasticsearch">
<attribute name="port"/>
<attribute name="timeoutproperty"/>
<sequential>
<echo>Waiting for elasticsearch to become available on port @{port}...</echo>
<waitfor maxwait="30" maxwaitunit="second"
checkevery="500" checkeveryunit="millisecond"
timeoutproperty="@{timeoutproperty}">
<socket server="127.0.0.1" port="@{port}"/>
</waitfor>
</sequential>
</macrodef>
<!-- FIXME remove this redefinition and fix in core -->
<macrodef name="startup-elasticsearch">
<attribute name="home" default="${integ.scratch}/elasticsearch-${elasticsearch.version}"/>
<attribute name="spawn" default="true"/>
<attribute name="args" default="${integ.args}"/>
<attribute name="es.unicast.enabled" default="false"/>
<attribute name="es.unicast.hosts" default=""/>
<attribute name="es.cluster.name" default="${integ.cluster.name}"/>
<attribute name="es.http.port" default="${integ.http.port}"/>
<attribute name="es.transport.tcp.port" default="${integ.transport.port}"/>
<attribute name="es.pidfile" default="${integ.pidfile}"/>
<attribute name="jvm.args" default="${tests.jvm.argline}"/>
<element name="nestedA" optional="true"/>
<sequential>
<!-- run bin/elasticsearch with args -->
<echo>Starting up external cluster...</echo>
<run-script script="@{home}/bin/elasticsearch"
spawn="@{spawn}">
<nested>
<env key="JAVA_HOME" value="${java.home}"/>
<!-- we pass these as gc options, even if they arent, to avoid conflicting gc options -->
<env key="ES_GC_OPTS" value="@{jvm.args}"/>
<arg value="-Des.cluster.name=@{es.cluster.name}"/>
<arg value="-Des.http.port=@{es.http.port}"/>
<arg value="-Des.transport.tcp.port=@{es.transport.tcp.port}"/>
<arg value="-Des.pidfile=@{es.pidfile}"/>
<arg value="-Des.discovery.zen.ping.unicast.enabled=@{es.unicast.enabled}"/>
<arg value="-Des.discovery.zen.ping.unicast.hosts=@{es.unicast.hosts}"/>
<arg value="-Des.path.repo=@{home}/repo"/>
<arg value="-Des.discovery.zen.ping.multicast.enabled=false"/>
<arg value="-Des.script.inline=on"/>
<arg value="-Des.script.indexed=on"/>
<arg value="-Des.repositories.url.allowed_urls=http://snapshot.test*"/>
<arg value="-Des.http.cors.enabled=true"/>
<arg value="-Des.http.cors.allow-origin=*"/>
<nestedA/>
</nested>
</run-script>
<!-- wait for startup -->
<local name="failed.to.start"/>
<waitfor-elasticsearch port="@{es.http.port}"
timeoutproperty="failed.to.start"/>
<!-- best effort, print console log. useful if it fails especially -->
<local name="log.contents"/>
<loadfile srcFile="@{home}/logs/@{es.cluster.name}.log"
property="log.contents"
failonerror="false"/>
<echo message="${log.contents}" taskname="elasticsearch"/>
<fail message="ES instance did not start" if="failed.to.start"/>
<local name="integ.pid"/>
<extract-pid file="@{es.pidfile}" property="integ.pid"/>
<echo>External node started PID ${integ.pid}</echo>
</sequential>
</macrodef>
<target name="start-external-cluster-with-watcher-and-shield" depends="setup-workspace">
<ac:for list="${xplugins.list}" param="xplugin.name">
<sequential>
<fail message="Expected @{xplugin.name}-${version}.zip as a dependency, but could not be found in ${integ.deps}/plugins}">
<condition>
<not>
<available file="${integ.deps}/plugins/@{xplugin.name}-${elasticsearch.version}.zip" />
</not>
</condition>
</fail>
</sequential>
</ac:for>
<ac:for param="file">
<path>
<fileset dir="${integ.deps}/plugins"/>
</path>
<sequential>
<local name="plugin.name"/>
<convert-plugin-name file="@{file}" outputproperty="plugin.name"/>
<install-plugin name="${plugin.name}" file="@{file}"/>
</sequential>
</ac:for>
<local name="home"/>
<property name="home" location="${integ.scratch}/elasticsearch-${elasticsearch.version}"/>
<echo>Adding roles.yml with watcher roles</echo>
<copy file="watcher-with-shield-roles.yml" tofile="${home}/config/shield/roles.yml" overwrite="true"/>
<echo>Adding shield users...</echo>
<run-script script="${home}/bin/shield/esusers">
<nested>
<arg value="useradd"/>
<arg value="test_admin"/>
<arg value="-p"/>
<arg value="changeme"/>
<arg value="-r"/>
<arg value="admin"/>
</nested>
</run-script>
<run-script script="${home}/bin/shield/esusers">
<nested>
<arg value="useradd"/>
<arg value="watcher_manager"/>
<arg value="-p"/>
<arg value="changeme"/>
<arg value="-r"/>
<arg value="watcher_manager"/>
</nested>
</run-script>
<run-script script="${home}/bin/shield/esusers">
<nested>
<arg value="useradd"/>
<arg value="powerless_user"/>
<arg value="-p"/>
<arg value="changeme"/>
<arg value="-r"/>
<arg value="crapy_role"/>
</nested>
</run-script>
<startup-elasticsearch />
<echo>Checking we can connect with basic auth on port ${integ.http.port}...</echo>
<local name="temp.file"/>
<tempfile property="temp.file" destdir="${java.io.tmpdir}"/>
<get src="http://127.0.0.1:${integ.http.port}" dest="${temp.file}"
username="test_admin" password="changeme" verbose="true" retries="10"/>
</target>
</project>

View File

@ -0,0 +1,216 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ ELASTICSEARCH CONFIDENTIAL
~ __________________
~
~ [2014] Elasticsearch Incorporated. All Rights Reserved.
~
~ NOTICE: All information contained herein is, and remains
~ the property of Elasticsearch Incorporated and its suppliers,
~ if any. The intellectual and technical concepts contained
~ herein are proprietary to Elasticsearch Incorporated
~ and its suppliers and may be covered by U.S. and Foreign Patents,
~ patents in process, and are protected by trade secret or copyright law.
~ Dissemination of this information or reproduction of this material
~ is strictly forbidden unless prior written permission is obtained
~ from Elasticsearch Incorporated.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.elasticsearch.qa</groupId>
<artifactId>x-plugins-qa</artifactId>
<version>2.0.0-beta1-SNAPSHOT</version>
</parent>
<artifactId>smoke-test-watcher-with-shield</artifactId>
<name>QA: Smoke Test Watcher's Shield integration</name>
<description>Installs Watcher and Shield and runs Watcher's rest tests and checks if the Shield integrations work correctly</description>
<properties>
<skip.unit.tests>true</skip.unit.tests>
<elasticsearch.integ.antfile>${project.basedir}/integration-tests.xml</elasticsearch.integ.antfile>
<tests.rest.load_packaged>false</tests.rest.load_packaged>
<xplugins.list>elasticsearch-license,elasticsearch-shield,elasticsearch-watcher</xplugins.list>
<tests.rest.blacklist>hijack/10_basic/*</tests.rest.blacklist>
</properties>
<dependencies>
<dependency>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>elasticsearch-shield</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>elasticsearch-watcher</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>elasticsearch-license</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<testResources>
<!-- Watcher REST API specification and test suites -->
<testResource>
<directory>../../watcher/rest-api-spec</directory>
<filtering>true</filtering>
<targetPath>rest-api-spec</targetPath>
<includes>
<include>api/*.json</include>
<include>test/**/*.yaml</include>
</includes>
</testResource>
<!-- REST API specifications copied from main Elasticsearch specs
because they are required to execute the Watcher REST tests -->
<testResource>
<directory>${elasticsearch.tools.directory}/rest-api-spec</directory>
<targetPath>rest-api-spec</targetPath>
<includes>
<!-- required by the test framework -->
<include>api/info.json</include>
<include>api/cluster.health.json</include>
<include>api/cluster.state.json</include>
<!-- used by Watcher REST tests -->
<include>api/index.json</include>
<include>api/get.json</include>
<include>api/delete.json</include>
<include>api/delete-by-query.json</include>
<include>api/bulk.json</include>
<include>api/update.json</include>
<include>api/search.json</include>
<include>api/indices.delete.json</include>
<include>api/indices.refresh.json</include>
</includes>
</testResource>
</testResources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>integ-setup-dependencies</id>
<phase>pre-integration-test</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<skip>${skip.integ.tests}</skip>
<useBaseVersion>true</useBaseVersion>
<outputDirectory>${integ.deps}/plugins</outputDirectory>
<artifactItems>
<!-- elasticsearch distribution -->
<artifactItem>
<groupId>org.elasticsearch.distribution.zip</groupId>
<artifactId>elasticsearch</artifactId>
<version>${elasticsearch.version}</version>
<type>zip</type>
<overWrite>true</overWrite>
<outputDirectory>${integ.deps}</outputDirectory>
</artifactItem>
<!-- commercial plugins -->
<artifactItem>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>elasticsearch-license</artifactId>
<version>${elasticsearch.version}</version>
<type>zip</type>
<overWrite>true</overWrite>
</artifactItem>
<artifactItem>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>elasticsearch-watcher</artifactId>
<version>${elasticsearch.version}</version>
<type>zip</type>
<overWrite>true</overWrite>
</artifactItem>
<artifactItem>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>elasticsearch-shield</artifactId>
<version>${elasticsearch.version}</version>
<type>zip</type>
<overWrite>true</overWrite>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<!-- integration tests -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<!-- start up external cluster -->
<execution>
<id>integ-setup</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<ant antfile="${elasticsearch.integ.antfile}" target="start-external-cluster-with-watcher-and-shield">
<property name="tests.jvm.argline" value="${tests.jvm.argline}"/>
<property name="plugins.dir" value="${plugins.dir}"/>
<property name="xplugins.list" value="${xplugins.list}"/>
</ant>
</target>
<skip>${skip.integ.tests}</skip>
</configuration>
</execution>
<!-- shut down external cluster -->
<execution>
<id>integ-teardown</id>
<phase>post-integration-test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<ant antfile="${elasticsearch.integ.antfile}" target="stop-external-cluster"/>
</target>
<skip>${skip.integ.tests}</skip>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>ant-contrib</groupId>
<artifactId>ant-contrib</artifactId>
<version>1.0b3</version>
<exclusions>
<exclusion>
<groupId>ant</groupId>
<artifactId>ant</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant-nodeps</artifactId>
<version>1.8.1</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,91 @@
/*
* 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.apache.http.client.methods.HttpPut;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
import org.elasticsearch.client.support.Headers;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.plugin.LicensePlugin;
import org.elasticsearch.shield.ShieldPlugin;
import org.elasticsearch.shield.authc.support.SecuredString;
import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import org.elasticsearch.watcher.WatcherPlugin;
import org.junit.After;
import org.junit.Before;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.URI;
import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
public class WatcherWithShieldIT extends ESRestTestCase {
private final static String TEST_ADMIN_USERNAME = "test_admin";
private final static String TEST_ADMIN_PASSWORD = "changeme";
public WatcherWithShieldIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
}
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
}
@Before
public void startWatcher() throws Exception {
try(CloseableHttpClient client = HttpClients.createMinimal(new BasicHttpClientConnectionManager())) {
InetSocketAddress address = cluster().httpAddresses()[0];
HttpPut request = new HttpPut(new URI("http", null, address.getAddress().getHostAddress(), address.getPort(), "/_watcher/_start", null, null));
String token = basicAuthHeaderValue(TEST_ADMIN_USERNAME, new SecuredString(TEST_ADMIN_PASSWORD.toCharArray()));
request.addHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, token);
client.execute(request);
}
}
@After
public void stopWatcher() throws Exception {
try(CloseableHttpClient client = HttpClients.createMinimal(new BasicHttpClientConnectionManager())) {
InetSocketAddress address = cluster().httpAddresses()[0];
HttpPut request = new HttpPut(new URI("http", null, address.getAddress().getHostAddress(), address.getPort(), "/_watcher/_stop", null, null));
String token = basicAuthHeaderValue(TEST_ADMIN_USERNAME, new SecuredString(TEST_ADMIN_PASSWORD.toCharArray()));
request.addHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, token);
client.execute(request);
}
}
@Override
protected Settings restClientSettings() {
String[] credentials = getCredentials();
String token = basicAuthHeaderValue(credentials[0], new SecuredString(credentials[1].toCharArray()));
return Settings.builder()
.put(Headers.PREFIX + ".Authorization", token)
.build();
}
@Override
protected Settings externalClusterClientSettings() {
return Settings.builder()
.put("shield.user", TEST_ADMIN_USERNAME + ":" + TEST_ADMIN_PASSWORD)
.put("plugin.types", WatcherPlugin.class.getName() + "," + ShieldPlugin.class.getName() + "," + LicensePlugin.class.getName())
.build();
}
protected String[] getCredentials() {
return new String[]{"watcher_manager", "changeme"};
}
}

View File

@ -0,0 +1,40 @@
/*
* 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 org.elasticsearch.test.rest.RestTestCandidate;
import org.junit.Test;
import java.io.IOException;
import static org.hamcrest.Matchers.anyOf;
import static org.hamcrest.Matchers.containsString;
public class WatcherWithShieldInsufficientRoleIT extends WatcherWithShieldIT {
public WatcherWithShieldInsufficientRoleIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
}
@Test
public void test() throws IOException {
try {
super.test();
fail();
} catch(AssertionError ae) {
assertThat(ae.getMessage(), anyOf(containsString("action [cluster:monitor/watcher/"), containsString("action [cluster:admin/watcher/")));
assertThat(ae.getMessage(), containsString("returned [403 Forbidden]"));
assertThat(ae.getMessage(), containsString("is unauthorized for user [powerless_user]"));
}
}
@Override
protected String[] getCredentials() {
return new String[]{"powerless_user", "changeme"};
}
}

View File

@ -0,0 +1,110 @@
admin:
cluster: all
indices:
'*': all
# monitoring cluster privileges
# All operations on all indices
power_user:
cluster: monitor
indices:
'*': all
# Read-only operations on indices
user:
indices:
'*': read
# Defines the required permissions for transport clients
transport_client:
cluster:
- cluster:monitor/nodes/info
#uncomment the following for sniffing
#- cluster:monitor/state
# The required role for kibana 3 users
kibana3:
cluster: cluster:monitor/nodes/info
indices:
'*': indices:data/read/search, indices:data/read/get, indices:admin/get
'kibana-int': indices:data/read/search, indices:data/read/get, indices:data/write/delete, indices:data/write/index, create_index
# The required permissions for kibana 4 users.
kibana4:
cluster:
- cluster:monitor/nodes/info
- cluster:monitor/health
indices:
'*':
- indices:admin/mappings/fields/get
- indices:admin/validate/query
- indices:data/read/search
- indices:data/read/msearch
- indices:admin/get
'.kibana':
- indices:admin/exists
- indices:admin/mapping/put
- indices:admin/mappings/fields/get
- indices:admin/refresh
- indices:admin/validate/query
- indices:data/read/get
- indices:data/read/mget
- indices:data/read/search
- indices:data/write/delete
- indices:data/write/index
- indices:data/write/update
- indices:admin/create
# The required permissions for the kibana 4 server
kibana4_server:
cluster:
- cluster:monitor/nodes/info
- cluster:monitor/health
indices:
'.kibana':
- indices:admin/exists
- indices:admin/mapping/put
- indices:admin/mappings/fields/get
- indices:admin/refresh
- indices:admin/validate/query
- indices:data/read/get
- indices:data/read/mget
- indices:data/read/search
- indices:data/write/delete
- indices:data/write/index
- indices:data/write/update
# The required role for logstash users
logstash:
cluster: indices:admin/template/get, indices:admin/template/put
indices:
'logstash-*': indices:data/write/bulk, indices:data/write/delete, indices:data/write/update, indices:data/read/search, indices:data/read/scroll, create_index
# Marvel role, allowing all operations
# on the marvel indices
marvel_user:
cluster: cluster:monitor/nodes/info, cluster:admin/plugin/license/get
indices:
'.marvel-*': all
# Marvel Agent users
marvel_agent:
cluster: indices:admin/template/get, indices:admin/template/put
indices:
'.marvel-*': indices:data/write/bulk, create_index
watcher_manager:
cluster: manage_watcher, cluster:monitor/nodes/info, cluster:monitor/health
indices:
'.watch_history-*': all
watcher_monitor:
cluster: monitor_watcher
indices:
'.watch_history-*': read
crapy_role:
cluster:
- cluster:monitor/nodes/info
- cluster:monitor/health
- cluster:monitor/nodes/liveness

View File

@ -24,7 +24,7 @@
<elasticsearch.integ.antfile>dev-tools/integration-tests.xml</elasticsearch.integ.antfile>
<tests.rest.load_packaged>false</tests.rest.load_packaged>
<tests.timewarp>true</tests.timewarp>
<tests.rest.blacklist>hijack/10_basic/*,getting_started/10_monitor_cluster_health/*</tests.rest.blacklist>
<tests.rest.blacklist>hijack/10_basic/*</tests.rest.blacklist>
</properties>
<dependencies>
@ -144,6 +144,17 @@
<include>api/indices.refresh.json</include>
</includes>
</testResource>
<!-- REST API specification and test suites -->
<!-- Copied this from plugins parent module, because filtering needs to be enabled -->
<testResource>
<directory>${project.basedir}/rest-api-spec</directory>
<targetPath>rest-api-spec</targetPath>
<filtering>true</filtering>
<includes>
<include>api/*.json</include>
<include>test/**/*.yaml</include>
</includes>
</testResource>
</testResources>
<plugins>
<plugin>

View File

@ -7,9 +7,7 @@
- do: {watcher.stats:{}}
- match: { "watcher_state": "started" }
# - match: { "watch_count": 0 }
# Unfortunately we need to find a good way of starting and stopping watcher between tests for the different use cases (tests and integ tests)
- match: { "watch_count": 0 }
- do:
watcher.put_watch:
@ -25,11 +23,11 @@
"http": {
"request": {
"host": "localhost",
"port": 9400,
"port": ${integ.http.port},
"path": "/_cluster/health",
"auth" : {
"basic" : {
"username" : "admin",
"username" : "test_admin",
"password" : "changeme"
}
}
@ -54,8 +52,8 @@
- match: { _id: "cluster_health_watch" }
- match: { created: true }
# - do: {watcher.stats:{}}
# - match: { "watch_count": 1 }
- do: {watcher.stats:{}}
- match: { "watch_count": 1 }
# Simulate a Thread.sleep()
- do:
@ -102,5 +100,5 @@
- match: { found: true }
# - do: {watcher.stats:{}}
# - match: { "watch_count": 0 }
- do: {watcher.stats:{}}
- match: { "watch_count": 0 }

View File

@ -1,61 +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.watcher.test.rest;
import com.carrotsearch.randomizedtesting.annotations.Name;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.watcher.license.LicenseIntegrationTests;
import org.elasticsearch.watcher.license.LicenseIntegrationTests.MockLicenseService;
import org.junit.Test;
import java.io.IOException;
import static org.hamcrest.Matchers.containsString;
/**
*/
public class WatcherDisabledLicenseRestTests extends WatcherRestTests {
@Override
protected Class<? extends Plugin> licensePluginClass() {
return LicenseIntegrationTests.MockLicensePlugin.class;
}
public WatcherDisabledLicenseRestTests(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
}
@Test
public void test() throws IOException {
try {
disableLicensing();
super.test();
fail();
} catch(AssertionError e) {
assertThat(e.getMessage(), containsString("license expired for feature [watcher]"));
} finally {
enableLicensing();
}
}
public static void disableLicensing() {
for (MockLicenseService service : internalCluster().getInstances(MockLicenseService.class)) {
service.disable();
}
}
public static void enableLicensing() {
for (MockLicenseService service : internalCluster().getInstances(MockLicenseService.class)) {
service.enable();
}
}
@Override
protected boolean enableShield() {
return false;
}
}

View File

@ -8,14 +8,10 @@ package org.elasticsearch.watcher.test.rest;
import org.elasticsearch.test.rest.RestTestCandidate;
/** Runs rest tests against external cluster */
public class WatcherRestIT extends WatcherRestTests {
public class WatcherRestIT extends WatcherRestTestCase {
public WatcherRestIT(RestTestCandidate testCandidate) {
super(testCandidate);
}
@Override
protected boolean enableShield() {
return false;
}
}

View File

@ -0,0 +1,82 @@
/*
* 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.watcher.test.rest;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.plugin.LicensePlugin;
import org.elasticsearch.node.Node;
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
import org.elasticsearch.test.junit.annotations.TestLogging;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import org.elasticsearch.watcher.WatcherPlugin;
import org.junit.After;
import org.junit.Before;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.URI;
import static org.elasticsearch.test.ESIntegTestCase.Scope.SUITE;
@ESRestTestCase.Rest
@ClusterScope(scope = SUITE, numClientNodes = 1, transportClientRatio = 0, numDataNodes = 1, randomDynamicTemplates = false)
@TestLogging("_root:DEBUG")
public abstract class WatcherRestTestCase extends ESRestTestCase {
public WatcherRestTestCase(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
}
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
}
@Before
public void startWatcher() throws Exception {
try(CloseableHttpClient client = HttpClients.createMinimal(new BasicHttpClientConnectionManager())) {
InetSocketAddress address = cluster().httpAddresses()[0];
HttpPut request = new HttpPut(new URI("http", null, address.getAddress().getHostAddress(), address.getPort(), "/_watcher/_start", null, null));
client.execute(request);
}
}
@After
public void stopWatcher() throws Exception {
try(CloseableHttpClient client = HttpClients.createMinimal(new BasicHttpClientConnectionManager())) {
InetSocketAddress address = cluster().httpAddresses()[0];
HttpPut request = new HttpPut(new URI("http", null, address.getAddress().getHostAddress(), address.getPort(), "/_watcher/_stop", null, null));
client.execute(request);
}
}
@Override
protected Settings nodeSettings(int nodeOrdinal) {
return Settings.builder()
.put(super.nodeSettings(nodeOrdinal))
.put("plugin.types", WatcherPlugin.class.getName() + "," + LicensePlugin.class.getName())
.put(Node.HTTP_ENABLED, true)
.build();
}
@Override
protected Settings transportClientSettings() {
return Settings.builder()
.put(Node.HTTP_ENABLED, true)
.put("plugin.types", WatcherPlugin.class.getName() + "," + LicensePlugin.class.getName())
.build();
}
}

View File

@ -1,171 +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.watcher.test.rest;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
import org.elasticsearch.client.support.Headers;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.plugin.LicensePlugin;
import org.elasticsearch.node.Node;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.shield.ShieldPlugin;
import org.elasticsearch.shield.authc.esusers.ESUsersRealm;
import org.elasticsearch.shield.authc.support.Hasher;
import org.elasticsearch.shield.authc.support.SecuredString;
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
import org.elasticsearch.test.junit.annotations.TestLogging;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import org.elasticsearch.watcher.WatcherPlugin;
import org.elasticsearch.watcher.test.AbstractWatcherIntegrationTests;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
import static org.elasticsearch.test.ESIntegTestCase.Scope.SUITE;
@ESRestTestCase.Rest
@ClusterScope(scope = SUITE, numClientNodes = 1, transportClientRatio = 0, numDataNodes = 1, randomDynamicTemplates = false)
@TestLogging("_root:DEBUG")
public class WatcherRestTests extends ESRestTestCase {
final boolean shieldEnabled = enableShield();
public WatcherRestTests(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
}
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
}
protected boolean enableShield() {
return randomBoolean();
}
@Override
protected Settings nodeSettings(int nodeOrdinal) {
return Settings.builder()
.put(super.nodeSettings(nodeOrdinal))
.put("scroll.size", randomIntBetween(1, 100))
.put("plugin.types", WatcherPlugin.class.getName() + ","
+ (shieldEnabled ? ShieldPlugin.class.getName() + "," : "")
+ "," + licensePluginClass().getName())
.put(Node.HTTP_ENABLED, true)
.put("http.netty.port", "9400-9500") // at least matches with integ.http.port property
.put("transport.tcp.port", "9500-9600") // at least matches with integ.transport.port property
.put(ShieldSettings.settings(shieldEnabled))
.build();
}
protected Class<? extends Plugin> licensePluginClass() {
return LicensePlugin.class;
}
/**
* Used to obtain settings for the REST client that is used to send REST requests.
*/
@Override
protected Settings restClientSettings() {
if (shieldEnabled) {
String token = basicAuthHeaderValue("admin", new SecuredString("changeme".toCharArray()));
return Settings.builder()
.put(Headers.PREFIX + ".Authorization", token)
.build();
} else {
return Settings.EMPTY;
}
}
@Override
protected Settings transportClientSettings() {
if (shieldEnabled) {
return Settings.builder()
.put(super.transportClientSettings())
.put("client.transport.sniff", false)
.put("plugin.types", WatcherPlugin.class.getName() + ","
+ (shieldEnabled ? ShieldPlugin.class.getName() + "," : ""))
.put("shield.user", "admin:changeme")
.put(Node.HTTP_ENABLED, true)
.build();
}
return Settings.builder()
.put("plugin.types", WatcherPlugin.class.getName())
.put(Node.HTTP_ENABLED, true)
.put("plugin.types", WatcherPlugin.class.getName() + ","
+ "," + LicensePlugin.class.getName())
.build();
}
/** Shield related settings */
public static class ShieldSettings {
public static final String IP_FILTER = "allow: all\n";
public static final String TEST_USERNAME = "test";
public static final String TEST_PASSWORD = "changeme";
private static final String TEST_PASSWORD_HASHED = new String(Hasher.BCRYPT.hash(new SecuredString(TEST_PASSWORD.toCharArray())));
public static final String USERS =
"transport_client:" + TEST_PASSWORD_HASHED + "\n" +
TEST_USERNAME + ":" + TEST_PASSWORD_HASHED + "\n" +
"admin:" + TEST_PASSWORD_HASHED + "\n" +
"monitor:" + TEST_PASSWORD_HASHED;
public static final String USER_ROLES = "test:test\n" +
"admin:admin\n" +
"monitor:monitor";
public static final String ROLES =
"test:\n" + // a user for the test infra.
" cluster: cluster:monitor/state, cluster:monitor/health, indices:admin/template/delete, cluster:admin/repository/delete, cluster:monitor/nodes/liveness, indices:admin/template/put, cluster:admin/delete\n" +
" indices:\n" +
" '*': all\n" +
"\n" +
"admin:\n" +
" cluster: manage_watcher, cluster:monitor/nodes/info, cluster:monitor/state, cluster:monitor/nodes/liveness, cluster:monitor/health, cluster:admin/repository/delete, cluster:admin/repository/put, indices:admin/template/put, indices:admin/template/get, cluster:monitor/nodes/stats, cluster:admin/reroute, cluster:admin/analyze, cluster:monitor/task, cluster:admin/repository/verify, cluster:admin/repository/get\n" +
" indices:\n" +
" '*': all, indices:admin/template/delete\n" +
"\n" +
"monitor:\n" +
" cluster: monitor_watcher, cluster:monitor/nodes/info, cluster:monitor/nodes/liveness\n" +
"\n"
;
public static Settings settings(boolean enabled) {
Settings.Builder builder = Settings.builder();
if (!enabled) {
return builder.put("shield.enabled", false).build();
}
try {
Path folder = createTempDir().resolve("watcher_shield");
Files.createDirectories(folder);
return builder.put("shield.enabled", true)
.put("shield.user", "test:changeme")
.put("shield.authc.realms.esusers.type", ESUsersRealm.TYPE)
.put("shield.authc.realms.esusers.order", 0)
.put("shield.authc.realms.esusers.files.users", AbstractWatcherIntegrationTests.ShieldSettings.writeFile(folder, "users", USERS))
.put("shield.authc.realms.esusers.files.users_roles", AbstractWatcherIntegrationTests.ShieldSettings.writeFile(folder, "users_roles", USER_ROLES))
.put("shield.authz.store.files.roles", AbstractWatcherIntegrationTests.ShieldSettings.writeFile(folder, "roles.yml", ROLES))
.put("shield.transport.n2n.ip_filter.file", AbstractWatcherIntegrationTests.ShieldSettings.writeFile(folder, "ip_filter.yml", IP_FILTER))
.put("shield.audit.enabled", true)
.build();
} catch (IOException ex) {
throw new RuntimeException("failed to build settings for shield", ex);
}
}
}
}

View File

@ -1,51 +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.watcher.test.rest;
import com.carrotsearch.randomizedtesting.annotations.Name;
import org.elasticsearch.client.support.Headers;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.shield.authc.support.SecuredString;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.junit.Test;
import java.io.IOException;
import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
import static org.hamcrest.Matchers.containsString;
/**
*/
public class WatcherShieldAuthorizationFailedRestTests extends WatcherRestTests {
@Override
protected boolean enableShield() {
return true; // Always run with Shield enabled:
}
public WatcherShieldAuthorizationFailedRestTests(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
}
@Test
public void test() throws IOException {
try {
super.test();
fail();
} catch(AssertionError ae) {
assertThat(ae.getMessage(), containsString("returned [403 Forbidden]"));
assertThat(ae.getMessage(), containsString("is unauthorized for user [test]"));
}
}
@Override
protected Settings restClientSettings() {
String token = basicAuthHeaderValue("test", new SecuredString("changeme".toCharArray()));
return Settings.builder()
.put(Headers.PREFIX + ".Authorization", token)
.build();
}
}