Tests: Smoke tests with SSL enabled.

We should smoke test our plugins with ssl enabled to make sure that plugins
still work together and eg. Marvel still manages to export stats.

Close elastic/elasticsearch#402

Original commit: elastic/x-pack-elasticsearch@3bb7c2b96c
This commit is contained in:
Adrien Grand 2015-08-11 18:03:07 +02:00
parent 2842898c1c
commit cd5169745d
7 changed files with 652 additions and 1 deletions

View File

@ -319,5 +319,6 @@
<modules> <modules>
<module>smoke-test-plugins</module> <module>smoke-test-plugins</module>
<module>smoke-test-plugins-ssl</module>
</modules> </modules>
</project> </project>

View File

@ -0,0 +1,90 @@
<?xml version="1.0"?>
<project name="smoke-test-x-plugins-ssl"
xmlns:ac="antlib:net.sf.antcontrib">
<import file="${elasticsearch.integ.antfile.default}"/>
<property name="home" location="${integ.scratch}/elasticsearch-${elasticsearch.version}"/>
<!-- 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>
<target name="start-external-cluster-with-plugins" 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>
<echo>Setting up Shield auth</echo>
<run-script script="${home}/bin/shield/esusers">
<nested>
<arg value="useradd"/>
<arg value="test_user"/>
<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="marvel_export"/>
<arg value="-p"/>
<arg value="changeme"/>
<arg value="-r"/>
<arg value="marvel_agent"/>
</nested>
</run-script>
<copy file="${keystore.path}" todir="${home}/config/"/> <!-- move to a dir that the security manager will be happy with -->
<startup-elasticsearch>
<additional-args>
<arg value="-Des.marvel.agent.exporter.es.hosts=https://marvel_export:changeme@localhost:${integ.http.port}"/>
<arg value="-Des.marvel.agent.exporter.es.ssl.truststore.path=${home}/config/test-node.jks"/>
<arg value="-Des.marvel.agent.exporter.es.ssl.truststore.password=keypass"/>
<arg value="-Des.shield.transport.ssl=true"/>
<arg value="-Des.shield.http.ssl=true"/>
<arg value="-Des.shield.ssl.keystore.path=${home}/config/test-node.jks"/>
<arg value="-Des.shield.ssl.keystore.password=keypass"/>
<arg value="-Des.discovery.zen.ping.multicast.enabled=false"/>
</additional-args>
</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}"/>
<!-- TODO: how to make the get task take a non-default keystore? -->
<!--<get src="https://127.0.0.1:${integ.http.port}" dest="${temp.file}"
username="test_user" password="changeme" verbose="true" retries="10"/>-->
</target>
</project>

View File

@ -0,0 +1,287 @@
<?xml version="1.0" encoding="UTF-8"?>
<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>
<!--
This test unzips elasticsearch, installs each plugin,
starts elasticsearch, verifies loaded plugin count.
-->
<artifactId>smoke-test-x-plugins-ssl</artifactId>
<name>QA: Smoke Test X-Plugins</name>
<description>Loads up all of our commercial and open-source plugins with ssl enabled</description>
<properties>
<skip.unit.tests>true</skip.unit.tests>
<elasticsearch.integ.antfile>${project.basedir}/integration-tests.xml</elasticsearch.integ.antfile>
<tests.rest.suite>smoke_test_plugins_ssl</tests.rest.suite>
<tests.rest.load_packaged>false</tests.rest.load_packaged>
<xplugins.list>elasticsearch-license,elasticsearch-marvel,elasticsearch-shield,elasticsearch-watcher</xplugins.list>
<ssl.antfile>${project.basedir}/ssl-setup.xml</ssl.antfile>
<keystore.path>${project.build.outputDirectory}/test-node.jks</keystore.path>
</properties>
<dependencies>
<dependency>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>elasticsearch-shield</artifactId>
<version>2.0.0-beta1-SNAPSHOT</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<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>
<artifactItem>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>elasticsearch-marvel</artifactId>
<version>${elasticsearch.version}</version>
<type>zip</type>
<overWrite>true</overWrite>
</artifactItem>
<!-- open-source plugins -->
<artifactItem>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>elasticsearch-analysis-kuromoji</artifactId>
<version>${elasticsearch.version}</version>
<type>zip</type>
<overWrite>true</overWrite>
</artifactItem>
<artifactItem>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>elasticsearch-analysis-smartcn</artifactId>
<version>${elasticsearch.version}</version>
<type>zip</type>
<overWrite>true</overWrite>
</artifactItem>
<artifactItem>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>elasticsearch-analysis-stempel</artifactId>
<version>${elasticsearch.version}</version>
<type>zip</type>
<overWrite>true</overWrite>
</artifactItem>
<artifactItem>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>elasticsearch-analysis-phonetic</artifactId>
<version>${elasticsearch.version}</version>
<type>zip</type>
<overWrite>true</overWrite>
</artifactItem>
<artifactItem>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>elasticsearch-analysis-icu</artifactId>
<version>${elasticsearch.version}</version>
<type>zip</type>
<overWrite>true</overWrite>
</artifactItem>
<artifactItem>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>elasticsearch-cloud-gce</artifactId>
<version>${elasticsearch.version}</version>
<type>zip</type>
<overWrite>true</overWrite>
</artifactItem>
<artifactItem>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>elasticsearch-cloud-azure</artifactId>
<version>${elasticsearch.version}</version>
<type>zip</type>
<overWrite>true</overWrite>
</artifactItem>
<artifactItem>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>elasticsearch-cloud-aws</artifactId>
<version>${elasticsearch.version}</version>
<type>zip</type>
<overWrite>true</overWrite>
</artifactItem>
<artifactItem>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>elasticsearch-delete-by-query</artifactId>
<version>${elasticsearch.version}</version>
<type>zip</type>
<overWrite>true</overWrite>
</artifactItem>
<artifactItem>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>elasticsearch-lang-python</artifactId>
<version>${elasticsearch.version}</version>
<type>zip</type>
<overWrite>true</overWrite>
</artifactItem>
<artifactItem>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>elasticsearch-lang-javascript</artifactId>
<version>${elasticsearch.version}</version>
<type>zip</type>
<overWrite>true</overWrite>
</artifactItem>
<artifactItem>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>elasticsearch-mapper-size</artifactId>
<version>${elasticsearch.version}</version>
<type>zip</type>
<overWrite>true</overWrite>
</artifactItem>
<artifactItem>
<groupId>org.elasticsearch.plugin</groupId>
<artifactId>elasticsearch-site-example</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>
<!-- generate certificates/keys -->
<execution>
<id>certificate-setup</id>
<phase>generate-test-resources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<ant antfile="${ssl.antfile}" target="generate-keystore">
</ant>
</target>
<skip>${skip.integ.tests}</skip>
</configuration>
</execution>
<!-- 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-plugins">
<property name="tests.jvm.argline" value="${tests.jvm.argline}"/>
<property name="plugins.dir" value="${plugins.dir}"/>
</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,16 @@
# Integration tests for smoke testing plugins
#
"Plugins are actually installed":
- do:
cluster.state: {}
# Get master node id
- set: { master_node: master }
- do:
nodes.info: {}
- match: { nodes.$master.plugins.11.name: license }
- match: { nodes.$master.plugins.13.name: marvel }
- match: { nodes.$master.plugins.14.name: shield }
- match: { nodes.$master.plugins.16.name: watcher }

View File

@ -0,0 +1,87 @@
/*
* 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 static org.elasticsearch.shield.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.client.support.Headers;
import org.elasticsearch.common.io.PathUtils;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.shield.ShieldPlugin;
import org.elasticsearch.shield.authc.support.SecuredString;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.test.rest.RestTestCandidate;
import org.elasticsearch.test.rest.client.RestClient;
import org.elasticsearch.test.rest.parser.RestTestParseException;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
public class SmokeTestPluginsSslIT extends ESRestTestCase {
private static final String USER = "test_user";
private static final String PASS = "changeme";
private static final String KEYSTORE_PASS = "keypass";
public SmokeTestPluginsSslIT(@Name("yaml") RestTestCandidate testCandidate) {
super(testCandidate);
}
@ParametersFactory
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
return ESRestTestCase.createParameters(0, 1);
}
static Path keyStore;
@BeforeClass
public static void getKeyStore() {
try {
keyStore = PathUtils.get(SmokeTestPluginsSslIT.class.getResource("/test-node.jks").toURI());
} catch (URISyntaxException e) {
throw new ElasticsearchException("exception while reading the store", e);
}
if (!Files.exists(keyStore)) {
throw new IllegalStateException("Keystore file [" + keyStore + "] does not exist.");
}
}
@AfterClass
public static void clearKeyStore() {
keyStore = null;
}
@Override
protected Settings restClientSettings() {
String token = basicAuthHeaderValue(USER, new SecuredString(PASS.toCharArray()));
return Settings.builder()
.put(Headers.PREFIX + ".Authorization", token)
.put(RestClient.PROTOCOL, "https")
.put(RestClient.TRUSTSTORE_PATH, keyStore)
.put(RestClient.TRUSTSTORE_PASSWORD, KEYSTORE_PASS)
.build();
}
@Override
protected Settings externalClusterClientSettings() {
return Settings.builder()
.put("shield.user", USER + ":" + PASS)
.put("shield.transport.ssl", true)
.put("shield.ssl.keystore.path", keyStore)
.put("shield.ssl.keystore.password", KEYSTORE_PASS)
.put("plugin.types", ShieldPlugin.class.getName())
.build();
}
}

View File

@ -0,0 +1,170 @@
<?xml version="1.0"?>
<project name="smoke-test-plugins"
xmlns:ac="antlib:net.sf.antcontrib">
<target name="create-certificate-authority">
<ac:for list="private,certs,conf" param="dir">
<sequential>
<mkdir dir="${integ.scratch}/ca/@{dir}"/>
</sequential>
</ac:for>
<echo file="${integ.scratch}/ca/serial">01</echo>
<touch file="${integ.scratch}/ca/index.txt"/>
<echo file="${integ.scratch}/ca/conf/caconfig.cnf">[ ca ]
default_ca = CA_default
[ CA_default ]
copy_extensions = copy
dir = ${integ.scratch}/ca
serial = $dir/serial
database = $dir/index.txt
new_certs_dir = $dir/certs
certificate = $dir/certs/cacert.pem
private_key = $dir/private/cakey.pem
default_days = 712
default_md = sha256
preserve = no
email_in_dn = no
x509_extensions = v3_ca
name_opt = ca_default
cert_opt = ca_default
policy = policy_anything
[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
default_bits = 2048 # Size of keys
default_keyfile = key.pem # name of generated keys
default_md = sha256 # message digest algorithm
string_mask = nombstr # permitted characters
distinguished_name = req_distinguished_name
req_extensions = v3_req
[ req_distinguished_name ]
# Variable name Prompt string
#------------------------- ----------------------------------
0.organizationName = Organization Name (company)
organizationalUnitName = Organizational Unit Name (department, division)
emailAddress = Email Address
emailAddress_max = 40
localityName = Locality Name (city, district)
stateOrProvinceName = State or Province Name (full name)
countryName = Country Name (2 letter code)
countryName_min = 2
countryName_max = 2
commonName = Common Name (hostname, IP, or your name)
commonName_max = 64
# Default values for the above, for consistency and less typing.
# Variable name Value
#------------------------ ------------------------------
0.organizationName_default = Elasticsearch Test Org
localityName_default = Amsterdam
stateOrProvinceName_default = Amsterdam
countryName_default = NL
emailAddress_default = cacerttest@YOUR.COMPANY.TLD
[ v3_ca ]
basicConstraints = CA:TRUE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
[ v3_req ]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash</echo>
<exec executable="openssl" failonerror="true">
<arg value="req"/>
<arg value="-new"/>
<arg value="-x509"/>
<arg value="-extensions"/>
<arg value="v3_ca"/>
<arg value="-keyout"/>
<arg value="${integ.scratch}/ca/private/cakey.pem"/>
<arg value="-out"/>
<arg value="${integ.scratch}/ca/certs/cacert.pem"/>
<arg value="-days"/>
<arg value="1460"/>
<arg value="-config"/>
<arg value="${integ.scratch}/ca/conf/caconfig.cnf"/>
<arg value="-subj"/>
<arg value="/OU=XPlugins QA"/>
<arg value="-passout"/>
<arg value="pass:capass"/>
</exec>
</target>
<target name="create-key">
<local name="parent.dir"/>
<dirname file="${keystore.path}" property="parent.dir" />
<mkdir dir="${parent.dir}"/>
<exec executable="keytool" failonerror="true"
inputstring="FirstName LastName&#x0A;Unit&#x0A;Organization&#x0A;City&#x0A;State&#x0A;NL&#x0A;yes&#x0A;&#x0A;">
<arg value="-genkey"/>
<arg value="-alias"/>
<arg value="test-node"/>
<arg value="-keystore"/>
<arg value="${keystore.path}"/>
<arg value="-keyalg"/>
<arg value="RSA"/>
<arg value="-keysize"/>
<arg value="2048"/>
<arg value="-validity"/>
<arg value="712"/>
<arg value="-ext"/>
<arg value="san=dns:localhost,ip:127.0.0.1"/>
<arg value="-storepass"/>
<arg value="keypass"/>
</exec>
</target>
<target name="create-certificate" depends="create-key">
<mkdir dir="${integ.scratch}/cert"/>
<exec executable="keytool" failonerror="true"
inputstring="keypass&#x0A;">
<arg value="-certreq"/>
<arg value="-alias"/>
<arg value="test-node"/>
<arg value="-keystore"/>
<arg value="${keystore.path}"/>
<arg value="-file"/>
<arg value="${integ.scratch}/cert/test-node.csr"/>
<arg value="-keyalg"/>
<arg value="RSA"/>
<arg value="-ext"/>
<arg value="san=dns:localhost,ip:127.0.0.1"/>
</exec>
</target>
<target name="sign-certificate" depends="create-certificate,create-certificate-authority">
<exec executable="openssl" failonerror="true"
inputstring="y&#x0A;y&#x0A;">
<arg value="ca"/>
<arg value="-in"/>
<arg value="${integ.scratch}/cert/test-node.csr"/>
<arg value="-notext"/>
<arg value="-out"/>
<arg value="${integ.scratch}/cert/test-node-signed.csr"/>
<arg value="-config"/>
<arg value="${integ.scratch}/ca/conf/caconfig.cnf"/>
<arg value="-extensions"/>
<arg value="v3_req"/>
<arg value="-passin"/>
<arg value="pass:capass"/>
</exec>
</target>
<target name="import-certificate" depends="sign-certificate">
<exec executable="keytool" failonerror="true"
inputstring="keypass&#x0A;yes&#x0A;">
<arg value="-importcert"/>
<arg value="-keystore"/>
<arg value="${keystore.path}"/>
<arg value="-file"/>
<arg value="${integ.scratch}/cert/test-node-signed.csr"/>
<arg value="-trustcacerts"/>
</exec>
</target>
<target name="generate-keystore" depends="import-certificate"/>
</project>

View File

@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<project name="smoke-test-plugins" <project name="smoke-test-x-plugins"
xmlns:ac="antlib:net.sf.antcontrib"> xmlns:ac="antlib:net.sf.antcontrib">
<import file="${elasticsearch.integ.antfile.default}"/> <import file="${elasticsearch.integ.antfile.default}"/>