Merge pull request elastic/elasticsearch#429 from jpountz/enhancement/qa_shield_ssl

Tests: Smoke tests with SSL enabled.

Original commit: elastic/x-pack-elasticsearch@39361caa4b
This commit is contained in:
Adrien Grand 2015-08-12 14:10:06 +02:00
commit 9479569b02
7 changed files with 652 additions and 1 deletions

View File

@ -319,5 +319,6 @@
<modules>
<module>smoke-test-plugins</module>
<module>smoke-test-plugins-ssl</module>
</modules>
</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"?>
<project name="smoke-test-plugins"
<project name="smoke-test-x-plugins"
xmlns:ac="antlib:net.sf.antcontrib">
<import file="${elasticsearch.integ.antfile.default}"/>