diff --git a/qa/build.gradle b/elasticsearch/build.gradle similarity index 100% rename from qa/build.gradle rename to elasticsearch/build.gradle diff --git a/elasticsearch/license/README.md b/elasticsearch/license/README.md new file mode 100644 index 00000000000..37aecd4c25f --- /dev/null +++ b/elasticsearch/license/README.md @@ -0,0 +1,36 @@ +elasticsearch-license +===================== + +Elasticsearch Licensing core, tools and plugin + +## Core + +Contains core data structures, utilities used by **Licensor** and **Plugin**. + +See `core/` and `core-shaded/` + +## Licensor + +Contains a collection of tools to generate key-pairs, licenses and validate licenses. + +See `licensor/` + +see [wiki] (https://github.com/elasticsearch/elasticsearch-license/wiki) for documentation on +[Licensing Tools Usage & Reference] (https://github.com/elasticsearch/elasticsearch-license/wiki/License-Tools-Usage-&-Reference) + +## Plugin + +**NOTE**: The license plugin has to be packaged with the right public key when being deployed to public repositories in maven +or uploaded to s3. Use `-Dkeys.path=` with maven command to package the plugin with a specified key. + +See `plugin/` + +see [Getting Started] (https://github.com/elasticsearch/elasticsearch-license/blob/master/docs/getting-started.asciidoc) to install license plugin. + +see [Licensing REST APIs] (https://github.com/elasticsearch/elasticsearch-license/blob/master/docs/license.asciidoc) +to use the license plugin from an elasticsearch deployment. + +see [wiki] (https://github.com/elasticsearch/elasticsearch-license/wiki) for documentation on + - [License Plugin Consumer Interface] (https://github.com/elasticsearch/elasticsearch-license/wiki/License---Consumer-Interface) + - [License Plugin Release Process] (https://github.com/elasticsearch/elasticsearch-license/wiki/Plugin-Release-Process) + - [License Plugin Design] (https://github.com/elasticsearch/elasticsearch-license/wiki/License-Plugin--Design) diff --git a/elasticsearch/license/base/build.gradle b/elasticsearch/license/base/build.gradle new file mode 100644 index 00000000000..fefabaacf5a --- /dev/null +++ b/elasticsearch/license/base/build.gradle @@ -0,0 +1,13 @@ +apply plugin: 'elasticsearch.build' + +dependencies { + compile "org.elasticsearch:elasticsearch:${version}" + testCompile "org.elasticsearch:test-framework:${version}" +} + +dependencyLicenses.enabled = false + +jar { + baseName = 'license-core' +} + diff --git a/elasticsearch/license/base/src/main/java/org/elasticsearch/license/core/CryptUtils.java b/elasticsearch/license/base/src/main/java/org/elasticsearch/license/core/CryptUtils.java new file mode 100644 index 00000000000..939b5192828 --- /dev/null +++ b/elasticsearch/license/base/src/main/java/org/elasticsearch/license/core/CryptUtils.java @@ -0,0 +1,245 @@ +/* + * 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.license.core; + + +import org.elasticsearch.common.Base64; + +import javax.crypto.*; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.StandardCharsets; +import java.security.*; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; + +public class CryptUtils { + private static final int minimumPadding = 20; + private static final byte[] salt = { + (byte) 0xA9, (byte) 0xA2, (byte) 0xB5, (byte) 0xDE, + (byte) 0x2A, (byte) 0x8A, (byte) 0x9A, (byte) 0xE6 + }; + private static final int iterationCount = 1024; + private static final int aesKeyLength = 128; + private static final String keyAlgorithm = "RSA"; + private static final String passHashAlgorithm = "SHA-512"; + private static final String DEFAULT_PASS_PHRASE = "elasticsearch-license"; + + private static final SecureRandom random = new SecureRandom(); + + /** + * Read encrypted private key file content with default pass phrase + */ + public static PrivateKey readEncryptedPrivateKey(byte[] fileContents) { + try { + return readEncryptedPrivateKey(fileContents, hashPassPhrase(DEFAULT_PASS_PHRASE)); + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException(e); + } + } + + /** + * Read encrypted public key file content with default pass phrase + */ + public static PublicKey readEncryptedPublicKey(byte[] fileContents) { + try { + return readEncryptedPublicKey(fileContents, hashPassPhrase(DEFAULT_PASS_PHRASE)); + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException(e); + } + } + + /** + * Returns encrypted public key file content with default pass phrase + */ + public static byte[] writeEncryptedPublicKey(PublicKey publicKey) { + try { + return writeEncryptedPublicKey(publicKey, hashPassPhrase(DEFAULT_PASS_PHRASE)); + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException(e); + } + } + + /** + * Returns encrypted private key file content with default pass phrase + */ + public static byte[] writeEncryptedPrivateKey(PrivateKey privateKey) { + try { + return writeEncryptedPrivateKey(privateKey, hashPassPhrase(DEFAULT_PASS_PHRASE)); + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException(e); + } + } + + /** + * Read encrypted private key file content with provided passPhrase + */ + public static PrivateKey readEncryptedPrivateKey(byte[] fileContents, char[] passPhrase) { + PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(decrypt(fileContents, passPhrase)); + try { + return KeyFactory.getInstance(keyAlgorithm).generatePrivate(privateKeySpec); + } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { + throw new IllegalStateException(e); + } + } + + /** + * Read encrypted public key file content with provided passPhrase + */ + public static PublicKey readEncryptedPublicKey(byte[] fileContents, char[] passPhrase) { + X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(decrypt(fileContents, passPhrase)); + try { + return KeyFactory.getInstance(CryptUtils.keyAlgorithm).generatePublic(publicKeySpec); + } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { + throw new IllegalStateException(e); + } + } + + /** + * Returns encrypted public key file content with provided passPhrase + */ + public static byte[] writeEncryptedPublicKey(PublicKey publicKey, char[] passPhrase) { + X509EncodedKeySpec encodedKeySpec = new X509EncodedKeySpec(publicKey.getEncoded()); + return encrypt(encodedKeySpec.getEncoded(), passPhrase); + } + + /** + * Returns encrypted private key file content with provided passPhrase + */ + public static byte[] writeEncryptedPrivateKey(PrivateKey privateKey, char[] passPhrase) { + PKCS8EncodedKeySpec encodedKeySpec = new PKCS8EncodedKeySpec(privateKey.getEncoded()); + return encrypt(encodedKeySpec.getEncoded(), passPhrase); + } + + /** + * Encrypts provided data with DEFAULT_PASS_PHRASE + */ + public static byte[] encrypt(byte[] data) { + try { + return encrypt(data, hashPassPhrase(DEFAULT_PASS_PHRASE)); + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException(e); + } + } + + /** + * Decrypts provided encryptedData with DEFAULT_PASS_PHRASE + */ + public static byte[] decrypt(byte[] encryptedData) { + try { + return decrypt(encryptedData, hashPassPhrase(DEFAULT_PASS_PHRASE)); + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException(e); + } + } + + /** + * Encrypts provided data with passPhrase + */ + public static byte[] encrypt(byte[] data, char[] passPhrase) { + try { + final Cipher encryptionCipher = getEncryptionCipher(getSecretKey(passPhrase)); + return encryptionCipher.doFinal(pad(data, minimumPadding)); + } catch (InvalidKeySpecException | IllegalBlockSizeException | BadPaddingException e) { + throw new IllegalStateException(e); + } + } + + /** + * Decrypts provided encryptedData with passPhrase + */ + private static byte[] decrypt(byte[] encryptedData, char[] passPhrase) { + try { + final Cipher cipher = getDecryptionCipher(getSecretKey(passPhrase)); + return unPad(cipher.doFinal(encryptedData)); + } catch (IllegalBlockSizeException | BadPaddingException | InvalidKeySpecException e) { + throw new IllegalStateException(e); + } + + } + + private static SecretKey getSecretKey(char[] passPhrase) throws InvalidKeySpecException { + try { + PBEKeySpec keySpec = new PBEKeySpec(passPhrase, salt, iterationCount, aesKeyLength); + + byte[] shortKey = SecretKeyFactory.getInstance("PBEWithSHA1AndDESede"). + generateSecret(keySpec).getEncoded(); + + byte[] intermediaryKey = new byte[aesKeyLength / 8]; + for (int i = 0, j = 0; i < aesKeyLength / 8; i++) { + intermediaryKey[i] = shortKey[j]; + if (++j == shortKey.length) + j = 0; + } + + return new SecretKeySpec(intermediaryKey, "AES"); + } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { + throw new IllegalStateException(e); + } + } + + private static Cipher getEncryptionCipher(SecretKey secretKey) { + return getCipher(Cipher.ENCRYPT_MODE, secretKey); + } + + private static Cipher getDecryptionCipher(SecretKey secretKey) { + return getCipher(Cipher.DECRYPT_MODE, secretKey); + } + + private static Cipher getCipher(int mode, SecretKey secretKey) { + try { + Cipher cipher = Cipher.getInstance(secretKey.getAlgorithm()); + cipher.init(mode, secretKey, random); + return cipher; + } catch (NoSuchAlgorithmException | InvalidKeyException | NoSuchPaddingException e) { + throw new IllegalStateException(e); + } + } + + private static byte[] pad(byte[] bytes, int length) { + if (bytes.length >= length) { + byte[] out = new byte[bytes.length + 1]; + System.arraycopy(bytes, 0, out, 0, bytes.length); + out[bytes.length] = (byte) 1; + return out; + } + + byte[] out = new byte[length + 1]; + + int i = 0; + for (; i < bytes.length; i++) + out[i] = bytes[i]; + + int padded = length - i; + + // fill the rest with random bytes + byte[] fill = new byte[padded - 1]; + random.nextBytes(fill); + System.arraycopy(fill, 0, out, i, padded - 1); + + out[length] = (byte) (padded + 1); + + return out; + } + + private static byte[] unPad(byte[] bytes) { + int padded = (int) bytes[bytes.length - 1]; + int targetLength = bytes.length - padded; + + byte[] out = new byte[targetLength]; + + System.arraycopy(bytes, 0, out, 0, targetLength); + + return out; + } + + private static char[] hashPassPhrase(String passPhrase) throws NoSuchAlgorithmException { + final byte[] passBytes = passPhrase.getBytes(StandardCharsets.UTF_8); + final byte[] digest = MessageDigest.getInstance(passHashAlgorithm).digest(passBytes); + return new String(Base64.encodeBytesToBytes(digest), StandardCharsets.UTF_8).toCharArray(); + } +} diff --git a/elasticsearch/license/base/src/main/java/org/elasticsearch/license/core/DateUtils.java b/elasticsearch/license/base/src/main/java/org/elasticsearch/license/core/DateUtils.java new file mode 100644 index 00000000000..80b42aa82bf --- /dev/null +++ b/elasticsearch/license/base/src/main/java/org/elasticsearch/license/core/DateUtils.java @@ -0,0 +1,44 @@ +/* + * 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.license.core; + +import org.elasticsearch.common.joda.FormatDateTimeFormatter; +import org.elasticsearch.common.joda.Joda; +import org.joda.time.MutableDateTime; +import org.joda.time.format.DateTimeFormatter; +import org.joda.time.format.ISODateTimeFormat; + +public class DateUtils { + + private final static FormatDateTimeFormatter formatDateOnlyFormatter = Joda.forPattern("yyyy-MM-dd"); + + private final static DateTimeFormatter dateOnlyFormatter = formatDateOnlyFormatter.parser().withZoneUTC(); + + private final static DateTimeFormatter dateTimeFormatter = ISODateTimeFormat.dateTime().withZoneUTC(); + + public static long endOfTheDay(String date) { + try { + // Try parsing using complete date/time format + return dateTimeFormatter.parseDateTime(date).getMillis(); + } catch (IllegalArgumentException ex) { + // Fall back to the date only format + MutableDateTime dateTime = dateOnlyFormatter.parseMutableDateTime(date); + dateTime.millisOfDay().set(dateTime.millisOfDay().getMaximumValue()); + return dateTime.getMillis(); + } + } + + public static long beginningOfTheDay(String date) { + try { + // Try parsing using complete date/time format + return dateTimeFormatter.parseDateTime(date).getMillis(); + } catch (IllegalArgumentException ex) { + // Fall back to the date only format + return dateOnlyFormatter.parseDateTime(date).getMillis(); + } + + } +} diff --git a/elasticsearch/license/base/src/main/java/org/elasticsearch/license/core/License.java b/elasticsearch/license/base/src/main/java/org/elasticsearch/license/core/License.java new file mode 100644 index 00000000000..418a07e524d --- /dev/null +++ b/elasticsearch/license/base/src/main/java/org/elasticsearch/license/core/License.java @@ -0,0 +1,693 @@ +/* + * 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.license.core; + +import org.apache.lucene.util.CollectionUtil; +import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.ElasticsearchParseException; +import org.elasticsearch.common.Base64; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.common.xcontent.*; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Locale; + +/** + * Data structure for license. Use {@link Builder} to build a license. + * Provides serialization/deserialization & validation methods for license object + */ +public class License implements ToXContent { + public final static int VERSION_START = 1; + public final static int VERSION_NO_FEATURE_TYPE = 2; + public final static int VERSION_CURRENT = VERSION_NO_FEATURE_TYPE; + + /** + * XContent param name to deserialize license(s) with + * an additional status field, indicating whether a + * particular license is 'active' or 'expired' and no signature + * and in a human readable format + */ + public static final String REST_VIEW_MODE = "rest_view"; + /** + * XContent param name to deserialize license(s) with + * no signature + */ + public static final String LICENSE_SPEC_VIEW_MODE = "license_spec_view"; + /** + * XContent param name to deserialize licenses according + * to a specific license version + */ + public static final String LICENSE_VERSION_MODE = "license_version"; + + public final static Comparator LATEST_ISSUE_DATE_FIRST = new Comparator() { + @Override + public int compare(License right, License left) { + return Long.compare(left.issueDate(), right.issueDate()); + } + }; + + private final int version; + private final String uid; + private final String issuer; + private final String issuedTo; + private final long issueDate; + private final String type; + private final String subscriptionType; + private final String feature; + private final String signature; + private final long expiryDate; + private final int maxNodes; + private final OperationMode operationMode; + + /** + * Decouples operation mode of a license + * from the license type value + */ + public enum OperationMode { + NONE, + TRIAL, + BASIC, + GOLD, + PLATINUM; + + public static OperationMode resolve(String type) { + switch (type.toLowerCase(Locale.ROOT)) { + case "trial": + case "none": // bwc for 1.x subscription_type field + case "dev": // bwc for 1.x subscription_type field + case "development": // bwc for 1.x subscription_type field + return TRIAL; + case "basic": + return BASIC; + case "silver": + case "gold": + return GOLD; + case "platinum": + case "internal": // bwc for 1.x subscription_type field + return PLATINUM; + default: + throw new IllegalArgumentException("unknown type [" + type + "]"); + } + } + } + + private License(int version, String uid, String issuer, String issuedTo, long issueDate, String type, + String subscriptionType, String feature, String signature, long expiryDate, int maxNodes) { + this.version = version; + this.uid = uid; + this.issuer = issuer; + this.issuedTo = issuedTo; + this.issueDate = issueDate; + this.type = type; + this.subscriptionType = subscriptionType; + this.feature = feature; + this.signature = signature; + this.expiryDate = expiryDate; + this.maxNodes = maxNodes; + if (version == VERSION_START) { + // in 1.x: the acceptable values for 'subscription_type': none | dev | silver | gold | platinum + this.operationMode = OperationMode.resolve(subscriptionType); + } else { + // in 2.x: the acceptable values for 'type': trial | basic | silver | dev | gold | platinum + this.operationMode = OperationMode.resolve(type); + } + validate(); + } + + /** + * @return version of the license + */ + public int version() { + return version; + } + + /** + * @return a unique identifier for a license + */ + public String uid() { + return uid; + } + + /** + * @return type of the license [trial, subscription, internal] + */ + public String type() { + return type; + } + + /** + * @return the issueDate in milliseconds + */ + public long issueDate() { + return issueDate; + } + + /** + * @return the expiry date in milliseconds + */ + public long expiryDate() { + return expiryDate; + } + + /** + * @return the maximum number of nodes this license has been issued for + */ + public int maxNodes() { + return maxNodes; + } + + /** + * @return a string representing the entity this licenses has been issued to + */ + public String issuedTo() { + return issuedTo; + } + + /** + * @return a string representing the entity responsible for issuing this license (internal) + */ + public String issuer() { + return issuer; + } + + /** + * @return a string representing the signature of the license used for license verification + */ + public String signature() { + return signature; + } + + /** + * @return the operation mode of the license as computed from the license type + */ + public OperationMode operationMode() { + return operationMode; + } + + /** + * @return the current license's status + */ + public Status status() { + long now = System.currentTimeMillis(); + if (issueDate > now) { + return Status.INVALID; + } else if (expiryDate < now) { + return Status.EXPIRED; + } + return Status.ACTIVE; + } + + private void validate() { + if (issuer == null) { + throw new IllegalStateException("issuer can not be null"); + } else if (issuedTo == null) { + throw new IllegalStateException("issuedTo can not be null"); + } else if (issueDate == -1) { + throw new IllegalStateException("issueDate has to be set"); + } else if (type == null) { + throw new IllegalStateException("type can not be null"); + } else if (subscriptionType == null && version == VERSION_START) { + throw new IllegalStateException("subscriptionType can not be null"); + } else if (uid == null) { + throw new IllegalStateException("uid can not be null"); + } else if (feature == null && version == VERSION_START) { + throw new IllegalStateException("feature can not be null"); + } else if (maxNodes == -1) { + throw new IllegalStateException("maxNodes has to be set"); + } else if (expiryDate == -1) { + throw new IllegalStateException("expiryDate has to be set"); + } + } + + public static License readLicense(StreamInput in) throws IOException { + int version = in.readVInt(); // Version for future extensibility + if (version > VERSION_CURRENT) { + throw new ElasticsearchException("Unknown license version found, please upgrade all nodes to the latest elasticsearch-license plugin"); + } + Builder builder = builder(); + builder.version(version); + builder.uid(in.readString()); + builder.type(in.readString()); + if (version == VERSION_START) { + builder.subscriptionType(in.readString()); + } + builder.issueDate(in.readLong()); + if (version == VERSION_START) { + builder.feature(in.readString()); + } + builder.expiryDate(in.readLong()); + builder.maxNodes(in.readInt()); + builder.issuedTo(in.readString()); + builder.issuer(in.readString()); + builder.signature(in.readOptionalString()); + return builder.build(); + } + + public void writeTo(StreamOutput out) throws IOException { + out.writeVInt(version); + out.writeString(uid); + out.writeString(type); + if (version == VERSION_START) { + out.writeString(subscriptionType); + } + out.writeLong(issueDate); + if (version == VERSION_START) { + out.writeString(feature); + } + out.writeLong(expiryDate); + out.writeInt(maxNodes); + out.writeString(issuedTo); + out.writeString(issuer); + out.writeOptionalString(signature); + } + + @Override + public String toString() { + try { + final XContentBuilder builder = XContentFactory.jsonBuilder(); + toXContent(builder, ToXContent.EMPTY_PARAMS); + return builder.string(); + } catch (IOException e) { + return ""; + } + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(); + toInnerXContent(builder, params); + builder.endObject(); + return builder; + } + + public XContentBuilder toInnerXContent(XContentBuilder builder, Params params) throws IOException { + boolean licenseSpecMode = params.paramAsBoolean(LICENSE_SPEC_VIEW_MODE, false); + boolean restViewMode = params.paramAsBoolean(REST_VIEW_MODE, false); + boolean previouslyHumanReadable = builder.humanReadable(); + if (licenseSpecMode && restViewMode) { + throw new IllegalArgumentException("can have either " + REST_VIEW_MODE + " or " + LICENSE_SPEC_VIEW_MODE); + } else if (restViewMode) { + if (!previouslyHumanReadable) { + builder.humanReadable(true); + } + } + final int version; + if (params.param(LICENSE_VERSION_MODE) != null && restViewMode) { + version = Integer.parseInt(params.param(LICENSE_VERSION_MODE)); + } else { + version = this.version; + } + if (restViewMode) { + builder.field(XFields.STATUS, status().label()); + } + builder.field(XFields.UID, uid); + builder.field(XFields.TYPE, type); + if (version == VERSION_START) { + builder.field(XFields.SUBSCRIPTION_TYPE, subscriptionType); + } + builder.dateValueField(XFields.ISSUE_DATE_IN_MILLIS, XFields.ISSUE_DATE, issueDate); + if (version == VERSION_START) { + builder.field(XFields.FEATURE, feature); + } + builder.dateValueField(XFields.EXPIRY_DATE_IN_MILLIS, XFields.EXPIRY_DATE, expiryDate); + builder.field(XFields.MAX_NODES, maxNodes); + builder.field(XFields.ISSUED_TO, issuedTo); + builder.field(XFields.ISSUER, issuer); + if (!licenseSpecMode && !restViewMode && signature != null) { + builder.field(XFields.SIGNATURE, signature); + } + if (restViewMode) { + builder.humanReadable(previouslyHumanReadable); + } + return builder; + } + + public static License fromXContent(XContentParser parser) throws IOException { + Builder builder = new Builder(); + XContentParser.Token token; + while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { + if (token == XContentParser.Token.FIELD_NAME) { + String currentFieldName = parser.currentName(); + token = parser.nextToken(); + if (token.isValue()) { + if (Fields.UID.equals(currentFieldName)) { + builder.uid(parser.text()); + } else if (Fields.TYPE.equals(currentFieldName)) { + builder.type(parser.text()); + } else if (Fields.SUBSCRIPTION_TYPE.equals(currentFieldName)) { + builder.subscriptionType(parser.text()); + } else if (Fields.ISSUE_DATE.equals(currentFieldName)) { + builder.issueDate(parseDate(parser, "issue", false)); + } else if (Fields.ISSUE_DATE_IN_MILLIS.equals(currentFieldName)) { + builder.issueDate(parser.longValue()); + } else if (Fields.FEATURE.equals(currentFieldName)) { + builder.feature(parser.text()); + } else if (Fields.EXPIRY_DATE.equals(currentFieldName)) { + builder.expiryDate(parseDate(parser, "expiration", true)); + } else if (Fields.EXPIRY_DATE_IN_MILLIS.equals(currentFieldName)) { + builder.expiryDate(parser.longValue()); + } else if (Fields.MAX_NODES.equals(currentFieldName)) { + builder.maxNodes(parser.intValue()); + } else if (Fields.ISSUED_TO.equals(currentFieldName)) { + builder.issuedTo(parser.text()); + } else if (Fields.ISSUER.equals(currentFieldName)) { + builder.issuer(parser.text()); + } else if (Fields.SIGNATURE.equals(currentFieldName)) { + builder.signature(parser.text()); + } else if (Fields.VERSION.equals(currentFieldName)) { + builder.version(parser.intValue()); + } + // Ignore unknown elements - might be new version of license + } else if (token == XContentParser.Token.START_ARRAY) { + // It was probably created by newer version - ignoring + parser.skipChildren(); + } else if (token == XContentParser.Token.START_OBJECT) { + // It was probably created by newer version - ignoring + parser.skipChildren(); + } + } + } + // not a license spec + if (builder.signature != null) { + byte[] signatureBytes = Base64.decode(builder.signature); + ByteBuffer byteBuffer = ByteBuffer.wrap(signatureBytes); + int version = byteBuffer.getInt(); + // we take the absolute version, because negative versions + // mean that the license was generated by the cluster (see TrialLicense) + // and positive version means that the license was signed + if (version < 0) { + version *= -1; + } + if (version == 0) { + throw new ElasticsearchException("malformed signature for license [" + builder.uid + "]"); + } else if (version > VERSION_CURRENT) { + throw new ElasticsearchException("Unknown license version found, please upgrade all nodes to the latest elasticsearch-license plugin"); + } + // signature version is the source of truth + builder.version(version); + } + return builder.build(); + } + + /** + * Returns true if the license was auto-generated (by license plugin), + * false otherwise + */ + public static boolean isAutoGeneratedLicense(String signature) { + try { + byte[] signatureBytes = Base64.decode(signature); + ByteBuffer byteBuffer = ByteBuffer.wrap(signatureBytes); + return byteBuffer.getInt() < 0; + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + + public static License fromSource(String content) throws IOException { + return fromSource(content.getBytes(StandardCharsets.UTF_8)); + } + + public static License fromSource(byte[] bytes) throws IOException { + final XContentParser parser = XContentFactory.xContent(bytes).createParser(bytes); + License license = null; + if (parser.nextToken() == XContentParser.Token.START_OBJECT) { + if (parser.nextToken() == XContentParser.Token.FIELD_NAME) { + String currentFieldName = parser.currentName(); + if (Fields.LICENSES.equals(currentFieldName)) { + final List pre20Licenses = new ArrayList<>(); + if (parser.nextToken() == XContentParser.Token.START_ARRAY) { + while (parser.nextToken() != XContentParser.Token.END_ARRAY) { + pre20Licenses.add(License.fromXContent(parser)); + } + // take the latest issued unexpired license + CollectionUtil.timSort(pre20Licenses, LATEST_ISSUE_DATE_FIRST); + long now = System.currentTimeMillis(); + for (License oldLicense : pre20Licenses) { + if (oldLicense.expiryDate() > now) { + license = oldLicense; + break; + } + } + if (license == null && !pre20Licenses.isEmpty()) { + license = pre20Licenses.get(0); + } + } else { + throw new ElasticsearchParseException("failed to parse licenses expected an array of licenses"); + } + } else if (Fields.LICENSE.equals(currentFieldName)) { + license = License.fromXContent(parser); + } + // Ignore all other fields - might be created with new version + } else { + throw new ElasticsearchParseException("failed to parse licenses expected field"); + } + } else { + throw new ElasticsearchParseException("failed to parse licenses expected start object"); + } + return license; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + License license = (License) o; + + if (issueDate != license.issueDate) return false; + if (expiryDate != license.expiryDate) return false; + if (maxNodes != license.maxNodes) return false; + if (version != license.version) return false; + if (uid != null ? !uid.equals(license.uid) : license.uid != null) return false; + if (issuer != null ? !issuer.equals(license.issuer) : license.issuer != null) return false; + if (issuedTo != null ? !issuedTo.equals(license.issuedTo) : license.issuedTo != null) return false; + if (type != null ? !type.equals(license.type) : license.type != null) return false; + if (subscriptionType != null ? !subscriptionType.equals(license.subscriptionType) : license.subscriptionType != null) + return false; + if (feature != null ? !feature.equals(license.feature) : license.feature != null) return false; + return !(signature != null ? !signature.equals(license.signature) : license.signature != null); + + } + + @Override + public int hashCode() { + int result = uid != null ? uid.hashCode() : 0; + result = 31 * result + (issuer != null ? issuer.hashCode() : 0); + result = 31 * result + (issuedTo != null ? issuedTo.hashCode() : 0); + result = 31 * result + (int) (issueDate ^ (issueDate >>> 32)); + result = 31 * result + (type != null ? type.hashCode() : 0); + result = 31 * result + (subscriptionType != null ? subscriptionType.hashCode() : 0); + result = 31 * result + (feature != null ? feature.hashCode() : 0); + result = 31 * result + (signature != null ? signature.hashCode() : 0); + result = 31 * result + (int) (expiryDate ^ (expiryDate >>> 32)); + result = 31 * result + maxNodes; + result = 31 * result + version; + return result; + } + + final static class Fields { + static final String STATUS = "status"; + static final String UID = "uid"; + static final String TYPE = "type"; + static final String SUBSCRIPTION_TYPE = "subscription_type"; + static final String ISSUE_DATE_IN_MILLIS = "issue_date_in_millis"; + static final String ISSUE_DATE = "issue_date"; + static final String FEATURE = "feature"; + static final String EXPIRY_DATE_IN_MILLIS = "expiry_date_in_millis"; + static final String EXPIRY_DATE = "expiry_date"; + static final String MAX_NODES = "max_nodes"; + static final String ISSUED_TO = "issued_to"; + static final String ISSUER = "issuer"; + static final String VERSION = "version"; + static final String SIGNATURE = "signature"; + + static final String LICENSES = "licenses"; + static final String LICENSE = "license"; + + } + + public interface XFields { + XContentBuilderString STATUS = new XContentBuilderString(Fields.STATUS); + XContentBuilderString UID = new XContentBuilderString(Fields.UID); + XContentBuilderString TYPE = new XContentBuilderString(Fields.TYPE); + XContentBuilderString SUBSCRIPTION_TYPE = new XContentBuilderString(Fields.SUBSCRIPTION_TYPE); + XContentBuilderString ISSUE_DATE_IN_MILLIS = new XContentBuilderString(Fields.ISSUE_DATE_IN_MILLIS); + XContentBuilderString ISSUE_DATE = new XContentBuilderString(Fields.ISSUE_DATE); + XContentBuilderString FEATURE = new XContentBuilderString(Fields.FEATURE); + XContentBuilderString EXPIRY_DATE_IN_MILLIS = new XContentBuilderString(Fields.EXPIRY_DATE_IN_MILLIS); + XContentBuilderString EXPIRY_DATE = new XContentBuilderString(Fields.EXPIRY_DATE); + XContentBuilderString MAX_NODES = new XContentBuilderString(Fields.MAX_NODES); + XContentBuilderString ISSUED_TO = new XContentBuilderString(Fields.ISSUED_TO); + XContentBuilderString ISSUER = new XContentBuilderString(Fields.ISSUER); + XContentBuilderString SIGNATURE = new XContentBuilderString(Fields.SIGNATURE); + } + + private static long parseDate(XContentParser parser, String description, boolean endOfTheDay) throws IOException { + if (parser.currentToken() == XContentParser.Token.VALUE_NUMBER) { + return parser.longValue(); + } else { + try { + if (endOfTheDay) { + return DateUtils.endOfTheDay(parser.text()); + } else { + return DateUtils.beginningOfTheDay(parser.text()); + } + } catch (IllegalArgumentException ex) { + throw new ElasticsearchParseException("invalid " + description + " date format " + parser.text()); + } + } + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private int version = License.VERSION_CURRENT; + private String uid; + private String issuer; + private String issuedTo; + private long issueDate = -1; + private String type; + private String subscriptionType; + private String feature; + private String signature; + private long expiryDate = -1; + private int maxNodes = -1; + + public Builder uid(String uid) { + this.uid = uid; + return this; + } + + public Builder version(int version) { + this.version = version; + return this; + } + + public Builder issuer(String issuer) { + this.issuer = issuer; + return this; + } + + public Builder issuedTo(String issuedTo) { + this.issuedTo = issuedTo; + return this; + } + + public Builder issueDate(long issueDate) { + this.issueDate = issueDate; + return this; + } + + public Builder type(String type) { + this.type = type; + return this; + } + + public Builder subscriptionType(String subscriptionType) { + this.subscriptionType = subscriptionType; + return this; + } + + public Builder feature(String feature) { + this.feature = feature; + return this; + } + + public Builder expiryDate(long expiryDate) { + this.expiryDate = expiryDate; + return this; + } + + public Builder maxNodes(int maxNodes) { + this.maxNodes = maxNodes; + return this; + } + + public Builder signature(String signature) { + if (signature != null) { + this.signature = signature; + } + return this; + } + + public Builder fromLicenseSpec(License license, String signature) { + return uid(license.uid()) + .version(license.version()) + .issuedTo(license.issuedTo()) + .issueDate(license.issueDate()) + .type(license.type()) + .subscriptionType(license.subscriptionType) + .feature(license.feature) + .maxNodes(license.maxNodes()) + .expiryDate(license.expiryDate()) + .issuer(license.issuer()) + .signature(signature); + } + + /** + * Returns a builder that converts pre 2.0 licenses + * to the new license format + */ + public Builder fromPre20LicenseSpec(License pre20License) { + return uid(pre20License.uid()) + .issuedTo(pre20License.issuedTo()) + .issueDate(pre20License.issueDate()) + .maxNodes(pre20License.maxNodes()) + .expiryDate(pre20License.expiryDate()); + } + + public License build() { + return new License(version, uid, issuer, issuedTo, issueDate, type, + subscriptionType, feature, signature, expiryDate, maxNodes); + } + + public Builder validate() { + if (issuer == null) { + throw new IllegalStateException("issuer can not be null"); + } else if (issuedTo == null) { + throw new IllegalStateException("issuedTo can not be null"); + } else if (issueDate == -1) { + throw new IllegalStateException("issueDate has to be set"); + } else if (type == null) { + throw new IllegalStateException("type can not be null"); + } else if (uid == null) { + throw new IllegalStateException("uid can not be null"); + } else if (signature == null) { + throw new IllegalStateException("signature can not be null"); + } else if (maxNodes == -1) { + throw new IllegalStateException("maxNodes has to be set"); + } else if (expiryDate == -1) { + throw new IllegalStateException("expiryDate has to be set"); + } + return this; + } + } + + public enum Status { + ACTIVE("active"), + INVALID("invalid"), + EXPIRED("expired"); + + private final String label; + + Status(String label) { + this.label = label; + } + + public String label() { + return label; + } + } +} diff --git a/elasticsearch/license/base/src/main/java/org/elasticsearch/license/core/LicenseVerifier.java b/elasticsearch/license/base/src/main/java/org/elasticsearch/license/core/LicenseVerifier.java new file mode 100644 index 00000000000..51ace787491 --- /dev/null +++ b/elasticsearch/license/base/src/main/java/org/elasticsearch/license/core/LicenseVerifier.java @@ -0,0 +1,69 @@ +/* + * 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.license.core; + +import org.elasticsearch.common.Base64; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentType; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.Signature; +import java.security.SignatureException; +import java.util.Arrays; +import java.util.Collections; + +/** + * Responsible for verifying signed licenses + */ +public class LicenseVerifier { + + /** + * verifies the license content with the signature using the packaged + * public key + * @param license to verify + * @return true if valid, false otherwise + */ + public static boolean verifyLicense(final License license, byte[] encryptedPublicKeyData) { + byte[] signedContent = null; + byte[] signatureHash = null; + try { + byte[] signatureBytes = Base64.decode(license.signature()); + ByteBuffer byteBuffer = ByteBuffer.wrap(signatureBytes); + int version = byteBuffer.getInt(); + int magicLen = byteBuffer.getInt(); + byte[] magic = new byte[magicLen]; + byteBuffer.get(magic); + int hashLen = byteBuffer.getInt(); + signatureHash = new byte[hashLen]; + byteBuffer.get(signatureHash); + int signedContentLen = byteBuffer.getInt(); + signedContent = new byte[signedContentLen]; + byteBuffer.get(signedContent); + XContentBuilder contentBuilder = XContentFactory.contentBuilder(XContentType.JSON); + license.toXContent(contentBuilder, new ToXContent.MapParams(Collections.singletonMap(License.LICENSE_SPEC_VIEW_MODE, "true"))); + Signature rsa = Signature.getInstance("SHA512withRSA"); + rsa.initVerify(CryptUtils.readEncryptedPublicKey(encryptedPublicKeyData)); + rsa.update(contentBuilder.bytes().toBytes()); + return rsa.verify(signedContent) + && Arrays.equals(Base64.encodeBytesToBytes(encryptedPublicKeyData), signatureHash); + } catch (IOException | NoSuchAlgorithmException | SignatureException | InvalidKeyException e) { + throw new IllegalStateException(e); + } finally { + Arrays.fill(encryptedPublicKeyData, (byte) 0); + if (signedContent != null) { + Arrays.fill(signedContent, (byte) 0); + } + if (signatureHash != null) { + Arrays.fill(signatureHash, (byte) 0); + } + } + } +} diff --git a/elasticsearch/license/base/src/test/java/org/elasticsearch/license/core/LicenseSerializationTests.java b/elasticsearch/license/base/src/test/java/org/elasticsearch/license/core/LicenseSerializationTests.java new file mode 100644 index 00000000000..b1947ee971b --- /dev/null +++ b/elasticsearch/license/base/src/test/java/org/elasticsearch/license/core/LicenseSerializationTests.java @@ -0,0 +1,99 @@ +/* + * 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.license.core; + +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentHelper; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.test.ESTestCase; + +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.Map; + +import static org.hamcrest.core.IsEqual.equalTo; +import static org.hamcrest.core.IsNull.notNullValue; +import static org.hamcrest.core.IsNull.nullValue; + +public class LicenseSerializationTests extends ESTestCase { + public void testSimpleIssueExpiryDate() throws Exception { + long now = System.currentTimeMillis(); + String issueDate = TestUtils.dateMathString("now", now); + String expiryDate = TestUtils.dateMathString("now+10d/d", now); + String licenseSpecs = TestUtils.generateLicenseSpecString(new TestUtils.LicenseSpec(issueDate, expiryDate)); + License generatedLicense = License.fromSource(licenseSpecs.getBytes(StandardCharsets.UTF_8)); + assertThat(generatedLicense.issueDate(), equalTo(DateUtils.beginningOfTheDay(issueDate))); + assertThat(generatedLicense.expiryDate(), equalTo(DateUtils.endOfTheDay(expiryDate))); + } + + public void testLicensesFields() throws Exception { + TestUtils.LicenseSpec randomLicenseSpec = TestUtils.generateRandomLicenseSpec(License.VERSION_START);//randomIntBetween(License.VERSION_START, License.VERSION_CURRENT)); + String licenseSpecsSource = TestUtils.generateLicenseSpecString(randomLicenseSpec); + final License fromSource = License.fromSource(licenseSpecsSource.getBytes(StandardCharsets.UTF_8)); + TestUtils.assertLicenseSpec(randomLicenseSpec, fromSource); + } + + public void testLicenseRestView() throws Exception { + long now = System.currentTimeMillis(); + String expiredLicenseExpiryDate = TestUtils.dateMathString("now-1d/d", now); + String validLicenseIssueDate = TestUtils.dateMathString("now-10d/d", now); + String invalidLicenseIssueDate = TestUtils.dateMathString("now+1d/d", now); + String validLicenseExpiryDate = TestUtils.dateMathString("now+2d/d", now); + + License license = TestUtils.generateLicenses(new TestUtils.LicenseSpec(validLicenseIssueDate, expiredLicenseExpiryDate)); + XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON); + license.toXContent(builder, new ToXContent.MapParams(Collections.singletonMap(License.REST_VIEW_MODE, "true"))); + builder.flush(); + Map map = XContentHelper.convertToMap(builder.bytesStream().bytes(), false).v2(); + + // should have an extra status field, human readable issue_data and expiry_date + assertThat(map.get("status"), notNullValue()); + assertThat(map.get("issue_date"), notNullValue()); + assertThat(map.get("expiry_date"), notNullValue()); + assertThat(map.get("status"), equalTo("expired")); + builder = XContentFactory.contentBuilder(XContentType.JSON); + license.toXContent(builder, ToXContent.EMPTY_PARAMS); + builder.flush(); + map = XContentHelper.convertToMap(builder.bytesStream().bytes(), false).v2(); + assertThat(map.get("status"), nullValue()); + + license = TestUtils.generateLicenses(new TestUtils.LicenseSpec(validLicenseIssueDate, validLicenseExpiryDate)); + builder = XContentFactory.contentBuilder(XContentType.JSON); + license.toXContent(builder, new ToXContent.MapParams(Collections.singletonMap(License.REST_VIEW_MODE, "true"))); + builder.flush(); + map = XContentHelper.convertToMap(builder.bytesStream().bytes(), false).v2(); + + // should have an extra status field, human readable issue_data and expiry_date + assertThat(map.get("status"), notNullValue()); + assertThat(map.get("issue_date"), notNullValue()); + assertThat(map.get("expiry_date"), notNullValue()); + assertThat(map.get("status"), equalTo("active")); + builder = XContentFactory.contentBuilder(XContentType.JSON); + license.toXContent(builder, ToXContent.EMPTY_PARAMS); + builder.flush(); + map = XContentHelper.convertToMap(builder.bytesStream().bytes(), false).v2(); + assertThat(map.get("status"), nullValue()); + + license = TestUtils.generateLicenses(new TestUtils.LicenseSpec(invalidLicenseIssueDate, validLicenseExpiryDate)); + builder = XContentFactory.contentBuilder(XContentType.JSON); + license.toXContent(builder, new ToXContent.MapParams(Collections.singletonMap(License.REST_VIEW_MODE, "true"))); + builder.flush(); + map = XContentHelper.convertToMap(builder.bytesStream().bytes(), false).v2(); + + // should have an extra status field, human readable issue_data and expiry_date + assertThat(map.get("status"), notNullValue()); + assertThat(map.get("issue_date"), notNullValue()); + assertThat(map.get("expiry_date"), notNullValue()); + assertThat(map.get("status"), equalTo("invalid")); + builder = XContentFactory.contentBuilder(XContentType.JSON); + license.toXContent(builder, ToXContent.EMPTY_PARAMS); + builder.flush(); + map = XContentHelper.convertToMap(builder.bytesStream().bytes(), false).v2(); + assertThat(map.get("status"), nullValue()); + } +} diff --git a/elasticsearch/license/base/src/test/java/org/elasticsearch/license/core/TestUtils.java b/elasticsearch/license/base/src/test/java/org/elasticsearch/license/core/TestUtils.java new file mode 100644 index 00000000000..7f3dd01be26 --- /dev/null +++ b/elasticsearch/license/base/src/test/java/org/elasticsearch/license/core/TestUtils.java @@ -0,0 +1,197 @@ +/* + * 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.license.core; + +import org.elasticsearch.common.joda.DateMathParser; +import org.elasticsearch.common.joda.FormatDateTimeFormatter; +import org.elasticsearch.common.joda.Joda; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.hamcrest.MatcherAssert; +import org.joda.time.format.DateTimeFormatter; + +import java.io.IOException; +import java.util.*; +import java.util.concurrent.Callable; + +import static com.carrotsearch.randomizedtesting.RandomizedTest.*; +import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; +import static org.elasticsearch.test.ESTestCase.randomFrom; +import static org.hamcrest.core.IsEqual.equalTo; + +public class TestUtils { + + private final static FormatDateTimeFormatter formatDateTimeFormatter = Joda.forPattern("yyyy-MM-dd"); + private final static DateMathParser dateMathParser = new DateMathParser(formatDateTimeFormatter); + private final static DateTimeFormatter dateTimeFormatter = formatDateTimeFormatter.printer(); + + public static String dateMathString(String time, final long now) { + return dateTimeFormatter.print(dateMathParser.parse(time, new Callable() { + @Override + public Long call() throws Exception { + return now; + } + })); + } + + public static long dateMath(String time, final long now) { + return dateMathParser.parse(time, new Callable() { + @Override + public Long call() throws Exception { + return now; + } + }); + } + + public static LicenseSpec generateRandomLicenseSpec(int version) { + boolean datesInMillis = randomBoolean(); + long now = System.currentTimeMillis(); + String uid = UUID.randomUUID().toString(); + String feature = "feature__" + randomInt(); + String issuer = "issuer__" + randomInt(); + String issuedTo = "issuedTo__" + randomInt(); + final String type; + final String subscriptionType; + if (version < License.VERSION_NO_FEATURE_TYPE) { + subscriptionType = randomFrom("gold", "silver", "platinum"); + type = "subscription";//randomFrom("subscription", "internal", "development"); + } else { + subscriptionType = null; + type = randomFrom("basic", "dev", "gold", "silver", "platinum"); + } + int maxNodes = randomIntBetween(5, 100); + if (datesInMillis) { + long issueDateInMillis = dateMath("now", now); + long expiryDateInMillis = dateMath("now+10d/d", now); + return new LicenseSpec(version, uid, feature, issueDateInMillis, expiryDateInMillis, type, subscriptionType, issuedTo, issuer, maxNodes); + } else { + String issueDate = dateMathString("now", now); + String expiryDate = dateMathString("now+10d/d", now); + return new LicenseSpec(version, uid, feature, issueDate, expiryDate, type, subscriptionType, issuedTo, issuer, maxNodes); + } + } + + public static String generateLicenseSpecString(LicenseSpec licenseSpec) throws IOException { + XContentBuilder licenses = jsonBuilder(); + licenses.startObject(); + licenses.startArray("licenses"); + licenses.startObject() + .field("uid", licenseSpec.uid) + .field("type", licenseSpec.type) + .field("subscription_type", licenseSpec.subscriptionType) + .field("issued_to", licenseSpec.issuedTo) + .field("issuer", licenseSpec.issuer) + .field("feature", licenseSpec.feature) + .field("max_nodes", licenseSpec.maxNodes); + + if (licenseSpec.issueDate != null) { + licenses.field("issue_date", licenseSpec.issueDate); + } else { + licenses.field("issue_date_in_millis", licenseSpec.issueDateInMillis); + } + if (licenseSpec.expiryDate != null) { + licenses.field("expiry_date", licenseSpec.expiryDate); + } else { + licenses.field("expiry_date_in_millis", licenseSpec.expiryDateInMillis); + } + licenses.field("version", licenseSpec.version); + licenses.endObject(); + licenses.endArray(); + licenses.endObject(); + return licenses.string(); + } + + public static License generateLicenses(LicenseSpec spec) { + License.Builder builder = License.builder() + .uid(spec.uid) + .feature(spec.feature) + .type(spec.type) + .subscriptionType(spec.subscriptionType) + .issuedTo(spec.issuedTo) + .issuer(spec.issuer) + .maxNodes(spec.maxNodes); + + if (spec.expiryDate != null) { + builder.expiryDate(DateUtils.endOfTheDay(spec.expiryDate)); + } else { + builder.expiryDate(spec.expiryDateInMillis); + } + if (spec.issueDate != null) { + builder.issueDate(DateUtils.beginningOfTheDay(spec.issueDate)); + } else { + builder.issueDate(spec.issueDateInMillis); + } + return builder.build(); + } + + public static void assertLicenseSpec(LicenseSpec spec, License license) { + MatcherAssert.assertThat(license.uid(), equalTo(spec.uid)); + MatcherAssert.assertThat(license.issuedTo(), equalTo(spec.issuedTo)); + MatcherAssert.assertThat(license.issuer(), equalTo(spec.issuer)); + MatcherAssert.assertThat(license.type(), equalTo(spec.type)); + MatcherAssert.assertThat(license.maxNodes(), equalTo(spec.maxNodes)); + if (spec.issueDate != null) { + MatcherAssert.assertThat(license.issueDate(), equalTo(DateUtils.beginningOfTheDay(spec.issueDate))); + } else { + MatcherAssert.assertThat(license.issueDate(), equalTo(spec.issueDateInMillis)); + } + if (spec.expiryDate != null) { + MatcherAssert.assertThat(license.expiryDate(), equalTo(DateUtils.endOfTheDay(spec.expiryDate))); + } else { + MatcherAssert.assertThat(license.expiryDate(), equalTo(spec.expiryDateInMillis)); + } + } + + public static class LicenseSpec { + public final int version; + public final String feature; + public final String issueDate; + public final long issueDateInMillis; + public final String expiryDate; + public final long expiryDateInMillis; + public final String uid; + public final String type; + public final String subscriptionType; + public final String issuedTo; + public final String issuer; + public final int maxNodes; + + public LicenseSpec(String issueDate, String expiryDate) { + this(License.VERSION_CURRENT, UUID.randomUUID().toString(), "feature", issueDate, expiryDate, "trial", "none", "customer", "elasticsearch", 5); + } + + public LicenseSpec(int version, String uid, String feature, long issueDateInMillis, long expiryDateInMillis, String type, + String subscriptionType, String issuedTo, String issuer, int maxNodes) { + this.version = version; + this.feature = feature; + this.issueDateInMillis = issueDateInMillis; + this.issueDate = null; + this.expiryDateInMillis = expiryDateInMillis; + this.expiryDate = null; + this.uid = uid; + this.type = type; + this.subscriptionType = subscriptionType; + this.issuedTo = issuedTo; + this.issuer = issuer; + this.maxNodes = maxNodes; + } + + public LicenseSpec(int version, String uid, String feature, String issueDate, String expiryDate, String type, + String subscriptionType, String issuedTo, String issuer, int maxNodes) { + this.version = version; + this.feature = feature; + this.issueDate = issueDate; + this.issueDateInMillis = -1; + this.expiryDate = expiryDate; + this.expiryDateInMillis = -1; + this.uid = uid; + this.type = type; + this.subscriptionType = subscriptionType; + this.issuedTo = issuedTo; + this.issuer = issuer; + this.maxNodes = maxNodes; + } + } +} diff --git a/elasticsearch/license/base/src/test/resources/log4j.properties b/elasticsearch/license/base/src/test/resources/log4j.properties new file mode 100644 index 00000000000..76defc8660c --- /dev/null +++ b/elasticsearch/license/base/src/test/resources/log4j.properties @@ -0,0 +1,11 @@ +es.logger.level=INFO +log4j.rootLogger=${es.logger.level}, out + +log4j.logger.org.apache.http=INFO, out +log4j.additivity.org.apache.http=false + +log4j.logger.org.elasticsearch.license=TRACE + +log4j.appender.out=org.apache.log4j.ConsoleAppender +log4j.appender.out.layout=org.apache.log4j.PatternLayout +log4j.appender.out.layout.conversionPattern=[%d{ISO8601}][%-5p][%-25c] %m%n diff --git a/elasticsearch/license/base/src/test/resources/private.key b/elasticsearch/license/base/src/test/resources/private.key new file mode 100644 index 00000000000..1f545803d87 Binary files /dev/null and b/elasticsearch/license/base/src/test/resources/private.key differ diff --git a/elasticsearch/license/base/src/test/resources/public.key b/elasticsearch/license/base/src/test/resources/public.key new file mode 100644 index 00000000000..2a9f272e0b3 --- /dev/null +++ b/elasticsearch/license/base/src/test/resources/public.key @@ -0,0 +1,3 @@ +ýŽÇqÝnêÄÌgŠœwM}¹‡UiKŠ•0âbÖ2غqö]â쇴¯ÖÏÃcÌ+IÒðÔ &IJ†fÉ~ßlj ˆº]d™}o§Oè¾Id®È +5A(ìµ´^ØöW©DªJµë}ù-Oîë?u N5¾ÛvpÛ{’¼²Áô­œát–¤7ùøÃê #²Vqöó»ktwm’Œ]ÏLõ£z"| Q‹lŸòQðsâ>ù<}[Á2ÖÓàZÖ|5‹¯ÊÊ7%ØêD +Yå‘xn:¼lúLÈæHò¢«Ë2˜ŸHvEEWÇ\¦H:“6Žh9 [!š…Ûæ©Š¤+;Ö.w7Cì©_|Þ ÓªÏÁ*ñ§D`ƒÚ?‚ùxU/3>x­UÓ“+ è \ No newline at end of file diff --git a/elasticsearch/license/build.gradle b/elasticsearch/license/build.gradle new file mode 100644 index 00000000000..b4e221e7884 --- /dev/null +++ b/elasticsearch/license/build.gradle @@ -0,0 +1,7 @@ +subprojects { + project.afterEvaluate { + project.forbiddenPatterns { + exclude '**/*.key' + } + } +} diff --git a/elasticsearch/license/found-plugin/.gitignore b/elasticsearch/license/found-plugin/.gitignore new file mode 100644 index 00000000000..ab956abf6f9 --- /dev/null +++ b/elasticsearch/license/found-plugin/.gitignore @@ -0,0 +1 @@ +/eclipse-build/ diff --git a/elasticsearch/license/found-plugin/build.gradle b/elasticsearch/license/found-plugin/build.gradle new file mode 100644 index 00000000000..577ed689782 --- /dev/null +++ b/elasticsearch/license/found-plugin/build.gradle @@ -0,0 +1,19 @@ +apply plugin: 'elasticsearch.esplugin' +esplugin { + name 'found-plugin' + description 'Internal Elasticsearch Licensing Plugin for Found' + classname 'org.elasticsearch.license.plugin.LicensePlugin' +} + +dependencies { + compile project(':x-plugins:elasticsearch:license:plugin-api') + testCompile project(':x-plugins:elasticsearch:license:licensor') +} + +// no tests +test.enabled = false +integTest.enabled = false + +dependencyLicenses.enabled = false + +compileJava.options.compilerArgs << "-Xlint:-rawtypes,-unchecked" diff --git a/elasticsearch/license/found-plugin/src/main/java/org/elasticsearch/license/plugin/LicenseModule.java b/elasticsearch/license/found-plugin/src/main/java/org/elasticsearch/license/plugin/LicenseModule.java new file mode 100644 index 00000000000..626049a8e53 --- /dev/null +++ b/elasticsearch/license/found-plugin/src/main/java/org/elasticsearch/license/plugin/LicenseModule.java @@ -0,0 +1,23 @@ +/* + * 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.license.plugin; + +import org.elasticsearch.common.inject.AbstractModule; +import org.elasticsearch.license.core.LicenseVerifier; +import org.elasticsearch.license.plugin.core.FoundLicensesService; +import org.elasticsearch.license.plugin.core.LicenseeRegistry; +import org.elasticsearch.license.plugin.core.LicensesManagerService; + +public class LicenseModule extends AbstractModule { + + @Override + protected void configure() { + bind(LicenseVerifier.class).asEagerSingleton(); + bind(LicenseeRegistry.class).to(FoundLicensesService.class); + bind(LicensesManagerService.class).to(FoundLicensesService.class); + } + +} \ No newline at end of file diff --git a/elasticsearch/license/found-plugin/src/main/java/org/elasticsearch/license/plugin/LicensePlugin.java b/elasticsearch/license/found-plugin/src/main/java/org/elasticsearch/license/plugin/LicensePlugin.java new file mode 100644 index 00000000000..82367bfad0a --- /dev/null +++ b/elasticsearch/license/found-plugin/src/main/java/org/elasticsearch/license/plugin/LicensePlugin.java @@ -0,0 +1,49 @@ +/* + * 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.license.plugin; + +import org.elasticsearch.common.component.LifecycleComponent; +import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.inject.Module; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.license.plugin.core.FoundLicensesService; +import org.elasticsearch.plugins.Plugin; + +import java.util.ArrayList; +import java.util.Collection; + +public class LicensePlugin extends Plugin { + + public static final String NAME = "license"; + + @Inject + public LicensePlugin(Settings settings) { + } + + @Override + public String name() { + return NAME; + } + + @Override + public String description() { + return "Internal Elasticsearch Licensing Plugin"; + } + + @Override + public Collection> nodeServices() { + Collection> services = new ArrayList<>(); + services.add(FoundLicensesService.class); + return services; + } + + @Override + public Collection nodeModules() { + Collection modules = new ArrayList(); + modules.add(new LicenseModule()); + return modules; + } +} diff --git a/elasticsearch/license/found-plugin/src/main/java/org/elasticsearch/license/plugin/core/FoundLicensesService.java b/elasticsearch/license/found-plugin/src/main/java/org/elasticsearch/license/plugin/core/FoundLicensesService.java new file mode 100644 index 00000000000..af1273697b3 --- /dev/null +++ b/elasticsearch/license/found-plugin/src/main/java/org/elasticsearch/license/plugin/core/FoundLicensesService.java @@ -0,0 +1,57 @@ +/* + * 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.license.plugin.core; + +import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.common.component.AbstractLifecycleComponent; +import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.inject.Singleton; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.license.core.License; + +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.UUID; + +@Singleton +public class FoundLicensesService extends AbstractLifecycleComponent implements LicenseeRegistry, LicensesManagerService { + + @Inject + public FoundLicensesService(Settings settings) { + super(settings); + } + + /** + * {@inheritDoc} + */ + @Override + public void register(Licensee licensee) { + licensee.onChange(new Licensee.Status(License.OperationMode.PLATINUM, LicenseState.ENABLED)); + } + + @Override + protected void doStart() throws ElasticsearchException { + } + + @Override + protected void doStop() throws ElasticsearchException { + } + + @Override + protected void doClose() throws ElasticsearchException { + } + + @Override + public List licenseesWithState(LicenseState state) { + return Collections.emptyList(); + } + + @Override + public License getLicense() { + return null; + } +} diff --git a/elasticsearch/license/licensor/bin/key-pair-generator b/elasticsearch/license/licensor/bin/key-pair-generator new file mode 100755 index 00000000000..7c6308673fa --- /dev/null +++ b/elasticsearch/license/licensor/bin/key-pair-generator @@ -0,0 +1,58 @@ +#!/bin/sh + +# 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. + +CDPATH="" +SCRIPT="$0" + +# SCRIPT may be an arbitrarily deep series of symlinks. Loop until we have the concrete path. +while [ -h "$SCRIPT" ] ; do + ls=`ls -ld "$SCRIPT"` + # Drop everything prior to -> + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + SCRIPT="$link" + else + SCRIPT=`dirname "$SCRIPT"`/"$link" + fi +done + +# determine license home +LICENSE_HOME=`dirname "$SCRIPT"`/.. + +# make LICENSE_HOME absolute +LICENSE_HOME=`cd "$LICENSE_HOME"; pwd` + +# setup classpath +LICENSE_CLASSPATH=$LICENSE_CLASSPATH:$LICENSE_HOME/lib/${project.artifactId}-${project.version}-exec.jar:$LICENSE_HOME/lib/* + +if [ -x "$JAVA_HOME/bin/java" ]; then + JAVA=$JAVA_HOME/bin/java +else + JAVA=`which java` +fi + + +# Parse any long getopt options and put them into properties before calling getopt below +# Be dash compatible to make sure running under ubuntu works +ARGCOUNT=$# +COUNT=0 +while [ $COUNT -lt $ARGCOUNT ] +do + case $1 in + -D*=*) + properties="$properties $1" + shift 1; COUNT=$(($COUNT+1)) + ;; + -D*) + properties="$properties $1=$2" + shift ; shift; COUNT=$(($COUNT+2)) + ;; + *) set -- "$@" "$1"; shift; COUNT=$(($COUNT+1)) + esac +done + +exec "$JAVA" $JAVA_OPTS -Xmx64m -Xms16m $properties -cp "$LICENSE_CLASSPATH" -Des.path.home="`pwd`" org.elasticsearch.license.licensor.tools.KeyPairGeneratorTool "$@" + diff --git a/elasticsearch/license/licensor/bin/license-generator b/elasticsearch/license/licensor/bin/license-generator new file mode 100755 index 00000000000..d51ac254ee1 --- /dev/null +++ b/elasticsearch/license/licensor/bin/license-generator @@ -0,0 +1,56 @@ +#!/bin/sh + +# 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. + +CDPATH="" +SCRIPT="$0" + +# SCRIPT may be an arbitrarily deep series of symlinks. Loop until we have the concrete path. +while [ -h "$SCRIPT" ] ; do + ls=`ls -ld "$SCRIPT"` + # Drop everything prior to -> + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + SCRIPT="$link" + else + SCRIPT=`dirname "$SCRIPT"`/"$link" + fi +done + +# determine license home +LICENSE_HOME=`dirname "$SCRIPT"`/.. + +# make LICENSE_HOME absolute +LICENSE_HOME=`cd "$LICENSE_HOME"; pwd` + +# setup classpath +LICENSE_CLASSPATH=$LICENSE_CLASSPATH:$LICENSE_HOME/lib/${project.artifactId}-${project.version}-exec.jar:$LICENSE_HOME/lib/* + +if [ -x "$JAVA_HOME/bin/java" ]; then + JAVA=$JAVA_HOME/bin/java +else + JAVA=`which java` +fi + +# Parse any long getopt options and put them into properties before calling getopt below +# Be dash compatible to make sure running under ubuntu works +ARGCOUNT=$# +COUNT=0 +while [ $COUNT -lt $ARGCOUNT ] +do + case $1 in + -D*=*) + properties="$properties $1" + shift 1; COUNT=$(($COUNT+1)) + ;; + -D*) + properties="$properties $1=$2" + shift ; shift; COUNT=$(($COUNT+2)) + ;; + *) set -- "$@" "$1"; shift; COUNT=$(($COUNT+1)) + esac +done + +exec "$JAVA" $JAVA_OPTS -Xmx64m -Xms16m $properties -cp "$LICENSE_CLASSPATH" -Des.path.home="`pwd`" org.elasticsearch.license.licensor.tools.LicenseGeneratorTool "$@" diff --git a/elasticsearch/license/licensor/bin/verify-license b/elasticsearch/license/licensor/bin/verify-license new file mode 100755 index 00000000000..49762803123 --- /dev/null +++ b/elasticsearch/license/licensor/bin/verify-license @@ -0,0 +1,57 @@ +#!/bin/sh + +# 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. + +CDPATH="" +SCRIPT="$0" + +# SCRIPT may be an arbitrarily deep series of symlinks. Loop until we have the concrete path. +while [ -h "$SCRIPT" ] ; do + ls=`ls -ld "$SCRIPT"` + # Drop everything prior to -> + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + SCRIPT="$link" + else + SCRIPT=`dirname "$SCRIPT"`/"$link" + fi +done + +# determine license home +LICENSE_HOME=`dirname "$SCRIPT"`/.. + +# make LICENSE_HOME absolute +LICENSE_HOME=`cd "$LICENSE_HOME"; pwd` + +# setup classpath +LICENSE_CLASSPATH=$LICENSE_CLASSPATH:$LICENSE_HOME/lib/${project.artifactId}-${project.version}-exec.jar:$LICENSE_HOME/lib/* + +if [ -x "$JAVA_HOME/bin/java" ]; then + JAVA=$JAVA_HOME/bin/java +else + JAVA=`which java` +fi + +# Parse any long getopt options and put them into properties before calling getopt below +# Be dash compatible to make sure running under ubuntu works +ARGCOUNT=$# +COUNT=0 +while [ $COUNT -lt $ARGCOUNT ] +do + case $1 in + -D*=*) + properties="$properties $1" + shift 1; COUNT=$(($COUNT+1)) + ;; + -D*) + properties="$properties $1=$2" + shift ; shift; COUNT=$(($COUNT+2)) + ;; + *) set -- "$@" "$1"; shift; COUNT=$(($COUNT+1)) + esac +done + +exec "$JAVA" $JAVA_OPTS -Xmx64m -Xms16m $properties -cp "$LICENSE_CLASSPATH" -Des.path.home="`pwd`" org.elasticsearch.license.licensor.tools.LicenseVerificationTool "$@" + diff --git a/elasticsearch/license/licensor/build.gradle b/elasticsearch/license/licensor/build.gradle new file mode 100644 index 00000000000..e14cd0045d8 --- /dev/null +++ b/elasticsearch/license/licensor/build.gradle @@ -0,0 +1,9 @@ +apply plugin: 'elasticsearch.build' + +dependencies { + compile project(':x-plugins:elasticsearch:license:base') + compile "org.elasticsearch:elasticsearch:${version}" + testCompile "org.elasticsearch:test-framework:${version}" +} + +dependencyLicenses.enabled = false diff --git a/elasticsearch/license/licensor/dev-tools/integration-tests.xml b/elasticsearch/license/licensor/dev-tools/integration-tests.xml new file mode 100644 index 00000000000..153253fd27d --- /dev/null +++ b/elasticsearch/license/licensor/dev-tools/integration-tests.xml @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/elasticsearch/license/licensor/sample/license_spec.json b/elasticsearch/license/licensor/sample/license_spec.json new file mode 100644 index 00000000000..cff074c0e7d --- /dev/null +++ b/elasticsearch/license/licensor/sample/license_spec.json @@ -0,0 +1 @@ +{"licenses":[{"uid": "893361dc-9749-4997-93cb-802e3d7fa4a8", "type":"basic","issued_to":"issuedTo","issuer":"issuer","issue_date":"2014-09-29","expiry_date":"2030-08-29","max_nodes":1}]} diff --git a/elasticsearch/license/licensor/src/main/java/org/elasticsearch/license/licensor/LicenseSigner.java b/elasticsearch/license/licensor/src/main/java/org/elasticsearch/license/licensor/LicenseSigner.java new file mode 100644 index 00000000000..4f634978b1b --- /dev/null +++ b/elasticsearch/license/licensor/src/main/java/org/elasticsearch/license/licensor/LicenseSigner.java @@ -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.license.licensor; + +import org.elasticsearch.common.Base64; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.license.core.License; +import org.elasticsearch.license.core.CryptUtils; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.*; +import java.util.Collections; + +/** + * Responsible for generating a license signature according to + * the signature spec and sign it with the provided encrypted private key + */ +public class LicenseSigner { + + private final static int MAGIC_LENGTH = 13; + + private final Path publicKeyPath; + + private final Path privateKeyPath; + + public LicenseSigner(final Path privateKeyPath, final Path publicKeyPath) { + this.publicKeyPath = publicKeyPath; + this.privateKeyPath = privateKeyPath; + } + + /** + * Generates a signature for the licenseSpec. + * Signature structure: + * | VERSION | MAGIC | PUB_KEY_DIGEST | SIGNED_LICENSE_CONTENT | + * + * @return a signed License + */ + public License sign(License licenseSpec) throws IOException { + XContentBuilder contentBuilder = XContentFactory.contentBuilder(XContentType.JSON); + licenseSpec.toXContent(contentBuilder, new ToXContent.MapParams(Collections.singletonMap(License.LICENSE_SPEC_VIEW_MODE, "true"))); + final byte[] signedContent; + try { + final Signature rsa = Signature.getInstance("SHA512withRSA"); + rsa.initSign(CryptUtils.readEncryptedPrivateKey(Files.readAllBytes(privateKeyPath))); + rsa.update(contentBuilder.bytes().toBytes()); + signedContent = rsa.sign(); + } catch (InvalidKeyException | IOException | NoSuchAlgorithmException | SignatureException e) { + throw new IllegalStateException(e); + } + final byte[] magic = new byte[MAGIC_LENGTH]; + SecureRandom random = new SecureRandom(); + random.nextBytes(magic); + final byte[] hash = Base64.encodeBytesToBytes(Files.readAllBytes(publicKeyPath)); + assert hash != null; + byte[] bytes = new byte[4 + 4 + MAGIC_LENGTH + 4 + hash.length + 4 + signedContent.length]; + ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); + byteBuffer.putInt(licenseSpec.version()) + .putInt(magic.length) + .put(magic) + .putInt(hash.length) + .put(hash) + .putInt(signedContent.length) + .put(signedContent); + + return License.builder() + .fromLicenseSpec(licenseSpec, Base64.encodeBytes(bytes)) + .build(); + } +} diff --git a/elasticsearch/license/licensor/src/main/java/org/elasticsearch/license/licensor/tools/KeyPairGeneratorTool.java b/elasticsearch/license/licensor/src/main/java/org/elasticsearch/license/licensor/tools/KeyPairGeneratorTool.java new file mode 100644 index 00000000000..73c911e76fd --- /dev/null +++ b/elasticsearch/license/licensor/src/main/java/org/elasticsearch/license/licensor/tools/KeyPairGeneratorTool.java @@ -0,0 +1,108 @@ +/* + * 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.license.licensor.tools; + +import org.apache.commons.cli.CommandLine; +import org.elasticsearch.common.SuppressForbidden; +import org.elasticsearch.common.cli.CliTool; +import org.elasticsearch.common.cli.CliToolConfig; +import org.elasticsearch.common.cli.Terminal; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.env.Environment; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; + +import static org.elasticsearch.common.cli.CliToolConfig.Builder.cmd; +import static org.elasticsearch.common.cli.CliToolConfig.Builder.option; +import static org.elasticsearch.common.cli.CliToolConfig.config; +import static org.elasticsearch.license.core.CryptUtils.writeEncryptedPrivateKey; +import static org.elasticsearch.license.core.CryptUtils.writeEncryptedPublicKey; + +public class KeyPairGeneratorTool extends CliTool { + + public static final String NAME = "key-pair-generator"; + private static final CliToolConfig CONFIG = config("licensor", KeyPairGeneratorTool.class) + .cmds(KeyGenerator.CMD) + .build(); + + public KeyPairGeneratorTool() { + super(CONFIG); + } + + @Override + protected Command parse(String s, CommandLine commandLine) throws Exception { + return KeyGenerator.parse(terminal, commandLine, env); + } + + public static class KeyGenerator extends Command { + + private static final CliToolConfig.Cmd CMD = cmd(NAME, KeyGenerator.class) + .options( + option("pub", "publicKeyPath").required(true).hasArg(true), + option("pri", "privateKeyPath").required(true).hasArg(true) + ).build(); + + public final Path publicKeyPath; + public final Path privateKeyPath; + + protected KeyGenerator(Terminal terminal, Path publicKeyPath, Path privateKeyPath) { + super(terminal); + this.privateKeyPath = privateKeyPath; + this.publicKeyPath = publicKeyPath; + } + + public static Command parse(Terminal terminal, CommandLine commandLine, Environment environment) { + Path publicKeyPath = environment.binFile().getParent().resolve(commandLine.getOptionValue("publicKeyPath")); + Path privateKeyPath = environment.binFile().getParent().resolve(commandLine.getOptionValue("privateKeyPath")); + + if (Files.exists(privateKeyPath)) { + return exitCmd(ExitStatus.USAGE, terminal, privateKeyPath + " already exists"); + } else if (Files.exists(publicKeyPath)) { + return exitCmd(ExitStatus.USAGE, terminal, publicKeyPath + " already exists"); + } + return new KeyGenerator(terminal, publicKeyPath, privateKeyPath); + } + + @Override + public ExitStatus execute(Settings settings, Environment env) throws Exception { + KeyPair keyPair = generateKeyPair(privateKeyPath, publicKeyPath); + terminal.println(Terminal.Verbosity.VERBOSE, "generating key pair [public key: " + publicKeyPath + ", private key: " + privateKeyPath + "]"); + return (keyPair != null) ? ExitStatus.OK : ExitStatus.CANT_CREATE; + } + + private static KeyPair generateKeyPair(Path privateKeyPath, Path publicKeyPath) throws IOException, NoSuchAlgorithmException { + SecureRandom random = new SecureRandom(); + + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); + keyGen.initialize(2048, random); + KeyPair keyPair = keyGen.generateKeyPair(); + + saveKeyPairToFiles(keyPair, privateKeyPath, publicKeyPath); + return keyPair; + } + } + + private static void saveKeyPairToFiles(KeyPair keyPair, Path privateKeyPath, Path publicKeyPath) throws IOException { + Files.write(privateKeyPath, writeEncryptedPrivateKey(keyPair.getPrivate())); + Files.write(publicKeyPath, writeEncryptedPublicKey(keyPair.getPublic())); + } + + public static void main(String[] args) throws Exception { + ExitStatus exitStatus = new KeyPairGeneratorTool().execute(args); + exit(exitStatus.status()); + } + + @SuppressForbidden(reason = "Allowed to exit explicitly from #main()") + private static void exit(int status) { + System.exit(status); + } +} diff --git a/elasticsearch/license/licensor/src/main/java/org/elasticsearch/license/licensor/tools/LicenseGeneratorTool.java b/elasticsearch/license/licensor/src/main/java/org/elasticsearch/license/licensor/tools/LicenseGeneratorTool.java new file mode 100644 index 00000000000..0064a3a7fa4 --- /dev/null +++ b/elasticsearch/license/licensor/src/main/java/org/elasticsearch/license/licensor/tools/LicenseGeneratorTool.java @@ -0,0 +1,125 @@ +/* + * 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.license.licensor.tools; + +import org.apache.commons.cli.CommandLine; +import org.elasticsearch.common.SuppressForbidden; +import org.elasticsearch.common.cli.CliTool; +import org.elasticsearch.common.cli.CliToolConfig; +import org.elasticsearch.common.cli.Terminal; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.env.Environment; +import org.elasticsearch.license.core.License; +import org.elasticsearch.license.licensor.LicenseSigner; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import static org.elasticsearch.common.cli.CliToolConfig.Builder.cmd; +import static org.elasticsearch.common.cli.CliToolConfig.Builder.option; +import static org.elasticsearch.common.cli.CliToolConfig.config; + +public class LicenseGeneratorTool extends CliTool { + public static final String NAME = "license-generator"; + + private static final CliToolConfig CONFIG = config("licensor", LicenseGeneratorTool.class) + .cmds(LicenseGenerator.CMD) + .build(); + + public LicenseGeneratorTool() { + super(CONFIG); + } + + @Override + protected Command parse(String s, CommandLine commandLine) throws Exception { + return LicenseGenerator.parse(terminal, commandLine, env); + } + + public static class LicenseGenerator extends Command { + + private static final CliToolConfig.Cmd CMD = cmd(NAME, LicenseGenerator.class) + .options( + option("pub", "publicKeyPath").required(true).hasArg(true), + option("pri", "privateKeyPath").required(true).hasArg(true), + option("l", "license").required(false).hasArg(true), + option("lf", "licenseFile").required(false).hasArg(true) + ).build(); + + public final License licenseSpec; + public final Path publicKeyFilePath; + public final Path privateKeyFilePath; + + public LicenseGenerator(Terminal terminal, Path publicKeyFilePath, Path privateKeyFilePath, License licenseSpec) { + super(terminal); + this.licenseSpec = licenseSpec; + this.privateKeyFilePath = privateKeyFilePath; + this.publicKeyFilePath = publicKeyFilePath; + } + + public static Command parse(Terminal terminal, CommandLine commandLine, Environment environment) throws IOException { + Path publicKeyPath = environment.binFile().getParent().resolve(commandLine.getOptionValue("publicKeyPath")); + Path privateKeyPath = environment.binFile().getParent().resolve(commandLine.getOptionValue("privateKeyPath")); + String licenseSpecSource = commandLine.getOptionValue("license"); + String licenseSpecSourceFile = commandLine.getOptionValue("licenseFile"); + + if (!Files.exists(privateKeyPath)) { + return exitCmd(ExitStatus.USAGE, terminal, privateKeyPath + " does not exist"); + } else if (!Files.exists(publicKeyPath)) { + return exitCmd(ExitStatus.USAGE, terminal, publicKeyPath + " does not exist"); + } + + License license = null; + if (licenseSpecSource != null) { + license = License.fromSource(licenseSpecSource); + } else if (licenseSpecSourceFile != null) { + Path licenseSpecPath = environment.binFile().getParent().resolve(licenseSpecSourceFile); + if (!Files.exists(licenseSpecPath)) { + return exitCmd(ExitStatus.USAGE, terminal, licenseSpecSourceFile + " does not exist"); + } + license = License.fromSource(Files.readAllBytes(licenseSpecPath)); + } + + if (license == null) { + return exitCmd(ExitStatus.USAGE, terminal, "no license spec provided"); + } + return new LicenseGenerator(terminal, publicKeyPath, privateKeyPath, license); + } + + @Override + public ExitStatus execute(Settings settings, Environment env) throws Exception { + + // sign + License license = new LicenseSigner(privateKeyFilePath, publicKeyFilePath).sign(licenseSpec); + + // dump + XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON); + builder.startObject(); + builder.startObject("license"); + license.toInnerXContent(builder, ToXContent.EMPTY_PARAMS); + builder.endObject(); + builder.endObject(); + builder.flush(); + terminal.print(builder.string()); + + return ExitStatus.OK; + } + } + + public static void main(String[] args) throws Exception { + ExitStatus exitStatus = new LicenseGeneratorTool().execute(args); + exit(exitStatus.status()); + } + + @SuppressForbidden(reason = "Allowed to exit explicitly from #main()") + private static void exit(int status) { + System.exit(status); + } +} diff --git a/elasticsearch/license/licensor/src/main/java/org/elasticsearch/license/licensor/tools/LicenseVerificationTool.java b/elasticsearch/license/licensor/src/main/java/org/elasticsearch/license/licensor/tools/LicenseVerificationTool.java new file mode 100644 index 00000000000..58666e02bd8 --- /dev/null +++ b/elasticsearch/license/licensor/src/main/java/org/elasticsearch/license/licensor/tools/LicenseVerificationTool.java @@ -0,0 +1,117 @@ +/* + * 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.license.licensor.tools; + +import org.apache.commons.cli.CommandLine; +import org.elasticsearch.common.SuppressForbidden; +import org.elasticsearch.common.cli.CliTool; +import org.elasticsearch.common.cli.CliToolConfig; +import org.elasticsearch.common.cli.Terminal; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.env.Environment; +import org.elasticsearch.license.core.License; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import static org.elasticsearch.common.cli.CliToolConfig.Builder.cmd; +import static org.elasticsearch.common.cli.CliToolConfig.Builder.option; +import static org.elasticsearch.common.cli.CliToolConfig.config; + +public class LicenseVerificationTool extends CliTool { + public static final String NAME = "verify-license"; + + private static final CliToolConfig CONFIG = config("licensor", LicenseVerificationTool.class) + .cmds(LicenseVerifier.CMD) + .build(); + + public LicenseVerificationTool() { + super(CONFIG); + } + + @Override + protected Command parse(String s, CommandLine commandLine) throws Exception { + return LicenseVerifier.parse(terminal, commandLine, env); + } + + public static class LicenseVerifier extends Command { + + private static final CliToolConfig.Cmd CMD = cmd(NAME, LicenseVerifier.class) + .options( + option("pub", "publicKeyPath").required(true).hasArg(true), + option("l", "license").required(false).hasArg(true), + option("lf", "licenseFile").required(false).hasArg(true) + ).build(); + + public final License license; + public final Path publicKeyPath; + + public LicenseVerifier(Terminal terminal, License license, Path publicKeyPath) { + super(terminal); + this.license = license; + this.publicKeyPath = publicKeyPath; + } + + public static Command parse(Terminal terminal, CommandLine commandLine, Environment environment) throws IOException { + String publicKeyPathString = commandLine.getOptionValue("publicKeyPath"); + String licenseSource = commandLine.getOptionValue("license"); + String licenseSourceFile = commandLine.getOptionValue("licenseFile"); + + License license = null; + if (licenseSource != null) { + license = License.fromSource(licenseSource); + } else if (licenseSourceFile != null) { + Path licenseSpecPath = environment.binFile().getParent().resolve(licenseSourceFile); + if (!Files.exists(licenseSpecPath)) { + return exitCmd(ExitStatus.USAGE, terminal, licenseSourceFile + " does not exist"); + } + license = License.fromSource(Files.readAllBytes(licenseSpecPath)); + } + if (license == null) { + return exitCmd(ExitStatus.USAGE, terminal, "no license spec provided"); + } + Path publicKeyPath = environment.binFile().getParent().resolve(publicKeyPathString); + if (!Files.exists(publicKeyPath)) { + return exitCmd(ExitStatus.USAGE, terminal, publicKeyPath + " does not exist"); + } + return new LicenseVerifier(terminal, license, publicKeyPath); + } + + @Override + public ExitStatus execute(Settings settings, Environment env) throws Exception { + + // verify + if (!org.elasticsearch.license.core.LicenseVerifier.verifyLicense(license, Files.readAllBytes(publicKeyPath))) { + terminal.println("Invalid License!"); + return ExitStatus.DATA_ERROR; + } + XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON); + builder.startObject(); + builder.startObject("license"); + license.toInnerXContent(builder, ToXContent.EMPTY_PARAMS); + builder.endObject(); + builder.endObject(); + builder.flush(); + terminal.print(builder.string()); + return ExitStatus.OK; + } + } + + public static void main(String[] args) throws Exception { + ExitStatus exitStatus = new LicenseVerificationTool().execute(args); + exit(exitStatus.status()); + } + + @SuppressForbidden(reason = "Allowed to exit explicitly from #main()") + private static void exit(int status) { + System.exit(status); + } +} diff --git a/elasticsearch/license/licensor/src/main/resources/org/elasticsearch/license/licensor/tools/licensor-key-pair-generator.help b/elasticsearch/license/licensor/src/main/resources/org/elasticsearch/license/licensor/tools/licensor-key-pair-generator.help new file mode 100644 index 00000000000..c41ed5c0ed7 --- /dev/null +++ b/elasticsearch/license/licensor/src/main/resources/org/elasticsearch/license/licensor/tools/licensor-key-pair-generator.help @@ -0,0 +1,22 @@ +NAME + + key-pair-generator - generates a key pair with RSA 2048-bit security + +SYNOPSIS + + key-pair-generator -pub publicKeyPath -pri privateKeyPath + +DESCRIPTION + + This tool generates and saves a key pair to the provided publicKeyPath + and privateKeyPath. The tool checks the existence of the provided key paths + and will not override if any existing keys are found. + +OPTIONS + + -h,--help Shows this message + + -pub,--publicKeyPath Save the generated public key to path + + -pri,--privateKeyPath Save the generated private key to path + diff --git a/elasticsearch/license/licensor/src/main/resources/org/elasticsearch/license/licensor/tools/licensor-license-generator.help b/elasticsearch/license/licensor/src/main/resources/org/elasticsearch/license/licensor/tools/licensor-license-generator.help new file mode 100644 index 00000000000..75d507f7dd9 --- /dev/null +++ b/elasticsearch/license/licensor/src/main/resources/org/elasticsearch/license/licensor/tools/licensor-license-generator.help @@ -0,0 +1,26 @@ +NAME + + license-generator - generates signed elasticsearch license(s) for a given license spec(s) + +SYNOPSIS + + license-generator -l licenseSpec -pub publicKeyPath -pri privateKeyPath + +DESCRIPTION + + This tool generate elasticsearch license(s) for the provided license spec(s). The tool + can take arbitrary number of `--license` and/or `--licenseFile` to generate corrosponding + signed license(s). + +OPTIONS + + -h,--help Shows this message + + -l,--license License spec to generate a signed license from + + -lf,--licenseFile Path to a license spec file + + -pub,--publicKeyPath Path to public key to be used + + -pri,--privateKeyPath Path to private key to be used + diff --git a/elasticsearch/license/licensor/src/main/resources/org/elasticsearch/license/licensor/tools/licensor-verify-license.help b/elasticsearch/license/licensor/src/main/resources/org/elasticsearch/license/licensor/tools/licensor-verify-license.help new file mode 100644 index 00000000000..e36007f3838 --- /dev/null +++ b/elasticsearch/license/licensor/src/main/resources/org/elasticsearch/license/licensor/tools/licensor-verify-license.help @@ -0,0 +1,28 @@ +NAME + + verify-license - verifies the integrity of elasticsearch signed license(s) + +SYNOPSIS + + verify-license -l signedLicense -pub publicKeyPath + +DESCRIPTION + + This tool assumes the configured public key to be the same as that of the production license plugin public key. + The tool can take arbitrary number of `--license` and/or `--licenseFile` for verifying signed license(s). If any + of the provided license(s) are invalid, the tool will error out, otherwise it will output a effective licenses file. + + Effective Licenses: + A set of licenses that only has one effective sub-license for every feature provided through the input license file. + Where effective sub-licenses are identified as the sub-licenses with the latest `expiry_date` for a `feature` + and the sub-license has not already expired. + +OPTIONS + + -h,--help Shows this message + + -l,--license signed license(s) string + + -lf,--licenseFile Path to signed license(s) file + + -pub,--publicKeyPath Path to public key to verify against diff --git a/elasticsearch/license/licensor/src/test/java/org/elasticsearch/license/licensor/LicenseVerificationTests.java b/elasticsearch/license/licensor/src/test/java/org/elasticsearch/license/licensor/LicenseVerificationTests.java new file mode 100644 index 00000000000..4e081953d6e --- /dev/null +++ b/elasticsearch/license/licensor/src/test/java/org/elasticsearch/license/licensor/LicenseVerificationTests.java @@ -0,0 +1,83 @@ +/* + * 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.license.licensor; + +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.license.core.DateUtils; +import org.elasticsearch.license.core.License; +import org.elasticsearch.license.core.LicenseVerifier; +import org.elasticsearch.test.ESTestCase; +import org.junit.After; +import org.junit.Before; + +import java.nio.file.Files; +import java.nio.file.Path; + +import static org.hamcrest.Matchers.equalTo; + +public class LicenseVerificationTests extends ESTestCase { + protected Path pubKeyPath = null; + protected Path priKeyPath = null; + + @Before + public void setup() throws Exception { + pubKeyPath = getDataPath("/public.key"); + priKeyPath = getDataPath("/private.key"); + } + + @After + public void cleanUp() { + pubKeyPath = null; + priKeyPath = null; + } + + public void testGeneratedLicenses() throws Exception { + assertThat(LicenseVerifier.verifyLicense(TestUtils.generateSignedLicense(TimeValue.timeValueHours(2 * 24), pubKeyPath, priKeyPath), Files.readAllBytes(pubKeyPath)), equalTo(true)); + } + + public void testLicenseTampering() throws Exception { + License license = TestUtils.generateSignedLicense(TimeValue.timeValueHours(2), pubKeyPath, priKeyPath); + + final License tamperedLicense = License.builder() + .fromLicenseSpec(license, license.signature()) + .expiryDate(license.expiryDate() + 10 * 24 * 60 * 60 * 1000l) + .validate() + .build(); + + assertThat(LicenseVerifier.verifyLicense(tamperedLicense, Files.readAllBytes(pubKeyPath)), equalTo(false)); + } + + public void testRandomLicenseVerification() throws Exception { + TestUtils.LicenseSpec licenseSpec = TestUtils.generateRandomLicenseSpec(randomIntBetween(License.VERSION_START, License.VERSION_CURRENT)); + License generatedLicense = generateSignedLicense(licenseSpec, pubKeyPath, priKeyPath); + assertThat(LicenseVerifier.verifyLicense(generatedLicense, Files.readAllBytes(pubKeyPath)), equalTo(true)); + } + + private static License generateSignedLicense(TestUtils.LicenseSpec spec, Path pubKeyPath, Path priKeyPath) throws Exception { + LicenseSigner signer = new LicenseSigner(priKeyPath, pubKeyPath); + License.Builder builder = License.builder() + .uid(spec.uid) + .feature(spec.feature) + .type(spec.type) + .subscriptionType(spec.subscriptionType) + .issuedTo(spec.issuedTo) + .issuer(spec.issuer) + .maxNodes(spec.maxNodes); + + if (spec.expiryDate != null) { + builder.expiryDate(DateUtils.endOfTheDay(spec.expiryDate)); + } else { + builder.expiryDate(spec.expiryDateInMillis); + } + if (spec.issueDate != null) { + builder.issueDate(DateUtils.beginningOfTheDay(spec.issueDate)); + } else { + builder.issueDate(spec.issueDateInMillis); + } + builder.version(spec.version); + return signer.sign(builder.build()); + } +} diff --git a/elasticsearch/license/licensor/src/test/java/org/elasticsearch/license/licensor/TestUtils.java b/elasticsearch/license/licensor/src/test/java/org/elasticsearch/license/licensor/TestUtils.java new file mode 100644 index 00000000000..4ca5fdb07e5 --- /dev/null +++ b/elasticsearch/license/licensor/src/test/java/org/elasticsearch/license/licensor/TestUtils.java @@ -0,0 +1,214 @@ +/* + * 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.license.licensor; + +import org.elasticsearch.common.joda.DateMathParser; +import org.elasticsearch.common.joda.FormatDateTimeFormatter; +import org.elasticsearch.common.joda.Joda; +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.license.core.DateUtils; +import org.elasticsearch.license.core.License; +import org.elasticsearch.test.ESTestCase; +import org.hamcrest.MatcherAssert; +import org.joda.time.format.DateTimeFormatter; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.*; +import java.util.concurrent.Callable; + +import static com.carrotsearch.randomizedtesting.RandomizedTest.*; +import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; +import static org.elasticsearch.test.ESTestCase.randomFrom; +import static org.hamcrest.core.IsEqual.equalTo; + +public class TestUtils { + + public static final String PUBLIC_KEY_RESOURCE = "/public.key"; + public static final String PRIVATE_KEY_RESOURCE = "/private.key"; + + private final static FormatDateTimeFormatter formatDateTimeFormatter = Joda.forPattern("yyyy-MM-dd"); + private final static DateMathParser dateMathParser = new DateMathParser(formatDateTimeFormatter); + private final static DateTimeFormatter dateTimeFormatter = formatDateTimeFormatter.printer(); + + public static String dumpLicense(License license) throws Exception { + XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON); + builder.startObject(); + builder.startObject("license"); + license.toInnerXContent(builder, ToXContent.EMPTY_PARAMS); + builder.endObject(); + builder.endObject(); + return builder.string(); + } + + public static String dateMathString(String time, final long now) { + return dateTimeFormatter.print(dateMathParser.parse(time, new Callable() { + @Override + public Long call() throws Exception { + return now; + } + })); + } + + public static long dateMath(String time, final long now) { + return dateMathParser.parse(time, new Callable() { + @Override + public Long call() throws Exception { + return now; + } + }); + } + + public static LicenseSpec generateRandomLicenseSpec(int version) { + boolean datesInMillis = randomBoolean(); + long now = System.currentTimeMillis(); + String uid = UUID.randomUUID().toString(); + String issuer = "issuer__" + randomInt(); + String issuedTo = "issuedTo__" + randomInt(); + String type = version < License.VERSION_NO_FEATURE_TYPE ? + randomFrom("subscription", "internal", "development") : + randomFrom("basic", "silver", "dev", "gold", "platinum"); + final String subscriptionType; + final String feature; + if (version < License.VERSION_NO_FEATURE_TYPE) { + subscriptionType = randomFrom("gold", "silver", "platinum"); + feature = "feature__" + randomInt(); + } else { + subscriptionType = null; + feature = null; + } + int maxNodes = randomIntBetween(5, 100); + if (datesInMillis) { + long issueDateInMillis = dateMath("now", now); + long expiryDateInMillis = dateMath("now+10d/d", now); + return new LicenseSpec(version, uid, feature, issueDateInMillis, expiryDateInMillis, type, subscriptionType, issuedTo, issuer, maxNodes); + } else { + String issueDate = dateMathString("now", now); + String expiryDate = dateMathString("now+10d/d", now); + return new LicenseSpec(version, uid, feature, issueDate, expiryDate, type, subscriptionType, issuedTo, issuer, maxNodes); + } + } + + public static String generateLicenseSpecString(LicenseSpec licenseSpec) throws IOException { + XContentBuilder licenses = jsonBuilder(); + licenses.startObject(); + licenses.startObject("license") + .field("uid", licenseSpec.uid) + .field("type", licenseSpec.type) + .field("subscription_type", licenseSpec.subscriptionType) + .field("issued_to", licenseSpec.issuedTo) + .field("issuer", licenseSpec.issuer) + .field("feature", licenseSpec.feature) + .field("max_nodes", licenseSpec.maxNodes); + + if (licenseSpec.issueDate != null) { + licenses.field("issue_date", licenseSpec.issueDate); + } else { + licenses.field("issue_date_in_millis", licenseSpec.issueDateInMillis); + } + if (licenseSpec.expiryDate != null) { + licenses.field("expiry_date", licenseSpec.expiryDate); + } else { + licenses.field("expiry_date_in_millis", licenseSpec.expiryDateInMillis); + } + licenses.field("version", licenseSpec.version); + licenses.endObject(); + licenses.endObject(); + return licenses.string(); + } + + public static void assertLicenseSpec(LicenseSpec spec, License license) { + MatcherAssert.assertThat(license.uid(), equalTo(spec.uid)); + MatcherAssert.assertThat(license.issuedTo(), equalTo(spec.issuedTo)); + MatcherAssert.assertThat(license.issuer(), equalTo(spec.issuer)); + MatcherAssert.assertThat(license.type(), equalTo(spec.type)); + MatcherAssert.assertThat(license.maxNodes(), equalTo(spec.maxNodes)); + if (spec.issueDate != null) { + MatcherAssert.assertThat(license.issueDate(), equalTo(DateUtils.beginningOfTheDay(spec.issueDate))); + } else { + MatcherAssert.assertThat(license.issueDate(), equalTo(spec.issueDateInMillis)); + } + if (spec.expiryDate != null) { + MatcherAssert.assertThat(license.expiryDate(), equalTo(DateUtils.endOfTheDay(spec.expiryDate))); + } else { + MatcherAssert.assertThat(license.expiryDate(), equalTo(spec.expiryDateInMillis)); + } + } + + public static License generateSignedLicense(TimeValue expiryDuration, Path pubKeyPath, Path priKeyPath) throws Exception { + long issue = System.currentTimeMillis(); + int version = ESTestCase.randomIntBetween(License.VERSION_START, License.VERSION_CURRENT); + String type = version < License.VERSION_NO_FEATURE_TYPE ? + randomFrom("subscription", "internal", "development") : + randomFrom("trial", "basic", "silver", "dev", "gold", "platinum"); + final License.Builder builder = License.builder() + .uid(UUID.randomUUID().toString()) + .expiryDate(issue + expiryDuration.getMillis()) + .issueDate(issue) + .version(version) + .type(type) + .issuedTo("customer") + .issuer("elasticsearch") + .maxNodes(5); + if (version == License.VERSION_START) { + builder.subscriptionType(randomFrom("dev", "gold", "platinum", "silver")); + builder.feature(ESTestCase.randomAsciiOfLength(10)); + } + LicenseSigner signer = new LicenseSigner(priKeyPath, pubKeyPath); + return signer.sign(builder.build()); + } + + public static class LicenseSpec { + public final int version; + public final String feature; + public final String issueDate; + public final long issueDateInMillis; + public final String expiryDate; + public final long expiryDateInMillis; + public final String uid; + public final String type; + public final String subscriptionType; + public final String issuedTo; + public final String issuer; + public final int maxNodes; + + public LicenseSpec(int version, String uid, String feature, long issueDateInMillis, long expiryDateInMillis, String type, + String subscriptionType, String issuedTo, String issuer, int maxNodes) { + this.version = version; + this.feature = feature; + this.issueDateInMillis = issueDateInMillis; + this.issueDate = null; + this.expiryDateInMillis = expiryDateInMillis; + this.expiryDate = null; + this.uid = uid; + this.type = type; + this.subscriptionType = subscriptionType; + this.issuedTo = issuedTo; + this.issuer = issuer; + this.maxNodes = maxNodes; + } + + public LicenseSpec(int version, String uid, String feature, String issueDate, String expiryDate, String type, + String subscriptionType, String issuedTo, String issuer, int maxNodes) { + this.version = version; + this.feature = feature; + this.issueDate = issueDate; + this.issueDateInMillis = -1; + this.expiryDate = expiryDate; + this.expiryDateInMillis = -1; + this.uid = uid; + this.type = type; + this.subscriptionType = subscriptionType; + this.issuedTo = issuedTo; + this.issuer = issuer; + this.maxNodes = maxNodes; + } + } +} diff --git a/elasticsearch/license/licensor/src/test/java/org/elasticsearch/license/licensor/tools/KeyPairGenerationToolTests.java b/elasticsearch/license/licensor/src/test/java/org/elasticsearch/license/licensor/tools/KeyPairGenerationToolTests.java new file mode 100644 index 00000000000..a70e646e292 --- /dev/null +++ b/elasticsearch/license/licensor/src/test/java/org/elasticsearch/license/licensor/tools/KeyPairGenerationToolTests.java @@ -0,0 +1,95 @@ +/* + * 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.license.licensor.tools; + +import org.apache.commons.cli.MissingOptionException; +import org.elasticsearch.common.cli.CliTool.Command; +import org.elasticsearch.common.cli.CliTool.ExitStatus; +import org.elasticsearch.common.cli.CliToolTestCase; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.env.Environment; +import org.elasticsearch.license.licensor.tools.KeyPairGeneratorTool.KeyGenerator; + +import java.nio.file.Files; +import java.nio.file.Path; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.core.IsEqual.equalTo; + +public class KeyPairGenerationToolTests extends CliToolTestCase { + public void testParsingMissingPath() throws Exception { + KeyPairGeneratorTool keyPairGeneratorTool = new KeyPairGeneratorTool(); + Path tempFile = createTempFile(); + try { + keyPairGeneratorTool.parse(KeyPairGeneratorTool.NAME, + new String[] { "--privateKeyPath", tempFile.toAbsolutePath().toString() }); + fail("no public key path provided"); + } catch (MissingOptionException e) { + assertThat(e.getMessage(), containsString("pub")); + } + try { + keyPairGeneratorTool.parse(KeyPairGeneratorTool.NAME, + new String[] { "--publicKeyPath", tempFile.toAbsolutePath().toString() }); + fail("no private key path provided"); + } catch (MissingOptionException e) { + assertThat(e.getMessage(), containsString("pri")); + } + } + + public void testParsingNeverOverrideKey() throws Exception { + KeyPairGeneratorTool keyPairGeneratorTool = new KeyPairGeneratorTool(); + Path tempFile = createTempFile(); + Path tempFile2 = createTempFile(); + String nonExistentFilePath = tempFile2.toAbsolutePath().toString(); + Files.delete(tempFile2); + assertThat(Files.exists(tempFile2), equalTo(false)); + + Command command = keyPairGeneratorTool.parse(KeyPairGeneratorTool.NAME, new String[] {"--privateKeyPath", tempFile.toAbsolutePath().toString(), + "--publicKeyPath", nonExistentFilePath }); + + assertThat(command, instanceOf(Command.Exit.class)); + Command.Exit exitCommand = (Command.Exit) command; + assertThat(exitCommand.status(), equalTo(ExitStatus.USAGE)); + + command = keyPairGeneratorTool.parse(KeyPairGeneratorTool.NAME, new String[] {"--publicKeyPath", tempFile.toAbsolutePath().toString(), + "--privateKeyPath", nonExistentFilePath }); + + assertThat(command, instanceOf(Command.Exit.class)); + exitCommand = (Command.Exit) command; + assertThat(exitCommand.status(), equalTo(ExitStatus.USAGE)); + } + + public void testToolSimple() throws Exception { + KeyPairGeneratorTool keyPairGeneratorTool = new KeyPairGeneratorTool(); + Path publicKeyFilePath = createTempFile().toAbsolutePath(); + Path privateKeyFilePath = createTempFile().toAbsolutePath(); + Settings settings = Settings.builder().put("path.home", createTempDir("KeyPairGenerationToolTests")).build(); + + Files.delete(publicKeyFilePath); + Files.delete(privateKeyFilePath); + assertThat(Files.exists(publicKeyFilePath), equalTo(false)); + assertThat(Files.exists(privateKeyFilePath), equalTo(false)); + + Command command = keyPairGeneratorTool.parse(KeyPairGeneratorTool.NAME, new String[] { "--privateKeyPath", privateKeyFilePath.toString(), + "--publicKeyPath", publicKeyFilePath.toString() }); + + assertThat(command, instanceOf(KeyGenerator.class)); + KeyGenerator keyGenerator = (KeyGenerator) command; + assertThat(keyGenerator.privateKeyPath, equalTo(privateKeyFilePath)); + assertThat(keyGenerator.publicKeyPath, equalTo(publicKeyFilePath)); + + assertThat(Files.exists(publicKeyFilePath), equalTo(false)); + assertThat(Files.exists(privateKeyFilePath), equalTo(false)); + + assertThat(keyGenerator.execute(settings, new Environment(settings)), equalTo(ExitStatus.OK)); + assertThat(Files.exists(publicKeyFilePath), equalTo(true)); + assertThat(Files.exists(privateKeyFilePath), equalTo(true)); + + Files.delete(publicKeyFilePath); + Files.delete(privateKeyFilePath); + } +} diff --git a/elasticsearch/license/licensor/src/test/java/org/elasticsearch/license/licensor/tools/LicenseGenerationToolTests.java b/elasticsearch/license/licensor/src/test/java/org/elasticsearch/license/licensor/tools/LicenseGenerationToolTests.java new file mode 100644 index 00000000000..578b6b42a71 --- /dev/null +++ b/elasticsearch/license/licensor/src/test/java/org/elasticsearch/license/licensor/tools/LicenseGenerationToolTests.java @@ -0,0 +1,140 @@ +/* + * 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.license.licensor.tools; + +import org.apache.commons.cli.MissingOptionException; +import org.elasticsearch.common.cli.CliTool.Command; +import org.elasticsearch.common.cli.CliTool.ExitStatus; +import org.elasticsearch.common.cli.CliToolTestCase; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.env.Environment; +import org.elasticsearch.license.core.License; +import org.elasticsearch.license.licensor.TestUtils; +import org.elasticsearch.license.licensor.tools.LicenseGeneratorTool.LicenseGenerator; +import org.junit.Before; + +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.core.IsEqual.equalTo; + +public class LicenseGenerationToolTests extends CliToolTestCase { + protected Path pubKeyPath = null; + protected Path priKeyPath = null; + + @Before + public void setup() throws Exception { + logger.error("project.basedir [{}]", System.getProperty("project.basedir")); + pubKeyPath = getDataPath(TestUtils.PUBLIC_KEY_RESOURCE); + priKeyPath = getDataPath(TestUtils.PRIVATE_KEY_RESOURCE); + } + + public void testParsingNonExistentKeyFile() throws Exception { + TestUtils.LicenseSpec inputLicenseSpec = TestUtils.generateRandomLicenseSpec(License.VERSION_CURRENT); + LicenseGeneratorTool licenseGeneratorTool = new LicenseGeneratorTool(); + Command command = licenseGeneratorTool.parse(LicenseGeneratorTool.NAME, + new String[] {"--license", TestUtils.generateLicenseSpecString(inputLicenseSpec), + "--publicKeyPath", pubKeyPath.toString().concat("invalid"), + "--privateKeyPath", priKeyPath.toString() }); + + assertThat(command, instanceOf(Command.Exit.class)); + Command.Exit exitCommand = (Command.Exit) command; + assertThat(exitCommand.status(), equalTo(ExitStatus.USAGE)); + + command = licenseGeneratorTool.parse(LicenseGeneratorTool.NAME, + new String[] {"--license", TestUtils.generateLicenseSpecString(inputLicenseSpec), + "--privateKeyPath", priKeyPath.toString().concat("invalid"), + "--publicKeyPath", pubKeyPath.toString() }); + + assertThat(command, instanceOf(Command.Exit.class)); + exitCommand = (Command.Exit) command; + assertThat(exitCommand.status(), equalTo(ExitStatus.USAGE)); + } + + public void testParsingMissingLicenseSpec() throws Exception { + LicenseGeneratorTool licenseGeneratorTool = new LicenseGeneratorTool(); + Command command = licenseGeneratorTool.parse(LicenseGeneratorTool.NAME, + new String[] { "--publicKeyPath", pubKeyPath.toString(), + "--privateKeyPath", priKeyPath.toString() }); + + assertThat(command, instanceOf(Command.Exit.class)); + Command.Exit exitCommand = (Command.Exit) command; + assertThat(exitCommand.status(), equalTo(ExitStatus.USAGE)); + } + + public void testParsingMissingArgs() throws Exception { + TestUtils.LicenseSpec inputLicenseSpec = TestUtils.generateRandomLicenseSpec(License.VERSION_CURRENT); + LicenseGeneratorTool licenseGeneratorTool = new LicenseGeneratorTool(); + boolean pubKeyMissing = randomBoolean(); + try { + licenseGeneratorTool.parse(LicenseGeneratorTool.NAME, + new String[] { "--license", TestUtils.generateLicenseSpecString(inputLicenseSpec), + ((pubKeyMissing) ? "--privateKeyPath" : "--publicKeyPath"), + ((pubKeyMissing) ? priKeyPath.toString() : pubKeyPath.toString()) }); + fail("missing argument: " + ((pubKeyMissing) ? "publicKeyPath" : "privateKeyPath") + " should throw an exception"); + } catch (MissingOptionException e) { + assertThat(e.getMessage(), containsString((pubKeyMissing) ? "pub" : "pri")); + } + } + + public void testParsingSimple() throws Exception { + TestUtils.LicenseSpec inputLicenseSpec = TestUtils.generateRandomLicenseSpec(License.VERSION_CURRENT); + LicenseGeneratorTool licenseGeneratorTool = new LicenseGeneratorTool(); + Command command = licenseGeneratorTool.parse(LicenseGeneratorTool.NAME, + new String[]{"--license", TestUtils.generateLicenseSpecString(inputLicenseSpec), + "--publicKeyPath", pubKeyPath.toString(), + "--privateKeyPath", priKeyPath.toString() }); + + assertThat(command, instanceOf(LicenseGenerator.class)); + LicenseGenerator licenseGenerator = (LicenseGenerator) command; + assertThat(licenseGenerator.publicKeyFilePath, equalTo(pubKeyPath)); + assertThat(licenseGenerator.privateKeyFilePath, equalTo(priKeyPath)); + TestUtils.assertLicenseSpec(inputLicenseSpec, licenseGenerator.licenseSpec); + } + + public void testParsingLicenseFile() throws Exception { + TestUtils.LicenseSpec inputLicenseSpec = TestUtils.generateRandomLicenseSpec(License.VERSION_CURRENT); + Path tempFile = createTempFile(); + Files.write(tempFile, TestUtils.generateLicenseSpecString(inputLicenseSpec).getBytes(StandardCharsets.UTF_8)); + + LicenseGeneratorTool licenseGeneratorTool = new LicenseGeneratorTool(); + Command command = licenseGeneratorTool.parse(LicenseGeneratorTool.NAME, + new String[] { "--licenseFile", tempFile.toAbsolutePath().toString(), + "--publicKeyPath", pubKeyPath.toString(), + "--privateKeyPath", priKeyPath.toString() }); + + assertThat(command, instanceOf(LicenseGenerator.class)); + LicenseGenerator licenseGenerator = (LicenseGenerator) command; + assertThat(licenseGenerator.publicKeyFilePath, equalTo(pubKeyPath)); + assertThat(licenseGenerator.privateKeyFilePath, equalTo(priKeyPath)); + TestUtils.assertLicenseSpec(inputLicenseSpec, licenseGenerator.licenseSpec); + } + + public void testTool() throws Exception { + TestUtils.LicenseSpec licenseSpec = TestUtils.generateRandomLicenseSpec(License.VERSION_CURRENT); + License license = License.fromSource(TestUtils.generateLicenseSpecString(licenseSpec).getBytes(StandardCharsets.UTF_8)); + String output = runLicenseGenerationTool(pubKeyPath, priKeyPath, license, ExitStatus.OK); + License outputLicense = License.fromSource(output.getBytes(StandardCharsets.UTF_8)); + TestUtils.assertLicenseSpec(licenseSpec, outputLicense); + } + + private String runLicenseGenerationTool(Path pubKeyPath, Path priKeyPath, License licenseSpec, ExitStatus expectedExitStatus) throws Exception { + CaptureOutputTerminal outputTerminal = new CaptureOutputTerminal(); + Settings settings = Settings.builder().put("path.home", createTempDir("LicenseGenerationToolTests")).build(); + LicenseGenerator licenseGenerator = new LicenseGenerator(outputTerminal, pubKeyPath, priKeyPath, licenseSpec); + assertThat(execute(licenseGenerator, settings), equalTo(expectedExitStatus)); + assertThat(outputTerminal.getTerminalOutput().size(), equalTo(1)); + return outputTerminal.getTerminalOutput().get(0); + } + + private ExitStatus execute(Command cmd, Settings settings) throws Exception { + Environment env = new Environment(settings); + return cmd.execute(settings, env); + } +} diff --git a/elasticsearch/license/licensor/src/test/java/org/elasticsearch/license/licensor/tools/LicenseVerificationToolTests.java b/elasticsearch/license/licensor/src/test/java/org/elasticsearch/license/licensor/tools/LicenseVerificationToolTests.java new file mode 100644 index 00000000000..16a5bb70b00 --- /dev/null +++ b/elasticsearch/license/licensor/src/test/java/org/elasticsearch/license/licensor/tools/LicenseVerificationToolTests.java @@ -0,0 +1,154 @@ +/* + * 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.license.licensor.tools; + +import org.apache.commons.cli.MissingOptionException; +import org.elasticsearch.common.cli.CliTool.Command; +import org.elasticsearch.common.cli.CliTool.ExitStatus; +import org.elasticsearch.common.cli.CliToolTestCase; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.env.Environment; +import org.elasticsearch.license.core.License; +import org.elasticsearch.license.licensor.TestUtils; +import org.elasticsearch.license.licensor.tools.LicenseVerificationTool.LicenseVerifier; +import org.hamcrest.CoreMatchers; +import org.junit.Before; + +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.core.IsEqual.equalTo; + +public class LicenseVerificationToolTests extends CliToolTestCase { + protected Path pubKeyPath = null; + protected Path priKeyPath = null; + + @Before + public void setup() throws Exception { + logger.error("project.basedir [{}]", System.getProperty("project.basedir")); + pubKeyPath = getDataPath(TestUtils.PUBLIC_KEY_RESOURCE); + priKeyPath = getDataPath(TestUtils.PRIVATE_KEY_RESOURCE); + } + + public void testParsingMissingLicense() throws Exception { + LicenseVerificationTool licenseVerificationTool = new LicenseVerificationTool(); + Path path = getDataPath(TestUtils.PUBLIC_KEY_RESOURCE); + Command command = licenseVerificationTool.parse(LicenseVerificationTool.NAME, new String[] { "--publicKeyPath", path.toString() }); + + assertThat(command, instanceOf(Command.Exit.class)); + Command.Exit exitCommand = (Command.Exit) command; + assertThat(exitCommand.status(), equalTo(ExitStatus.USAGE)); + } + + public void testParsingMissingPublicKeyPath() throws Exception { + License inputLicense = TestUtils.generateSignedLicense(TimeValue.timeValueHours(1), pubKeyPath, priKeyPath); + LicenseVerificationTool licenseVerificationTool = new LicenseVerificationTool(); + try { + licenseVerificationTool.parse(LicenseVerificationTool.NAME, + new String[] { "--license", TestUtils.dumpLicense(inputLicense) }); + } catch (MissingOptionException e) { + assertThat(e.getMessage(), containsString("pub")); + } + } + + public void testParsingNonExistentPublicKeyPath() throws Exception { + LicenseVerificationTool licenseVerificationTool = new LicenseVerificationTool(); + Path path = getDataPath(TestUtils.PUBLIC_KEY_RESOURCE); + Command command = licenseVerificationTool.parse(LicenseVerificationTool.NAME, + new String[] { "--publicKeyPath", path.toString().concat(".invalid") }); + + assertThat(command, instanceOf(Command.Exit.class)); + Command.Exit exitCommand = (Command.Exit) command; + assertThat(exitCommand.status(), equalTo(ExitStatus.USAGE)); + } + + public void testParsingSimple() throws Exception { + License inputLicense = TestUtils.generateSignedLicense(TimeValue.timeValueHours(1), pubKeyPath, priKeyPath); + LicenseVerificationTool licenseVerificationTool = new LicenseVerificationTool(); + Command command = licenseVerificationTool.parse(LicenseVerificationTool.NAME, + new String[] { "--license", TestUtils.dumpLicense(inputLicense), + "--publicKeyPath", getDataPath(TestUtils.PUBLIC_KEY_RESOURCE).toString() }); + assertThat(command, instanceOf(LicenseVerifier.class)); + LicenseVerifier licenseVerifier = (LicenseVerifier) command; + assertThat(inputLicense, equalTo(licenseVerifier.license)); + } + + public void testParsingLicenseFile() throws Exception { + License inputLicense = TestUtils.generateSignedLicense(TimeValue.timeValueHours(1), pubKeyPath, priKeyPath); + + LicenseVerificationTool licenseVerificationTool = new LicenseVerificationTool(); + Command command = licenseVerificationTool.parse(LicenseVerificationTool.NAME, + new String[]{"--licenseFile", dumpLicenseAsFile(inputLicense), + "--publicKeyPath", getDataPath(TestUtils.PUBLIC_KEY_RESOURCE).toString()}); + assertThat(command, instanceOf(LicenseVerifier.class)); + LicenseVerifier licenseVerifier = (LicenseVerifier) command; + assertThat(inputLicense, equalTo(licenseVerifier.license)); + + } + + public void testParsingMultipleLicense() throws Exception { + License license = TestUtils.generateSignedLicense(TimeValue.timeValueHours(1), pubKeyPath, priKeyPath); + List arguments = new ArrayList<>(); + arguments.add("--license"); + arguments.add(TestUtils.dumpLicense(license)); + arguments.add("--publicKeyPath"); + arguments.add(getDataPath(TestUtils.PUBLIC_KEY_RESOURCE).toString()); + LicenseVerificationTool licenseVerificationTool = new LicenseVerificationTool(); + Command command = licenseVerificationTool.parse(LicenseVerificationTool.NAME, arguments.toArray(new String[arguments.size()])); + + assertThat(command, instanceOf(LicenseVerifier.class)); + LicenseVerifier licenseVerifier = (LicenseVerifier) command; + assertThat(licenseVerifier.license, equalTo(license)); + } + + public void testToolSimple() throws Exception { + License license = TestUtils.generateSignedLicense(TimeValue.timeValueHours(1), pubKeyPath, priKeyPath); + String output = runLicenseVerificationTool(license, getDataPath(TestUtils.PUBLIC_KEY_RESOURCE), ExitStatus.OK); + License outputLicense = License.fromSource(output.getBytes(StandardCharsets.UTF_8)); + assertThat(outputLicense, CoreMatchers.equalTo(license)); + } + + public void testToolInvalidLicense() throws Exception { + License signedLicense = TestUtils.generateSignedLicense(TimeValue.timeValueHours(1), pubKeyPath, priKeyPath); + + License tamperedLicense = License.builder() + .fromLicenseSpec(signedLicense, signedLicense.signature()) + .expiryDate(signedLicense.expiryDate() + randomIntBetween(1, 1000)).build(); + + runLicenseVerificationTool(tamperedLicense, getDataPath(TestUtils.PUBLIC_KEY_RESOURCE), ExitStatus.DATA_ERROR); + } + + private String dumpLicenseAsFile(License license) throws Exception { + Path tempFile = createTempFile(); + Files.write(tempFile, TestUtils.dumpLicense(license).getBytes(StandardCharsets.UTF_8)); + return tempFile.toAbsolutePath().toString(); + } + + private String runLicenseVerificationTool(License license, Path publicKeyPath, ExitStatus expectedExitStatus) throws Exception { + CaptureOutputTerminal outputTerminal = new CaptureOutputTerminal(); + Settings settings = Settings.builder().put("path.home", createTempDir("LicenseVerificationToolTests")).build(); + LicenseVerifier licenseVerifier = new LicenseVerifier(outputTerminal, license, publicKeyPath); + assertThat(execute(licenseVerifier, settings), equalTo(expectedExitStatus)); + if (expectedExitStatus == ExitStatus.OK) { + assertThat(outputTerminal.getTerminalOutput().size(), equalTo(1)); + + return outputTerminal.getTerminalOutput().get(0); + } else { + return null; + } + } + + private ExitStatus execute(Command cmd, Settings settings) throws Exception { + Environment env = new Environment(settings); + return cmd.execute(settings, env); + } +} diff --git a/elasticsearch/license/licensor/src/test/resources/log4j.properties b/elasticsearch/license/licensor/src/test/resources/log4j.properties new file mode 100644 index 00000000000..76defc8660c --- /dev/null +++ b/elasticsearch/license/licensor/src/test/resources/log4j.properties @@ -0,0 +1,11 @@ +es.logger.level=INFO +log4j.rootLogger=${es.logger.level}, out + +log4j.logger.org.apache.http=INFO, out +log4j.additivity.org.apache.http=false + +log4j.logger.org.elasticsearch.license=TRACE + +log4j.appender.out=org.apache.log4j.ConsoleAppender +log4j.appender.out.layout=org.apache.log4j.PatternLayout +log4j.appender.out.layout.conversionPattern=[%d{ISO8601}][%-5p][%-25c] %m%n diff --git a/elasticsearch/license/licensor/src/test/resources/private.key b/elasticsearch/license/licensor/src/test/resources/private.key new file mode 100644 index 00000000000..1f545803d87 Binary files /dev/null and b/elasticsearch/license/licensor/src/test/resources/private.key differ diff --git a/elasticsearch/license/licensor/src/test/resources/public.key b/elasticsearch/license/licensor/src/test/resources/public.key new file mode 100644 index 00000000000..2a9f272e0b3 --- /dev/null +++ b/elasticsearch/license/licensor/src/test/resources/public.key @@ -0,0 +1,3 @@ +ýŽÇqÝnêÄÌgŠœwM}¹‡UiKŠ•0âbÖ2غqö]â쇴¯ÖÏÃcÌ+IÒðÔ &IJ†fÉ~ßlj ˆº]d™}o§Oè¾Id®È +5A(ìµ´^ØöW©DªJµë}ù-Oîë?u N5¾ÛvpÛ{’¼²Áô­œát–¤7ùøÃê #²Vqöó»ktwm’Œ]ÏLõ£z"| Q‹lŸòQðsâ>ù<}[Á2ÖÓàZÖ|5‹¯ÊÊ7%ØêD +Yå‘xn:¼lúLÈæHò¢«Ë2˜ŸHvEEWÇ\¦H:“6Žh9 [!š…Ûæ©Š¤+;Ö.w7Cì©_|Þ ÓªÏÁ*ñ§D`ƒÚ?‚ùxU/3>x­UÓ“+ è \ No newline at end of file diff --git a/elasticsearch/license/plugin-api/.gitignore b/elasticsearch/license/plugin-api/.gitignore new file mode 100644 index 00000000000..ab956abf6f9 --- /dev/null +++ b/elasticsearch/license/plugin-api/.gitignore @@ -0,0 +1 @@ +/eclipse-build/ diff --git a/elasticsearch/license/plugin-api/build.gradle b/elasticsearch/license/plugin-api/build.gradle new file mode 100644 index 00000000000..7e38efa068d --- /dev/null +++ b/elasticsearch/license/plugin-api/build.gradle @@ -0,0 +1,15 @@ +apply plugin: 'elasticsearch.build' + +dependencies { + compile project(':x-plugins:elasticsearch:license:base') + compile "org.elasticsearch:elasticsearch:${version}" + testCompile project(':x-plugins:elasticsearch:license:licensor') + testCompile "org.elasticsearch:test-framework:${version}" +} + +dependencyLicenses.enabled = false + +jar { + baseName = 'license-plugin-api' +} + diff --git a/elasticsearch/license/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/AbstractLicenseeComponent.java b/elasticsearch/license/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/AbstractLicenseeComponent.java new file mode 100644 index 00000000000..9c8fd1ed6bd --- /dev/null +++ b/elasticsearch/license/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/AbstractLicenseeComponent.java @@ -0,0 +1,74 @@ +/* + * 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.license.plugin.core; + +import org.elasticsearch.common.component.AbstractLifecycleComponent; +import org.elasticsearch.common.settings.Settings; + +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * A supporting base class for injectable Licensee components. + */ +public abstract class AbstractLicenseeComponent> extends AbstractLifecycleComponent implements Licensee { + + private final String id; + private final LicenseeRegistry clientService; + private final List listeners = new CopyOnWriteArrayList<>(); + + // we initialize the licensee state to enabled with trial operation mode + protected volatile Status status = Status.ENABLED; + + protected AbstractLicenseeComponent(Settings settings, String id, LicenseeRegistry clientService) { + super(settings); + this.id = id; + this.clientService = clientService; + } + + @Override + protected void doStart() { + clientService.register(this); + } + + @Override + protected void doStop() { + } + + @Override + protected void doClose() { + } + + @Override + public final String id() { + return id; + } + + /** + * @return the current status of this licensee (can never be null) + */ + public Status getStatus() { + return status; + } + + public void add(Listener listener) { + listeners.add(listener); + } + + @Override + public void onChange(Status status) { + this.status = status; + logger.trace("[{}] is running in [{}] mode", id(), status); + for (Listener listener : listeners) { + listener.onChange(status); + } + } + + public interface Listener { + void onChange(Status status); + } + +} diff --git a/elasticsearch/license/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/LicenseState.java b/elasticsearch/license/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/LicenseState.java new file mode 100644 index 00000000000..a6eba86c532 --- /dev/null +++ b/elasticsearch/license/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/LicenseState.java @@ -0,0 +1,42 @@ +/* + * 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.license.plugin.core; + +/** + * States of a registered licensee + * based on the current license + */ +public enum LicenseState { + + /** + * Active license is valid. + * + * When license expires + * changes to {@link #GRACE_PERIOD} + */ + ENABLED, + + /** + * Active license expired + * but grace period has not. + * + * When grace period expires + * changes to {@link #DISABLED}. + * When valid license is installed + * changes back to {@link #ENABLED} + */ + GRACE_PERIOD, + + /** + * Grace period for active license + * expired. + * + * When a valid license is installed + * changes to {@link #ENABLED}, otherwise + * remains unchanged + */ + DISABLED +} diff --git a/elasticsearch/license/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/LicenseUtils.java b/elasticsearch/license/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/LicenseUtils.java new file mode 100644 index 00000000000..e90166b87ed --- /dev/null +++ b/elasticsearch/license/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/LicenseUtils.java @@ -0,0 +1,35 @@ +/* + * 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.license.plugin.core; + +import org.elasticsearch.ElasticsearchSecurityException; +import org.elasticsearch.rest.RestStatus; + +public class LicenseUtils { + + public final static String EXPIRED_FEATURE_HEADER = "es.license.expired.feature"; + + /** + * Exception to be thrown when a feature action requires a valid license, but license + * has expired + * + * feature accessible through {@link #EXPIRED_FEATURE_HEADER} in the + * exception's rest header + */ + public static ElasticsearchSecurityException newComplianceException(String feature) { + ElasticsearchSecurityException e = new ElasticsearchSecurityException("current license is non-compliant for [{}]", RestStatus.UNAUTHORIZED, feature); + e.addHeader(EXPIRED_FEATURE_HEADER, feature); + return e; + } + + /** + * Checks if a given {@link ElasticsearchSecurityException} refers to a feature that + * requires a valid license, but the license has expired. + */ + public static boolean isLicenseExpiredException(ElasticsearchSecurityException exception) { + return (exception != null) && (exception.getHeader(EXPIRED_FEATURE_HEADER) != null); + } +} diff --git a/elasticsearch/license/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/Licensee.java b/elasticsearch/license/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/Licensee.java new file mode 100644 index 00000000000..00d3bc6bef3 --- /dev/null +++ b/elasticsearch/license/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/Licensee.java @@ -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.license.plugin.core; + +import org.elasticsearch.license.core.License; +import org.elasticsearch.license.core.License.OperationMode; + +import java.util.Locale; + +public interface Licensee { + + /** + * Unique id used to log expiry and + * acknowledgment messages + */ + String id(); + + /** + * Messages to be printed when + * logging license expiry warnings + */ + String[] expirationMessages(); + + /** + * Messages to be returned when + * installing newLicense + * when oldLicense is + * active + */ + String[] acknowledgmentMessages(License currentLicense, License newLicense); + + /** + * Notifies when a new license is activated + * or when a license state change has occurred + */ + void onChange(Status status); + + class Status { + + public static Status ENABLED = new Status(OperationMode.TRIAL, LicenseState.ENABLED); + + private final OperationMode mode; + private final LicenseState licenseState; + + public Status(OperationMode mode, LicenseState licenseState) { + this.mode = mode; + this.licenseState = licenseState; + } + + /** + * Returns the operation mode of the license + * responsible for the current licenseState + */ + public OperationMode getMode() { + return mode; + } + + /** + * When a license is active, the state is + * {@link LicenseState#ENABLED}, upon license expiry + * the state changes to {@link LicenseState#GRACE_PERIOD} + * and after the grace period has ended the state changes + * to {@link LicenseState#DISABLED} + */ + public LicenseState getLicenseState() { + return licenseState; + } + + @Override + public String toString() { + if (mode == OperationMode.NONE) { + return "disabled"; + } + switch (licenseState) { + case DISABLED: + return "disabled " + mode.name().toLowerCase(Locale.ROOT); + case GRACE_PERIOD: + return mode.name().toLowerCase(Locale.ROOT) + " grace period"; + default: + return mode.name().toLowerCase(Locale.ROOT); + } + } + } +} diff --git a/elasticsearch/license/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/LicenseeRegistry.java b/elasticsearch/license/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/LicenseeRegistry.java new file mode 100644 index 00000000000..53a855fa637 --- /dev/null +++ b/elasticsearch/license/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/LicenseeRegistry.java @@ -0,0 +1,14 @@ +/* + * 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.license.plugin.core; + +public interface LicenseeRegistry { + + /** + * Registers a licensee for license notifications + */ + void register(Licensee licensee); +} diff --git a/elasticsearch/license/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/LicensesManagerService.java b/elasticsearch/license/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/LicensesManagerService.java new file mode 100644 index 00000000000..f80d7dac03f --- /dev/null +++ b/elasticsearch/license/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/LicensesManagerService.java @@ -0,0 +1,23 @@ +/* + * 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.license.plugin.core; + +import org.elasticsearch.license.core.License; + +import java.util.List; + +public interface LicensesManagerService { + + /** + * @return the id of registered licensees currently in state + */ + List licenseesWithState(LicenseState state); + + /** + * @return the currently active license, or {@code null} if no license is currently installed + */ + License getLicense(); +} diff --git a/elasticsearch/license/plugin-api/src/test/java/org/elasticsearch/license/plugin/core/LicenseUtilsTests.java b/elasticsearch/license/plugin-api/src/test/java/org/elasticsearch/license/plugin/core/LicenseUtilsTests.java new file mode 100644 index 00000000000..4f7f526ca81 --- /dev/null +++ b/elasticsearch/license/plugin-api/src/test/java/org/elasticsearch/license/plugin/core/LicenseUtilsTests.java @@ -0,0 +1,34 @@ +/* + * 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.license.plugin.core; + +import org.elasticsearch.ElasticsearchSecurityException; +import org.elasticsearch.test.ESTestCase; + +import java.util.Arrays; + +import static org.hamcrest.Matchers.*; + +public class LicenseUtilsTests extends ESTestCase { + + public void testNewExpirationException() { + for (String feature : Arrays.asList("feature", randomAsciiOfLength(5), null, "")) { + ElasticsearchSecurityException exception = LicenseUtils.newComplianceException(feature); + assertNotNull(exception); + assertThat(exception.getHeaderKeys(), contains(LicenseUtils.EXPIRED_FEATURE_HEADER)); + assertThat(exception.getHeader(LicenseUtils.EXPIRED_FEATURE_HEADER), hasSize(1)); + assertThat(exception.getHeader(LicenseUtils.EXPIRED_FEATURE_HEADER).iterator().next(), equalTo(feature)); + } + } + + public void testIsLicenseExpiredException() { + ElasticsearchSecurityException exception = LicenseUtils.newComplianceException("feature"); + assertTrue(LicenseUtils.isLicenseExpiredException(exception)); + + exception = new ElasticsearchSecurityException("msg"); + assertFalse(LicenseUtils.isLicenseExpiredException(exception)); + } +} diff --git a/shield/config/shield/role_mapping.yml b/elasticsearch/qa/build.gradle similarity index 100% rename from shield/config/shield/role_mapping.yml rename to elasticsearch/qa/build.gradle diff --git a/qa/messy-test-watcher-with-groovy/build.gradle b/elasticsearch/qa/messy-test-watcher-with-groovy/build.gradle similarity index 66% rename from qa/messy-test-watcher-with-groovy/build.gradle rename to elasticsearch/qa/messy-test-watcher-with-groovy/build.gradle index 5d7a245277a..23c31b51c5c 100644 --- a/qa/messy-test-watcher-with-groovy/build.gradle +++ b/elasticsearch/qa/messy-test-watcher-with-groovy/build.gradle @@ -7,9 +7,7 @@ apply plugin: 'elasticsearch.standalone-test' dependencies { - testCompile project(path: ':x-plugins:license:plugin', configuration: 'runtime') - testCompile project(path: ':x-plugins:shield', configuration: 'runtime') - testCompile project(path: ':x-plugins:watcher', configuration: 'testArtifacts') + testCompile project(path: ':x-plugins:elasticsearch:x-pack', configuration: 'testArtifacts') testCompile project(path: ':modules:lang-groovy', configuration: 'runtime') } diff --git a/qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/ExecutionVarsIntegrationTests.java b/elasticsearch/qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/ExecutionVarsIntegrationTests.java similarity index 100% rename from qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/ExecutionVarsIntegrationTests.java rename to elasticsearch/qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/ExecutionVarsIntegrationTests.java diff --git a/qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/GroovyManualExecutionTests.java b/elasticsearch/qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/GroovyManualExecutionTests.java similarity index 100% rename from qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/GroovyManualExecutionTests.java rename to elasticsearch/qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/GroovyManualExecutionTests.java diff --git a/qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/HistoryTemplateTransformMappingsTests.java b/elasticsearch/qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/HistoryTemplateTransformMappingsTests.java similarity index 100% rename from qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/HistoryTemplateTransformMappingsTests.java rename to elasticsearch/qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/HistoryTemplateTransformMappingsTests.java diff --git a/qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/IndexActionIntegrationTests.java b/elasticsearch/qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/IndexActionIntegrationTests.java similarity index 100% rename from qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/IndexActionIntegrationTests.java rename to elasticsearch/qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/IndexActionIntegrationTests.java diff --git a/qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/MessyTestUtils.java b/elasticsearch/qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/MessyTestUtils.java similarity index 100% rename from qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/MessyTestUtils.java rename to elasticsearch/qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/MessyTestUtils.java diff --git a/qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/ScriptConditionSearchTests.java b/elasticsearch/qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/ScriptConditionSearchTests.java similarity index 100% rename from qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/ScriptConditionSearchTests.java rename to elasticsearch/qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/ScriptConditionSearchTests.java diff --git a/qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/ScriptConditionTests.java b/elasticsearch/qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/ScriptConditionTests.java similarity index 100% rename from qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/ScriptConditionTests.java rename to elasticsearch/qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/ScriptConditionTests.java diff --git a/qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/TransformIntegrationTests.java b/elasticsearch/qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/TransformIntegrationTests.java similarity index 100% rename from qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/TransformIntegrationTests.java rename to elasticsearch/qa/messy-test-watcher-with-groovy/src/test/java/org/elasticsearch/messy/tests/TransformIntegrationTests.java diff --git a/qa/shield-audit-tests/build.gradle b/elasticsearch/qa/shield-audit-tests/build.gradle similarity index 68% rename from qa/shield-audit-tests/build.gradle rename to elasticsearch/qa/shield-audit-tests/build.gradle index 9ebb5cc83c9..32f50580d7f 100644 --- a/qa/shield-audit-tests/build.gradle +++ b/elasticsearch/qa/shield-audit-tests/build.gradle @@ -1,18 +1,16 @@ apply plugin: 'elasticsearch.rest-test' dependencies { - testCompile project(path: ':x-plugins:shield', configuration: 'runtime') + testCompile project(path: ':x-plugins:elasticsearch:x-pack', configuration: 'runtime') } integTest { cluster { - plugin 'license', project(':x-plugins:license:plugin') - plugin 'shield', project(':x-plugins:shield') - // TODO: these should be settings? + plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack') systemProperty 'es.shield.audit.enabled', 'true' systemProperty 'es.shield.audit.outputs', 'index' setupCommand 'setupDummyUser', - 'bin/shield/esusers', 'useradd', 'test_user', '-p', 'changeme', '-r', 'admin' + 'bin/x-pack/esusers', 'useradd', 'test_user', '-p', 'changeme', '-r', 'admin' waitCondition = { node, ant -> File tmpFile = new File(node.cwd, 'wait.success') ant.get(src: "http://localhost:${node.httpPort()}", diff --git a/qa/shield-audit-tests/src/test/java/org/elasticsearch/shield/audit/IndexAuditIT.java b/elasticsearch/qa/shield-audit-tests/src/test/java/org/elasticsearch/shield/audit/IndexAuditIT.java similarity index 95% rename from qa/shield-audit-tests/src/test/java/org/elasticsearch/shield/audit/IndexAuditIT.java rename to elasticsearch/qa/shield-audit-tests/src/test/java/org/elasticsearch/shield/audit/IndexAuditIT.java index e899db8d3e1..49e395bc8c2 100644 --- a/qa/shield-audit-tests/src/test/java/org/elasticsearch/shield/audit/IndexAuditIT.java +++ b/elasticsearch/qa/shield-audit-tests/src/test/java/org/elasticsearch/shield/audit/IndexAuditIT.java @@ -9,7 +9,7 @@ import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.plugins.Plugin; -import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.authc.support.SecuredString; import org.elasticsearch.shield.authc.support.UsernamePasswordToken; import org.elasticsearch.test.ESIntegTestCase; @@ -56,6 +56,6 @@ public class IndexAuditIT extends ESIntegTestCase { @Override protected Collection> transportClientPlugins() { - return Collections.>singleton(ShieldPlugin.class); + return Collections.>singleton(XPackPlugin.class); } } diff --git a/qa/shield-client-tests/build.gradle b/elasticsearch/qa/shield-client-tests/build.gradle similarity index 65% rename from qa/shield-client-tests/build.gradle rename to elasticsearch/qa/shield-client-tests/build.gradle index 4c3cba8ea59..1a3ea6ccaf8 100644 --- a/qa/shield-client-tests/build.gradle +++ b/elasticsearch/qa/shield-client-tests/build.gradle @@ -1,17 +1,16 @@ apply plugin: 'elasticsearch.rest-test' dependencies { - testCompile project(path: ':x-plugins:shield', configuration: 'runtime') + testCompile project(path: ':x-plugins:elasticsearch:x-pack', configuration: 'runtime') } integTest { cluster { - plugin 'license', project(':x-plugins:license:plugin') - plugin 'shield', project(':x-plugins:shield') + plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack') setupCommand 'setupDummyUser', - 'bin/shield/esusers', 'useradd', 'test_user', '-p', 'changeme', '-r', 'admin' + 'bin/x-pack/esusers', 'useradd', 'test_user', '-p', 'changeme', '-r', 'admin' setupCommand 'setupTransportClientUser', - 'bin/shield/esusers', 'useradd', 'transport', '-p', 'changeme', '-r', 'transport_client' + 'bin/x-pack/esusers', 'useradd', 'transport', '-p', 'changeme', '-r', 'transport_client' waitCondition = { node, ant -> File tmpFile = new File(node.cwd, 'wait.success') ant.get(src: "http://localhost:${node.httpPort()}", diff --git a/qa/shield-client-tests/src/test/java/org/elasticsearch/shield/qa/ShieldTransportClientIT.java b/elasticsearch/qa/shield-client-tests/src/test/java/org/elasticsearch/shield/qa/ShieldTransportClientIT.java similarity index 96% rename from qa/shield-client-tests/src/test/java/org/elasticsearch/shield/qa/ShieldTransportClientIT.java rename to elasticsearch/qa/shield-client-tests/src/test/java/org/elasticsearch/shield/qa/ShieldTransportClientIT.java index 3dcaa58a950..f76bcb8d4f6 100644 --- a/qa/shield-client-tests/src/test/java/org/elasticsearch/shield/qa/ShieldTransportClientIT.java +++ b/elasticsearch/qa/shield-client-tests/src/test/java/org/elasticsearch/shield/qa/ShieldTransportClientIT.java @@ -13,7 +13,7 @@ import org.elasticsearch.client.transport.TransportClient; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.plugins.Plugin; -import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.authc.support.SecuredString; import org.elasticsearch.test.ESIntegTestCase; @@ -41,7 +41,7 @@ public class ShieldTransportClientIT extends ESIntegTestCase { @Override protected Collection> transportClientPlugins() { - return Collections.singletonList(ShieldPlugin.class); + return Collections.singletonList(XPackPlugin.class); } public void testThatTransportClientWithoutAuthenticationDoesNotWork() throws Exception { @@ -111,6 +111,6 @@ public class ShieldTransportClientIT extends ESIntegTestCase { .put("cluster.name", clusterName) .build(); - return TransportClient.builder().settings(settings).addPlugin(ShieldPlugin.class).build().addTransportAddress(publishAddress); + return TransportClient.builder().settings(settings).addPlugin(XPackPlugin.class).build().addTransportAddress(publishAddress); } } diff --git a/qa/shield-core-rest-tests/build.gradle b/elasticsearch/qa/shield-core-rest-tests/build.gradle similarity index 82% rename from qa/shield-core-rest-tests/build.gradle rename to elasticsearch/qa/shield-core-rest-tests/build.gradle index 8d2d2411db2..4da9a0b405e 100644 --- a/qa/shield-core-rest-tests/build.gradle +++ b/elasticsearch/qa/shield-core-rest-tests/build.gradle @@ -1,12 +1,12 @@ apply plugin: 'elasticsearch.rest-test' dependencies { - testCompile project(path: ':x-plugins:shield', configuration: 'runtime') + testCompile project(path: ':x-plugins:elasticsearch:x-pack', configuration: 'runtime') } integTest { includePackaged true - systemProperty 'tests.rest.blacklist', + systemProperty 'tests.rest.blacklist', ['indices.get/10_basic/*allow_no_indices*', 'cat.count/10_basic/Test cat count output', 'cat.aliases/10_basic/Empty cluster', @@ -30,10 +30,11 @@ integTest { 'bulk/40_fields/Fields'].join(',') cluster { - plugin 'license', project(':x-plugins:license:plugin') - plugin 'shield', project(':x-plugins:shield') + plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack') + systemProperty 'es.watcher.enabled', 'false' + systemProperty 'es.marvel.enabled', 'false' setupCommand 'setupDummyUser', - 'bin/shield/esusers', 'useradd', 'test_user', '-p', 'changeme', '-r', 'admin' + 'bin/x-pack/esusers', 'useradd', 'test_user', '-p', 'changeme', '-r', 'admin' waitCondition = { node, ant -> File tmpFile = new File(node.cwd, 'wait.success') ant.get(src: "http://localhost:${node.httpPort()}", diff --git a/qa/shield-core-rest-tests/src/test/java/org/elasticsearch/shield/RestIT.java b/elasticsearch/qa/shield-core-rest-tests/src/test/java/org/elasticsearch/shield/RestIT.java similarity index 94% rename from qa/shield-core-rest-tests/src/test/java/org/elasticsearch/shield/RestIT.java rename to elasticsearch/qa/shield-core-rest-tests/src/test/java/org/elasticsearch/shield/RestIT.java index 608cb20ce1f..b3716a126dc 100644 --- a/qa/shield-core-rest-tests/src/test/java/org/elasticsearch/shield/RestIT.java +++ b/elasticsearch/qa/shield-core-rest-tests/src/test/java/org/elasticsearch/shield/RestIT.java @@ -11,6 +11,7 @@ import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; import org.elasticsearch.client.support.Headers; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.authc.support.SecuredString; import org.elasticsearch.test.rest.ESRestTestCase; import org.elasticsearch.test.rest.RestTestCandidate; @@ -53,7 +54,7 @@ public class RestIT extends ESRestTestCase { @Override protected Collection> transportClientPlugins() { - return Collections.>singleton(ShieldPlugin.class); + return Collections.>singleton(XPackPlugin.class); } } diff --git a/qa/shield-example-realm/build.gradle b/elasticsearch/qa/shield-example-realm/build.gradle similarity index 77% rename from qa/shield-example-realm/build.gradle rename to elasticsearch/qa/shield-example-realm/build.gradle index debd3aa8008..acd928f580f 100644 --- a/qa/shield-example-realm/build.gradle +++ b/elasticsearch/qa/shield-example-realm/build.gradle @@ -7,8 +7,7 @@ esplugin { } dependencies { - provided project(path: ':x-plugins:license:plugin', configuration: 'runtime') - provided project(path: ':x-plugins:shield', configuration: 'runtime') + provided project(path: ':x-plugins:elasticsearch:x-pack', configuration: 'runtime') } compileJava.options.compilerArgs << "-Xlint:-rawtypes" @@ -16,8 +15,7 @@ compileJava.options.compilerArgs << "-Xlint:-rawtypes" integTest { cluster { - plugin 'license', project(':x-plugins:license:plugin') - plugin 'shield', project(':x-plugins:shield') + plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack') // TODO: these should be settings? systemProperty 'es.shield.authc.realms.custom.order', '0' systemProperty 'es.shield.authc.realms.custom.type', 'custom' @@ -25,7 +23,7 @@ integTest { systemProperty 'es.shield.authc.realms.esusers.type', 'esusers' setupCommand 'setupDummyUser', - 'bin/shield/esusers', 'useradd', 'test_user', '-p', 'changeme', '-r', 'admin' + 'bin/x-pack/esusers', 'useradd', 'test_user', '-p', 'changeme', '-r', 'admin' waitCondition = { node, ant -> File tmpFile = new File(node.cwd, 'wait.success') ant.get(src: "http://localhost:${node.httpPort()}", diff --git a/qa/shield-example-realm/src/main/java/org/elasticsearch/example/ExampleRealmPlugin.java b/elasticsearch/qa/shield-example-realm/src/main/java/org/elasticsearch/example/ExampleRealmPlugin.java similarity index 100% rename from qa/shield-example-realm/src/main/java/org/elasticsearch/example/ExampleRealmPlugin.java rename to elasticsearch/qa/shield-example-realm/src/main/java/org/elasticsearch/example/ExampleRealmPlugin.java diff --git a/qa/shield-example-realm/src/main/java/org/elasticsearch/example/realm/CustomAuthenticationFailureHandler.java b/elasticsearch/qa/shield-example-realm/src/main/java/org/elasticsearch/example/realm/CustomAuthenticationFailureHandler.java similarity index 100% rename from qa/shield-example-realm/src/main/java/org/elasticsearch/example/realm/CustomAuthenticationFailureHandler.java rename to elasticsearch/qa/shield-example-realm/src/main/java/org/elasticsearch/example/realm/CustomAuthenticationFailureHandler.java diff --git a/qa/shield-example-realm/src/main/java/org/elasticsearch/example/realm/CustomRealm.java b/elasticsearch/qa/shield-example-realm/src/main/java/org/elasticsearch/example/realm/CustomRealm.java similarity index 100% rename from qa/shield-example-realm/src/main/java/org/elasticsearch/example/realm/CustomRealm.java rename to elasticsearch/qa/shield-example-realm/src/main/java/org/elasticsearch/example/realm/CustomRealm.java diff --git a/qa/shield-example-realm/src/main/java/org/elasticsearch/example/realm/CustomRealmFactory.java b/elasticsearch/qa/shield-example-realm/src/main/java/org/elasticsearch/example/realm/CustomRealmFactory.java similarity index 100% rename from qa/shield-example-realm/src/main/java/org/elasticsearch/example/realm/CustomRealmFactory.java rename to elasticsearch/qa/shield-example-realm/src/main/java/org/elasticsearch/example/realm/CustomRealmFactory.java diff --git a/qa/shield-example-realm/src/test/java/org/elasticsearch/example/realm/CustomRealmIT.java b/elasticsearch/qa/shield-example-realm/src/test/java/org/elasticsearch/example/realm/CustomRealmIT.java similarity index 94% rename from qa/shield-example-realm/src/test/java/org/elasticsearch/example/realm/CustomRealmIT.java rename to elasticsearch/qa/shield-example-realm/src/test/java/org/elasticsearch/example/realm/CustomRealmIT.java index d7e16c99de2..d6240893bf3 100644 --- a/qa/shield-example-realm/src/test/java/org/elasticsearch/example/realm/CustomRealmIT.java +++ b/elasticsearch/qa/shield-example-realm/src/test/java/org/elasticsearch/example/realm/CustomRealmIT.java @@ -14,7 +14,7 @@ import org.elasticsearch.client.transport.TransportClient; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.plugins.Plugin; -import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.test.ESIntegTestCase; import org.elasticsearch.test.rest.client.http.HttpResponse; @@ -37,7 +37,7 @@ public class CustomRealmIT extends ESIntegTestCase { @Override protected Collection> transportClientPlugins() { - return Collections.>singleton(ShieldPlugin.class); + return Collections.>singleton(XPackPlugin.class); } public void testHttpConnectionWithNoAuthentication() throws Exception { @@ -67,7 +67,7 @@ public class CustomRealmIT extends ESIntegTestCase { .put(Headers.PREFIX + "." + CustomRealm.USER_HEADER, CustomRealm.KNOWN_USER) .put(Headers.PREFIX + "." + CustomRealm.PW_HEADER, CustomRealm.KNOWN_PW) .build(); - try (TransportClient client = TransportClient.builder().settings(settings).addPlugin(ShieldPlugin.class).build()) { + try (TransportClient client = TransportClient.builder().settings(settings).addPlugin(XPackPlugin.class).build()) { client.addTransportAddress(publishAddress); ClusterHealthResponse response = client.admin().cluster().prepareHealth().execute().actionGet(); assertThat(response.isTimedOut(), is(false)); @@ -86,7 +86,7 @@ public class CustomRealmIT extends ESIntegTestCase { .put(Headers.PREFIX + "." + CustomRealm.USER_HEADER, CustomRealm.KNOWN_USER + randomAsciiOfLength(1)) .put(Headers.PREFIX + "." + CustomRealm.PW_HEADER, CustomRealm.KNOWN_PW) .build(); - try (TransportClient client = TransportClient.builder().addPlugin(ShieldPlugin.class).settings(settings).build()) { + try (TransportClient client = TransportClient.builder().addPlugin(XPackPlugin.class).settings(settings).build()) { client.addTransportAddress(publishAddress); client.admin().cluster().prepareHealth().execute().actionGet(); fail("authentication failure should have resulted in a NoNodesAvailableException"); diff --git a/qa/shield-example-realm/src/test/java/org/elasticsearch/example/realm/CustomRealmTests.java b/elasticsearch/qa/shield-example-realm/src/test/java/org/elasticsearch/example/realm/CustomRealmTests.java similarity index 100% rename from qa/shield-example-realm/src/test/java/org/elasticsearch/example/realm/CustomRealmTests.java rename to elasticsearch/qa/shield-example-realm/src/test/java/org/elasticsearch/example/realm/CustomRealmTests.java diff --git a/qa/shield-tribe-node-tests/integration-tests.xml b/elasticsearch/qa/shield-tribe-node-tests/integration-tests.xml similarity index 100% rename from qa/shield-tribe-node-tests/integration-tests.xml rename to elasticsearch/qa/shield-tribe-node-tests/integration-tests.xml diff --git a/qa/shield-tribe-node-tests/rest-api-spec/test/tribe_node/10_basic.yaml b/elasticsearch/qa/shield-tribe-node-tests/rest-api-spec/test/tribe_node/10_basic.yaml similarity index 100% rename from qa/shield-tribe-node-tests/rest-api-spec/test/tribe_node/10_basic.yaml rename to elasticsearch/qa/shield-tribe-node-tests/rest-api-spec/test/tribe_node/10_basic.yaml diff --git a/qa/shield-tribe-node-tests/shield-roles.yml b/elasticsearch/qa/shield-tribe-node-tests/shield-roles.yml similarity index 100% rename from qa/shield-tribe-node-tests/shield-roles.yml rename to elasticsearch/qa/shield-tribe-node-tests/shield-roles.yml diff --git a/qa/shield-tribe-node-tests/src/test/java/org/elasticsearch/ant/HttpCondition.java b/elasticsearch/qa/shield-tribe-node-tests/src/test/java/org/elasticsearch/ant/HttpCondition.java similarity index 100% rename from qa/shield-tribe-node-tests/src/test/java/org/elasticsearch/ant/HttpCondition.java rename to elasticsearch/qa/shield-tribe-node-tests/src/test/java/org/elasticsearch/ant/HttpCondition.java diff --git a/qa/shield-tribe-node-tests/src/test/java/org/elasticsearch/ant/HttpTask.java b/elasticsearch/qa/shield-tribe-node-tests/src/test/java/org/elasticsearch/ant/HttpTask.java similarity index 100% rename from qa/shield-tribe-node-tests/src/test/java/org/elasticsearch/ant/HttpTask.java rename to elasticsearch/qa/shield-tribe-node-tests/src/test/java/org/elasticsearch/ant/HttpTask.java diff --git a/qa/shield-tribe-node-tests/src/test/java/org/elasticsearch/shield/RestIT.java b/elasticsearch/qa/shield-tribe-node-tests/src/test/java/org/elasticsearch/shield/RestIT.java similarity index 100% rename from qa/shield-tribe-node-tests/src/test/java/org/elasticsearch/shield/RestIT.java rename to elasticsearch/qa/shield-tribe-node-tests/src/test/java/org/elasticsearch/shield/RestIT.java diff --git a/qa/shield-tribe-node-tests/src/test/java/org/elasticsearch/shield/TribeRestTestCase.java b/elasticsearch/qa/shield-tribe-node-tests/src/test/java/org/elasticsearch/shield/TribeRestTestCase.java similarity index 100% rename from qa/shield-tribe-node-tests/src/test/java/org/elasticsearch/shield/TribeRestTestCase.java rename to elasticsearch/qa/shield-tribe-node-tests/src/test/java/org/elasticsearch/shield/TribeRestTestCase.java diff --git a/qa/smoke-test-found-license-with-shield-and-watcher/integration-tests.xml b/elasticsearch/qa/smoke-test-found-license-with-shield-and-watcher/integration-tests.xml similarity index 100% rename from qa/smoke-test-found-license-with-shield-and-watcher/integration-tests.xml rename to elasticsearch/qa/smoke-test-found-license-with-shield-and-watcher/integration-tests.xml diff --git a/qa/smoke-test-found-license-with-shield-and-watcher/src/test/java/org/elasticsearch/smoketest/MarvelClusterInfoIT.java b/elasticsearch/qa/smoke-test-found-license-with-shield-and-watcher/src/test/java/org/elasticsearch/smoketest/MarvelClusterInfoIT.java similarity index 97% rename from qa/smoke-test-found-license-with-shield-and-watcher/src/test/java/org/elasticsearch/smoketest/MarvelClusterInfoIT.java rename to elasticsearch/qa/smoke-test-found-license-with-shield-and-watcher/src/test/java/org/elasticsearch/smoketest/MarvelClusterInfoIT.java index da2c390600a..e6439d71ebc 100644 --- a/qa/smoke-test-found-license-with-shield-and-watcher/src/test/java/org/elasticsearch/smoketest/MarvelClusterInfoIT.java +++ b/elasticsearch/qa/smoke-test-found-license-with-shield-and-watcher/src/test/java/org/elasticsearch/smoketest/MarvelClusterInfoIT.java @@ -11,7 +11,7 @@ import org.elasticsearch.common.Strings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.IndexNotFoundException; import org.elasticsearch.plugins.Plugin; -import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.test.ESIntegTestCase; import org.hamcrest.Matcher; @@ -37,7 +37,7 @@ public class MarvelClusterInfoIT extends ESIntegTestCase { @Override protected Collection> transportClientPlugins() { - return Collections.singletonList(ShieldPlugin.class); + return Collections.singletonList(XPackPlugin.class); } public void testMarvelClusterInfoCollectorWorks() throws Exception { diff --git a/qa/smoke-test-found-license-with-shield-and-watcher/src/test/java/org/elasticsearch/smoketest/WatcherWithShieldIT.java b/elasticsearch/qa/smoke-test-found-license-with-shield-and-watcher/src/test/java/org/elasticsearch/smoketest/WatcherWithShieldIT.java similarity index 96% rename from qa/smoke-test-found-license-with-shield-and-watcher/src/test/java/org/elasticsearch/smoketest/WatcherWithShieldIT.java rename to elasticsearch/qa/smoke-test-found-license-with-shield-and-watcher/src/test/java/org/elasticsearch/smoketest/WatcherWithShieldIT.java index 3c5022f7b34..0c2b66ad4c9 100644 --- a/qa/smoke-test-found-license-with-shield-and-watcher/src/test/java/org/elasticsearch/smoketest/WatcherWithShieldIT.java +++ b/elasticsearch/qa/smoke-test-found-license-with-shield-and-watcher/src/test/java/org/elasticsearch/smoketest/WatcherWithShieldIT.java @@ -15,7 +15,7 @@ import org.elasticsearch.client.support.Headers; import org.elasticsearch.common.network.NetworkAddress; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.plugins.Plugin; -import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.authc.support.SecuredString; import org.elasticsearch.shield.authc.support.UsernamePasswordToken; import org.elasticsearch.test.rest.ESRestTestCase; @@ -90,7 +90,7 @@ public class WatcherWithShieldIT extends ESRestTestCase { @Override protected Collection> transportClientPlugins() { - return Collections.>singleton(ShieldPlugin.class); + return Collections.>singleton(XPackPlugin.class); } } diff --git a/qa/smoke-test-found-license-with-shield-and-watcher/src/test/java/org/elasticsearch/smoketest/WatcherWithShieldInsufficientRoleIT.java b/elasticsearch/qa/smoke-test-found-license-with-shield-and-watcher/src/test/java/org/elasticsearch/smoketest/WatcherWithShieldInsufficientRoleIT.java similarity index 100% rename from qa/smoke-test-found-license-with-shield-and-watcher/src/test/java/org/elasticsearch/smoketest/WatcherWithShieldInsufficientRoleIT.java rename to elasticsearch/qa/smoke-test-found-license-with-shield-and-watcher/src/test/java/org/elasticsearch/smoketest/WatcherWithShieldInsufficientRoleIT.java diff --git a/qa/smoke-test-found-license-with-shield-and-watcher/watcher-with-shield-roles.yml b/elasticsearch/qa/smoke-test-found-license-with-shield-and-watcher/watcher-with-shield-roles.yml similarity index 100% rename from qa/smoke-test-found-license-with-shield-and-watcher/watcher-with-shield-roles.yml rename to elasticsearch/qa/smoke-test-found-license-with-shield-and-watcher/watcher-with-shield-roles.yml diff --git a/qa/smoke-test-plugins-ssl/build.gradle b/elasticsearch/qa/smoke-test-plugins-ssl/build.gradle similarity index 85% rename from qa/smoke-test-plugins-ssl/build.gradle rename to elasticsearch/qa/smoke-test-plugins-ssl/build.gradle index fd2dbf8750d..bc8bbad1e37 100644 --- a/qa/smoke-test-plugins-ssl/build.gradle +++ b/elasticsearch/qa/smoke-test-plugins-ssl/build.gradle @@ -1,10 +1,12 @@ +import org.elasticsearch.gradle.MavenFilteringHack + import org.elasticsearch.gradle.LoggedExec import org.elasticsearch.gradle.MavenFilteringHack apply plugin: 'elasticsearch.rest-test' dependencies { - testCompile project(path: ':x-plugins:shield', configuration: 'runtime') + testCompile project(path: ':x-plugins:elasticsearch:x-pack', configuration: 'runtime') } // location of keystore and files to generate it @@ -49,17 +51,14 @@ integTest { systemProperty 'es.shield.http.ssl', 'true' systemProperty 'es.shield.ssl.keystore.path', keystore.name systemProperty 'es.shield.ssl.keystore.password', 'keypass' - plugin 'licence', project(':x-plugins:license:plugin') - plugin 'shield', project(':x-plugins:shield') - plugin 'watcher', project(':x-plugins:watcher') - plugin 'marvel-agent', project(':x-plugins:marvel') + plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack') // copy keystore into config/ extraConfigFile keystore.name, keystore setupCommand 'setupTestUser', - 'bin/shield/esusers', 'useradd', 'test_user', '-p', 'changeme', '-r', 'admin' + 'bin/x-pack/esusers', 'useradd', 'test_user', '-p', 'changeme', '-r', 'admin' setupCommand 'setupMarvelUser', - 'bin/shield/esusers', 'useradd', 'marvel_export', '-p', 'changeme', '-r', 'marvel_agent' + 'bin/x-pack/esusers', 'useradd', 'marvel_export', '-p', 'changeme', '-r', 'marvel_agent' waitCondition = { node, ant -> // we just return true, doing an https check is tricky here return true diff --git a/qa/smoke-test-plugins-ssl/src/test/java/org/elasticsearch/smoketest/SmokeTestPluginsSslIT.java b/elasticsearch/qa/smoke-test-plugins-ssl/src/test/java/org/elasticsearch/smoketest/SmokeTestPluginsSslIT.java similarity index 96% rename from qa/smoke-test-plugins-ssl/src/test/java/org/elasticsearch/smoketest/SmokeTestPluginsSslIT.java rename to elasticsearch/qa/smoke-test-plugins-ssl/src/test/java/org/elasticsearch/smoketest/SmokeTestPluginsSslIT.java index f33264fb239..6e6cb863dbd 100644 --- a/qa/smoke-test-plugins-ssl/src/test/java/org/elasticsearch/smoketest/SmokeTestPluginsSslIT.java +++ b/elasticsearch/qa/smoke-test-plugins-ssl/src/test/java/org/elasticsearch/smoketest/SmokeTestPluginsSslIT.java @@ -19,7 +19,7 @@ import org.elasticsearch.client.support.Headers; import org.elasticsearch.common.io.PathUtils; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.plugins.Plugin; -import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.authc.support.SecuredString; import org.elasticsearch.test.rest.ESRestTestCase; import org.elasticsearch.test.rest.RestTestCandidate; @@ -88,7 +88,7 @@ public class SmokeTestPluginsSslIT extends ESRestTestCase { @Override protected Collection> transportClientPlugins() { - return Collections.>singleton(ShieldPlugin.class); + return Collections.>singleton(XPackPlugin.class); } } diff --git a/qa/smoke-test-plugins-ssl/src/test/resources/rest-api-spec/test/smoke_test_plugins_ssl/10_basic.yaml b/elasticsearch/qa/smoke-test-plugins-ssl/src/test/resources/rest-api-spec/test/smoke_test_plugins_ssl/10_basic.yaml similarity index 100% rename from qa/smoke-test-plugins-ssl/src/test/resources/rest-api-spec/test/smoke_test_plugins_ssl/10_basic.yaml rename to elasticsearch/qa/smoke-test-plugins-ssl/src/test/resources/rest-api-spec/test/smoke_test_plugins_ssl/10_basic.yaml diff --git a/qa/smoke-test-plugins/build.gradle b/elasticsearch/qa/smoke-test-plugins/build.gradle similarity index 74% rename from qa/smoke-test-plugins/build.gradle rename to elasticsearch/qa/smoke-test-plugins/build.gradle index fa1513a9ccc..5754d153ded 100644 --- a/qa/smoke-test-plugins/build.gradle +++ b/elasticsearch/qa/smoke-test-plugins/build.gradle @@ -3,7 +3,7 @@ import org.elasticsearch.gradle.MavenFilteringHack apply plugin: 'elasticsearch.rest-test' dependencies { - testCompile project(path: ':x-plugins:shield', configuration: 'runtime') + testCompile project(path: ':x-plugins:elasticsearch:x-pack', configuration: 'runtime') } ext.pluginsCount = 4 // we install xplugins explicitly @@ -15,13 +15,10 @@ project.rootProject.subprojects.findAll { it.path.startsWith(':plugins:') }.each integTest { cluster { - plugin 'licence', project(':x-plugins:license:plugin') - plugin 'shield', project(':x-plugins:shield') - plugin 'watcher', project(':x-plugins:watcher') - plugin 'marvel-agent', project(':x-plugins:marvel') + plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack') setupCommand 'setupDummyUser', - 'bin/shield/esusers', 'useradd', 'test_user', '-p', 'changeme', '-r', 'admin' + 'bin/x-pack/esusers', 'useradd', 'test_user', '-p', 'changeme', '-r', 'admin' waitCondition = { node, ant -> File tmpFile = new File(node.cwd, 'wait.success') ant.get(src: "http://localhost:${node.httpPort()}", diff --git a/qa/smoke-test-plugins/src/test/java/org/elasticsearch/smoketest/SmokeTestPluginsIT.java b/elasticsearch/qa/smoke-test-plugins/src/test/java/org/elasticsearch/smoketest/SmokeTestPluginsIT.java similarity index 93% rename from qa/smoke-test-plugins/src/test/java/org/elasticsearch/smoketest/SmokeTestPluginsIT.java rename to elasticsearch/qa/smoke-test-plugins/src/test/java/org/elasticsearch/smoketest/SmokeTestPluginsIT.java index edf0edc1252..572eecfe0a4 100644 --- a/qa/smoke-test-plugins/src/test/java/org/elasticsearch/smoketest/SmokeTestPluginsIT.java +++ b/elasticsearch/qa/smoke-test-plugins/src/test/java/org/elasticsearch/smoketest/SmokeTestPluginsIT.java @@ -11,7 +11,7 @@ import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; import org.elasticsearch.client.support.Headers; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.plugins.Plugin; -import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.authc.support.SecuredString; import org.elasticsearch.test.rest.ESRestTestCase; import org.elasticsearch.test.rest.RestTestCandidate; @@ -54,7 +54,7 @@ public class SmokeTestPluginsIT extends ESRestTestCase { @Override protected Collection> transportClientPlugins() { - return Collections.>singleton(ShieldPlugin.class); + return Collections.>singleton(XPackPlugin.class); } } diff --git a/qa/smoke-test-plugins/src/test/resources/rest-api-spec/test/smoke_test_plugins/10_basic.yaml b/elasticsearch/qa/smoke-test-plugins/src/test/resources/rest-api-spec/test/smoke_test_plugins/10_basic.yaml similarity index 100% rename from qa/smoke-test-plugins/src/test/resources/rest-api-spec/test/smoke_test_plugins/10_basic.yaml rename to elasticsearch/qa/smoke-test-plugins/src/test/resources/rest-api-spec/test/smoke_test_plugins/10_basic.yaml diff --git a/qa/smoke-test-watcher-with-groovy/build.gradle b/elasticsearch/qa/smoke-test-watcher-with-groovy/build.gradle similarity index 51% rename from qa/smoke-test-watcher-with-groovy/build.gradle rename to elasticsearch/qa/smoke-test-watcher-with-groovy/build.gradle index 3688a6d4a91..f2fdbcb472b 100644 --- a/qa/smoke-test-watcher-with-groovy/build.gradle +++ b/elasticsearch/qa/smoke-test-watcher-with-groovy/build.gradle @@ -1,14 +1,14 @@ apply plugin: 'elasticsearch.rest-test' dependencies { - testCompile project(path: ':x-plugins:watcher', configuration: 'runtime') + testCompile project(path: ':x-plugins:elasticsearch:x-pack', configuration: 'runtime') testCompile project(path: ':modules:lang-groovy', configuration: 'runtime') } integTest { cluster { - plugin 'license', project(':x-plugins:license:plugin') - plugin 'watcher', project(':x-plugins:watcher') + plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack') systemProperty 'es.script.inline', 'on' + systemProperty 'es.shield.enabled', 'false' } } diff --git a/watcher/src/test/java/org/elasticsearch/watcher/test/rest/WatcherRestTestCase.java b/elasticsearch/qa/smoke-test-watcher-with-groovy/src/test/java/org/elasticsearch/smoketest/WatcherRestTestCase.java similarity index 96% rename from watcher/src/test/java/org/elasticsearch/watcher/test/rest/WatcherRestTestCase.java rename to elasticsearch/qa/smoke-test-watcher-with-groovy/src/test/java/org/elasticsearch/smoketest/WatcherRestTestCase.java index 2173cd82578..bc998eb11c4 100644 --- a/watcher/src/test/java/org/elasticsearch/watcher/test/rest/WatcherRestTestCase.java +++ b/elasticsearch/qa/smoke-test-watcher-with-groovy/src/test/java/org/elasticsearch/smoketest/WatcherRestTestCase.java @@ -13,14 +13,14 @@ import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.BasicHttpClientConnectionManager; import org.elasticsearch.common.network.NetworkAddress; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.license.plugin.LicensePlugin; +import org.elasticsearch.xpack.XPackPlugin; 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.elasticsearch.xpack.XPackPlugin; import org.junit.After; import org.junit.Before; diff --git a/qa/smoke-test-watcher-with-groovy/src/test/java/org/elasticsearch/smoketest/WatcherWithGroovyIT.java b/elasticsearch/qa/smoke-test-watcher-with-groovy/src/test/java/org/elasticsearch/smoketest/WatcherWithGroovyIT.java similarity index 100% rename from qa/smoke-test-watcher-with-groovy/src/test/java/org/elasticsearch/smoketest/WatcherWithGroovyIT.java rename to elasticsearch/qa/smoke-test-watcher-with-groovy/src/test/java/org/elasticsearch/smoketest/WatcherWithGroovyIT.java diff --git a/qa/smoke-test-watcher-with-groovy/src/test/resources/rest-api-spec/test/watcher_groovy/10_basic.yaml b/elasticsearch/qa/smoke-test-watcher-with-groovy/src/test/resources/rest-api-spec/test/watcher_groovy/10_basic.yaml similarity index 100% rename from qa/smoke-test-watcher-with-groovy/src/test/resources/rest-api-spec/test/watcher_groovy/10_basic.yaml rename to elasticsearch/qa/smoke-test-watcher-with-groovy/src/test/resources/rest-api-spec/test/watcher_groovy/10_basic.yaml diff --git a/qa/smoke-test-watcher-with-groovy/src/test/resources/rest-api-spec/test/watcher_groovy/20_minimal_body.yaml b/elasticsearch/qa/smoke-test-watcher-with-groovy/src/test/resources/rest-api-spec/test/watcher_groovy/20_minimal_body.yaml similarity index 100% rename from qa/smoke-test-watcher-with-groovy/src/test/resources/rest-api-spec/test/watcher_groovy/20_minimal_body.yaml rename to elasticsearch/qa/smoke-test-watcher-with-groovy/src/test/resources/rest-api-spec/test/watcher_groovy/20_minimal_body.yaml diff --git a/qa/smoke-test-watcher-with-groovy/src/test/resources/rest-api-spec/test/watcher_groovy/30_inline_watch.yaml b/elasticsearch/qa/smoke-test-watcher-with-groovy/src/test/resources/rest-api-spec/test/watcher_groovy/30_inline_watch.yaml similarity index 100% rename from qa/smoke-test-watcher-with-groovy/src/test/resources/rest-api-spec/test/watcher_groovy/30_inline_watch.yaml rename to elasticsearch/qa/smoke-test-watcher-with-groovy/src/test/resources/rest-api-spec/test/watcher_groovy/30_inline_watch.yaml diff --git a/qa/smoke-test-watcher-with-shield/build.gradle b/elasticsearch/qa/smoke-test-watcher-with-shield/build.gradle similarity index 60% rename from qa/smoke-test-watcher-with-shield/build.gradle rename to elasticsearch/qa/smoke-test-watcher-with-shield/build.gradle index 64db01497b7..16eb7e07509 100644 --- a/qa/smoke-test-watcher-with-shield/build.gradle +++ b/elasticsearch/qa/smoke-test-watcher-with-shield/build.gradle @@ -1,15 +1,14 @@ apply plugin: 'elasticsearch.rest-test' dependencies { - testCompile project(path: ':x-plugins:shield', configuration: 'runtime') - testCompile project(path: ':x-plugins:watcher', configuration: 'runtime') + testCompile project(path: ':x-plugins:elasticsearch:x-pack', configuration: 'runtime') } // bring in watcher rest test suite task copyWatcherRestTests(type: Copy) { into project.sourceSets.test.output.resourcesDir - from project(':x-plugins:watcher').sourceSets.test.resources.srcDirs - include 'rest-api-spec/test/**' + from project(':x-plugins:elasticsearch:x-pack').sourceSets.test.resources.srcDirs + include 'rest-api-spec/test/watcher/**' } integTest { @@ -19,16 +18,14 @@ integTest { 'array_compare_watch/10_basic/Basic array_compare watch'].join(',') cluster { - plugin 'license', project(':x-plugins:license:plugin') - plugin 'shield', project(':x-plugins:shield') - plugin 'watcher', project(':x-plugins:watcher') - extraConfigFile 'shield/roles.yml', 'roles.yml' + plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack') + extraConfigFile 'x-pack/roles.yml', 'roles.yml' setupCommand 'setupTestAdminUser', - 'bin/shield/esusers', 'useradd', 'test_admin', '-p', 'changeme', '-r', 'admin' + 'bin/x-pack/esusers', 'useradd', 'test_admin', '-p', 'changeme', '-r', 'admin' setupCommand 'setupWatcherManagerUser', - 'bin/shield/esusers', 'useradd', 'watcher_manager', '-p', 'changeme', '-r', 'watcher_manager' + 'bin/x-pack/esusers', 'useradd', 'watcher_manager', '-p', 'changeme', '-r', 'watcher_manager' setupCommand 'setupPowerlessUser', - 'bin/shield/esusers', 'useradd', 'powerless_user', '-p', 'changeme', '-r', 'crapy_role' + 'bin/x-pack/esusers', 'useradd', 'powerless_user', '-p', 'changeme', '-r', 'crapy_role' waitCondition = { node, ant -> File tmpFile = new File(node.cwd, 'wait.success') ant.get(src: "http://localhost:${node.httpPort()}", diff --git a/qa/smoke-test-watcher-with-shield/roles.yml b/elasticsearch/qa/smoke-test-watcher-with-shield/roles.yml similarity index 100% rename from qa/smoke-test-watcher-with-shield/roles.yml rename to elasticsearch/qa/smoke-test-watcher-with-shield/roles.yml diff --git a/qa/smoke-test-watcher-with-shield/src/test/java/org/elasticsearch/smoketest/WatcherWithShieldIT.java b/elasticsearch/qa/smoke-test-watcher-with-shield/src/test/java/org/elasticsearch/smoketest/WatcherWithShieldIT.java similarity index 96% rename from qa/smoke-test-watcher-with-shield/src/test/java/org/elasticsearch/smoketest/WatcherWithShieldIT.java rename to elasticsearch/qa/smoke-test-watcher-with-shield/src/test/java/org/elasticsearch/smoketest/WatcherWithShieldIT.java index 3c5022f7b34..0c2b66ad4c9 100644 --- a/qa/smoke-test-watcher-with-shield/src/test/java/org/elasticsearch/smoketest/WatcherWithShieldIT.java +++ b/elasticsearch/qa/smoke-test-watcher-with-shield/src/test/java/org/elasticsearch/smoketest/WatcherWithShieldIT.java @@ -15,7 +15,7 @@ import org.elasticsearch.client.support.Headers; import org.elasticsearch.common.network.NetworkAddress; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.plugins.Plugin; -import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.authc.support.SecuredString; import org.elasticsearch.shield.authc.support.UsernamePasswordToken; import org.elasticsearch.test.rest.ESRestTestCase; @@ -90,7 +90,7 @@ public class WatcherWithShieldIT extends ESRestTestCase { @Override protected Collection> transportClientPlugins() { - return Collections.>singleton(ShieldPlugin.class); + return Collections.>singleton(XPackPlugin.class); } } diff --git a/qa/smoke-test-watcher-with-shield/src/test/java/org/elasticsearch/smoketest/WatcherWithShieldInsufficientRoleIT.java b/elasticsearch/qa/smoke-test-watcher-with-shield/src/test/java/org/elasticsearch/smoketest/WatcherWithShieldInsufficientRoleIT.java similarity index 100% rename from qa/smoke-test-watcher-with-shield/src/test/java/org/elasticsearch/smoketest/WatcherWithShieldInsufficientRoleIT.java rename to elasticsearch/qa/smoke-test-watcher-with-shield/src/test/java/org/elasticsearch/smoketest/WatcherWithShieldInsufficientRoleIT.java diff --git a/x-dev-tools/RELEASE.md b/elasticsearch/x-dev-tools/RELEASE.md similarity index 100% rename from x-dev-tools/RELEASE.md rename to elasticsearch/x-dev-tools/RELEASE.md diff --git a/x-dev-tools/src/main/resources/ant/shield-overrides.xml b/elasticsearch/x-dev-tools/src/main/resources/ant/shield-overrides.xml similarity index 100% rename from x-dev-tools/src/main/resources/ant/shield-overrides.xml rename to elasticsearch/x-dev-tools/src/main/resources/ant/shield-overrides.xml diff --git a/x-dev-tools/src/main/resources/commercial-license-check/elasticsearch_license_header.txt b/elasticsearch/x-dev-tools/src/main/resources/commercial-license-check/elasticsearch_license_header.txt similarity index 100% rename from x-dev-tools/src/main/resources/commercial-license-check/elasticsearch_license_header.txt rename to elasticsearch/x-dev-tools/src/main/resources/commercial-license-check/elasticsearch_license_header.txt diff --git a/x-dev-tools/src/main/resources/commercial-license-check/license_header_definition.xml b/elasticsearch/x-dev-tools/src/main/resources/commercial-license-check/license_header_definition.xml similarity index 100% rename from x-dev-tools/src/main/resources/commercial-license-check/license_header_definition.xml rename to elasticsearch/x-dev-tools/src/main/resources/commercial-license-check/license_header_definition.xml diff --git a/elasticsearch/x-pack/build.gradle b/elasticsearch/x-pack/build.gradle new file mode 100644 index 00000000000..6177348c490 --- /dev/null +++ b/elasticsearch/x-pack/build.gradle @@ -0,0 +1,139 @@ +import org.elasticsearch.gradle.MavenFilteringHack + +apply plugin: 'elasticsearch.esplugin' +esplugin { + name 'x-pack' + description 'Elasticsearch Expanded Pack Plugin' + classname 'org.elasticsearch.xpack.XPackPlugin' + // FIXME we still can't be isolated due to shield custom realms + isolated false +} + +ext.versions = [ + okhttp: '2.3.0' +] + +// TODO: fix this! https://github.com/elastic/x-plugins/issues/1066 +ext.compactProfile = 'full' + +dependencyLicenses.enabled = false + +dependencies { + // license deps + compile project(':x-plugins:elasticsearch:license:plugin-api') + testCompile project(':x-plugins:elasticsearch:license:licensor') + + // shield deps + compile 'dk.brics.automaton:automaton:1.11-8' + compile 'com.unboundid:unboundid-ldapsdk:2.3.8' + testCompile 'com.google.jimfs:jimfs:1.0' + + // watcher deps + compile 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:r239' + compile 'com.google.guava:guava:16.0.1' // needed by watcher and shield tests for jimfs + compile 'com.google.code.findbugs:jsr305:3.0.1' // TODO: remove this + compile 'com.sun.mail:javax.mail:1.5.3' + compile 'javax.activation:activation:1.1.1' + testCompile 'org.subethamail:subethasmtp:3.1.7' + + // common test deps + testCompile 'org.elasticsearch:securemock:1.1' + testCompile 'org.slf4j:slf4j-log4j12:1.6.2' + testCompile 'org.slf4j:slf4j-api:1.6.2' + + // mock web server + testCompile "com.squareup.okhttp:mockwebserver:${versions.okhttp}" + testCompile "com.squareup.okhttp:okhttp:${versions.okhttp}" + testCompile "com.squareup.okhttp:okhttp-ws:${versions.okhttp}" + testCompile 'com.squareup.okio:okio:1.3.0' + testCompile 'org.bouncycastle:bcprov-jdk15on:1.50' +} + +// we keep the source directories in the original structure of split plugins, +// in order to facilitate backports to 2.x. TODO: remove after 5.0 release +for (String module : ['', 'license-plugin/', 'shield/', 'watcher/', 'marvel/']) { + sourceSets { + main { + java.srcDir("${module}src/main/java") + resources.srcDir("${module}src/main/resources") + } + test { + java.srcDir("${module}src/test/java") + resources.srcDir("${module}src/test/resources") + } + } +} + +compileJava.options.compilerArgs << "-Xlint:-deprecation,-rawtypes,-serial,-try,-unchecked" +compileTestJava.options.compilerArgs << "-Xlint:-deprecation,-rawtypes,-serial,-try,-unchecked" + +ext.expansions = [ + 'project.version': version, + 'integ.http.port': integTest.cluster.baseHttpPort +] + +processResources { + from(sourceSets.main.resources.srcDirs) { + exclude '**/public.key' + inputs.properties(expansions) + MavenFilteringHack.filter(it, expansions) + } + String licenseKeyName = System.getProperty('license.key', 'dev') + String licenseKeyPath = "license-plugin/keys/${licenseKeyName}/public.key" + if (file(licenseKeyPath).exists() == false) { + throw new GradleException("no public key found for '${licenseKeyName}'") + } + from licenseKeyPath +} + +processTestResources { + from(sourceSets.test.resources.srcDirs) { + exclude '**/*.key' + exclude '**/*.jks' + exclude '**/*.p12' + inputs.properties(expansions) + MavenFilteringHack.filter(it, expansions) + } +} + +forbiddenPatterns { + exclude '**/*.key' + exclude '**/*.p12' +} + +// TODO: standardize packaging config for plugins +bundlePlugin { + from(projectDir) { + include 'LICENSE.txt' + include 'NOTICE.txt' + } + from('shield/bin/shield') { + into 'bin' + } + from('shield/config/shield') { + into 'config' + } + from('watcher/bin/watcher') { + into 'bin' + } + + integTest { + cluster { + // TODO set up tests so that shield can be enabled or disabled + systemProperty 'es.shield.enabled', 'false' + } + } +} + +// TODO: don't publish test artifacts just to run messy tests, fix the tests! +// https://github.com/elastic/x-plugins/issues/724 +configurations { + testArtifacts.extendsFrom testRuntime +} +task testJar(type: Jar) { + classifier "test" + from sourceSets.test.output +} +artifacts { + testArtifacts testJar +} diff --git a/elasticsearch/x-pack/license-plugin/.gitignore b/elasticsearch/x-pack/license-plugin/.gitignore new file mode 100644 index 00000000000..ab956abf6f9 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/.gitignore @@ -0,0 +1 @@ +/eclipse-build/ diff --git a/marvel/LICENSE.txt b/elasticsearch/x-pack/license-plugin/LICENSE.txt similarity index 100% rename from marvel/LICENSE.txt rename to elasticsearch/x-pack/license-plugin/LICENSE.txt diff --git a/marvel/NOTICE.txt b/elasticsearch/x-pack/license-plugin/NOTICE.txt similarity index 100% rename from marvel/NOTICE.txt rename to elasticsearch/x-pack/license-plugin/NOTICE.txt diff --git a/elasticsearch/x-pack/license-plugin/keys/dev/public.key b/elasticsearch/x-pack/license-plugin/keys/dev/public.key new file mode 100644 index 00000000000..2a9f272e0b3 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/keys/dev/public.key @@ -0,0 +1,3 @@ +ýŽÇqÝnêÄÌgŠœwM}¹‡UiKŠ•0âbÖ2غqö]â쇴¯ÖÏÃcÌ+IÒðÔ &IJ†fÉ~ßlj ˆº]d™}o§Oè¾Id®È +5A(ìµ´^ØöW©DªJµë}ù-Oîë?u N5¾ÛvpÛ{’¼²Áô­œát–¤7ùøÃê #²Vqöó»ktwm’Œ]ÏLõ£z"| Q‹lŸòQðsâ>ù<}[Á2ÖÓàZÖ|5‹¯ÊÊ7%ØêD +Yå‘xn:¼lúLÈæHò¢«Ë2˜ŸHvEEWÇ\¦H:“6Žh9 [!š…Ûæ©Š¤+;Ö.w7Cì©_|Þ ÓªÏÁ*ñ§D`ƒÚ?‚ùxU/3>x­UÓ“+ è \ No newline at end of file diff --git a/elasticsearch/x-pack/license-plugin/keys/prod/public.key b/elasticsearch/x-pack/license-plugin/keys/prod/public.key new file mode 100644 index 00000000000..cf62043826c --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/keys/prod/public.key @@ -0,0 +1,3 @@ +ýŽÇqÝnêÄÌgŠœwM}¹‡UiKŠ•0âbÖ2ˆŒµô!Â[ÔCצ°ê4O9 š0'‰Q]b‰ÉဖÓ0ëèîqI´™0H7ÔÚaTuîl0ÿˆà5¿ø›&ŒÌjƒŒvÐ¥°[ä®]%Q'–Ì/‰Q;Qý` Ê[È1ûïX^sA€’v½îÿlñ<ÄàTÁÜ¡©ž±ùxh¢¡è÷²?1ì ÅàN3óÑ78ê'D["“Ö½¶GüY!:`j1YŸ…Gõyé@&I‚Ïü²b1Û¡re‰Ø£V!¸ÿæMÍô êÇÌ{ƒ³í[ÜMs“ ½M E?e…Sø¿TË +Y¬¥i:ÄR;«R2HäYkW}šcL׆8 +ÎÁfîs \ No newline at end of file diff --git a/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/LicenseModule.java b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/LicenseModule.java new file mode 100644 index 00000000000..b50a18a09ea --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/LicenseModule.java @@ -0,0 +1,24 @@ +/* + * 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.license.plugin; + +import org.elasticsearch.common.inject.AbstractModule; +import org.elasticsearch.license.core.LicenseVerifier; +import org.elasticsearch.license.plugin.core.LicenseeRegistry; +import org.elasticsearch.license.plugin.core.LicensesManagerService; +import org.elasticsearch.license.plugin.core.LicensesService; + +public class LicenseModule extends AbstractModule { + + @Override + protected void configure() { + bind(LicenseVerifier.class).asEagerSingleton(); + bind(LicensesService.class).asEagerSingleton(); + bind(LicenseeRegistry.class).to(LicensesService.class); + bind(LicensesManagerService.class).to(LicensesService.class); + } + +} \ No newline at end of file diff --git a/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/LicensePlugin.java b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/LicensePlugin.java new file mode 100644 index 00000000000..b4556f40fe1 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/LicensePlugin.java @@ -0,0 +1,93 @@ +/* + * 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.license.plugin; + +import org.elasticsearch.action.ActionModule; +import org.elasticsearch.client.Client; +import org.elasticsearch.cluster.metadata.MetaData; +import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.common.component.LifecycleComponent; +import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.inject.Module; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.license.plugin.action.delete.DeleteLicenseAction; +import org.elasticsearch.license.plugin.action.delete.TransportDeleteLicenseAction; +import org.elasticsearch.license.plugin.action.get.GetLicenseAction; +import org.elasticsearch.license.plugin.action.get.TransportGetLicenseAction; +import org.elasticsearch.license.plugin.action.put.PutLicenseAction; +import org.elasticsearch.license.plugin.action.put.TransportPutLicenseAction; +import org.elasticsearch.license.plugin.core.LicensesMetaData; +import org.elasticsearch.license.plugin.core.LicensesService; +import org.elasticsearch.license.plugin.rest.RestDeleteLicenseAction; +import org.elasticsearch.license.plugin.rest.RestGetLicenseAction; +import org.elasticsearch.license.plugin.rest.RestPutLicenseAction; +import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.rest.RestModule; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; + +public class LicensePlugin extends Plugin { + + public static final String NAME = "license"; + private final boolean isEnabled; + + static { + MetaData.registerPrototype(LicensesMetaData.TYPE, LicensesMetaData.PROTO); + } + + @Inject + public LicensePlugin(Settings settings) { + if (DiscoveryNode.clientNode(settings)) { + // Enable plugin only on node clients + this.isEnabled = "node".equals(settings.get(Client.CLIENT_TYPE_SETTING)); + } else { + this.isEnabled = true; + } + } + + @Override + public String name() { + return NAME; + } + + @Override + public String description() { + return "Internal Elasticsearch Licensing Plugin"; + } + + public void onModule(RestModule module) { + // Register REST endpoint + module.addRestAction(RestPutLicenseAction.class); + module.addRestAction(RestGetLicenseAction.class); + module.addRestAction(RestDeleteLicenseAction.class); + } + + public void onModule(ActionModule module) { + module.registerAction(PutLicenseAction.INSTANCE, TransportPutLicenseAction.class); + module.registerAction(GetLicenseAction.INSTANCE, TransportGetLicenseAction.class); + module.registerAction(DeleteLicenseAction.INSTANCE, TransportDeleteLicenseAction.class); + } + + @Override + public Collection> nodeServices() { + Collection> services = new ArrayList<>(); + if (isEnabled) { + services.add(LicensesService.class); + } + return services; + } + + + @Override + public Collection nodeModules() { + if (isEnabled) { + return Collections.singletonList(new LicenseModule()); + } + return Collections.emptyList(); + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseAction.java b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseAction.java new file mode 100644 index 00000000000..c7c8a675f84 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseAction.java @@ -0,0 +1,29 @@ +/* + * 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.license.plugin.action.delete; + +import org.elasticsearch.action.Action; +import org.elasticsearch.client.ElasticsearchClient; + +public class DeleteLicenseAction extends Action { + + public static final DeleteLicenseAction INSTANCE = new DeleteLicenseAction(); + public static final String NAME = "cluster:admin/plugin/license/delete"; + + private DeleteLicenseAction() { + super(NAME); + } + + @Override + public DeleteLicenseResponse newResponse() { + return new DeleteLicenseResponse(); + } + + @Override + public DeleteLicenseRequestBuilder newRequestBuilder(ElasticsearchClient client) { + return new DeleteLicenseRequestBuilder(client, this); + } +} \ No newline at end of file diff --git a/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseRequest.java b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseRequest.java new file mode 100644 index 00000000000..acfc1e6a9bf --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseRequest.java @@ -0,0 +1,36 @@ +/* + * 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.license.plugin.action.delete; + +import org.elasticsearch.action.ActionRequestValidationException; +import org.elasticsearch.action.support.master.AcknowledgedRequest; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; + +import java.io.IOException; +import java.util.Set; + + +public class DeleteLicenseRequest extends AcknowledgedRequest { + + public DeleteLicenseRequest() { + } + + @Override + public ActionRequestValidationException validate() { + return null; + } + + @Override + public void readFrom(StreamInput in) throws IOException { + super.readFrom(in); + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + super.writeTo(out); + } +} \ No newline at end of file diff --git a/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseRequestBuilder.java b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseRequestBuilder.java new file mode 100644 index 00000000000..c210d54c13f --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseRequestBuilder.java @@ -0,0 +1,23 @@ +/* + * 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.license.plugin.action.delete; + +import org.elasticsearch.action.support.master.AcknowledgedRequestBuilder; +import org.elasticsearch.client.ElasticsearchClient; + +import java.util.Set; + +public class DeleteLicenseRequestBuilder extends AcknowledgedRequestBuilder { + + /** + * Creates new get licenses request builder + * + * @param client elasticsearch client + */ + public DeleteLicenseRequestBuilder(ElasticsearchClient client, DeleteLicenseAction action) { + super(client, action, new DeleteLicenseRequest()); + } +} \ No newline at end of file diff --git a/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseResponse.java b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseResponse.java new file mode 100644 index 00000000000..2b5d35edeae --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseResponse.java @@ -0,0 +1,35 @@ +/* + * 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.license.plugin.action.delete; + +import org.elasticsearch.action.support.master.AcknowledgedResponse; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; + +import java.io.IOException; + +public class DeleteLicenseResponse extends AcknowledgedResponse { + + DeleteLicenseResponse() { + } + + DeleteLicenseResponse(boolean acknowledged) { + super(acknowledged); + } + + @Override + public void readFrom(StreamInput in) throws IOException { + super.readFrom(in); + readAcknowledged(in); + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + super.writeTo(out); + writeAcknowledged(out); + } + +} diff --git a/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/TransportDeleteLicenseAction.java b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/TransportDeleteLicenseAction.java new file mode 100644 index 00000000000..a5c5594cb05 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/TransportDeleteLicenseAction.java @@ -0,0 +1,65 @@ +/* + * 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.license.plugin.action.delete; + +import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.action.ActionListener; +import org.elasticsearch.action.support.ActionFilters; +import org.elasticsearch.action.support.master.TransportMasterNodeAction; +import org.elasticsearch.cluster.ClusterService; +import org.elasticsearch.cluster.ClusterState; +import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse; +import org.elasticsearch.cluster.block.ClusterBlockException; +import org.elasticsearch.cluster.block.ClusterBlockLevel; +import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; +import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.license.plugin.core.LicensesManagerService; +import org.elasticsearch.license.plugin.core.LicensesService; +import org.elasticsearch.threadpool.ThreadPool; +import org.elasticsearch.transport.TransportService; + +public class TransportDeleteLicenseAction extends TransportMasterNodeAction { + + private final LicensesService licensesService; + + @Inject + public TransportDeleteLicenseAction(Settings settings, TransportService transportService, ClusterService clusterService, LicensesService licensesService, + ThreadPool threadPool, ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver) { + super(settings, DeleteLicenseAction.NAME, transportService, clusterService, threadPool, actionFilters, indexNameExpressionResolver, DeleteLicenseRequest::new); + this.licensesService = licensesService; + } + + @Override + protected String executor() { + return ThreadPool.Names.MANAGEMENT; + } + + @Override + protected DeleteLicenseResponse newResponse() { + return new DeleteLicenseResponse(); + } + + @Override + protected ClusterBlockException checkBlock(DeleteLicenseRequest request, ClusterState state) { + return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE); + } + + @Override + protected void masterOperation(final DeleteLicenseRequest request, ClusterState state, final ActionListener listener) throws ElasticsearchException { + licensesService.removeLicense(request, new ActionListener() { + @Override + public void onResponse(ClusterStateUpdateResponse clusterStateUpdateResponse) { + listener.onResponse(new DeleteLicenseResponse(clusterStateUpdateResponse.isAcknowledged())); + } + + @Override + public void onFailure(Throwable e) { + listener.onFailure(e); + } + }); + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseAction.java b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseAction.java new file mode 100644 index 00000000000..d426b1b8aab --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseAction.java @@ -0,0 +1,29 @@ +/* + * 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.license.plugin.action.get; + +import org.elasticsearch.action.Action; +import org.elasticsearch.client.ElasticsearchClient; + +public class GetLicenseAction extends Action { + + public static final GetLicenseAction INSTANCE = new GetLicenseAction(); + public static final String NAME = "cluster:admin/plugin/license/get"; + + private GetLicenseAction() { + super(NAME); + } + + @Override + public GetLicenseResponse newResponse() { + return new GetLicenseResponse(); + } + + @Override + public GetLicenseRequestBuilder newRequestBuilder(ElasticsearchClient client) { + return new GetLicenseRequestBuilder(client, this); + } +} \ No newline at end of file diff --git a/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseRequest.java b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseRequest.java new file mode 100644 index 00000000000..7f8d20512a1 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseRequest.java @@ -0,0 +1,21 @@ +/* + * 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.license.plugin.action.get; + +import org.elasticsearch.action.ActionRequestValidationException; +import org.elasticsearch.action.support.master.MasterNodeReadRequest; + + +public class GetLicenseRequest extends MasterNodeReadRequest { + + public GetLicenseRequest() { + } + + @Override + public ActionRequestValidationException validate() { + return null; + } +} \ No newline at end of file diff --git a/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseRequestBuilder.java b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseRequestBuilder.java new file mode 100644 index 00000000000..a837141e194 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseRequestBuilder.java @@ -0,0 +1,21 @@ +/* + * 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.license.plugin.action.get; + +import org.elasticsearch.action.support.master.MasterNodeReadOperationRequestBuilder; +import org.elasticsearch.client.ElasticsearchClient; + +public class GetLicenseRequestBuilder extends MasterNodeReadOperationRequestBuilder { + + /** + * Creates new get licenses request builder + * + * @param client elasticsearch client + */ + public GetLicenseRequestBuilder(ElasticsearchClient client, GetLicenseAction action) { + super(client, action, new GetLicenseRequest()); + } +} \ No newline at end of file diff --git a/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseResponse.java b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseResponse.java new file mode 100644 index 00000000000..95f4799e618 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseResponse.java @@ -0,0 +1,49 @@ +/* + * 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.license.plugin.action.get; + +import org.elasticsearch.action.ActionResponse; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.license.core.License; + +import java.io.IOException; + +public class GetLicenseResponse extends ActionResponse { + + private License license; + + GetLicenseResponse() { + } + + GetLicenseResponse(License license) { + this.license = license; + } + + public License license() { + return license; + } + + @Override + public void readFrom(StreamInput in) throws IOException { + super.readFrom(in); + if (in.readBoolean()) { + license = License.readLicense(in); + } + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + super.writeTo(out); + if (license == null) { + out.writeBoolean(false); + } else { + out.writeBoolean(true); + license.writeTo(out); + } + } + +} \ No newline at end of file diff --git a/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/get/TransportGetLicenseAction.java b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/get/TransportGetLicenseAction.java new file mode 100644 index 00000000000..3a9a0c24a0b --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/get/TransportGetLicenseAction.java @@ -0,0 +1,53 @@ +/* + * 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.license.plugin.action.get; + +import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.action.ActionListener; +import org.elasticsearch.action.support.ActionFilters; +import org.elasticsearch.action.support.master.TransportMasterNodeReadAction; +import org.elasticsearch.cluster.ClusterService; +import org.elasticsearch.cluster.ClusterState; +import org.elasticsearch.cluster.block.ClusterBlockException; +import org.elasticsearch.cluster.block.ClusterBlockLevel; +import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; +import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.license.plugin.core.LicensesManagerService; +import org.elasticsearch.threadpool.ThreadPool; +import org.elasticsearch.transport.TransportService; + +public class TransportGetLicenseAction extends TransportMasterNodeReadAction { + + private final LicensesManagerService licensesManagerService; + + @Inject + public TransportGetLicenseAction(Settings settings, TransportService transportService, ClusterService clusterService, LicensesManagerService licensesManagerService, + ThreadPool threadPool, ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver) { + super(settings, GetLicenseAction.NAME, transportService, clusterService, threadPool, actionFilters, indexNameExpressionResolver, GetLicenseRequest::new); + this.licensesManagerService = licensesManagerService; + } + + @Override + protected String executor() { + return ThreadPool.Names.MANAGEMENT; + } + + @Override + protected GetLicenseResponse newResponse() { + return new GetLicenseResponse(); + } + + @Override + protected ClusterBlockException checkBlock(GetLicenseRequest request, ClusterState state) { + return state.blocks().indexBlockedException(ClusterBlockLevel.METADATA_READ, ""); + } + + @Override + protected void masterOperation(final GetLicenseRequest request, ClusterState state, final ActionListener listener) throws ElasticsearchException { + listener.onResponse(new GetLicenseResponse(licensesManagerService.getLicense())); + } +} \ No newline at end of file diff --git a/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseAction.java b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseAction.java new file mode 100644 index 00000000000..e90523b9c1d --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseAction.java @@ -0,0 +1,29 @@ +/* + * 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.license.plugin.action.put; + +import org.elasticsearch.action.Action; +import org.elasticsearch.client.ElasticsearchClient; + +public class PutLicenseAction extends Action { + + public static final PutLicenseAction INSTANCE = new PutLicenseAction(); + public static final String NAME = "cluster:admin/plugin/license/put"; + + private PutLicenseAction() { + super(NAME); + } + + @Override + public PutLicenseResponse newResponse() { + return new PutLicenseResponse(); + } + + @Override + public PutLicenseRequestBuilder newRequestBuilder(ElasticsearchClient client) { + return new PutLicenseRequestBuilder(client, this); + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseRequest.java b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseRequest.java new file mode 100644 index 00000000000..7780908cce9 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseRequest.java @@ -0,0 +1,77 @@ +/* + * 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.license.plugin.action.put; + +import org.elasticsearch.action.ActionRequestValidationException; +import org.elasticsearch.action.ValidateActions; +import org.elasticsearch.action.support.master.AcknowledgedRequest; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.license.core.License; + +import java.io.IOException; + + +public class PutLicenseRequest extends AcknowledgedRequest { + + private License license; + private boolean acknowledge = false; + + public PutLicenseRequest() { + } + + @Override + public ActionRequestValidationException validate() { + return (license == null) ? ValidateActions.addValidationError("license is missing", null) : null; + } + + /** + * Parses license from json format to an instance of {@link org.elasticsearch.license.core.License} + * + * @param licenseDefinition licenses definition + */ + public PutLicenseRequest license(String licenseDefinition) { + try { + return license(License.fromSource(licenseDefinition)); + } catch (IOException e) { + throw new IllegalArgumentException("failed to parse license source", e); + } + } + + public PutLicenseRequest license(License license) { + this.license = license; + return this; + } + + public License license() { + return license; + } + + public PutLicenseRequest acknowledge(boolean acknowledge) { + this.acknowledge = acknowledge; + return this; + } + + public boolean acknowledged() { + return acknowledge; + } + + @Override + public void readFrom(StreamInput in) throws IOException { + super.readFrom(in); + license = License.readLicense(in); + acknowledge = in.readBoolean(); + readTimeout(in); + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + super.writeTo(out); + license.writeTo(out); + out.writeBoolean(acknowledge); + writeTimeout(out); + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseRequestBuilder.java b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseRequestBuilder.java new file mode 100644 index 00000000000..b4a3a5e8499 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseRequestBuilder.java @@ -0,0 +1,46 @@ +/* + * 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.license.plugin.action.put; + +import org.elasticsearch.action.support.master.AcknowledgedRequestBuilder; +import org.elasticsearch.client.ElasticsearchClient; +import org.elasticsearch.license.core.License; + +/** + * Register license request builder + */ +public class PutLicenseRequestBuilder extends AcknowledgedRequestBuilder { + + /** + * Constructs register license request + * + * @param client elasticsearch client + */ + public PutLicenseRequestBuilder(ElasticsearchClient client, PutLicenseAction action) { + super(client, action, new PutLicenseRequest()); + } + + /** + * Sets the license + * + * @param license license + * @return this builder + */ + public PutLicenseRequestBuilder setLicense(License license) { + request.license(license); + return this; + } + + public PutLicenseRequestBuilder setLicense(String licenseSource) { + request.license(licenseSource); + return this; + } + + public PutLicenseRequestBuilder setAcknowledge(boolean acknowledge) { + request.acknowledge(acknowledge); + return this; + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseResponse.java b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseResponse.java new file mode 100644 index 00000000000..0bd0839b5da --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseResponse.java @@ -0,0 +1,129 @@ +/* + * 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.license.plugin.action.put; + +import org.elasticsearch.action.support.master.AcknowledgedResponse; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.license.plugin.core.LicensesStatus; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class PutLicenseResponse extends AcknowledgedResponse implements ToXContent { + + private LicensesStatus status; + private Map acknowledgeMessages; + private String acknowledgeHeader; + + PutLicenseResponse() { + } + + public PutLicenseResponse(boolean acknowledged, LicensesStatus status, String acknowledgeHeader, Map acknowledgeMessages) { + super(acknowledged); + this.status = status; + this.acknowledgeHeader = acknowledgeHeader; + this.acknowledgeMessages = acknowledgeMessages; + } + + public LicensesStatus status() { + return status; + } + + public Map acknowledgeMessages() { + return acknowledgeMessages; + } + + public String acknowledgeHeader() { + return acknowledgeHeader; + } + + @Override + public void readFrom(StreamInput in) throws IOException { + super.readFrom(in); + readAcknowledged(in); + status = LicensesStatus.fromId(in.readVInt()); + acknowledgeHeader = in.readOptionalString(); + int size = in.readVInt(); + Map acknowledgeMessages = new HashMap<>(size); + for (int i = 0; i < size; i++) { + String feature = in.readString(); + int nMessages = in.readVInt(); + String[] messages = new String[nMessages]; + for (int j = 0; j < nMessages; j++) { + messages[i] = in.readString(); + } + acknowledgeMessages.put(feature, messages); + } + this.acknowledgeMessages = acknowledgeMessages; + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + super.writeTo(out); + writeAcknowledged(out); + out.writeVInt(status.id()); + out.writeOptionalString(acknowledgeHeader); + out.writeVInt(acknowledgeMessages.size()); + for (Map.Entry entry : acknowledgeMessages.entrySet()) { + out.writeString(entry.getKey()); + out.writeVInt(entry.getValue().length); + for (String message : entry.getValue()) { + out.writeString(message); + } + } + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.field("acknowledged", isAcknowledged()); + switch (status) { + case VALID: + builder.field("license_status", "valid"); + break; + case INVALID: + builder.field("license_status", "invalid"); + break; + case EXPIRED: + builder.field("license_status", "expired"); + break; + default: + throw new IllegalArgumentException("unknown status [" + status + "] found"); + } + if (!acknowledgeMessages.isEmpty()) { + builder.startObject("acknowledge"); + builder.field("message", acknowledgeHeader); + for (Map.Entry entry : acknowledgeMessages.entrySet()) { + builder.startArray(entry.getKey()); + for (String message : entry.getValue()) { + builder.value(message); + } + builder.endArray(); + } + builder.endObject(); + } + return builder; + } + + @Override + public String toString() { + try { + XContentBuilder builder = XContentFactory.jsonBuilder().prettyPrint(); + builder.startObject(); + toXContent(builder, EMPTY_PARAMS); + builder.endObject(); + return builder.string(); + } catch (IOException e) { + return "{ \"error\" : \"" + e.getMessage() + "\"}"; + } + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/put/TransportPutLicenseAction.java b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/put/TransportPutLicenseAction.java new file mode 100644 index 00000000000..8eda9c4ffb4 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/action/put/TransportPutLicenseAction.java @@ -0,0 +1,68 @@ +/* + * 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.license.plugin.action.put; + +import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.action.ActionListener; +import org.elasticsearch.action.support.ActionFilters; +import org.elasticsearch.action.support.master.TransportMasterNodeAction; +import org.elasticsearch.cluster.ClusterService; +import org.elasticsearch.cluster.ClusterState; +import org.elasticsearch.cluster.block.ClusterBlockException; +import org.elasticsearch.cluster.block.ClusterBlockLevel; +import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; +import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.license.plugin.core.LicensesManagerService; +import org.elasticsearch.license.plugin.core.LicensesService; +import org.elasticsearch.threadpool.ThreadPool; +import org.elasticsearch.transport.TransportService; + +import static org.elasticsearch.license.plugin.core.LicensesService.LicensesUpdateResponse; + +public class TransportPutLicenseAction extends TransportMasterNodeAction { + + private final LicensesService licensesService; + + @Inject + public TransportPutLicenseAction(Settings settings, TransportService transportService, ClusterService clusterService, + LicensesService licensesService, ThreadPool threadPool, ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver) { + super(settings, PutLicenseAction.NAME, transportService, clusterService, threadPool, actionFilters, indexNameExpressionResolver, PutLicenseRequest::new); + this.licensesService = licensesService; + } + + @Override + protected String executor() { + return ThreadPool.Names.MANAGEMENT; + } + + @Override + protected PutLicenseResponse newResponse() { + return new PutLicenseResponse(); + } + + @Override + protected ClusterBlockException checkBlock(PutLicenseRequest request, ClusterState state) { + return state.blocks().indexBlockedException(ClusterBlockLevel.METADATA_WRITE, ""); + } + + @Override + protected void masterOperation(final PutLicenseRequest request, ClusterState state, final ActionListener listener) throws ElasticsearchException { + licensesService.registerLicense(request, new ActionListener() { + @Override + public void onResponse(LicensesUpdateResponse licensesUpdateResponse) { + listener.onResponse(new PutLicenseResponse(licensesUpdateResponse.isAcknowledged(), licensesUpdateResponse.status(), + licensesUpdateResponse.acknowledgementHeader(), licensesUpdateResponse.acknowledgeMessages())); + } + + @Override + public void onFailure(Throwable e) { + listener.onFailure(e); + } + }); + } + +} diff --git a/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesMetaData.java b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesMetaData.java new file mode 100644 index 00000000000..03c58bcdf54 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesMetaData.java @@ -0,0 +1,237 @@ +/* + * 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.license.plugin.core; + +import org.apache.lucene.util.CollectionUtil; +import org.elasticsearch.Version; +import org.elasticsearch.cluster.AbstractDiffable; +import org.elasticsearch.cluster.metadata.MetaData; +import org.elasticsearch.common.Base64; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.common.xcontent.*; +import org.elasticsearch.license.core.License; + +import java.io.IOException; +import java.util.*; + +import static org.elasticsearch.license.core.CryptUtils.decrypt; +import static org.elasticsearch.license.core.CryptUtils.encrypt; + +/** + * Contains metadata about registered licenses + */ +public class LicensesMetaData extends AbstractDiffable implements MetaData.Custom { + + public static final String TYPE = "licenses"; + + /** + * When license is explicitly removed by a user, LICENSE_TOMBSTONE + * is used as a placeholder in the license metadata. This enables + * us to distinguish between the scenario when a cluster never + * had a license (null) and when a license was removed explicitly + * (LICENSE_TOMBSTONE). + * We rely on this to decide whether to generate a unsigned trial + * license or not. we should only generate a license if no license + * ever existed in the cluster state + */ + public static final License LICENSE_TOMBSTONE = License.builder() + .type("trial") + .issuer("elasticsearch") + .uid("TOMBSTONE") + .issuedTo("") + .maxNodes(0) + .issueDate(0) + .expiryDate(0) + .build(); + + public static final LicensesMetaData PROTO = new LicensesMetaData(null); + + private License license; + + public LicensesMetaData(License license) { + this.license = license; + } + + public License getLicense() { + return license; + } + + @Override + public String toString() { + if (license != null) { + return license.toString(); + } + return ""; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + LicensesMetaData that = (LicensesMetaData) o; + return !(license != null ? !license.equals(that.license) : that.license != null); + } + + @Override + public int hashCode() { + return license != null ? license.hashCode() : 0; + } + + @Override + public String type() { + return TYPE; + } + + @Override + public EnumSet context() { + return EnumSet.of(MetaData.XContentContext.GATEWAY); + } + + @Override + public LicensesMetaData fromXContent(XContentParser parser) throws IOException { + List pre20Licenses = new ArrayList<>(1); + License license = LICENSE_TOMBSTONE; + while (parser.currentToken() != XContentParser.Token.END_OBJECT) { + XContentParser.Token token = parser.nextToken(); + if (token == XContentParser.Token.FIELD_NAME) { + String fieldName = parser.text(); + if (fieldName != null) { + // for back compat with 1.x license metadata + if (fieldName.equals(Fields.TRIAL_LICENSES) || fieldName.equals(Fields.SIGNED_LICENCES)) { + token = parser.nextToken(); + if (token == XContentParser.Token.START_ARRAY) { + while (parser.nextToken() != XContentParser.Token.END_ARRAY) { + if (parser.currentToken().isValue()) { + // trial license + byte[] data = decrypt(Base64.decode(parser.text())); + try (XContentParser trialLicenseParser = XContentFactory.xContent(XContentType.JSON).createParser(data)) { + trialLicenseParser.nextToken(); + License pre20TrialLicense = License.fromXContent(trialLicenseParser); + pre20Licenses.add(TrialLicense.create(License.builder().fromPre20LicenseSpec(pre20TrialLicense))); + } + } else { + // signed license + pre20Licenses.add(License.fromXContent(parser)); + } + } + } + } else if (fieldName.equals(Fields.LICENSE)) { + token = parser.nextToken(); + if (token == XContentParser.Token.START_OBJECT) { + license = License.fromXContent(parser); + } else if (token == XContentParser.Token.VALUE_NULL) { + license = LICENSE_TOMBSTONE; + } + } + } + } + } + // when we see old license metadata, + // we try to choose the license that has the latest issue date that is not expired + if (!pre20Licenses.isEmpty()) { + // take the best unexpired license + CollectionUtil.timSort(pre20Licenses, License.LATEST_ISSUE_DATE_FIRST); + long now = System.currentTimeMillis(); + for (License oldLicense : pre20Licenses) { + if (oldLicense.expiryDate() > now) { + license = oldLicense; + break; + } + } + // take the best expired license + if (license == LICENSE_TOMBSTONE && !pre20Licenses.isEmpty()) { + license = pre20Licenses.get(0); + } + } + return new LicensesMetaData(license); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + if (license == LICENSE_TOMBSTONE) { + builder.nullField(Fields.LICENSE); + } else { + builder.startObject(Fields.LICENSE); + license.toInnerXContent(builder, params); + builder.endObject(); + } + return builder; + } + + @Override + public void writeTo(StreamOutput streamOutput) throws IOException { + if (streamOutput.getVersion().before(Version.V_2_0_0)) { + if (license == LICENSE_TOMBSTONE) { + streamOutput.writeVInt(0); // no signed license + streamOutput.writeVInt(0); // no trial license + } else if (!License.isAutoGeneratedLicense(license.signature())) { + streamOutput.writeVInt(1); // one signed license + license.writeTo(streamOutput); + streamOutput.writeVInt(0); // no trial license + } else { + streamOutput.writeVInt(0); // no signed license + streamOutput.writeVInt(1); // one trial license + XContentBuilder contentBuilder = XContentFactory.contentBuilder(XContentType.JSON); + license.toXContent(contentBuilder, new ToXContent.MapParams(Collections.singletonMap(License.LICENSE_SPEC_VIEW_MODE, "true"))); + streamOutput.writeString(Base64.encodeBytes(encrypt(contentBuilder.bytes().toBytes()))); + } + } else { + if (license == LICENSE_TOMBSTONE) { + streamOutput.writeBoolean(false); // no license + } else { + streamOutput.writeBoolean(true); // has a license + license.writeTo(streamOutput); + } + } + } + + @Override + public LicensesMetaData readFrom(StreamInput streamInput) throws IOException { + License license = LICENSE_TOMBSTONE; + if (streamInput.getVersion().before(Version.V_2_0_0)) { + int size = streamInput.readVInt(); + List licenses = new ArrayList<>(); + for (int i = 0; i < size; i++) { + licenses.add(License.readLicense(streamInput)); + } + int numTrialLicenses = streamInput.readVInt(); + for (int i = 0; i < numTrialLicenses; i++) { + byte[] data = decrypt(Base64.decode(streamInput.readString())); + try (XContentParser trialLicenseParser = XContentFactory.xContent(XContentType.JSON).createParser(data)) { + trialLicenseParser.nextToken(); + License pre20TrialLicense = License.fromXContent(trialLicenseParser); + licenses.add(TrialLicense.create(License.builder().fromPre20LicenseSpec(pre20TrialLicense))); + } + } + // when we see read licenses from old pre v2.0, + // we try to choose the license that has the latest issue date that is not expired + CollectionUtil.timSort(licenses, License.LATEST_ISSUE_DATE_FIRST); + long now = System.currentTimeMillis(); + for (License oldLicense : licenses) { + if (oldLicense.expiryDate() > now) { + license = oldLicense; + break; + } + } + // take the best expired license + if (license == LICENSE_TOMBSTONE && !licenses.isEmpty()) { + license = licenses.get(0); + } + } else { + if (streamInput.readBoolean()) { + license = License.readLicense(streamInput); + } + } + return new LicensesMetaData(license); + } + + private final static class Fields { + private static final String SIGNED_LICENCES = "signed_licenses"; + private static final String TRIAL_LICENSES = "trial_licenses"; + private static final String LICENSE = "license"; + } +} \ No newline at end of file diff --git a/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesService.java b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesService.java new file mode 100644 index 00000000000..95bde3a6d86 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesService.java @@ -0,0 +1,845 @@ +/* + * 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.license.plugin.core; + +import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.action.ActionListener; +import org.elasticsearch.cluster.*; +import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse; +import org.elasticsearch.cluster.metadata.MetaData; +import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.common.Nullable; +import org.elasticsearch.common.component.AbstractLifecycleComponent; +import org.elasticsearch.common.component.Lifecycle; +import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.inject.Singleton; +import org.elasticsearch.common.io.Streams; +import org.elasticsearch.common.joda.FormatDateTimeFormatter; +import org.elasticsearch.common.joda.Joda; +import org.elasticsearch.common.logging.support.LoggerMessageFormat; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.common.util.concurrent.EsRejectedExecutionException; +import org.elasticsearch.common.util.concurrent.FutureUtils; +import org.elasticsearch.gateway.GatewayService; +import org.elasticsearch.license.core.License; +import org.elasticsearch.license.core.LicenseVerifier; +import org.elasticsearch.license.plugin.action.delete.DeleteLicenseRequest; +import org.elasticsearch.license.plugin.action.put.PutLicenseRequest; +import org.elasticsearch.threadpool.ThreadPool; +import org.elasticsearch.transport.*; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.*; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.atomic.AtomicReference; + +/** + * Service responsible for managing {@link LicensesMetaData} + * Interfaces through which this is exposed are: + * - LicensesManagerService - responsible for managing signed and one-time-trial licenses + * - LicensesClientService - responsible for listener registration of consumer plugin(s) + *

+ * Registration Scheme: + *

+ * A consumer plugin is registered with {@link LicenseeRegistry#register(Licensee)} + * This method can be called at any time during the life-cycle of the consumer plugin. + * If the listener can not be registered immediately, it is queued up and registered on the first clusterChanged event with + * no {@link org.elasticsearch.gateway.GatewayService#STATE_NOT_RECOVERED_BLOCK} block + * Upon successful registration, the listeners are notified appropriately using the notification scheme + *

+ * Notification Scheme: + *

+ * All registered listeners are notified of the current license upon registration or when a new license is installed in the cluster state. + * When a new license is notified as enabled to the registered listener, a notification is scheduled at the time of license expiry. + * Registered listeners are notified using {@link #notifyAndSchedule(LicensesMetaData)} + */ +@Singleton +public class LicensesService extends AbstractLifecycleComponent implements ClusterStateListener, LicensesManagerService, LicenseeRegistry { + + public static final String REGISTER_TRIAL_LICENSE_ACTION_NAME = "internal:plugin/license/cluster/register_trial_license"; + + private final ClusterService clusterService; + + private final ThreadPool threadPool; + + private final TransportService transportService; + + /** + * Currently active consumers to notify to + */ + private final List registeredLicensees = new CopyOnWriteArrayList<>(); + + /** + * Currently active expiry notifications + */ + private final Queue expiryNotifications = new ConcurrentLinkedQueue<>(); + + /** + * Currently active event notifications for every registered listener + */ + private final Queue eventNotifications = new ConcurrentLinkedQueue<>(); + + /** + * Currently active license + */ + private final AtomicReference currentLicense = new AtomicReference<>(); + + /** + * Callbacks to notify relative to license expiry + */ + private List expirationCallbacks = new ArrayList<>(); + + /** + * Duration of generated trial license + */ + private TimeValue trialLicenseDuration = TimeValue.timeValueHours(30 * 24); + + /** + * Max number of nodes licensed by generated trial license + */ + private int trialLicenseMaxNodes = 1000; + + /** + * Duration of grace period after a license has expired + */ + private TimeValue gracePeriodDuration = days(7); + + private static final FormatDateTimeFormatter DATE_FORMATTER = Joda.forPattern("EEEE, MMMMM dd, yyyy", Locale.ROOT); + + private static final String ACKNOWLEDGEMENT_HEADER = "This license update requires acknowledgement. To acknowledge the license, please read the following messages and update the license again, this time with the \"acknowledge=true\" parameter:"; + + @Inject + public LicensesService(Settings settings, ClusterService clusterService, ThreadPool threadPool, TransportService transportService) { + super(settings); + this.clusterService = clusterService; + this.threadPool = threadPool; + this.transportService = transportService; + if (DiscoveryNode.masterNode(settings)) { + transportService.registerRequestHandler(REGISTER_TRIAL_LICENSE_ACTION_NAME, TransportRequest.Empty::new, + ThreadPool.Names.SAME, new RegisterTrialLicenseRequestHandler()); + } + populateExpirationCallbacks(); + } + + private void populateExpirationCallbacks() { + expirationCallbacks.add(new ExpirationCallback.Pre(days(7), days(30), days(1)) { + @Override + public void on(License license) { + String general = LoggerMessageFormat.format(null, "\n" + + "#\n" + + "# License will expire on [{}]. If you have a new license, please update it.\n" + + "# Otherwise, please reach out to your support contact.\n" + + "# ", DATE_FORMATTER.printer().print(license.expiryDate())); + if (!registeredLicensees.isEmpty()) { + StringBuilder builder = new StringBuilder(general); + builder.append(System.lineSeparator()); + builder.append("# Commercial plugins operate with reduced functionality on license expiration:"); + for (InternalLicensee licensee : registeredLicensees) { + if (licensee.expirationMessages().length > 0) { + builder.append(System.lineSeparator()); + builder.append("# - "); + builder.append(licensee.id()); + for (String message : licensee.expirationMessages()) { + builder.append(System.lineSeparator()); + builder.append("# - "); + builder.append(message); + } + } + } + logger.error(builder.toString()); + } else { + logger.error(general); + } + } + } + ); + expirationCallbacks.add(new ExpirationCallback.Pre(days(0), days(7), TimeValue.timeValueMinutes(10)) { + @Override + public void on(License license) { + String general = LoggerMessageFormat.format(null, "\n" + + "#\n" + + "# License will expire on [{}]. If you have a new license, please update it.\n" + + "# Otherwise, please reach out to your support contact.\n" + + "# ", DATE_FORMATTER.printer().print(license.expiryDate())); + if (!registeredLicensees.isEmpty()) { + StringBuilder builder = new StringBuilder(general); + builder.append(System.lineSeparator()); + builder.append("# Commercial plugins operate with reduced functionality on license expiration:"); + for (InternalLicensee licensee : registeredLicensees) { + if (licensee.expirationMessages().length > 0) { + builder.append(System.lineSeparator()); + builder.append("# - "); + builder.append(licensee.id()); + for (String message : licensee.expirationMessages()) { + builder.append(System.lineSeparator()); + builder.append("# - "); + builder.append(message); + } + } + } + logger.error(builder.toString()); + } else { + logger.error(general); + } + } + } + ); + expirationCallbacks.add(new ExpirationCallback.Post(days(0), null, TimeValue.timeValueMinutes(10)) { + @Override + public void on(License license) { + // logged when grace period begins + String general = LoggerMessageFormat.format(null, "\n" + + "#\n" + + "# LICENSE EXPIRED ON [{}]. IF YOU HAVE A NEW LICENSE, PLEASE\n" + + "# UPDATE IT. OTHERWISE, PLEASE REACH OUT TO YOUR SUPPORT CONTACT.\n" + + "# ", DATE_FORMATTER.printer().print(license.expiryDate())); + if (!registeredLicensees.isEmpty()) { + StringBuilder builder = new StringBuilder(general); + builder.append(System.lineSeparator()); + builder.append("# COMMERCIAL PLUGINS OPERATING WITH REDUCED FUNCTIONALITY"); + for (InternalLicensee licensee : registeredLicensees) { + if (licensee.expirationMessages().length > 0) { + builder.append(System.lineSeparator()); + builder.append("# - "); + builder.append(licensee.id()); + for (String message : licensee.expirationMessages()) { + builder.append(System.lineSeparator()); + builder.append("# - "); + builder.append(message); + } + } + } + logger.error(builder.toString()); + } else { + logger.error(general); + } + } + } + ); + } + + /** + * Registers new license in the cluster + * Master only operation. Installs a new license on the master provided it is VALID + */ + public void registerLicense(final PutLicenseRequest request, final ActionListener listener) { + final License newLicense = request.license(); + final long now = System.currentTimeMillis(); + if (!verifyLicense(newLicense) || newLicense.issueDate() > now) { + listener.onResponse(new LicensesUpdateResponse(true, LicensesStatus.INVALID)); + } else if (newLicense.expiryDate() < now) { + listener.onResponse(new LicensesUpdateResponse(true, LicensesStatus.EXPIRED)); + } else { + if (!request.acknowledged()) { + final LicensesMetaData currentMetaData = clusterService.state().metaData().custom(LicensesMetaData.TYPE); + final License currentLicense = getLicense(currentMetaData); + Map acknowledgeMessages = new HashMap<>(registeredLicensees.size() + 1); + if (currentLicense != null && !License.isAutoGeneratedLicense(currentLicense.signature()) // when current license is not an auto-generated license + && currentLicense.issueDate() > newLicense.issueDate()) { // and has a later issue date + acknowledgeMessages.put("license", + new String[] { "The new license is older than the currently installed license. Are you sure you want to override the current license?" }); + } + for (InternalLicensee licensee : registeredLicensees) { + String[] listenerAcknowledgeMessages = licensee.acknowledgmentMessages(currentLicense, newLicense); + if (listenerAcknowledgeMessages.length > 0) { + acknowledgeMessages.put(licensee.id(), listenerAcknowledgeMessages); + } + } + if (!acknowledgeMessages.isEmpty()) { + // needs acknowledgement + listener.onResponse(new LicensesUpdateResponse(false, LicensesStatus.VALID, ACKNOWLEDGEMENT_HEADER, acknowledgeMessages)); + return; + } + } + clusterService.submitStateUpdateTask("register license [" + newLicense.uid() + "]", new AckedClusterStateUpdateTask(request, listener) { + @Override + protected LicensesUpdateResponse newResponse(boolean acknowledged) { + return new LicensesUpdateResponse(acknowledged, LicensesStatus.VALID); + } + + @Override + public ClusterState execute(ClusterState currentState) throws Exception { + MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData()); + mdBuilder.putCustom(LicensesMetaData.TYPE, new LicensesMetaData(newLicense)); + return ClusterState.builder(currentState).metaData(mdBuilder).build(); + } + }); + } + } + + private boolean verifyLicense(final License license) { + final byte[] publicKeyBytes; + try (InputStream is = LicensesService.class.getResourceAsStream("/public.key")) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + Streams.copy(is, out); + publicKeyBytes = out.toByteArray(); + } catch (IOException ex) { + throw new IllegalStateException(ex); + } + return LicenseVerifier.verifyLicense(license, publicKeyBytes); + } + + static TimeValue days(int days) { + return TimeValue.timeValueHours(days * 24); + } + + public static class LicensesUpdateResponse extends ClusterStateUpdateResponse { + private final LicensesStatus status; + private final String acknowledgementHeader; + private final Map acknowledgeMessages; + + public LicensesUpdateResponse(boolean acknowledged, LicensesStatus status) { + this(acknowledged, status, null, Collections.emptyMap()); + } + + public LicensesUpdateResponse(boolean acknowledged, LicensesStatus status, String acknowledgementHeader, Map acknowledgeMessages) { + super(acknowledged); + this.status = status; + this.acknowledgeMessages = acknowledgeMessages; + this.acknowledgementHeader = acknowledgementHeader; + } + + public LicensesStatus status() { + return status; + } + + public String acknowledgementHeader() { + return acknowledgementHeader; + } + + public Map acknowledgeMessages() { + return acknowledgeMessages; + } + } + + /** + * Remove license from the cluster state metadata + */ + public void removeLicense(final DeleteLicenseRequest request, final ActionListener listener) { + clusterService.submitStateUpdateTask("delete license", new AckedClusterStateUpdateTask(request, listener) { + @Override + protected ClusterStateUpdateResponse newResponse(boolean acknowledged) { + return new ClusterStateUpdateResponse(acknowledged); + } + + @Override + public ClusterState execute(ClusterState currentState) throws Exception { + MetaData metaData = currentState.metaData(); + final LicensesMetaData currentLicenses = metaData.custom(LicensesMetaData.TYPE); + if (currentLicenses.getLicense() != LicensesMetaData.LICENSE_TOMBSTONE) { + MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData()); + mdBuilder.putCustom(LicensesMetaData.TYPE, new LicensesMetaData(LicensesMetaData.LICENSE_TOMBSTONE)); + return ClusterState.builder(currentState).metaData(mdBuilder).build(); + } else { + return currentState; + } + } + }); + } + + @Override + public List licenseesWithState(LicenseState state) { + List licensees = new ArrayList<>(registeredLicensees.size()); + for (InternalLicensee licensee : registeredLicensees) { + if (licensee.currentLicenseState == state) { + licensees.add(licensee.id()); + } + } + return licensees; + } + + @Override + public License getLicense() { + final LicensesMetaData metaData = clusterService.state().metaData().custom(LicensesMetaData.TYPE); + return getLicense(metaData); + } + + /** + * Master-only operation to generate a one-time global trial license. + * The trial license is only generated and stored if the current cluster state metaData + * has no signed/trial license + */ + private void registerTrialLicense() { + clusterService.submitStateUpdateTask("generate trial license for [" + trialLicenseDuration + "]", new ClusterStateUpdateTask() { + @Override + public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) { + LicensesMetaData licensesMetaData = newState.metaData().custom(LicensesMetaData.TYPE); + if (logger.isDebugEnabled()) { + logger.debug("registered trial license", licensesMetaData); + } + } + + @Override + public ClusterState execute(ClusterState currentState) throws Exception { + final MetaData metaData = currentState.metaData(); + final LicensesMetaData currentLicensesMetaData = metaData.custom(LicensesMetaData.TYPE); + MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData()); + // do not generate a trial license if any license is present + if (currentLicensesMetaData == null) { + long issueDate = System.currentTimeMillis(); + License.Builder specBuilder = License.builder() + .uid(UUID.randomUUID().toString()) + .issuedTo(clusterService.state().getClusterName().value()) + .maxNodes(trialLicenseMaxNodes) + .issueDate(issueDate) + .expiryDate(issueDate + trialLicenseDuration.getMillis()); + License trialLicense = TrialLicense.create(specBuilder); + mdBuilder.putCustom(LicensesMetaData.TYPE, new LicensesMetaData(trialLicense)); + return ClusterState.builder(currentState).metaData(mdBuilder).build(); + } + return currentState; + } + + @Override + public void onFailure(String source, @Nullable Throwable t) { + logger.error("unexpected failure during [{}]", t, source); + } + + }); + } + + @Override + protected void doStart() throws ElasticsearchException { + clusterService.add(this); + } + + @Override + protected void doStop() throws ElasticsearchException { + clusterService.remove(this); + + // cancel all notifications + for (ScheduledFuture scheduledNotification : expiryNotifications) { + FutureUtils.cancel(scheduledNotification); + } + for (ScheduledFuture eventNotification : eventNotifications) { + FutureUtils.cancel(eventNotification); + } + + // clear all handlers + registeredLicensees.clear(); + + // empty out notification queue + expiryNotifications.clear(); + + // clear current license + currentLicense.set(null); + } + + @Override + protected void doClose() throws ElasticsearchException { + transportService.removeHandler(REGISTER_TRIAL_LICENSE_ACTION_NAME); + } + + /** + * When there is no global block on {@link org.elasticsearch.gateway.GatewayService#STATE_NOT_RECOVERED_BLOCK} + * notify licensees and issue auto-generated license if no license has been installed/issued yet. + */ + @Override + public void clusterChanged(ClusterChangedEvent event) { + final ClusterState previousClusterState = event.previousState(); + final ClusterState currentClusterState = event.state(); + if (!currentClusterState.blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK)) { + final LicensesMetaData prevLicensesMetaData = previousClusterState.getMetaData().custom(LicensesMetaData.TYPE); + final LicensesMetaData currentLicensesMetaData = currentClusterState.getMetaData().custom(LicensesMetaData.TYPE); + if (logger.isDebugEnabled()) { + logger.debug("previous [{}]", prevLicensesMetaData); + logger.debug("current [{}]", currentLicensesMetaData); + } + // notify all interested plugins + if (previousClusterState.blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK)) { + notifyAndSchedule(currentLicensesMetaData); + } else { + if (prevLicensesMetaData == null) { + if (currentLicensesMetaData != null) { + notifyAndSchedule(currentLicensesMetaData); + } + } else if (!prevLicensesMetaData.equals(currentLicensesMetaData)) { + notifyAndSchedule(currentLicensesMetaData); + } + } + // auto-generate license if no licenses ever existed + // this will trigger a subsequent cluster changed event + if (prevLicensesMetaData == null + && (currentLicensesMetaData == null || currentLicensesMetaData.getLicense() == null)) { + requestTrialLicense(currentClusterState); + } + } else if (logger.isDebugEnabled()) { + logger.debug("skipped license notifications reason: [{}]", GatewayService.STATE_NOT_RECOVERED_BLOCK); + } + } + + /** + * Notifies registered licensees of license state change and/or new active license + * based on the license in currentLicensesMetaData. + * Additionally schedules license expiry notifications and event callbacks + * relative to the current license's expiry + */ + private void notifyAndSchedule(final LicensesMetaData currentLicensesMetaData) { + final License license = getLicense(currentLicensesMetaData); + if (license != null) { + logger.debug("notifying [{}] listeners", registeredLicensees.size()); + long now = System.currentTimeMillis(); + if (license.issueDate() > now) { + logger.info("license [{}] - invalid", license.uid()); + return; + } + long expiryDuration = license.expiryDate() - now; + if (license.expiryDate() > now) { + for (InternalLicensee licensee : registeredLicensees) { + licensee.onChange(license, LicenseState.ENABLED); + } + logger.info("license [{}] - valid", license.uid()); + final TimeValue delay = TimeValue.timeValueMillis(expiryDuration); + // cancel any previous notifications + cancelNotifications(expiryNotifications); + try { + logger.debug("schedule grace notification after [{}] for license [{}]", delay.toString(), license.uid()); + expiryNotifications.add(threadPool.schedule(delay, executorName(), new LicensingClientNotificationJob())); + } catch (EsRejectedExecutionException ex) { + logger.debug("couldn't schedule grace notification", ex); + } + } else if ((license.expiryDate() + gracePeriodDuration.getMillis()) > now) { + for (InternalLicensee licensee : registeredLicensees) { + licensee.onChange(license, LicenseState.GRACE_PERIOD); + } + logger.info("license [{}] - grace", license.uid()); + final TimeValue delay = TimeValue.timeValueMillis(expiryDuration + gracePeriodDuration.getMillis()); + // cancel any previous notifications + cancelNotifications(expiryNotifications); + try { + logger.debug("schedule expiry notification after [{}] for license [{}]", delay.toString(), license.uid()); + expiryNotifications.add(threadPool.schedule(delay, executorName(), new LicensingClientNotificationJob())); + } catch (EsRejectedExecutionException ex) { + logger.debug("couldn't schedule expiry notification", ex); + } + } else { + for (InternalLicensee licensee : registeredLicensees) { + licensee.onChange(license, LicenseState.DISABLED); + } + logger.info("license [{}] - expired", license.uid()); + } + if (!license.equals(currentLicense.get())) { + currentLicense.set(license); + // cancel all scheduled event notifications + cancelNotifications(eventNotifications); + // schedule expiry callbacks + for (ExpirationCallback expirationCallback : this.expirationCallbacks) { + final TimeValue delay; + if (expirationCallback.matches(license.expiryDate(), now)) { + expirationCallback.on(license); + TimeValue frequency = expirationCallback.frequency(); + delay = frequency != null ? frequency : expirationCallback.delay(expiryDuration); + } else { + delay = expirationCallback.delay(expiryDuration); + } + if (delay != null) { + eventNotifications.add(threadPool.schedule(delay, executorName(), new EventNotificationJob(expirationCallback))); + } + if (logger.isDebugEnabled()) { + logger.debug("schedule [{}] after [{}]", expirationCallback, delay); + } + } + logger.debug("scheduled expiry callbacks for [{}] expiring after [{}]", license.uid(), TimeValue.timeValueMillis(expiryDuration)); + } + } + } + + private class LicensingClientNotificationJob implements Runnable { + @Override + public void run() { + logger.debug("running expiry notification"); + final ClusterState currentClusterState = clusterService.state(); + if (!currentClusterState.blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK)) { + final LicensesMetaData currentLicensesMetaData = currentClusterState.metaData().custom(LicensesMetaData.TYPE); + notifyAndSchedule(currentLicensesMetaData); + } else if (logger.isDebugEnabled()) { + // next clusterChanged event will deal with the missed notifications + logger.debug("skip expiry notification [{}]", GatewayService.STATE_NOT_RECOVERED_BLOCK); + } + } + } + + private class EventNotificationJob implements Runnable { + private final ExpirationCallback expirationCallback; + + EventNotificationJob(ExpirationCallback expirationCallback) { + this.expirationCallback = expirationCallback; + } + + @Override + public void run() { + logger.debug("running event notification for [{}]", expirationCallback); + LicensesMetaData currentLicensesMetaData = clusterService.state().metaData().custom(LicensesMetaData.TYPE); + License license = getLicense(currentLicensesMetaData); + if (license != null) { + long now = System.currentTimeMillis(); + if (expirationCallback.matches(license.expiryDate(), now)) { + expirationCallback.on(license); + if (expirationCallback.frequency() != null) { + // schedule next event + eventNotifications.add(threadPool.schedule(expirationCallback.frequency(), executorName(), this)); + } + } else if (logger.isDebugEnabled()) { + logger.debug("skip scheduling notification for [{}] with license expiring after [{}]", expirationCallback, + TimeValue.timeValueMillis(license.expiryDate() - now)); + } + } + // clear out any finished event notifications + while (!eventNotifications.isEmpty()) { + ScheduledFuture notification = eventNotifications.peek(); + if (notification != null && notification.isDone()) { + // remove the notifications that are done + eventNotifications.poll(); + } else { + // stop emptying out the queue as soon as the first undone future hits + break; + } + } + } + } + + public static abstract class ExpirationCallback { + + public enum Orientation { PRE, POST } + + public static abstract class Pre extends ExpirationCallback { + + /** + * Callback schedule prior to license expiry + * + * @param min latest relative time to execute before license expiry + * @param max earliest relative time to execute before license expiry + * @param frequency interval between execution + */ + public Pre(TimeValue min, TimeValue max, TimeValue frequency) { + super(Orientation.PRE, min, max, frequency); + } + + @Override + public boolean matches(long expirationDate, long now) { + long expiryDuration = expirationDate - now; + if (expiryDuration > 0l) { + if (expiryDuration <= max.getMillis()) { + return expiryDuration >= min.getMillis(); + } + } + return false; + } + + @Override + public TimeValue delay(long expiryDuration) { + return TimeValue.timeValueMillis(expiryDuration - max.getMillis()); + } + } + + public static abstract class Post extends ExpirationCallback { + + /** + * Callback schedule after license expiry + * + * @param min earliest relative time to execute after license expiry + * @param max latest relative time to execute after license expiry + * @param frequency interval between execution + */ + public Post(TimeValue min, TimeValue max, TimeValue frequency) { + super(Orientation.POST, min, max, frequency); + } + + @Override + public boolean matches(long expirationDate, long now) { + long postExpiryDuration = now - expirationDate; + if (postExpiryDuration > 0l) { + if (postExpiryDuration <= max.getMillis()) { + return postExpiryDuration >= min.getMillis(); + } + } + return false; + } + + @Override + public TimeValue delay(long expiryDuration) { + final long delay; + if (expiryDuration >= 0l) { + delay = expiryDuration + min.getMillis(); + } else { + delay = (-1l * expiryDuration) - min.getMillis(); + } + if (delay > 0l) { + return TimeValue.timeValueMillis(delay); + } else { + return null; + } + } + } + + protected final Orientation orientation; + protected final TimeValue min; + protected final TimeValue max; + private final TimeValue frequency; + + private ExpirationCallback(Orientation orientation, TimeValue min, TimeValue max, TimeValue frequency) { + this.orientation = orientation; + this.min = (min == null) ? TimeValue.timeValueMillis(0) : min; + this.max = (max == null) ? TimeValue.timeValueMillis(Long.MAX_VALUE) : max; + this.frequency = frequency; + } + + public TimeValue frequency() { + return frequency; + } + + public abstract TimeValue delay(long expiryDuration); + + public abstract boolean matches(long expirationDate, long now); + + public abstract void on(License license); + + @Override + public String toString() { + return LoggerMessageFormat.format(null, "ExpirationCallback:(orientation [{}], min [{}], max [{}], freq [{}])", orientation.name(), min, max, frequency); + } + } + + @Override + public void register(Licensee licensee) { + for (final InternalLicensee existingLicensee : registeredLicensees) { + if (existingLicensee.id().equals(licensee.id())) { + throw new IllegalStateException("listener: [" + licensee.id() + "] has been already registered"); + } + } + logger.debug("registering licensee [{}]", licensee.id()); + registeredLicensees.add(new InternalLicensee(licensee)); + final ClusterState clusterState = clusterService.state(); + if (clusterService.lifecycleState() == Lifecycle.State.STARTED + && clusterState.blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK) == false + && clusterState.nodes().masterNode() != null) { + final LicensesMetaData currentMetaData = clusterState.metaData().custom(LicensesMetaData.TYPE); + if (currentMetaData == null || currentMetaData.getLicense() == null) { + // triggers a cluster changed event + // eventually notifying the current licensee + requestTrialLicense(clusterState); + } else { + notifyAndSchedule(currentMetaData); + } + } + } + + private void requestTrialLicense(final ClusterState currentState) { + DiscoveryNode masterNode = currentState.nodes().masterNode(); + if (masterNode == null) { + throw new IllegalStateException("master not available when registering auto-generated license"); + } + transportService.sendRequest(masterNode, + REGISTER_TRIAL_LICENSE_ACTION_NAME, TransportRequest.Empty.INSTANCE, EmptyTransportResponseHandler.INSTANCE_SAME); + } + + public License getLicense(final LicensesMetaData metaData) { + if (metaData != null) { + License license = metaData.getLicense(); + if (license != LicensesMetaData.LICENSE_TOMBSTONE) { + boolean autoGeneratedLicense = License.isAutoGeneratedLicense(license.signature()); + if ((autoGeneratedLicense && TrialLicense.verify(license)) + || (!autoGeneratedLicense && verifyLicense(license))) { + return license; + } + } + } + return null; + } + + /** + * Cancels out all notification futures + */ + private static void cancelNotifications(Queue scheduledNotifications) { + // clear out notification queue + while (!scheduledNotifications.isEmpty()) { + ScheduledFuture notification = scheduledNotifications.peek(); + if (notification != null) { + // cancel + FutureUtils.cancel(notification); + scheduledNotifications.poll(); + } + } + } + + private String executorName() { + return ThreadPool.Names.GENERIC; + } + + /** + * Stores acknowledgement, expiration and license notification callbacks + * for a registered listener + */ + private class InternalLicensee { + volatile License currentLicense = null; + volatile LicenseState currentLicenseState = LicenseState.DISABLED; + private final Licensee licensee; + + private InternalLicensee(Licensee licensee) { + this.licensee = licensee; + } + + @Override + public String toString() { + return "(listener: " + licensee.id() + ", state: " + currentLicenseState.name() + ")"; + } + + public String id() { + return licensee.id(); + } + + public String[] expirationMessages() { + return licensee.expirationMessages(); + } + + public String[] acknowledgmentMessages(License currentLicense, License newLicense) { + return licensee.acknowledgmentMessages(currentLicense, newLicense); + } + + public void onChange(License license, LicenseState state) { + synchronized (this) { + if (currentLicense == null // not yet initialized + || !currentLicense.equals(license) // current license has changed + || currentLicenseState != state) { // same license but state has changed + logger.debug("licensee [{}] notified", licensee.id()); + licensee.onChange(new Licensee.Status(license.operationMode(), state)); + currentLicense = license; + currentLicenseState = state; + } + } + } + } + + /** + * Request handler for trial license generation to master + */ + private class RegisterTrialLicenseRequestHandler implements TransportRequestHandler { + + @Override + public void messageReceived(TransportRequest.Empty empty, TransportChannel channel) throws Exception { + registerTrialLicense(); + channel.sendResponse(TransportResponse.Empty.INSTANCE); + } + } + + // TODO - temporary hack for tests, should be removed once we introduce `ClockMock` + public void setGracePeriodDuration(TimeValue gracePeriodDuration) { + this.gracePeriodDuration = gracePeriodDuration; + } + // only for adding expiration callbacks for tests + public void setExpirationCallbacks(List expirationCallbacks) { + this.expirationCallbacks = expirationCallbacks; + } + // TODO - temporary hack for tests, should be removed once we introduce `ClockMock` + public void setTrialLicenseDuration(TimeValue trialLicenseDuration) { + this.trialLicenseDuration = trialLicenseDuration; + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesStatus.java b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesStatus.java new file mode 100644 index 00000000000..3bd18d58770 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesStatus.java @@ -0,0 +1,34 @@ +/* + * 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.license.plugin.core; + +public enum LicensesStatus { + VALID((byte) 0), + INVALID((byte) 1), + EXPIRED((byte) 2); + + private final byte id; + + LicensesStatus(byte id) { + this.id = id; + } + + public int id() { + return id; + } + + public static LicensesStatus fromId(int id) { + if (id == 0) { + return VALID; + } else if (id == 1) { + return INVALID; + } else if (id == 2) { + return EXPIRED; + } else { + throw new IllegalStateException("no valid LicensesStatus for id=" + id); + } + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/core/TrialLicense.java b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/core/TrialLicense.java new file mode 100644 index 00000000000..c528c452a4e --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/core/TrialLicense.java @@ -0,0 +1,63 @@ +/* + * 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.license.plugin.core; + +import org.elasticsearch.common.Base64; +import org.elasticsearch.common.xcontent.*; +import org.elasticsearch.license.core.License; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.Collections; + +import static org.elasticsearch.license.core.CryptUtils.decrypt; +import static org.elasticsearch.license.core.CryptUtils.encrypt; + +public class TrialLicense { + + public static License create(License.Builder specBuilder) { + License spec = specBuilder + .type("trial") + .issuer("elasticsearch") + .version(License.VERSION_CURRENT) + .build(); + final String signature; + try { + XContentBuilder contentBuilder = XContentFactory.contentBuilder(XContentType.JSON); + spec.toXContent(contentBuilder, new ToXContent.MapParams(Collections.singletonMap(License.LICENSE_SPEC_VIEW_MODE, "true"))); + byte[] encrypt = encrypt(contentBuilder.bytes().toBytes()); + byte[] bytes = new byte[4 + 4 + encrypt.length]; + ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); + // always generate license version -VERSION_CURRENT + byteBuffer.putInt(-License.VERSION_CURRENT) + .putInt(encrypt.length) + .put(encrypt); + signature = Base64.encodeBytes(bytes); + } catch (IOException e) { + throw new IllegalStateException(e); + } + return License.builder().fromLicenseSpec(spec, signature).build(); + } + + public static boolean verify(final License license) { + try { + byte[] signatureBytes = Base64.decode(license.signature()); + ByteBuffer byteBuffer = ByteBuffer.wrap(signatureBytes); + int version = byteBuffer.getInt(); + int contentLen = byteBuffer.getInt(); + byte[] content = new byte[contentLen]; + byteBuffer.get(content); + final License expectedLicense; + try (XContentParser parser = XContentFactory.xContent(XContentType.JSON).createParser(decrypt(content))) { + parser.nextToken(); + expectedLicense = License.builder().fromLicenseSpec(License.fromXContent(parser), license.signature()).version(-version).build(); + } + return license.equals(expectedLicense); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/rest/RestDeleteLicenseAction.java b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/rest/RestDeleteLicenseAction.java new file mode 100644 index 00000000000..7919ba8c121 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/rest/RestDeleteLicenseAction.java @@ -0,0 +1,35 @@ +/* + * 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.license.plugin.rest; + +import org.elasticsearch.client.Client; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.license.plugin.action.delete.DeleteLicenseAction; +import org.elasticsearch.license.plugin.action.delete.DeleteLicenseRequest; +import org.elasticsearch.license.plugin.action.delete.DeleteLicenseResponse; +import org.elasticsearch.rest.BaseRestHandler; +import org.elasticsearch.rest.RestChannel; +import org.elasticsearch.rest.RestController; +import org.elasticsearch.rest.RestRequest; +import org.elasticsearch.rest.action.support.AcknowledgedRestListener; + +import static org.elasticsearch.rest.RestRequest.Method.DELETE; + +public class RestDeleteLicenseAction extends BaseRestHandler { + + @Inject + public RestDeleteLicenseAction(Settings settings, RestController controller, Client client) { + super(settings, controller, client); + controller.registerHandler(DELETE, "/_license", this); + } + + @Override + public void handleRequest(final RestRequest request, final RestChannel channel, final Client client) { + client.admin().cluster().execute(DeleteLicenseAction.INSTANCE, new DeleteLicenseRequest(), new AcknowledgedRestListener(channel)); + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/rest/RestGetLicenseAction.java b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/rest/RestGetLicenseAction.java new file mode 100644 index 00000000000..6d9a31b56f1 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/rest/RestGetLicenseAction.java @@ -0,0 +1,68 @@ +/* + * 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.license.plugin.rest; + +import org.elasticsearch.client.Client; +import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.license.core.License; +import org.elasticsearch.license.plugin.action.get.GetLicenseAction; +import org.elasticsearch.license.plugin.action.get.GetLicenseRequest; +import org.elasticsearch.license.plugin.action.get.GetLicenseResponse; +import org.elasticsearch.rest.*; +import org.elasticsearch.rest.action.support.RestBuilderListener; + +import java.util.HashMap; +import java.util.Map; + +import static org.elasticsearch.rest.RestRequest.Method.GET; +import static org.elasticsearch.rest.RestStatus.NOT_FOUND; +import static org.elasticsearch.rest.RestStatus.OK; + +public class RestGetLicenseAction extends BaseRestHandler { + + @Inject + public RestGetLicenseAction(Settings settings, RestController controller, Client client) { + super(settings, controller, client); + controller.registerHandler(GET, "/_license", this); + } + + /** + * There will be only one license displayed per feature, the selected license will have the latest expiry_date + * out of all other licenses for the feature. + *

+ * The licenses are sorted by latest issue_date + */ + @Override + public void handleRequest(final RestRequest request, final RestChannel channel, final Client client) { + final Map overrideParams = new HashMap<>(2); + overrideParams.put(License.REST_VIEW_MODE, "true"); + overrideParams.put(License.LICENSE_VERSION_MODE, String.valueOf(License.VERSION_CURRENT)); + final ToXContent.Params params = new ToXContent.DelegatingMapParams(overrideParams, request); + GetLicenseRequest getLicenseRequest = new GetLicenseRequest(); + getLicenseRequest.local(request.paramAsBoolean("local", getLicenseRequest.local())); + client.admin().cluster().execute(GetLicenseAction.INSTANCE, getLicenseRequest, new RestBuilderListener(channel) { + @Override + public RestResponse buildResponse(GetLicenseResponse response, XContentBuilder builder) throws Exception { + // Default to pretty printing, but allow ?pretty=false to disable + if (!request.hasParam("pretty")) { + builder.prettyPrint().lfAtEnd(); + } + builder.startObject(); + if (response.license() != null) { + builder.startObject("license"); + response.license().toInnerXContent(builder, params); + builder.endObject(); + } + builder.endObject(); + return new BytesRestResponse(OK, builder); + } + }); + } + +} diff --git a/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/rest/RestPutLicenseAction.java b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/rest/RestPutLicenseAction.java new file mode 100644 index 00000000000..f355a610791 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/main/java/org/elasticsearch/license/plugin/rest/RestPutLicenseAction.java @@ -0,0 +1,46 @@ +/* + * 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.license.plugin.rest; + +import org.elasticsearch.client.Client; +import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.license.plugin.action.put.PutLicenseAction; +import org.elasticsearch.license.plugin.action.put.PutLicenseRequest; +import org.elasticsearch.license.plugin.action.put.PutLicenseResponse; +import org.elasticsearch.rest.*; +import org.elasticsearch.rest.action.support.RestBuilderListener; + +import static org.elasticsearch.rest.RestRequest.Method.POST; +import static org.elasticsearch.rest.RestRequest.Method.PUT; + +public class RestPutLicenseAction extends BaseRestHandler { + + @Inject + public RestPutLicenseAction(Settings settings, RestController controller, Client client) { + super(settings, controller, client); + controller.registerHandler(PUT, "/_license", this); + controller.registerHandler(POST, "/_license", this); + } + + @Override + public void handleRequest(final RestRequest request, final RestChannel channel, final Client client) { + PutLicenseRequest putLicenseRequest = new PutLicenseRequest(); + putLicenseRequest.license(request.content().toUtf8()); + putLicenseRequest.acknowledge(request.paramAsBoolean("acknowledge", false)); + client.admin().cluster().execute(PutLicenseAction.INSTANCE, putLicenseRequest, new RestBuilderListener(channel) { + @Override + public RestResponse buildResponse(PutLicenseResponse response, XContentBuilder builder) throws Exception { + builder.startObject(); + response.toXContent(builder, ToXContent.EMPTY_PARAMS); + builder.endObject(); + return new BytesRestResponse(RestStatus.OK, builder); + } + }); + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesConsumerPluginIntegrationTestCase.java b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesConsumerPluginIntegrationTestCase.java new file mode 100644 index 00000000000..3484a9c41a8 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesConsumerPluginIntegrationTestCase.java @@ -0,0 +1,152 @@ +/* + * 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.license.plugin; + +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.gateway.GatewayService; +import org.elasticsearch.license.plugin.consumer.TestConsumerPluginBase; +import org.elasticsearch.license.plugin.consumer.TestPluginServiceBase; +import org.elasticsearch.license.plugin.core.LicenseState; +import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.test.ESIntegTestCase.ClusterScope; +import org.elasticsearch.test.InternalTestCluster; +import org.elasticsearch.xpack.XPackPlugin; +import org.junit.After; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import static org.elasticsearch.test.ESIntegTestCase.Scope.TEST; + +/** + * Framework to test licensing plugin integration for existing/new consumer plugins + * see {@link org.elasticsearch.license.plugin.LicensesEagerConsumerPluginIntegrationTests} and {@link org.elasticsearch.license.plugin.LicensesLazyConsumerPluginIntegrationTests} + * for example usage + */ +@ClusterScope(scope = TEST, numDataNodes = 2, numClientNodes = 0, transportClientRatio = 0.0) +public abstract class AbstractLicensesConsumerPluginIntegrationTestCase extends AbstractLicensesIntegrationTestCase { + protected final TestConsumerPluginBase consumerPlugin; + + public AbstractLicensesConsumerPluginIntegrationTestCase(TestConsumerPluginBase consumerPlugin) { + this.consumerPlugin = consumerPlugin; + } + + private final int trialLicenseDurationInSeconds = 20; + + @Override + protected Settings nodeSettings(int nodeOrdinal) { + return Settings.settingsBuilder() + .put(super.nodeSettings(nodeOrdinal)) + // this setting is only used in tests + .put(".trial_license_duration_in_seconds", trialLicenseDurationInSeconds) + .build(); + } + + @Override + protected Collection> nodePlugins() { + return Arrays.asList(XPackPlugin.class, consumerPlugin.getClass()); + } + + @Override + protected Collection> transportClientPlugins() { + return nodePlugins(); + } + + @After + public void afterTest() throws Exception { + wipeAllLicenses(); + assertTrue(awaitBusy(() -> !clusterService().state().blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK))); + } + + public void testTrialLicenseAndSignedLicenseNotification() throws Exception { + logger.info("using " + consumerPlugin.getClass().getName() + " consumer plugin"); + logger.info(" --> trial license generated"); + // managerService should report feature to be enabled on all data nodes + assertLicenseeState(consumerPlugin.id(), LicenseState.ENABLED); + // consumer plugin service should return enabled on all data nodes + assertConsumerPluginNotification(consumerPluginServices(), LicenseState.ENABLED, 2); + + logger.info(" --> check trial license expiry notification"); + // consumer plugin should notify onDisabled on all data nodes (expired trial license) + assertConsumerPluginNotification(consumerPluginServices(), LicenseState.GRACE_PERIOD, trialLicenseDurationInSeconds * 2); + assertLicenseeState(consumerPlugin.id(), LicenseState.GRACE_PERIOD); + assertConsumerPluginNotification(consumerPluginServices(), LicenseState.DISABLED, trialLicenseDurationInSeconds * 2); + assertLicenseeState(consumerPlugin.id(), LicenseState.DISABLED); + + logger.info(" --> put signed license"); + putLicense(TimeValue.timeValueSeconds(trialLicenseDurationInSeconds)); + + logger.info(" --> check signed license enabled notification"); + // consumer plugin should notify onEnabled on all data nodes (signed license) + assertConsumerPluginNotification(consumerPluginServices(), LicenseState.ENABLED, 1); + assertLicenseeState(consumerPlugin.id(), LicenseState.ENABLED); + + logger.info(" --> check signed license expiry notification"); + // consumer plugin should notify onDisabled on all data nodes (expired signed license) + assertConsumerPluginNotification(consumerPluginServices(), LicenseState.GRACE_PERIOD, trialLicenseDurationInSeconds * 2); + assertLicenseeState(consumerPlugin.id(), LicenseState.GRACE_PERIOD); + assertConsumerPluginNotification(consumerPluginServices(), LicenseState.DISABLED, trialLicenseDurationInSeconds * 2); + assertLicenseeState(consumerPlugin.id(), LicenseState.DISABLED); + } + + public void testTrialLicenseNotification() throws Exception { + logger.info(" --> check onEnabled for trial license"); + // managerService should report feature to be enabled on all data nodes + assertLicenseeState(consumerPlugin.id(), LicenseState.ENABLED); + // consumer plugin service should return enabled on all data nodes + assertConsumerPluginNotification(consumerPluginServices(), LicenseState.ENABLED, 1); + + logger.info(" --> check trial license expiry notification"); + // consumer plugin should notify onDisabled on all data nodes (expired signed license) + assertConsumerPluginNotification(consumerPluginServices(), LicenseState.GRACE_PERIOD, trialLicenseDurationInSeconds); + assertLicenseeState(consumerPlugin.id(), LicenseState.GRACE_PERIOD); + assertConsumerPluginNotification(consumerPluginServices(), LicenseState.DISABLED, trialLicenseDurationInSeconds); + assertLicenseeState(consumerPlugin.id(), LicenseState.DISABLED); + } + + public void testOverlappingTrialAndSignedLicenseNotification() throws Exception { + logger.info(" --> check onEnabled for trial license"); + // managerService should report feature to be enabled on all data nodes + assertLicenseeState(consumerPlugin.id(), LicenseState.ENABLED); + // consumer plugin service should return enabled on all data nodes + assertConsumerPluginNotification(consumerPluginServices(), LicenseState.ENABLED, 1); + + logger.info(" --> put signed license while trial license is in effect"); + putLicense(TimeValue.timeValueSeconds(trialLicenseDurationInSeconds * 2)); + + logger.info(" --> check signed license enabled notification"); + // consumer plugin should notify onEnabled on all data nodes (signed license) + assertConsumerPluginNotification(consumerPluginServices(), LicenseState.ENABLED, 1); + assertLicenseeState(consumerPlugin.id(), LicenseState.ENABLED); + + logger.info(" --> sleep for rest of trailLicense duration"); + Thread.sleep(trialLicenseDurationInSeconds * 1000l); + + logger.info(" --> check consumer is still enabled [signed license]"); + // consumer plugin should notify onEnabled on all data nodes (signed license) + assertConsumerPluginNotification(consumerPluginServices(), LicenseState.ENABLED, 1); + assertLicenseeState(consumerPlugin.id(), LicenseState.ENABLED); + + logger.info(" --> check signed license expiry notification"); + // consumer plugin should notify onDisabled on all data nodes (expired signed license) + assertConsumerPluginNotification(consumerPluginServices(), LicenseState.GRACE_PERIOD, trialLicenseDurationInSeconds * 2 * 2); + assertLicenseeState(consumerPlugin.id(), LicenseState.GRACE_PERIOD); + assertConsumerPluginNotification(consumerPluginServices(), LicenseState.DISABLED, trialLicenseDurationInSeconds * 2 * 2); + assertLicenseeState(consumerPlugin.id(), LicenseState.DISABLED); + } + + private List consumerPluginServices() { + final InternalTestCluster clients = internalCluster(); + List consumerPluginServices = new ArrayList<>(); + for (TestPluginServiceBase service : clients.getDataNodeInstances(consumerPlugin.service())) { + consumerPluginServices.add(service); + } + return consumerPluginServices; + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesIntegrationTestCase.java b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesIntegrationTestCase.java new file mode 100644 index 00000000000..fd96745b9c4 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesIntegrationTestCase.java @@ -0,0 +1,150 @@ +/* + * 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.license.plugin; + +import org.elasticsearch.cluster.ClusterService; +import org.elasticsearch.cluster.ClusterState; +import org.elasticsearch.cluster.ClusterStateUpdateTask; +import org.elasticsearch.cluster.metadata.MetaData; +import org.elasticsearch.common.Nullable; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.license.core.License; +import org.elasticsearch.license.plugin.action.put.PutLicenseAction; +import org.elasticsearch.license.plugin.action.put.PutLicenseRequestBuilder; +import org.elasticsearch.license.plugin.action.put.PutLicenseResponse; +import org.elasticsearch.license.plugin.consumer.EagerLicenseRegistrationPluginService; +import org.elasticsearch.license.plugin.consumer.LazyLicenseRegistrationPluginService; +import org.elasticsearch.license.plugin.consumer.TestPluginServiceBase; +import org.elasticsearch.license.plugin.core.*; +import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.test.ESIntegTestCase; +import org.elasticsearch.test.InternalTestCluster; +import org.elasticsearch.xpack.XPackPlugin; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import static org.elasticsearch.license.plugin.TestUtils.generateSignedLicense; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.Matchers.greaterThan; + +public abstract class AbstractLicensesIntegrationTestCase extends ESIntegTestCase { + + @Override + protected Settings nodeSettings(int nodeOrdinal) { + return Settings.builder() + .put("shield.enabled", false) + .put("marvel.enabled", false) + .put("watcher.enabled", false) + .build(); + } + + @Override + protected Collection> nodePlugins() { + return Collections.>singletonList(XPackPlugin.class); + } + + @Override + protected Collection> transportClientPlugins() { + return nodePlugins(); + } + + @Override + protected Settings transportClientSettings() { + // Plugin should be loaded on the transport client as well + return nodeSettings(0); + } + + protected void wipeAllLicenses() throws InterruptedException { + final CountDownLatch latch = new CountDownLatch(1); + ClusterService clusterService = internalCluster().getInstance(ClusterService.class, internalCluster().getMasterName()); + clusterService.submitStateUpdateTask("delete licensing metadata", new ClusterStateUpdateTask() { + @Override + public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) { + latch.countDown(); + } + + @Override + public ClusterState execute(ClusterState currentState) throws Exception { + MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData()); + mdBuilder.removeCustom(LicensesMetaData.TYPE); + return ClusterState.builder(currentState).metaData(mdBuilder).build(); + } + + @Override + public void onFailure(String source, @Nullable Throwable t) { + logger.error("error on metaData cleanup after test", t); + } + }); + latch.await(); + } + + protected void putLicense(TimeValue expiryDuration) throws Exception { + License license1 = generateSignedLicense(expiryDuration); + final PutLicenseResponse putLicenseResponse = new PutLicenseRequestBuilder(client().admin().cluster(), PutLicenseAction.INSTANCE).setLicense(license1).get(); + assertThat(putLicenseResponse.isAcknowledged(), equalTo(true)); + assertThat(putLicenseResponse.status(), equalTo(LicensesStatus.VALID)); + } + + protected void assertLicenseeState(final String id, final LicenseState state) throws InterruptedException { + assertTrue("LicensesManagerService for licensee " + id + " should have status " + state.name(), awaitBusy(() -> { + final InternalTestCluster clients = internalCluster(); + for (LicensesManagerService managerService : clients.getDataNodeInstances(LicensesManagerService.class)) { + if (!managerService.licenseesWithState(state).contains(id)) { + return false; + } + } + return true; + })); + } + + protected void assertLazyConsumerPluginNotification(final LicenseState state, int timeoutInSec) throws InterruptedException { + final List consumerPluginServices = consumerLazyPluginServices(); + assertConsumerPluginNotification(consumerPluginServices, state, timeoutInSec); + } + + protected void assertEagerConsumerPluginNotification(final LicenseState state, int timeoutInSec) throws InterruptedException { + final List consumerPluginServices = consumerEagerPluginServices(); + assertConsumerPluginNotification(consumerPluginServices, state, timeoutInSec); + } + + protected void assertConsumerPluginNotification(final List consumerPluginServices, final LicenseState state, int timeoutInSec) throws InterruptedException { + assertThat("At least one instance has to be present", consumerPluginServices.size(), greaterThan(0)); + boolean success = awaitBusy(() -> { + for (TestPluginServiceBase pluginService : consumerPluginServices) { + if (state != pluginService.state()) { + return false; + } + } + return true; + }, timeoutInSec + 1, TimeUnit.SECONDS); + logger.debug("Notification assertion complete"); + assertThat(consumerPluginServices.get(0).getClass().getName() + " should have status " + state.name(), success, equalTo(true)); + } + + private List consumerLazyPluginServices() { + final InternalTestCluster clients = internalCluster(); + List consumerPluginServices = new ArrayList<>(); + for (TestPluginServiceBase service : clients.getDataNodeInstances(LazyLicenseRegistrationPluginService.class)) { + consumerPluginServices.add(service); + } + return consumerPluginServices; + } + + private List consumerEagerPluginServices() { + final InternalTestCluster clients = internalCluster(); + List consumerPluginServices = new ArrayList<>(); + for (TestPluginServiceBase service : clients.getDataNodeInstances(EagerLicenseRegistrationPluginService.class)) { + consumerPluginServices.add(service); + } + return consumerPluginServices; + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/LicensesEagerConsumerPluginIntegrationTests.java b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/LicensesEagerConsumerPluginIntegrationTests.java new file mode 100644 index 00000000000..fc87ca63184 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/LicensesEagerConsumerPluginIntegrationTests.java @@ -0,0 +1,19 @@ +/* + * 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.license.plugin; + +import org.apache.lucene.util.LuceneTestCase.BadApple; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.license.plugin.consumer.EagerLicenseRegistrationConsumerPlugin; + +// test is just too slow, please fix it to not be sleep-based +@BadApple(bugUrl = "https://github.com/elastic/x-plugins/issues/1007") +public class LicensesEagerConsumerPluginIntegrationTests extends AbstractLicensesConsumerPluginIntegrationTestCase { + + public LicensesEagerConsumerPluginIntegrationTests() { + super(new EagerLicenseRegistrationConsumerPlugin(Settings.EMPTY)); + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/LicensesLazyConsumerPluginIntegrationTests.java b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/LicensesLazyConsumerPluginIntegrationTests.java new file mode 100644 index 00000000000..6204bbf9cae --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/LicensesLazyConsumerPluginIntegrationTests.java @@ -0,0 +1,19 @@ +/* + * 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.license.plugin; + +import org.apache.lucene.util.LuceneTestCase.BadApple; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.license.plugin.consumer.LazyLicenseRegistrationConsumerPlugin; + +//test is just too slow, please fix it to not be sleep-based +@BadApple(bugUrl = "https://github.com/elastic/x-plugins/issues/1007") +public class LicensesLazyConsumerPluginIntegrationTests extends AbstractLicensesConsumerPluginIntegrationTestCase { + + public LicensesLazyConsumerPluginIntegrationTests() { + super(new LazyLicenseRegistrationConsumerPlugin(Settings.EMPTY)); + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/LicensesPluginIntegrationTests.java b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/LicensesPluginIntegrationTests.java new file mode 100644 index 00000000000..e8275719ae5 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/LicensesPluginIntegrationTests.java @@ -0,0 +1,162 @@ +/* + * 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.license.plugin; + +import org.apache.lucene.util.LuceneTestCase.BadApple; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.gateway.GatewayService; +import org.elasticsearch.license.plugin.consumer.EagerLicenseRegistrationConsumerPlugin; +import org.elasticsearch.license.plugin.consumer.EagerLicenseRegistrationPluginService; +import org.elasticsearch.license.plugin.consumer.LazyLicenseRegistrationConsumerPlugin; +import org.elasticsearch.license.plugin.consumer.LazyLicenseRegistrationPluginService; +import org.elasticsearch.license.plugin.core.LicenseState; +import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.test.ESIntegTestCase.ClusterScope; +import org.elasticsearch.xpack.XPackPlugin; +import org.junit.After; + +import java.util.Arrays; +import java.util.Collection; + +import static org.elasticsearch.test.ESIntegTestCase.Scope.TEST; + +//test is just too slow, please fix it to not be sleep-based +@BadApple(bugUrl = "https://github.com/elastic/x-plugins/issues/1007") +@ClusterScope(scope = TEST, numDataNodes = 2, numClientNodes = 0) +public class LicensesPluginIntegrationTests extends AbstractLicensesIntegrationTestCase { + private final boolean useEagerLicenseRegistrationPlugin = randomBoolean(); + + private final int trialLicenseDurationInSeconds = 10; + + @Override + protected Settings nodeSettings(int nodeOrdinal) { + return Settings.settingsBuilder() + .put(super.nodeSettings(nodeOrdinal)) + // this setting is only used in tests + .put(".trial_license_duration_in_seconds", trialLicenseDurationInSeconds) + .build(); + } + + @Override + protected Collection> nodePlugins() { + if (useEagerLicenseRegistrationPlugin) { + return Arrays.asList(XPackPlugin.class, EagerLicenseRegistrationConsumerPlugin.class); + } else { + return Arrays.asList(XPackPlugin.class, LazyLicenseRegistrationConsumerPlugin.class); + } + } + + @Override + protected Collection> transportClientPlugins() { + return nodePlugins(); + } + + @After + public void afterTest() throws Exception { + wipeAllLicenses(); + assertTrue(awaitBusy(() -> !clusterService().state().blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK))); + } + + public void testTrialLicenseAndSignedLicenseNotification() throws Exception { + logger.info("using " + ((useEagerLicenseRegistrationPlugin) ? "eager" : "lazy") + " consumer plugin"); + logger.info(" --> trial license generated"); + // managerService should report feature to be enabled on all data nodes + assertLicenseeState(getCurrentFeatureName(), LicenseState.ENABLED); + // consumer plugin service should return enabled on all data nodes + assertConsumerPluginEnabledNotification(2); + + logger.info(" --> check trial license expiry notification"); + // consumer plugin should notify onDisabled on all data nodes (expired trial license) + assertConsumerPluginDisabledNotification(trialLicenseDurationInSeconds * 2); + assertLicenseeState(getCurrentFeatureName(), LicenseState.GRACE_PERIOD); + + assertLicenseeState(getCurrentFeatureName(), LicenseState.DISABLED); + + logger.info(" --> put signed license"); + putLicense(TimeValue.timeValueSeconds(trialLicenseDurationInSeconds)); + + logger.info(" --> check signed license enabled notification"); + // consumer plugin should notify onEnabled on all data nodes (signed license) + assertConsumerPluginEnabledNotification(1); + assertLicenseeState(getCurrentFeatureName(), LicenseState.ENABLED); + + logger.info(" --> check signed license expiry notification"); + // consumer plugin should notify onDisabled on all data nodes (expired signed license) + assertConsumerPluginDisabledNotification(trialLicenseDurationInSeconds * 2); + assertLicenseeState(getCurrentFeatureName(), LicenseState.GRACE_PERIOD); + assertLicenseeState(getCurrentFeatureName(), LicenseState.DISABLED); + } + + public void testTrialLicenseNotification() throws Exception { + logger.info(" --> check onEnabled for trial license"); + // managerService should report feature to be enabled on all data nodes + assertLicenseeState(getCurrentFeatureName(), LicenseState.ENABLED); + // consumer plugin service should return enabled on all data nodes + assertConsumerPluginEnabledNotification(1); + + logger.info(" --> check trial license expiry notification"); + // consumer plugin should notify onDisabled on all data nodes (expired signed license) + assertConsumerPluginDisabledNotification(trialLicenseDurationInSeconds * 2); + assertLicenseeState(getCurrentFeatureName(), LicenseState.GRACE_PERIOD); + assertLicenseeState(getCurrentFeatureName(), LicenseState.DISABLED); + } + + public void testOverlappingTrialAndSignedLicenseNotification() throws Exception { + logger.info(" --> check onEnabled for trial license"); + // managerService should report feature to be enabled on all data nodes + assertLicenseeState(getCurrentFeatureName(), LicenseState.ENABLED); + // consumer plugin service should return enabled on all data nodes + assertConsumerPluginEnabledNotification(1); + + logger.info(" --> put signed license while trial license is in effect"); + putLicense(TimeValue.timeValueSeconds(trialLicenseDurationInSeconds * 2)); + + logger.info(" --> check signed license enabled notification"); + // consumer plugin should notify onEnabled on all data nodes (signed license) + assertConsumerPluginEnabledNotification(1); + assertLicenseeState(getCurrentFeatureName(), LicenseState.ENABLED); + + logger.info(" --> sleep for rest of trailLicense duration"); + Thread.sleep(trialLicenseDurationInSeconds * 1000l); + + logger.info(" --> check consumer is still enabled [signed license]"); + // consumer plugin should notify onEnabled on all data nodes (signed license) + assertConsumerPluginEnabledNotification(1); + assertLicenseeState(getCurrentFeatureName(), LicenseState.ENABLED); + + logger.info(" --> check signed license expiry notification"); + // consumer plugin should notify onDisabled on all data nodes (expired signed license) + assertConsumerPluginDisabledNotification(trialLicenseDurationInSeconds * 2 * 2); + assertLicenseeState(getCurrentFeatureName(), LicenseState.GRACE_PERIOD); + assertLicenseeState(getCurrentFeatureName(), LicenseState.DISABLED); + } + + private String getCurrentFeatureName() { + if (useEagerLicenseRegistrationPlugin) { + return EagerLicenseRegistrationPluginService.ID; + } else { + return LazyLicenseRegistrationPluginService.ID; + } + } + + private void assertConsumerPluginEnabledNotification(int timeoutInSec) throws InterruptedException { + if (useEagerLicenseRegistrationPlugin) { + assertEagerConsumerPluginNotification(LicenseState.ENABLED, timeoutInSec); + } else { + assertLazyConsumerPluginNotification(LicenseState.ENABLED, timeoutInSec); + } + } + + private void assertConsumerPluginDisabledNotification(int timeoutInSec) throws InterruptedException { + if (useEagerLicenseRegistrationPlugin) { + assertEagerConsumerPluginNotification(LicenseState.GRACE_PERIOD, timeoutInSec); + } else { + assertLazyConsumerPluginNotification(LicenseState.GRACE_PERIOD, timeoutInSec); + } + } + +} diff --git a/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/LicensesPluginsIntegrationTests.java b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/LicensesPluginsIntegrationTests.java new file mode 100644 index 00000000000..ec293da26d6 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/LicensesPluginsIntegrationTests.java @@ -0,0 +1,139 @@ +/* + * 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.license.plugin; + +import org.apache.lucene.util.LuceneTestCase.BadApple; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.license.plugin.consumer.EagerLicenseRegistrationConsumerPlugin; +import org.elasticsearch.license.plugin.consumer.EagerLicenseRegistrationPluginService; +import org.elasticsearch.license.plugin.consumer.LazyLicenseRegistrationConsumerPlugin; +import org.elasticsearch.license.plugin.consumer.LazyLicenseRegistrationPluginService; +import org.elasticsearch.license.plugin.core.LicenseState; +import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.test.ESIntegTestCase.ClusterScope; +import org.elasticsearch.xpack.XPackPlugin; +import org.junit.After; + +import java.util.Arrays; +import java.util.Collection; + +import static org.elasticsearch.test.ESIntegTestCase.Scope.TEST; + +//test is just too slow, please fix it to not be sleep-based +@BadApple(bugUrl = "https://github.com/elastic/x-plugins/issues/1007") +@ClusterScope(scope = TEST, numDataNodes = 0, numClientNodes = 0) +public class LicensesPluginsIntegrationTests extends AbstractLicensesIntegrationTestCase { + + private static final String ID_1 = EagerLicenseRegistrationPluginService.ID; + private static final String ID_2 = LazyLicenseRegistrationPluginService.ID; + + @Override + protected Settings nodeSettings(int nodeOrdinal) { + return Settings.settingsBuilder() + .put(super.nodeSettings(nodeOrdinal)) + .build(); + } + + private Settings nodeSettingsWithConsumerPlugin(int trialLicenseDuration) { + return Settings.settingsBuilder() + .put(super.nodeSettings(0)) + // this setting is only used in tests + .put(".trial_license_duration_in_seconds", trialLicenseDuration) + .build(); + + } + + @Override + protected Collection> nodePlugins() { + return Arrays.asList(XPackPlugin.class, EagerLicenseRegistrationConsumerPlugin.class, LazyLicenseRegistrationConsumerPlugin.class); + } + + @Override + protected Collection> transportClientPlugins() { + return nodePlugins(); + } + + @After + public void afterTest() throws Exception { + wipeAllLicenses(); + } + + public void testMultipleConsumerPlugins() throws Exception { + int nNodes = randomIntBetween(2, 3); + int trialLicenseDurationInSec = 20; + int signedLicenseDuration = 5; + startNodesWithConsumerPlugins(nNodes, trialLicenseDurationInSec); + + logger.info(" --> trial license generated"); + // managerService should report feature to be enabled on all data nodes + assertLicenseeState(ID_1, LicenseState.ENABLED); + assertLicenseeState(ID_2, LicenseState.ENABLED); + // consumer plugin service should return enabled on all data nodes + assertEagerConsumerPluginNotification(LicenseState.ENABLED, 1); + assertLazyConsumerPluginNotification(LicenseState.ENABLED, 1); + + logger.info(" --> check trial license expiry notification"); + // consumer plugin should notify onDisabled on all data nodes (expired trial license) + assertEagerConsumerPluginNotification(LicenseState.GRACE_PERIOD, trialLicenseDurationInSec * 2); + assertLazyConsumerPluginNotification(LicenseState.GRACE_PERIOD, trialLicenseDurationInSec * 2); + assertLicenseeState(ID_1, LicenseState.GRACE_PERIOD); + assertLicenseeState(ID_2, LicenseState.GRACE_PERIOD); + assertLicenseeState(ID_1, LicenseState.DISABLED); + assertLicenseeState(ID_2, LicenseState.DISABLED); + + logger.info(" --> put signed license"); + putLicense(TimeValue.timeValueSeconds(signedLicenseDuration)); + + logger.info(" --> check signed license enabled notification"); + // consumer plugin should notify onEnabled on all data nodes (signed license) + assertEagerConsumerPluginNotification(LicenseState.ENABLED, 1); + assertLazyConsumerPluginNotification(LicenseState.ENABLED, 1); + assertLicenseeState(ID_1, LicenseState.ENABLED); + assertLicenseeState(ID_2, LicenseState.ENABLED); + + logger.info(" --> check signed license expiry notification"); + // consumer plugin should notify onDisabled on all data nodes (expired signed license) + assertEagerConsumerPluginNotification(LicenseState.GRACE_PERIOD, signedLicenseDuration * 2); + assertLazyConsumerPluginNotification(LicenseState.GRACE_PERIOD, signedLicenseDuration * 2); + assertLicenseeState(ID_1, LicenseState.GRACE_PERIOD); + assertLicenseeState(ID_2, LicenseState.GRACE_PERIOD); + + assertEagerConsumerPluginNotification(LicenseState.DISABLED, 10 * 2); + assertLazyConsumerPluginNotification(LicenseState.DISABLED, 10 * 2); + assertLicenseeState(ID_1, LicenseState.DISABLED); + assertLicenseeState(ID_2, LicenseState.DISABLED); + } + + public void testRandomFeatureLicensesActions() throws Exception { + int nNodes = randomIntBetween(2, 3); + + startNodesWithConsumerPlugins(nNodes, 10); + + logger.info(" --> check license enabled notification"); + assertEagerConsumerPluginNotification(LicenseState.ENABLED, 1); + assertLazyConsumerPluginNotification(LicenseState.ENABLED, 1); + assertLicenseeState(ID_1, LicenseState.ENABLED); + assertLicenseeState(ID_2, LicenseState.ENABLED); + + logger.info(" --> check license expiry notification"); + // consumer plugin should notify onDisabled on all data nodes (expired signed license) + assertEagerConsumerPluginNotification(LicenseState.GRACE_PERIOD, 10 * 2); + assertLazyConsumerPluginNotification(LicenseState.GRACE_PERIOD, 10 * 2); + assertLicenseeState(ID_1, LicenseState.GRACE_PERIOD); + assertLicenseeState(ID_2, LicenseState.GRACE_PERIOD); + assertEagerConsumerPluginNotification(LicenseState.DISABLED, 10 * 2); + assertLazyConsumerPluginNotification(LicenseState.DISABLED, 10 * 2); + assertLicenseeState(ID_1, LicenseState.DISABLED); + assertLicenseeState(ID_2, LicenseState.DISABLED); + } + + private void startNodesWithConsumerPlugins(int nNodes, int trialLicenseDuration) { + for (int i = 0; i < nNodes; i++) { + internalCluster().startNode(nodeSettingsWithConsumerPlugin(trialLicenseDuration)); + } + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/LicensesServiceClusterTests.java b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/LicensesServiceClusterTests.java new file mode 100644 index 00000000000..756e96c3fde --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/LicensesServiceClusterTests.java @@ -0,0 +1,233 @@ +/* + * 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.license.plugin; + +import org.elasticsearch.client.ClusterAdminClient; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.license.core.License; +import org.elasticsearch.license.plugin.action.delete.DeleteLicenseAction; +import org.elasticsearch.license.plugin.action.delete.DeleteLicenseRequestBuilder; +import org.elasticsearch.license.plugin.action.delete.DeleteLicenseResponse; +import org.elasticsearch.license.plugin.action.get.GetLicenseAction; +import org.elasticsearch.license.plugin.action.get.GetLicenseRequestBuilder; +import org.elasticsearch.license.plugin.action.get.GetLicenseResponse; +import org.elasticsearch.license.plugin.action.put.PutLicenseAction; +import org.elasticsearch.license.plugin.action.put.PutLicenseRequestBuilder; +import org.elasticsearch.license.plugin.action.put.PutLicenseResponse; +import org.elasticsearch.license.plugin.consumer.EagerLicenseRegistrationConsumerPlugin; +import org.elasticsearch.license.plugin.consumer.EagerLicenseRegistrationPluginService; +import org.elasticsearch.license.plugin.consumer.LazyLicenseRegistrationConsumerPlugin; +import org.elasticsearch.license.plugin.consumer.LazyLicenseRegistrationPluginService; +import org.elasticsearch.license.plugin.core.LicenseState; +import org.elasticsearch.license.plugin.core.LicensesManagerService; +import org.elasticsearch.license.plugin.core.LicensesMetaData; +import org.elasticsearch.license.plugin.core.LicensesStatus; +import org.elasticsearch.node.Node; +import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.test.ESIntegTestCase.ClusterScope; +import org.elasticsearch.test.InternalTestCluster; +import org.elasticsearch.xpack.XPackPlugin; + +import java.util.Arrays; +import java.util.Collection; + +import static org.elasticsearch.license.plugin.TestUtils.generateSignedLicense; +import static org.elasticsearch.test.ESIntegTestCase.Scope.TEST; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.CoreMatchers.nullValue; + +@ClusterScope(scope = TEST, numDataNodes = 0, numClientNodes = 0, maxNumDataNodes = 0, transportClientRatio = 0) +public class LicensesServiceClusterTests extends AbstractLicensesIntegrationTestCase { + private final String[] PLUGINS = {EagerLicenseRegistrationPluginService.ID, LazyLicenseRegistrationPluginService.ID}; + + @Override + protected Settings transportClientSettings() { + return super.transportClientSettings(); + } + + @Override + protected Settings nodeSettings(int nodeOrdinal) { + return nodeSettingsBuilder(nodeOrdinal).build(); + } + + private Settings.Builder nodeSettingsBuilder(int nodeOrdinal) { + return Settings.builder() + .put(super.nodeSettings(nodeOrdinal)) + .put("plugins.load_classpath_plugins", false) + .put("node.data", true) + .put("format", "json") + // this setting is only used in tests + .put(".trial_license_duration_in_seconds", 9) + // this setting is only used in tests + .put(".grace_duration_in_seconds", 9) + .put(Node.HTTP_ENABLED, true); + } + + @Override + protected Collection> nodePlugins() { + return Arrays.asList(XPackPlugin.class, EagerLicenseRegistrationConsumerPlugin.class, LazyLicenseRegistrationConsumerPlugin.class); + } + + @Override + protected Collection> transportClientPlugins() { + return nodePlugins(); + } + + public void testClusterRestartWithLicense() throws Exception { + wipeAllLicenses(); + + int numNodes = randomIntBetween(1, 5); + logger.info("--> starting " + numNodes + " node(s)"); + for (int i = 0; i < numNodes; i++) { + internalCluster().startNode(); + } + ensureGreen(); + + logger.info("--> put signed license"); + License license = generateAndPutLicenses(); + getAndCheckLicense(license); + logger.info("--> restart all nodes"); + internalCluster().fullRestart(); + ensureYellow(); + + logger.info("--> get and check signed license"); + getAndCheckLicense(license); + + logger.info("--> remove licenses"); + removeLicense(); + assertNoLicense(); + logger.info("--> restart all nodes"); + internalCluster().fullRestart(); + ensureYellow(); + assertNoLicense(); + + wipeAllLicenses(); + } + + public void testClusterRestartWhileEnabled() throws Exception { + wipeAllLicenses(); + internalCluster().startNode(); + ensureGreen(); + assertEagerConsumerPluginNotification(LicenseState.ENABLED, 5); + assertLazyConsumerPluginNotification(LicenseState.ENABLED, 5); + logger.info("--> restart node"); + internalCluster().fullRestart(); + ensureYellow(); + logger.info("--> await node for enabled"); + assertEagerConsumerPluginNotification(LicenseState.ENABLED, 5); + assertLazyConsumerPluginNotification(LicenseState.ENABLED, 5); + } + + public void testClusterRestartWhileGrace() throws Exception { + wipeAllLicenses(); + internalCluster().startNode(); + ensureGreen(); + assertEagerConsumerPluginNotification(LicenseState.GRACE_PERIOD, 10); + assertLazyConsumerPluginNotification(LicenseState.GRACE_PERIOD, 10); + logger.info("--> restart node"); + internalCluster().fullRestart(); + ensureYellow(); + logger.info("--> await node for grace_period"); + assertEagerConsumerPluginNotification(LicenseState.GRACE_PERIOD, 5); + assertLazyConsumerPluginNotification(LicenseState.GRACE_PERIOD, 5); + } + + public void testClusterRestartWhileExpired() throws Exception { + wipeAllLicenses(); + internalCluster().startNode(); + ensureGreen(); + assertEagerConsumerPluginNotification(LicenseState.DISABLED, 20); + assertLazyConsumerPluginNotification(LicenseState.DISABLED, 20); + logger.info("--> restart node"); + internalCluster().fullRestart(); + ensureYellow(); + logger.info("--> await node for disabled"); + assertEagerConsumerPluginNotification(LicenseState.DISABLED, 5); + assertLazyConsumerPluginNotification(LicenseState.DISABLED, 5); + } + + public void testClusterNotRecovered() throws Exception { + logger.info("--> start one master out of two [recovery state]"); + internalCluster().startNode(nodeSettingsBuilder(0).put("discovery.zen.minimum_master_nodes", 2).put("node.master", true)); + logger.info("--> start second master out of two [recovered state]"); + internalCluster().startNode(nodeSettingsBuilder(1).put("discovery.zen.minimum_master_nodes", 2).put("node.master", true)); + assertLicenseesStateEnabled(); + assertConsumerPluginEnabledNotification(1); + } + + public void testAtMostOnceTrialLicenseGeneration() throws Exception { + wipeAllLicenses(); + logger.info("--> start one node [trial license should be generated & enabled]"); + internalCluster().startNode(nodeSettingsBuilder(0)); + assertLicenseesStateEnabled(); + assertConsumerPluginEnabledNotification(1); + + logger.info("--> start another node [trial license should be propagated from the old master not generated]"); + internalCluster().startNode(nodeSettings(1)); + assertLicenseesStateEnabled(); + assertConsumerPluginEnabledNotification(1); + + logger.info("--> check if multiple trial licenses are found for a id"); + LicensesMetaData licensesMetaData = clusterService().state().metaData().custom(LicensesMetaData.TYPE); + assertThat(licensesMetaData.getLicense(), not(LicensesMetaData.LICENSE_TOMBSTONE)); + + wipeAllLicenses(); + } + + private void removeLicense() throws Exception { + ClusterAdminClient cluster = internalCluster().client().admin().cluster(); + ensureGreen(); + License putLicenses = generateSignedLicense(TimeValue.timeValueMinutes(1)); + PutLicenseRequestBuilder putLicenseRequestBuilder = new PutLicenseRequestBuilder(cluster, PutLicenseAction.INSTANCE); + putLicenseRequestBuilder.setLicense(putLicenses); + DeleteLicenseResponse response = new DeleteLicenseRequestBuilder(cluster, DeleteLicenseAction.INSTANCE).get(); + assertThat(response.isAcknowledged(), equalTo(true)); + } + + private License generateAndPutLicenses() throws Exception { + ClusterAdminClient cluster = internalCluster().client().admin().cluster(); + ensureGreen(); + License putLicenses = generateSignedLicense(TimeValue.timeValueMinutes(1)); + PutLicenseRequestBuilder putLicenseRequestBuilder = new PutLicenseRequestBuilder(cluster, PutLicenseAction.INSTANCE); + putLicenseRequestBuilder.setLicense(putLicenses); + final PutLicenseResponse putLicenseResponse = putLicenseRequestBuilder.get(); + assertThat(putLicenseResponse.isAcknowledged(), equalTo(true)); + assertThat(putLicenseResponse.status(), equalTo(LicensesStatus.VALID)); + return putLicenses; + } + + private void assertNoLicense() { + ClusterAdminClient cluster = internalCluster().client().admin().cluster(); + final GetLicenseResponse response = new GetLicenseRequestBuilder(cluster, GetLicenseAction.INSTANCE).get(); + assertThat(response.license(), nullValue()); + LicensesMetaData licensesMetaData = clusterService().state().metaData().custom(LicensesMetaData.TYPE); + assertThat(licensesMetaData, notNullValue()); + assertThat(licensesMetaData.getLicense(), equalTo(LicensesMetaData.LICENSE_TOMBSTONE)); + } + + private void getAndCheckLicense(License license) { + ClusterAdminClient cluster = internalCluster().client().admin().cluster(); + final GetLicenseResponse response = new GetLicenseRequestBuilder(cluster, GetLicenseAction.INSTANCE).get(); + assertThat(response.license(), equalTo(license)); + LicensesMetaData licensesMetaData = clusterService().state().metaData().custom(LicensesMetaData.TYPE); + assertThat(licensesMetaData, notNullValue()); + assertThat(licensesMetaData.getLicense(), not(LicensesMetaData.LICENSE_TOMBSTONE)); + } + + private void assertLicenseesStateEnabled() throws Exception { + for (String id : PLUGINS) { + assertLicenseeState(id, LicenseState.ENABLED); + } + } + + private void assertConsumerPluginEnabledNotification(int timeoutInSec) throws InterruptedException { + assertEagerConsumerPluginNotification(LicenseState.ENABLED, timeoutInSec); + assertLazyConsumerPluginNotification(LicenseState.ENABLED, timeoutInSec); + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/LicensesServiceNodeTests.java b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/LicensesServiceNodeTests.java new file mode 100644 index 00000000000..1ad36215294 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/LicensesServiceNodeTests.java @@ -0,0 +1,57 @@ +/* + * 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.license.plugin; + +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.license.plugin.consumer.EagerLicenseRegistrationConsumerPlugin; +import org.elasticsearch.license.plugin.consumer.EagerLicenseRegistrationPluginService; +import org.elasticsearch.license.plugin.core.LicenseState; +import org.elasticsearch.node.Node; +import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.test.ESIntegTestCase; +import org.elasticsearch.xpack.XPackPlugin; + +import java.util.Arrays; +import java.util.Collection; + +import static org.elasticsearch.test.ESIntegTestCase.Scope.TEST; + +/** + */ +@ESIntegTestCase.ClusterScope(scope = TEST, numDataNodes = 10, numClientNodes = 0) +public class LicensesServiceNodeTests extends AbstractLicensesIntegrationTestCase { + @Override + protected Settings nodeSettings(int nodeOrdinal) { + return Settings.settingsBuilder() + .put(super.nodeSettings(nodeOrdinal)) + .put(Node.HTTP_ENABLED, true) + .build(); + } + + @Override + protected Collection> nodePlugins() { + return Arrays.asList(XPackPlugin.class, EagerLicenseRegistrationConsumerPlugin.class); + } + + @Override + protected Collection> transportClientPlugins() { + return nodePlugins(); + } + + public void testPluginStatus() throws Exception { + final Iterable testPluginServices = internalCluster().getDataNodeInstances(EagerLicenseRegistrationPluginService.class); + assertTrue(awaitBusy(() -> { + for (EagerLicenseRegistrationPluginService pluginService : testPluginServices) { + if (pluginService.state() != LicenseState.ENABLED) { + return false; + } + } + return true; + })); + + } + +} diff --git a/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/LicensesTransportTests.java b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/LicensesTransportTests.java new file mode 100644 index 00000000000..9b8ea3294c3 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/LicensesTransportTests.java @@ -0,0 +1,149 @@ +/* + * 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.license.plugin; + +import org.elasticsearch.action.ActionFuture; +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.license.core.License; +import org.elasticsearch.license.plugin.action.delete.DeleteLicenseAction; +import org.elasticsearch.license.plugin.action.delete.DeleteLicenseRequestBuilder; +import org.elasticsearch.license.plugin.action.delete.DeleteLicenseResponse; +import org.elasticsearch.license.plugin.action.get.GetLicenseAction; +import org.elasticsearch.license.plugin.action.get.GetLicenseRequestBuilder; +import org.elasticsearch.license.plugin.action.get.GetLicenseResponse; +import org.elasticsearch.license.plugin.action.put.PutLicenseAction; +import org.elasticsearch.license.plugin.action.put.PutLicenseRequestBuilder; +import org.elasticsearch.license.plugin.action.put.PutLicenseResponse; +import org.elasticsearch.license.plugin.core.LicensesStatus; +import org.elasticsearch.test.ESIntegTestCase.ClusterScope; +import org.junit.After; + +import static org.elasticsearch.license.plugin.TestUtils.dateMath; +import static org.elasticsearch.license.plugin.TestUtils.generateSignedLicense; +import static org.elasticsearch.test.ESIntegTestCase.Scope.TEST; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.not; + +@ClusterScope(scope = TEST, numDataNodes = 10) +public class LicensesTransportTests extends AbstractLicensesIntegrationTestCase { + @After + public void beforeTest() throws Exception { + wipeAllLicenses(); + } + + public void testEmptyGetLicense() throws Exception { + final ActionFuture getLicenseFuture = new GetLicenseRequestBuilder(client().admin().cluster(), GetLicenseAction.INSTANCE).execute(); + final GetLicenseResponse getLicenseResponse = getLicenseFuture.get(); + assertNotNull(getLicenseResponse.license()); + assertThat(getLicenseResponse.license().operationMode(), equalTo(License.OperationMode.TRIAL)); + } + + public void testPutLicense() throws Exception { + License signedLicense = generateSignedLicense(TimeValue.timeValueMinutes(2)); + + // put license + PutLicenseRequestBuilder putLicenseRequestBuilder = new PutLicenseRequestBuilder(client().admin().cluster(), PutLicenseAction.INSTANCE) + .setLicense(signedLicense); + PutLicenseResponse putLicenseResponse = putLicenseRequestBuilder.get(); + assertThat(putLicenseResponse.isAcknowledged(), equalTo(true)); + assertThat(putLicenseResponse.status(), equalTo(LicensesStatus.VALID)); + + // get and check license + GetLicenseResponse getLicenseResponse = new GetLicenseRequestBuilder(client().admin().cluster(), GetLicenseAction.INSTANCE).get(); + assertThat(getLicenseResponse.license(), equalTo(signedLicense)); + } + + public void testPutLicenseFromString() throws Exception { + License signedLicense = generateSignedLicense(TimeValue.timeValueMinutes(2)); + String licenseString = TestUtils.dumpLicense(signedLicense); + + // put license source + PutLicenseRequestBuilder putLicenseRequestBuilder = new PutLicenseRequestBuilder(client().admin().cluster(), PutLicenseAction.INSTANCE) + .setLicense(licenseString); + PutLicenseResponse putLicenseResponse = putLicenseRequestBuilder.get(); + assertThat(putLicenseResponse.isAcknowledged(), equalTo(true)); + assertThat(putLicenseResponse.status(), equalTo(LicensesStatus.VALID)); + + // get and check license + GetLicenseResponse getLicenseResponse = new GetLicenseRequestBuilder(client().admin().cluster(), GetLicenseAction.INSTANCE).get(); + assertThat(getLicenseResponse.license(), equalTo(signedLicense)); + } + + public void testPutInvalidLicense() throws Exception { + License signedLicense = generateSignedLicense(TimeValue.timeValueMinutes(2)); + + // modify content of signed license + License tamperedLicense = License.builder() + .fromLicenseSpec(signedLicense, signedLicense.signature()) + .expiryDate(signedLicense.expiryDate() + 10 * 24 * 60 * 60 * 1000l) + .validate() + .build(); + + PutLicenseRequestBuilder builder = new PutLicenseRequestBuilder(client().admin().cluster(), PutLicenseAction.INSTANCE); + builder.setLicense(tamperedLicense); + + // try to put license (should be invalid) + final PutLicenseResponse putLicenseResponse = builder.get(); + assertThat(putLicenseResponse.status(), equalTo(LicensesStatus.INVALID)); + + // try to get invalid license + GetLicenseResponse getLicenseResponse = new GetLicenseRequestBuilder(client().admin().cluster(), GetLicenseAction.INSTANCE).get(); + assertThat(getLicenseResponse.license(), not(tamperedLicense)); + } + + public void testPutExpiredLicense() throws Exception { + License expiredLicense = generateSignedLicense(dateMath("now-10d/d", System.currentTimeMillis()), TimeValue.timeValueMinutes(2)); + License signedLicense = generateSignedLicense(TimeValue.timeValueMinutes(2)); + + PutLicenseRequestBuilder builder = new PutLicenseRequestBuilder(client().admin().cluster(), PutLicenseAction.INSTANCE); + builder.setLicense(signedLicense); + // put license should return valid (as there is one valid license) + PutLicenseResponse putLicenseResponse = builder.get(); + assertThat(putLicenseResponse.status(), equalTo(LicensesStatus.VALID)); + builder.setLicense(expiredLicense); + putLicenseResponse = builder.get(); + assertThat(putLicenseResponse.status(), equalTo(LicensesStatus.EXPIRED)); + // get license should not return the expired license + GetLicenseResponse getLicenseResponse = new GetLicenseRequestBuilder(client().admin().cluster(), GetLicenseAction.INSTANCE).get(); + assertThat(getLicenseResponse.license(), equalTo(signedLicense)); + } + + public void testPutLicensesSimple() throws Exception { + License basicSignedLicense = generateSignedLicense("basic", TimeValue.timeValueMinutes(5)); + PutLicenseRequestBuilder putLicenseRequestBuilder = new PutLicenseRequestBuilder(client().admin().cluster(), PutLicenseAction.INSTANCE) + .setLicense(basicSignedLicense); + PutLicenseResponse putLicenseResponse = putLicenseRequestBuilder.get(); + assertThat(putLicenseResponse.status(), equalTo(LicensesStatus.VALID)); + GetLicenseResponse getLicenseResponse = new GetLicenseRequestBuilder(client().admin().cluster(), GetLicenseAction.INSTANCE).get(); + assertThat(getLicenseResponse.license(), equalTo(basicSignedLicense)); + + License platinumSignedLicense = generateSignedLicense("platinum", TimeValue.timeValueMinutes(2)); + putLicenseRequestBuilder.setLicense(platinumSignedLicense); + putLicenseResponse = putLicenseRequestBuilder.get(); + assertThat(putLicenseResponse.isAcknowledged(), equalTo(true)); + assertThat(putLicenseResponse.status(), equalTo(LicensesStatus.VALID)); + getLicenseResponse = new GetLicenseRequestBuilder(client().admin().cluster(), GetLicenseAction.INSTANCE).get(); + assertThat(getLicenseResponse.license(), equalTo(platinumSignedLicense)); + } + + public void testRemoveLicensesSimple() throws Exception { + License goldLicense = generateSignedLicense("gold", TimeValue.timeValueMinutes(5)); + PutLicenseRequestBuilder putLicenseRequestBuilder = new PutLicenseRequestBuilder(client().admin().cluster(), PutLicenseAction.INSTANCE) + .setLicense(goldLicense); + PutLicenseResponse putLicenseResponse = putLicenseRequestBuilder.get(); + assertThat(putLicenseResponse.isAcknowledged(), equalTo(true)); + assertThat(putLicenseResponse.status(), equalTo(LicensesStatus.VALID)); + GetLicenseResponse getLicenseResponse = new GetLicenseRequestBuilder(client().admin().cluster(), GetLicenseAction.INSTANCE).get(); + assertThat(getLicenseResponse.license(), equalTo(goldLicense)); + // delete all licenses + DeleteLicenseRequestBuilder deleteLicenseRequestBuilder = new DeleteLicenseRequestBuilder(client().admin().cluster(), DeleteLicenseAction.INSTANCE); + DeleteLicenseResponse deleteLicenseResponse = deleteLicenseRequestBuilder.get(); + assertThat(deleteLicenseResponse.isAcknowledged(), equalTo(true)); + // get licenses (expected no licenses) + getLicenseResponse = new GetLicenseRequestBuilder(client().admin().cluster(), GetLicenseAction.INSTANCE).get(); + assertNull(getLicenseResponse.license()); + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/PutLicenseResponseTests.java b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/PutLicenseResponseTests.java new file mode 100644 index 00000000000..5bec19a549c --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/PutLicenseResponseTests.java @@ -0,0 +1,63 @@ +/* + * 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.license.plugin; + +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentHelper; +import org.elasticsearch.license.plugin.action.put.PutLicenseResponse; +import org.elasticsearch.license.plugin.core.LicensesStatus; +import org.elasticsearch.test.ESTestCase; + +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import static org.hamcrest.Matchers.equalTo; + +public class PutLicenseResponseTests extends ESTestCase { + public void testSerialization() throws Exception { + boolean acknowledged = randomBoolean(); + LicensesStatus status = randomFrom(LicensesStatus.VALID, LicensesStatus.INVALID, LicensesStatus.EXPIRED); + int nFeatures = randomIntBetween(1, 5); + Map ackMessages = new HashMap<>(); + for (int i = 0; i < nFeatures; i++) { + String feature = randomAsciiOfLengthBetween(9, 15); + int nMessages = randomIntBetween(1, 5); + String[] messages = new String[nMessages]; + for (int j = 0; j < nMessages; j++) { + messages[j] = randomAsciiOfLengthBetween(10, 30); + } + ackMessages.put(feature, messages); + } + + PutLicenseResponse response = new PutLicenseResponse(acknowledged, status, "", ackMessages); + XContentBuilder contentBuilder = XContentFactory.jsonBuilder(); + contentBuilder.startObject(); + response.toXContent(contentBuilder, ToXContent.EMPTY_PARAMS); + contentBuilder.endObject(); + + Map map = XContentHelper.convertToMap(contentBuilder.bytesStream().bytes(), false).v2(); + assertThat(map.containsKey("acknowledged"), equalTo(true)); + boolean actualAcknowledged = (boolean) map.get("acknowledged"); + assertThat(actualAcknowledged, equalTo(acknowledged)); + + assertThat(map.containsKey("license_status"), equalTo(true)); + String actualStatus = (String) map.get("license_status"); + assertThat(actualStatus, equalTo(status.name().toLowerCase(Locale.ROOT))); + + assertThat(map.containsKey("acknowledge"), equalTo(true)); + Map> actualAckMessages = (HashMap) map.get("acknowledge"); + assertTrue(actualAckMessages.containsKey("message")); + actualAckMessages.remove("message"); + assertThat(actualAckMessages.keySet(), equalTo(ackMessages.keySet())); + for (Map.Entry> entry : actualAckMessages.entrySet()) { + assertArrayEquals(entry.getValue().toArray(), ackMessages.get(entry.getKey())); + } + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/TestUtils.java b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/TestUtils.java new file mode 100644 index 00000000000..8450120ca14 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/TestUtils.java @@ -0,0 +1,217 @@ +/* + * 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.license.plugin; + +import org.apache.lucene.util.CollectionUtil; +import org.elasticsearch.action.ActionListener; +import org.elasticsearch.client.Client; +import org.elasticsearch.cluster.block.ClusterBlock; +import org.elasticsearch.cluster.block.ClusterBlockLevel; +import org.elasticsearch.common.collect.Tuple; +import org.elasticsearch.common.io.PathUtils; +import org.elasticsearch.common.joda.DateMathParser; +import org.elasticsearch.common.joda.FormatDateTimeFormatter; +import org.elasticsearch.common.joda.Joda; +import org.elasticsearch.common.logging.ESLogger; +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.license.core.License; +import org.elasticsearch.license.licensor.LicenseSigner; +import org.elasticsearch.license.plugin.action.put.PutLicenseRequest; +import org.elasticsearch.license.plugin.core.*; +import org.hamcrest.Matchers; +import org.junit.Assert; + +import java.nio.file.Path; +import java.util.*; +import java.util.concurrent.Callable; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + +import static org.elasticsearch.test.ESTestCase.*; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.assertThat; + +public class TestUtils { + + private final static FormatDateTimeFormatter formatDateTimeFormatter = Joda.forPattern("yyyy-MM-dd"); + private final static DateMathParser dateMathParser = new DateMathParser(formatDateTimeFormatter); + + public static long dateMath(String time, final long now) { + return dateMathParser.parse(time, new Callable() { + @Override + public Long call() throws Exception { + return now; + } + }); + } + public static Path getTestPriKeyPath() throws Exception { + return getResourcePath("/private.key"); + } + + public static Path getTestPubKeyPath() throws Exception { + return getResourcePath("/public.key"); + } + + public static void isSame(Collection firstLicenses, Collection secondLicenses) { + // check if the effective licenses have the same feature set + assertThat(firstLicenses.size(), equalTo(secondLicenses.size())); + + List license1 = new ArrayList<>(firstLicenses); + + CollectionUtil.timSort(license1, new Comparator() { + @Override + public int compare(License o1, License o2) { + return Long.compare(o1.expiryDate(), o2.expiryDate()); + } + }); + List license2 = new ArrayList<>(secondLicenses); + CollectionUtil.timSort(license2, new Comparator() { + @Override + public int compare(License o1, License o2) { + return Long.compare(o1.expiryDate(), o2.expiryDate()); + } + }); + assertThat(license1, equalTo(license2)); + } + + public static String dumpLicense(License license) throws Exception { + XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON); + builder.startObject(); + builder.startObject("license"); + license.toInnerXContent(builder, ToXContent.EMPTY_PARAMS); + builder.endObject(); + builder.endObject(); + return builder.string(); + } + + public static License generateSignedLicense(TimeValue expiryDuration) throws Exception { + return generateSignedLicense(null, -1, expiryDuration); + } + + public static License generateSignedLicense(String type, TimeValue expiryDuration) throws Exception { + return generateSignedLicense(type, -1, expiryDuration); + } + + public static License generateSignedLicense(long issueDate, TimeValue expiryDuration) throws Exception { + return generateSignedLicense(null, issueDate, expiryDuration); + } + + public static License generateSignedLicense(String type, long issueDate, TimeValue expiryDuration) throws Exception { + long issue = (issueDate != -1l) ? issueDate : System.currentTimeMillis(); + int version = randomIntBetween(License.VERSION_START, License.VERSION_CURRENT); + final String licenseType; + if (version < License.VERSION_NO_FEATURE_TYPE) { + licenseType = randomFrom("subscription", "internal", "development"); + } else { + licenseType = (type != null) ? type : randomFrom("basic", "silver", "dev", "gold", "platinum"); + } + final License.Builder builder = License.builder() + .uid(UUID.randomUUID().toString()) + .version(version) + .expiryDate(issue + expiryDuration.getMillis()) + .issueDate(issue) + .type(licenseType) + .issuedTo("customer") + .issuer("elasticsearch") + .maxNodes(5); + if (version == License.VERSION_START) { + builder.subscriptionType((type != null) ? type : randomFrom("dev", "gold", "platinum", "silver")); + builder.feature(randomAsciiOfLength(10)); + } + LicenseSigner signer = new LicenseSigner(getTestPriKeyPath(), getTestPubKeyPath()); + return signer.sign(builder.build()); + } + + private static Path getResourcePath(String resource) throws Exception { + return PathUtils.get(TestUtils.class.getResource(resource).toURI()); + } + + public static void awaitNoBlock(final Client client) throws InterruptedException { + boolean success = awaitBusy(() -> { + Set clusterBlocks = client.admin().cluster().prepareState().setLocal(true).execute().actionGet() + .getState().blocks().global(ClusterBlockLevel.METADATA_WRITE); + return clusterBlocks.isEmpty(); + }); + assertThat("awaiting no block for too long", success, equalTo(true)); + } + + public static void awaitNoPendingTasks(final Client client) throws InterruptedException { + boolean success = awaitBusy(() -> client.admin().cluster().preparePendingClusterTasks().get().getPendingTasks().isEmpty()); + assertThat("awaiting no pending tasks for too long", success, equalTo(true)); + } + + public static void registerAndAckSignedLicenses(final LicensesService licensesService, License license, final LicensesStatus expectedStatus) { + PutLicenseRequest putLicenseRequest = new PutLicenseRequest().license(license); + final CountDownLatch latch = new CountDownLatch(1); + final AtomicReference status = new AtomicReference<>(); + licensesService.registerLicense(putLicenseRequest, new ActionListener() { + @Override + public void onResponse(LicensesService.LicensesUpdateResponse licensesUpdateResponse) { + status.set(licensesUpdateResponse.status()); + latch.countDown(); + } + + @Override + public void onFailure(Throwable e) { + latch.countDown(); + } + }); + try { + latch.await(); + } catch (InterruptedException e) { + Assert.fail(e.getMessage()); + } + assertThat(status.get(), equalTo(expectedStatus)); + } + + public static class AssertingLicensee implements Licensee { + public final ESLogger logger; + public final String id; + public final List licenseStates = new CopyOnWriteArrayList<>(); + public final AtomicInteger expirationMessagesCalled = new AtomicInteger(0); + public final List> acknowledgementRequested = new CopyOnWriteArrayList<>(); + + private String[] acknowledgmentMessages = new String[0]; + + public AssertingLicensee(String id, ESLogger logger) { + this.logger = logger; + this.id = id; + } + + public void setAcknowledgementMessages(String[] acknowledgementMessages) { + this.acknowledgmentMessages = acknowledgementMessages; + } + @Override + public String id() { + return id; + } + + @Override + public String[] expirationMessages() { + expirationMessagesCalled.incrementAndGet(); + return new String[0]; + } + + @Override + public String[] acknowledgmentMessages(License currentLicense, License newLicense) { + acknowledgementRequested.add(new Tuple<>(currentLicense, newLicense)); + return acknowledgmentMessages; + } + + @Override + public void onChange(Status status) { + assertNotNull(status); + licenseStates.add(status.getLicenseState()); + } + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/TrialLicenseTests.java b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/TrialLicenseTests.java new file mode 100644 index 00000000000..f1f20d3f7a3 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/TrialLicenseTests.java @@ -0,0 +1,112 @@ +/* + * 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.license.plugin; + +import org.elasticsearch.common.Base64; +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.license.core.License; +import org.elasticsearch.license.plugin.core.TrialLicense; +import org.elasticsearch.test.ESTestCase; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.Collections; +import java.util.UUID; + +import static org.elasticsearch.license.core.CryptUtils.encrypt; +import static org.hamcrest.Matchers.equalTo; + + +public class TrialLicenseTests extends ESTestCase { + public void testBasic() throws Exception { + long issueDate = System.currentTimeMillis(); + License.Builder specBuilder = License.builder() + .uid(UUID.randomUUID().toString()) + .issuedTo("customer") + .maxNodes(5) + .issueDate(issueDate) + .expiryDate(issueDate + TimeValue.timeValueHours(2).getMillis()); + License trialLicense = TrialLicense.create(specBuilder); + assertThat(TrialLicense.verify(trialLicense), equalTo(true)); + } + + public void testTampered() throws Exception { + long issueDate = System.currentTimeMillis(); + License.Builder specBuilder = License.builder() + .uid(UUID.randomUUID().toString()) + .issuedTo("customer") + .maxNodes(5) + .issueDate(issueDate) + .expiryDate(issueDate + TimeValue.timeValueHours(2).getMillis()); + License trialLicense = TrialLicense.create(specBuilder); + final String originalSignature = trialLicense.signature(); + License tamperedLicense = License.builder().fromLicenseSpec(trialLicense, originalSignature) + .expiryDate(System.currentTimeMillis() + TimeValue.timeValueHours(5).getMillis()) + .build(); + assertThat(TrialLicense.verify(trialLicense), equalTo(true)); + assertThat(TrialLicense.verify(tamperedLicense), equalTo(false)); + } + + public void testFrom1x() throws Exception { + long issueDate = System.currentTimeMillis(); + License.Builder specBuilder = License.builder() + .uid(UUID.randomUUID().toString()) + .issuedTo("customer") + .type("subscription") + .subscriptionType("trial") + .issuer("elasticsearch") + .feature("") + .version(License.VERSION_START) + .maxNodes(5) + .issueDate(issueDate) + .expiryDate(issueDate + TimeValue.timeValueHours(2).getMillis()); + License pre20TrialLicense = specBuilder.build(); + License license = TrialLicense.create(License.builder().fromPre20LicenseSpec(pre20TrialLicense)); + assertThat(TrialLicense.verify(license), equalTo(true)); + } + + public void testTrialLicenseVerifyWithOlderVersion() throws Exception { + long issueDate = System.currentTimeMillis(); + License.Builder specBuilder = License.builder() + .issuedTo("customer") + .maxNodes(5) + .issueDate(issueDate) + .expiryDate(issueDate + TimeValue.timeValueHours(2).getMillis()) + .feature("") + .subscriptionType("trial") + .version(1); + License trialLicenseV1 = createTrialLicense(specBuilder); + assertThat(TrialLicense.verify(trialLicenseV1), equalTo(true)); + } + + static License createTrialLicense(License.Builder specBuilder) { + License spec = specBuilder + .type("trial") + .issuer("elasticsearch") + .uid(UUID.randomUUID().toString()) + .build(); + final String signature; + try { + XContentBuilder contentBuilder = XContentFactory.contentBuilder(XContentType.JSON); + spec.toXContent(contentBuilder, new ToXContent.MapParams(Collections.singletonMap(License.LICENSE_SPEC_VIEW_MODE, "true"))); + byte[] encrypt = encrypt(contentBuilder.bytes().toBytes()); + byte[] bytes = new byte[4 + 4 + encrypt.length]; + ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); + byteBuffer.putInt(-spec.version()) + .putInt(encrypt.length) + .put(encrypt); + signature = Base64.encodeBytes(bytes); + } catch (IOException e) { + throw new IllegalStateException(e); + } + return License.builder().fromLicenseSpec(spec, signature).build(); + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/consumer/EagerLicenseRegistrationConsumerPlugin.java b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/consumer/EagerLicenseRegistrationConsumerPlugin.java new file mode 100644 index 00000000000..bd003f279bf --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/consumer/EagerLicenseRegistrationConsumerPlugin.java @@ -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.license.plugin.consumer; + +import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.settings.Settings; + +/** + * Registers licenses upon the start of the service lifecycle + * see {@link EagerLicenseRegistrationPluginService} + *

+ * License registration might happen before clusterService start() + */ +public class EagerLicenseRegistrationConsumerPlugin extends TestConsumerPluginBase { + + public final static String NAME = "test_consumer_plugin_1"; + + @Inject + public EagerLicenseRegistrationConsumerPlugin(Settings settings) { + super(settings); + } + + @Override + public Class service() { + return EagerLicenseRegistrationPluginService.class; + } + + @Override + protected String pluginName() { + return NAME; + } + + @Override + public String id() { + return EagerLicenseRegistrationPluginService.ID; + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/consumer/EagerLicenseRegistrationPluginService.java b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/consumer/EagerLicenseRegistrationPluginService.java new file mode 100644 index 00000000000..2afc647ad69 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/consumer/EagerLicenseRegistrationPluginService.java @@ -0,0 +1,27 @@ +/* + * 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.license.plugin.consumer; + +import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.inject.Singleton; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.license.plugin.core.LicensesService; + +@Singleton +public class EagerLicenseRegistrationPluginService extends TestPluginServiceBase { + + public static String ID = "id1"; + + @Inject + public EagerLicenseRegistrationPluginService(Settings settings, LicensesService licensesClientService) { + super(true, settings, licensesClientService, null); + } + + @Override + public String id() { + return ID; + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/consumer/LazyLicenseRegistrationConsumerPlugin.java b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/consumer/LazyLicenseRegistrationConsumerPlugin.java new file mode 100644 index 00000000000..f8902f0da40 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/consumer/LazyLicenseRegistrationConsumerPlugin.java @@ -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.license.plugin.consumer; + +import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.settings.Settings; + +/** + * Registers licenses only after cluster has recovered + * see {@link LazyLicenseRegistrationPluginService} + *

+ * License registration happens after clusterservice start() + */ +public class LazyLicenseRegistrationConsumerPlugin extends TestConsumerPluginBase { + + public static String NAME = "test_consumer_plugin_2"; + + @Inject + public LazyLicenseRegistrationConsumerPlugin(Settings settings) { + super(settings); + } + + @Override + public Class service() { + return LazyLicenseRegistrationPluginService.class; + } + + @Override + protected String pluginName() { + return NAME; + } + + @Override + public String id() { + return LazyLicenseRegistrationPluginService.ID; + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/consumer/LazyLicenseRegistrationPluginService.java b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/consumer/LazyLicenseRegistrationPluginService.java new file mode 100644 index 00000000000..72f2470e52b --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/consumer/LazyLicenseRegistrationPluginService.java @@ -0,0 +1,28 @@ +/* + * 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.license.plugin.consumer; + +import org.elasticsearch.cluster.ClusterService; +import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.inject.Singleton; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.license.plugin.core.LicensesService; + +@Singleton +public class LazyLicenseRegistrationPluginService extends TestPluginServiceBase { + + public static String ID = "id2"; + + @Inject + public LazyLicenseRegistrationPluginService(Settings settings, LicensesService licensesClientService, ClusterService clusterService) { + super(false, settings, licensesClientService, clusterService); + } + + @Override + public String id() { + return ID; + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/consumer/TestConsumerPluginBase.java b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/consumer/TestConsumerPluginBase.java new file mode 100644 index 00000000000..b2106920e02 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/consumer/TestConsumerPluginBase.java @@ -0,0 +1,55 @@ +/* + * 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.license.plugin.consumer; + +import org.elasticsearch.client.Client; +import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.common.component.LifecycleComponent; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.plugins.Plugin; + +import java.util.ArrayList; +import java.util.Collection; + +public abstract class TestConsumerPluginBase extends Plugin { + + private final boolean isEnabled; + + public TestConsumerPluginBase(Settings settings) { + if (DiscoveryNode.clientNode(settings)) { + // Enable plugin only on node clients + this.isEnabled = "node".equals(settings.get(Client.CLIENT_TYPE_SETTING)); + } else { + this.isEnabled = true; + } + } + + @Override + public String name() { + return pluginName(); + } + + @Override + public String description() { + return "test licensing consumer plugin"; + } + + + @Override + public Collection> nodeServices() { + Collection> services = new ArrayList<>(); + if (isEnabled) { + services.add(service()); + } + return services; + } + + public abstract Class service(); + + protected abstract String pluginName(); + + public abstract String id(); +} diff --git a/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/consumer/TestPluginServiceBase.java b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/consumer/TestPluginServiceBase.java new file mode 100644 index 00000000000..94008744700 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/consumer/TestPluginServiceBase.java @@ -0,0 +1,104 @@ +/* + * 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.license.plugin.consumer; + +import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.cluster.ClusterChangedEvent; +import org.elasticsearch.cluster.ClusterService; +import org.elasticsearch.cluster.ClusterStateListener; +import org.elasticsearch.common.component.AbstractLifecycleComponent; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.gateway.GatewayService; +import org.elasticsearch.license.core.License; +import org.elasticsearch.license.plugin.core.LicenseState; +import org.elasticsearch.license.plugin.core.Licensee; +import org.elasticsearch.license.plugin.core.LicensesService; + +import java.util.Collections; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; + +public abstract class TestPluginServiceBase extends AbstractLifecycleComponent implements ClusterStateListener, Licensee { + + private LicensesService licensesClientService; + private final ClusterService clusterService; + final boolean eagerLicenseRegistration; + public final AtomicBoolean registered = new AtomicBoolean(false); + private AtomicReference state = new AtomicReference<>(LicenseState.DISABLED); + + public TestPluginServiceBase(boolean eagerLicenseRegistration, Settings settings, LicensesService licensesClientService, ClusterService clusterService) { + super(settings); + this.eagerLicenseRegistration = eagerLicenseRegistration; + this.licensesClientService = licensesClientService; + int trialDurationInSec = settings.getAsInt(".trial_license_duration_in_seconds", -1); + if (trialDurationInSec != -1) { + licensesClientService.setTrialLicenseDuration(TimeValue.timeValueSeconds(trialDurationInSec)); + } + int graceDurationInSec = settings.getAsInt(".grace_duration_in_seconds", 5); + licensesClientService.setGracePeriodDuration(TimeValue.timeValueSeconds(graceDurationInSec)); + if (!eagerLicenseRegistration) { + this.clusterService = clusterService; + clusterService.add(this); + } else { + this.clusterService = null; + } + } + + // should be the same string used by the license Manger to generate + // signed license + public abstract String id(); + + // check if feature is enabled + public LicenseState state() { + return state.get(); + } + + @Override + public void clusterChanged(ClusterChangedEvent event) { + if (!eagerLicenseRegistration && !event.state().blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK)) { + if (registered.compareAndSet(false, true)) { + logger.info("Registering to licensesService [lazy]"); + licensesClientService.register(this); + } + } + } + + protected void doStart() throws ElasticsearchException { + if (eagerLicenseRegistration) { + if (registered.compareAndSet(false, true)) { + logger.info("Registering to licensesService [eager]"); + licensesClientService.register(this); + } + } + } + + @Override + public String[] expirationMessages() { + return new String[0]; + } + + @Override + public String[] acknowledgmentMessages(License currentLicense, License newLicense) { + return new String[0]; + } + + @Override + public void onChange(Status status) { + this.state.set(status.getLicenseState()); + } + + @Override + protected void doStop() throws ElasticsearchException { + if (clusterService != null) { + clusterService.remove(this); + } + } + + @Override + protected void doClose() throws ElasticsearchException { + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/core/LicensesAcknowledgementTests.java b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/core/LicensesAcknowledgementTests.java new file mode 100644 index 00000000000..6beda195dce --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/core/LicensesAcknowledgementTests.java @@ -0,0 +1,161 @@ +/* + * 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.license.plugin.core; + +import org.elasticsearch.action.ActionListener; +import org.elasticsearch.cluster.metadata.MetaData; +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.license.core.License; +import org.elasticsearch.license.plugin.TestUtils; +import org.elasticsearch.license.plugin.action.put.PutLicenseRequest; +import org.elasticsearch.test.ESSingleNodeTestCase; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import static org.elasticsearch.license.plugin.TestUtils.awaitNoBlock; +import static org.elasticsearch.license.plugin.TestUtils.awaitNoPendingTasks; +import static org.elasticsearch.license.plugin.TestUtils.generateSignedLicense; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.not; + +public class LicensesAcknowledgementTests extends ESSingleNodeTestCase { + static { + MetaData.registerPrototype(LicensesMetaData.TYPE, LicensesMetaData.PROTO); + } + + @Override + protected boolean resetNodeAfterTest() { + return true; + } + + public void testAcknowledgment() throws Exception { + final LicensesService licensesService = getInstanceFromNode(LicensesService.class); + licensesService.start(); + String id = "testAcknowledgment"; + String[] acknowledgeMessages = new String[] {"message"}; + TestUtils.AssertingLicensee licensee = new TestUtils.AssertingLicensee(id, logger); + licensee.setAcknowledgementMessages(acknowledgeMessages); + awaitNoBlock(client()); + licensesService.register(licensee); + awaitNoPendingTasks(client()); + // try installing a signed license + License signedLicense = generateSignedLicense(TimeValue.timeValueHours(10)); + PutLicenseRequest putLicenseRequest = new PutLicenseRequest().license(signedLicense); + CountDownLatch latch = new CountDownLatch(1); + // ensure acknowledgement message was part of the response + licensesService.registerLicense(putLicenseRequest, new AssertingLicensesUpdateResponse(false, LicensesStatus.VALID, + Collections.singletonMap(id, acknowledgeMessages), latch)); + if (!latch.await(5, TimeUnit.SECONDS)) { + fail("waiting too long for a response to license registration"); + } + awaitNoPendingTasks(client()); + assertThat(licensee.acknowledgementRequested.size(), equalTo(1)); + assertThat(licensee.acknowledgementRequested.get(0).v2(), equalTo(signedLicense)); + assertThat(licensesService.getLicense(), not(signedLicense)); + + latch = new CountDownLatch(1); + // try installing a signed license with acknowledgement + putLicenseRequest = new PutLicenseRequest().license(signedLicense).acknowledge(true); + // ensure license was installed and no acknowledgment message was returned + licensee.setAcknowledgementMessages(new String[0]); + licensesService.registerLicense(putLicenseRequest, new AssertingLicensesUpdateResponse(true, LicensesStatus.VALID, Collections.emptyMap(), latch)); + if (!latch.await(5, TimeUnit.SECONDS)) { + fail("waiting too long for a response to license registration"); + } + awaitNoPendingTasks(client()); + assertThat(licensee.acknowledgementRequested.size(), equalTo(1)); + assertThat(licensee.acknowledgementRequested.get(0).v2(), equalTo(signedLicense)); + assertThat(licensesService.getLicense(), equalTo(signedLicense)); + licensesService.stop(); + } + + public void testAcknowledgementMultipleLicensee() throws Exception { + final LicensesService licensesService = getInstanceFromNode(LicensesService.class); + licensesService.start(); + String id1 = "testAcknowledgementMultipleLicensee_1"; + String[] acknowledgeMessages1 = new String[] {"testAcknowledgementMultipleLicensee_1"}; + String id2 = "testAcknowledgementMultipleLicensee_2"; + String[] acknowledgeMessages2 = new String[] {"testAcknowledgementMultipleLicensee_2"}; + TestUtils.AssertingLicensee licensee1 = new TestUtils.AssertingLicensee(id1, logger); + licensee1.setAcknowledgementMessages(acknowledgeMessages1); + TestUtils.AssertingLicensee licensee2 = new TestUtils.AssertingLicensee(id2, logger); + licensee2.setAcknowledgementMessages(acknowledgeMessages2); + awaitNoBlock(client()); + licensesService.register(licensee1); + licensesService.register(licensee2); + awaitNoPendingTasks(client()); + // try installing a signed license + License signedLicense = generateSignedLicense(TimeValue.timeValueHours(10)); + PutLicenseRequest putLicenseRequest = new PutLicenseRequest().license(signedLicense); + CountDownLatch latch = new CountDownLatch(1); + // ensure acknowledgement message was part of the response + final HashMap expectedMessages = new HashMap<>(); + expectedMessages.put(id1, acknowledgeMessages1); + expectedMessages.put(id2, acknowledgeMessages2); + licensesService.registerLicense(putLicenseRequest, new AssertingLicensesUpdateResponse(false, LicensesStatus.VALID, + expectedMessages, latch)); + if (!latch.await(5, TimeUnit.SECONDS)) { + fail("waiting too long for a response to license registration"); + } + awaitNoPendingTasks(client()); + assertThat(licensee2.acknowledgementRequested.size(), equalTo(1)); + assertThat(licensee2.acknowledgementRequested.get(0).v2(), equalTo(signedLicense)); + assertThat(licensee1.acknowledgementRequested.size(), equalTo(1)); + assertThat(licensee1.acknowledgementRequested.get(0).v2(), equalTo(signedLicense)); + assertThat(licensesService.getLicense(), not(signedLicense)); + + latch = new CountDownLatch(1); + // try installing a signed license with acknowledgement + putLicenseRequest = new PutLicenseRequest().license(signedLicense).acknowledge(true); + // ensure license was installed and no acknowledgment message was returned + licensee1.setAcknowledgementMessages(new String[0]); + licensee2.setAcknowledgementMessages(new String[0]); + licensesService.registerLicense(putLicenseRequest, new AssertingLicensesUpdateResponse(true, LicensesStatus.VALID, Collections.emptyMap(), latch)); + if (!latch.await(5, TimeUnit.SECONDS)) { + fail("waiting too long for a response to license registration"); + } + awaitNoPendingTasks(client()); + assertThat(licensesService.getLicense(), equalTo(signedLicense)); + licensesService.stop(); + } + + private static class AssertingLicensesUpdateResponse implements ActionListener { + private final boolean expectedAcknowledgement; + private final LicensesStatus expectedStatus; + private final Map expectedAckMessages; + private final CountDownLatch latch; + + public AssertingLicensesUpdateResponse(boolean expectedAcknowledgement, LicensesStatus expectedStatus, Map expectedAckMessages, CountDownLatch latch) { + this.expectedAcknowledgement = expectedAcknowledgement; + this.expectedStatus = expectedStatus; + this.expectedAckMessages = expectedAckMessages; + this.latch = latch; + } + + @Override + public void onResponse(LicensesService.LicensesUpdateResponse licensesUpdateResponse) { + assertThat(licensesUpdateResponse.isAcknowledged(), equalTo(expectedAcknowledgement)); + assertThat(licensesUpdateResponse.status(), equalTo(expectedStatus)); + assertThat(licensesUpdateResponse.acknowledgeMessages().size(), equalTo(expectedAckMessages.size())); + for (Map.Entry expectedEntry : expectedAckMessages.entrySet()) { + Map actual = licensesUpdateResponse.acknowledgeMessages(); + assertThat(actual.containsKey(expectedEntry.getKey()), equalTo(true)); + String[] actualMessages = actual.get(expectedEntry.getKey()); + assertThat(actualMessages, equalTo(expectedEntry.getValue())); + } + latch.countDown(); + } + + @Override + public void onFailure(Throwable throwable) { + latch.countDown(); + } + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/core/LicensesExpirationCallbackTests.java b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/core/LicensesExpirationCallbackTests.java new file mode 100644 index 00000000000..f7d2da9bf2c --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/core/LicensesExpirationCallbackTests.java @@ -0,0 +1,160 @@ +/* + * 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.license.plugin.core; + +import org.elasticsearch.cluster.metadata.MetaData; +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.license.core.License; +import org.elasticsearch.license.plugin.TestUtils; +import org.elasticsearch.test.ESSingleNodeTestCase; + +import java.util.Arrays; +import java.util.Collections; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.hamcrest.Matchers.equalTo; + +public class LicensesExpirationCallbackTests extends ESSingleNodeTestCase { + static { + MetaData.registerPrototype(LicensesMetaData.TYPE, LicensesMetaData.PROTO); + } + + @Override + protected boolean resetNodeAfterTest() { + return true; + } + + public void testPostExpiration() throws Exception { + int postExpirySeconds = randomIntBetween(5, 10); + TimeValue postExpiryDuration = TimeValue.timeValueSeconds(postExpirySeconds); + TimeValue min = TimeValue.timeValueSeconds(postExpirySeconds - randomIntBetween(1, 3)); + TimeValue max = TimeValue.timeValueSeconds(postExpirySeconds + randomIntBetween(1, 10)); + + final LicensesService.ExpirationCallback.Post post = new LicensesService.ExpirationCallback.Post(min, max, TimeValue.timeValueMillis(10)) { + @Override + public void on(License license) { + } + }; + long now = System.currentTimeMillis(); + assertThat(post.matches(now - postExpiryDuration.millis(), now), equalTo(true)); + assertThat(post.matches(now + postExpiryDuration.getMillis(), now), equalTo(false)); + } + + public void testPostExpirationWithNullMax() throws Exception { + int postExpirySeconds = randomIntBetween(5, 10); + TimeValue postExpiryDuration = TimeValue.timeValueSeconds(postExpirySeconds); + TimeValue min = TimeValue.timeValueSeconds(postExpirySeconds - randomIntBetween(1, 3)); + + final LicensesService.ExpirationCallback.Post post = new LicensesService.ExpirationCallback.Post(min, null, TimeValue.timeValueMillis(10)) { + @Override + public void on(License license) { + } + }; + long now = System.currentTimeMillis(); + assertThat(post.matches(now - postExpiryDuration.millis(), now), equalTo(true)); + } + + public void testPreExpirationWithNullMin() throws Exception { + int expirySeconds = randomIntBetween(5, 10); + TimeValue expiryDuration = TimeValue.timeValueSeconds(expirySeconds); + TimeValue max = TimeValue.timeValueSeconds(expirySeconds + randomIntBetween(1, 10)); + + final LicensesService.ExpirationCallback.Pre pre = new LicensesService.ExpirationCallback.Pre(null, max, TimeValue.timeValueMillis(10)) { + @Override + public void on(License license) { + } + }; + long now = System.currentTimeMillis(); + assertThat(pre.matches(expiryDuration.millis() + now, now), equalTo(true)); + } + + public void testPreExpiration() throws Exception { + int expirySeconds = randomIntBetween(5, 10); + TimeValue expiryDuration = TimeValue.timeValueSeconds(expirySeconds); + TimeValue min = TimeValue.timeValueSeconds(expirySeconds - randomIntBetween(0, 3)); + TimeValue max = TimeValue.timeValueSeconds(expirySeconds + randomIntBetween(1, 10)); + + final LicensesService.ExpirationCallback.Pre pre = new LicensesService.ExpirationCallback.Pre(min, max, TimeValue.timeValueMillis(10)) { + @Override + public void on(License license) { + } + }; + long now = System.currentTimeMillis(); + assertThat(pre.matches(expiryDuration.millis() + now, now), equalTo(true)); + assertThat(pre.matches(now - expiryDuration.getMillis(), now), equalTo(false)); + } + + public void testPreExpirationNotification() throws Exception { + final LicensesService licensesService = getInstanceFromNode(LicensesService.class); + licensesService.setTrialLicenseDuration(TimeValue.timeValueSeconds(5)); + AtomicInteger counter = new AtomicInteger(0); + licensesService.setExpirationCallbacks(Collections.singletonList( + preCallbackLatch(TimeValue.timeValueSeconds(1), TimeValue.timeValueSeconds(2), TimeValue.timeValueMillis(400), counter)) // 2000, 1600, 1200 + ); + licensesService.start(); + TestUtils.AssertingLicensee licensee = new TestUtils.AssertingLicensee("testPreExpirationNotification", logger); + licensesService.register(licensee); + boolean success = awaitBusy(() -> (counter.get() == 3 || counter.get() == 2)); + assertThat("counter: actual: " + counter.get() + "vs expected: 3", success, equalTo(true)); + licensesService.stop(); + } + + public void testPostExpirationNotification() throws Exception { + final LicensesService licensesService = getInstanceFromNode(LicensesService.class); + licensesService.setTrialLicenseDuration(TimeValue.timeValueSeconds(3)); + AtomicInteger counter = new AtomicInteger(0); + licensesService.setExpirationCallbacks(Collections.singletonList( + postCallbackLatch(TimeValue.timeValueMillis(700), TimeValue.timeValueSeconds(3), TimeValue.timeValueSeconds(1), counter)) // 700, 1700, 2700 + ); + licensesService.start(); + TestUtils.AssertingLicensee licensee = new TestUtils.AssertingLicensee("testPostExpirationNotification", logger); + licensesService.register(licensee); + // callback can be called only twice if the third notification is triggered with a delay + // causing the trigger time to be out of the post expiry callback window + boolean success = awaitBusy(() -> (counter.get() == 3 || counter.get() == 2)); + assertThat("counter: actual: " + counter.get() + "vs expected: 3", success, equalTo(true)); + licensesService.stop(); + } + + public void testMultipleExpirationNotification() throws Exception { + final LicensesService licensesService = getInstanceFromNode(LicensesService.class); + licensesService.setTrialLicenseDuration(TimeValue.timeValueSeconds(4)); + AtomicInteger postCounter = new AtomicInteger(0); + AtomicInteger preCounter = new AtomicInteger(0); + licensesService.setExpirationCallbacks(Arrays.asList( + preCallbackLatch(TimeValue.timeValueSeconds(1), TimeValue.timeValueSeconds(2), TimeValue.timeValueMillis(400), preCounter), // 2000, 1600, 1200 + postCallbackLatch(TimeValue.timeValueMillis(100), TimeValue.timeValueSeconds(2), TimeValue.timeValueMillis(400), postCounter)) // 100, 500, 900, 1300, 1700 + ); + licensesService.start(); + TestUtils.AssertingLicensee licensee = new TestUtils.AssertingLicensee("testMultipleExpirationNotification", logger); + licensesService.register(licensee); + // callback can be called one less than expected if the last notification is triggered + // with a delay, causing the trigger time to be out of the expiry callback window + boolean success = awaitBusy(() -> ((preCounter.get() == 3 || preCounter.get() == 2) + && (postCounter.get() == 5 || postCounter.get() == 4))); + assertThat("post count: actual: " + postCounter.get() + "vs expected: 5 " + + "pre count: actual: " + preCounter.get() + " vs expected: 3", success, equalTo(true)); + licensesService.stop(); + } + + private static LicensesService.ExpirationCallback preCallbackLatch(TimeValue min, TimeValue max, TimeValue frequency, final AtomicInteger count) { + return new LicensesService.ExpirationCallback.Pre(min, max, frequency) { + @Override + public void on(License license) { + count.incrementAndGet(); + } + }; + } + + private static LicensesService.ExpirationCallback postCallbackLatch(TimeValue min, TimeValue max, TimeValue frequency, final AtomicInteger count) { + return new LicensesService.ExpirationCallback.Post(min, max, frequency) { + @Override + public void on(License license) { + count.incrementAndGet(); + } + }; + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/core/LicensesExpiryNotificationTests.java b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/core/LicensesExpiryNotificationTests.java new file mode 100644 index 00000000000..7ba8b8375c5 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/core/LicensesExpiryNotificationTests.java @@ -0,0 +1,213 @@ +/* + * 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.license.plugin.core; + +import org.apache.lucene.util.LuceneTestCase.BadApple; +import org.elasticsearch.cluster.metadata.MetaData; +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.license.plugin.TestUtils.AssertingLicensee; +import org.elasticsearch.test.ESSingleNodeTestCase; + +import java.util.List; + +import static org.elasticsearch.license.plugin.TestUtils.awaitNoBlock; +import static org.elasticsearch.license.plugin.TestUtils.awaitNoPendingTasks; +import static org.elasticsearch.license.plugin.TestUtils.generateSignedLicense; +import static org.elasticsearch.license.plugin.TestUtils.registerAndAckSignedLicenses; +import static org.hamcrest.Matchers.equalTo; + +//test is just too slow, please fix it to not be sleep-based +@BadApple(bugUrl = "https://github.com/elastic/x-plugins/issues/1007") +public class LicensesExpiryNotificationTests extends ESSingleNodeTestCase { + static { + MetaData.registerPrototype(LicensesMetaData.TYPE, LicensesMetaData.PROTO); + } + + @Override + protected boolean resetNodeAfterTest() { + return true; + } + + public void testTrialLicenseEnforcement() throws Exception { + LicensesService licensesService = getInstanceFromNode(LicensesService.class); + licensesService.setTrialLicenseDuration(TimeValue.timeValueSeconds(5)); + licensesService.setGracePeriodDuration(TimeValue.timeValueSeconds(3)); + licensesService.start(); + String id1 = "testTrialLicenseEnforcement"; + final AssertingLicensee licensee = new AssertingLicensee(id1, logger); + awaitNoBlock(client()); + licensesService.register(licensee); + awaitNoPendingTasks(client()); + boolean success = awaitBusy(() -> licensee.licenseStates.size() == 3); + // trail license: enable, grace, disabled + assertLicenseStates(licensee, LicenseState.ENABLED, LicenseState.GRACE_PERIOD, LicenseState.DISABLED); + assertTrue(dumpLicensingStates(licensee.licenseStates), success); + licensesService.stop(); + } + + public void testTrialLicenseEnforcementMultipleLicensees() throws Exception { + LicensesService licensesService = getInstanceFromNode(LicensesService.class); + licensesService.setTrialLicenseDuration(TimeValue.timeValueSeconds(5)); + licensesService.setGracePeriodDuration(TimeValue.timeValueSeconds(3)); + licensesService.start(); + String id1 = "testTrialLicenseEnforcementMultipleLicensees_1"; + final AssertingLicensee licensee1 = new AssertingLicensee(id1, logger); + String id12 = "testTrialLicenseEnforcementMultipleLicensees_2"; + final AssertingLicensee licensee2 = new AssertingLicensee(id12, logger); + awaitNoBlock(client()); + licensesService.register(licensee1); + licensesService.register(licensee2); + awaitNoPendingTasks(client()); + boolean success = awaitBusy(() -> licensee1.licenseStates.size() == 3); + assertTrue(dumpLicensingStates(licensee1.licenseStates), success); + success = awaitBusy(() -> licensee2.licenseStates.size() == 3); + assertTrue(dumpLicensingStates(licensee2.licenseStates), success); + // trail license: enable, grace, disabled + assertLicenseStates(licensee1, LicenseState.ENABLED, LicenseState.GRACE_PERIOD, LicenseState.DISABLED); + assertLicenseStates(licensee2, LicenseState.ENABLED, LicenseState.GRACE_PERIOD, LicenseState.DISABLED); + licensesService.stop(); + } + + public void testTrialSignedLicenseEnforcement() throws Exception { + LicensesService licensesService = getInstanceFromNode(LicensesService.class); + licensesService.setTrialLicenseDuration(TimeValue.timeValueSeconds(2)); + licensesService.setGracePeriodDuration(TimeValue.timeValueSeconds(3)); + licensesService.start(); + String id1 = "testTrialSignedLicenseEnforcement"; + final AssertingLicensee licensee = new AssertingLicensee(id1, logger); + awaitNoBlock(client()); + licensesService.register(licensee); + awaitNoPendingTasks(client()); + boolean success = awaitBusy(() -> licensee.licenseStates.size() == 1); + assertTrue(dumpLicensingStates(licensee.licenseStates), success); + registerAndAckSignedLicenses(licensesService, generateSignedLicense(TimeValue.timeValueSeconds(4)), LicensesStatus.VALID); + success = awaitBusy(() -> licensee.licenseStates.size() == 4); + // trial: enable, signed: enable, signed: grace, signed: disabled + assertLicenseStates(licensee, LicenseState.ENABLED, LicenseState.ENABLED, LicenseState.GRACE_PERIOD, LicenseState.DISABLED); + assertTrue(dumpLicensingStates(licensee.licenseStates), success); + licensesService.stop(); + } + + public void testSignedLicenseEnforcement() throws Exception { + LicensesService licensesService = getInstanceFromNode(LicensesService.class); + licensesService.setTrialLicenseDuration(TimeValue.timeValueSeconds(4)); + licensesService.setGracePeriodDuration(TimeValue.timeValueSeconds(3)); + licensesService.start(); + String id1 = "testSignedLicenseEnforcement"; + final AssertingLicensee licensee = new AssertingLicensee(id1, logger); + awaitNoBlock(client()); + registerAndAckSignedLicenses(licensesService, generateSignedLicense(TimeValue.timeValueSeconds(2)), LicensesStatus.VALID); + licensesService.register(licensee); + awaitNoPendingTasks(client()); + boolean success = awaitBusy(() -> licensee.licenseStates.size() == 3); + // signed: enable, signed: grace, signed: disabled + assertLicenseStates(licensee, LicenseState.ENABLED, LicenseState.GRACE_PERIOD, LicenseState.DISABLED); + assertTrue(dumpLicensingStates(licensee.licenseStates), success); + licensesService.stop(); + } + + public void testSingedLicenseEnforcementMultipleLicensees() throws Exception { + LicensesService licensesService = getInstanceFromNode(LicensesService.class); + licensesService.setTrialLicenseDuration(TimeValue.timeValueSeconds(4)); + licensesService.setGracePeriodDuration(TimeValue.timeValueSeconds(3)); + licensesService.start(); + String id1 = "testSingedLicenseEnforcementMultipleLicensees_1"; + final AssertingLicensee licensee1 = new AssertingLicensee(id1, logger); + String id12 = "testSingedLicenseEnforcementMultipleLicensees_2"; + final AssertingLicensee licensee2 = new AssertingLicensee(id12, logger); + awaitNoBlock(client()); + registerAndAckSignedLicenses(licensesService, generateSignedLicense(TimeValue.timeValueSeconds(2)), LicensesStatus.VALID); + licensesService.register(licensee1); + licensesService.register(licensee2); + awaitNoPendingTasks(client()); + boolean success = awaitBusy(() -> licensee1.licenseStates.size() == 3); + assertTrue(dumpLicensingStates(licensee1.licenseStates), success); + success = awaitBusy(() -> licensee2.licenseStates.size() == 3); + assertTrue(dumpLicensingStates(licensee2.licenseStates), success); + // signed license: enable, grace, disabled + assertLicenseStates(licensee1, LicenseState.ENABLED, LicenseState.GRACE_PERIOD, LicenseState.DISABLED); + assertLicenseStates(licensee2, LicenseState.ENABLED, LicenseState.GRACE_PERIOD, LicenseState.DISABLED); + licensesService.stop(); + } + + public void testMultipleSignedLicenseEnforcement() throws Exception { + // register with trial license and assert onEnable and onDisable notification + LicensesService licensesService = getInstanceFromNode(LicensesService.class); + licensesService.setTrialLicenseDuration(TimeValue.timeValueSeconds(4)); + licensesService.setGracePeriodDuration(TimeValue.timeValueSeconds(1)); + licensesService.start(); + String id1 = "testMultipleSignedLicenseEnforcement"; + final AssertingLicensee licensee = new AssertingLicensee(id1, logger); + awaitNoBlock(client()); + licensesService.register(licensee); + awaitNoPendingTasks(client()); + // trial license enabled + boolean success = awaitBusy(() -> licensee.licenseStates.size() == 1); + assertTrue(dumpLicensingStates(licensee.licenseStates), success); + registerAndAckSignedLicenses(licensesService, generateSignedLicense("basic", TimeValue.timeValueSeconds(3)), LicensesStatus.VALID); + // signed license enabled + success = awaitBusy(() -> licensee.licenseStates.size() == 2); + assertTrue(dumpLicensingStates(licensee.licenseStates), success); + registerAndAckSignedLicenses(licensesService, generateSignedLicense("gold", TimeValue.timeValueSeconds(2)), LicensesStatus.VALID); + // second signed license enabled, grace and expired + success = awaitBusy(() ->licensee.licenseStates.size() == 5); + assertLicenseStates(licensee, LicenseState.ENABLED, LicenseState.ENABLED, LicenseState.ENABLED, LicenseState.GRACE_PERIOD, LicenseState.DISABLED); + assertTrue(dumpLicensingStates(licensee.licenseStates), success); + licensesService.stop(); + } + + public void testNonOverlappingMultipleLicensesEnforcement() throws Exception { + // register with trial license and assert onEnable and onDisable notification + LicensesService licensesService = getInstanceFromNode(LicensesService.class); + licensesService.setTrialLicenseDuration(TimeValue.timeValueSeconds(3)); + licensesService.setGracePeriodDuration(TimeValue.timeValueSeconds(1)); + licensesService.start(); + String id1 = "testNonOverlappingMultipleLicensesEnforcement"; + final AssertingLicensee licensee = new AssertingLicensee(id1, logger); + awaitNoBlock(client()); + licensesService.register(licensee); + // trial license: enabled, grace, disabled + boolean success = awaitBusy(() -> licensee.licenseStates.size() == 3); + + assertTrue(dumpLicensingStates(licensee.licenseStates), success); + // install license + registerAndAckSignedLicenses(licensesService, generateSignedLicense("basic", TimeValue.timeValueSeconds(2)), LicensesStatus.VALID); + // trial license: enabled, grace, disabled, signed license: enabled, grace, disabled + success = awaitBusy(() -> licensee.licenseStates.size() == 6); + assertLicenseStates(licensee, LicenseState.ENABLED, LicenseState.GRACE_PERIOD, LicenseState.DISABLED, LicenseState.ENABLED, LicenseState.GRACE_PERIOD, LicenseState.DISABLED); + assertTrue(dumpLicensingStates(licensee.licenseStates), success); + licensesService.stop(); + } + + private void assertLicenseStates(AssertingLicensee licensee, LicenseState... states) { + StringBuilder msg = new StringBuilder(); + msg.append("Actual: "); + msg.append(dumpLicensingStates(licensee.licenseStates)); + msg.append(" Expected: "); + msg.append(dumpLicensingStates(states)); + assertThat(msg.toString(), licensee.licenseStates.size(), equalTo(states.length)); + for (int i = 0; i < states.length; i++) { + assertThat(msg.toString(), licensee.licenseStates.get(i), equalTo(states[i])); + } + } + + private String dumpLicensingStates(List states) { + return dumpLicensingStates(states.toArray(new LicenseState[states.size()])); + } + + private String dumpLicensingStates(LicenseState... states) { + StringBuilder sb = new StringBuilder(); + sb.append("["); + for (int i = 0; i < states.length; i++) { + sb.append(states[i].name()); + if (i != states.length - 1) { + sb.append(", "); + } + } + sb.append("]"); + return sb.toString(); + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/core/LicensesManagerServiceTests.java b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/core/LicensesManagerServiceTests.java new file mode 100644 index 00000000000..993b2f89d4a --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/core/LicensesManagerServiceTests.java @@ -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.license.plugin.core; + +import org.elasticsearch.action.ActionListener; +import org.elasticsearch.cluster.ClusterService; +import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse; +import org.elasticsearch.cluster.metadata.MetaData; +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.license.core.License; +import org.elasticsearch.license.plugin.TestUtils; +import org.elasticsearch.license.plugin.action.delete.DeleteLicenseRequest; +import org.elasticsearch.test.ESSingleNodeTestCase; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.elasticsearch.license.plugin.TestUtils.generateSignedLicense; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.not; + +public class LicensesManagerServiceTests extends ESSingleNodeTestCase { + static { + MetaData.registerPrototype(LicensesMetaData.TYPE, LicensesMetaData.PROTO); + } + + @Override + protected boolean resetNodeAfterTest() { + return true; + } + + public void testStoreAndGetLicenses() throws Exception { + LicensesService licensesService = getInstanceFromNode(LicensesService.class); + ClusterService clusterService = getInstanceFromNode(ClusterService.class); + License goldLicense = generateSignedLicense("gold", TimeValue.timeValueHours(1)); + TestUtils.registerAndAckSignedLicenses(licensesService, goldLicense, LicensesStatus.VALID); + License silverLicense = generateSignedLicense("silver", TimeValue.timeValueHours(2)); + TestUtils.registerAndAckSignedLicenses(licensesService, silverLicense, LicensesStatus.VALID); + License platinumLicense = generateSignedLicense("platinum", TimeValue.timeValueHours(1)); + TestUtils.registerAndAckSignedLicenses(licensesService, platinumLicense, LicensesStatus.VALID); + License basicLicense = generateSignedLicense("basic", TimeValue.timeValueHours(3)); + TestUtils.registerAndAckSignedLicenses(licensesService, basicLicense, LicensesStatus.VALID); + LicensesMetaData licensesMetaData = clusterService.state().metaData().custom(LicensesMetaData.TYPE); + assertThat(licensesMetaData.getLicense(), equalTo(basicLicense)); + final License getLicenses = licensesService.getLicense(); + assertThat(getLicenses, equalTo(basicLicense)); + } + + public void testEffectiveLicenses() throws Exception { + final LicensesService licensesService = getInstanceFromNode(LicensesService.class); + final ClusterService clusterService = getInstanceFromNode(ClusterService.class); + License goldLicense = generateSignedLicense("gold", TimeValue.timeValueSeconds(5)); + // put gold license + TestUtils.registerAndAckSignedLicenses(licensesService, goldLicense, LicensesStatus.VALID); + LicensesMetaData licensesMetaData = clusterService.state().metaData().custom(LicensesMetaData.TYPE); + assertThat(licensesService.getLicense(licensesMetaData), equalTo(goldLicense)); + + License platinumLicense = generateSignedLicense("platinum", TimeValue.timeValueSeconds(3)); + // put platinum license + TestUtils.registerAndAckSignedLicenses(licensesService, platinumLicense, LicensesStatus.VALID); + licensesMetaData = clusterService.state().metaData().custom(LicensesMetaData.TYPE); + assertThat(licensesService.getLicense(licensesMetaData), equalTo(platinumLicense)); + + License basicLicense = generateSignedLicense("basic", TimeValue.timeValueSeconds(3)); + // put basic license + TestUtils.registerAndAckSignedLicenses(licensesService, basicLicense, LicensesStatus.VALID); + licensesMetaData = clusterService.state().metaData().custom(LicensesMetaData.TYPE); + assertThat(licensesService.getLicense(licensesMetaData), equalTo(basicLicense)); + } + + public void testInvalidLicenseStorage() throws Exception { + LicensesService licensesService = getInstanceFromNode(LicensesService.class); + ClusterService clusterService = getInstanceFromNode(ClusterService.class); + License signedLicense = generateSignedLicense(TimeValue.timeValueMinutes(2)); + + // modify content of signed license + License tamperedLicense = License.builder() + .fromLicenseSpec(signedLicense, signedLicense.signature()) + .expiryDate(signedLicense.expiryDate() + 10 * 24 * 60 * 60 * 1000l) + .validate() + .build(); + + TestUtils.registerAndAckSignedLicenses(licensesService, tamperedLicense, LicensesStatus.INVALID); + + // ensure that the invalid license never made it to cluster state + LicensesMetaData licensesMetaData = clusterService.state().metaData().custom(LicensesMetaData.TYPE); + if (licensesMetaData != null) { + assertThat(licensesMetaData.getLicense(), equalTo(LicensesMetaData.LICENSE_TOMBSTONE)); + } + } + + public void testRemoveLicenses() throws Exception { + LicensesService licensesService = getInstanceFromNode(LicensesService.class); + ClusterService clusterService = getInstanceFromNode(ClusterService.class); + + // generate a trial license for one feature + licensesService.register(new TestUtils.AssertingLicensee("", logger)); + + // generate signed licenses + License license = generateSignedLicense(TimeValue.timeValueHours(1)); + TestUtils.registerAndAckSignedLicenses(licensesService, license, LicensesStatus.VALID); + LicensesMetaData licensesMetaData = clusterService.state().metaData().custom(LicensesMetaData.TYPE); + assertThat(licensesMetaData.getLicense(), not(LicensesMetaData.LICENSE_TOMBSTONE)); + + // remove signed licenses + removeAndAckSignedLicenses(licensesService); + licensesMetaData = clusterService.state().metaData().custom(LicensesMetaData.TYPE); + assertThat(licensesMetaData.getLicense(), equalTo(LicensesMetaData.LICENSE_TOMBSTONE)); + } + + private void removeAndAckSignedLicenses(final LicensesService licensesService) { + final CountDownLatch latch = new CountDownLatch(1); + final AtomicBoolean success = new AtomicBoolean(false); + licensesService.removeLicense(new DeleteLicenseRequest(), new ActionListener() { + @Override + public void onResponse(ClusterStateUpdateResponse clusterStateUpdateResponse) { + if (clusterStateUpdateResponse.isAcknowledged()) { + success.set(true); + } + latch.countDown(); + } + + @Override + public void onFailure(Throwable throwable) { + latch.countDown(); + } + }); + try { + latch.await(); + } catch (InterruptedException e) { + fail(e.getMessage()); + } + assertThat("remove license(s) failed", success.get(), equalTo(true)); + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/core/LicensesMetaDataSerializationTests.java b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/core/LicensesMetaDataSerializationTests.java new file mode 100644 index 00000000000..e2bee38d75b --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/core/LicensesMetaDataSerializationTests.java @@ -0,0 +1,196 @@ +/* + * 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.license.plugin.core; + +import org.elasticsearch.Version; +import org.elasticsearch.common.Base64; +import org.elasticsearch.common.io.stream.ByteBufferStreamInput; +import org.elasticsearch.common.io.stream.BytesStreamOutput; +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.license.core.License; +import org.elasticsearch.license.plugin.TestUtils; +import org.elasticsearch.test.ESTestCase; + +import java.nio.ByteBuffer; +import java.util.Collections; +import java.util.UUID; + +import static org.elasticsearch.license.core.CryptUtils.encrypt; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.nullValue; + +public class LicensesMetaDataSerializationTests extends ESTestCase { + public void testXContentSerializationOneSignedLicense() throws Exception { + License license = TestUtils.generateSignedLicense(TimeValue.timeValueHours(2)); + LicensesMetaData licensesMetaData = new LicensesMetaData(license); + XContentBuilder builder = XContentFactory.jsonBuilder(); + builder.startObject("licenses"); + licensesMetaData.toXContent(builder, ToXContent.EMPTY_PARAMS); + builder.endObject(); + byte[] serializedBytes = builder.bytes().toBytes(); + + LicensesMetaData licensesMetaDataFromXContent = getLicensesMetaDataFromXContent(serializedBytes); + assertThat(licensesMetaDataFromXContent.getLicense(), equalTo(license)); + } + + public void testXContentSerializationOneTrial() throws Exception { + long issueDate = System.currentTimeMillis(); + License.Builder specBuilder = License.builder() + .uid(UUID.randomUUID().toString()) + .issuedTo("customer") + .maxNodes(5) + .issueDate(issueDate) + .expiryDate(issueDate + TimeValue.timeValueHours(2).getMillis()); + final License trialLicense = TrialLicense.create(specBuilder); + LicensesMetaData licensesMetaData = new LicensesMetaData(trialLicense); + XContentBuilder builder = XContentFactory.jsonBuilder(); + builder.startObject("licenses"); + licensesMetaData.toXContent(builder, ToXContent.EMPTY_PARAMS); + builder.endObject(); + byte[] serializedBytes = builder.bytes().toBytes(); + + LicensesMetaData licensesMetaDataFromXContent = getLicensesMetaDataFromXContent(serializedBytes); + assertThat(licensesMetaDataFromXContent.getLicense(), equalTo(trialLicense)); + } + + public void test1xLicensesMetaDataFromXContent() throws Exception { + License signedLicense = TestUtils.generateSignedLicense(TimeValue.timeValueHours(2)); + long issueDate = signedLicense.issueDate() - TimeValue.timeValueMillis(200).getMillis(); + License.Builder specBuilder = License.builder() + .uid(UUID.randomUUID().toString()) + .issuedTo("customer") + .maxNodes(5) + .issueDate(issueDate) + .expiryDate(issueDate + TimeValue.timeValueHours(2).getMillis()); + final License trialLicense = TrialLicense.create(specBuilder); + // trial license + XContentBuilder builder = XContentFactory.jsonBuilder(); + builder.startObject(); + builder.startObject("licenses"); + builder.startArray("trial_licenses"); + XContentBuilder contentBuilder = XContentFactory.contentBuilder(XContentType.JSON); + trialLicense.toXContent(contentBuilder, new ToXContent.MapParams(Collections.singletonMap(License.LICENSE_SPEC_VIEW_MODE, "true"))); + builder.value(Base64.encodeBytes(encrypt(contentBuilder.bytes().toBytes()))); + builder.endArray(); + builder.startArray("signed_licenses"); + builder.endArray(); + builder.endObject(); + builder.endObject(); + LicensesMetaData licensesMetaDataFromXContent = getLicensesMetaDataFromXContent(builder.bytes().toBytes()); + assertThat(licensesMetaDataFromXContent.getLicense(), equalTo(trialLicense)); + + // signed license + builder = XContentFactory.jsonBuilder(); + builder.startObject(); + builder.startObject("licenses"); + builder.startArray("trial_licenses"); + builder.endArray(); + builder.startArray("signed_licenses"); + signedLicense.toXContent(builder, ToXContent.EMPTY_PARAMS); + builder.endArray(); + builder.endObject(); + builder.endObject(); + licensesMetaDataFromXContent = getLicensesMetaDataFromXContent(builder.bytes().toBytes()); + assertThat(licensesMetaDataFromXContent.getLicense(), equalTo(signedLicense)); + + // trial and signed license + builder = XContentFactory.jsonBuilder(); + builder.startObject(); + builder.startObject("licenses"); + builder.startArray("trial_licenses"); + contentBuilder = XContentFactory.contentBuilder(XContentType.JSON); + trialLicense.toXContent(contentBuilder, new ToXContent.MapParams(Collections.singletonMap(License.LICENSE_SPEC_VIEW_MODE, "true"))); + builder.value(Base64.encodeBytes(encrypt(contentBuilder.bytes().toBytes()))); + builder.endArray(); + builder.startArray("signed_licenses"); + signedLicense.toXContent(builder, ToXContent.EMPTY_PARAMS); + builder.endArray(); + builder.endObject(); + builder.endObject(); + licensesMetaDataFromXContent = getLicensesMetaDataFromXContent(builder.bytes().toBytes()); + assertThat(licensesMetaDataFromXContent.getLicense(), equalTo(signedLicense)); + + // license with later issue date is selected + License signedLicenseIssuedLater = TestUtils.generateSignedLicense(TimeValue.timeValueHours(2)); + builder = XContentFactory.jsonBuilder(); + builder.startObject(); + builder.startObject("licenses"); + builder.startArray("trial_licenses"); + contentBuilder = XContentFactory.contentBuilder(XContentType.JSON); + trialLicense.toXContent(contentBuilder, new ToXContent.MapParams(Collections.singletonMap(License.LICENSE_SPEC_VIEW_MODE, "true"))); + builder.value(Base64.encodeBytes(encrypt(contentBuilder.bytes().toBytes()))); + builder.endArray(); + builder.startArray("signed_licenses"); + signedLicense.toXContent(builder, ToXContent.EMPTY_PARAMS); + signedLicenseIssuedLater.toXContent(builder, ToXContent.EMPTY_PARAMS); + builder.endArray(); + builder.endObject(); + builder.endObject(); + licensesMetaDataFromXContent = getLicensesMetaDataFromXContent(builder.bytes().toBytes()); + assertThat(licensesMetaDataFromXContent.getLicense(), equalTo(signedLicenseIssuedLater)); + + } + + public void test1xLicensesMetaDataFromStream() throws Exception { + long issueDate = System.currentTimeMillis(); + License.Builder specBuilder = License.builder() + .uid(UUID.randomUUID().toString()) + .issuedTo("customer") + .maxNodes(5) + .issueDate(issueDate) + .expiryDate(issueDate + TimeValue.timeValueHours(1).getMillis()); + final License trialLicense = TrialLicense.create(specBuilder); + // trial license + BytesStreamOutput output = new BytesStreamOutput(); + output.writeVInt(0); + output.writeVInt(1); + XContentBuilder contentBuilder = XContentFactory.contentBuilder(XContentType.JSON); + trialLicense.toXContent(contentBuilder, new ToXContent.MapParams(Collections.singletonMap(License.LICENSE_SPEC_VIEW_MODE, "true"))); + output.writeString(Base64.encodeBytes(encrypt(contentBuilder.bytes().toBytes()))); + byte[] bytes = output.bytes().toBytes(); + ByteBufferStreamInput input = new ByteBufferStreamInput(ByteBuffer.wrap(bytes)); + + input.setVersion(Version.V_2_0_0_beta1); + LicensesMetaData licensesMetaData = LicensesMetaData.PROTO.readFrom(input); + assertThat(licensesMetaData.getLicense(), equalTo(trialLicense)); + + // signed license + License signedLicense = TestUtils.generateSignedLicense(TimeValue.timeValueHours(2)); + output = new BytesStreamOutput(); + output.writeVInt(1); + signedLicense.writeTo(output); + output.writeVInt(0); + bytes = output.bytes().toBytes(); + input = new ByteBufferStreamInput(ByteBuffer.wrap(bytes)); + input.setVersion(Version.V_2_0_0_beta1); + licensesMetaData = LicensesMetaData.PROTO.readFrom(input); + assertThat(licensesMetaData.getLicense(), equalTo(signedLicense)); + } + + public void testLicenseTombstoneFromXContext() throws Exception { + final XContentBuilder builder = XContentFactory.jsonBuilder(); + builder.startObject("licenses"); + builder.nullField("license"); + builder.endObject(); + LicensesMetaData metaDataFromXContent = getLicensesMetaDataFromXContent(builder.bytes().toBytes()); + assertThat(metaDataFromXContent.getLicense(), equalTo(LicensesMetaData.LICENSE_TOMBSTONE)); + } + + private static LicensesMetaData getLicensesMetaDataFromXContent(byte[] bytes) throws Exception { + final XContentParser parser = XContentFactory.xContent(XContentType.JSON).createParser(bytes); + parser.nextToken(); // consume null + parser.nextToken(); // consume "licenses" + LicensesMetaData licensesMetaDataFromXContent = LicensesMetaData.PROTO.fromXContent(parser); + parser.nextToken(); // consume endObject + assertThat(parser.nextToken(), nullValue()); + return licensesMetaDataFromXContent; + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/test/resources/log4j.properties b/elasticsearch/x-pack/license-plugin/src/test/resources/log4j.properties new file mode 100644 index 00000000000..bad42d74b70 --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/test/resources/log4j.properties @@ -0,0 +1,11 @@ +es.logger.level=DEBUG +log4j.rootLogger=${es.logger.level}, out + +log4j.logger.org.apache.http=INFO, out +log4j.additivity.org.apache.http=false + +log4j.logger.org.elasticsearch.license=TRACE + +log4j.appender.out=org.apache.log4j.ConsoleAppender +log4j.appender.out.layout=org.apache.log4j.PatternLayout +log4j.appender.out.layout.conversionPattern=[%d{ISO8601}][%-5p][%-25c] %m%n diff --git a/elasticsearch/x-pack/license-plugin/src/test/resources/private.key b/elasticsearch/x-pack/license-plugin/src/test/resources/private.key new file mode 100644 index 00000000000..1f545803d87 Binary files /dev/null and b/elasticsearch/x-pack/license-plugin/src/test/resources/private.key differ diff --git a/elasticsearch/x-pack/license-plugin/src/test/resources/rest-api-spec/api/license.get.json b/elasticsearch/x-pack/license-plugin/src/test/resources/rest-api-spec/api/license.get.json new file mode 100644 index 00000000000..ad01451d51a --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/test/resources/rest-api-spec/api/license.get.json @@ -0,0 +1,19 @@ +{ + "license.get": { + "documentation": "https://www.elastic.co/guide/en/shield/current/license-management.html", + "methods": ["GET"], + "url": { + "path": "/_license", + "paths": ["/_license"], + "parts" : { + }, + "params": { + "local": { + "type" : "boolean", + "description" : "Return local information, do not retrieve the state from master node (default: false)" + } + } + }, + "body": null + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/test/resources/rest-api-spec/api/license.post.json b/elasticsearch/x-pack/license-plugin/src/test/resources/rest-api-spec/api/license.post.json new file mode 100644 index 00000000000..d7aa3dbc56f --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/test/resources/rest-api-spec/api/license.post.json @@ -0,0 +1,21 @@ +{ + "license.post": { + "documentation": "https://www.elastic.co/guide/en/shield/current/license-management.html", + "methods": ["PUT", "POST"], + "url": { + "path": "/_license", + "paths": ["/_license"], + "parts" : { + }, + "params": { + "acknowledge": { + "type" : "boolean", + "description" : "whether the user has acknowledged acknowledge messages (default: false)" + } + } + }, + "body": { + "description" : "licenses to be installed" + } + } +} diff --git a/elasticsearch/x-pack/license-plugin/src/test/resources/rest-api-spec/test/license/20_put_license.yaml b/elasticsearch/x-pack/license-plugin/src/test/resources/rest-api-spec/test/license/20_put_license.yaml new file mode 100644 index 00000000000..1d5fb822c7e --- /dev/null +++ b/elasticsearch/x-pack/license-plugin/src/test/resources/rest-api-spec/test/license/20_put_license.yaml @@ -0,0 +1,57 @@ +--- +"installing and getting license works": + + ## current license version + - do: + license.post: + body: | + {"license":{"uid":"893361dc-9749-4997-93cb-802e3d7fa4a8","type":"basic","issue_date_in_millis":1411948800000,"expiry_date_in_millis":1914278399999,"max_nodes":1,"issued_to":"issuedTo","issuer":"issuer","signature":"AAAAAgAAAA0lKPZ0a7aZquUltho/AAABmC9ZN0hjZDBGYnVyRXpCOW5Bb3FjZDAxOWpSbTVoMVZwUzRxVk1PSmkxakxZdW5IMlhlTHNoN1N2MXMvRFk4d3JTZEx3R3RRZ0pzU3lobWJKZnQvSEFva0ppTHBkWkprZWZSQi9iNmRQNkw1SlpLN0lDalZCS095MXRGN1lIZlpYcVVTTnFrcTE2dzhJZmZrdFQrN3JQeGwxb0U0MXZ0dDJHSERiZTVLOHNzSDByWnpoZEphZHBEZjUrTVBxRENNSXNsWWJjZllaODdzVmEzUjNiWktNWGM5TUhQV2plaUo4Q1JOUml4MXNuL0pSOEhQaVB2azhmUk9QVzhFeTFoM1Q0RnJXSG53MWk2K055c28zSmRnVkF1b2JSQkFLV2VXUmVHNDZ2R3o2VE1qbVNQS2lxOHN5bUErZlNIWkZSVmZIWEtaSU9wTTJENDVvT1NCYklacUYyK2FwRW9xa0t6dldMbmMzSGtQc3FWOTgzZ3ZUcXMvQkt2RUZwMFJnZzlvL2d2bDRWUzh6UG5pdENGWFRreXNKNkE9PQAAAQAALuQ44S3IG6SzolcXVJ6Z4CIXORDrYQ+wdLCeey0XdujTslAOj+k+vNgo6wauc7Uswi01esHu4lb5IgpvKy7RRCbh5bj/z2ubu2qMJqopp9BQyD7VQjVfqmG6seUMJwJ1a5Avvm9r41YPSPcrii3bKK2e1l6jK6N8ibCvnTyY/XkYGCJrBWTSJePDbg6ErbyodrZ37x1StLbPWcNAkmweyHjDJnvYnbeZZO7A3NmubXZjW7Ttf8/YwQyE00PqMcl7fVPY3hkKpAeHf8aaJbqkKYbqZuER3EWJX7ZvLVb1dNdNg8aXRn7YrkQcYwWgptYQpfV+D7yEJ4j5muAEoler"}} + + - match: { license_status: "valid" } + + - do: + license.get: {} + + ## a license object has 10 attributes + - length: { license: 10 } + + ## bwc for licenses format + - do: + license.post: + body: | + {"licenses":[{"uid":"893361dc-9749-4997-93cb-802e3d7fa4a8","type":"basic","issue_date_in_millis":1411948800000,"expiry_date_in_millis":1914278399999,"max_nodes":1,"issued_to":"issuedTo","issuer":"issuer","signature":"AAAAAgAAAA0lKPZ0a7aZquUltho/AAABmC9ZN0hjZDBGYnVyRXpCOW5Bb3FjZDAxOWpSbTVoMVZwUzRxVk1PSmkxakxZdW5IMlhlTHNoN1N2MXMvRFk4d3JTZEx3R3RRZ0pzU3lobWJKZnQvSEFva0ppTHBkWkprZWZSQi9iNmRQNkw1SlpLN0lDalZCS095MXRGN1lIZlpYcVVTTnFrcTE2dzhJZmZrdFQrN3JQeGwxb0U0MXZ0dDJHSERiZTVLOHNzSDByWnpoZEphZHBEZjUrTVBxRENNSXNsWWJjZllaODdzVmEzUjNiWktNWGM5TUhQV2plaUo4Q1JOUml4MXNuL0pSOEhQaVB2azhmUk9QVzhFeTFoM1Q0RnJXSG53MWk2K055c28zSmRnVkF1b2JSQkFLV2VXUmVHNDZ2R3o2VE1qbVNQS2lxOHN5bUErZlNIWkZSVmZIWEtaSU9wTTJENDVvT1NCYklacUYyK2FwRW9xa0t6dldMbmMzSGtQc3FWOTgzZ3ZUcXMvQkt2RUZwMFJnZzlvL2d2bDRWUzh6UG5pdENGWFRreXNKNkE9PQAAAQAALuQ44S3IG6SzolcXVJ6Z4CIXORDrYQ+wdLCeey0XdujTslAOj+k+vNgo6wauc7Uswi01esHu4lb5IgpvKy7RRCbh5bj/z2ubu2qMJqopp9BQyD7VQjVfqmG6seUMJwJ1a5Avvm9r41YPSPcrii3bKK2e1l6jK6N8ibCvnTyY/XkYGCJrBWTSJePDbg6ErbyodrZ37x1StLbPWcNAkmweyHjDJnvYnbeZZO7A3NmubXZjW7Ttf8/YwQyE00PqMcl7fVPY3hkKpAeHf8aaJbqkKYbqZuER3EWJX7ZvLVb1dNdNg8aXRn7YrkQcYwWgptYQpfV+D7yEJ4j5muAEoler"}]} + + - match: { license_status: "valid" } + + - do: + license.get: {} + + - length: { license: 10 } + + ## license version: 1.x + - do: + license.post: + body: | + {"licenses":[{"uid":"893361dc-9749-4997-93cb-802e3d7fa4a8","type":"subscription","subscription_type":"gold","issue_date_in_millis":1411948800000,"feature":"shield","expiry_date_in_millis":1914278399999,"max_nodes":1,"issued_to":"issuedTo","issuer":"issuer","signature":"AAAAAQAAAA0LVAywwpSH94cyXr4zAAABmC9ZN0hjZDBGYnVyRXpCOW5Bb3FjZDAxOWpSbTVoMVZwUzRxVk1PSmkxakxZdW5IMlhlTHNoN1N2MXMvRFk4d3JTZEx3R3RRZ0pzU3lobWJKZnQvSEFva0ppTHBkWkprZWZSQi9iNmRQNkw1SlpLN0lDalZCS095MXRGN1lIZlpYcVVTTnFrcTE2dzhJZmZrdFQrN3JQeGwxb0U0MXZ0dDJHSERiZTVLOHNzSDByWnpoZEphZHBEZjUrTVBxRENNSXNsWWJjZllaODdzVmEzUjNiWktNWGM5TUhQV2plaUo4Q1JOUml4MXNuL0pSOEhQaVB2azhmUk9QVzhFeTFoM1Q0RnJXSG53MWk2K055c28zSmRnVkF1b2JSQkFLV2VXUmVHNDZ2R3o2VE1qbVNQS2lxOHN5bUErZlNIWkZSVmZIWEtaSU9wTTJENDVvT1NCYklacUYyK2FwRW9xa0t6dldMbmMzSGtQc3FWOTgzZ3ZUcXMvQkt2RUZwMFJnZzlvL2d2bDRWUzh6UG5pdENGWFRreXNKNkE9PQAAAQA4qscc/URRZVdFoLwgy9dqybYEQLW8YLkiAyPV5XHHHdtk+dtZIepiNEDkUXhSX2waVJlsNRF8/4kqplDfwNoD2TUM8fTgiIfiSiZYGDTGST+yW/5eAveEU5J5v1liBN27bwkqL+V4YAa0Tcm7NKKwjScWKAHiTU3vF8chPkGfCHE0kQgVwPC9RE82pTw0s6/uR4PfLGNFfqPM0uiE5nucfVrtj89JQiO/KA/7ZyFbo7VTNXxZQt7T7rZWBCP9KIjptXzcWuk08Q5S+rSoJNYbFo3HGKtrCVsRz/55rceNtdwKKXu1IwnSeir4I1/KLduQTtFLy0+1th87VS8T88UT"}]} + + - match: { license_status: "valid" } + + - do: + license.get: {} + + - length: { license: 10 } + + ## multiple licenses version: 1.x + - do: + license.post: + body: | + {"licenses":[{"uid":"893361dc-9749-4997-93cb-802e3d7fa4a8","type":"internal","subscription_type":"none","issue_date_in_millis":1411948800000,"feature":"shield","expiry_date_in_millis":1440892799999,"max_nodes":1,"issued_to":"issuedTo","issuer":"issuer","signature":"AAAAAQAAAA04Q4ky3rFyyWLFkytEAAABmC9ZN0hjZDBGYnVyRXpCOW5Bb3FjZDAxOWpSbTVoMVZwUzRxVk1PSmkxakxZdW5IMlhlTHNoN1N2MXMvRFk4d3JTZEx3R3RRZ0pzU3lobWJKZnQvSEFva0ppTHBkWkprZWZSQi9iNmRQNkw1SlpLN0lDalZCS095MXRGN1lIZlpYcVVTTnFrcTE2dzhJZmZrdFQrN3JQeGwxb0U0MXZ0dDJHSERiZTVLOHNzSDByWnpoZEphZHBEZjUrTVBxRENNSXNsWWJjZllaODdzVmEzUjNiWktNWGM5TUhQV2plaUo4Q1JOUml4MXNuL0pSOEhQaVB2azhmUk9QVzhFeTFoM1Q0RnJXSG53MWk2K055c28zSmRnVkF1b2JSQkFLV2VXUmVHNDZ2R3o2VE1qbVNQS2lxOHN5bUErZlNIWkZSVmZIWEtaSU9wTTJENDVvT1NCYklacUYyK2FwRW9xa0t6dldMbmMzSGtQc3FWOTgzZ3ZUcXMvQkt2RUZwMFJnZzlvL2d2bDRWUzh6UG5pdENGWFRreXNKNkE9PQAAAQBxMvUMn4h2E4R4TQMijahTxQj4LPQO4f1M79UxX/XkDlGcH+J5pRHx08OtTRPsFL1lED+h+PIXx307Vo+PNDsOxrWvoYZeYBkOLAO3ny9vhQga+52jYhMxIuFrT9xbcSCSNpMhGojgOIPU2WgiopVdVcimo1+Gk8VtklPB1wPwFzfOjOnPgp/Icx3WYpfkeAUUOyWUYiFIBAe4bnz84iF+xwLKbgYk6aHF25ECBtdb/Uruhcm9+jEFpoIEUtCouvvk9C+NJZ4OickV4xpRgaRG2x9PONH8ZN0QGhGYhJGbisoCxuDmlLsyVxqxfMu3n/r7/jdsEJScjAlSrsLDOu6H"},{"uid":"893361dc-9749-4997-93cb-802e3dofh7aa","type":"internal","subscription_type":"none","issue_date_in_millis":1443484800000,"feature":"watcher","expiry_date_in_millis":1914278399999,"max_nodes":1,"issued_to":"issuedTo","issuer":"issuer","signature":"AAAAAQAAAA0Sc90guRIaQEmgLvMnAAABmC9ZN0hjZDBGYnVyRXpCOW5Bb3FjZDAxOWpSbTVoMVZwUzRxVk1PSmkxakxZdW5IMlhlTHNoN1N2MXMvRFk4d3JTZEx3R3RRZ0pzU3lobWJKZnQvSEFva0ppTHBkWkprZWZSQi9iNmRQNkw1SlpLN0lDalZCS095MXRGN1lIZlpYcVVTTnFrcTE2dzhJZmZrdFQrN3JQeGwxb0U0MXZ0dDJHSERiZTVLOHNzSDByWnpoZEphZHBEZjUrTVBxRENNSXNsWWJjZllaODdzVmEzUjNiWktNWGM5TUhQV2plaUo4Q1JOUml4MXNuL0pSOEhQaVB2azhmUk9QVzhFeTFoM1Q0RnJXSG53MWk2K055c28zSmRnVkF1b2JSQkFLV2VXUmVHNDZ2R3o2VE1qbVNQS2lxOHN5bUErZlNIWkZSVmZIWEtaSU9wTTJENDVvT1NCYklacUYyK2FwRW9xa0t6dldMbmMzSGtQc3FWOTgzZ3ZUcXMvQkt2RUZwMFJnZzlvL2d2bDRWUzh6UG5pdENGWFRreXNKNkE9PQAAAQCQ94dju0pnDZR3Uuypi0ic3aQJ+nvVqe+U8u79Dga5n1qIjcHDh7HvIBJEkF+tnVPlo/PXV/x7BZSwVY1PVErit+6rYix1yuHEgqwxmx/VdRICjCaZM6tk0Ob4dZCPv6Ebn2Mmk89KHC/PwiLPqF6QfwV/Pkpa8k2A3ORJmvYSDvXhe6tCs8dqc4ebrsFxqrZjwWh5CZSpzqqZBFXlngDv2N0hHhpGlueRszD0JJ5dfEL5ZA1DDOrgO9OJVejSHyRqe1L5QRUNdXPVfS+EAG0Dd1cNdJ/sMpYCPnVjbw6iq2/YgM3cuztsXVBY7ij4WnoP3ce7Zjs9TwHn+IqzftC6"}]} + + - match: { license_status: "valid" } + + - do: + license.get: {} + + - length: { license: 10 } + - match: { license.uid: "893361dc-9749-4997-93cb-802e3dofh7aa" } + diff --git a/elasticsearch/x-pack/marvel/LICENSE.txt b/elasticsearch/x-pack/marvel/LICENSE.txt new file mode 100644 index 00000000000..b1a2c354661 --- /dev/null +++ b/elasticsearch/x-pack/marvel/LICENSE.txt @@ -0,0 +1,439 @@ +SOFTWARE END USER LICENSE AGREEMENT + + READ THIS AGREEMENT CAREFULLY, WHICH CONSTITUTES A LEGALLY BINDING AGREEMENT AND GOVERNS YOUR USE OF +ELASTICSEARCH’S PROPRIETARY SOFTWARE. BY INSTALLING AND/OR USING SUCH SOFTWARE, YOU ARE INDICATING THAT YOU AGREE TO THE +TERMS AND CONDITIONS SET FORTH IN THIS AGREEMENT. IF YOU DO NOT AGREE WITH SUCH TERMS AND CONDITIONS, YOU MAY NOT +INSTALL OR USE ANY OF THE SOFTWARE. + + This END USER LICENSE AGREEMENT (this “Agreement") is entered into by and between the applicable Elasticsearch +entity referenced in Attachment 1 hereto (“Elasticsearchâ€) and the person or entity (“Youâ€) that has downloaded any of +Elasticsearch’s proprietary software to which this Agreement is attached or in connection with which this Agreement is +presented to You (collectively, the “Softwareâ€). This Agreement is effective upon the earlier of the date on the +commencement of any License granted pursuant to Section 1.1. below (as applicable, the “Effective Dateâ€). + +1. SOFTWARE LICENSE AND RESTRICTIONS +1.1 License Grants. + (a) Trial Version License. Subject to the terms and conditions of this Agreement, Elasticsearch agrees to +grant, and does hereby grant to You, for a period of thirty (30) days from the date on which You first install the +Software (the “Trial Termâ€), a License to the to use the Eligible Features and Functions of the Software that are +applicable to the Trial Version of the Software. You understand and agree that upon the expiration of a Trial Term, +You will no longer be able to use the Software, unless you either (i) purchase a Subscription, in which case You will +receive a License under Section 1.1(b) below to use the Eligible Features and Functions of the Software that are +applicable to the Subscription that You purchase, (ii) undertake the Registration of Your use of the Software with +Elasticsearch, in which case You will receive a License under Section 1.1(c) below to the Basic Version of the Software +or (iii) obtain from Elasticsearch written consent (e-mail sufficient) to extend the Trial Term, which may be granted by +Elasticsearch in its sole and absolute discretion. + (b) Subscription License. Subject to the terms and conditions of this Agreement and complete payment of any and +all applicable Subscription fees, Elasticsearch agrees to grant, and does hereby grant to You during the Subscription +Term, and for the restricted scope of this Agreement, a License (i) to use the Eligible Features and Functions of the +Software that are applicable to the Subscription level that You have purchased, (ii) for the number of Nodes (as defined +in the Elasticsearch Support Services Policy) and (iii) for the specific project for which you have purchased a +Subscription. The level of Subscription, the number of Nodes and specific project for which you have purchased such +Subscription, are set forth on the applicable ordering document entered into by Elasticsearch and You for the purchase +of the applicable Subscription (“Order Formâ€). + (c) Basic Version License. Subject to the terms and conditions of this Agreement, and in consideration of the +Registration of Your use the Software, Elasticsearch agrees to grant, and does hereby grant to You, for a period of one +(1) year from the date of Registration (“Basic Termâ€), a License to use the Eligible Features and Functions of the +Software that are applicable to the Basic Version of the Software. +1.2 Reservation of Rights; Restrictions. As between Elasticsearch and You, Elasticsearch owns all right title and +interest in and to the Software and any derivative works thereof, and except as expressly set forth in Section 1.1 +above, no other license to the Software is granted to You by implication, estoppel or otherwise. You agree not to: (i) +reverse engineer or decompile, decrypt, disassemble or otherwise reduce any Software or any portion thereof to +human-readable form, except and only to the extent any such restriction is prohibited by applicable law, (ii) deploy the +Software on more Nodes (as defined in Elasticsearch’s Support Services Policy) than are permitted under the applicable +License grant in Section 1.1 above (iii) where You have purchased a Subscription, use the Software in connection with +any project other than the project for which you have purchased such Subscription, as identified on the applicable Order +Form, (iv) prepare derivative works from, modify, copy or use the Software in any manner except as expressly permitted +in this Agreement; (v) except as expressly permitted in Section 1.1 above, transfer, sell, rent, lease, distribute, +sublicense, loan or otherwise transfer the Software in whole or in part to any third party; (vi) except as may be +expressly permitted on an applicable Order Form, use the Software for providing time-sharing services, any +software-as-a-service offering (“SaaSâ€), service bureau services or as part of an application services provider or other +service offering; (vii) circumvent the limitations on use of the Software that are imposed or preserved by any License +Key, (viii) alter or remove any proprietary notices in the Software; or (ix) make available to any third party any +analysis of the results of operation of the Software, including benchmarking results, without the prior written consent +of Elasticsearch. The Software may contain or be provided with open source libraries, components, utilities and other +open source software (collectively, “Open Source Softwareâ€), which Open Source Software may have applicable license +terms as identified on a website designated by Elasticsearch or otherwise provided with the Software or Documentation. +Notwithstanding anything to the contrary herein, use of the Open Source Software shall be subject to the license terms +and conditions applicable to such Open Source Software, to the extent required by the applicable licensor (which terms +shall not restrict the license rights granted to You hereunder, but may contain additional rights). +1.3 Audit Rights. You agree that, unless such right is waived in writing by Elasticsearch, Elasticsearch shall have the +right, upon fifteen (15) days’ notice to You, to audit Your use of the Software for compliance with any quantitative +limitations on Your use of the Software that are set forth in the applicable Order Form. You agree to provide +Elasticsearch with the necessary access to the Software to conduct such an audit either (i) remotely, or (ii) if remote +performance is not possible, at Your facilities, during normal business hours and no more than one (1) time in any +twelve (12) month period. In the event any such audit reveals that You have used the Software in excess of the +applicable quantitative limitations, You agree to solely for Your internal business operations, a limited, +non-exclusive, non-transferable, fully paid up, right and license (without the right to grant or authorize sublicenses) +promptly pay to Elasticsearch an amount equal to the difference between the fees actually paid and the fees that You +should have paid to remain in compliance with such quantitative limitations. This Section 1.3 shall survive for a +period of two (2) years from the termination or expiration of this Agreement. +1.4 Cluster Metadata. You understand and agree that once deployed, and on a daily basis, the Software may provide +metadata to Elasticsearch about Your cluster statistics and associates that metadata with Your IP address. However, no +other information is provided to Elasticsearch by the Software, including any information about the data You process or +store in connection with your use of the Software. Instructions for disabling this feature are contained in the +Software, however leaving this feature active enables Elasticsearch to gather cluster statistics and provide an improved +level of support to You. + +2. TERM AND TERMINATION +2.1 Term. Unless earlier terminated under Section 2.2 below, this Agreement shall commence on the Effective Date, and +shall continue in force for the term of the last to expire applicable license set forth in Section 1.1 above. +2.2 Termination. Either party may, upon written notice to the other party, terminate this Agreement for material breach +by the other party automatically and without any other formality, if such party has failed to cure such material breach +within thirty (30) days of receiving written notice of such material breach from the non-breaching party. +Notwithstanding the foregoing, this Agreement shall automatically terminate in the event that You intentionally breach +the scope of the license granted in Section 1.1 of this Agreement, provided that Elasticsearch reserves the right to +retroactively waive such automatic termination upon written notice to You. +2.3 Post Termination or Expiration. Upon termination or expiration of this Agreement, for any reason, You shall +promptly cease the use of the Software and Documentation and destroy (and certify to Elasticsearch in writing the fact +of such destruction), or return to Elasticsearch, all copies of the Software and Documentation then in Your possession +or under Your control. +2.4 Survival. Sections 2.3, 2.4, 3, 4 and 5 (as any such Sections may be modified by Attachment 1, if applicable) shall +survive any termination or expiration of this Agreement. +3. LIMITED WARRANTY AND DISCLAIMER OF WARRANTIES +3.1 Limited Performance Warranty. Subject to You purchasing a Subscription, Elasticsearch warrants that during the +applicable Subscription Term, the Software will perform in all material respects in accordance with the Documentation. +In the event of a breach of the foregoing warranty, Elasticsearch’s sole obligation, and Your exclusive remedy shall be +for Elasticsearch to (i) correct any failure(s) of the Software to perform in all material respects in accordance with +the Documentation or (ii) if Elasticsearch is unable to provide such a correction within thirty (30) days of receipt of +notice of the applicable non-conformity, promptly refund to Customer any pre-paid, unused fees paid by You to +Elasticsearch for the applicable Subscription. The warranty set forth in this Section 3.1 does not apply if the +applicable Software or any portion thereof: (a) has been altered, except by or on behalf Elasticsearch; (b) has not been +used, installed, operated, repaired, or maintained in accordance with this Agreement and/or the Documentation; (c) has +been subjected to abnormal physical or electrical stress, misuse, negligence, or accident; or (d) is used on equipment, +products, or systems not meeting specifications identified by Elasticsearch in the Documentation. Additionally, the +warranties set forth herein only apply when notice of a warranty claim is provided to Elasticsearch within the +applicable warranty period specified herein and do not apply to any bug, defect or error caused by or attributable to +software or hardware not supplied by Elasticsearch. +3.2 Malicious Code. Elasticsearch represents and warrants that prior to making it available for delivery to You, +Elasticsearch will use standard industry practices including, without limitation, the use of an updated commercial +anti-virus program, to test the Software for Malicious Code and remove any Malicious Code it discovers. In the event of +a breach of the foregoing warranty, Elasticsearch’s sole obligation, and Your exclusive remedy shall be for +Elasticsearch to replace the Software with Software that does not contain any Malicious Code. +3.3 Warranty Disclaimer. TO THE MAXIMUM EXTENT PERMITTED UNDER APPLICABLE LAW, THE SOFTWARE IS PROVIDED “AS IS†WITHOUT +WARRANTY OF ANY KIND, AND ELASTICSEARCH AND ITS LICENSORS MAKE NO WARRANTIES WHETHER EXPRESSED, IMPLIED OR STATUTORY +REGARDING OR RELATING TO THE SOFTWARE OR DOCUMENTATION. TO THE MAXIMUM EXTENT PERMITTED UNDER APPLICABLE LAW, +ELASTICSEARCH AND ITS LICENSORS SPECIFICALLY DISCLAIM ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NON-INFRINGEMENT WITH RESPECT TO THE SOFTWARE AND DOCUMENTATION, AND WITH RESPECT TO THE USE OF +THE FOREGOING. FURTHER, ELASTICSEARCH DOES NOT WARRANT RESULTS OF USE OR THAT THE SOFTWARE WILL BE ERROR FREE OR THAT +THE USE OF THE SOFTWARE WILL BE UNINTERRUPTED. +4. LIMITATION OF LIABILITY +The provisions of this Section 4 apply if You have not purchased a Subscription. If you have purchased a Subscription, +then the limitations of liability set forth in the applicable Subscription Agreement will apply in lieu of those set +forth in this Section 4. +4.1 Disclaimer of Certain Damages. IN NO EVENT SHALL YOU OR ELASTICSEARCH OR ITS LICENSORS BE LIABLE FOR ANY LOSS OF +PROFITS, LOSS OF USE, BUSINESS INTERRUPTION, LOSS OF DATA, COST OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, +SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND IN CONNECTION WITH OR ARISING OUT OF THE USE OR INABILITY TO +USE THE SOFTWARE, OR THE PERFORMANCE OF OR FAILURE TO PERFORM THIS AGREEMENT, WHETHER ALLEGED AS A BREACH OF CONTRACT OR +TORTIOUS CONDUCT, INCLUDING NEGLIGENCE, EVEN IF THE RESPONSIBLE PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. THE LIMITATIONS OF LIABILITY SET FORTH IN THIS SECTION 4.1 SHALL NOT APPLY TO A BREACH THROUGH GROSS NEGLIGENCE +OR INTENTIONAL MISCONDUCT BY YOU OF THE SCOPE OF THE LICENSE GRANTED IN SECTION 1.1 OR TO ANY OTHER LIABILITY THAT +CANNOT BE EXCLUDED OR LIMITED UNDER APPLICABLE LAW. +4.2 Damages Cap. IN NO EVENT SHALL ELASTICSEARCH’S OR ITS LICENSORS’ AGGREGATE, CUMULATIVE LIABILITY UNDER THIS +AGREEMENT EXCEED ONE THOUSAND DOLLARS ($1,000). +4.3 YOU AGREE THAT THE FOREGOING LIMITATIONS, EXCLUSIONS AND DISCLAIMERS ARE A REASONABLE ALLOCATION OF THE RISK BETWEEN +THE PARTIES AND WILL APPLY TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, EVEN IF ANY REMEDY FAILS IN ITS ESSENTIAL +PURPOSE. +5. DEFINITIONS +The following terms have the meanings ascribed: +5.1 “License†means a limited, non-exclusive, non-transferable, fully paid up, right and license (without the right to +grant or authorize sublicenses) solely for Your internal business operations to (i) install and use, in object code +format, the applicable Eligible Features and Functions of the Software, (ii) use, and distribute internally a reasonable +number of copies of the Documentation, provided that You must include on such copies all Marks and Notices; (iii) permit +Contractors to use the Software and Documentation as set forth in (i) and (ii) above, provided that such use must be +solely for Your benefit, and You shall be responsible for all acts and omissions of such Contractors in connection with +their use of the Software that are contrary to the terms and conditions of this Agreement.. +5.2 “License Key†means an alphanumeric code that enables the Eligible Features and Functions of the Software. +5.3 “Basic Version†means that version of the Software available for use without the purchase of a Qualifying +Subscription, but which does require Registration. +5.4 “Contractor†means third party contractors performing services on Your behalf. +5.5 “Documentation†means the published end user documentation provided by Elasticsearch with the Software. +5.6 “Eligible Features and Functions†means those features and functions of the Software that are eligible for use with +respect to a particular version of the Software or level of the Subscription. A list of the Eligible Features and +Functions that correspond to each version of the Software and Subscription levels may be found at +https://www.elastic.co/subscriptions. +5.7 “Malicious Code†means any code that is designed to harm, or otherwise disrupt in any unauthorized manner, the +operation of a recipient’s computer programs or computer systems or destroy or damage recipient’s data. For clarity, +Malicious Code shall not include any software bugs or errors handled through Support Services, or any standard features +of functions of the Software and/or any License Key that are intended to enforce the temporal and other limitations on +the scope of the use of the Software to the scope of the license purchased by You. +5.8 “Marks and Notices†means all Elasticsearch trademarks, trade names, logos and notices present on the Documentation +as originally provided by Elasticsearch. +5.9 “Registration†means Elasticsearch’s then-current process under which You may register Your use of the Software with +Elasticsearch by providing certain information to Elasticsearch regarding your use of the Software. +5.10 “Subscription†means the right to receive Support Services and a License to the Software. +5.11 “Subscription Term†means the period of time for which You have purchased a Subscription. +5.12 “Trial Version†means that version of the Software available for use without the purchase of a Qualifying +Subscription and without Registration. +6. MISCELLANEOUS +This Agreement, including Attachment 1 hereto, which is hereby incorporated herein by this reference, completely and +exclusively states the entire agreement of the parties regarding the subject matter herein, and it supersedes, and its +terms govern, all prior proposals, agreements, or other communications between the parties, oral or written, regarding +such subject matter. For the avoidance of doubt, the parties hereby expressly acknowledge and agree that if You issue +any purchase order or similar document in connection with its purchase of a license to the Software, You will do so only +for Your internal, administrative purposes and not with the intent to provide any contractual terms. This Agreement may +not be modified except by a subsequently dated, written amendment that expressly amends this Agreement and which is +signed on behalf of Elasticsearch and You, by duly authorized representatives. If any provision hereof is held +unenforceable, this Agreement will continue without said provision and be interpreted to reflect the original intent of +the parties. + + +ATTACHMENT 1 +ADDITIONAL TERMS AND CONDITIONS + +A. The following additional terms and conditions apply to all Customers with principal offices in the United States +of America: + +(1) Applicable Elasticsearch Entity. The entity providing the license is Elasticsearch, Inc., a Delaware corporation. + +(2) Government Rights. The Software product is "Commercial Computer Software," as that term is defined in 48 C.F.R. +2.101, and as the term is used in 48 C.F.R. Part 12, and is a Commercial Item comprised of "commercial computer +software" and "commercial computer software documentation". If acquired by or on behalf of a civilian agency, the U.S. +Government acquires this commercial computer software and/or commercial computer software documentation subject to the +terms of this Agreement, as specified in 48 C.F.R. 12.212 (Computer Software) and 12.211 (Technical Data) of the Federal +Acquisition Regulation ("FAR") and its successors. If acquired by or on behalf of any agency within the Department of +Defense ("DOD"), the U.S. Government acquires this commercial computer software and/or commercial computer software +documentation subject to the terms of the Elasticsearch Software License Agreement as specified in 48 C.F.R. 227.7202-3 +and 48 C.F.R. 227.7202-4 of the DOD FAR Supplement ("DFARS") and its successors, and consistent with 48 C.F.R. 227.7202. + This U.S. Government Rights clause, consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202 is in lieu of, and +supersedes, any other FAR, DFARS, or other clause or provision that addresses Government rights in computer software, +computer software documentation or technical data related to the Software under this Agreement and in any Subcontract +under which this commercial computer software and commercial computer software documentation is acquired or licensed. + +(3) Export Control. You acknowledge that the goods, software and technology acquired from Elasticsearch are subject +to U.S. export control laws and regulations, including but not limited to the International Traffic In Arms Regulations +(“ITARâ€) (22 C.F.R. Parts 120-130 (2010)); the Export Administration Regulations ("EAR") (15 C.F.R. Parts 730-774 +(2010)); the U.S. antiboycott regulations in the EAR and U.S. Department of the Treasury regulations; the economic +sanctions regulations and guidelines of the U.S. Department of the Treasury, Office of Foreign Assets Control, and the +USA Patriot Act (Title III of Pub. L. 107-56, signed into law October 26, 2001), as amended. You are now and will +remain in the future compliant with all such export control laws and regulations, and will not export, re-export, +otherwise transfer any Elasticsearch goods, software or technology or disclose any Elasticsearch software or technology +to any person contrary to such laws or regulations. You acknowledge that remote access to the Software may in certain +circumstances be considered a re-export of Software, and accordingly, may not be granted in contravention of U.S. export +control laws and regulations. +(4) Governing Law, Jurisdiction and Venue. +(a) Customers in California. If Customer is located in California (as determined by the Customer address on the +applicable Order Form, or for a trial license under 1.1(a), the location of person who installed the Software), this +Agreement will be governed by the laws of the State of California, without regard to its conflict of laws principles, +and all suits hereunder will be brought solely in Federal Court for the Northern District of California, or if that +court lacks subject matter jurisdiction, in any California State Court located in Santa Clara County. +(b) Customers Outside of California. If Customer is located anywhere other than California (as determined by the +Customer address on the applicable Order Form, or for a trial license under 1.1(a), the location of person who installed +the Software), this Agreement will be governed by the laws of the State of Delaware, without regard to its conflict of +laws principles, and all suits hereunder will be brought solely in Federal Court for the District of Delaware, or if +that court lacks subject matter jurisdiction, in any Delaware State Court located in Wilmington, Delaware. +(c) All Customers. This Agreement shall not be governed by the 1980 UN Convention on Contracts for the International +Sale of Goods. The parties hereby irrevocably waive any and all claims and defenses either might otherwise have in any +action or proceeding in any of the applicable courts set forth in (a) or (b) above, based upon any alleged lack of +personal jurisdiction, improper venue, forum non conveniens, or any similar claim or defense. +(d) Equitable Relief. A breach or threatened breach, by either party of Section 4 may cause irreparable harm for +which the non-breaching party shall be entitled to seek injunctive relief without being required to post a bond. + +B. The following additional terms and conditions apply to all Customers with principal offices in Canada: + +(1) Applicable Elasticsearch Entity. The entity providing the license is Elasticsearch B.C. Ltd., a corporation +incorporated under laws of the Province of British Columbia. + +(2) Export Control. You acknowledge that the goods, software and technology acquired from Elasticsearch are subject +to the restrictions and controls set out in Section A(3) above as well as those imposed by the Export and Import Permits +Act (Canada) and the regulations thereunder and that you will comply with all applicable laws and regulations. Without +limitation, You acknowledge that the Marvel Software, or any portion thereof, will not be exported: (a) to any country +on Canada's Area Control List; (b) to any country subject to UN Security Council embargo or action; or (c) contrary to +Canada's Export Control List Item 5505. You are now and will remain in the future compliant with all such export control +laws and regulations, and will not export, re-export, otherwise transfer any Elasticsearch goods, software or technology +or disclose any Elasticsearch software or technology to any person contrary to such laws or regulations. You will not +export or re-export the Marvel Software, or any portion thereof, directly or indirectly, in violation of the Canadian +export administration laws and regulations to any country or end user, or to any end user who you know or have reason to +know will utilize them in the design, development or production of nuclear, chemical or biological weapons. You further +acknowledge that the Marvel Software product may include technical data subject to such Canadian export regulations. +Elasticsearch does not represent that the Marvel Software is appropriate or available for use in all countries. +Elasticsearch prohibits accessing materials from countries or states where contents are illegal. You are using the +Marvel Software on your own initiative and you are responsible for compliance with all applicable laws. You hereby agree +to indemnify Elasticsearch and its affiliates from any claims, actions, liability or expenses (including reasonable +lawyers' fees) resulting from Your failure to act in accordance with the acknowledgements, agreements, and +representations in this Section B(2). + (3) Governing Law and Dispute Resolution. This Agreement shall be governed by the Province of Ontario and the +federal laws of Canada applicable therein without regard to conflict of laws provisions. The parties hereby irrevocably +waive any and all claims and defenses either might otherwise have in any such action or proceeding in any of such courts +based upon any alleged lack of personal jurisdiction, improper venue, forum non conveniens or any similar claim or +defense. Any dispute, claim or controversy arising out of or relating to this Agreement or the existence, breach, +termination, enforcement, interpretation or validity thereof, including the determination of the scope or applicability +of this agreement to arbitrate, (each, a “Disputeâ€), which the parties are unable to resolve after good faith +negotiations, shall be submitted first to the upper management level of the parties. The parties, through their upper +management level representatives shall meet within thirty (30) days of the Dispute being referred to them and if the +parties are unable to resolve such Dispute within thirty (30) days of meeting, the parties agree to seek to resolve the +Dispute through mediation with ADR Chambers in the City of Toronto, Ontario, Canada before pursuing any other +proceedings. The costs of the mediator shall be shared equally by the parties. If the Dispute has not been resolved +within thirty (30) days of the notice to desire to mediate, any party may terminate the mediation and proceed to +arbitration and the matter shall be referred to and finally resolved by arbitration at ADR Chambers pursuant to the +general ADR Chambers Rules for Arbitration in the City of Toronto, Ontario, Canada. The arbitration shall proceed in +accordance with the provisions of the Arbitration Act (Ontario). The arbitral panel shall consist of three (3) +arbitrators, selected as follows: each party shall appoint one (1) arbitrator; and those two (2) arbitrators shall +discuss and select a chairman. If the two (2) party-appointed arbitrators are unable to agree on the chairman, the +chairman shall be selected in accordance with the applicable rules of the arbitration body. Each arbitrator shall be +independent of each of the parties. The arbitrators shall have the authority to grant specific performance and to +allocate between the parties the costs of arbitration (including service fees, arbitrator fees and all other fees +related to the arbitration) in such equitable manner as the arbitrators may determine. The prevailing party in any +arbitration shall be entitled to receive reimbursement of its reasonable expenses incurred in connection therewith. +Judgment upon the award so rendered may be entered in a court having jurisdiction or application may be made to such +court for judicial acceptance of any award and an order of enforcement, as the case may be. Notwithstanding the +foregoing, Elasticsearch shall have the right to institute an action in a court of proper jurisdiction for preliminary +injunctive relief pending a final decision by the arbitrator, provided that a permanent injunction and damages shall +only be awarded by the arbitrator. The language to be used in the arbitral proceedings shall be English. + (4) Language. Any translation of this Agreement is done for local requirements and in the event of a dispute +between the English and any non-English version, the English version of this Agreement shall govern. At the request of +the parties, the official language of this Agreement and all communications and documents relating hereto is the English +language, and the English-language version shall govern all interpretation of the Agreement. À la demande des parties, +la langue officielle de la présente convention ainsi que toutes communications et tous documents s'y rapportant est la +langue anglaise, et la version anglaise est celle qui régit toute interprétation de la présente convention. +(5) Warranty Disclaimer. For Customers with principal offices in the Province of Québec, the following new sentence +is to be added to the end of Section 3.3: “SOME JURISDICTIONS DO NOT ALLOW LIMITATIONS OR EXCLUSIONS OF CERTAIN TYPES OF +DAMAGES AND/OR WARRANTIES AND CONDITIONS. THE LIMITATIONS, EXCLUSIONS AND DISCLAIMERS SET FORTH IN THIS AGREEMENT SHALL +NOT APPLY IF AND ONLY IF AND TO THE EXTENT THAT THE LAWS OF A COMPETENT JURISDICTION REQUIRE LIABILITIES BEYOND AND +DESPITE THESE LIMITATIONS, EXCLUSIONS AND DISCLAIMERS.†+(6) Limitation of Liability. For Customers with principal offices in the Province of Québec, the following new +sentence is to be added to the end of Section 4.1: “SOME JURISDICTIONS DO NOT ALLOW LIMITATIONS OR EXCLUSIONS OF CERTAIN +TYPES OF DAMAGES AND/OR WARRANTIES AND CONDITIONS. THE LIMITATIONS, EXCLUSIONS AND DISCLAIMERS SET FORTH IN THIS +AGREEMENT SHALL NOT APPLY IF AND ONLY IF AND TO THE EXTENT THAT THE LAWS OF A COMPETENT JURISDICTION REQUIRE LIABILITIES +BEYOND AND DESPITE THESE LIMITATIONS, EXCLUSIONS AND DISCLAIMERS.†+ +C. The following additional terms and conditions apply to all Customers with principal offices outside of the United +States of America and Canada: + +(1) Applicable Elasticsearch Entity. The entity providing the license in Germany is Elasticsearch Gmbh; in France is +Elasticsearch SARL, in the United Kingdom is Elasticsearch Ltd, in Australia is Elasticsearch Pty Ltd., in Japan is +Elasticsearch KK, in Sweden is Elasticsearch AB, in Norway is Elasticsearch AS and in all other countries is +Elasticsearch BV. + +(2) Choice of Law. This Agreement shall be governed by and construed in accordance with the laws of the State of New +York, without reference to or application of choice of law rules or principles. Notwithstanding any choice of law +provision or otherwise, the Uniform Computer Information Transactions Act (UCITA) and the United Nations Convention on +the International Sale of Goods shall not apply. + +(3) Arbitration. Any dispute, claim or controversy arising out of or relating to this Agreement or the existence, +breach, termination, enforcement, interpretation or validity thereof, including the determination of the scope or +applicability of this agreement to arbitrate, (each, a “Disputeâ€) shall be referred to and finally resolved by +arbitration under the rules and at the location identified below. The arbitral panel shall consist of three (3) +arbitrators, selected as follows: each party shall appoint one (1) arbitrator; and those two (2) arbitrators shall +discuss and select a chairman. If the two party-appointed arbitrators are unable to agree on the chairman, the chairman +shall be selected in accordance with the applicable rules of the arbitration body. Each arbitrator shall be independent +of each of the parties. The arbitrators shall have the authority to grant specific performance and to allocate between +the parties the costs of arbitration (including service fees, arbitrator fees and all other fees related to the +arbitration) in such equitable manner as the arbitrators may determine. The prevailing party in any arbitration shall +be entitled to receive reimbursement of its reasonable expenses incurred in connection therewith. Judgment upon the +award so rendered may be entered in a court having jurisdiction or application may be made to such court for judicial +acceptance of any award and an order of enforcement, as the case may be. Notwithstanding the foregoing, Elasticsearch +shall have the right to institute an action in a court of proper jurisdiction for preliminary injunctive relief pending +a final decision by the arbitrator, provided that a permanent injunction and damages shall only be awarded by the +arbitrator. The language to be used in the arbitral proceedings shall be English. + +In addition, the following terms only apply to Customers with principal offices within Europe, the Middle East or Africa +(EMEA): + +Arbitration Rules and Location. Any Dispute shall be referred to and finally resolved by arbitration under the London +Court of International Arbitration (“LCIAâ€) Rules (which Rules are deemed to be incorporated by reference into this +clause) on the basis that the governing law is the law of the State of New York, USA. The seat, or legal place, of +arbitration shall be London, England. + +(b) In addition, the following terms only apply to Customers with principal offices within Asia Pacific, Australia & +New Zealand: + +Arbitration Rules and Location. Any Dispute shall be referred to and finally resolved by arbitration under the Rules of +Conciliation and Arbitration of the International Chamber of Commerce (“ICCâ€) in force on the date when the notice of +arbitration is submitted in accordance with such Rules (which Rules are deemed to be incorporated by reference into this +clause) on the basis that the governing law is the law of the State of New York, USA. The seat, or legal place, of +arbitration shall be Singapore. + +(c) In addition, the following terms only apply to Customers with principal offices within the Americas (excluding +North America): + +Arbitration Rules and Location. Any Dispute shall be referred to and finally resolved by arbitration under +International Dispute Resolution Procedures of the American Arbitration Association (“AAAâ€) in force on the date when +the notice of arbitration is submitted in accordance with such Procedures (which Procedures are deemed to be +incorporated by reference into this clause) on the basis that the governing law is the law of the State of New York, +USA. The seat, or legal place, of arbitration shall be New York, New York, USA. + +(4) In addition, for Customers with principal offices within the UK, the following new sentence is added to the end +of Section 4.1: + +Nothing in this Agreement shall have effect so as to limit or exclude a party’s liability for death or personal injury +caused by negligence or for fraud including fraudulent misrepresentation and this Section 4.1 shall take effect subject +to this provision. + +(5) In addition, for Customers with principal offices within France, Sections 1.2, 3 and 4.1 of the Agreement are +deleted and replaced with the following new Sections 1.2, 3.3 and 4.1: +1.2 Reservation of Rights; Restrictions. Elasticsearch owns all right title and interest in and to the Software and +any derivative works thereof, and except as expressly set forth in Section 1.1 above, no other license to the Software +is granted to You by implication, or otherwise. You agree not to prepare derivative works from, modify, copy or use the +Software in any manner except as expressly permitted in this Agreement; provided that You may copy the Software for +archival purposes, only where such software is provided on a non-durable medium; and You may decompile the Software, +where necessary for interoperability purposes and where necessary for the correction of errors making the software unfit +for its intended purpose, if such right is not reserved by Elasticsearch as editor of the Software. Pursuant to article +L122-6-1 of the French intellectual property code, Elasticsearch reserves the right to correct any bugs as necessary for +the Software to serve its intended purpose. You agree not to: (i) transfer, sell, rent, lease, distribute, sublicense, +loan or otherwise transfer the Software in whole or in part to any third party; (ii) use the Software for providing +time-sharing services, any software-as-a-service offering (“SaaSâ€), service bureau services or as part of an application +services provider or other service offering; (iii) alter or remove any proprietary notices in the Software; or (iv) make +available to any third party any analysis of the results of operation of the Software, including benchmarking results, +without the prior written consent of Elasticsearch. +3.3 Warranty Disclaimer. TO THE MAXIMUM EXTENT PERMITTED UNDER APPLICABLE LAW, THE SOFTWARE IS PROVIDED “AS IS†+WITHOUT WARRANTY OF ANY KIND, AND ELASTICSEARCH AND ITS LICENSORS MAKE NO WARRANTIES WHETHER EXPRESSED, IMPLIED OR +STATUTORY REGARDING OR RELATING TO THE SOFTWARE OR DOCUMENTATION. TO THE MAXIMUM EXTENT PERMITTED UNDER APPLICABLE LAW, +ELASTICSEARCH AND ITS LICENSORS SPECIFICALLY DISCLAIM ALL IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE WITH +RESPECT TO THE SOFTWARE AND DOCUMENTATION, AND WITH RESPECT TO THE USE OF THE FOREGOING. FURTHER, ELASTICSEARCH DOES +NOT WARRANT RESULTS OF USE OR THAT THE SOFTWARE WILL BE ERROR FREE OR THAT THE USE OF THE SOFTWARE WILL BE +UNINTERRUPTED. +4.1 Disclaimer of Certain Damages. IN NO EVENT SHALL YOU OR ELASTICSEARCH OR ITS LICENSORS BE LIABLE FOR ANY LOSS OF +PROFITS, LOSS OF USE, BUSINESS INTERRUPTION, LOSS OF DATA, COST OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT OR +UNFORESEEABLE DAMAGES OF ANY KIND IN CONNECTION WITH OR ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE, OR THE +PERFORMANCE OF OR FAILURE TO PERFORM THIS AGREEMENT, WHETHER ALLEGED AS A BREACH OF CONTRACT OR TORTIOUS CONDUCT, +INCLUDING NEGLIGENCE. THE LIMITATIONS OF LIABILITY SET FORTH IN THIS SECTION 4.1 SHALL NOT APPLY TO A BREACH, THROUGH +GROSS NEGLIGENCE OR INTENTIONAL MISCONDUCT BY YOU, OF THE SCOPE OF THE LICENSE GRANTED IN SECTION 1.1, OR IN CASE OF +DEATH OR PERSONAL INJURY. +(6) In addition, for Customers with principal offices within Australia, Sections 4.1, 4.2 and 4.3 of the Agreement +are deleted and replaced with the following new Sections 4.1, 4.2 and 4.3: +4.1 Disclaimer of Certain Damages. Subject to clause 4.3, a party is not liable for Consequential Loss however +caused (including by the negligence of that party) suffered or incurred by the other party in connection with this +agreement. “Consequential Loss†means loss of revenues, loss of reputation, indirect loss, loss of profits, +consequential loss, loss of actual or anticipated savings, indirect loss, lost opportunities, including opportunities to +enter into arrangements with third parties, loss or damage in connection with claims against by third parties, or loss +or corruption or data. +4.2 Damages Cap. SUBJECT TO CLAUSES 4.1 AND 4.3, ANY LIABILITY OF ELASTICSEARCH FOR ANY LOSS OR DAMAGE, HOWEVER +CAUSED (INCLUDING BY THE NEGLIGENCE OF ELASTICSEARCH), SUFFERED BY YOU IN CONNECTION WITH THIS AGREEMENT IS LIMITED TO +THE AMOUNT YOU PAID, IN THE TWELVE (12) MONTHS IMMEDIATELY PRIOR TO THE EVENT GIVING RISE TO LIABILITY, UNDER THE +ELASTICSEARCH SUPPORT SERVICES AGREEMENT IN CONNECTION WITH WHICH YOU OBTAINED THE LICENSE TO USE THE SOFTWARE. THE +LIMITATION SET OUT IN THIS SECTION 4.2 IS AN AGGREGATE LIMIT FOR ALL CLAIMS, WHENEVER MADE. +4.3 Limitation and Disclaimer Exceptions. If the Competition and Consumer Act 2010 (Cth) or any other legislation or +any other legislation states that there is a guarantee in relation to any good or service supplied by Elasticsearch in +connection with this agreement, and Elasticsearch’s liability for failing to comply with that guarantee cannot be +excluded but may be limited, Sections 4.1 and 4.2 do not apply to that liability and instead Elasticsearch’s liability +for such failure is limited (at Elasticsearch’s election) to, in the case of a supply of goods, the Elasticsearch +replacing the goods or supplying equivalent goods or repairing the goods, or in the case of a supply of services, +Elasticsearch supplying the services again or paying the cost of having the services supplied again. +(7) In addition, for Customers with principal offices within Japan, Sections 1.2, 3 and 4.1 of the Agreement are +deleted and replaced with the following new Sections 1.2, 3.3 and 4.1: +1.2 Reservation of Rights; Restrictions. As between Elasticsearch and You, Elasticsearch owns all right title and +interest in and to the Software and any derivative works thereof, and except as expressly set forth in Section 1.1 +above, no other license to the Software is granted to You by implication or otherwise. You agree not to: (i) prepare +derivative works from, modify, copy or use the Software in any manner except as expressly permitted in this Agreement or +applicable law; (ii) transfer, sell, rent, lease, distribute, sublicense, loan or otherwise transfer the Software in +whole or in part to any third party; (iii) use the Software for providing time-sharing services, any +software-as-a-service offering (“SaaSâ€), service bureau services or as part of an application services provider or other +service offering; (iv) alter or remove any proprietary notices in the Software; or (v) make available to any third party +any analysis of the results of operation of the Software, including benchmarking results, without the prior written +consent of Elasticsearch. +3.3 Warranty Disclaimer. TO THE MAXIMUM EXTENT PERMITTED UNDER APPLICABLE LAW, THE SOFTWARE IS PROVIDED “AS IS†+WITHOUT WARRANTY OF ANY KIND, AND ELASTICSEARCH AND ITS LICENSORS MAKE NO WARRANTIES WHETHER EXPRESSED, IMPLIED OR +STATUTORY REGARDING OR RELATING TO THE SOFTWARE OR DOCUMENTATION. TO THE MAXIMUM EXTENT PERMITTED UNDER APPLICABLE LAW, +ELASTICSEARCH AND ITS LICENSORS SPECIFICALLY DISCLAIM ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NON-INFRINGEMENT WITH RESPECT TO THE SOFTWARE AND DOCUMENTATION, AND WITH RESPECT TO THE USE OF +THE FOREGOING. FURTHER, ELASTICSEARCH DOES NOT WARRANT RESULTS OF USE OR THAT THE SOFTWARE WILL BE ERROR FREE OR THAT +THE USE OF THE SOFTWARE WILL BE UNINTERRUPTED. +4.1 Disclaimer of Certain Damages. IN NO EVENT SHALL YOU OR ELASTICSEARCH OR ITS LICENSORS BE LIABLE FOR ANY LOSS OF +PROFITS, LOSS OF USE, BUSINESS INTERRUPTION, LOSS OF DATA, COST OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY +SPECIALINDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND IN CONNECTION WITH OR ARISING OUT OF THE USE +OR INABILITY TO USE THE SOFTWARE, OR THE PERFORMANCE OF OR FAILURE TO PERFORM THIS AGREEMENT, WHETHER ALLEGED AS A +BREACH OF CONTRACT OR TORTIOUS CONDUCT, INCLUDING NEGLIGENCE, EVEN IF THE RESPONSIBLE PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. THE LIMITATIONS OF LIABILITY SET FORTH IN THIS SECTION 4.1 SHALL NOT APPLY TO A BREACH +THROUGH GROSS NEGLIGENCE OR INTENTIONAL MISCONDUCT BY YOU OF THE SCOPE OF THE LICENSE GRANTED IN SECTION 1.1 OR TO ANY +OTHER LIABILITY THAT CANNOT BE EXCLUDED OR LIMITED UNDER APPLICABLE LAW. \ No newline at end of file diff --git a/elasticsearch/x-pack/marvel/NOTICE.txt b/elasticsearch/x-pack/marvel/NOTICE.txt new file mode 100644 index 00000000000..bd58384daf2 --- /dev/null +++ b/elasticsearch/x-pack/marvel/NOTICE.txt @@ -0,0 +1,6 @@ +Elasticsearch License +Copyright 2009-2015 Elastic + +--- +This product includes software developed by The Apache Software +Foundation (http://www.apache.org/). \ No newline at end of file diff --git a/marvel/src/main/java/org/elasticsearch/marvel/MarvelPlugin.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/MarvelPlugin.java similarity index 97% rename from marvel/src/main/java/org/elasticsearch/marvel/MarvelPlugin.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/MarvelPlugin.java index 55a0404104d..16103e91310 100644 --- a/marvel/src/main/java/org/elasticsearch/marvel/MarvelPlugin.java +++ b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/MarvelPlugin.java @@ -28,6 +28,7 @@ import org.elasticsearch.marvel.shield.MarvelShieldModule; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.shield.authz.AuthorizationModule; import org.elasticsearch.tribe.TribeService; +import org.elasticsearch.xpack.XPackPlugin; import java.util.Arrays; import java.util.Collection; @@ -36,7 +37,7 @@ import java.util.Map; public class MarvelPlugin extends Plugin { - private static final ESLogger logger = Loggers.getLogger(MarvelPlugin.class); + private static final ESLogger logger = Loggers.getLogger(XPackPlugin.class); public static final String NAME = "marvel"; public static final String ENABLED = NAME + ".enabled"; diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/AgentService.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/AgentService.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/AgentService.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/AgentService.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/AbstractCollector.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/AbstractCollector.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/collector/AbstractCollector.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/AbstractCollector.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/Collector.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/Collector.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/collector/Collector.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/Collector.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/CollectorModule.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/CollectorModule.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/collector/CollectorModule.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/CollectorModule.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterInfoCollector.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterInfoCollector.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterInfoCollector.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterInfoCollector.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterInfoMarvelDoc.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterInfoMarvelDoc.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterInfoMarvelDoc.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterInfoMarvelDoc.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStateCollector.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStateCollector.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStateCollector.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStateCollector.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStateMarvelDoc.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStateMarvelDoc.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStateMarvelDoc.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStateMarvelDoc.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStateNodeMarvelDoc.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStateNodeMarvelDoc.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStateNodeMarvelDoc.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStateNodeMarvelDoc.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStatsCollector.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStatsCollector.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStatsCollector.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStatsCollector.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStatsMarvelDoc.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStatsMarvelDoc.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStatsMarvelDoc.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStatsMarvelDoc.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/DiscoveryNodeMarvelDoc.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/DiscoveryNodeMarvelDoc.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/DiscoveryNodeMarvelDoc.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/DiscoveryNodeMarvelDoc.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/indices/IndexRecoveryCollector.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/indices/IndexRecoveryCollector.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/collector/indices/IndexRecoveryCollector.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/indices/IndexRecoveryCollector.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/indices/IndexRecoveryMarvelDoc.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/indices/IndexRecoveryMarvelDoc.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/collector/indices/IndexRecoveryMarvelDoc.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/indices/IndexRecoveryMarvelDoc.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/indices/IndexStatsCollector.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/indices/IndexStatsCollector.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/collector/indices/IndexStatsCollector.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/indices/IndexStatsCollector.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/indices/IndexStatsMarvelDoc.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/indices/IndexStatsMarvelDoc.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/collector/indices/IndexStatsMarvelDoc.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/indices/IndexStatsMarvelDoc.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/indices/IndicesStatsCollector.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/indices/IndicesStatsCollector.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/collector/indices/IndicesStatsCollector.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/indices/IndicesStatsCollector.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/indices/IndicesStatsMarvelDoc.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/indices/IndicesStatsMarvelDoc.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/collector/indices/IndicesStatsMarvelDoc.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/indices/IndicesStatsMarvelDoc.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/node/NodeStatsCollector.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/node/NodeStatsCollector.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/collector/node/NodeStatsCollector.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/node/NodeStatsCollector.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/node/NodeStatsMarvelDoc.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/node/NodeStatsMarvelDoc.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/collector/node/NodeStatsMarvelDoc.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/node/NodeStatsMarvelDoc.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/shards/ShardMarvelDoc.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/shards/ShardMarvelDoc.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/collector/shards/ShardMarvelDoc.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/shards/ShardMarvelDoc.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/shards/ShardsCollector.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/shards/ShardsCollector.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/collector/shards/ShardsCollector.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/shards/ShardsCollector.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/ExportBulk.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/ExportBulk.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/ExportBulk.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/ExportBulk.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/Exporter.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/Exporter.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/Exporter.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/Exporter.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/ExporterModule.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/ExporterModule.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/ExporterModule.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/ExporterModule.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/Exporters.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/Exporters.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/Exporters.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/Exporters.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/IndexNameResolver.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/IndexNameResolver.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/IndexNameResolver.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/IndexNameResolver.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/MarvelDoc.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/MarvelDoc.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/MarvelDoc.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/MarvelDoc.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/MarvelTemplateUtils.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/MarvelTemplateUtils.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/MarvelTemplateUtils.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/MarvelTemplateUtils.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/http/HttpExporter.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/http/HttpExporter.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/http/HttpExporter.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/http/HttpExporter.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/http/HttpExporterUtils.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/http/HttpExporterUtils.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/http/HttpExporterUtils.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/http/HttpExporterUtils.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/local/LocalBulk.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/local/LocalBulk.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/local/LocalBulk.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/local/LocalBulk.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/local/LocalExporter.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/local/LocalExporter.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/local/LocalExporter.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/exporter/local/LocalExporter.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/AbstractRenderer.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/AbstractRenderer.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/AbstractRenderer.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/AbstractRenderer.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/Renderer.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/Renderer.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/Renderer.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/Renderer.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/RendererModule.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/RendererModule.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/RendererModule.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/RendererModule.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/RendererRegistry.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/RendererRegistry.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/RendererRegistry.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/RendererRegistry.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterInfoRenderer.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterInfoRenderer.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterInfoRenderer.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterInfoRenderer.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStateNodeRenderer.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStateNodeRenderer.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStateNodeRenderer.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStateNodeRenderer.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStateRenderer.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStateRenderer.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStateRenderer.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStateRenderer.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStatsRenderer.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStatsRenderer.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStatsRenderer.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStatsRenderer.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/DiscoveryNodeRenderer.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/DiscoveryNodeRenderer.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/DiscoveryNodeRenderer.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/DiscoveryNodeRenderer.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/indices/IndexRecoveryRenderer.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/indices/IndexRecoveryRenderer.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/indices/IndexRecoveryRenderer.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/indices/IndexRecoveryRenderer.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/indices/IndexStatsRenderer.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/indices/IndexStatsRenderer.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/indices/IndexStatsRenderer.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/indices/IndexStatsRenderer.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/indices/IndicesStatsRenderer.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/indices/IndicesStatsRenderer.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/indices/IndicesStatsRenderer.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/indices/IndicesStatsRenderer.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/node/NodeStatsRenderer.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/node/NodeStatsRenderer.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/node/NodeStatsRenderer.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/node/NodeStatsRenderer.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/shards/ShardsRenderer.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/shards/ShardsRenderer.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/shards/ShardsRenderer.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/shards/ShardsRenderer.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/settings/MarvelModule.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/settings/MarvelModule.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/settings/MarvelModule.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/settings/MarvelModule.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/settings/MarvelSetting.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/settings/MarvelSetting.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/settings/MarvelSetting.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/settings/MarvelSetting.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/settings/MarvelSettings.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/settings/MarvelSettings.java similarity index 99% rename from marvel/src/main/java/org/elasticsearch/marvel/agent/settings/MarvelSettings.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/settings/MarvelSettings.java index 682b0c2e657..d1c52a0fae7 100644 --- a/marvel/src/main/java/org/elasticsearch/marvel/agent/settings/MarvelSettings.java +++ b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/agent/settings/MarvelSettings.java @@ -12,6 +12,7 @@ import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.marvel.MarvelPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.node.settings.NodeSettingsService; import java.util.Collection; diff --git a/marvel/src/main/java/org/elasticsearch/marvel/license/LicenseModule.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/license/LicenseModule.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/license/LicenseModule.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/license/LicenseModule.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/license/MarvelLicensee.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/license/MarvelLicensee.java similarity index 98% rename from marvel/src/main/java/org/elasticsearch/marvel/license/MarvelLicensee.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/license/MarvelLicensee.java index defa53de700..c3821c3d27a 100644 --- a/marvel/src/main/java/org/elasticsearch/marvel/license/MarvelLicensee.java +++ b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/license/MarvelLicensee.java @@ -12,6 +12,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.license.core.License; import org.elasticsearch.license.plugin.core.*; import org.elasticsearch.marvel.MarvelPlugin; +import org.elasticsearch.xpack.XPackPlugin; public class MarvelLicensee extends AbstractLicenseeComponent implements Licensee { diff --git a/marvel/src/main/java/org/elasticsearch/marvel/shield/MarvelInternalUserHolder.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/shield/MarvelInternalUserHolder.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/shield/MarvelInternalUserHolder.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/shield/MarvelInternalUserHolder.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/shield/MarvelSettingsFilter.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/shield/MarvelSettingsFilter.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/shield/MarvelSettingsFilter.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/shield/MarvelSettingsFilter.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/shield/MarvelShieldIntegration.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/shield/MarvelShieldIntegration.java similarity index 98% rename from marvel/src/main/java/org/elasticsearch/marvel/shield/MarvelShieldIntegration.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/shield/MarvelShieldIntegration.java index 819718e2681..812828d4110 100644 --- a/marvel/src/main/java/org/elasticsearch/marvel/shield/MarvelShieldIntegration.java +++ b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/shield/MarvelShieldIntegration.java @@ -11,6 +11,7 @@ import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.inject.Injector; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.ShieldSettingsFilter; import org.elasticsearch.shield.authc.AuthenticationService; import org.elasticsearch.transport.TransportMessage; diff --git a/marvel/src/main/java/org/elasticsearch/marvel/shield/MarvelShieldModule.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/shield/MarvelShieldModule.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/shield/MarvelShieldModule.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/shield/MarvelShieldModule.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/shield/SecuredClient.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/shield/SecuredClient.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/shield/SecuredClient.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/shield/SecuredClient.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/support/VersionUtils.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/support/VersionUtils.java similarity index 100% rename from marvel/src/main/java/org/elasticsearch/marvel/support/VersionUtils.java rename to elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/support/VersionUtils.java diff --git a/marvel/src/main/resources/marvel_index_template.json b/elasticsearch/x-pack/marvel/src/main/resources/marvel_index_template.json similarity index 100% rename from marvel/src/main/resources/marvel_index_template.json rename to elasticsearch/x-pack/marvel/src/main/resources/marvel_index_template.json diff --git a/marvel/src/test/java/org/elasticsearch/marvel/MarvelF.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/MarvelF.java similarity index 90% rename from marvel/src/test/java/org/elasticsearch/marvel/MarvelF.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/MarvelF.java index 28f544d3edf..825c227b5a8 100644 --- a/marvel/src/test/java/org/elasticsearch/marvel/MarvelF.java +++ b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/MarvelF.java @@ -8,10 +8,10 @@ package org.elasticsearch.marvel; import org.elasticsearch.Version; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.CollectionUtils; -import org.elasticsearch.license.plugin.LicensePlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.node.MockNode; import org.elasticsearch.node.Node; -import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import java.util.Arrays; import java.util.concurrent.CountDownLatch; @@ -38,7 +38,7 @@ public class MarvelF { } final CountDownLatch latch = new CountDownLatch(1); - final Node node = new MockNode(settings.build(), Version.CURRENT, Arrays.asList(MarvelPlugin.class, LicensePlugin.class, ShieldPlugin.class)); + final Node node = new MockNode(settings.build(), Version.CURRENT, Arrays.asList(XPackPlugin.class, XPackPlugin.class, XPackPlugin.class)); Runtime.getRuntime().addShutdownHook(new Thread() { @Override diff --git a/marvel/src/test/java/org/elasticsearch/marvel/MarvelPluginClientTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/MarvelPluginClientTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/MarvelPluginClientTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/MarvelPluginClientTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/MarvelPluginTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/MarvelPluginTests.java similarity index 94% rename from marvel/src/test/java/org/elasticsearch/marvel/MarvelPluginTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/MarvelPluginTests.java index a366d5aec76..9de1859b940 100644 --- a/marvel/src/test/java/org/elasticsearch/marvel/MarvelPluginTests.java +++ b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/MarvelPluginTests.java @@ -13,6 +13,7 @@ import org.elasticsearch.marvel.test.MarvelIntegTestCase; import org.elasticsearch.plugins.PluginInfo; import org.elasticsearch.test.ESIntegTestCase.ClusterScope; import org.elasticsearch.tribe.TribeService; +import org.elasticsearch.xpack.XPackPlugin; import static org.elasticsearch.test.ESIntegTestCase.Scope.TEST; import static org.hamcrest.Matchers.equalTo; @@ -53,12 +54,12 @@ public class MarvelPluginTests extends MarvelIntegTestCase { for (PluginInfo plugin : nodeInfo.getPlugins().getPluginInfos()) { assertNotNull(plugin); - if (MarvelPlugin.NAME.equals(plugin.getName())) { + if (XPackPlugin.NAME.equals(plugin.getName())) { found = true; break; } } - assertThat("marvel plugin not found", found, equalTo(true)); + assertThat("x-pack plugin not found", found, equalTo(true)); } } diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/AbstractCollectorTestCase.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/AbstractCollectorTestCase.java similarity index 89% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/collector/AbstractCollectorTestCase.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/AbstractCollectorTestCase.java index d2557f58e35..49ccbd0b29f 100644 --- a/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/AbstractCollectorTestCase.java +++ b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/AbstractCollectorTestCase.java @@ -7,29 +7,31 @@ package org.elasticsearch.marvel.agent.collector; import com.carrotsearch.randomizedtesting.RandomizedTest; import com.carrotsearch.randomizedtesting.SysGlobals; -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse; +import org.elasticsearch.action.ActionModule; import org.elasticsearch.cluster.block.ClusterBlocks; import org.elasticsearch.common.component.AbstractComponent; +import org.elasticsearch.common.component.LifecycleComponent; import org.elasticsearch.common.inject.AbstractModule; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.inject.Module; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.license.core.License; -import org.elasticsearch.license.plugin.action.delete.DeleteLicenseRequest; -import org.elasticsearch.license.plugin.action.put.PutLicenseRequest; -import org.elasticsearch.license.plugin.core.*; -import org.elasticsearch.marvel.MarvelPlugin; +import org.elasticsearch.license.plugin.LicensePlugin; +import org.elasticsearch.license.plugin.core.LicenseState; +import org.elasticsearch.license.plugin.core.Licensee; +import org.elasticsearch.license.plugin.core.LicenseeRegistry; +import org.elasticsearch.license.plugin.core.LicensesManagerService; import org.elasticsearch.marvel.agent.settings.MarvelSettings; import org.elasticsearch.marvel.shield.MarvelShieldIntegration; import org.elasticsearch.marvel.shield.SecuredClient; import org.elasticsearch.marvel.test.MarvelIntegTestCase; import org.elasticsearch.node.Node; import org.elasticsearch.plugins.Plugin; -import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.rest.RestModule; import org.elasticsearch.test.ESIntegTestCase; import org.elasticsearch.test.ESIntegTestCase.ClusterScope; +import org.elasticsearch.xpack.XPackPlugin; import org.junit.Before; import java.util.*; @@ -41,10 +43,7 @@ public class AbstractCollectorTestCase extends MarvelIntegTestCase { @Override protected Collection> nodePlugins() { - if (shieldEnabled) { - return Arrays.asList(LicensePluginForCollectors.class, MarvelPlugin.class, ShieldPlugin.class); - } - return Arrays.asList(LicensePluginForCollectors.class, MarvelPlugin.class); + return Arrays.asList(InternalXPackPlugin.class); } @Override @@ -181,18 +180,10 @@ public class AbstractCollectorTestCase extends MarvelIntegTestCase { }, 30L, TimeUnit.SECONDS); } - public static class LicensePluginForCollectors extends Plugin { + public static class InternalLicensePlugin extends LicensePlugin { - public static final String NAME = "internal-test-licensing"; - - @Override - public String name() { - return NAME; - } - - @Override - public String description() { - return name(); + public InternalLicensePlugin() { + super(Settings.EMPTY); } @Override @@ -208,6 +199,27 @@ public class AbstractCollectorTestCase extends MarvelIntegTestCase { } }); } + + @Override + public void onModule(RestModule module) { + } + + @Override + public void onModule(ActionModule module) { + } + + @Override + public Collection> nodeServices() { + return Collections.emptyList(); + } + } + + public static class InternalXPackPlugin extends XPackPlugin { + + public InternalXPackPlugin(Settings settings) { + super(settings); + licensePlugin = new InternalLicensePlugin(); + } } public static class LicenseServiceForCollectors extends AbstractComponent implements LicenseeRegistry { diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterInfoCollectorTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterInfoCollectorTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterInfoCollectorTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterInfoCollectorTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStateCollectorTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStateCollectorTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStateCollectorTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStateCollectorTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStatsCollectorTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStatsCollectorTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStatsCollectorTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStatsCollectorTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/indices/IndexRecoveryCollectorTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/indices/IndexRecoveryCollectorTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/collector/indices/IndexRecoveryCollectorTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/indices/IndexRecoveryCollectorTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/indices/IndexStatsCollectorTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/indices/IndexStatsCollectorTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/collector/indices/IndexStatsCollectorTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/indices/IndexStatsCollectorTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/indices/IndicesStatsCollectorTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/indices/IndicesStatsCollectorTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/collector/indices/IndicesStatsCollectorTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/indices/IndicesStatsCollectorTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/node/NodeStatsCollectorTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/node/NodeStatsCollectorTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/collector/node/NodeStatsCollectorTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/node/NodeStatsCollectorTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/shards/ShardsCollectorTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/shards/ShardsCollectorTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/collector/shards/ShardsCollectorTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/shards/ShardsCollectorTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/exporter/ExportersTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/exporter/ExportersTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/exporter/ExportersTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/exporter/ExportersTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/exporter/http/HttpExporterTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/exporter/http/HttpExporterTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/exporter/http/HttpExporterTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/exporter/http/HttpExporterTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/exporter/http/HttpExporterUtilsTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/exporter/http/HttpExporterUtilsTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/exporter/http/HttpExporterUtilsTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/exporter/http/HttpExporterUtilsTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/exporter/local/LocalExporterTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/exporter/local/LocalExporterTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/exporter/local/LocalExporterTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/exporter/local/LocalExporterTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/RendererTestUtils.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/RendererTestUtils.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/RendererTestUtils.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/RendererTestUtils.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterInfoTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterInfoTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterInfoTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterInfoTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStateRendererTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStateRendererTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStateRendererTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStateRendererTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStateTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStateTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStateTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStateTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStatsRendererTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStatsRendererTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStatsRendererTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStatsRendererTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStatsTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStatsTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStatsTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStatsTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/indices/IndexRecoveryRendererTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/indices/IndexRecoveryRendererTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/indices/IndexRecoveryRendererTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/indices/IndexRecoveryRendererTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/indices/IndexRecoveryTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/indices/IndexRecoveryTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/indices/IndexRecoveryTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/indices/IndexRecoveryTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/indices/IndexStatsRendererTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/indices/IndexStatsRendererTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/indices/IndexStatsRendererTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/indices/IndexStatsRendererTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/indices/IndexStatsTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/indices/IndexStatsTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/indices/IndexStatsTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/indices/IndexStatsTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/indices/IndicesStatsRendererTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/indices/IndicesStatsRendererTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/indices/IndicesStatsRendererTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/indices/IndicesStatsRendererTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/indices/IndicesStatsTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/indices/IndicesStatsTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/indices/IndicesStatsTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/indices/IndicesStatsTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/node/MultiNodesStatsTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/node/MultiNodesStatsTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/node/MultiNodesStatsTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/node/MultiNodesStatsTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/node/NodeStatsRendererTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/node/NodeStatsRendererTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/node/NodeStatsRendererTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/node/NodeStatsRendererTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/node/NodeStatsTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/node/NodeStatsTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/node/NodeStatsTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/node/NodeStatsTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/shards/ShardsRendererTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/shards/ShardsRendererTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/shards/ShardsRendererTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/shards/ShardsRendererTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/shards/ShardsTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/shards/ShardsTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/shards/ShardsTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/shards/ShardsTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/settings/MarvelSettingTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/settings/MarvelSettingTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/settings/MarvelSettingTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/settings/MarvelSettingTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/settings/MarvelSettingsTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/settings/MarvelSettingsTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/agent/settings/MarvelSettingsTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/agent/settings/MarvelSettingsTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/license/LicenseIntegrationTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/license/LicenseIntegrationTests.java similarity index 82% rename from marvel/src/test/java/org/elasticsearch/marvel/license/LicenseIntegrationTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/license/LicenseIntegrationTests.java index d5fd177d862..150eb3c766c 100644 --- a/marvel/src/test/java/org/elasticsearch/marvel/license/LicenseIntegrationTests.java +++ b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/license/LicenseIntegrationTests.java @@ -5,20 +5,26 @@ */ package org.elasticsearch.marvel.license; +import org.elasticsearch.action.ActionModule; import org.elasticsearch.common.component.AbstractComponent; +import org.elasticsearch.common.component.LifecycleComponent; import org.elasticsearch.common.inject.AbstractModule; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.inject.Module; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.index.IndexModule; +import org.elasticsearch.index.IndexService; import org.elasticsearch.license.core.License; +import org.elasticsearch.license.plugin.LicensePlugin; import org.elasticsearch.license.plugin.core.LicenseState; import org.elasticsearch.license.plugin.core.Licensee; import org.elasticsearch.license.plugin.core.LicenseeRegistry; import org.elasticsearch.license.plugin.core.LicensesManagerService; -import org.elasticsearch.marvel.MarvelPlugin; +import org.elasticsearch.rest.RestModule; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.marvel.test.MarvelIntegTestCase; import org.elasticsearch.plugins.Plugin; -import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.test.ESIntegTestCase.ClusterScope; import java.util.ArrayList; @@ -36,10 +42,7 @@ import static org.hamcrest.Matchers.isOneOf; public class LicenseIntegrationTests extends MarvelIntegTestCase { @Override protected Collection> nodePlugins() { - if (shieldEnabled) { - return Arrays.asList(MockLicensePlugin.class, MarvelPlugin.class, ShieldPlugin.class); - } - return Arrays.asList(MockLicensePlugin.class, MarvelPlugin.class); + return Arrays.asList(InternalXPackPlugin.class); } @Override @@ -80,13 +83,10 @@ public class LicenseIntegrationTests extends MarvelIntegTestCase { } } - public static class MockLicensePlugin extends Plugin { + public static class MockLicensePlugin extends LicensePlugin { - public static final String NAME = "internal-test-licensing"; - - @Override - public String name() { - return NAME; + public MockLicensePlugin() { + super(Settings.EMPTY); } @Override @@ -98,6 +98,20 @@ public class LicenseIntegrationTests extends MarvelIntegTestCase { public Collection nodeModules() { return Collections.singletonList(new InternalLicenseModule()); } + + @Override + public void onModule(RestModule module) { + } + + @Override + public void onModule(ActionModule module) { + } + + @Override + public Collection> nodeServices() { + return Collections.emptyList(); + } + } public static class InternalLicenseModule extends AbstractModule { @@ -151,4 +165,11 @@ public class LicenseIntegrationTests extends MarvelIntegTestCase { return null; } } + + public static class InternalXPackPlugin extends XPackPlugin { + public InternalXPackPlugin(Settings settings) { + super(settings); + licensePlugin = new MockLicensePlugin(); + } + } } diff --git a/marvel/src/test/java/org/elasticsearch/marvel/support/VersionUtilsTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/support/VersionUtilsTests.java similarity index 100% rename from marvel/src/test/java/org/elasticsearch/marvel/support/VersionUtilsTests.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/support/VersionUtilsTests.java diff --git a/marvel/src/test/java/org/elasticsearch/marvel/test/MarvelIntegTestCase.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/test/MarvelIntegTestCase.java similarity index 97% rename from marvel/src/test/java/org/elasticsearch/marvel/test/MarvelIntegTestCase.java rename to elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/test/MarvelIntegTestCase.java index 2f25f15b2a9..7dac83909f3 100644 --- a/marvel/src/test/java/org/elasticsearch/marvel/test/MarvelIntegTestCase.java +++ b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/test/MarvelIntegTestCase.java @@ -18,8 +18,6 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.CountDown; import org.elasticsearch.index.IndexModule; import org.elasticsearch.index.IndexNotFoundException; -import org.elasticsearch.license.plugin.LicensePlugin; -import org.elasticsearch.marvel.MarvelPlugin; import org.elasticsearch.marvel.agent.AgentService; import org.elasticsearch.marvel.agent.exporter.MarvelTemplateUtils; import org.elasticsearch.marvel.agent.settings.MarvelSettings; @@ -31,6 +29,7 @@ import org.elasticsearch.shield.authc.support.SecuredString; import org.elasticsearch.shield.crypto.InternalCryptoService; import org.elasticsearch.test.ESIntegTestCase; import org.elasticsearch.test.TestCluster; +import org.elasticsearch.xpack.XPackPlugin; import org.hamcrest.Matcher; import org.jboss.netty.util.internal.SystemPropertyUtil; @@ -71,6 +70,10 @@ public abstract class MarvelIntegTestCase extends ESIntegTestCase { protected Settings nodeSettings(int nodeOrdinal) { Settings.Builder builder = Settings.builder() .put(super.nodeSettings(nodeOrdinal)) + + //TODO: for now lets isolate marvel tests from watcher (randomize this later) + .put("watcher.enabled", false) + // we do this by default in core, but for marvel this isn't needed and only adds noise. .put("index.store.mock.check_index_on_close", false); @@ -88,15 +91,14 @@ public abstract class MarvelIntegTestCase extends ESIntegTestCase { .put("shield.user", "test:changeme") .build(); } - return super.transportClientSettings(); + return Settings.builder().put(super.transportClientSettings()) + .put("shield.enabled", false) + .build(); } @Override protected Collection> nodePlugins() { - if (shieldEnabled) { - return Arrays.asList(LicensePlugin.class, MarvelPlugin.class, ShieldPlugin.class); - } - return Arrays.asList(LicensePlugin.class, MarvelPlugin.class); + return Collections.singletonList(XPackPlugin.class); } @Override diff --git a/marvel/src/test/resources/log4j.properties b/elasticsearch/x-pack/marvel/src/test/resources/log4j.properties similarity index 100% rename from marvel/src/test/resources/log4j.properties rename to elasticsearch/x-pack/marvel/src/test/resources/log4j.properties diff --git a/marvel/src/test/resources/samples/cluster_state.json b/elasticsearch/x-pack/marvel/src/test/resources/samples/cluster_state.json similarity index 100% rename from marvel/src/test/resources/samples/cluster_state.json rename to elasticsearch/x-pack/marvel/src/test/resources/samples/cluster_state.json diff --git a/marvel/src/test/resources/samples/cluster_stats.json b/elasticsearch/x-pack/marvel/src/test/resources/samples/cluster_stats.json similarity index 100% rename from marvel/src/test/resources/samples/cluster_stats.json rename to elasticsearch/x-pack/marvel/src/test/resources/samples/cluster_stats.json diff --git a/marvel/src/test/resources/samples/index_recovery.json b/elasticsearch/x-pack/marvel/src/test/resources/samples/index_recovery.json similarity index 100% rename from marvel/src/test/resources/samples/index_recovery.json rename to elasticsearch/x-pack/marvel/src/test/resources/samples/index_recovery.json diff --git a/marvel/src/test/resources/samples/index_stats.json b/elasticsearch/x-pack/marvel/src/test/resources/samples/index_stats.json similarity index 100% rename from marvel/src/test/resources/samples/index_stats.json rename to elasticsearch/x-pack/marvel/src/test/resources/samples/index_stats.json diff --git a/marvel/src/test/resources/samples/indices_stats.json b/elasticsearch/x-pack/marvel/src/test/resources/samples/indices_stats.json similarity index 100% rename from marvel/src/test/resources/samples/indices_stats.json rename to elasticsearch/x-pack/marvel/src/test/resources/samples/indices_stats.json diff --git a/marvel/src/test/resources/samples/node_stats.json b/elasticsearch/x-pack/marvel/src/test/resources/samples/node_stats.json similarity index 100% rename from marvel/src/test/resources/samples/node_stats.json rename to elasticsearch/x-pack/marvel/src/test/resources/samples/node_stats.json diff --git a/marvel/src/test/resources/samples/shards.json b/elasticsearch/x-pack/marvel/src/test/resources/samples/shards.json similarity index 100% rename from marvel/src/test/resources/samples/shards.json rename to elasticsearch/x-pack/marvel/src/test/resources/samples/shards.json diff --git a/shield/LICENSE.txt b/elasticsearch/x-pack/shield/LICENSE.txt similarity index 100% rename from shield/LICENSE.txt rename to elasticsearch/x-pack/shield/LICENSE.txt diff --git a/shield/NOTICE.txt b/elasticsearch/x-pack/shield/NOTICE.txt similarity index 100% rename from shield/NOTICE.txt rename to elasticsearch/x-pack/shield/NOTICE.txt diff --git a/shield/README.asciidoc b/elasticsearch/x-pack/shield/README.asciidoc similarity index 100% rename from shield/README.asciidoc rename to elasticsearch/x-pack/shield/README.asciidoc diff --git a/shield/TESTING.asciidoc b/elasticsearch/x-pack/shield/TESTING.asciidoc similarity index 100% rename from shield/TESTING.asciidoc rename to elasticsearch/x-pack/shield/TESTING.asciidoc diff --git a/shield/bin/shield/.in.bat b/elasticsearch/x-pack/shield/bin/shield/.in.bat similarity index 99% rename from shield/bin/shield/.in.bat rename to elasticsearch/x-pack/shield/bin/shield/.in.bat index b2935f48214..3fd70a04222 100644 Binary files a/shield/bin/shield/.in.bat and b/elasticsearch/x-pack/shield/bin/shield/.in.bat differ diff --git a/shield/bin/shield/esusers b/elasticsearch/x-pack/shield/bin/shield/esusers similarity index 98% rename from shield/bin/shield/esusers rename to elasticsearch/x-pack/shield/bin/shield/esusers index 61c0553760d..2c859bc5159 100755 --- a/shield/bin/shield/esusers +++ b/elasticsearch/x-pack/shield/bin/shield/esusers @@ -123,7 +123,7 @@ fi export HOSTNAME=`hostname -s` # include shield jars in classpath -ES_CLASSPATH="$ES_CLASSPATH:$ES_HOME/plugins/shield/*" +ES_CLASSPATH="$ES_CLASSPATH:$ES_HOME/plugins/x-pack/*" cd "$ES_HOME" > /dev/null "$JAVA" $ES_JAVA_OPTS -cp "$ES_CLASSPATH" -Des.path.home="$ES_HOME" $properties org.elasticsearch.shield.authc.esusers.tool.ESUsersTool "$@" diff --git a/shield/bin/shield/esusers.bat b/elasticsearch/x-pack/shield/bin/shield/esusers.bat similarity index 100% rename from shield/bin/shield/esusers.bat rename to elasticsearch/x-pack/shield/bin/shield/esusers.bat diff --git a/shield/bin/shield/syskeygen b/elasticsearch/x-pack/shield/bin/shield/syskeygen similarity index 98% rename from shield/bin/shield/syskeygen rename to elasticsearch/x-pack/shield/bin/shield/syskeygen index 726a729fc01..e79f97c3648 100755 --- a/shield/bin/shield/syskeygen +++ b/elasticsearch/x-pack/shield/bin/shield/syskeygen @@ -123,7 +123,7 @@ fi export HOSTNAME=`hostname -s` # include shield jars in classpath -ES_CLASSPATH="$ES_CLASSPATH:$ES_HOME/plugins/shield/*" +ES_CLASSPATH="$ES_CLASSPATH:$ES_HOME/plugins/x-pack/*" cd "$ES_HOME" > /dev/null $JAVA $ES_JAVA_OPTS -cp "$ES_CLASSPATH" -Des.path.home="$ES_HOME" $properties org.elasticsearch.shield.crypto.tool.SystemKeyTool "$@" diff --git a/shield/bin/shield/syskeygen.bat b/elasticsearch/x-pack/shield/bin/shield/syskeygen.bat similarity index 100% rename from shield/bin/shield/syskeygen.bat rename to elasticsearch/x-pack/shield/bin/shield/syskeygen.bat diff --git a/shield/config/shield/logging.yml b/elasticsearch/x-pack/shield/config/shield/logging.yml similarity index 100% rename from shield/config/shield/logging.yml rename to elasticsearch/x-pack/shield/config/shield/logging.yml diff --git a/shield/config/shield/users b/elasticsearch/x-pack/shield/config/shield/role_mapping.yml similarity index 100% rename from shield/config/shield/users rename to elasticsearch/x-pack/shield/config/shield/role_mapping.yml diff --git a/shield/config/shield/roles.yml b/elasticsearch/x-pack/shield/config/shield/roles.yml similarity index 100% rename from shield/config/shield/roles.yml rename to elasticsearch/x-pack/shield/config/shield/roles.yml diff --git a/shield/config/shield/users_roles b/elasticsearch/x-pack/shield/config/shield/users similarity index 100% rename from shield/config/shield/users_roles rename to elasticsearch/x-pack/shield/config/shield/users diff --git a/elasticsearch/x-pack/shield/config/shield/users_roles b/elasticsearch/x-pack/shield/config/shield/users_roles new file mode 100644 index 00000000000..e69de29bb2d diff --git a/shield/dev-tools/esvm/.esvm-shield-config/role_mapping.yml b/elasticsearch/x-pack/shield/dev-tools/esvm/.esvm-shield-config/role_mapping.yml similarity index 100% rename from shield/dev-tools/esvm/.esvm-shield-config/role_mapping.yml rename to elasticsearch/x-pack/shield/dev-tools/esvm/.esvm-shield-config/role_mapping.yml diff --git a/shield/dev-tools/esvm/.esvm-shield-config/roles.yml b/elasticsearch/x-pack/shield/dev-tools/esvm/.esvm-shield-config/roles.yml similarity index 100% rename from shield/dev-tools/esvm/.esvm-shield-config/roles.yml rename to elasticsearch/x-pack/shield/dev-tools/esvm/.esvm-shield-config/roles.yml diff --git a/shield/dev-tools/esvm/.esvm-shield-config/system_key b/elasticsearch/x-pack/shield/dev-tools/esvm/.esvm-shield-config/system_key similarity index 100% rename from shield/dev-tools/esvm/.esvm-shield-config/system_key rename to elasticsearch/x-pack/shield/dev-tools/esvm/.esvm-shield-config/system_key diff --git a/shield/dev-tools/esvm/.esvm-shield-config/users b/elasticsearch/x-pack/shield/dev-tools/esvm/.esvm-shield-config/users similarity index 100% rename from shield/dev-tools/esvm/.esvm-shield-config/users rename to elasticsearch/x-pack/shield/dev-tools/esvm/.esvm-shield-config/users diff --git a/shield/dev-tools/esvm/.esvm-shield-config/users_roles b/elasticsearch/x-pack/shield/dev-tools/esvm/.esvm-shield-config/users_roles similarity index 100% rename from shield/dev-tools/esvm/.esvm-shield-config/users_roles rename to elasticsearch/x-pack/shield/dev-tools/esvm/.esvm-shield-config/users_roles diff --git a/shield/dev-tools/esvm/.esvmrc b/elasticsearch/x-pack/shield/dev-tools/esvm/.esvmrc similarity index 100% rename from shield/dev-tools/esvm/.esvmrc rename to elasticsearch/x-pack/shield/dev-tools/esvm/.esvmrc diff --git a/shield/dev-tools/esvm/readme.txt b/elasticsearch/x-pack/shield/dev-tools/esvm/readme.txt similarity index 100% rename from shield/dev-tools/esvm/readme.txt rename to elasticsearch/x-pack/shield/dev-tools/esvm/readme.txt diff --git a/shield/dev-tools/randomization.yml b/elasticsearch/x-pack/shield/dev-tools/randomization.yml similarity index 100% rename from shield/dev-tools/randomization.yml rename to elasticsearch/x-pack/shield/dev-tools/randomization.yml diff --git a/shield/src/main/java/org/elasticsearch/shield/ShieldBuild.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/ShieldBuild.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/ShieldBuild.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/ShieldBuild.java diff --git a/shield/src/main/java/org/elasticsearch/shield/ShieldDisabledModule.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/ShieldDisabledModule.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/ShieldDisabledModule.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/ShieldDisabledModule.java diff --git a/shield/src/main/java/org/elasticsearch/shield/ShieldLifecycleService.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/ShieldLifecycleService.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/ShieldLifecycleService.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/ShieldLifecycleService.java diff --git a/shield/src/main/java/org/elasticsearch/shield/ShieldModule.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/ShieldModule.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/ShieldModule.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/ShieldModule.java diff --git a/shield/src/main/java/org/elasticsearch/shield/ShieldPlugin.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/ShieldPlugin.java similarity index 90% rename from shield/src/main/java/org/elasticsearch/shield/ShieldPlugin.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/ShieldPlugin.java index fc7a9a2e0a4..a4fb96e0035 100644 --- a/shield/src/main/java/org/elasticsearch/shield/ShieldPlugin.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/ShieldPlugin.java @@ -5,7 +5,6 @@ */ package org.elasticsearch.shield; -import org.elasticsearch.SpecialPermission; import org.elasticsearch.action.ActionModule; import org.elasticsearch.client.Client; import org.elasticsearch.client.support.Headers; @@ -17,8 +16,6 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.env.Environment; import org.elasticsearch.http.HttpServerModule; import org.elasticsearch.index.IndexModule; -import org.elasticsearch.index.IndexService; -import org.elasticsearch.index.shard.IndexEventListener; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.rest.RestModule; import org.elasticsearch.shield.action.ShieldActionFilter; @@ -51,6 +48,7 @@ import org.elasticsearch.shield.transport.filter.IPFilter; import org.elasticsearch.shield.transport.netty.ShieldNettyHttpServerTransport; import org.elasticsearch.shield.transport.netty.ShieldNettyTransport; import org.elasticsearch.transport.TransportModule; +import org.elasticsearch.xpack.XPackPlugin; import java.nio.file.Path; import java.util.*; @@ -74,36 +72,6 @@ public class ShieldPlugin extends Plugin { private final boolean clientMode; private ShieldLicenseState shieldLicenseState; - // TODO: clean up this library to not ask for write access to all system properties! - static { - // invoke this clinit in unbound with permissions to access all system properties - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new SpecialPermission()); - } - try { - AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Void run() { - try { - Class.forName("com.unboundid.util.Debug"); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - return null; - } - }); - // TODO: fix gradle to add all shield resources (plugin metadata) to test classpath - // of watcher plugin, which depends on it directly. This prevents these plugins - // from being initialized correctly by the test framework, and means we have to - // have this leniency. - } catch (ExceptionInInitializerError bogus) { - if (bogus.getCause() instanceof SecurityException == false) { - throw bogus; // some other bug - } - } - } - public ShieldPlugin(Settings settings) { this.settings = settings; this.enabled = shieldEnabled(settings); @@ -319,7 +287,7 @@ public class ShieldPlugin extends Plugin { } public static Path configDir(Environment env) { - return env.configFile().resolve(NAME); + return env.configFile().resolve(XPackPlugin.NAME); } public static Path resolveConfigFile(Environment env, String name) { diff --git a/shield/src/main/java/org/elasticsearch/shield/ShieldSettingsFilter.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/ShieldSettingsFilter.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/ShieldSettingsFilter.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/ShieldSettingsFilter.java diff --git a/shield/src/main/java/org/elasticsearch/shield/User.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/User.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/User.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/User.java diff --git a/shield/src/main/java/org/elasticsearch/shield/action/ShieldActionFilter.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/ShieldActionFilter.java similarity index 99% rename from shield/src/main/java/org/elasticsearch/shield/action/ShieldActionFilter.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/ShieldActionFilter.java index c5fbdbcca2f..e8dfbc90839 100644 --- a/shield/src/main/java/org/elasticsearch/shield/action/ShieldActionFilter.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/ShieldActionFilter.java @@ -18,6 +18,7 @@ import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.license.plugin.core.LicenseUtils; import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.User; import org.elasticsearch.shield.action.interceptor.RequestInterceptor; import org.elasticsearch.shield.audit.AuditTrail; diff --git a/shield/src/main/java/org/elasticsearch/shield/action/ShieldActionMapper.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/ShieldActionMapper.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/action/ShieldActionMapper.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/ShieldActionMapper.java diff --git a/shield/src/main/java/org/elasticsearch/shield/action/ShieldActionModule.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/ShieldActionModule.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/action/ShieldActionModule.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/ShieldActionModule.java diff --git a/shield/src/main/java/org/elasticsearch/shield/action/authc/cache/ClearRealmCacheAction.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/authc/cache/ClearRealmCacheAction.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/action/authc/cache/ClearRealmCacheAction.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/authc/cache/ClearRealmCacheAction.java diff --git a/shield/src/main/java/org/elasticsearch/shield/action/authc/cache/ClearRealmCacheRequest.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/authc/cache/ClearRealmCacheRequest.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/action/authc/cache/ClearRealmCacheRequest.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/authc/cache/ClearRealmCacheRequest.java diff --git a/shield/src/main/java/org/elasticsearch/shield/action/authc/cache/ClearRealmCacheRequestBuilder.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/authc/cache/ClearRealmCacheRequestBuilder.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/action/authc/cache/ClearRealmCacheRequestBuilder.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/authc/cache/ClearRealmCacheRequestBuilder.java diff --git a/shield/src/main/java/org/elasticsearch/shield/action/authc/cache/ClearRealmCacheResponse.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/authc/cache/ClearRealmCacheResponse.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/action/authc/cache/ClearRealmCacheResponse.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/authc/cache/ClearRealmCacheResponse.java diff --git a/shield/src/main/java/org/elasticsearch/shield/action/authc/cache/TransportClearRealmCacheAction.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/authc/cache/TransportClearRealmCacheAction.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/action/authc/cache/TransportClearRealmCacheAction.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/authc/cache/TransportClearRealmCacheAction.java diff --git a/shield/src/main/java/org/elasticsearch/shield/action/interceptor/BulkRequestInterceptor.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/BulkRequestInterceptor.java similarity index 97% rename from shield/src/main/java/org/elasticsearch/shield/action/interceptor/BulkRequestInterceptor.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/BulkRequestInterceptor.java index 49992f7d7e3..c344c9f610b 100644 --- a/shield/src/main/java/org/elasticsearch/shield/action/interceptor/BulkRequestInterceptor.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/BulkRequestInterceptor.java @@ -13,6 +13,7 @@ import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.rest.RestStatus; import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.User; import org.elasticsearch.transport.TransportRequest; diff --git a/shield/src/main/java/org/elasticsearch/shield/action/interceptor/FieldSecurityRequestInterceptor.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/FieldSecurityRequestInterceptor.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/action/interceptor/FieldSecurityRequestInterceptor.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/FieldSecurityRequestInterceptor.java diff --git a/shield/src/main/java/org/elasticsearch/shield/action/interceptor/RealtimeRequestInterceptor.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/RealtimeRequestInterceptor.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/action/interceptor/RealtimeRequestInterceptor.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/RealtimeRequestInterceptor.java diff --git a/shield/src/main/java/org/elasticsearch/shield/action/interceptor/RequestInterceptor.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/RequestInterceptor.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/action/interceptor/RequestInterceptor.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/RequestInterceptor.java diff --git a/shield/src/main/java/org/elasticsearch/shield/action/interceptor/SearchRequestInterceptor.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/SearchRequestInterceptor.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/action/interceptor/SearchRequestInterceptor.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/SearchRequestInterceptor.java diff --git a/shield/src/main/java/org/elasticsearch/shield/action/interceptor/UpdateRequestInterceptor.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/UpdateRequestInterceptor.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/action/interceptor/UpdateRequestInterceptor.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/action/interceptor/UpdateRequestInterceptor.java diff --git a/shield/src/main/java/org/elasticsearch/shield/audit/AuditTrail.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/audit/AuditTrail.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/audit/AuditTrail.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/audit/AuditTrail.java diff --git a/shield/src/main/java/org/elasticsearch/shield/audit/AuditTrailModule.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/audit/AuditTrailModule.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/audit/AuditTrailModule.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/audit/AuditTrailModule.java diff --git a/shield/src/main/java/org/elasticsearch/shield/audit/AuditTrailService.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/audit/AuditTrailService.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/audit/AuditTrailService.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/audit/AuditTrailService.java diff --git a/shield/src/main/java/org/elasticsearch/shield/audit/AuditUtil.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/audit/AuditUtil.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/audit/AuditUtil.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/audit/AuditUtil.java diff --git a/shield/src/main/java/org/elasticsearch/shield/audit/index/IndexAuditLevel.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/audit/index/IndexAuditLevel.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/audit/index/IndexAuditLevel.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/audit/index/IndexAuditLevel.java diff --git a/shield/src/main/java/org/elasticsearch/shield/audit/index/IndexAuditTrail.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/audit/index/IndexAuditTrail.java similarity index 99% rename from shield/src/main/java/org/elasticsearch/shield/audit/index/IndexAuditTrail.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/audit/index/IndexAuditTrail.java index 30512967d70..129a0b9b5c6 100644 --- a/shield/src/main/java/org/elasticsearch/shield/audit/index/IndexAuditTrail.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/audit/index/IndexAuditTrail.java @@ -43,7 +43,7 @@ import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.env.Environment; import org.elasticsearch.gateway.GatewayService; import org.elasticsearch.rest.RestRequest; -import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.User; import org.elasticsearch.shield.audit.AuditTrail; import org.elasticsearch.shield.authc.AuthenticationService; @@ -705,7 +705,7 @@ public class IndexAuditTrail extends AbstractComponent implements AuditTrail, Cl .settings(Settings.builder() .put("name", DEFAULT_CLIENT_NAME + "-" + settings.get("name")) .put(clientSettings)) - .addPlugin(ShieldPlugin.class) + .addPlugin(XPackPlugin.class) .build(); for (Tuple pair : hostPortPairs) { try { diff --git a/shield/src/main/java/org/elasticsearch/shield/audit/index/IndexAuditUserHolder.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/audit/index/IndexAuditUserHolder.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/audit/index/IndexAuditUserHolder.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/audit/index/IndexAuditUserHolder.java diff --git a/shield/src/main/java/org/elasticsearch/shield/audit/index/IndexNameResolver.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/audit/index/IndexNameResolver.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/audit/index/IndexNameResolver.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/audit/index/IndexNameResolver.java diff --git a/shield/src/main/java/org/elasticsearch/shield/audit/logfile/LoggingAuditTrail.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/audit/logfile/LoggingAuditTrail.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/audit/logfile/LoggingAuditTrail.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/audit/logfile/LoggingAuditTrail.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/AnonymousService.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/AnonymousService.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/AnonymousService.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/AnonymousService.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/AuthenticationFailureHandler.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/AuthenticationFailureHandler.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/AuthenticationFailureHandler.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/AuthenticationFailureHandler.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/AuthenticationModule.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/AuthenticationModule.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/AuthenticationModule.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/AuthenticationModule.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/AuthenticationService.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/AuthenticationService.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/AuthenticationService.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/AuthenticationService.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/AuthenticationToken.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/AuthenticationToken.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/AuthenticationToken.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/AuthenticationToken.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/DefaultAuthenticationFailureHandler.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/DefaultAuthenticationFailureHandler.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/DefaultAuthenticationFailureHandler.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/DefaultAuthenticationFailureHandler.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/InternalAuthenticationService.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/InternalAuthenticationService.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/InternalAuthenticationService.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/InternalAuthenticationService.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/Realm.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/Realm.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/Realm.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/Realm.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/RealmConfig.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/RealmConfig.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/RealmConfig.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/RealmConfig.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/Realms.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/Realms.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/Realms.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/Realms.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/activedirectory/ActiveDirectoryGroupsResolver.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/activedirectory/ActiveDirectoryGroupsResolver.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/activedirectory/ActiveDirectoryGroupsResolver.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/activedirectory/ActiveDirectoryGroupsResolver.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/activedirectory/ActiveDirectoryRealm.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/activedirectory/ActiveDirectoryRealm.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/activedirectory/ActiveDirectoryRealm.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/activedirectory/ActiveDirectoryRealm.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/activedirectory/ActiveDirectorySessionFactory.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/activedirectory/ActiveDirectorySessionFactory.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/activedirectory/ActiveDirectorySessionFactory.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/activedirectory/ActiveDirectorySessionFactory.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/esusers/ESUsersRealm.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/esusers/ESUsersRealm.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/esusers/ESUsersRealm.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/esusers/ESUsersRealm.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/esusers/FileUserPasswdStore.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/esusers/FileUserPasswdStore.java similarity index 99% rename from shield/src/main/java/org/elasticsearch/shield/authc/esusers/FileUserPasswdStore.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/esusers/FileUserPasswdStore.java index 60ec7deeb67..5c662c4fa98 100644 --- a/shield/src/main/java/org/elasticsearch/shield/authc/esusers/FileUserPasswdStore.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/esusers/FileUserPasswdStore.java @@ -11,6 +11,7 @@ import org.elasticsearch.common.logging.ESLogger; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.env.Environment; import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.authc.RealmConfig; import org.elasticsearch.shield.authc.support.Hasher; import org.elasticsearch.shield.authc.support.RefreshListener; diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/esusers/FileUserRolesStore.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/esusers/FileUserRolesStore.java similarity index 99% rename from shield/src/main/java/org/elasticsearch/shield/authc/esusers/FileUserRolesStore.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/esusers/FileUserRolesStore.java index b1df110a914..87a4f2a34d4 100644 --- a/shield/src/main/java/org/elasticsearch/shield/authc/esusers/FileUserRolesStore.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/esusers/FileUserRolesStore.java @@ -12,6 +12,7 @@ import org.elasticsearch.common.logging.ESLogger; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.env.Environment; import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.authc.RealmConfig; import org.elasticsearch.shield.authc.support.RefreshListener; import org.elasticsearch.shield.support.NoOpLogger; diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/esusers/tool/ESUsersTool.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/esusers/tool/ESUsersTool.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/esusers/tool/ESUsersTool.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/esusers/tool/ESUsersTool.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/ldap/LdapRealm.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/ldap/LdapRealm.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/ldap/LdapRealm.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/ldap/LdapRealm.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/ldap/LdapSessionFactory.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/ldap/LdapSessionFactory.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/ldap/LdapSessionFactory.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/ldap/LdapSessionFactory.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/ldap/LdapUserSearchSessionFactory.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/ldap/LdapUserSearchSessionFactory.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/ldap/LdapUserSearchSessionFactory.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/ldap/LdapUserSearchSessionFactory.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/ldap/SearchGroupsResolver.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/ldap/SearchGroupsResolver.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/ldap/SearchGroupsResolver.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/ldap/SearchGroupsResolver.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/ldap/UserAttributeGroupsResolver.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/ldap/UserAttributeGroupsResolver.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/ldap/UserAttributeGroupsResolver.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/ldap/UserAttributeGroupsResolver.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/ldap/support/AbstractLdapRealm.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/ldap/support/AbstractLdapRealm.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/ldap/support/AbstractLdapRealm.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/ldap/support/AbstractLdapRealm.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/ldap/support/LdapSearchScope.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/ldap/support/LdapSearchScope.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/ldap/support/LdapSearchScope.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/ldap/support/LdapSearchScope.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/ldap/support/LdapSession.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/ldap/support/LdapSession.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/ldap/support/LdapSession.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/ldap/support/LdapSession.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/ldap/support/LdapUtils.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/ldap/support/LdapUtils.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/ldap/support/LdapUtils.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/ldap/support/LdapUtils.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/ldap/support/SessionFactory.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/ldap/support/SessionFactory.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/ldap/support/SessionFactory.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/ldap/support/SessionFactory.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/pki/PkiRealm.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/pki/PkiRealm.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/pki/PkiRealm.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/pki/PkiRealm.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/pki/X509AuthenticationToken.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/pki/X509AuthenticationToken.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/pki/X509AuthenticationToken.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/pki/X509AuthenticationToken.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/support/BCrypt.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/support/BCrypt.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/support/BCrypt.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/support/BCrypt.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/support/CachingRealm.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/support/CachingRealm.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/support/CachingRealm.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/support/CachingRealm.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/support/CachingUsernamePasswordRealm.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/support/CachingUsernamePasswordRealm.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/support/CachingUsernamePasswordRealm.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/support/CachingUsernamePasswordRealm.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/support/CharArrays.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/support/CharArrays.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/support/CharArrays.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/support/CharArrays.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/support/DnRoleMapper.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/support/DnRoleMapper.java similarity index 99% rename from shield/src/main/java/org/elasticsearch/shield/authc/support/DnRoleMapper.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/support/DnRoleMapper.java index 9c235f873c2..a4514a1a3d0 100644 --- a/shield/src/main/java/org/elasticsearch/shield/authc/support/DnRoleMapper.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/support/DnRoleMapper.java @@ -14,6 +14,7 @@ import org.elasticsearch.common.logging.ESLogger; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.env.Environment; import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.authc.RealmConfig; import org.elasticsearch.watcher.FileChangesListener; import org.elasticsearch.watcher.FileWatcher; diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/support/Hasher.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/support/Hasher.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/support/Hasher.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/support/Hasher.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/support/RefreshListener.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/support/RefreshListener.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/support/RefreshListener.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/support/RefreshListener.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/support/SecuredString.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/support/SecuredString.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/support/SecuredString.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/support/SecuredString.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/support/UsernamePasswordRealm.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/support/UsernamePasswordRealm.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/support/UsernamePasswordRealm.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/support/UsernamePasswordRealm.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authc/support/UsernamePasswordToken.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/support/UsernamePasswordToken.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authc/support/UsernamePasswordToken.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authc/support/UsernamePasswordToken.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authz/AuthorizationModule.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/AuthorizationModule.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authz/AuthorizationModule.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/AuthorizationModule.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authz/AuthorizationService.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/AuthorizationService.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authz/AuthorizationService.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/AuthorizationService.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authz/InternalAuthorizationService.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/InternalAuthorizationService.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authz/InternalAuthorizationService.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/InternalAuthorizationService.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authz/Permission.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/Permission.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authz/Permission.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/Permission.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authz/Privilege.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/Privilege.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authz/Privilege.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/Privilege.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authz/SystemRole.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/SystemRole.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authz/SystemRole.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/SystemRole.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authz/accesscontrol/DocumentSubsetReader.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/accesscontrol/DocumentSubsetReader.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authz/accesscontrol/DocumentSubsetReader.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/accesscontrol/DocumentSubsetReader.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authz/accesscontrol/FieldSubsetReader.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/accesscontrol/FieldSubsetReader.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authz/accesscontrol/FieldSubsetReader.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/accesscontrol/FieldSubsetReader.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authz/accesscontrol/IndicesAccessControl.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/accesscontrol/IndicesAccessControl.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authz/accesscontrol/IndicesAccessControl.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/accesscontrol/IndicesAccessControl.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authz/accesscontrol/OptOutQueryCache.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/accesscontrol/OptOutQueryCache.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authz/accesscontrol/OptOutQueryCache.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/accesscontrol/OptOutQueryCache.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authz/accesscontrol/RequestContext.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/accesscontrol/RequestContext.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authz/accesscontrol/RequestContext.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/accesscontrol/RequestContext.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authz/accesscontrol/ShieldIndexSearcherWrapper.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/accesscontrol/ShieldIndexSearcherWrapper.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authz/accesscontrol/ShieldIndexSearcherWrapper.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/accesscontrol/ShieldIndexSearcherWrapper.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authz/indicesresolver/DefaultIndicesAndAliasesResolver.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/indicesresolver/DefaultIndicesAndAliasesResolver.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authz/indicesresolver/DefaultIndicesAndAliasesResolver.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/indicesresolver/DefaultIndicesAndAliasesResolver.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authz/indicesresolver/IndicesAndAliasesResolver.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/indicesresolver/IndicesAndAliasesResolver.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authz/indicesresolver/IndicesAndAliasesResolver.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/indicesresolver/IndicesAndAliasesResolver.java diff --git a/shield/src/main/java/org/elasticsearch/shield/authz/store/FileRolesStore.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/store/FileRolesStore.java similarity index 99% rename from shield/src/main/java/org/elasticsearch/shield/authz/store/FileRolesStore.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/store/FileRolesStore.java index 4882ab795d5..169b21e8326 100644 --- a/shield/src/main/java/org/elasticsearch/shield/authz/store/FileRolesStore.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/store/FileRolesStore.java @@ -22,6 +22,7 @@ import org.elasticsearch.common.xcontent.json.JsonXContent; import org.elasticsearch.common.xcontent.yaml.YamlXContent; import org.elasticsearch.env.Environment; import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.authc.support.RefreshListener; import org.elasticsearch.shield.authz.Permission; import org.elasticsearch.shield.authz.Privilege; diff --git a/shield/src/main/java/org/elasticsearch/shield/authz/store/RolesStore.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/store/RolesStore.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/authz/store/RolesStore.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/authz/store/RolesStore.java diff --git a/shield/src/main/java/org/elasticsearch/shield/client/ShieldAuthcClient.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/client/ShieldAuthcClient.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/client/ShieldAuthcClient.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/client/ShieldAuthcClient.java diff --git a/shield/src/main/java/org/elasticsearch/shield/client/ShieldClient.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/client/ShieldClient.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/client/ShieldClient.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/client/ShieldClient.java diff --git a/shield/src/main/java/org/elasticsearch/shield/crypto/CryptoModule.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/crypto/CryptoModule.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/crypto/CryptoModule.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/crypto/CryptoModule.java diff --git a/shield/src/main/java/org/elasticsearch/shield/crypto/CryptoService.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/crypto/CryptoService.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/crypto/CryptoService.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/crypto/CryptoService.java diff --git a/shield/src/main/java/org/elasticsearch/shield/crypto/InternalCryptoService.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/crypto/InternalCryptoService.java similarity index 99% rename from shield/src/main/java/org/elasticsearch/shield/crypto/InternalCryptoService.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/crypto/InternalCryptoService.java index 22fc33b8388..5042465323c 100644 --- a/shield/src/main/java/org/elasticsearch/shield/crypto/InternalCryptoService.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/crypto/InternalCryptoService.java @@ -13,6 +13,7 @@ import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.env.Environment; import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.authc.support.CharArrays; import org.elasticsearch.watcher.FileChangesListener; import org.elasticsearch.watcher.FileWatcher; diff --git a/shield/src/main/java/org/elasticsearch/shield/crypto/tool/SystemKeyTool.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/crypto/tool/SystemKeyTool.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/crypto/tool/SystemKeyTool.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/crypto/tool/SystemKeyTool.java diff --git a/shield/src/main/java/org/elasticsearch/shield/license/LicenseModule.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/license/LicenseModule.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/license/LicenseModule.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/license/LicenseModule.java diff --git a/shield/src/main/java/org/elasticsearch/shield/license/ShieldLicenseState.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/license/ShieldLicenseState.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/license/ShieldLicenseState.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/license/ShieldLicenseState.java diff --git a/shield/src/main/java/org/elasticsearch/shield/license/ShieldLicensee.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/license/ShieldLicensee.java similarity index 98% rename from shield/src/main/java/org/elasticsearch/shield/license/ShieldLicensee.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/license/ShieldLicensee.java index 32ea9a70b09..d646af19ec8 100644 --- a/shield/src/main/java/org/elasticsearch/shield/license/ShieldLicensee.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/license/ShieldLicensee.java @@ -12,6 +12,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.license.core.License; import org.elasticsearch.license.plugin.core.*; import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; /** * diff --git a/shield/src/main/java/org/elasticsearch/shield/rest/RemoteHostHeader.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/rest/RemoteHostHeader.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/rest/RemoteHostHeader.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/rest/RemoteHostHeader.java diff --git a/shield/src/main/java/org/elasticsearch/shield/rest/ShieldRestFilter.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/rest/ShieldRestFilter.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/rest/ShieldRestFilter.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/rest/ShieldRestFilter.java diff --git a/shield/src/main/java/org/elasticsearch/shield/rest/ShieldRestModule.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/rest/ShieldRestModule.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/rest/ShieldRestModule.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/rest/ShieldRestModule.java diff --git a/shield/src/main/java/org/elasticsearch/shield/rest/action/RestShieldInfoAction.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/rest/action/RestShieldInfoAction.java similarity index 98% rename from shield/src/main/java/org/elasticsearch/shield/rest/action/RestShieldInfoAction.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/rest/action/RestShieldInfoAction.java index 46b33685ab1..ed682ddfa19 100644 --- a/shield/src/main/java/org/elasticsearch/shield/rest/action/RestShieldInfoAction.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/rest/action/RestShieldInfoAction.java @@ -15,6 +15,7 @@ import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.rest.*; import org.elasticsearch.shield.ShieldBuild; import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.license.ShieldLicenseState; import static org.elasticsearch.rest.RestRequest.Method.GET; diff --git a/shield/src/main/java/org/elasticsearch/shield/rest/action/authc/cache/RestClearRealmCacheAction.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/rest/action/authc/cache/RestClearRealmCacheAction.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/rest/action/authc/cache/RestClearRealmCacheAction.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/rest/action/authc/cache/RestClearRealmCacheAction.java diff --git a/shield/src/main/java/org/elasticsearch/shield/ssl/AbstractSSLService.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/ssl/AbstractSSLService.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/ssl/AbstractSSLService.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/ssl/AbstractSSLService.java diff --git a/shield/src/main/java/org/elasticsearch/shield/ssl/ClientSSLService.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/ssl/ClientSSLService.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/ssl/ClientSSLService.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/ssl/ClientSSLService.java diff --git a/shield/src/main/java/org/elasticsearch/shield/ssl/SSLModule.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/ssl/SSLModule.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/ssl/SSLModule.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/ssl/SSLModule.java diff --git a/shield/src/main/java/org/elasticsearch/shield/ssl/ServerSSLService.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/ssl/ServerSSLService.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/ssl/ServerSSLService.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/ssl/ServerSSLService.java diff --git a/shield/src/main/java/org/elasticsearch/shield/support/AbstractShieldModule.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/support/AbstractShieldModule.java similarity index 97% rename from shield/src/main/java/org/elasticsearch/shield/support/AbstractShieldModule.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/support/AbstractShieldModule.java index 865accf0b12..31ad7cc7085 100644 --- a/shield/src/main/java/org/elasticsearch/shield/support/AbstractShieldModule.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/support/AbstractShieldModule.java @@ -9,6 +9,7 @@ import org.elasticsearch.client.Client; import org.elasticsearch.common.inject.AbstractModule; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; /** * diff --git a/shield/src/main/java/org/elasticsearch/shield/support/AutomatonPredicate.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/support/AutomatonPredicate.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/support/AutomatonPredicate.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/support/AutomatonPredicate.java diff --git a/shield/src/main/java/org/elasticsearch/shield/support/Automatons.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/support/Automatons.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/support/Automatons.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/support/Automatons.java diff --git a/shield/src/main/java/org/elasticsearch/shield/support/Exceptions.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/support/Exceptions.java similarity index 96% rename from shield/src/main/java/org/elasticsearch/shield/support/Exceptions.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/support/Exceptions.java index 94780c4aa00..2377101c962 100644 --- a/shield/src/main/java/org/elasticsearch/shield/support/Exceptions.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/support/Exceptions.java @@ -8,6 +8,7 @@ package org.elasticsearch.shield.support; import org.elasticsearch.ElasticsearchSecurityException; import org.elasticsearch.rest.RestStatus; import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; /** * diff --git a/shield/src/main/java/org/elasticsearch/shield/support/NoOpLogger.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/support/NoOpLogger.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/support/NoOpLogger.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/support/NoOpLogger.java diff --git a/shield/src/main/java/org/elasticsearch/shield/support/ShieldFiles.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/support/ShieldFiles.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/support/ShieldFiles.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/support/ShieldFiles.java diff --git a/shield/src/main/java/org/elasticsearch/shield/support/Validation.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/support/Validation.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/support/Validation.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/support/Validation.java diff --git a/shield/src/main/java/org/elasticsearch/shield/transport/ClientTransportFilter.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/transport/ClientTransportFilter.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/transport/ClientTransportFilter.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/transport/ClientTransportFilter.java diff --git a/shield/src/main/java/org/elasticsearch/shield/transport/SSLClientAuth.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/transport/SSLClientAuth.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/transport/SSLClientAuth.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/transport/SSLClientAuth.java diff --git a/shield/src/main/java/org/elasticsearch/shield/transport/SSLExceptionHelper.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/transport/SSLExceptionHelper.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/transport/SSLExceptionHelper.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/transport/SSLExceptionHelper.java diff --git a/shield/src/main/java/org/elasticsearch/shield/transport/ServerTransportFilter.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/transport/ServerTransportFilter.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/transport/ServerTransportFilter.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/transport/ServerTransportFilter.java diff --git a/shield/src/main/java/org/elasticsearch/shield/transport/ShieldClientTransportService.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/transport/ShieldClientTransportService.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/transport/ShieldClientTransportService.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/transport/ShieldClientTransportService.java diff --git a/shield/src/main/java/org/elasticsearch/shield/transport/ShieldServerTransportService.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/transport/ShieldServerTransportService.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/transport/ShieldServerTransportService.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/transport/ShieldServerTransportService.java diff --git a/shield/src/main/java/org/elasticsearch/shield/transport/ShieldTransportModule.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/transport/ShieldTransportModule.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/transport/ShieldTransportModule.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/transport/ShieldTransportModule.java diff --git a/shield/src/main/java/org/elasticsearch/shield/transport/filter/IPFilter.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/transport/filter/IPFilter.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/transport/filter/IPFilter.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/transport/filter/IPFilter.java diff --git a/shield/src/main/java/org/elasticsearch/shield/transport/filter/ShieldIpFilterRule.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/transport/filter/ShieldIpFilterRule.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/transport/filter/ShieldIpFilterRule.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/transport/filter/ShieldIpFilterRule.java diff --git a/shield/src/main/java/org/elasticsearch/shield/transport/netty/HandshakeWaitingHandler.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/transport/netty/HandshakeWaitingHandler.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/transport/netty/HandshakeWaitingHandler.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/transport/netty/HandshakeWaitingHandler.java diff --git a/shield/src/main/java/org/elasticsearch/shield/transport/netty/IPFilterNettyUpstreamHandler.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/transport/netty/IPFilterNettyUpstreamHandler.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/transport/netty/IPFilterNettyUpstreamHandler.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/transport/netty/IPFilterNettyUpstreamHandler.java diff --git a/shield/src/main/java/org/elasticsearch/shield/transport/netty/ShieldNettyHttpServerTransport.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/transport/netty/ShieldNettyHttpServerTransport.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/transport/netty/ShieldNettyHttpServerTransport.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/transport/netty/ShieldNettyHttpServerTransport.java diff --git a/shield/src/main/java/org/elasticsearch/shield/transport/netty/ShieldNettyTransport.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/transport/netty/ShieldNettyTransport.java similarity index 100% rename from shield/src/main/java/org/elasticsearch/shield/transport/netty/ShieldNettyTransport.java rename to elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/transport/netty/ShieldNettyTransport.java diff --git a/shield/src/main/resources/org/elasticsearch/shield/authc/esusers/tool/esusers-list.help b/elasticsearch/x-pack/shield/src/main/resources/org/elasticsearch/shield/authc/esusers/tool/esusers-list.help similarity index 100% rename from shield/src/main/resources/org/elasticsearch/shield/authc/esusers/tool/esusers-list.help rename to elasticsearch/x-pack/shield/src/main/resources/org/elasticsearch/shield/authc/esusers/tool/esusers-list.help diff --git a/shield/src/main/resources/org/elasticsearch/shield/authc/esusers/tool/esusers-passwd.help b/elasticsearch/x-pack/shield/src/main/resources/org/elasticsearch/shield/authc/esusers/tool/esusers-passwd.help similarity index 100% rename from shield/src/main/resources/org/elasticsearch/shield/authc/esusers/tool/esusers-passwd.help rename to elasticsearch/x-pack/shield/src/main/resources/org/elasticsearch/shield/authc/esusers/tool/esusers-passwd.help diff --git a/shield/src/main/resources/org/elasticsearch/shield/authc/esusers/tool/esusers-roles.help b/elasticsearch/x-pack/shield/src/main/resources/org/elasticsearch/shield/authc/esusers/tool/esusers-roles.help similarity index 100% rename from shield/src/main/resources/org/elasticsearch/shield/authc/esusers/tool/esusers-roles.help rename to elasticsearch/x-pack/shield/src/main/resources/org/elasticsearch/shield/authc/esusers/tool/esusers-roles.help diff --git a/shield/src/main/resources/org/elasticsearch/shield/authc/esusers/tool/esusers-useradd.help b/elasticsearch/x-pack/shield/src/main/resources/org/elasticsearch/shield/authc/esusers/tool/esusers-useradd.help similarity index 100% rename from shield/src/main/resources/org/elasticsearch/shield/authc/esusers/tool/esusers-useradd.help rename to elasticsearch/x-pack/shield/src/main/resources/org/elasticsearch/shield/authc/esusers/tool/esusers-useradd.help diff --git a/shield/src/main/resources/org/elasticsearch/shield/authc/esusers/tool/esusers-userdel.help b/elasticsearch/x-pack/shield/src/main/resources/org/elasticsearch/shield/authc/esusers/tool/esusers-userdel.help similarity index 100% rename from shield/src/main/resources/org/elasticsearch/shield/authc/esusers/tool/esusers-userdel.help rename to elasticsearch/x-pack/shield/src/main/resources/org/elasticsearch/shield/authc/esusers/tool/esusers-userdel.help diff --git a/shield/src/main/resources/org/elasticsearch/shield/authc/esusers/tool/esusers.help b/elasticsearch/x-pack/shield/src/main/resources/org/elasticsearch/shield/authc/esusers/tool/esusers.help similarity index 100% rename from shield/src/main/resources/org/elasticsearch/shield/authc/esusers/tool/esusers.help rename to elasticsearch/x-pack/shield/src/main/resources/org/elasticsearch/shield/authc/esusers/tool/esusers.help diff --git a/shield/src/main/resources/org/elasticsearch/shield/crypto/tool/syskey-generate.help b/elasticsearch/x-pack/shield/src/main/resources/org/elasticsearch/shield/crypto/tool/syskey-generate.help similarity index 100% rename from shield/src/main/resources/org/elasticsearch/shield/crypto/tool/syskey-generate.help rename to elasticsearch/x-pack/shield/src/main/resources/org/elasticsearch/shield/crypto/tool/syskey-generate.help diff --git a/shield/src/main/resources/shield-build.properties b/elasticsearch/x-pack/shield/src/main/resources/shield-build.properties similarity index 100% rename from shield/src/main/resources/shield-build.properties rename to elasticsearch/x-pack/shield/src/main/resources/shield-build.properties diff --git a/shield/src/main/resources/shield_audit_log.json b/elasticsearch/x-pack/shield/src/main/resources/shield_audit_log.json similarity index 100% rename from shield/src/main/resources/shield_audit_log.json rename to elasticsearch/x-pack/shield/src/main/resources/shield_audit_log.json diff --git a/shield/src/test/java/org/elasticsearch/bench/HasherBenchmark.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/bench/HasherBenchmark.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/bench/HasherBenchmark.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/bench/HasherBenchmark.java diff --git a/shield/src/test/java/org/elasticsearch/http/netty/NettyHttpMockUtil.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/http/netty/NettyHttpMockUtil.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/http/netty/NettyHttpMockUtil.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/http/netty/NettyHttpMockUtil.java diff --git a/shield/src/test/java/org/elasticsearch/integration/AbstractPrivilegeTestCase.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/AbstractPrivilegeTestCase.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/integration/AbstractPrivilegeTestCase.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/AbstractPrivilegeTestCase.java diff --git a/shield/src/test/java/org/elasticsearch/integration/BulkUpdateTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/BulkUpdateTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/integration/BulkUpdateTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/BulkUpdateTests.java diff --git a/shield/src/test/java/org/elasticsearch/integration/ClearRealmsCacheTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/ClearRealmsCacheTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/integration/ClearRealmsCacheTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/ClearRealmsCacheTests.java diff --git a/shield/src/test/java/org/elasticsearch/integration/ClusterPrivilegeTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/ClusterPrivilegeTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/integration/ClusterPrivilegeTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/ClusterPrivilegeTests.java diff --git a/shield/src/test/java/org/elasticsearch/integration/DocumentAndFieldLevelSecurityTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/DocumentAndFieldLevelSecurityTests.java similarity index 99% rename from shield/src/test/java/org/elasticsearch/integration/DocumentAndFieldLevelSecurityTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/DocumentAndFieldLevelSecurityTests.java index c109ba374ed..e721435b6a2 100644 --- a/shield/src/test/java/org/elasticsearch/integration/DocumentAndFieldLevelSecurityTests.java +++ b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/DocumentAndFieldLevelSecurityTests.java @@ -9,6 +9,7 @@ import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.IndexModule; import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.authc.support.Hasher; import org.elasticsearch.shield.authc.support.SecuredString; import org.elasticsearch.test.ShieldIntegTestCase; diff --git a/shield/src/test/java/org/elasticsearch/integration/DocumentLevelSecurityRandomTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/DocumentLevelSecurityRandomTests.java similarity index 99% rename from shield/src/test/java/org/elasticsearch/integration/DocumentLevelSecurityRandomTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/DocumentLevelSecurityRandomTests.java index 179e19cff69..78a6899a109 100644 --- a/shield/src/test/java/org/elasticsearch/integration/DocumentLevelSecurityRandomTests.java +++ b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/DocumentLevelSecurityRandomTests.java @@ -11,6 +11,7 @@ import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.authc.support.Hasher; import org.elasticsearch.shield.authc.support.SecuredString; import org.elasticsearch.test.ShieldIntegTestCase; diff --git a/shield/src/test/java/org/elasticsearch/integration/DocumentLevelSecurityTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/DocumentLevelSecurityTests.java similarity index 99% rename from shield/src/test/java/org/elasticsearch/integration/DocumentLevelSecurityTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/DocumentLevelSecurityTests.java index eb51f269881..ed2ee189b3b 100644 --- a/shield/src/test/java/org/elasticsearch/integration/DocumentLevelSecurityTests.java +++ b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/DocumentLevelSecurityTests.java @@ -21,6 +21,7 @@ import org.elasticsearch.search.aggregations.bucket.global.Global; import org.elasticsearch.search.aggregations.bucket.terms.Terms; import org.elasticsearch.search.sort.SortOrder; import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.authc.support.Hasher; import org.elasticsearch.shield.authc.support.SecuredString; import org.elasticsearch.test.ShieldIntegTestCase; diff --git a/shield/src/test/java/org/elasticsearch/integration/FieldLevelSecurityRandomTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/FieldLevelSecurityRandomTests.java similarity index 99% rename from shield/src/test/java/org/elasticsearch/integration/FieldLevelSecurityRandomTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/FieldLevelSecurityRandomTests.java index 29ed42bf48a..f37429668a9 100644 --- a/shield/src/test/java/org/elasticsearch/integration/FieldLevelSecurityRandomTests.java +++ b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/FieldLevelSecurityRandomTests.java @@ -11,6 +11,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.sort.SortOrder; import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.authc.support.Hasher; import org.elasticsearch.shield.authc.support.SecuredString; import org.elasticsearch.test.ShieldIntegTestCase; diff --git a/shield/src/test/java/org/elasticsearch/integration/FieldLevelSecurityTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/FieldLevelSecurityTests.java similarity index 99% rename from shield/src/test/java/org/elasticsearch/integration/FieldLevelSecurityTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/FieldLevelSecurityTests.java index 81190e3ba0a..ad10279607a 100644 --- a/shield/src/test/java/org/elasticsearch/integration/FieldLevelSecurityTests.java +++ b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/FieldLevelSecurityTests.java @@ -24,6 +24,7 @@ import org.elasticsearch.search.aggregations.AggregationBuilders; import org.elasticsearch.search.aggregations.bucket.terms.Terms; import org.elasticsearch.search.sort.SortOrder; import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.authc.support.Hasher; import org.elasticsearch.shield.authc.support.SecuredString; import org.elasticsearch.test.ESIntegTestCase; diff --git a/shield/src/test/java/org/elasticsearch/integration/IndexPrivilegeTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/IndexPrivilegeTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/integration/IndexPrivilegeTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/IndexPrivilegeTests.java diff --git a/shield/src/test/java/org/elasticsearch/integration/IndicesPermissionsWithAliasesWildcardsAndRegexsTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/IndicesPermissionsWithAliasesWildcardsAndRegexsTests.java similarity index 98% rename from shield/src/test/java/org/elasticsearch/integration/IndicesPermissionsWithAliasesWildcardsAndRegexsTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/IndicesPermissionsWithAliasesWildcardsAndRegexsTests.java index 0c2db3bcaab..e136fe463d8 100644 --- a/shield/src/test/java/org/elasticsearch/integration/IndicesPermissionsWithAliasesWildcardsAndRegexsTests.java +++ b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/IndicesPermissionsWithAliasesWildcardsAndRegexsTests.java @@ -9,6 +9,7 @@ import org.elasticsearch.action.admin.indices.alias.Alias; import org.elasticsearch.action.get.GetResponse; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.authc.support.Hasher; import org.elasticsearch.shield.authc.support.SecuredString; import org.elasticsearch.test.ShieldIntegTestCase; diff --git a/shield/src/test/java/org/elasticsearch/integration/LicensingTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/LicensingTests.java similarity index 90% rename from shield/src/test/java/org/elasticsearch/integration/LicensingTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/LicensingTests.java index bc4ef9b5392..928b0a043a9 100644 --- a/shield/src/test/java/org/elasticsearch/integration/LicensingTests.java +++ b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/LicensingTests.java @@ -6,6 +6,7 @@ package org.elasticsearch.integration; import org.elasticsearch.ElasticsearchSecurityException; +import org.elasticsearch.action.ActionModule; import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; import org.elasticsearch.action.admin.cluster.node.stats.NodesStatsResponse; import org.elasticsearch.action.admin.cluster.stats.ClusterStatsIndices; @@ -17,36 +18,35 @@ import org.elasticsearch.client.support.Headers; import org.elasticsearch.client.transport.NoNodeAvailableException; import org.elasticsearch.client.transport.TransportClient; import org.elasticsearch.common.component.AbstractComponent; +import org.elasticsearch.common.component.LifecycleComponent; import org.elasticsearch.common.inject.AbstractModule; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.inject.Module; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.license.core.License; import org.elasticsearch.license.core.License.OperationMode; +import org.elasticsearch.license.plugin.LicensePlugin; import org.elasticsearch.license.plugin.core.LicenseState; import org.elasticsearch.license.plugin.core.Licensee; import org.elasticsearch.license.plugin.core.LicenseeRegistry; import org.elasticsearch.node.Node; -import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.rest.RestModule; import org.elasticsearch.rest.RestStatus; import org.elasticsearch.shield.ShieldPlugin; import org.elasticsearch.shield.authc.support.UsernamePasswordToken; import org.elasticsearch.test.ShieldIntegTestCase; import org.elasticsearch.test.ShieldSettingsSource; import org.elasticsearch.transport.Transport; +import org.elasticsearch.xpack.XPackPlugin; import org.junit.After; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.Locale; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures; -import static org.hamcrest.Matchers.hasItem; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.*; /** * @@ -94,16 +94,6 @@ public class LicensingTests extends ShieldIntegTestCase { return USERS_ROLES; } - @Override - protected Class licensePluginClass() { - return InternalLicensePlugin.class; - } - - @Override - protected String licensePluginName() { - return InternalLicensePlugin.NAME; - } - @Override public Settings nodeSettings(int nodeOrdinal) { return Settings.builder().put(super.nodeSettings(nodeOrdinal)) @@ -111,6 +101,11 @@ public class LicensingTests extends ShieldIntegTestCase { .build(); } + @Override + protected Class xpackPluginClass() { + return InternalXPackPlugin.class; + } + @After public void resetLicensing() { enableLicensing(); @@ -208,7 +203,7 @@ public class LicensingTests extends ShieldIntegTestCase { builder.remove(Headers.PREFIX + "." + UsernamePasswordToken.BASIC_AUTH_HEADER); // basic has no auth - try (TransportClient client = TransportClient.builder().settings(builder).addPlugin(ShieldPlugin.class).build()) { + try (TransportClient client = TransportClient.builder().settings(builder).addPlugin(XPackPlugin.class).build()) { client.addTransportAddress(internalCluster().getDataNodeInstance(Transport.class).boundAddress().publishAddress()); assertGreenClusterState(client); } @@ -217,7 +212,7 @@ public class LicensingTests extends ShieldIntegTestCase { OperationMode mode = randomFrom(OperationMode.GOLD, OperationMode.PLATINUM, OperationMode.TRIAL); enableLicensing(mode); - try (TransportClient client = TransportClient.builder().settings(builder).addPlugin(ShieldPlugin.class).build()) { + try (TransportClient client = TransportClient.builder().settings(builder).addPlugin(XPackPlugin.class).build()) { client.addTransportAddress(internalCluster().getDataNodeInstance(Transport.class).boundAddress().publishAddress()); client.admin().cluster().prepareHealth().get(); fail("should not have been able to connect to a node!"); @@ -246,24 +241,37 @@ public class LicensingTests extends ShieldIntegTestCase { } } - public static class InternalLicensePlugin extends Plugin { - - public static final String NAME = "internal-licensing"; - - @Override - public String name() { - return NAME; - } - - @Override - public String description() { - return name(); - } + public static class InternalLicensePlugin extends LicensePlugin { @Override public Collection nodeModules() { return Collections.singletonList(new InternalLicenseModule()); } + + public InternalLicensePlugin() { + super(Settings.EMPTY); + } + + @Override + public void onModule(RestModule module) { + } + + @Override + public void onModule(ActionModule module) { + } + + @Override + public Collection> nodeServices() { + return Collections.emptyList(); + } + } + + public static class InternalXPackPlugin extends XPackPlugin { + + public InternalXPackPlugin(Settings settings) { + super(settings); + licensePlugin = new InternalLicensePlugin(); + } } public static class InternalLicenseModule extends AbstractModule { diff --git a/shield/src/test/java/org/elasticsearch/integration/MultipleIndicesPermissionsTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/MultipleIndicesPermissionsTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/integration/MultipleIndicesPermissionsTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/MultipleIndicesPermissionsTests.java diff --git a/shield/src/test/java/org/elasticsearch/integration/PermissionPrecedenceTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/PermissionPrecedenceTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/integration/PermissionPrecedenceTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/PermissionPrecedenceTests.java diff --git a/shield/src/test/java/org/elasticsearch/integration/ScrollIdSigningTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/ScrollIdSigningTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/integration/ScrollIdSigningTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/ScrollIdSigningTests.java diff --git a/shield/src/test/java/org/elasticsearch/integration/SearchGetAndSuggestPermissionsTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/SearchGetAndSuggestPermissionsTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/integration/SearchGetAndSuggestPermissionsTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/SearchGetAndSuggestPermissionsTests.java diff --git a/shield/src/test/java/org/elasticsearch/integration/SettingsFilterTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/SettingsFilterTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/integration/SettingsFilterTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/SettingsFilterTests.java diff --git a/shield/src/test/java/org/elasticsearch/integration/ShieldCachePermissionTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/ShieldCachePermissionTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/integration/ShieldCachePermissionTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/ShieldCachePermissionTests.java diff --git a/shield/src/test/java/org/elasticsearch/integration/ShieldClearScrollTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/ShieldClearScrollTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/integration/ShieldClearScrollTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/ShieldClearScrollTests.java diff --git a/shield/src/test/java/org/elasticsearch/integration/ldap/AbstractAdLdapRealmTestCase.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/ldap/AbstractAdLdapRealmTestCase.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/integration/ldap/AbstractAdLdapRealmTestCase.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/ldap/AbstractAdLdapRealmTestCase.java diff --git a/shield/src/test/java/org/elasticsearch/integration/ldap/GroupMappingTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/ldap/GroupMappingTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/integration/ldap/GroupMappingTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/ldap/GroupMappingTests.java diff --git a/shield/src/test/java/org/elasticsearch/integration/ldap/MultiGroupMappingTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/ldap/MultiGroupMappingTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/integration/ldap/MultiGroupMappingTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/integration/ldap/MultiGroupMappingTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/ShieldPluginEnabledDisabledTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/ShieldPluginEnabledDisabledTests.java similarity index 96% rename from shield/src/test/java/org/elasticsearch/shield/ShieldPluginEnabledDisabledTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/ShieldPluginEnabledDisabledTests.java index 2cc1c2e190e..c0e03eec664 100644 --- a/shield/src/test/java/org/elasticsearch/shield/ShieldPluginEnabledDisabledTests.java +++ b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/ShieldPluginEnabledDisabledTests.java @@ -24,6 +24,7 @@ import org.elasticsearch.test.rest.client.http.HttpResponse; import org.elasticsearch.test.rest.json.JsonPath; import org.elasticsearch.transport.Transport; import org.elasticsearch.transport.TransportService; +import org.elasticsearch.xpack.XPackPlugin; import org.hamcrest.Matcher; import org.junit.After; import org.junit.BeforeClass; @@ -56,6 +57,10 @@ public class ShieldPluginEnabledDisabledTests extends ShieldIntegTestCase { logger.info("cleanup: enabling licensing..."); LicensingTests.enableLicensing(); } + @Override + protected Class xpackPluginClass() { + return LicensingTests.InternalXPackPlugin.class; + } @Override protected Settings nodeSettings(int nodeOrdinal) { @@ -75,16 +80,6 @@ public class ShieldPluginEnabledDisabledTests extends ShieldIntegTestCase { .build(); } - @Override - protected Class licensePluginClass() { - return LicensingTests.InternalLicensePlugin.class; - } - - @Override - protected String licensePluginName() { - return LicensingTests.InternalLicensePlugin.NAME; - } - public void testTransportEnabledDisabled() throws Exception { for (TransportService service : internalCluster().getInstances(TransportService.class)) { Matcher matcher = instanceOf(ShieldServerTransportService.class); diff --git a/shield/src/test/java/org/elasticsearch/shield/ShieldPluginSettingsTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/ShieldPluginSettingsTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/ShieldPluginSettingsTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/ShieldPluginSettingsTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/ShieldPluginTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/ShieldPluginTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/ShieldPluginTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/ShieldPluginTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/UserTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/UserTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/UserTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/UserTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/VersionCompatibilityTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/VersionCompatibilityTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/VersionCompatibilityTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/VersionCompatibilityTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/action/ShieldActionFilterTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/action/ShieldActionFilterTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/action/ShieldActionFilterTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/action/ShieldActionFilterTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/action/ShieldActionMapperTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/action/ShieldActionMapperTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/action/ShieldActionMapperTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/action/ShieldActionMapperTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/audit/AuditTrailModuleTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/audit/AuditTrailModuleTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/audit/AuditTrailModuleTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/audit/AuditTrailModuleTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/audit/AuditTrailServiceTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/audit/AuditTrailServiceTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/audit/AuditTrailServiceTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/audit/AuditTrailServiceTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/audit/index/IndexAuditLevelTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/audit/index/IndexAuditLevelTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/audit/index/IndexAuditLevelTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/audit/index/IndexAuditLevelTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/audit/index/IndexAuditTrailEnabledTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/audit/index/IndexAuditTrailEnabledTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/audit/index/IndexAuditTrailEnabledTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/audit/index/IndexAuditTrailEnabledTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/audit/index/IndexAuditTrailTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/audit/index/IndexAuditTrailTests.java similarity index 82% rename from shield/src/test/java/org/elasticsearch/shield/audit/index/IndexAuditTrailTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/audit/index/IndexAuditTrailTests.java index 78214265f81..ecac2284805 100644 --- a/shield/src/test/java/org/elasticsearch/shield/audit/index/IndexAuditTrailTests.java +++ b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/audit/index/IndexAuditTrailTests.java @@ -219,20 +219,20 @@ public class IndexAuditTrailTests extends ShieldIntegTestCase { SearchHit hit = getIndexedAuditMessage(); assertAuditMessage(hit, "transport", "anonymous_access_denied"); - + Map sourceMap = hit.sourceAsMap(); if (message instanceof RemoteHostMockMessage) { - assertEquals(remoteHostAddress(), hit.field("origin_address").getValue()); + assertEquals(remoteHostAddress(), sourceMap.get("origin_address")); } else { - assertEquals("local[local_host]", hit.field("origin_address").getValue()); + assertEquals("local[local_host]", sourceMap.get("origin_address")); } - assertEquals("_action", hit.field("action").getValue()); - assertEquals("transport", hit.field("origin_type").getValue()); + assertEquals("_action", sourceMap.get("action")); + assertEquals("transport", sourceMap.get("origin_type")); if (message instanceof IndicesRequest) { - List indices = hit.field("indices").getValues(); + List indices = (List) sourceMap.get("indices"); assertThat(indices, contains((Object[]) ((IndicesRequest) message).indices())); } - assertEquals(hit.field("request").getValue(), message.getClass().getSimpleName()); + assertEquals(sourceMap.get("request"), message.getClass().getSimpleName()); } public void testAnonymousAccessDeniedTransportMuted() throws Exception { @@ -256,10 +256,11 @@ public class IndexAuditTrailTests extends ShieldIntegTestCase { SearchHit hit = getIndexedAuditMessage(); assertAuditMessage(hit, "rest", "anonymous_access_denied"); - assertThat(NetworkAddress.formatAddress(InetAddress.getLoopbackAddress()), equalTo(hit.field("origin_address").getValue())); - assertThat("_uri", equalTo(hit.field("uri").getValue())); - assertThat(hit.field("origin_type").getValue(), is("rest")); - assertThat(hit.field("request_body").getValue(), notNullValue()); + Map sourceMap = hit.sourceAsMap(); + assertThat(NetworkAddress.formatAddress(InetAddress.getLoopbackAddress()), equalTo(sourceMap.get("origin_address"))); + assertThat("_uri", equalTo(sourceMap.get("uri"))); + assertThat(sourceMap.get("origin_type"), is("rest")); + assertThat(sourceMap.get("request_body"), notNullValue()); } public void testAnonymousAccessDeniedRestMuted() throws Exception { @@ -281,19 +282,19 @@ public class IndexAuditTrailTests extends ShieldIntegTestCase { awaitAuditDocumentCreation(resolveIndexName()); SearchHit hit = getIndexedAuditMessage(); - + Map sourceMap = hit.sourceAsMap(); assertAuditMessage(hit, "transport", "authentication_failed"); if (message instanceof RemoteHostMockMessage) { - assertEquals(remoteHostAddress(), hit.field("origin_address").getValue()); + assertEquals(remoteHostAddress(), sourceMap.get("origin_address")); } else { - assertEquals("local[local_host]", hit.field("origin_address").getValue()); + assertEquals("local[local_host]", sourceMap.get("origin_address")); } - assertEquals("_principal", hit.field("principal").getValue()); - assertEquals("_action", hit.field("action").getValue()); - assertEquals("transport", hit.field("origin_type").getValue()); - assertEquals(hit.field("request").getValue(), message.getClass().getSimpleName()); + assertEquals("_principal", sourceMap.get("principal")); + assertEquals("_action", sourceMap.get("action")); + assertEquals("transport", sourceMap.get("origin_type")); + assertEquals(sourceMap.get("request"), message.getClass().getSimpleName()); } public void testAuthenticationFailedTransportNoToken() throws Exception { @@ -305,21 +306,21 @@ public class IndexAuditTrailTests extends ShieldIntegTestCase { SearchHit hit = getIndexedAuditMessage(); assertAuditMessage(hit, "transport", "authentication_failed"); - + Map sourceMap = hit.sourceAsMap(); if (message instanceof RemoteHostMockMessage) { - assertEquals(remoteHostAddress(), hit.field("origin_address").getValue()); + assertEquals(remoteHostAddress(), sourceMap.get("origin_address")); } else { - assertEquals("local[local_host]", hit.field("origin_address").getValue()); + assertEquals("local[local_host]", sourceMap.get("origin_address")); } - assertThat(hit.field("principal"), nullValue()); - assertEquals("_action", hit.field("action").getValue()); - assertEquals("transport", hit.field("origin_type").getValue()); + assertThat(sourceMap.get("principal"), nullValue()); + assertEquals("_action", sourceMap.get("action")); + assertEquals("transport", sourceMap.get("origin_type")); if (message instanceof IndicesRequest) { - List indices = hit.field("indices").getValues(); + List indices = (List) sourceMap.get("indices"); assertThat(indices, contains((Object[]) ((IndicesRequest) message).indices())); } - assertEquals(hit.field("request").getValue(), message.getClass().getSimpleName()); + assertEquals(sourceMap.get("request"), message.getClass().getSimpleName()); } public void testAuthenticationFailed_Transport_Muted() throws Exception { @@ -355,11 +356,12 @@ public class IndexAuditTrailTests extends ShieldIntegTestCase { SearchHit hit = getIndexedAuditMessage(); assertAuditMessage(hit, "rest", "authentication_failed"); - assertThat(hit.field("principal").getValue(), is((Object) "_principal")); - assertThat("127.0.0.1", equalTo(hit.field("origin_address").getValue())); - assertThat("_uri", equalTo(hit.field("uri").getValue())); - assertThat(hit.field("origin_type").getValue(), is("rest")); - assertThat(hit.field("request_body").getValue(), notNullValue()); + Map sourceMap = hit.sourceAsMap(); + assertThat(sourceMap.get("principal"), is((Object) "_principal")); + assertThat("127.0.0.1", equalTo(sourceMap.get("origin_address"))); + assertThat("_uri", equalTo(sourceMap.get("uri"))); + assertThat(sourceMap.get("origin_type"), is("rest")); + assertThat(sourceMap.get("request_body"), notNullValue()); } public void testAuthenticationFailedRestNoToken() throws Exception { @@ -371,11 +373,12 @@ public class IndexAuditTrailTests extends ShieldIntegTestCase { SearchHit hit = getIndexedAuditMessage(); assertAuditMessage(hit, "rest", "authentication_failed"); - assertThat(hit.field("principal"), nullValue()); - assertThat("127.0.0.1", equalTo(hit.field("origin_address").getValue())); - assertThat("_uri", equalTo(hit.field("uri").getValue())); - assertThat(hit.field("origin_type").getValue(), is("rest")); - assertThat(hit.field("request_body").getValue(), notNullValue()); + Map sourceMap = hit.sourceAsMap(); + assertThat(sourceMap.get("principal"), nullValue()); + assertThat("127.0.0.1", equalTo(sourceMap.get("origin_address"))); + assertThat("_uri", equalTo(sourceMap.get("uri"))); + assertThat(sourceMap.get("origin_type"), is("rest")); + assertThat(sourceMap.get("request_body"), notNullValue()); } public void testAuthenticationFailedRestMuted() throws Exception { @@ -411,22 +414,23 @@ public class IndexAuditTrailTests extends ShieldIntegTestCase { SearchHit hit = getIndexedAuditMessage(); assertAuditMessage(hit, "transport", "authentication_failed"); + Map sourceMap = hit.sourceAsMap(); if (message instanceof RemoteHostMockMessage) { - assertEquals(remoteHostAddress(), hit.field("origin_address").getValue()); + assertEquals(remoteHostAddress(), sourceMap.get("origin_address")); } else { - assertEquals("local[local_host]", hit.field("origin_address").getValue()); + assertEquals("local[local_host]", sourceMap.get("origin_address")); } - assertEquals("transport", hit.field("origin_type").getValue()); - assertEquals("_principal", hit.field("principal").getValue()); - assertEquals("_action", hit.field("action").getValue()); - assertEquals("_realm", hit.field("realm").getValue()); + assertEquals("transport", sourceMap.get("origin_type")); + assertEquals("_principal", sourceMap.get("principal")); + assertEquals("_action", sourceMap.get("action")); + assertEquals("_realm", sourceMap.get("realm")); if (message instanceof IndicesRequest) { - List indices = hit.field("indices").getValues(); + List indices = (List) sourceMap.get("indices"); assertThat(indices, contains((Object[]) ((IndicesRequest)message).indices())); } - assertEquals(hit.field("request").getValue(), message.getClass().getSimpleName()); + assertEquals(sourceMap.get("request"), message.getClass().getSimpleName()); } public void testAuthenticationFailedTransportRealmMuted() throws Exception { @@ -450,11 +454,12 @@ public class IndexAuditTrailTests extends ShieldIntegTestCase { SearchHit hit = getIndexedAuditMessage(); assertAuditMessage(hit, "rest", "authentication_failed"); - assertThat("127.0.0.1", equalTo(hit.field("origin_address").getValue())); - assertThat("_uri", equalTo(hit.field("uri").getValue())); - assertEquals("_realm", hit.field("realm").getValue()); - assertThat(hit.field("origin_type").getValue(), is("rest")); - assertThat(hit.field("request_body").getValue(), notNullValue()); + Map sourceMap = hit.sourceAsMap(); + assertThat("127.0.0.1", equalTo(sourceMap.get("origin_address"))); + assertThat("_uri", equalTo(sourceMap.get("uri"))); + assertEquals("_realm", sourceMap.get("realm")); + assertThat(sourceMap.get("origin_type"), is("rest")); + assertThat(sourceMap.get("request_body"), notNullValue()); } public void testAuthenticationFailedRestRealmMuted() throws Exception { @@ -484,19 +489,20 @@ public class IndexAuditTrailTests extends ShieldIntegTestCase { SearchHit hit = getIndexedAuditMessage(); assertAuditMessage(hit, "transport", "access_granted"); - assertEquals("transport", hit.field("origin_type").getValue()); + Map sourceMap = hit.sourceAsMap(); + assertEquals("transport", sourceMap.get("origin_type")); if (runAs) { - assertThat(hit.field("principal").getValue(), is("running as")); - assertThat(hit.field("run_by_principal").getValue(), is("_username")); + assertThat(sourceMap.get("principal"), is("running as")); + assertThat(sourceMap.get("run_by_principal"), is("_username")); } else { - assertEquals("_username", hit.field("principal").getValue()); + assertEquals("_username", sourceMap.get("principal")); } - assertEquals("_action", hit.field("action").getValue()); + assertEquals("_action", sourceMap.get("action")); if (message instanceof IndicesRequest) { - List indices = hit.field("indices").getValues(); + List indices = (List) sourceMap.get("indices"); assertThat(indices, contains((Object[]) ((IndicesRequest)message).indices())); } - assertEquals(hit.field("request").getValue(), message.getClass().getSimpleName()); + assertEquals(sourceMap.get("request"), message.getClass().getSimpleName()); } public void testAccessGrantedMuted() throws Exception { @@ -518,10 +524,11 @@ public class IndexAuditTrailTests extends ShieldIntegTestCase { SearchHit hit = getIndexedAuditMessage(); assertAuditMessage(hit, "transport", "access_granted"); - assertEquals("transport", hit.field("origin_type").getValue()); - assertEquals(User.SYSTEM.principal(), hit.field("principal").getValue()); - assertEquals("internal:_action", hit.field("action").getValue()); - assertEquals(hit.field("request").getValue(), message.getClass().getSimpleName()); + Map sourceMap = hit.sourceAsMap(); + assertEquals("transport", sourceMap.get("origin_type")); + assertEquals(User.SYSTEM.principal(), sourceMap.get("principal")); + assertEquals("internal:_action", sourceMap.get("action")); + assertEquals(sourceMap.get("request"), message.getClass().getSimpleName()); } public void testSystemAccessGrantedMuted() throws Exception { @@ -550,20 +557,21 @@ public class IndexAuditTrailTests extends ShieldIntegTestCase { awaitAuditDocumentCreation(resolveIndexName()); SearchHit hit = getIndexedAuditMessage(); + Map sourceMap = hit.sourceAsMap(); assertAuditMessage(hit, "transport", "access_denied"); - assertEquals("transport", hit.field("origin_type").getValue()); + assertEquals("transport", sourceMap.get("origin_type")); if (runAs) { - assertThat(hit.field("principal").getValue(), is("running as")); - assertThat(hit.field("run_by_principal").getValue(), is("_username")); + assertThat(sourceMap.get("principal"), is("running as")); + assertThat(sourceMap.get("run_by_principal"), is("_username")); } else { - assertEquals("_username", hit.field("principal").getValue()); + assertEquals("_username", sourceMap.get("principal")); } - assertEquals("_action", hit.field("action").getValue()); + assertEquals("_action", sourceMap.get("action")); if (message instanceof IndicesRequest) { - List indices = hit.field("indices").getValues(); + List indices = (List) sourceMap.get("indices"); assertThat(indices, contains((Object[]) ((IndicesRequest)message).indices())); } - assertEquals(hit.field("request").getValue(), message.getClass().getSimpleName()); + assertEquals(sourceMap.get("request"), message.getClass().getSimpleName()); } public void testAccessDenied_Muted() throws Exception { @@ -585,12 +593,12 @@ public class IndexAuditTrailTests extends ShieldIntegTestCase { awaitAuditDocumentCreation(resolveIndexName()); SearchHit hit = getIndexedAuditMessage(); - + Map sourceMap = hit.sourceAsMap(); assertAuditMessage(hit, "transport", "tampered_request"); - assertEquals("transport", hit.field("origin_type").getValue()); - assertThat(hit.field("principal"), is(nullValue())); - assertEquals("_action", hit.field("action").getValue()); - assertEquals(hit.field("request").getValue(), message.getClass().getSimpleName()); + assertEquals("transport", sourceMap.get("origin_type")); + assertThat(sourceMap.get("principal"), is(nullValue())); + assertEquals("_action", sourceMap.get("action")); + assertEquals(sourceMap.get("request"), message.getClass().getSimpleName()); } public void testTamperedRequestWithUser() throws Exception { @@ -609,15 +617,16 @@ public class IndexAuditTrailTests extends ShieldIntegTestCase { SearchHit hit = getIndexedAuditMessage(); assertAuditMessage(hit, "transport", "tampered_request"); - assertEquals("transport", hit.field("origin_type").getValue()); + Map sourceMap = hit.sourceAsMap(); + assertEquals("transport", sourceMap.get("origin_type")); if (runAs) { - assertThat(hit.field("principal").getValue(), is("running as")); - assertThat(hit.field("run_by_principal").getValue(), is("_username")); + assertThat(sourceMap.get("principal"), is("running as")); + assertThat(sourceMap.get("run_by_principal"), is("_username")); } else { - assertEquals("_username", hit.field("principal").getValue()); + assertEquals("_username", sourceMap.get("principal")); } - assertEquals("_action", hit.field("action").getValue()); - assertEquals(hit.field("request").getValue(), message.getClass().getSimpleName()); + assertEquals("_action", sourceMap.get("action")); + assertEquals(sourceMap.get("request"), message.getClass().getSimpleName()); } public void testTamperedRequestMuted() throws Exception { @@ -646,8 +655,9 @@ public class IndexAuditTrailTests extends ShieldIntegTestCase { SearchHit hit = getIndexedAuditMessage(); assertAuditMessage(hit, "ip_filter", "connection_granted"); - assertEquals("allow default:accept_all", hit.field("rule").getValue()); - assertEquals("default", hit.field("transport_profile").getValue()); + Map sourceMap = hit.sourceAsMap(); + assertEquals("allow default:accept_all", sourceMap.get("rule")); + assertEquals("default", sourceMap.get("transport_profile")); } public void testConnectionGrantedMuted() throws Exception { @@ -673,8 +683,9 @@ public class IndexAuditTrailTests extends ShieldIntegTestCase { SearchHit hit = getIndexedAuditMessage(); assertAuditMessage(hit, "ip_filter", "connection_denied"); - assertEquals("deny _all", hit.field("rule").getValue()); - assertEquals("default", hit.field("transport_profile").getValue()); + Map sourceMap = hit.sourceAsMap(); + assertEquals("deny _all", sourceMap.get("rule")); + assertEquals("default", sourceMap.get("transport_profile")); } public void testConnectionDeniedMuted() throws Exception { @@ -699,11 +710,12 @@ public class IndexAuditTrailTests extends ShieldIntegTestCase { SearchHit hit = getIndexedAuditMessage(); assertAuditMessage(hit, "transport", "run_as_granted"); - assertEquals("transport", hit.field("origin_type").getValue()); - assertThat(hit.field("principal").getValue(), is("_username")); - assertThat(hit.field("run_as_principal").getValue(), is("running as")); - assertEquals("_action", hit.field("action").getValue()); - assertEquals(hit.field("request").getValue(), message.getClass().getSimpleName()); + Map sourceMap = hit.sourceAsMap(); + assertEquals("transport", sourceMap.get("origin_type")); + assertThat(sourceMap.get("principal"), is("_username")); + assertThat(sourceMap.get("run_as_principal"), is("running as")); + assertEquals("_action", sourceMap.get("action")); + assertEquals(sourceMap.get("request"), message.getClass().getSimpleName()); } public void testRunAsGrantedMuted() throws Exception { @@ -727,11 +739,12 @@ public class IndexAuditTrailTests extends ShieldIntegTestCase { SearchHit hit = getIndexedAuditMessage(); assertAuditMessage(hit, "transport", "run_as_denied"); - assertEquals("transport", hit.field("origin_type").getValue()); - assertThat(hit.field("principal").getValue(), is("_username")); - assertThat(hit.field("run_as_principal").getValue(), is("running as")); - assertEquals("_action", hit.field("action").getValue()); - assertEquals(hit.field("request").getValue(), message.getClass().getSimpleName()); + Map sourceMap = hit.sourceAsMap(); + assertEquals("transport", sourceMap.get("origin_type")); + assertThat(sourceMap.get("principal"), is("_username")); + assertThat(sourceMap.get("run_as_principal"), is("running as")); + assertEquals("_action", sourceMap.get("action")); + assertEquals(sourceMap.get("request"), message.getClass().getSimpleName()); } public void testRunAsDeniedMuted() throws Exception { @@ -747,15 +760,16 @@ public class IndexAuditTrailTests extends ShieldIntegTestCase { } private void assertAuditMessage(SearchHit hit, String layer, String type) { - assertThat(hit.field("@timestamp").getValue(), notNullValue()); - DateTime dateTime = ISODateTimeFormat.dateTimeParser().withZoneUTC().parseDateTime(hit.field("@timestamp").getValue()); + Map sourceMap = hit.sourceAsMap(); + assertThat(sourceMap.get("@timestamp"), notNullValue()); + DateTime dateTime = ISODateTimeFormat.dateTimeParser().withZoneUTC().parseDateTime((String) sourceMap.get("@timestamp")); assertThat(dateTime.isBefore(DateTime.now(DateTimeZone.UTC)), is(true)); - assertThat(DummyTransportAddress.INSTANCE.getHost(), equalTo(hit.field("node_host_name").getValue())); - assertThat(DummyTransportAddress.INSTANCE.getAddress(), equalTo(hit.field("node_host_address").getValue())); + assertThat(DummyTransportAddress.INSTANCE.getHost(), equalTo(sourceMap.get("node_host_name"))); + assertThat(DummyTransportAddress.INSTANCE.getAddress(), equalTo(sourceMap.get("node_host_address"))); - assertEquals(layer, hit.field("layer").getValue()); - assertEquals(type, hit.field("event_type").getValue()); + assertEquals(layer, sourceMap.get("layer")); + assertEquals(type, sourceMap.get("event_type")); } private static class LocalHostMockMessage extends TransportMessage { @@ -820,7 +834,6 @@ public class IndexAuditTrailTests extends ShieldIntegTestCase { SearchResponse response = getClient().prepareSearch(resolveIndexName()) .setTypes(IndexAuditTrail.DOC_TYPE) - .fields(fieldList()) .execute().actionGet(); assertEquals(1, response.getHits().getTotalHits()); diff --git a/shield/src/test/java/org/elasticsearch/shield/audit/index/IndexAuditTrailUpdateMappingTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/audit/index/IndexAuditTrailUpdateMappingTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/audit/index/IndexAuditTrailUpdateMappingTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/audit/index/IndexAuditTrailUpdateMappingTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/audit/index/RemoteIndexAuditTrailStartingTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/audit/index/RemoteIndexAuditTrailStartingTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/audit/index/RemoteIndexAuditTrailStartingTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/audit/index/RemoteIndexAuditTrailStartingTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/audit/logfile/CapturingLogger.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/audit/logfile/CapturingLogger.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/audit/logfile/CapturingLogger.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/audit/logfile/CapturingLogger.java diff --git a/shield/src/test/java/org/elasticsearch/shield/audit/logfile/LoggingAuditTrailTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/audit/logfile/LoggingAuditTrailTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/audit/logfile/LoggingAuditTrailTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/audit/logfile/LoggingAuditTrailTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/AnonymousUserHolderTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/AnonymousUserHolderTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authc/AnonymousUserHolderTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/AnonymousUserHolderTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/AnonymousUserTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/AnonymousUserTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authc/AnonymousUserTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/AnonymousUserTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/AuthenticationModuleTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/AuthenticationModuleTests.java similarity index 98% rename from shield/src/test/java/org/elasticsearch/shield/authc/AuthenticationModuleTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/AuthenticationModuleTests.java index e9d74f77d2a..eabded21bba 100644 --- a/shield/src/test/java/org/elasticsearch/shield/authc/AuthenticationModuleTests.java +++ b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/AuthenticationModuleTests.java @@ -25,9 +25,7 @@ import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPoolModule; import org.elasticsearch.transport.TransportMessage; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.*; /** * Unit tests for the AuthenticationModule diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/InternalAuthenticationServiceTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/InternalAuthenticationServiceTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authc/InternalAuthenticationServiceTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/InternalAuthenticationServiceTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/RealmsTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/RealmsTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authc/RealmsTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/RealmsTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/RunAsIntegTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/RunAsIntegTests.java similarity index 99% rename from shield/src/test/java/org/elasticsearch/shield/authc/RunAsIntegTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/RunAsIntegTests.java index df3294aee2c..78bda6d2bd7 100644 --- a/shield/src/test/java/org/elasticsearch/shield/authc/RunAsIntegTests.java +++ b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/RunAsIntegTests.java @@ -13,7 +13,7 @@ import org.elasticsearch.client.transport.TransportClient; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.node.Node; -import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.authc.support.SecuredString; import org.elasticsearch.shield.authc.support.SecuredStringTests; import org.elasticsearch.shield.authc.support.UsernamePasswordToken; @@ -194,7 +194,7 @@ public class RunAsIntegTests extends ShieldIntegTestCase { return TransportClient.builder() .settings(settings) - .addPlugin(ShieldPlugin.class) + .addPlugin(XPackPlugin.class) .build() .addTransportAddress(publishAddress); } diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/activedirectory/ActiveDirectoryGroupsResolverTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/activedirectory/ActiveDirectoryGroupsResolverTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authc/activedirectory/ActiveDirectoryGroupsResolverTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/activedirectory/ActiveDirectoryGroupsResolverTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/activedirectory/ActiveDirectoryRealmTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/activedirectory/ActiveDirectoryRealmTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authc/activedirectory/ActiveDirectoryRealmTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/activedirectory/ActiveDirectoryRealmTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/activedirectory/ActiveDirectorySessionFactoryTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/activedirectory/ActiveDirectorySessionFactoryTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authc/activedirectory/ActiveDirectorySessionFactoryTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/activedirectory/ActiveDirectorySessionFactoryTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/esusers/ESUsersRealmTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/esusers/ESUsersRealmTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authc/esusers/ESUsersRealmTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/esusers/ESUsersRealmTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/esusers/FileUserPasswdStoreTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/esusers/FileUserPasswdStoreTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authc/esusers/FileUserPasswdStoreTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/esusers/FileUserPasswdStoreTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/esusers/FileUserRolesStoreTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/esusers/FileUserRolesStoreTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authc/esusers/FileUserRolesStoreTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/esusers/FileUserRolesStoreTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/esusers/tool/ESUsersToolTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/esusers/tool/ESUsersToolTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authc/esusers/tool/ESUsersToolTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/esusers/tool/ESUsersToolTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/ldap/LdapRealmTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/ldap/LdapRealmTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authc/ldap/LdapRealmTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/ldap/LdapRealmTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/ldap/LdapSessionFactoryTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/ldap/LdapSessionFactoryTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authc/ldap/LdapSessionFactoryTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/ldap/LdapSessionFactoryTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/ldap/LdapUserSearchSessionFactoryTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/ldap/LdapUserSearchSessionFactoryTests.java similarity index 99% rename from shield/src/test/java/org/elasticsearch/shield/authc/ldap/LdapUserSearchSessionFactoryTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/ldap/LdapUserSearchSessionFactoryTests.java index 2c9e2392e6e..3c87f839910 100644 --- a/shield/src/test/java/org/elasticsearch/shield/authc/ldap/LdapUserSearchSessionFactoryTests.java +++ b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/ldap/LdapUserSearchSessionFactoryTests.java @@ -20,10 +20,10 @@ import org.elasticsearch.common.Strings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.env.Environment; -import org.elasticsearch.license.plugin.LicensePlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.node.MockNode; import org.elasticsearch.node.Node; -import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.authc.RealmConfig; import org.elasticsearch.shield.authc.activedirectory.ActiveDirectorySessionFactoryTests; import org.elasticsearch.shield.authc.ldap.support.LdapSearchScope; @@ -515,7 +515,7 @@ public class LdapUserSearchSessionFactoryTests extends LdapTestCase { } builder.put("path.home", createTempDir()); - try (Node node = new MockNode(builder.build(), Version.CURRENT, Arrays.asList(ShieldPlugin.class, LicensePlugin.class))) { + try (Node node = new MockNode(builder.build(), Version.CURRENT, Arrays.asList(XPackPlugin.class, XPackPlugin.class))) { node.start(); } } diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/ldap/OpenLdapTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/ldap/OpenLdapTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authc/ldap/OpenLdapTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/ldap/OpenLdapTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/ldap/SearchGroupsResolverTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/ldap/SearchGroupsResolverTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authc/ldap/SearchGroupsResolverTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/ldap/SearchGroupsResolverTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/ldap/UserAttributeGroupsResolverTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/ldap/UserAttributeGroupsResolverTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authc/ldap/UserAttributeGroupsResolverTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/ldap/UserAttributeGroupsResolverTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/ldap/support/LDAPServersTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/ldap/support/LDAPServersTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authc/ldap/support/LDAPServersTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/ldap/support/LDAPServersTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/ldap/support/LdapTestCase.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/ldap/support/LdapTestCase.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authc/ldap/support/LdapTestCase.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/ldap/support/LdapTestCase.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/ldap/support/SessionFactoryTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/ldap/support/SessionFactoryTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authc/ldap/support/SessionFactoryTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/ldap/support/SessionFactoryTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/pki/PkiAuthenticationTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/pki/PkiAuthenticationTests.java similarity index 98% rename from shield/src/test/java/org/elasticsearch/shield/authc/pki/PkiAuthenticationTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/pki/PkiAuthenticationTests.java index 0c8f479aebd..43a9227f560 100644 --- a/shield/src/test/java/org/elasticsearch/shield/authc/pki/PkiAuthenticationTests.java +++ b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/pki/PkiAuthenticationTests.java @@ -18,7 +18,7 @@ import org.elasticsearch.common.transport.InetSocketTransportAddress; import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.http.HttpServerTransport; import org.elasticsearch.node.Node; -import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.transport.SSLClientAuth; import org.elasticsearch.shield.transport.netty.ShieldNettyHttpServerTransport; import org.elasticsearch.test.ESIntegTestCase.ClusterScope; @@ -46,6 +46,7 @@ import static org.hamcrest.Matchers.is; */ @ClusterScope(numClientNodes = 0, numDataNodes = 1) public class PkiAuthenticationTests extends ShieldIntegTestCase { + @Override protected Settings nodeSettings(int nodeOrdinal) { return Settings.builder() @@ -139,7 +140,7 @@ public class PkiAuthenticationTests extends ShieldIntegTestCase { .put("cluster.name", internalCluster().getClusterName()); builder.remove("shield.user"); builder.remove("request.headers.Authorization"); - return TransportClient.builder().settings(builder).addPlugin(ShieldPlugin.class).build(); + return TransportClient.builder().settings(builder).addPlugin(XPackPlugin.class).build(); } private String getNodeUrl() { diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/pki/PkiOptionalClientAuthTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/pki/PkiOptionalClientAuthTests.java similarity index 98% rename from shield/src/test/java/org/elasticsearch/shield/authc/pki/PkiOptionalClientAuthTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/pki/PkiOptionalClientAuthTests.java index 8769004b0fa..9a8d4e07ce6 100644 --- a/shield/src/test/java/org/elasticsearch/shield/authc/pki/PkiOptionalClientAuthTests.java +++ b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/pki/PkiOptionalClientAuthTests.java @@ -12,7 +12,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.InetSocketTransportAddress; import org.elasticsearch.http.HttpServerTransport; import org.elasticsearch.node.Node; -import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.authc.support.SecuredString; import org.elasticsearch.shield.authc.support.UsernamePasswordToken; import org.elasticsearch.shield.transport.SSLClientAuth; @@ -105,7 +105,7 @@ public class PkiOptionalClientAuthTests extends ShieldIntegTestCase { .build(); - try (TransportClient client = TransportClient.builder().settings(settings).addPlugin(ShieldPlugin.class).build()) { + try (TransportClient client = TransportClient.builder().settings(settings).addPlugin(XPackPlugin.class).build()) { client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getLoopbackAddress(), port)); assertGreenClusterState(client); } diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/pki/PkiRealmTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/pki/PkiRealmTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authc/pki/PkiRealmTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/pki/PkiRealmTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/pki/PkiWithoutClientAuthenticationTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/pki/PkiWithoutClientAuthenticationTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authc/pki/PkiWithoutClientAuthenticationTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/pki/PkiWithoutClientAuthenticationTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/pki/PkiWithoutSSLTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/pki/PkiWithoutSSLTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authc/pki/PkiWithoutSSLTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/pki/PkiWithoutSSLTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/support/BCryptTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/support/BCryptTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authc/support/BCryptTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/support/BCryptTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/support/CachingUsernamePasswordRealmTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/support/CachingUsernamePasswordRealmTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authc/support/CachingUsernamePasswordRealmTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/support/CachingUsernamePasswordRealmTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/support/DnRoleMapperTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/support/DnRoleMapperTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authc/support/DnRoleMapperTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/support/DnRoleMapperTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/support/HasherTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/support/HasherTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authc/support/HasherTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/support/HasherTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/support/SecuredStringTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/support/SecuredStringTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authc/support/SecuredStringTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/support/SecuredStringTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authc/support/UsernamePasswordTokenTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/support/UsernamePasswordTokenTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authc/support/UsernamePasswordTokenTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authc/support/UsernamePasswordTokenTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authz/AnalyzeTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authz/AnalyzeTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authz/AnalyzeTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authz/AnalyzeTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authz/IndexAliasesTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authz/IndexAliasesTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authz/IndexAliasesTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authz/IndexAliasesTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authz/InternalAuthorizationServiceTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authz/InternalAuthorizationServiceTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authz/InternalAuthorizationServiceTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authz/InternalAuthorizationServiceTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authz/PermissionTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authz/PermissionTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authz/PermissionTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authz/PermissionTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authz/PrivilegeTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authz/PrivilegeTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authz/PrivilegeTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authz/PrivilegeTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authz/SystemRoleTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authz/SystemRoleTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authz/SystemRoleTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authz/SystemRoleTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authz/accesscontrol/DocumentSubsetReaderTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authz/accesscontrol/DocumentSubsetReaderTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authz/accesscontrol/DocumentSubsetReaderTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authz/accesscontrol/DocumentSubsetReaderTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authz/accesscontrol/FieldDataCacheWithFieldSubsetReaderTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authz/accesscontrol/FieldDataCacheWithFieldSubsetReaderTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authz/accesscontrol/FieldDataCacheWithFieldSubsetReaderTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authz/accesscontrol/FieldDataCacheWithFieldSubsetReaderTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authz/accesscontrol/FieldSubsetReaderTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authz/accesscontrol/FieldSubsetReaderTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authz/accesscontrol/FieldSubsetReaderTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authz/accesscontrol/FieldSubsetReaderTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authz/accesscontrol/IndicesPermissionTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authz/accesscontrol/IndicesPermissionTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authz/accesscontrol/IndicesPermissionTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authz/accesscontrol/IndicesPermissionTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authz/accesscontrol/ShieldIndexSearcherWrapperIntegrationTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authz/accesscontrol/ShieldIndexSearcherWrapperIntegrationTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authz/accesscontrol/ShieldIndexSearcherWrapperIntegrationTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authz/accesscontrol/ShieldIndexSearcherWrapperIntegrationTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authz/accesscontrol/ShieldIndexSearcherWrapperUnitTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authz/accesscontrol/ShieldIndexSearcherWrapperUnitTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authz/accesscontrol/ShieldIndexSearcherWrapperUnitTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authz/accesscontrol/ShieldIndexSearcherWrapperUnitTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authz/indicesresolver/DefaultIndicesResolverTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authz/indicesresolver/DefaultIndicesResolverTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authz/indicesresolver/DefaultIndicesResolverTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authz/indicesresolver/DefaultIndicesResolverTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authz/indicesresolver/IndicesAndAliasesResolverIntegrationTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authz/indicesresolver/IndicesAndAliasesResolverIntegrationTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/authz/indicesresolver/IndicesAndAliasesResolverIntegrationTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authz/indicesresolver/IndicesAndAliasesResolverIntegrationTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/authz/store/FileRolesStoreTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authz/store/FileRolesStoreTests.java similarity index 99% rename from shield/src/test/java/org/elasticsearch/shield/authz/store/FileRolesStoreTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authz/store/FileRolesStoreTests.java index 96914edebd3..3140dec76f1 100644 --- a/shield/src/test/java/org/elasticsearch/shield/authz/store/FileRolesStoreTests.java +++ b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/authz/store/FileRolesStoreTests.java @@ -8,6 +8,7 @@ package org.elasticsearch.shield.authz.store; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.env.Environment; import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.audit.logfile.CapturingLogger; import org.elasticsearch.shield.authc.support.RefreshListener; import org.elasticsearch.shield.authz.Permission; diff --git a/shield/src/test/java/org/elasticsearch/shield/crypto/InternalCryptoServiceTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/crypto/InternalCryptoServiceTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/crypto/InternalCryptoServiceTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/crypto/InternalCryptoServiceTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/crypto/tool/SystemKeyToolTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/crypto/tool/SystemKeyToolTests.java similarity index 99% rename from shield/src/test/java/org/elasticsearch/shield/crypto/tool/SystemKeyToolTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/crypto/tool/SystemKeyToolTests.java index f3cad08a0e6..cd2d7b337e0 100644 --- a/shield/src/test/java/org/elasticsearch/shield/crypto/tool/SystemKeyToolTests.java +++ b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/crypto/tool/SystemKeyToolTests.java @@ -11,6 +11,7 @@ import org.elasticsearch.common.cli.Terminal; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.env.Environment; import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.crypto.InternalCryptoService; import org.elasticsearch.shield.crypto.tool.SystemKeyTool.Generate; import org.junit.Before; diff --git a/shield/src/test/java/org/elasticsearch/shield/license/ShieldLicenseStateTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/license/ShieldLicenseStateTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/license/ShieldLicenseStateTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/license/ShieldLicenseStateTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/rest/ShieldRestFilterTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/rest/ShieldRestFilterTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/rest/ShieldRestFilterTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/rest/ShieldRestFilterTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/ssl/ClientSSLServiceTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/ssl/ClientSSLServiceTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/ssl/ClientSSLServiceTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/ssl/ClientSSLServiceTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/ssl/SSLSettingsTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/ssl/SSLSettingsTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/ssl/SSLSettingsTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/ssl/SSLSettingsTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/ssl/ServerSSLServiceTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/ssl/ServerSSLServiceTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/ssl/ServerSSLServiceTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/ssl/ServerSSLServiceTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/support/AutomatonsTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/support/AutomatonsTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/support/AutomatonsTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/support/AutomatonsTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/support/ShieldFilesTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/support/ShieldFilesTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/support/ShieldFilesTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/support/ShieldFilesTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/support/ValidationTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/support/ValidationTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/support/ValidationTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/support/ValidationTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/test/ShieldAssertions.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/test/ShieldAssertions.java similarity index 83% rename from shield/src/test/java/org/elasticsearch/shield/test/ShieldAssertions.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/test/ShieldAssertions.java index 2eae3a18544..9ecd4dc3d07 100644 --- a/shield/src/test/java/org/elasticsearch/shield/test/ShieldAssertions.java +++ b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/test/ShieldAssertions.java @@ -10,7 +10,10 @@ import org.elasticsearch.rest.RestStatus; import org.elasticsearch.shield.ShieldPlugin; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; public class ShieldAssertions { diff --git a/shield/src/test/java/org/elasticsearch/shield/test/ShieldTestUtils.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/test/ShieldTestUtils.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/test/ShieldTestUtils.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/test/ShieldTestUtils.java diff --git a/shield/src/test/java/org/elasticsearch/shield/transport/ClientTransportFilterTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/ClientTransportFilterTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/transport/ClientTransportFilterTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/ClientTransportFilterTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/transport/ServerTransportFilterIntegrationTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/ServerTransportFilterIntegrationTests.java similarity index 97% rename from shield/src/test/java/org/elasticsearch/shield/transport/ServerTransportFilterIntegrationTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/ServerTransportFilterIntegrationTests.java index 63cd66b5445..39ac084ea7c 100644 --- a/shield/src/test/java/org/elasticsearch/shield/transport/ServerTransportFilterIntegrationTests.java +++ b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/ServerTransportFilterIntegrationTests.java @@ -14,7 +14,7 @@ import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.discovery.MasterNotDiscoveredException; import org.elasticsearch.node.MockNode; import org.elasticsearch.node.Node; -import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.authc.esusers.ESUsersRealm; import org.elasticsearch.shield.crypto.InternalCryptoService; import org.elasticsearch.test.ShieldIntegTestCase; @@ -102,7 +102,7 @@ public class ServerTransportFilterIntegrationTests extends ShieldIntegTestCase { .put(InternalCryptoService.FILE_SETTING, systemKeyFile) .put("node.client", true) .build(); - try (Node node = new MockNode(nodeSettings, Version.CURRENT, Arrays.asList(ShieldPlugin.class, licensePluginClass()))) { + try (Node node = new MockNode(nodeSettings, Version.CURRENT, Arrays.asList(XPackPlugin.class))) { node.start(); assertGreenClusterState(node.client()); } @@ -136,7 +136,7 @@ public class ServerTransportFilterIntegrationTests extends ShieldIntegTestCase { .put("path.home", createTempDir()) .put("node.client", true) .build(); - try (Node node = new MockNode(nodeSettings, Version.CURRENT, Arrays.asList(ShieldPlugin.class, licensePluginClass()))) { + try (Node node = new MockNode(nodeSettings, Version.CURRENT, Arrays.asList(XPackPlugin.class))) { node.start(); // assert that node is not connected by waiting for the timeout diff --git a/shield/src/test/java/org/elasticsearch/shield/transport/ServerTransportFilterTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/ServerTransportFilterTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/transport/ServerTransportFilterTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/ServerTransportFilterTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/transport/TransportFilterTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/TransportFilterTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/transport/TransportFilterTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/TransportFilterTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/transport/filter/IPFilterTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/filter/IPFilterTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/transport/filter/IPFilterTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/filter/IPFilterTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/transport/filter/IpFilteringIntegrationTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/filter/IpFilteringIntegrationTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/transport/filter/IpFilteringIntegrationTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/filter/IpFilteringIntegrationTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/transport/filter/IpFilteringUpdateTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/filter/IpFilteringUpdateTests.java similarity index 99% rename from shield/src/test/java/org/elasticsearch/shield/transport/filter/IpFilteringUpdateTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/filter/IpFilteringUpdateTests.java index ec658b00e77..0f9e986dd0b 100644 --- a/shield/src/test/java/org/elasticsearch/shield/transport/filter/IpFilteringUpdateTests.java +++ b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/filter/IpFilteringUpdateTests.java @@ -23,6 +23,7 @@ import static org.hamcrest.Matchers.is; @ClusterScope(scope = TEST, numDataNodes = 1) public class IpFilteringUpdateTests extends ShieldIntegTestCase { + private static int randomClientPort; private final boolean httpEnabled = randomBoolean(); diff --git a/shield/src/test/java/org/elasticsearch/shield/transport/filter/ShieldIpFilterRuleTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/filter/ShieldIpFilterRuleTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/transport/filter/ShieldIpFilterRuleTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/filter/ShieldIpFilterRuleTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/transport/netty/HandshakeWaitingHandlerTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/netty/HandshakeWaitingHandlerTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/transport/netty/HandshakeWaitingHandlerTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/netty/HandshakeWaitingHandlerTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/transport/netty/IPFilterNettyUpstreamHandlerTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/netty/IPFilterNettyUpstreamHandlerTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/transport/netty/IPFilterNettyUpstreamHandlerTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/netty/IPFilterNettyUpstreamHandlerTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/transport/netty/IPHostnameVerificationTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/netty/IPHostnameVerificationTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/transport/netty/IPHostnameVerificationTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/netty/IPHostnameVerificationTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/transport/netty/ShieldNettyHttpServerTransportTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/netty/ShieldNettyHttpServerTransportTests.java similarity index 99% rename from shield/src/test/java/org/elasticsearch/shield/transport/netty/ShieldNettyHttpServerTransportTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/netty/ShieldNettyHttpServerTransportTests.java index f626f7de5a4..f601cf0b5ca 100644 --- a/shield/src/test/java/org/elasticsearch/shield/transport/netty/ShieldNettyHttpServerTransportTests.java +++ b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/netty/ShieldNettyHttpServerTransportTests.java @@ -28,6 +28,7 @@ import static org.hamcrest.Matchers.is; import static org.mockito.Mockito.mock; public class ShieldNettyHttpServerTransportTests extends ESTestCase { + private ServerSSLService serverSSLService; @Before diff --git a/shield/src/test/java/org/elasticsearch/shield/transport/netty/ShieldNettyTransportTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/netty/ShieldNettyTransportTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/transport/netty/ShieldNettyTransportTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/netty/ShieldNettyTransportTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/transport/netty/SslHostnameVerificationTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/netty/SslHostnameVerificationTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/transport/netty/SslHostnameVerificationTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/netty/SslHostnameVerificationTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/transport/ssl/SslClientAuthTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/ssl/SslClientAuthTests.java similarity index 97% rename from shield/src/test/java/org/elasticsearch/shield/transport/ssl/SslClientAuthTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/ssl/SslClientAuthTests.java index a2bbeff457d..3be274dbd61 100644 --- a/shield/src/test/java/org/elasticsearch/shield/transport/ssl/SslClientAuthTests.java +++ b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/ssl/SslClientAuthTests.java @@ -15,7 +15,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.http.HttpServerTransport; import org.elasticsearch.node.Node; -import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.ssl.ClientSSLService; import org.elasticsearch.shield.transport.netty.ShieldNettyHttpServerTransport; import org.elasticsearch.test.ShieldIntegTestCase; @@ -106,7 +106,7 @@ public class SslClientAuthTests extends ShieldIntegTestCase { .put("cluster.name", internalCluster().getClusterName()) .put("shield.user", transportClientUsername() + ":" + new String(transportClientPassword().internalChars())) .build(); - try (TransportClient client = TransportClient.builder().settings(settings).addPlugin(ShieldPlugin.class).addPlugin(licensePluginClass()).build()) { + try (TransportClient client = TransportClient.builder().settings(settings).addPlugin(XPackPlugin.class).build()) { Transport transport = internalCluster().getDataNodeInstance(Transport.class); TransportAddress transportAddress = transport.boundAddress().publishAddress(); client.addTransportAddress(transportAddress); diff --git a/shield/src/test/java/org/elasticsearch/shield/transport/ssl/SslIntegrationTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/ssl/SslIntegrationTests.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/shield/transport/ssl/SslIntegrationTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/ssl/SslIntegrationTests.java diff --git a/shield/src/test/java/org/elasticsearch/shield/transport/ssl/SslMultiPortTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/ssl/SslMultiPortTests.java similarity index 98% rename from shield/src/test/java/org/elasticsearch/shield/transport/ssl/SslMultiPortTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/ssl/SslMultiPortTests.java index 74b5692b03a..37d2267686f 100644 --- a/shield/src/test/java/org/elasticsearch/shield/transport/ssl/SslMultiPortTests.java +++ b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/transport/ssl/SslMultiPortTests.java @@ -10,7 +10,7 @@ import org.elasticsearch.client.transport.TransportClient; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.InetSocketTransportAddress; import org.elasticsearch.common.transport.TransportAddress; -import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.test.ShieldIntegTestCase; import org.elasticsearch.test.ShieldSettingsSource; import org.elasticsearch.transport.Transport; @@ -90,8 +90,7 @@ public class SslMultiPortTests extends ShieldIntegTestCase { .put(additionalSettings) .build(); return TransportClient.builder().settings(settings) - .addPlugin(licensePluginClass()) - .addPlugin(ShieldPlugin.class) + .addPlugin(XPackPlugin.class) .build(); } @@ -218,7 +217,7 @@ public class SslMultiPortTests extends ShieldIntegTestCase { .put("shield.user", DEFAULT_USER_NAME + ":" + DEFAULT_PASSWORD) .put("cluster.name", internalCluster().getClusterName()) .build(); - try (TransportClient transportClient = TransportClient.builder().settings(settings).addPlugin(ShieldPlugin.class).addPlugin(licensePluginClass()).build()) { + try (TransportClient transportClient = TransportClient.builder().settings(settings).addPlugin(XPackPlugin.class).build()) { transportClient.addTransportAddress(new InetSocketTransportAddress(InetAddress.getLoopbackAddress(), getProfilePort("no_ssl"))); assertGreenClusterState(transportClient); } @@ -291,7 +290,7 @@ public class SslMultiPortTests extends ShieldIntegTestCase { .put("shield.ssl.truststore.path", getDataPath("/org/elasticsearch/shield/transport/ssl/certs/simple/truststore-testnode-only.jks")) .put("shield.ssl.truststore.password", "truststore-testnode-only") .build(); - try (TransportClient transportClient = TransportClient.builder().settings(settings).addPlugin(ShieldPlugin.class).addPlugin(licensePluginClass()).build()) { + try (TransportClient transportClient = TransportClient.builder().settings(settings).addPlugin(XPackPlugin.class).build()) { transportClient.addTransportAddress(new InetSocketTransportAddress(InetAddress.getLoopbackAddress(), getProfilePort("no_client_auth"))); assertGreenClusterState(transportClient); } diff --git a/shield/src/test/java/org/elasticsearch/shield/tribe/TribeShieldLoadedTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/tribe/TribeShieldLoadedTests.java similarity index 90% rename from shield/src/test/java/org/elasticsearch/shield/tribe/TribeShieldLoadedTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/tribe/TribeShieldLoadedTests.java index de3f1e53fcc..ebde440376a 100644 --- a/shield/src/test/java/org/elasticsearch/shield/tribe/TribeShieldLoadedTests.java +++ b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/tribe/TribeShieldLoadedTests.java @@ -8,11 +8,10 @@ package org.elasticsearch.shield.tribe; import org.apache.lucene.util.LuceneTestCase; import org.elasticsearch.Version; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.license.plugin.LicensePlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.node.MockNode; import org.elasticsearch.node.Node; import org.elasticsearch.node.NodeBuilder; -import org.elasticsearch.shield.ShieldPlugin; import org.elasticsearch.test.ESTestCase; import java.util.Arrays; @@ -31,7 +30,7 @@ public class TribeShieldLoadedTests extends ESTestCase { //all good if the plugin is loaded on both tribe node and tribe clients, no matter how it gets loaded (manually or from classpath) Settings.Builder builder = defaultSettings(); - try (Node node = new MockNode(builder.build(), Version.CURRENT, Arrays.asList(ShieldPlugin.class, LicensePlugin.class))) { + try (Node node = new MockNode(builder.build(), Version.CURRENT, Arrays.asList(XPackPlugin.class, XPackPlugin.class))) { node.start(); } } @@ -67,7 +66,7 @@ public class TribeShieldLoadedTests extends ESTestCase { return addTribeSettings(Settings.builder() .put("node.name", "tribe_node") .put("path.home", createTempDir()) - .putArray("plugin.mandatory", ShieldPlugin.NAME, LicensePlugin.NAME), "t1"); + .putArray("plugin.mandatory", XPackPlugin.NAME), "t1"); } private static Settings.Builder addTribeSettings(Settings.Builder settingsBuilder, String tribe) { @@ -75,6 +74,6 @@ public class TribeShieldLoadedTests extends ESTestCase { return settingsBuilder.put(tribePrefix + "cluster.name", "non_existing_cluster") .put(tribePrefix + "discovery.type", "local") .put(tribePrefix + "discovery.initial_state_timeout", 0) - .putArray(tribePrefix + "plugin.mandatory", ShieldPlugin.NAME, LicensePlugin.NAME); + .putArray(tribePrefix + "plugin.mandatory", XPackPlugin.NAME); } } diff --git a/shield/src/test/java/org/elasticsearch/test/ShieldIntegTestCase.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/test/ShieldIntegTestCase.java similarity index 93% rename from shield/src/test/java/org/elasticsearch/test/ShieldIntegTestCase.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/test/ShieldIntegTestCase.java index 8cb9b876265..de09dcddbaa 100644 --- a/shield/src/test/java/org/elasticsearch/test/ShieldIntegTestCase.java +++ b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/test/ShieldIntegTestCase.java @@ -6,15 +6,15 @@ package org.elasticsearch.test; import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; -import org.elasticsearch.cluster.health.ClusterHealthStatus; import org.elasticsearch.action.admin.cluster.node.info.NodeInfo; import org.elasticsearch.action.admin.cluster.node.info.NodesInfoResponse; import org.elasticsearch.client.Client; +import org.elasticsearch.cluster.health.ClusterHealthStatus; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.plugins.Plugin; -import org.elasticsearch.shield.ShieldPlugin; import org.elasticsearch.shield.authc.support.SecuredString; import org.elasticsearch.test.ESIntegTestCase.SuppressLocalMode; +import org.elasticsearch.xpack.XPackPlugin; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; @@ -22,7 +22,7 @@ import org.junit.Rule; import org.junit.rules.ExternalResource; import java.nio.file.Path; -import java.util.*; +import java.util.Collection; import java.util.stream.Collectors; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoTimeout; @@ -127,8 +127,7 @@ public abstract class ShieldIntegTestCase extends ESIntegTestCase { // TODO: disable this assertion for now, because the test framework randomly runs with mock plugins. Maybe we should run without mock plugins? // assertThat(nodeInfo.getPlugins().getInfos(), hasSize(2)); Collection pluginNames = nodeInfo.getPlugins().getPluginInfos().stream().map(p -> p.getName()).collect(Collectors.toList()); - assertThat("plugin [" + ShieldPlugin.NAME + "] not found in [" + pluginNames + "]", pluginNames.contains(ShieldPlugin.NAME), is(true)); - assertThat("plugin [" + licensePluginName() + "] not found in [" + pluginNames + "]", pluginNames.contains(licensePluginName()), is(true)); + assertThat("plugin [" + XPackPlugin.NAME + "] not found in [" + pluginNames + "]", pluginNames.contains(XPackPlugin.NAME), is(true)); } } @@ -235,12 +234,8 @@ public abstract class ShieldIntegTestCase extends ESIntegTestCase { return randomBoolean(); } - protected Class licensePluginClass() { - return SHIELD_DEFAULT_SETTINGS.licensePluginClass(); - } - - protected String licensePluginName() { - return SHIELD_DEFAULT_SETTINGS.licensePluginName(); + protected Class xpackPluginClass() { + return SHIELD_DEFAULT_SETTINGS.xpackPluginClass(); } private class CustomShieldSettingsSource extends ShieldSettingsSource { @@ -284,13 +279,8 @@ public abstract class ShieldIntegTestCase extends ESIntegTestCase { } @Override - protected Class licensePluginClass() { - return ShieldIntegTestCase.this.licensePluginClass(); - } - - @Override - protected String licensePluginName() { - return ShieldIntegTestCase.this.licensePluginName(); + protected Class xpackPluginClass() { + return ShieldIntegTestCase.this.xpackPluginClass(); } } diff --git a/shield/src/test/java/org/elasticsearch/test/ShieldSettingsSource.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/test/ShieldSettingsSource.java similarity index 96% rename from shield/src/test/java/org/elasticsearch/test/ShieldSettingsSource.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/test/ShieldSettingsSource.java index 8ca9d1542ba..658fa3e5b15 100644 --- a/shield/src/test/java/org/elasticsearch/test/ShieldSettingsSource.java +++ b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/test/ShieldSettingsSource.java @@ -10,9 +10,9 @@ import org.elasticsearch.client.support.Headers; import org.elasticsearch.common.io.PathUtils; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.IndexModule; -import org.elasticsearch.license.plugin.LicensePlugin; -import org.elasticsearch.plugins.Plugin; import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; +import org.elasticsearch.plugins.Plugin; import org.elasticsearch.shield.authc.esusers.ESUsersRealm; import org.elasticsearch.shield.authc.support.Hasher; import org.elasticsearch.shield.authc.support.SecuredString; @@ -116,6 +116,11 @@ public class ShieldSettingsSource extends ClusterDiscoveryConfiguration.UnicastZ public Settings nodeSettings(int nodeOrdinal) { Path folder = ShieldTestUtils.createFolder(parentFolder, subfolderPrefix + "-" + nodeOrdinal); Settings.Builder builder = settingsBuilder().put(super.nodeSettings(nodeOrdinal)) + + //TODO: for now isolate shield tests from watcher & marvel (randomize this later) + .put("watcher.enabled", false) + .put("marvel.enabled", false) + .put("shield.audit.enabled", randomBoolean()) .put(InternalCryptoService.FILE_SETTING, writeFile(folder, "system_key", systemKey)) .put("shield.authc.realms.esusers.type", ESUsersRealm.TYPE) @@ -143,12 +148,12 @@ public class ShieldSettingsSource extends ClusterDiscoveryConfiguration.UnicastZ @Override public Collection> nodePlugins() { - return Arrays.asList(ShieldPlugin.class, licensePluginClass()); + return Arrays.asList(xpackPluginClass()); } @Override public Collection> transportClientPlugins() { - return Collections.>singletonList(ShieldPlugin.class); + return Collections.>singletonList(xpackPluginClass()); } protected String configUsers() { @@ -179,18 +184,14 @@ public class ShieldSettingsSource extends ClusterDiscoveryConfiguration.UnicastZ return new SecuredString(DEFAULT_PASSWORD.toCharArray()); } - protected Class licensePluginClass() { - return LicensePlugin.class; - } - - protected String licensePluginName() { - return LicensePlugin.NAME; - } - protected byte[] systemKey() { return systemKey; } + protected Class xpackPluginClass() { + return XPackPlugin.class; + } + private void setUser(Settings.Builder builder, String username, SecuredString password) { if (randomBoolean()) { builder.put(Headers.PREFIX + "." + UsernamePasswordToken.BASIC_AUTH_HEADER, basicAuthHeaderValue(username, password)); diff --git a/shield/src/test/java/org/elasticsearch/test/ShieldTestsUtils.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/test/ShieldTestsUtils.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/test/ShieldTestsUtils.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/test/ShieldTestsUtils.java diff --git a/shield/src/test/java/org/elasticsearch/transport/KnownActionsTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/transport/KnownActionsTests.java similarity index 99% rename from shield/src/test/java/org/elasticsearch/transport/KnownActionsTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/transport/KnownActionsTests.java index 354ab2871fa..500428dd759 100644 --- a/shield/src/test/java/org/elasticsearch/transport/KnownActionsTests.java +++ b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/transport/KnownActionsTests.java @@ -10,6 +10,7 @@ import org.elasticsearch.action.Action; import org.elasticsearch.common.io.PathUtils; import org.elasticsearch.common.io.Streams; import org.elasticsearch.license.plugin.LicensePlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.action.ShieldActionModule; import org.elasticsearch.test.ESIntegTestCase.ClusterScope; import org.elasticsearch.test.ShieldIntegTestCase; diff --git a/shield/src/test/java/org/elasticsearch/transport/ShieldServerTransportServiceTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/transport/ShieldServerTransportServiceTests.java similarity index 97% rename from shield/src/test/java/org/elasticsearch/transport/ShieldServerTransportServiceTests.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/transport/ShieldServerTransportServiceTests.java index df404496bb4..08e0c5d662d 100644 --- a/shield/src/test/java/org/elasticsearch/transport/ShieldServerTransportServiceTests.java +++ b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/transport/ShieldServerTransportServiceTests.java @@ -7,6 +7,7 @@ package org.elasticsearch.transport; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.transport.ShieldServerTransportService; import org.elasticsearch.test.ShieldIntegTestCase; diff --git a/shield/src/test/java/org/elasticsearch/transport/netty/NettyMockUtil.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/transport/netty/NettyMockUtil.java similarity index 100% rename from shield/src/test/java/org/elasticsearch/transport/netty/NettyMockUtil.java rename to elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/transport/netty/NettyMockUtil.java diff --git a/shield/src/test/resources/log4j.properties b/elasticsearch/x-pack/shield/src/test/resources/log4j.properties similarity index 100% rename from shield/src/test/resources/log4j.properties rename to elasticsearch/x-pack/shield/src/test/resources/log4j.properties diff --git a/shield/src/test/resources/logstash-shield.conf b/elasticsearch/x-pack/shield/src/test/resources/logstash-shield.conf similarity index 100% rename from shield/src/test/resources/logstash-shield.conf rename to elasticsearch/x-pack/shield/src/test/resources/logstash-shield.conf diff --git a/shield/src/test/resources/org/elasticsearch/shield/authc/activedirectory/ad-schema.ldif b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/authc/activedirectory/ad-schema.ldif similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/authc/activedirectory/ad-schema.ldif rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/authc/activedirectory/ad-schema.ldif diff --git a/shield/src/test/resources/org/elasticsearch/shield/authc/activedirectory/ad.ldif b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/authc/activedirectory/ad.ldif similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/authc/activedirectory/ad.ldif rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/authc/activedirectory/ad.ldif diff --git a/shield/src/test/resources/org/elasticsearch/shield/authc/activedirectory/role_mapping.yml b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/authc/activedirectory/role_mapping.yml similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/authc/activedirectory/role_mapping.yml rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/authc/activedirectory/role_mapping.yml diff --git a/shield/src/test/resources/org/elasticsearch/shield/authc/esusers/users b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/authc/esusers/users similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/authc/esusers/users rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/authc/esusers/users diff --git a/shield/src/test/resources/org/elasticsearch/shield/authc/esusers/users_roles b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/authc/esusers/users_roles similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/authc/esusers/users_roles rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/authc/esusers/users_roles diff --git a/shield/src/test/resources/org/elasticsearch/shield/authc/ldap/support/ldapWithGroupSearch.yaml b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/authc/ldap/support/ldapWithGroupSearch.yaml similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/authc/ldap/support/ldapWithGroupSearch.yaml rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/authc/ldap/support/ldapWithGroupSearch.yaml diff --git a/shield/src/test/resources/org/elasticsearch/shield/authc/ldap/support/ldapWithRoleMapping.yaml b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/authc/ldap/support/ldapWithRoleMapping.yaml similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/authc/ldap/support/ldapWithRoleMapping.yaml rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/authc/ldap/support/ldapWithRoleMapping.yaml diff --git a/shield/src/test/resources/org/elasticsearch/shield/authc/ldap/support/ldaptrust.jks b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/authc/ldap/support/ldaptrust.jks similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/authc/ldap/support/ldaptrust.jks rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/authc/ldap/support/ldaptrust.jks diff --git a/shield/src/test/resources/org/elasticsearch/shield/authc/ldap/support/seven-seas.ldif b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/authc/ldap/support/seven-seas.ldif similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/authc/ldap/support/seven-seas.ldif rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/authc/ldap/support/seven-seas.ldif diff --git a/shield/src/test/resources/org/elasticsearch/shield/authc/pki/role_mapping.yml b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/authc/pki/role_mapping.yml similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/authc/pki/role_mapping.yml rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/authc/pki/role_mapping.yml diff --git a/shield/src/test/resources/org/elasticsearch/shield/authc/support/role_mapping.yml b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/authc/support/role_mapping.yml similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/authc/support/role_mapping.yml rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/authc/support/role_mapping.yml diff --git a/shield/src/test/resources/org/elasticsearch/shield/authz/store/default_roles.yml b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/authz/store/default_roles.yml similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/authz/store/default_roles.yml rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/authz/store/default_roles.yml diff --git a/shield/src/test/resources/org/elasticsearch/shield/authz/store/invalid_roles.yml b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/authz/store/invalid_roles.yml similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/authz/store/invalid_roles.yml rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/authz/store/invalid_roles.yml diff --git a/shield/src/test/resources/org/elasticsearch/shield/authz/store/reserved_roles.yml b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/authz/store/reserved_roles.yml similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/authz/store/reserved_roles.yml rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/authz/store/reserved_roles.yml diff --git a/shield/src/test/resources/org/elasticsearch/shield/authz/store/roles.yml b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/authz/store/roles.yml similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/authz/store/roles.yml rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/authz/store/roles.yml diff --git a/shield/src/test/resources/org/elasticsearch/shield/plugin/roles.yml b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/plugin/roles.yml similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/plugin/roles.yml rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/plugin/roles.yml diff --git a/shield/src/test/resources/org/elasticsearch/shield/plugin/users b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/plugin/users similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/plugin/users rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/plugin/users diff --git a/shield/src/test/resources/org/elasticsearch/shield/plugin/users_roles b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/plugin/users_roles similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/plugin/users_roles rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/plugin/users_roles diff --git a/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/README.asciidoc b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/README.asciidoc similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/README.asciidoc rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/README.asciidoc diff --git a/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/activedir.crt b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/activedir.crt similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/activedir.crt rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/activedir.crt diff --git a/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/openldap.crt b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/openldap.crt similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/openldap.crt rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/openldap.crt diff --git a/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/openssl_config.cnf b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/openssl_config.cnf similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/openssl_config.cnf rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/openssl_config.cnf diff --git a/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient-client-profile.cert b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient-client-profile.cert similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient-client-profile.cert rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient-client-profile.cert diff --git a/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient-client-profile.jks b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient-client-profile.jks similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient-client-profile.jks rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient-client-profile.jks diff --git a/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient-client-profile.p12 b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient-client-profile.p12 similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient-client-profile.p12 rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient-client-profile.p12 diff --git a/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient-client-profile.pem b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient-client-profile.pem similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient-client-profile.pem rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient-client-profile.pem diff --git a/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient.cert b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient.cert similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient.cert rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient.cert diff --git a/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient.jks b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient.jks similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient.jks rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient.jks diff --git a/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient.p12 b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient.p12 similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient.p12 rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient.p12 diff --git a/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient.pem b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient.pem similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient.pem rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testclient.pem diff --git a/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-client-profile.cert b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-client-profile.cert similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-client-profile.cert rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-client-profile.cert diff --git a/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-client-profile.jks b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-client-profile.jks similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-client-profile.jks rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-client-profile.jks diff --git a/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-client-profile.p12 b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-client-profile.p12 similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-client-profile.p12 rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-client-profile.p12 diff --git a/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-client-profile.pem b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-client-profile.pem similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-client-profile.pem rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-client-profile.pem diff --git a/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-different-passwords.jks b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-different-passwords.jks similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-different-passwords.jks rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-different-passwords.jks diff --git a/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-ip-only.cert b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-ip-only.cert similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-ip-only.cert rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-ip-only.cert diff --git a/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-ip-only.jks b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-ip-only.jks similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-ip-only.jks rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-ip-only.jks diff --git a/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-no-subjaltname.cert b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-no-subjaltname.cert similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-no-subjaltname.cert rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-no-subjaltname.cert diff --git a/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-no-subjaltname.jks b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-no-subjaltname.jks similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-no-subjaltname.jks rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-no-subjaltname.jks diff --git a/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.cert b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.cert similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.cert rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.cert diff --git a/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks diff --git a/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.p12 b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.p12 similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.p12 rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.p12 diff --git a/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.pem b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.pem similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.pem rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.pem diff --git a/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/truststore-testnode-only.jks b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/truststore-testnode-only.jks similarity index 100% rename from shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/truststore-testnode-only.jks rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/truststore-testnode-only.jks diff --git a/shield/src/test/resources/org/elasticsearch/transport/actions b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/transport/actions similarity index 100% rename from shield/src/test/resources/org/elasticsearch/transport/actions rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/transport/actions diff --git a/shield/src/test/resources/org/elasticsearch/transport/handlers b/elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/transport/handlers similarity index 100% rename from shield/src/test/resources/org/elasticsearch/transport/handlers rename to elasticsearch/x-pack/shield/src/test/resources/org/elasticsearch/transport/handlers diff --git a/shield/test-signatures.txt b/elasticsearch/x-pack/shield/test-signatures.txt similarity index 100% rename from shield/test-signatures.txt rename to elasticsearch/x-pack/shield/test-signatures.txt diff --git a/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/XPackPlugin.java b/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/XPackPlugin.java new file mode 100644 index 00000000000..df70ab2c53e --- /dev/null +++ b/elasticsearch/x-pack/src/main/java/org/elasticsearch/xpack/XPackPlugin.java @@ -0,0 +1,163 @@ +/* + * 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; + +import org.elasticsearch.SpecialPermission; +import org.elasticsearch.action.ActionModule; +import org.elasticsearch.cluster.ClusterModule; +import org.elasticsearch.common.component.LifecycleComponent; +import org.elasticsearch.common.inject.Module; +import org.elasticsearch.common.logging.ESLogger; +import org.elasticsearch.common.logging.Loggers; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.http.HttpServerModule; +import org.elasticsearch.index.IndexModule; +import org.elasticsearch.license.plugin.LicensePlugin; +import org.elasticsearch.marvel.MarvelPlugin; +import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.rest.RestModule; +import org.elasticsearch.script.ScriptModule; +import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.shield.authz.AuthorizationModule; +import org.elasticsearch.transport.TransportModule; +import org.elasticsearch.watcher.WatcherPlugin; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.Collection; + +public class XPackPlugin extends Plugin { + + public static final String NAME = "x-pack"; + + private final static ESLogger logger = Loggers.getLogger(XPackPlugin.class); + + // TODO: clean up this library to not ask for write access to all system properties! + static { + // invoke this clinit in unbound with permissions to access all system properties + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new SpecialPermission()); + } + try { + AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Void run() { + try { + Class.forName("com.unboundid.util.Debug"); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + return null; + } + }); + // TODO: fix gradle to add all shield resources (plugin metadata) to test classpath + // of watcher plugin, which depends on it directly. This prevents these plugins + // from being initialized correctly by the test framework, and means we have to + // have this leniency. + } catch (ExceptionInInitializerError bogus) { + if (bogus.getCause() instanceof SecurityException == false) { + throw bogus; // some other bug + } + } + } + + protected final Settings settings; + protected LicensePlugin licensePlugin; + protected ShieldPlugin shieldPlugin; + protected MarvelPlugin marvelPlugin; + protected WatcherPlugin watcherPlugin; + + public XPackPlugin(Settings settings) { + this.settings = settings; + this.licensePlugin = new LicensePlugin(settings); + this.shieldPlugin = new ShieldPlugin(settings); + this.marvelPlugin = new MarvelPlugin(settings); + this.watcherPlugin = new WatcherPlugin(settings); + } + + @Override public String name() { + return NAME; + } + + @Override public String description() { + return "Elastic X-Pack"; + } + + @Override + public Collection nodeModules() { + ArrayList modules = new ArrayList<>(); + modules.addAll(licensePlugin.nodeModules()); + modules.addAll(shieldPlugin.nodeModules()); + modules.addAll(watcherPlugin.nodeModules()); + modules.addAll(marvelPlugin.nodeModules()); + return modules; + } + + @Override + public Collection> nodeServices() { + ArrayList> services = new ArrayList<>(); + services.addAll(licensePlugin.nodeServices()); + services.addAll(shieldPlugin.nodeServices()); + services.addAll(watcherPlugin.nodeServices()); + services.addAll(marvelPlugin.nodeServices()); + return services; + } + + @Override + public Settings additionalSettings() { + Settings.Builder builder = Settings.builder(); + builder.put(licensePlugin.additionalSettings()); + builder.put(shieldPlugin.additionalSettings()); + builder.put(watcherPlugin.additionalSettings()); + builder.put(marvelPlugin.additionalSettings()); + return builder.build(); + } + + public void onModule(ScriptModule module) { + watcherPlugin.onModule(module); + } + + public void onModule(ClusterModule module) { + shieldPlugin.onModule(module); + watcherPlugin.onModule(module); + marvelPlugin.onModule(module); + } + + public void onModule(RestModule module) { + licensePlugin.onModule(module); + shieldPlugin.onModule(module); + watcherPlugin.onModule(module); + } + + public void onModule(ActionModule module) { + licensePlugin.onModule(module); + shieldPlugin.onModule(module); + watcherPlugin.onModule(module); + } + + public void onModule(TransportModule module) { + shieldPlugin.onModule(module); + } + + public void onModule(HttpServerModule module) { + shieldPlugin.onModule(module); + } + + public void onModule(AuthorizationModule module) { + shieldPlugin.onModule(module); + // FIXME clean these up + watcherPlugin.onModule(module); + marvelPlugin.onModule(module); + } + + public void onIndexModule(IndexModule module) { + shieldPlugin.onIndexModule(module); + watcherPlugin.onIndexModule(module); + marvelPlugin.onIndexModule(module); + } +} diff --git a/shield/src/main/plugin-metadata/plugin-security.policy b/elasticsearch/x-pack/src/main/plugin-metadata/plugin-security.policy similarity index 56% rename from shield/src/main/plugin-metadata/plugin-security.policy rename to elasticsearch/x-pack/src/main/plugin-metadata/plugin-security.policy index b104d276aae..1195dcbd196 100644 --- a/shield/src/main/plugin-metadata/plugin-security.policy +++ b/elasticsearch/x-pack/src/main/plugin-metadata/plugin-security.policy @@ -1,4 +1,7 @@ grant { // needed because of problems in unbound LDAP library permission java.util.PropertyPermission "*", "read,write"; + + // needed to set expert SSL options, etc + permission java.lang.RuntimePermission "setFactory"; }; diff --git a/elasticsearch/x-pack/src/test/java/org/elasticsearch/xpack/TimeWarpedXPackPlugin.java b/elasticsearch/x-pack/src/test/java/org/elasticsearch/xpack/TimeWarpedXPackPlugin.java new file mode 100644 index 00000000000..3637df86f96 --- /dev/null +++ b/elasticsearch/x-pack/src/test/java/org/elasticsearch/xpack/TimeWarpedXPackPlugin.java @@ -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; + +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.watcher.test.TimeWarpedWatcherPlugin; + +public class TimeWarpedXPackPlugin extends XPackPlugin { + + public TimeWarpedXPackPlugin(Settings settings) { + super(settings); + watcherPlugin = new TimeWarpedWatcherPlugin(settings); + } +} diff --git a/watcher/src/test/java/org/elasticsearch/watcher/test/rest/WatcherRestIT.java b/elasticsearch/x-pack/src/test/java/org/elasticsearch/xpack/test/rest/XPackRestIT.java similarity index 70% rename from watcher/src/test/java/org/elasticsearch/watcher/test/rest/WatcherRestIT.java rename to elasticsearch/x-pack/src/test/java/org/elasticsearch/xpack/test/rest/XPackRestIT.java index fed6ba4f543..902d36c6f3d 100644 --- a/watcher/src/test/java/org/elasticsearch/watcher/test/rest/WatcherRestIT.java +++ b/elasticsearch/x-pack/src/test/java/org/elasticsearch/xpack/test/rest/XPackRestIT.java @@ -3,14 +3,14 @@ * 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; +package org.elasticsearch.xpack.test.rest; import org.elasticsearch.test.rest.RestTestCandidate; /** Runs rest tests against external cluster */ -public class WatcherRestIT extends WatcherRestTestCase { +public class XPackRestIT extends XPackRestTestCase { - public WatcherRestIT(RestTestCandidate testCandidate) { + public XPackRestIT(RestTestCandidate testCandidate) { super(testCandidate); } diff --git a/qa/smoke-test-watcher-with-groovy/src/test/java/org/elasticsearch/smoketest/WatcherRestTestCase.java b/elasticsearch/x-pack/src/test/java/org/elasticsearch/xpack/test/rest/XPackRestTestCase.java similarity index 90% rename from qa/smoke-test-watcher-with-groovy/src/test/java/org/elasticsearch/smoketest/WatcherRestTestCase.java rename to elasticsearch/x-pack/src/test/java/org/elasticsearch/xpack/test/rest/XPackRestTestCase.java index 2173cd82578..5841ddb3c30 100644 --- a/qa/smoke-test-watcher-with-groovy/src/test/java/org/elasticsearch/smoketest/WatcherRestTestCase.java +++ b/elasticsearch/x-pack/src/test/java/org/elasticsearch/xpack/test/rest/XPackRestTestCase.java @@ -3,7 +3,7 @@ * 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; +package org.elasticsearch.xpack.test.rest; import com.carrotsearch.randomizedtesting.annotations.Name; import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; @@ -13,14 +13,14 @@ import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.BasicHttpClientConnectionManager; import org.elasticsearch.common.network.NetworkAddress; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.license.plugin.LicensePlugin; +import org.elasticsearch.xpack.XPackPlugin; 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.elasticsearch.xpack.XPackPlugin; import org.junit.After; import org.junit.Before; @@ -34,9 +34,9 @@ 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 abstract class XPackRestTestCase extends ESRestTestCase { - public WatcherRestTestCase(@Name("yaml") RestTestCandidate testCandidate) { + public XPackRestTestCase(@Name("yaml") RestTestCandidate testCandidate) { super(testCandidate); } diff --git a/marvel/src/test/resources/rest-api-spec/test/marvel/10_basic.yaml b/elasticsearch/x-pack/src/test/resources/rest-api-spec/test/xpack/10_basic.yaml similarity index 54% rename from marvel/src/test/resources/rest-api-spec/test/marvel/10_basic.yaml rename to elasticsearch/x-pack/src/test/resources/rest-api-spec/test/xpack/10_basic.yaml index deea46f3c04..c7cfc4326f0 100644 --- a/marvel/src/test/resources/rest-api-spec/test/marvel/10_basic.yaml +++ b/elasticsearch/x-pack/src/test/resources/rest-api-spec/test/xpack/10_basic.yaml @@ -1,6 +1,6 @@ # Integration tests for Marvel plugin # -"Marvel loaded": +"X-Pack loaded": - do: cluster.state: {} @@ -10,7 +10,5 @@ - do: nodes.info: {} - - match: { nodes.$master.plugins.0.name: license } + - match: { nodes.$master.plugins.0.name: x-pack } - match: { nodes.$master.plugins.0.jvm: true } - - match: { nodes.$master.plugins.1.name: marvel-agent } - - match: { nodes.$master.plugins.1.jvm: true } diff --git a/watcher/LICENSE.txt b/elasticsearch/x-pack/watcher/LICENSE.txt similarity index 100% rename from watcher/LICENSE.txt rename to elasticsearch/x-pack/watcher/LICENSE.txt diff --git a/watcher/NOTICE.txt b/elasticsearch/x-pack/watcher/NOTICE.txt similarity index 100% rename from watcher/NOTICE.txt rename to elasticsearch/x-pack/watcher/NOTICE.txt diff --git a/watcher/README.asciidoc b/elasticsearch/x-pack/watcher/README.asciidoc similarity index 100% rename from watcher/README.asciidoc rename to elasticsearch/x-pack/watcher/README.asciidoc diff --git a/watcher/bin/watcher/.in.bat b/elasticsearch/x-pack/watcher/bin/watcher/.in.bat similarity index 99% rename from watcher/bin/watcher/.in.bat rename to elasticsearch/x-pack/watcher/bin/watcher/.in.bat index 837a61d216e..3fd70a04222 100644 Binary files a/watcher/bin/watcher/.in.bat and b/elasticsearch/x-pack/watcher/bin/watcher/.in.bat differ diff --git a/watcher/bin/watcher/croneval b/elasticsearch/x-pack/watcher/bin/watcher/croneval similarity index 97% rename from watcher/bin/watcher/croneval rename to elasticsearch/x-pack/watcher/bin/watcher/croneval index 418bbadcad9..27e8e02c92b 100755 --- a/watcher/bin/watcher/croneval +++ b/elasticsearch/x-pack/watcher/bin/watcher/croneval @@ -114,7 +114,7 @@ fi export HOSTNAME=`hostname -s` # include watcher jars in classpath -ES_CLASSPATH="$ES_CLASSPATH:$ES_HOME/plugins/watcher/*" +ES_CLASSPATH="$ES_CLASSPATH:$ES_HOME/plugins/x-pack/*" cd "$ES_HOME" > /dev/null $JAVA $ES_JAVA_OPTS -cp "$ES_CLASSPATH" org.elasticsearch.watcher.trigger.schedule.tool.CronEvalTool "$@" $properties diff --git a/watcher/bin/watcher/croneval.bat b/elasticsearch/x-pack/watcher/bin/watcher/croneval.bat similarity index 100% rename from watcher/bin/watcher/croneval.bat rename to elasticsearch/x-pack/watcher/bin/watcher/croneval.bat diff --git a/watcher/dev-tools/randomization.yml b/elasticsearch/x-pack/watcher/dev-tools/randomization.yml similarity index 100% rename from watcher/dev-tools/randomization.yml rename to elasticsearch/x-pack/watcher/dev-tools/randomization.yml diff --git a/watcher/src/main/java/org/elasticsearch/watcher/WatcherBuild.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/WatcherBuild.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/WatcherBuild.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/WatcherBuild.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/WatcherLifeCycleService.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/WatcherLifeCycleService.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/WatcherLifeCycleService.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/WatcherLifeCycleService.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/WatcherMetaData.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/WatcherMetaData.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/WatcherMetaData.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/WatcherMetaData.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/WatcherModule.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/WatcherModule.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/WatcherModule.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/WatcherModule.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/WatcherPlugin.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/WatcherPlugin.java similarity index 99% rename from watcher/src/main/java/org/elasticsearch/watcher/WatcherPlugin.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/WatcherPlugin.java index fef620bc677..4949e4ebc4b 100644 --- a/watcher/src/main/java/org/elasticsearch/watcher/WatcherPlugin.java +++ b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/WatcherPlugin.java @@ -70,6 +70,7 @@ import org.elasticsearch.watcher.transport.actions.stats.WatcherStatsAction; import org.elasticsearch.watcher.trigger.TriggerModule; import org.elasticsearch.watcher.trigger.schedule.ScheduleModule; import org.elasticsearch.watcher.watch.WatchModule; +import org.elasticsearch.xpack.XPackPlugin; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; @@ -82,7 +83,7 @@ public class WatcherPlugin extends Plugin { public static final String NAME = "watcher"; public static final String ENABLED_SETTING = NAME + ".enabled"; - private final static ESLogger logger = Loggers.getLogger(WatcherPlugin.class); + private final static ESLogger logger = Loggers.getLogger(XPackPlugin.class); static { MetaData.registerPrototype(WatcherMetaData.TYPE, WatcherMetaData.PROTO); diff --git a/watcher/src/main/java/org/elasticsearch/watcher/WatcherService.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/WatcherService.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/WatcherService.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/WatcherService.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/WatcherState.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/WatcherState.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/WatcherState.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/WatcherState.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/Action.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/Action.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/Action.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/Action.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/ActionBuilders.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/ActionBuilders.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/ActionBuilders.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/ActionBuilders.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/ActionFactory.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/ActionFactory.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/ActionFactory.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/ActionFactory.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/ActionRegistry.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/ActionRegistry.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/ActionRegistry.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/ActionRegistry.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/ActionStatus.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/ActionStatus.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/ActionStatus.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/ActionStatus.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/ActionWrapper.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/ActionWrapper.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/ActionWrapper.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/ActionWrapper.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/ExecutableAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/ExecutableAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/ExecutableAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/ExecutableAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/ExecutableActions.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/ExecutableActions.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/ExecutableActions.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/ExecutableActions.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/WatcherActionModule.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/WatcherActionModule.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/WatcherActionModule.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/WatcherActionModule.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/email/DataAttachment.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/DataAttachment.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/email/DataAttachment.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/DataAttachment.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/email/EmailAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/EmailAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/email/EmailAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/EmailAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/email/EmailActionFactory.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/EmailActionFactory.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/email/EmailActionFactory.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/EmailActionFactory.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/email/ExecutableEmailAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/ExecutableEmailAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/email/ExecutableEmailAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/ExecutableEmailAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/Account.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/Account.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/Account.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/Account.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/Accounts.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/Accounts.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/Accounts.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/Accounts.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/Attachment.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/Attachment.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/Attachment.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/Attachment.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/Authentication.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/Authentication.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/Authentication.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/Authentication.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/Email.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/Email.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/Email.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/Email.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/EmailService.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/EmailService.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/EmailService.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/EmailService.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/EmailTemplate.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/EmailTemplate.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/EmailTemplate.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/EmailTemplate.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/HtmlSanitizer.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/HtmlSanitizer.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/HtmlSanitizer.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/HtmlSanitizer.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/Inline.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/Inline.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/Inline.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/Inline.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/InternalEmailService.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/InternalEmailService.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/InternalEmailService.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/InternalEmailService.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/Profile.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/Profile.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/Profile.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/Profile.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/support/BodyPartSource.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/support/BodyPartSource.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/support/BodyPartSource.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/email/service/support/BodyPartSource.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/ExecutableHipChatAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/ExecutableHipChatAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/ExecutableHipChatAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/ExecutableHipChatAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/HipChatAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/HipChatAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/HipChatAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/HipChatAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/HipChatActionFactory.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/HipChatActionFactory.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/HipChatActionFactory.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/HipChatActionFactory.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatAccount.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatAccount.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatAccount.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatAccount.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatAccounts.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatAccounts.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatAccounts.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatAccounts.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatMessage.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatMessage.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatMessage.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatMessage.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatServer.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatServer.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatServer.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatServer.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatService.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatService.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatService.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatService.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/IntegrationAccount.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/IntegrationAccount.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/IntegrationAccount.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/IntegrationAccount.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/InternalHipChatService.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/InternalHipChatService.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/InternalHipChatService.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/InternalHipChatService.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/SentMessages.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/SentMessages.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/SentMessages.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/SentMessages.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/UserAccount.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/UserAccount.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/UserAccount.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/UserAccount.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/V1Account.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/V1Account.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/V1Account.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/hipchat/service/V1Account.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/index/ExecutableIndexAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/index/ExecutableIndexAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/index/ExecutableIndexAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/index/ExecutableIndexAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/index/IndexAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/index/IndexAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/index/IndexAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/index/IndexAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/index/IndexActionFactory.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/index/IndexActionFactory.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/index/IndexActionFactory.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/index/IndexActionFactory.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/logging/ExecutableLoggingAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/logging/ExecutableLoggingAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/logging/ExecutableLoggingAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/logging/ExecutableLoggingAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/logging/LoggingAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/logging/LoggingAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/logging/LoggingAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/logging/LoggingAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/logging/LoggingActionFactory.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/logging/LoggingActionFactory.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/logging/LoggingActionFactory.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/logging/LoggingActionFactory.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/logging/LoggingLevel.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/logging/LoggingLevel.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/logging/LoggingLevel.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/logging/LoggingLevel.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/ExecutableSlackAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/ExecutableSlackAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/slack/ExecutableSlackAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/ExecutableSlackAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/SlackAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/SlackAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/slack/SlackAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/SlackAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/SlackActionFactory.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/SlackActionFactory.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/slack/SlackActionFactory.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/SlackActionFactory.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/InternalSlackService.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/InternalSlackService.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/InternalSlackService.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/InternalSlackService.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/SentMessages.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/SentMessages.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/SentMessages.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/SentMessages.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/SlackAccount.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/SlackAccount.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/SlackAccount.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/SlackAccount.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/SlackAccounts.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/SlackAccounts.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/SlackAccounts.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/SlackAccounts.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/SlackService.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/SlackService.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/SlackService.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/SlackService.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/message/Attachment.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/message/Attachment.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/message/Attachment.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/message/Attachment.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/message/DynamicAttachments.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/message/DynamicAttachments.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/message/DynamicAttachments.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/message/DynamicAttachments.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/message/Field.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/message/Field.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/message/Field.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/message/Field.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/message/MessageElement.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/message/MessageElement.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/message/MessageElement.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/message/MessageElement.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/message/SlackMessage.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/message/SlackMessage.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/message/SlackMessage.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/message/SlackMessage.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/message/SlackMessageDefaults.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/message/SlackMessageDefaults.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/message/SlackMessageDefaults.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/slack/service/message/SlackMessageDefaults.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/throttler/AckThrottler.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/throttler/AckThrottler.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/throttler/AckThrottler.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/throttler/AckThrottler.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/throttler/ActionThrottler.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/throttler/ActionThrottler.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/throttler/ActionThrottler.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/throttler/ActionThrottler.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/throttler/PeriodThrottler.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/throttler/PeriodThrottler.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/throttler/PeriodThrottler.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/throttler/PeriodThrottler.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/throttler/Throttler.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/throttler/Throttler.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/throttler/Throttler.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/throttler/Throttler.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/webhook/ExecutableWebhookAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/webhook/ExecutableWebhookAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/webhook/ExecutableWebhookAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/webhook/ExecutableWebhookAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/webhook/WebhookAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/webhook/WebhookAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/webhook/WebhookAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/webhook/WebhookAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/actions/webhook/WebhookActionFactory.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/webhook/WebhookActionFactory.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/actions/webhook/WebhookActionFactory.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/actions/webhook/WebhookActionFactory.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/client/WatchSourceBuilder.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/client/WatchSourceBuilder.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/client/WatchSourceBuilder.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/client/WatchSourceBuilder.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/client/WatchSourceBuilders.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/client/WatchSourceBuilders.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/client/WatchSourceBuilders.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/client/WatchSourceBuilders.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/client/WatcherClient.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/client/WatcherClient.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/client/WatcherClient.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/client/WatcherClient.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/client/WatcherClientModule.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/client/WatcherClientModule.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/client/WatcherClientModule.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/client/WatcherClientModule.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/condition/Condition.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/Condition.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/condition/Condition.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/Condition.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/condition/ConditionBuilders.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/ConditionBuilders.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/condition/ConditionBuilders.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/ConditionBuilders.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/condition/ConditionFactory.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/ConditionFactory.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/condition/ConditionFactory.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/ConditionFactory.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/condition/ConditionModule.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/ConditionModule.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/condition/ConditionModule.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/ConditionModule.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/condition/ConditionRegistry.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/ConditionRegistry.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/condition/ConditionRegistry.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/ConditionRegistry.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/condition/ExecutableCondition.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/ExecutableCondition.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/condition/ExecutableCondition.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/ExecutableCondition.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/condition/always/AlwaysCondition.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/always/AlwaysCondition.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/condition/always/AlwaysCondition.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/always/AlwaysCondition.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/condition/always/AlwaysConditionFactory.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/always/AlwaysConditionFactory.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/condition/always/AlwaysConditionFactory.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/always/AlwaysConditionFactory.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/condition/always/ExecutableAlwaysCondition.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/always/ExecutableAlwaysCondition.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/condition/always/ExecutableAlwaysCondition.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/always/ExecutableAlwaysCondition.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/condition/compare/AbstractExecutableCompareCondition.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/compare/AbstractExecutableCompareCondition.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/condition/compare/AbstractExecutableCompareCondition.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/compare/AbstractExecutableCompareCondition.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/condition/compare/CompareCondition.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/compare/CompareCondition.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/condition/compare/CompareCondition.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/compare/CompareCondition.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/condition/compare/CompareConditionFactory.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/compare/CompareConditionFactory.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/condition/compare/CompareConditionFactory.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/compare/CompareConditionFactory.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/condition/compare/ExecutableCompareCondition.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/compare/ExecutableCompareCondition.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/condition/compare/ExecutableCompareCondition.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/compare/ExecutableCompareCondition.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/condition/compare/LenientCompare.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/compare/LenientCompare.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/condition/compare/LenientCompare.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/compare/LenientCompare.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/condition/compare/array/ArrayCompareCondition.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/compare/array/ArrayCompareCondition.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/condition/compare/array/ArrayCompareCondition.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/compare/array/ArrayCompareCondition.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/condition/compare/array/ArrayCompareConditionFactory.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/compare/array/ArrayCompareConditionFactory.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/condition/compare/array/ArrayCompareConditionFactory.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/compare/array/ArrayCompareConditionFactory.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/condition/compare/array/ExecutableArrayCompareCondition.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/compare/array/ExecutableArrayCompareCondition.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/condition/compare/array/ExecutableArrayCompareCondition.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/compare/array/ExecutableArrayCompareCondition.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/condition/never/ExecutableNeverCondition.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/never/ExecutableNeverCondition.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/condition/never/ExecutableNeverCondition.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/never/ExecutableNeverCondition.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/condition/never/NeverCondition.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/never/NeverCondition.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/condition/never/NeverCondition.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/never/NeverCondition.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/condition/never/NeverConditionFactory.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/never/NeverConditionFactory.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/condition/never/NeverConditionFactory.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/never/NeverConditionFactory.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/condition/script/ExecutableScriptCondition.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/script/ExecutableScriptCondition.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/condition/script/ExecutableScriptCondition.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/script/ExecutableScriptCondition.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/condition/script/ScriptCondition.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/script/ScriptCondition.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/condition/script/ScriptCondition.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/script/ScriptCondition.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/condition/script/ScriptConditionFactory.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/script/ScriptConditionFactory.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/condition/script/ScriptConditionFactory.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/condition/script/ScriptConditionFactory.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/execution/ActionExecutionMode.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/ActionExecutionMode.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/execution/ActionExecutionMode.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/ActionExecutionMode.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/execution/AsyncTriggerListener.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/AsyncTriggerListener.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/execution/AsyncTriggerListener.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/AsyncTriggerListener.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/execution/CurrentExecutions.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/CurrentExecutions.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/execution/CurrentExecutions.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/CurrentExecutions.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/execution/ExecutionModule.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/ExecutionModule.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/execution/ExecutionModule.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/ExecutionModule.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/execution/ExecutionPhase.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/ExecutionPhase.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/execution/ExecutionPhase.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/ExecutionPhase.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/execution/ExecutionService.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/ExecutionService.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/execution/ExecutionService.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/ExecutionService.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/execution/ExecutionState.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/ExecutionState.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/execution/ExecutionState.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/ExecutionState.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/execution/InternalWatchExecutor.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/InternalWatchExecutor.java similarity index 97% rename from watcher/src/main/java/org/elasticsearch/watcher/execution/InternalWatchExecutor.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/InternalWatchExecutor.java index 0a772c29b83..2e408874491 100644 --- a/watcher/src/main/java/org/elasticsearch/watcher/execution/InternalWatchExecutor.java +++ b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/InternalWatchExecutor.java @@ -11,6 +11,7 @@ import org.elasticsearch.common.util.concurrent.EsExecutors; import org.elasticsearch.common.util.concurrent.EsThreadPoolExecutor; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.watcher.WatcherPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.watcher.support.ThreadPoolSettingsBuilder; import java.util.concurrent.BlockingQueue; diff --git a/watcher/src/main/java/org/elasticsearch/watcher/execution/ManualExecutionContext.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/ManualExecutionContext.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/execution/ManualExecutionContext.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/ManualExecutionContext.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/execution/QueuedWatch.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/QueuedWatch.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/execution/QueuedWatch.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/QueuedWatch.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/execution/SyncTriggerListener.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/SyncTriggerListener.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/execution/SyncTriggerListener.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/SyncTriggerListener.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/execution/TriggeredExecutionContext.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/TriggeredExecutionContext.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/execution/TriggeredExecutionContext.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/TriggeredExecutionContext.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/execution/TriggeredWatch.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/TriggeredWatch.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/execution/TriggeredWatch.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/TriggeredWatch.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/execution/TriggeredWatchStore.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/TriggeredWatchStore.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/execution/TriggeredWatchStore.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/TriggeredWatchStore.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/execution/WatchExecutionContext.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/WatchExecutionContext.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/execution/WatchExecutionContext.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/WatchExecutionContext.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/execution/WatchExecutionResult.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/WatchExecutionResult.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/execution/WatchExecutionResult.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/WatchExecutionResult.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/execution/WatchExecutionSnapshot.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/WatchExecutionSnapshot.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/execution/WatchExecutionSnapshot.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/WatchExecutionSnapshot.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/execution/WatchExecutor.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/WatchExecutor.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/execution/WatchExecutor.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/WatchExecutor.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/execution/Wid.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/Wid.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/execution/Wid.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/execution/Wid.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/history/HistoryModule.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/history/HistoryModule.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/history/HistoryModule.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/history/HistoryModule.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/history/HistoryStore.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/history/HistoryStore.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/history/HistoryStore.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/history/HistoryStore.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/history/WatchRecord.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/history/WatchRecord.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/history/WatchRecord.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/history/WatchRecord.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/input/ExecutableInput.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/ExecutableInput.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/input/ExecutableInput.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/ExecutableInput.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/input/Input.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/Input.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/input/Input.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/Input.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/input/InputBuilders.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/InputBuilders.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/input/InputBuilders.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/InputBuilders.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/input/InputFactory.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/InputFactory.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/input/InputFactory.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/InputFactory.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/input/InputModule.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/InputModule.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/input/InputModule.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/InputModule.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/input/InputRegistry.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/InputRegistry.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/input/InputRegistry.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/InputRegistry.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/input/chain/ChainInput.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/chain/ChainInput.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/input/chain/ChainInput.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/chain/ChainInput.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/input/chain/ChainInputFactory.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/chain/ChainInputFactory.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/input/chain/ChainInputFactory.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/chain/ChainInputFactory.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/input/chain/ExecutableChainInput.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/chain/ExecutableChainInput.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/input/chain/ExecutableChainInput.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/chain/ExecutableChainInput.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/input/http/ExecutableHttpInput.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/http/ExecutableHttpInput.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/input/http/ExecutableHttpInput.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/http/ExecutableHttpInput.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/input/http/HttpInput.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/http/HttpInput.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/input/http/HttpInput.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/http/HttpInput.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/input/http/HttpInputFactory.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/http/HttpInputFactory.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/input/http/HttpInputFactory.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/http/HttpInputFactory.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/input/none/ExecutableNoneInput.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/none/ExecutableNoneInput.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/input/none/ExecutableNoneInput.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/none/ExecutableNoneInput.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/input/none/NoneInput.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/none/NoneInput.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/input/none/NoneInput.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/none/NoneInput.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/input/none/NoneInputFactory.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/none/NoneInputFactory.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/input/none/NoneInputFactory.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/none/NoneInputFactory.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/input/search/ExecutableSearchInput.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/search/ExecutableSearchInput.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/input/search/ExecutableSearchInput.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/search/ExecutableSearchInput.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/input/search/SearchInput.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/search/SearchInput.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/input/search/SearchInput.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/search/SearchInput.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/input/search/SearchInputFactory.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/search/SearchInputFactory.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/input/search/SearchInputFactory.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/search/SearchInputFactory.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/input/simple/ExecutableSimpleInput.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/simple/ExecutableSimpleInput.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/input/simple/ExecutableSimpleInput.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/simple/ExecutableSimpleInput.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/input/simple/SimpleInput.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/simple/SimpleInput.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/input/simple/SimpleInput.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/simple/SimpleInput.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/input/simple/SimpleInputFactory.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/simple/SimpleInputFactory.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/input/simple/SimpleInputFactory.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/input/simple/SimpleInputFactory.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/license/LicenseModule.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/license/LicenseModule.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/license/LicenseModule.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/license/LicenseModule.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/license/WatcherLicensee.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/license/WatcherLicensee.java similarity index 98% rename from watcher/src/main/java/org/elasticsearch/watcher/license/WatcherLicensee.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/license/WatcherLicensee.java index 2e837a4636d..7a874242e4c 100644 --- a/watcher/src/main/java/org/elasticsearch/watcher/license/WatcherLicensee.java +++ b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/license/WatcherLicensee.java @@ -13,6 +13,7 @@ import org.elasticsearch.license.plugin.core.AbstractLicenseeComponent; import org.elasticsearch.license.plugin.core.LicenseState; import org.elasticsearch.license.plugin.core.LicenseeRegistry; import org.elasticsearch.watcher.WatcherPlugin; +import org.elasticsearch.xpack.XPackPlugin; import static org.elasticsearch.license.core.License.OperationMode.*; diff --git a/watcher/src/main/java/org/elasticsearch/watcher/rest/WatcherRestHandler.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/rest/WatcherRestHandler.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/rest/WatcherRestHandler.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/rest/WatcherRestHandler.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestAckWatchAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestAckWatchAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestAckWatchAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestAckWatchAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestActivateWatchAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestActivateWatchAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestActivateWatchAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestActivateWatchAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestDeleteWatchAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestDeleteWatchAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestDeleteWatchAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestDeleteWatchAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestExecuteWatchAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestExecuteWatchAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestExecuteWatchAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestExecuteWatchAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestGetWatchAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestGetWatchAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestGetWatchAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestGetWatchAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestHijackOperationAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestHijackOperationAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestHijackOperationAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestHijackOperationAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestPutWatchAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestPutWatchAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestPutWatchAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestPutWatchAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestWatchServiceAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestWatchServiceAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestWatchServiceAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestWatchServiceAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestWatcherInfoAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestWatcherInfoAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestWatcherInfoAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestWatcherInfoAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestWatcherStatsAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestWatcherStatsAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestWatcherStatsAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/rest/action/RestWatcherStatsAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/shield/ShieldIntegration.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/shield/ShieldIntegration.java similarity index 98% rename from watcher/src/main/java/org/elasticsearch/watcher/shield/ShieldIntegration.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/shield/ShieldIntegration.java index eec5b59046f..f3e12627226 100644 --- a/watcher/src/main/java/org/elasticsearch/watcher/shield/ShieldIntegration.java +++ b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/shield/ShieldIntegration.java @@ -11,6 +11,7 @@ import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.inject.Injector; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.shield.ShieldSettingsFilter; import org.elasticsearch.shield.authc.AuthenticationService; import org.elasticsearch.transport.TransportMessage; diff --git a/watcher/src/main/java/org/elasticsearch/watcher/shield/ShieldSecretService.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/shield/ShieldSecretService.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/shield/ShieldSecretService.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/shield/ShieldSecretService.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/shield/WatcherSettingsFilter.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/shield/WatcherSettingsFilter.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/shield/WatcherSettingsFilter.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/shield/WatcherSettingsFilter.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/shield/WatcherShieldModule.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/shield/WatcherShieldModule.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/shield/WatcherShieldModule.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/shield/WatcherShieldModule.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/shield/WatcherUserHolder.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/shield/WatcherUserHolder.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/shield/WatcherUserHolder.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/shield/WatcherUserHolder.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/ArrayObjectIterator.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/ArrayObjectIterator.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/ArrayObjectIterator.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/ArrayObjectIterator.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/Exceptions.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/Exceptions.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/Exceptions.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/Exceptions.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/Integers.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/Integers.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/Integers.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/Integers.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/Script.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/Script.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/Script.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/Script.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/SearchRequestEquivalence.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/SearchRequestEquivalence.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/SearchRequestEquivalence.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/SearchRequestEquivalence.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/Strings.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/Strings.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/Strings.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/Strings.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/ThreadPoolSettingsBuilder.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/ThreadPoolSettingsBuilder.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/ThreadPoolSettingsBuilder.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/ThreadPoolSettingsBuilder.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/Variables.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/Variables.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/Variables.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/Variables.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/WatcherDateTimeUtils.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/WatcherDateTimeUtils.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/WatcherDateTimeUtils.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/WatcherDateTimeUtils.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/WatcherIndexTemplateRegistry.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/WatcherIndexTemplateRegistry.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/WatcherIndexTemplateRegistry.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/WatcherIndexTemplateRegistry.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/WatcherUtils.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/WatcherUtils.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/WatcherUtils.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/WatcherUtils.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/XContentFilterKeysUtils.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/XContentFilterKeysUtils.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/XContentFilterKeysUtils.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/XContentFilterKeysUtils.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/clock/Clock.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/clock/Clock.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/clock/Clock.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/clock/Clock.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/clock/ClockModule.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/clock/ClockModule.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/clock/ClockModule.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/clock/ClockModule.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/clock/HaltedClock.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/clock/HaltedClock.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/clock/HaltedClock.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/clock/HaltedClock.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/clock/SystemClock.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/clock/SystemClock.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/clock/SystemClock.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/clock/SystemClock.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/concurrent/FairKeyedLock.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/concurrent/FairKeyedLock.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/concurrent/FairKeyedLock.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/concurrent/FairKeyedLock.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpClient.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpClient.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpClient.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpClient.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpClientModule.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpClientModule.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpClientModule.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpClientModule.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpContentType.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpContentType.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpContentType.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpContentType.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpMethod.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpMethod.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpMethod.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpMethod.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpProxy.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpProxy.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpProxy.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpProxy.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpRequest.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpRequest.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpRequest.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpRequest.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpRequestTemplate.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpRequestTemplate.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpRequestTemplate.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpRequestTemplate.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpResponse.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpResponse.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpResponse.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/HttpResponse.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/http/Scheme.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/Scheme.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/http/Scheme.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/Scheme.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/http/auth/ApplicableHttpAuth.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/auth/ApplicableHttpAuth.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/http/auth/ApplicableHttpAuth.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/auth/ApplicableHttpAuth.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/http/auth/HttpAuth.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/auth/HttpAuth.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/http/auth/HttpAuth.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/auth/HttpAuth.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/http/auth/HttpAuthFactory.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/auth/HttpAuthFactory.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/http/auth/HttpAuthFactory.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/auth/HttpAuthFactory.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/http/auth/HttpAuthRegistry.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/auth/HttpAuthRegistry.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/http/auth/HttpAuthRegistry.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/auth/HttpAuthRegistry.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/http/auth/basic/ApplicableBasicAuth.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/auth/basic/ApplicableBasicAuth.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/http/auth/basic/ApplicableBasicAuth.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/auth/basic/ApplicableBasicAuth.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/http/auth/basic/BasicAuth.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/auth/basic/BasicAuth.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/http/auth/basic/BasicAuth.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/auth/basic/BasicAuth.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/http/auth/basic/BasicAuthFactory.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/auth/basic/BasicAuthFactory.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/http/auth/basic/BasicAuthFactory.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/http/auth/basic/BasicAuthFactory.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/init/InitializingModule.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/init/InitializingModule.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/init/InitializingModule.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/init/InitializingModule.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/init/InitializingService.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/init/InitializingService.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/init/InitializingService.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/init/InitializingService.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/init/proxy/ClientProxy.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/init/proxy/ClientProxy.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/init/proxy/ClientProxy.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/init/proxy/ClientProxy.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/init/proxy/ScriptServiceProxy.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/init/proxy/ScriptServiceProxy.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/init/proxy/ScriptServiceProxy.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/init/proxy/ScriptServiceProxy.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/secret/Secret.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/secret/Secret.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/secret/Secret.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/secret/Secret.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/secret/SecretModule.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/secret/SecretModule.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/secret/SecretModule.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/secret/SecretModule.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/secret/SecretService.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/secret/SecretService.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/secret/SecretService.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/secret/SecretService.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/text/TextTemplate.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/text/TextTemplate.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/text/TextTemplate.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/text/TextTemplate.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/text/TextTemplateEngine.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/text/TextTemplateEngine.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/text/TextTemplateEngine.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/text/TextTemplateEngine.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/text/TextTemplateModule.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/text/TextTemplateModule.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/text/TextTemplateModule.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/text/TextTemplateModule.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/text/xmustache/XMustacheFactory.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/text/xmustache/XMustacheFactory.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/text/xmustache/XMustacheFactory.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/text/xmustache/XMustacheFactory.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/text/xmustache/XMustacheScriptEngineService.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/text/xmustache/XMustacheScriptEngineService.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/text/xmustache/XMustacheScriptEngineService.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/text/xmustache/XMustacheScriptEngineService.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/text/xmustache/XMustacheTextTemplateEngine.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/text/xmustache/XMustacheTextTemplateEngine.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/text/xmustache/XMustacheTextTemplateEngine.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/text/xmustache/XMustacheTextTemplateEngine.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/validation/Validation.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/validation/Validation.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/validation/Validation.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/validation/Validation.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/validation/WatcherSettingsValidation.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/validation/WatcherSettingsValidation.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/validation/WatcherSettingsValidation.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/validation/WatcherSettingsValidation.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/xcontent/ObjectPath.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/xcontent/ObjectPath.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/xcontent/ObjectPath.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/xcontent/ObjectPath.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/xcontent/WatcherParams.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/xcontent/WatcherParams.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/xcontent/WatcherParams.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/xcontent/WatcherParams.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/xcontent/WatcherXContentParser.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/xcontent/WatcherXContentParser.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/xcontent/WatcherXContentParser.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/xcontent/WatcherXContentParser.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/xcontent/WatcherXContentUtils.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/xcontent/WatcherXContentUtils.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/xcontent/WatcherXContentUtils.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/xcontent/WatcherXContentUtils.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/support/xcontent/XContentSource.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/xcontent/XContentSource.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/support/xcontent/XContentSource.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/support/xcontent/XContentSource.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transform/ExecutableTransform.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transform/ExecutableTransform.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transform/ExecutableTransform.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transform/ExecutableTransform.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transform/Transform.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transform/Transform.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transform/Transform.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transform/Transform.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transform/TransformBuilders.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transform/TransformBuilders.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transform/TransformBuilders.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transform/TransformBuilders.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transform/TransformFactory.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transform/TransformFactory.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transform/TransformFactory.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transform/TransformFactory.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transform/TransformModule.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transform/TransformModule.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transform/TransformModule.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transform/TransformModule.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transform/TransformRegistry.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transform/TransformRegistry.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transform/TransformRegistry.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transform/TransformRegistry.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transform/chain/ChainTransform.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transform/chain/ChainTransform.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transform/chain/ChainTransform.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transform/chain/ChainTransform.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transform/chain/ChainTransformFactory.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transform/chain/ChainTransformFactory.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transform/chain/ChainTransformFactory.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transform/chain/ChainTransformFactory.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transform/chain/ExecutableChainTransform.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transform/chain/ExecutableChainTransform.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transform/chain/ExecutableChainTransform.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transform/chain/ExecutableChainTransform.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transform/script/ExecutableScriptTransform.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transform/script/ExecutableScriptTransform.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transform/script/ExecutableScriptTransform.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transform/script/ExecutableScriptTransform.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transform/script/ScriptTransform.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transform/script/ScriptTransform.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transform/script/ScriptTransform.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transform/script/ScriptTransform.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transform/script/ScriptTransformFactory.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transform/script/ScriptTransformFactory.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transform/script/ScriptTransformFactory.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transform/script/ScriptTransformFactory.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transform/search/ExecutableSearchTransform.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transform/search/ExecutableSearchTransform.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transform/search/ExecutableSearchTransform.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transform/search/ExecutableSearchTransform.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transform/search/SearchTransform.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transform/search/SearchTransform.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transform/search/SearchTransform.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transform/search/SearchTransform.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transform/search/SearchTransformFactory.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transform/search/SearchTransformFactory.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transform/search/SearchTransformFactory.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transform/search/SearchTransformFactory.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/WatcherTransportAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/WatcherTransportAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/WatcherTransportAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/WatcherTransportAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/ack/AckWatchAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/ack/AckWatchAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/ack/AckWatchAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/ack/AckWatchAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/ack/AckWatchRequest.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/ack/AckWatchRequest.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/ack/AckWatchRequest.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/ack/AckWatchRequest.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/ack/AckWatchRequestBuilder.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/ack/AckWatchRequestBuilder.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/ack/AckWatchRequestBuilder.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/ack/AckWatchRequestBuilder.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/ack/AckWatchResponse.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/ack/AckWatchResponse.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/ack/AckWatchResponse.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/ack/AckWatchResponse.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/ack/TransportAckWatchAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/ack/TransportAckWatchAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/ack/TransportAckWatchAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/ack/TransportAckWatchAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/activate/ActivateWatchAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/activate/ActivateWatchAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/activate/ActivateWatchAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/activate/ActivateWatchAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/activate/ActivateWatchRequest.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/activate/ActivateWatchRequest.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/activate/ActivateWatchRequest.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/activate/ActivateWatchRequest.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/activate/ActivateWatchRequestBuilder.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/activate/ActivateWatchRequestBuilder.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/activate/ActivateWatchRequestBuilder.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/activate/ActivateWatchRequestBuilder.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/activate/ActivateWatchResponse.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/activate/ActivateWatchResponse.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/activate/ActivateWatchResponse.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/activate/ActivateWatchResponse.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/activate/TransportActivateWatchAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/activate/TransportActivateWatchAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/activate/TransportActivateWatchAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/activate/TransportActivateWatchAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/delete/DeleteWatchAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/delete/DeleteWatchAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/delete/DeleteWatchAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/delete/DeleteWatchAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/delete/DeleteWatchRequest.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/delete/DeleteWatchRequest.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/delete/DeleteWatchRequest.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/delete/DeleteWatchRequest.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/delete/DeleteWatchRequestBuilder.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/delete/DeleteWatchRequestBuilder.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/delete/DeleteWatchRequestBuilder.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/delete/DeleteWatchRequestBuilder.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/delete/DeleteWatchResponse.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/delete/DeleteWatchResponse.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/delete/DeleteWatchResponse.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/delete/DeleteWatchResponse.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/delete/TransportDeleteWatchAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/delete/TransportDeleteWatchAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/delete/TransportDeleteWatchAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/delete/TransportDeleteWatchAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/execute/ExecuteWatchAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/execute/ExecuteWatchAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/execute/ExecuteWatchAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/execute/ExecuteWatchAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/execute/ExecuteWatchRequest.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/execute/ExecuteWatchRequest.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/execute/ExecuteWatchRequest.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/execute/ExecuteWatchRequest.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/execute/ExecuteWatchRequestBuilder.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/execute/ExecuteWatchRequestBuilder.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/execute/ExecuteWatchRequestBuilder.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/execute/ExecuteWatchRequestBuilder.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/execute/ExecuteWatchResponse.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/execute/ExecuteWatchResponse.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/execute/ExecuteWatchResponse.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/execute/ExecuteWatchResponse.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/execute/TransportExecuteWatchAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/execute/TransportExecuteWatchAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/execute/TransportExecuteWatchAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/execute/TransportExecuteWatchAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/get/GetWatchAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/get/GetWatchAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/get/GetWatchAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/get/GetWatchAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/get/GetWatchRequest.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/get/GetWatchRequest.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/get/GetWatchRequest.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/get/GetWatchRequest.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/get/GetWatchRequestBuilder.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/get/GetWatchRequestBuilder.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/get/GetWatchRequestBuilder.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/get/GetWatchRequestBuilder.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/get/GetWatchResponse.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/get/GetWatchResponse.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/get/GetWatchResponse.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/get/GetWatchResponse.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/get/TransportGetWatchAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/get/TransportGetWatchAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/get/TransportGetWatchAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/get/TransportGetWatchAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/put/PutWatchAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/put/PutWatchAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/put/PutWatchAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/put/PutWatchAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/put/PutWatchRequest.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/put/PutWatchRequest.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/put/PutWatchRequest.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/put/PutWatchRequest.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/put/PutWatchRequestBuilder.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/put/PutWatchRequestBuilder.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/put/PutWatchRequestBuilder.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/put/PutWatchRequestBuilder.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/put/PutWatchResponse.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/put/PutWatchResponse.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/put/PutWatchResponse.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/put/PutWatchResponse.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/put/TransportPutWatchAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/put/TransportPutWatchAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/put/TransportPutWatchAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/put/TransportPutWatchAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/service/TransportWatcherServiceAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/service/TransportWatcherServiceAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/service/TransportWatcherServiceAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/service/TransportWatcherServiceAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/service/WatcherServiceAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/service/WatcherServiceAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/service/WatcherServiceAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/service/WatcherServiceAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/service/WatcherServiceRequest.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/service/WatcherServiceRequest.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/service/WatcherServiceRequest.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/service/WatcherServiceRequest.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/service/WatcherServiceRequestBuilder.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/service/WatcherServiceRequestBuilder.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/service/WatcherServiceRequestBuilder.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/service/WatcherServiceRequestBuilder.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/service/WatcherServiceResponse.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/service/WatcherServiceResponse.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/service/WatcherServiceResponse.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/service/WatcherServiceResponse.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/stats/TransportWatcherStatsAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/stats/TransportWatcherStatsAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/stats/TransportWatcherStatsAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/stats/TransportWatcherStatsAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/stats/WatcherStatsAction.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/stats/WatcherStatsAction.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/stats/WatcherStatsAction.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/stats/WatcherStatsAction.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/stats/WatcherStatsRequest.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/stats/WatcherStatsRequest.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/stats/WatcherStatsRequest.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/stats/WatcherStatsRequest.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/stats/WatcherStatsRequestBuilder.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/stats/WatcherStatsRequestBuilder.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/stats/WatcherStatsRequestBuilder.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/stats/WatcherStatsRequestBuilder.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/stats/WatcherStatsResponse.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/stats/WatcherStatsResponse.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/transport/actions/stats/WatcherStatsResponse.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/transport/actions/stats/WatcherStatsResponse.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/AbstractTriggerEngine.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/AbstractTriggerEngine.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/AbstractTriggerEngine.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/AbstractTriggerEngine.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/Trigger.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/Trigger.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/Trigger.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/Trigger.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/TriggerBuilders.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/TriggerBuilders.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/TriggerBuilders.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/TriggerBuilders.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/TriggerEngine.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/TriggerEngine.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/TriggerEngine.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/TriggerEngine.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/TriggerEvent.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/TriggerEvent.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/TriggerEvent.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/TriggerEvent.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/TriggerModule.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/TriggerModule.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/TriggerModule.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/TriggerModule.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/TriggerService.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/TriggerService.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/TriggerService.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/TriggerService.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/manual/ManualTrigger.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/manual/ManualTrigger.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/manual/ManualTrigger.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/manual/ManualTrigger.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/manual/ManualTriggerEngine.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/manual/ManualTriggerEngine.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/manual/ManualTriggerEngine.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/manual/ManualTriggerEngine.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/manual/ManualTriggerEvent.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/manual/ManualTriggerEvent.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/manual/ManualTriggerEvent.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/manual/ManualTriggerEvent.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/Cron.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/Cron.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/Cron.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/Cron.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/CronSchedule.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/CronSchedule.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/CronSchedule.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/CronSchedule.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/CronnableSchedule.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/CronnableSchedule.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/CronnableSchedule.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/CronnableSchedule.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/DailySchedule.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/DailySchedule.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/DailySchedule.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/DailySchedule.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/HourlySchedule.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/HourlySchedule.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/HourlySchedule.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/HourlySchedule.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/IntervalSchedule.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/IntervalSchedule.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/IntervalSchedule.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/IntervalSchedule.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/MonthlySchedule.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/MonthlySchedule.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/MonthlySchedule.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/MonthlySchedule.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/Schedule.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/Schedule.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/Schedule.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/Schedule.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/ScheduleModule.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/ScheduleModule.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/ScheduleModule.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/ScheduleModule.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/ScheduleRegistry.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/ScheduleRegistry.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/ScheduleRegistry.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/ScheduleRegistry.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/ScheduleTrigger.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/ScheduleTrigger.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/ScheduleTrigger.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/ScheduleTrigger.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/ScheduleTriggerEngine.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/ScheduleTriggerEngine.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/ScheduleTriggerEngine.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/ScheduleTriggerEngine.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/ScheduleTriggerEvent.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/ScheduleTriggerEvent.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/ScheduleTriggerEvent.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/ScheduleTriggerEvent.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/Schedules.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/Schedules.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/Schedules.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/Schedules.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/WeeklySchedule.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/WeeklySchedule.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/WeeklySchedule.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/WeeklySchedule.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/YearlySchedule.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/YearlySchedule.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/YearlySchedule.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/YearlySchedule.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/engine/SchedulerScheduleTriggerEngine.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/engine/SchedulerScheduleTriggerEngine.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/engine/SchedulerScheduleTriggerEngine.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/engine/SchedulerScheduleTriggerEngine.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/engine/TickerScheduleTriggerEngine.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/engine/TickerScheduleTriggerEngine.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/engine/TickerScheduleTriggerEngine.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/engine/TickerScheduleTriggerEngine.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/support/DayOfWeek.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/support/DayOfWeek.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/support/DayOfWeek.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/support/DayOfWeek.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/support/DayTimes.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/support/DayTimes.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/support/DayTimes.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/support/DayTimes.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/support/Month.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/support/Month.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/support/Month.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/support/Month.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/support/MonthTimes.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/support/MonthTimes.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/support/MonthTimes.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/support/MonthTimes.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/support/Times.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/support/Times.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/support/Times.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/support/Times.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/support/WeekTimes.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/support/WeekTimes.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/support/WeekTimes.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/support/WeekTimes.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/support/YearTimes.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/support/YearTimes.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/support/YearTimes.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/support/YearTimes.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/tool/CronEvalTool.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/tool/CronEvalTool.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/tool/CronEvalTool.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/trigger/schedule/tool/CronEvalTool.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/watch/Payload.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/watch/Payload.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/watch/Payload.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/watch/Payload.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/watch/Watch.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/watch/Watch.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/watch/Watch.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/watch/Watch.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/watch/WatchLockService.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/watch/WatchLockService.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/watch/WatchLockService.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/watch/WatchLockService.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/watch/WatchModule.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/watch/WatchModule.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/watch/WatchModule.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/watch/WatchModule.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/watch/WatchStatus.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/watch/WatchStatus.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/watch/WatchStatus.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/watch/WatchStatus.java diff --git a/watcher/src/main/java/org/elasticsearch/watcher/watch/WatchStore.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/watch/WatchStore.java similarity index 100% rename from watcher/src/main/java/org/elasticsearch/watcher/watch/WatchStore.java rename to elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/watch/WatchStore.java diff --git a/watcher/src/main/resources/org/elasticsearch/watcher/trigger/schedule/tool/croneval-eval.help b/elasticsearch/x-pack/watcher/src/main/resources/org/elasticsearch/watcher/trigger/schedule/tool/croneval-eval.help similarity index 100% rename from watcher/src/main/resources/org/elasticsearch/watcher/trigger/schedule/tool/croneval-eval.help rename to elasticsearch/x-pack/watcher/src/main/resources/org/elasticsearch/watcher/trigger/schedule/tool/croneval-eval.help diff --git a/watcher/src/main/resources/triggered_watches.json b/elasticsearch/x-pack/watcher/src/main/resources/triggered_watches.json similarity index 100% rename from watcher/src/main/resources/triggered_watches.json rename to elasticsearch/x-pack/watcher/src/main/resources/triggered_watches.json diff --git a/watcher/src/main/resources/watch_history.json b/elasticsearch/x-pack/watcher/src/main/resources/watch_history.json similarity index 100% rename from watcher/src/main/resources/watch_history.json rename to elasticsearch/x-pack/watcher/src/main/resources/watch_history.json diff --git a/watcher/src/main/resources/watcher-build.properties b/elasticsearch/x-pack/watcher/src/main/resources/watcher-build.properties similarity index 100% rename from watcher/src/main/resources/watcher-build.properties rename to elasticsearch/x-pack/watcher/src/main/resources/watcher-build.properties diff --git a/watcher/src/main/resources/watches.json b/elasticsearch/x-pack/watcher/src/main/resources/watches.json similarity index 100% rename from watcher/src/main/resources/watches.json rename to elasticsearch/x-pack/watcher/src/main/resources/watches.json diff --git a/watcher/src/test/java/org/elasticsearch/script/SleepScriptEngine.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/script/SleepScriptEngine.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/script/SleepScriptEngine.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/script/SleepScriptEngine.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/WatcherF.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/WatcherF.java similarity index 95% rename from watcher/src/test/java/org/elasticsearch/watcher/WatcherF.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/WatcherF.java index e651477eb8a..9343332596b 100644 --- a/watcher/src/test/java/org/elasticsearch/watcher/WatcherF.java +++ b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/WatcherF.java @@ -8,7 +8,7 @@ package org.elasticsearch.watcher; import org.elasticsearch.Version; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.SuppressForbidden; -import org.elasticsearch.license.plugin.LicensePlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.node.MockNode; import org.elasticsearch.node.Node; @@ -50,7 +50,7 @@ public class WatcherF { System.setProperty("es.watcher.actions.slack.service.account.a1.url", "https://hooks.slack.com/services/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"); final CountDownLatch latch = new CountDownLatch(1); - final Node node = new MockNode(settings.build(), Version.CURRENT, Arrays.asList(WatcherPlugin.class, LicensePlugin.class)); + final Node node = new MockNode(settings.build(), Version.CURRENT, Arrays.asList(XPackPlugin.class, XPackPlugin.class)); Runtime.getRuntime().addShutdownHook(new Thread() { @Override diff --git a/watcher/src/test/java/org/elasticsearch/watcher/WatcherLifeCycleServiceTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/WatcherLifeCycleServiceTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/WatcherLifeCycleServiceTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/WatcherLifeCycleServiceTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/WatcherPluginDisableTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/WatcherPluginDisableTests.java similarity index 89% rename from watcher/src/test/java/org/elasticsearch/watcher/WatcherPluginDisableTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/WatcherPluginDisableTests.java index 5bb860daab0..c10e5b5276d 100644 --- a/watcher/src/test/java/org/elasticsearch/watcher/WatcherPluginDisableTests.java +++ b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/WatcherPluginDisableTests.java @@ -12,7 +12,8 @@ import org.elasticsearch.action.admin.cluster.node.info.NodeInfo; import org.elasticsearch.action.admin.cluster.node.info.NodesInfoResponse; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.http.HttpServerTransport; -import org.elasticsearch.license.plugin.LicensePlugin; +import org.elasticsearch.shield.ShieldPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.node.Node; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.test.ESIntegTestCase; @@ -41,18 +42,19 @@ public class WatcherPluginDisableTests extends ESIntegTestCase { return Settings.settingsBuilder() .put(super.nodeSettings(nodeOrdinal)) .put(WatcherPlugin.ENABLED_SETTING, false) + .put(ShieldPlugin.ENABLED_SETTING_NAME, false) // disable shield because of query cache check and authentication/authorization .put(Node.HTTP_ENABLED, true) .build(); } @Override protected Collection> nodePlugins() { - return Arrays.asList(WatcherPlugin.class, LicensePlugin.class); + return Collections.>singleton(XPackPlugin.class); } @Override protected Collection> transportClientPlugins() { - return Collections.>singleton(WatcherPlugin.class); + return Collections.>singleton(XPackPlugin.class); } @Override diff --git a/watcher/src/test/java/org/elasticsearch/watcher/WatcherPluginTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/WatcherPluginTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/WatcherPluginTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/WatcherPluginTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/WatcherServiceTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/WatcherServiceTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/WatcherServiceTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/WatcherServiceTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/ActionErrorIntegrationTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/ActionErrorIntegrationTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/ActionErrorIntegrationTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/ActionErrorIntegrationTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/TimeThrottleIntegrationTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/TimeThrottleIntegrationTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/TimeThrottleIntegrationTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/TimeThrottleIntegrationTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/email/DataAttachmentTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/email/DataAttachmentTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/email/DataAttachmentTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/email/DataAttachmentTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/email/EmailActionIntegrationTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/email/EmailActionIntegrationTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/email/EmailActionIntegrationTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/email/EmailActionIntegrationTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/email/EmailActionTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/email/EmailActionTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/email/EmailActionTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/email/EmailActionTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/email/EmailSecretsIntegrationTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/email/EmailSecretsIntegrationTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/email/EmailSecretsIntegrationTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/email/EmailSecretsIntegrationTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/AccountTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/AccountTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/AccountTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/AccountTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/AccountsTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/AccountsTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/AccountsTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/AccountsTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/EmailTemplateTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/EmailTemplateTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/EmailTemplateTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/EmailTemplateTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/EmailTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/EmailTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/EmailTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/EmailTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/HtmlSanitizerTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/HtmlSanitizerTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/HtmlSanitizerTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/HtmlSanitizerTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/InternalEmailServiceTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/InternalEmailServiceTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/InternalEmailServiceTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/InternalEmailServiceTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/ManualPublicSmtpServersTester.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/ManualPublicSmtpServersTester.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/ManualPublicSmtpServersTester.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/ManualPublicSmtpServersTester.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/support/EmailServer.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/support/EmailServer.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/support/EmailServer.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/email/service/support/EmailServer.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/HipChatActionFactoryTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/HipChatActionFactoryTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/HipChatActionFactoryTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/HipChatActionFactoryTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/HipChatActionTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/HipChatActionTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/HipChatActionTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/HipChatActionTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatAccountsTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatAccountsTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatAccountsTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatAccountsTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatMessageTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatMessageTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatMessageTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatMessageTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatServiceTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatServiceTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatServiceTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/service/HipChatServiceTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/service/IntegrationAccountTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/service/IntegrationAccountTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/service/IntegrationAccountTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/service/IntegrationAccountTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/service/InternalHipChatServiceTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/service/InternalHipChatServiceTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/service/InternalHipChatServiceTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/service/InternalHipChatServiceTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/service/UserAccountTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/service/UserAccountTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/service/UserAccountTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/service/UserAccountTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/service/V1AccountTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/service/V1AccountTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/service/V1AccountTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/hipchat/service/V1AccountTests.java diff --git a/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/index/IndexActionIntegrationTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/index/IndexActionIntegrationTests.java new file mode 100644 index 00000000000..4fedd5b0d8a --- /dev/null +++ b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/index/IndexActionIntegrationTests.java @@ -0,0 +1,205 @@ +/* + * 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.actions.index; + +import org.apache.lucene.util.LuceneTestCase.AwaitsFix; +import org.elasticsearch.action.search.SearchRequest; +import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.action.search.SearchType; +import org.elasticsearch.search.SearchHit; +import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval; +import org.elasticsearch.search.sort.SortOrder; +import org.elasticsearch.watcher.history.HistoryStore; +import org.elasticsearch.watcher.support.WatcherDateTimeUtils; +import org.elasticsearch.watcher.test.AbstractWatcherIntegrationTestCase; +import org.elasticsearch.watcher.transport.actions.execute.ExecuteWatchResponse; +import org.elasticsearch.watcher.transport.actions.put.PutWatchResponse; +import org.elasticsearch.watcher.trigger.schedule.ScheduleTriggerEvent; +import org.joda.time.DateTime; +import org.joda.time.DateTimeZone; + +import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; +import static org.elasticsearch.index.query.QueryBuilders.matchQuery; +import static org.elasticsearch.search.aggregations.AggregationBuilders.dateHistogram; +import static org.elasticsearch.search.builder.SearchSourceBuilder.searchSource; +import static org.elasticsearch.watcher.actions.ActionBuilders.indexAction; +import static org.elasticsearch.watcher.client.WatchSourceBuilders.watchBuilder; +import static org.elasticsearch.watcher.input.InputBuilders.searchInput; +import static org.elasticsearch.watcher.input.InputBuilders.simpleInput; +import static org.elasticsearch.watcher.transform.TransformBuilders.scriptTransform; +import static org.elasticsearch.watcher.trigger.TriggerBuilders.schedule; +import static org.elasticsearch.watcher.trigger.schedule.Schedules.cron; +import static org.hamcrest.Matchers.hasEntry; +import static org.hamcrest.Matchers.hasKey; +import static org.hamcrest.Matchers.is; + +/** + * + */ +@AwaitsFix(bugUrl = "https://github.com/elastic/x-plugins/issues/724") +public class IndexActionIntegrationTests extends AbstractWatcherIntegrationTestCase { + public void testSimple() throws Exception { + PutWatchResponse putWatchResponse = watcherClient().preparePutWatch("_id").setSource(watchBuilder() + .trigger(schedule(cron("0/1 * * * * ? 2020"))) + .input(simpleInput("foo", "bar")) + .addAction("index-buckets", indexAction("idx", "type").setExecutionTimeField("@timestamp"))) + .get(); + + assertThat(putWatchResponse.isCreated(), is(true)); + + DateTime now = timeWarped() ? timeWarp().clock().now(DateTimeZone.UTC) : DateTime.now(DateTimeZone.UTC); + + ExecuteWatchResponse executeWatchResponse = watcherClient().prepareExecuteWatch("_id") + .setTriggerEvent(new ScheduleTriggerEvent(now, now)) + .get(); + + assertThat(executeWatchResponse.getRecordSource().getValue("state"), is((Object) "executed")); + + flush("idx"); + refresh(); + + SearchResponse searchResponse = client().prepareSearch("idx").setTypes("type").get(); + assertThat(searchResponse.getHits().totalHits(), is(1L)); + SearchHit hit = searchResponse.getHits().getAt(0); + if (timeWarped()) { + assertThat(hit.getSource(), hasEntry("@timestamp", (Object) WatcherDateTimeUtils.formatDate(now))); + } else { + assertThat(hit.getSource(), hasKey("@timestamp")); + DateTime timestamp = WatcherDateTimeUtils.parseDate((String) hit.getSource().get("@timestamp")); + assertThat(timestamp.isEqual(now) || timestamp.isAfter(now), is(true)); + } + assertThat(hit.getSource(), hasEntry("foo", (Object) "bar")); + } + + public void testSimpleWithDocField() throws Exception { + PutWatchResponse putWatchResponse = watcherClient().preparePutWatch("_id").setSource(watchBuilder() + .trigger(schedule(cron("0/1 * * * * ? 2020"))) + .input(simpleInput("foo", "bar")) + .addAction("index-buckets", + scriptTransform("return [ '_doc' : ctx.payload ]"), + indexAction("idx", "type").setExecutionTimeField("@timestamp"))) + + .get(); + + assertThat(putWatchResponse.isCreated(), is(true)); + + DateTime now = timeWarped() ? timeWarp().clock().now(DateTimeZone.UTC) : DateTime.now(DateTimeZone.UTC); + + ExecuteWatchResponse executeWatchResponse = watcherClient().prepareExecuteWatch("_id") + .setTriggerEvent(new ScheduleTriggerEvent(now, now)) + .get(); + + assertThat(executeWatchResponse.getRecordSource().getValue("state"), is((Object) "executed")); + + flush("idx"); + refresh(); + + SearchResponse searchResponse = client().prepareSearch("idx").setTypes("type").get(); + assertThat(searchResponse.getHits().totalHits(), is(1L)); + SearchHit hit = searchResponse.getHits().getAt(0); + if (timeWarped()) { + assertThat(hit.getSource(), hasEntry("@timestamp", (Object) WatcherDateTimeUtils.formatDate(now))); + } else { + assertThat(hit.getSource(), hasKey("@timestamp")); + DateTime timestamp = WatcherDateTimeUtils.parseDate((String) hit.getSource().get("@timestamp")); + assertThat(timestamp.isEqual(now) || timestamp.isAfter(now), is(true)); + } + assertThat(hit.getSource(), hasEntry("foo", (Object) "bar")); + } + + public void testSimpleWithDocFieldWrongFieldType() throws Exception { + PutWatchResponse putWatchResponse = watcherClient().preparePutWatch("_id").setSource(watchBuilder() + .trigger(schedule(cron("0/1 * * * * ? 2020"))) + .input(simpleInput("foo", "bar")) + .addAction("index-buckets", + scriptTransform("return [ '_doc' : 1 ]"), + indexAction("idx", "type").setExecutionTimeField("@timestamp"))) + .get(); + + assertThat(putWatchResponse.isCreated(), is(true)); + + DateTime now = timeWarped() ? timeWarp().clock().now(DateTimeZone.UTC) : DateTime.now(DateTimeZone.UTC); + + ExecuteWatchResponse executeWatchResponse = watcherClient().prepareExecuteWatch("_id") + .setTriggerEvent(new ScheduleTriggerEvent(now, now)) + .setRecordExecution(true) + .get(); + + assertThat(executeWatchResponse.getRecordSource().getValue("state"), is((Object) "executed")); + + flush(); + refresh(); + + assertThat(client().admin().indices().prepareExists("idx").get().isExists(), is(false)); + + assertThat(docCount(HistoryStore.INDEX_PREFIX + "*", HistoryStore.DOC_TYPE, searchSource() + .query(matchQuery("result.actions.status", "failure"))), is(1L)); + + } + + public void testIndexAggsBucketsAsDocuments() throws Exception { + DateTime now = timeWarped() ? timeWarp().clock().now(DateTimeZone.UTC) : DateTime.now(DateTimeZone.UTC); + long bucketCount = randomIntBetween(2, 5); + for (int i = 0; i < bucketCount; i++) { + index("idx", "type", jsonBuilder().startObject() + .field("timestamp", now.minusDays(i)) + .endObject()); + } + + flush("idx"); + refresh(); + + PutWatchResponse putWatchResponse = watcherClient().preparePutWatch("_id").setSource(watchBuilder() + .trigger(schedule(cron("0/1 * * * * ? 2020"))) + .input(searchInput(new SearchRequest("idx") + .types("type") + .searchType(SearchType.QUERY_THEN_FETCH) + .source(searchSource() + .aggregation(dateHistogram("trend") + .field("timestamp") + .interval(DateHistogramInterval.DAY))))) + .addAction("index-buckets", + + // this transform takes the bucket list and assigns it to `_doc` + // this means each bucket will be indexed as a separate doc, + // so we expect to have the same number of documents as the number + // of buckets. + scriptTransform("return [ '_doc' : ctx.payload.aggregations.trend.buckets]"), + + indexAction("idx", "bucket").setExecutionTimeField("@timestamp"))) + + .get(); + + assertThat(putWatchResponse.isCreated(), is(true)); + + ExecuteWatchResponse executeWatchResponse = watcherClient().prepareExecuteWatch("_id") + .setTriggerEvent(new ScheduleTriggerEvent(now, now)) + .get(); + + assertThat(executeWatchResponse.getRecordSource().getValue("state"), is((Object) "executed")); + + flush("idx"); + refresh(); + + SearchResponse searchResponse = client().prepareSearch("idx").setTypes("bucket") + .addSort("key", SortOrder.DESC) + .get(); + assertThat(searchResponse.getHits().getTotalHits(), is(bucketCount)); + DateTime key = now.withMillisOfDay(0); + int i = 0; + for (SearchHit hit : searchResponse.getHits()) { + if (timeWarped()) { + assertThat(hit.getSource(), hasEntry("@timestamp", (Object) WatcherDateTimeUtils.formatDate(now))); + } else { + assertThat(hit.getSource(), hasKey("@timestamp")); + DateTime timestamp = WatcherDateTimeUtils.parseDate((String) hit.getSource().get("@timestamp")); + assertThat(timestamp.isEqual(now) || timestamp.isAfter(now), is(true)); + } + assertThat(hit.getSource(), hasEntry("key", (Object) key.getMillis())); + key = key.minusDays(1); + } + } +} diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/index/IndexActionTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/index/IndexActionTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/index/IndexActionTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/index/IndexActionTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/logging/LoggingActionTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/logging/LoggingActionTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/logging/LoggingActionTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/logging/LoggingActionTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/slack/SlackActionFactoryTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/slack/SlackActionFactoryTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/slack/SlackActionFactoryTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/slack/SlackActionFactoryTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/slack/SlackActionTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/slack/SlackActionTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/slack/SlackActionTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/slack/SlackActionTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/slack/service/SlackAccountsTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/slack/service/SlackAccountsTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/slack/service/SlackAccountsTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/slack/service/SlackAccountsTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/slack/service/SlackServiceTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/slack/service/SlackServiceTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/slack/service/SlackServiceTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/slack/service/SlackServiceTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/slack/service/message/SlackMessageDefaultsTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/slack/service/message/SlackMessageDefaultsTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/slack/service/message/SlackMessageDefaultsTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/slack/service/message/SlackMessageDefaultsTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/slack/service/message/SlackMessageTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/slack/service/message/SlackMessageTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/slack/service/message/SlackMessageTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/slack/service/message/SlackMessageTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/throttler/AckThrottlerTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/throttler/AckThrottlerTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/throttler/AckThrottlerTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/throttler/AckThrottlerTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/throttler/ActionThrottleTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/throttler/ActionThrottleTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/throttler/ActionThrottleTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/throttler/ActionThrottleTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/throttler/PeriodThrottlerTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/throttler/PeriodThrottlerTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/throttler/PeriodThrottlerTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/throttler/PeriodThrottlerTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/throttler/WatchThrottlerTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/throttler/WatchThrottlerTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/throttler/WatchThrottlerTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/throttler/WatchThrottlerTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/webhook/WebhookActionTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/webhook/WebhookActionTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/webhook/WebhookActionTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/webhook/WebhookActionTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/webhook/WebhookHttpsIntegrationTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/webhook/WebhookHttpsIntegrationTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/webhook/WebhookHttpsIntegrationTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/webhook/WebhookHttpsIntegrationTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/actions/webhook/WebhookIntegrationTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/webhook/WebhookIntegrationTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/actions/webhook/WebhookIntegrationTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/actions/webhook/WebhookIntegrationTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/condition/always/AlwaysConditionTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/condition/always/AlwaysConditionTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/condition/always/AlwaysConditionTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/condition/always/AlwaysConditionTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/condition/compare/CompareConditionSearchTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/condition/compare/CompareConditionSearchTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/condition/compare/CompareConditionSearchTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/condition/compare/CompareConditionSearchTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/condition/compare/CompareConditionTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/condition/compare/CompareConditionTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/condition/compare/CompareConditionTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/condition/compare/CompareConditionTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/condition/compare/array/ArrayCompareConditionSearchTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/condition/compare/array/ArrayCompareConditionSearchTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/condition/compare/array/ArrayCompareConditionSearchTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/condition/compare/array/ArrayCompareConditionSearchTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/condition/compare/array/ArrayCompareConditionTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/condition/compare/array/ArrayCompareConditionTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/condition/compare/array/ArrayCompareConditionTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/condition/compare/array/ArrayCompareConditionTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/condition/never/NeverConditionTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/condition/never/NeverConditionTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/condition/never/NeverConditionTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/condition/never/NeverConditionTests.java diff --git a/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/condition/script/ScriptConditionSearchTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/condition/script/ScriptConditionSearchTests.java new file mode 100644 index 00000000000..168796ec327 --- /dev/null +++ b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/condition/script/ScriptConditionSearchTests.java @@ -0,0 +1,97 @@ +/* + * 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.condition.script; + +import org.apache.lucene.util.LuceneTestCase.AwaitsFix; +import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.action.search.ShardSearchFailure; +import org.elasticsearch.common.text.StringText; +import org.elasticsearch.search.SearchShardTarget; +import org.elasticsearch.search.aggregations.AggregationBuilders; +import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval; +import org.elasticsearch.search.aggregations.bucket.histogram.Histogram; +import org.elasticsearch.search.internal.InternalSearchHit; +import org.elasticsearch.search.internal.InternalSearchHits; +import org.elasticsearch.search.internal.InternalSearchResponse; +import org.elasticsearch.threadpool.ThreadPool; +import org.elasticsearch.watcher.execution.WatchExecutionContext; +import org.elasticsearch.watcher.support.Script; +import org.elasticsearch.watcher.support.init.proxy.ScriptServiceProxy; +import org.elasticsearch.watcher.test.AbstractWatcherIntegrationTestCase; +import org.elasticsearch.watcher.test.WatcherTestUtils; +import org.elasticsearch.watcher.watch.Payload; +import org.junit.After; +import org.junit.Before; + +import static org.elasticsearch.watcher.test.WatcherTestUtils.mockExecutionContext; +import static org.hamcrest.Matchers.is; +import static org.mockito.Mockito.when; + +/** + */ +@AwaitsFix(bugUrl = "https://github.com/elastic/x-plugins/issues/724") +public class ScriptConditionSearchTests extends AbstractWatcherIntegrationTestCase { + private ThreadPool tp = null; + private ScriptServiceProxy scriptService; + + @Before + public void init() throws Exception { + tp = new ThreadPool(ThreadPool.Names.SAME); + scriptService = WatcherTestUtils.getScriptServiceProxy(tp); + } + + @After + public void cleanup() { + tp.shutdownNow(); + } + + public void testExecuteWithAggs() throws Exception { + client().admin().indices().prepareCreate("my-index") + .addMapping("my-type", "_timestamp", "enabled=true") + .get(); + + client().prepareIndex("my-index", "my-type").setTimestamp("2005-01-01T00:00").setSource("{}").get(); + client().prepareIndex("my-index", "my-type").setTimestamp("2005-01-01T00:10").setSource("{}").get(); + client().prepareIndex("my-index", "my-type").setTimestamp("2005-01-01T00:20").setSource("{}").get(); + client().prepareIndex("my-index", "my-type").setTimestamp("2005-01-01T00:30").setSource("{}").get(); + refresh(); + + SearchResponse response = client().prepareSearch("my-index") + .addAggregation(AggregationBuilders.dateHistogram("rate").field("_timestamp").interval(DateHistogramInterval.HOUR).order(Histogram.Order.COUNT_DESC)) + .get(); + + ExecutableScriptCondition condition = new ExecutableScriptCondition(new ScriptCondition(Script.inline("ctx.payload.aggregations.rate.buckets[0]?.doc_count >= 5").build()), logger, scriptService); + + WatchExecutionContext ctx = mockExecutionContext("_name", new Payload.XContent(response)); + assertFalse(condition.execute(ctx).met()); + + client().prepareIndex("my-index", "my-type").setTimestamp("2005-01-01T00:40").setSource("{}").get(); + refresh(); + + response = client().prepareSearch("my-index") + .addAggregation(AggregationBuilders.dateHistogram("rate").field("_timestamp").interval(DateHistogramInterval.HOUR).order(Histogram.Order.COUNT_DESC)) + .get(); + + ctx = mockExecutionContext("_name", new Payload.XContent(response)); + assertThat(condition.execute(ctx).met(), is(true)); + } + + public void testExecuteAccessHits() throws Exception { + ExecutableScriptCondition condition = new ExecutableScriptCondition(new ScriptCondition(Script.inline("ctx.payload.hits?.hits[0]?._score == 1.0").build()), logger, scriptService); + InternalSearchHit hit = new InternalSearchHit(0, "1", new StringText("type"), null); + hit.score(1f); + hit.shard(new SearchShardTarget("a", "a", 0)); + + InternalSearchResponse internalSearchResponse = new InternalSearchResponse(new InternalSearchHits(new InternalSearchHit[]{hit}, 1l, 1f), null, null, false, false); + SearchResponse response = new SearchResponse(internalSearchResponse, "", 3, 3, 500l, new ShardSearchFailure[0]); + + WatchExecutionContext ctx = mockExecutionContext("_watch_name", new Payload.XContent(response)); + assertThat(condition.execute(ctx).met(), is(true)); + hit.score(2f); + when(ctx.payload()).thenReturn(new Payload.XContent(response)); + assertThat(condition.execute(ctx).met(), is(false)); + } +} diff --git a/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/condition/script/ScriptConditionTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/condition/script/ScriptConditionTests.java new file mode 100644 index 00000000000..f66a3de6ce2 --- /dev/null +++ b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/condition/script/ScriptConditionTests.java @@ -0,0 +1,219 @@ +/* + * 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.condition.script; + + +import org.apache.lucene.util.LuceneTestCase.AwaitsFix; +import org.elasticsearch.ElasticsearchParseException; +import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.action.search.ShardSearchFailure; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.script.ScriptException; +import org.elasticsearch.script.ScriptService; +import org.elasticsearch.script.ScriptService.ScriptType; +import org.elasticsearch.search.internal.InternalSearchResponse; +import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.threadpool.ThreadPool; +import org.elasticsearch.watcher.condition.Condition; +import org.elasticsearch.watcher.execution.WatchExecutionContext; +import org.elasticsearch.watcher.support.Script; +import org.elasticsearch.watcher.support.init.proxy.ScriptServiceProxy; +import org.elasticsearch.watcher.watch.Payload; +import org.joda.time.DateTime; +import org.joda.time.DateTimeZone; +import org.junit.After; +import org.junit.Before; + +import java.io.IOException; + +import static java.util.Collections.singletonMap; +import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; +import static org.elasticsearch.watcher.support.Exceptions.illegalArgument; +import static org.elasticsearch.watcher.test.WatcherTestUtils.getScriptServiceProxy; +import static org.elasticsearch.watcher.test.WatcherTestUtils.mockExecutionContext; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +/** + */ +@AwaitsFix(bugUrl = "https://github.com/elastic/x-plugins/issues/724") +public class ScriptConditionTests extends ESTestCase { + ThreadPool tp = null; + + @Before + public void init() { + tp = new ThreadPool(ThreadPool.Names.SAME); + } + + @After + public void cleanup() { + tp.shutdownNow(); + } + + public void testExecute() throws Exception { + ScriptServiceProxy scriptService = getScriptServiceProxy(tp); + ExecutableScriptCondition condition = new ExecutableScriptCondition(new ScriptCondition(Script.inline("ctx.payload.hits.total > 1").build()), logger, scriptService); + SearchResponse response = new SearchResponse(InternalSearchResponse.empty(), "", 3, 3, 500l, new ShardSearchFailure[0]); + WatchExecutionContext ctx = mockExecutionContext("_name", new Payload.XContent(response)); + assertFalse(condition.execute(ctx).met()); + } + + public void testExecuteMergedParams() throws Exception { + ScriptServiceProxy scriptService = getScriptServiceProxy(tp); + Script script = Script.inline("ctx.payload.hits.total > threshold").lang(ScriptService.DEFAULT_LANG).params(singletonMap("threshold", 1)).build(); + ExecutableScriptCondition executable = new ExecutableScriptCondition(new ScriptCondition(script), logger, scriptService); + SearchResponse response = new SearchResponse(InternalSearchResponse.empty(), "", 3, 3, 500l, new ShardSearchFailure[0]); + WatchExecutionContext ctx = mockExecutionContext("_name", new Payload.XContent(response)); + assertFalse(executable.execute(ctx).met()); + } + + public void testParserValid() throws Exception { + ScriptConditionFactory factory = new ScriptConditionFactory(Settings.settingsBuilder().build(), getScriptServiceProxy(tp)); + + XContentBuilder builder = createConditionContent("ctx.payload.hits.total > 1", null, ScriptType.INLINE); + + XContentParser parser = XContentFactory.xContent(builder.bytes()).createParser(builder.bytes()); + parser.nextToken(); + ScriptCondition condition = factory.parseCondition("_watch", parser); + ExecutableScriptCondition executable = factory.createExecutable(condition); + + SearchResponse response = new SearchResponse(InternalSearchResponse.empty(), "", 3, 3, 500l, new ShardSearchFailure[0]); + WatchExecutionContext ctx = mockExecutionContext("_name", new Payload.XContent(response)); + + assertFalse(executable.execute(ctx).met()); + + + builder = createConditionContent("return true", null, ScriptType.INLINE); + parser = XContentFactory.xContent(builder.bytes()).createParser(builder.bytes()); + parser.nextToken(); + condition = factory.parseCondition("_watch", parser); + executable = factory.createExecutable(condition); + + ctx = mockExecutionContext("_name", new Payload.XContent(response)); + + assertTrue(executable.execute(ctx).met()); + } + + public void testParserInvalid() throws Exception { + ScriptConditionFactory factory = new ScriptConditionFactory(Settings.settingsBuilder().build(), getScriptServiceProxy(tp)); + XContentBuilder builder = XContentFactory.jsonBuilder(); + builder.startObject().endObject(); + XContentParser parser = XContentFactory.xContent(builder.bytes()).createParser(builder.bytes()); + parser.nextToken(); + try { + factory.parseCondition("_id", parser); + fail("expected a condition exception trying to parse an invalid condition XContent"); + } catch (ElasticsearchParseException e) { + // TODO add these when the test if fixed + // assertThat(e.getMessage(), is("ASDF")); + } + } + + public void testScriptConditionParserBadScript() throws Exception { + ScriptConditionFactory conditionParser = new ScriptConditionFactory(Settings.settingsBuilder().build(), getScriptServiceProxy(tp)); + ScriptType scriptType = randomFrom(ScriptType.values()); + String script; + switch (scriptType) { + case INDEXED: + case FILE: + script = "nonExisting_script"; + break; + case INLINE: + default: + script = "foo = = 1"; + } + XContentBuilder builder = createConditionContent(script, "groovy", scriptType); + XContentParser parser = XContentFactory.xContent(builder.bytes()).createParser(builder.bytes()); + parser.nextToken(); + ScriptCondition scriptCondition = conditionParser.parseCondition("_watch", parser); + try { + conditionParser.createExecutable(scriptCondition); + fail("expected a condition validation exception trying to create an executable with a bad or missing script"); + } catch (ScriptException e) { + // TODO add these when the test if fixed + // assertThat(e.getMessage(), is("ASDF")); + } + } + + public void testScriptConditionParser_badLang() throws Exception { + ScriptConditionFactory conditionParser = new ScriptConditionFactory(Settings.settingsBuilder().build(), getScriptServiceProxy(tp)); + ScriptType scriptType = ScriptType.INLINE; + String script = "return true"; + XContentBuilder builder = createConditionContent(script, "not_a_valid_lang", scriptType); + XContentParser parser = XContentFactory.xContent(builder.bytes()).createParser(builder.bytes()); + parser.nextToken(); + ScriptCondition scriptCondition = conditionParser.parseCondition("_watch", parser); + try { + conditionParser.createExecutable(scriptCondition); + fail("expected a condition validation exception trying to create an executable with an invalid language"); + } catch (ScriptException e) { + // TODO add these when the test if fixed + // assertThat(e.getMessage(), is("ASDF")); + } + } + + public void testScriptConditionThrowException() throws Exception { + ScriptServiceProxy scriptService = getScriptServiceProxy(tp); + ExecutableScriptCondition condition = new ExecutableScriptCondition(new ScriptCondition(Script.inline("assert false").build()), logger, scriptService); + SearchResponse response = new SearchResponse(InternalSearchResponse.empty(), "", 3, 3, 500l, new ShardSearchFailure[0]); + WatchExecutionContext ctx = mockExecutionContext("_name", new Payload.XContent(response)); + ScriptCondition.Result result = condition.execute(ctx); + assertThat(result, notNullValue()); + assertThat(result.status(), is(Condition.Result.Status.FAILURE)); + assertThat(result.reason(), notNullValue()); + assertThat(result.reason(), containsString("Assertion")); + } + + public void testScriptConditionReturnObject() throws Exception { + ScriptServiceProxy scriptService = getScriptServiceProxy(tp); + ExecutableScriptCondition condition = new ExecutableScriptCondition(new ScriptCondition(Script.inline("return new Object()").build()), logger, scriptService); + SearchResponse response = new SearchResponse(InternalSearchResponse.empty(), "", 3, 3, 500l, new ShardSearchFailure[0]); + WatchExecutionContext ctx = mockExecutionContext("_name", new Payload.XContent(response)); + ScriptCondition.Result result = condition.execute(ctx); + assertThat(result, notNullValue()); + assertThat(result.status(), is(Condition.Result.Status.FAILURE)); + assertThat(result.reason(), notNullValue()); + assertThat(result.reason(), containsString("ScriptException")); + } + + public void testScriptConditionAccessCtx() throws Exception { + ScriptServiceProxy scriptService = getScriptServiceProxy(tp); + ExecutableScriptCondition condition = new ExecutableScriptCondition(new ScriptCondition(Script.inline("ctx.trigger.scheduled_time.getMillis() < System.currentTimeMillis() ").build()), logger, scriptService); + SearchResponse response = new SearchResponse(InternalSearchResponse.empty(), "", 3, 3, 500l, new ShardSearchFailure[0]); + WatchExecutionContext ctx = mockExecutionContext("_name", new DateTime(DateTimeZone.UTC), new Payload.XContent(response)); + Thread.sleep(10); + assertThat(condition.execute(ctx).met(), is(true)); + } + + private static XContentBuilder createConditionContent(String script, String scriptLang, ScriptType scriptType) throws IOException { + XContentBuilder builder = jsonBuilder(); + if (scriptType == null) { + return builder.value(script); + } + builder.startObject(); + switch (scriptType) { + case INLINE: + builder.field("inline", script); + break; + case FILE: + builder.field("file", script); + break; + case INDEXED: + builder.field("id", script); + break; + default: + throw illegalArgument("unsupported script type [{}]", scriptType); + } + if (scriptLang != null) { + builder.field("lang", scriptLang); + } + return builder.endObject(); + } +} diff --git a/watcher/src/test/java/org/elasticsearch/watcher/execution/ExecutionServiceTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/execution/ExecutionServiceTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/execution/ExecutionServiceTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/execution/ExecutionServiceTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/execution/ManualExecutionTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/execution/ManualExecutionTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/execution/ManualExecutionTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/execution/ManualExecutionTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/execution/TriggeredWatchStoreLifeCycleTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/execution/TriggeredWatchStoreLifeCycleTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/execution/TriggeredWatchStoreLifeCycleTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/execution/TriggeredWatchStoreLifeCycleTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/execution/TriggeredWatchStoreTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/execution/TriggeredWatchStoreTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/execution/TriggeredWatchStoreTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/execution/TriggeredWatchStoreTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/execution/TriggeredWatchTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/execution/TriggeredWatchTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/execution/TriggeredWatchTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/execution/TriggeredWatchTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/history/HistoryStoreSettingsTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/history/HistoryStoreSettingsTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/history/HistoryStoreSettingsTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/history/HistoryStoreSettingsTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/history/HistoryStoreTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/history/HistoryStoreTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/history/HistoryStoreTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/history/HistoryStoreTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/history/HistoryTemplateEmailMappingsTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/history/HistoryTemplateEmailMappingsTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/history/HistoryTemplateEmailMappingsTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/history/HistoryTemplateEmailMappingsTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/history/HistoryTemplateHttpMappingsTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/history/HistoryTemplateHttpMappingsTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/history/HistoryTemplateHttpMappingsTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/history/HistoryTemplateHttpMappingsTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/history/HistoryTemplateIndexActionMappingsTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/history/HistoryTemplateIndexActionMappingsTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/history/HistoryTemplateIndexActionMappingsTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/history/HistoryTemplateIndexActionMappingsTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/history/HistoryTemplateSearchInputMappingsTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/history/HistoryTemplateSearchInputMappingsTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/history/HistoryTemplateSearchInputMappingsTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/history/HistoryTemplateSearchInputMappingsTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/history/HistoryTemplateTimeMappingsTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/history/HistoryTemplateTimeMappingsTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/history/HistoryTemplateTimeMappingsTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/history/HistoryTemplateTimeMappingsTests.java diff --git a/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/history/HistoryTemplateTransformMappingsTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/history/HistoryTemplateTransformMappingsTests.java new file mode 100644 index 00000000000..bac674d7821 --- /dev/null +++ b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/history/HistoryTemplateTransformMappingsTests.java @@ -0,0 +1,110 @@ +/* + * 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.history; + +import com.carrotsearch.hppc.cursors.ObjectObjectCursor; + +import org.apache.lucene.util.LuceneTestCase.AwaitsFix; +import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse; +import org.elasticsearch.cluster.metadata.MappingMetaData; +import org.elasticsearch.common.collect.ImmutableOpenMap; +import org.elasticsearch.watcher.execution.ExecutionState; +import org.elasticsearch.watcher.test.AbstractWatcherIntegrationTestCase; +import org.elasticsearch.watcher.transport.actions.put.PutWatchResponse; + +import java.io.IOException; +import java.util.Map; + +import static org.elasticsearch.common.xcontent.support.XContentMapValues.extractValue; +import static org.elasticsearch.watcher.actions.ActionBuilders.loggingAction; +import static org.elasticsearch.watcher.client.WatchSourceBuilders.watchBuilder; +import static org.elasticsearch.watcher.condition.ConditionBuilders.alwaysCondition; +import static org.elasticsearch.watcher.input.InputBuilders.simpleInput; +import static org.elasticsearch.watcher.transform.TransformBuilders.scriptTransform; +import static org.elasticsearch.watcher.trigger.TriggerBuilders.schedule; +import static org.elasticsearch.watcher.trigger.schedule.Schedules.interval; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +/** + * This test makes sure that the http host and path fields in the watch_record action result are + * not analyzed so they can be used in aggregations + */ +@AwaitsFix(bugUrl = "https://github.com/elastic/x-plugins/issues/724") +public class HistoryTemplateTransformMappingsTests extends AbstractWatcherIntegrationTestCase { + @Override + protected boolean timeWarped() { + return true; // just to have better control over the triggers + } + + @Override + protected boolean enableShield() { + return false; // remove shield noise from this test + } + + public void testTransformFields() throws Exception { + String index = "the-index"; + String type = "the-type"; + createIndex(index); + index(index, type, "{}"); + flush(); + refresh(); + + PutWatchResponse putWatchResponse = watcherClient().preparePutWatch("_id1").setSource(watchBuilder() + .trigger(schedule(interval("5s"))) + .input(simpleInput()) + .condition(alwaysCondition()) + .transform(scriptTransform("return [ 'key' : 'value1' ];")) + .addAction("logger", scriptTransform("return [ 'key' : 'value2' ];"), loggingAction("indexed"))) + .get(); + assertThat(putWatchResponse.isCreated(), is(true)); + timeWarp().scheduler().trigger("_id1"); + + // adding another watch which with a transform that should conflict with the preview watch. Since the + // mapping for the transform construct is disabled, there should be nor problems. + putWatchResponse = watcherClient().preparePutWatch("_id2").setSource(watchBuilder() + .trigger(schedule(interval("5s"))) + .input(simpleInput()) + .condition(alwaysCondition()) + .transform(scriptTransform("return [ 'key' : [ 'key1' : 'value1' ] ];")) + .addAction("logger", scriptTransform("return [ 'key' : [ 'key1' : 'value2' ] ];"), loggingAction("indexed"))) + .get(); + assertThat(putWatchResponse.isCreated(), is(true)); + timeWarp().scheduler().trigger("_id2"); + + flush(); + refresh(); + + assertWatchWithMinimumActionsCount("_id1", ExecutionState.EXECUTED, 1); + assertWatchWithMinimumActionsCount("_id2", ExecutionState.EXECUTED, 1); + + refresh(); + + assertBusy(new Runnable() { + @Override + public void run() { + GetMappingsResponse mappingsResponse = client().admin().indices().prepareGetMappings().get(); + assertThat(mappingsResponse, notNullValue()); + assertThat(mappingsResponse.getMappings().isEmpty(), is(false)); + for (ObjectObjectCursor> metadatas : mappingsResponse.getMappings()) { + if (!metadatas.key.startsWith(".watch_history")) { + continue; + } + MappingMetaData metadata = metadatas.value.get("watch_record"); + assertThat(metadata, notNullValue()); + try { + Map source = metadata.getSourceAsMap(); + logger.info("checking index [{}] with metadata:\n[{}]", metadatas.key, metadata.source().toString()); + assertThat(extractValue("properties.result.properties.transform.properties.payload.enabled", source), is((Object) false)); + assertThat(extractValue("properties.result.properties.actions.properties.transform.properties.payload.enabled", source), is((Object) false)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + }); + } +} diff --git a/watcher/src/test/java/org/elasticsearch/watcher/input/InputRegistryTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/input/InputRegistryTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/input/InputRegistryTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/input/InputRegistryTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/input/chain/ChainInputTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/input/chain/ChainInputTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/input/chain/ChainInputTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/input/chain/ChainInputTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/input/chain/ChainIntegrationTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/input/chain/ChainIntegrationTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/input/chain/ChainIntegrationTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/input/chain/ChainIntegrationTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/input/http/HttpInputIntegrationTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/input/http/HttpInputIntegrationTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/input/http/HttpInputIntegrationTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/input/http/HttpInputIntegrationTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/input/http/HttpInputTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/input/http/HttpInputTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/input/http/HttpInputTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/input/http/HttpInputTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/input/search/SearchInputTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/input/search/SearchInputTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/input/search/SearchInputTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/input/search/SearchInputTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/input/simple/SimpleInputTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/input/simple/SimpleInputTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/input/simple/SimpleInputTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/input/simple/SimpleInputTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/license/LicenseTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/license/LicenseTests.java similarity index 99% rename from watcher/src/test/java/org/elasticsearch/watcher/license/LicenseTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/license/LicenseTests.java index 1c51760d619..62fc0c3cc5c 100644 --- a/watcher/src/test/java/org/elasticsearch/watcher/license/LicenseTests.java +++ b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/license/LicenseTests.java @@ -19,6 +19,7 @@ import java.util.List; import static org.hamcrest.Matchers.is; public class LicenseTests extends ESTestCase { + private SimpleLicenseeRegistry licenseeRegistry = new SimpleLicenseeRegistry(); public void testPlatinumGoldTrialLicenseCanDoEverything() throws Exception { diff --git a/watcher/src/test/java/org/elasticsearch/watcher/shield/BasicShieldTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/shield/BasicShieldTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/shield/BasicShieldTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/shield/BasicShieldTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/support/DynamicIndexNameIntegrationTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/DynamicIndexNameIntegrationTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/support/DynamicIndexNameIntegrationTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/DynamicIndexNameIntegrationTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/support/FilterXContentTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/FilterXContentTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/support/FilterXContentTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/FilterXContentTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/support/VariablesTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/VariablesTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/support/VariablesTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/VariablesTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/support/WatcherDateTimeUtilsTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/WatcherDateTimeUtilsTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/support/WatcherDateTimeUtilsTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/WatcherDateTimeUtilsTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/support/WatcherIndexTemplateRegistryTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/WatcherIndexTemplateRegistryTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/support/WatcherIndexTemplateRegistryTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/WatcherIndexTemplateRegistryTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/support/WatcherUtilsTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/WatcherUtilsTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/support/WatcherUtilsTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/WatcherUtilsTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/support/clock/ClockMock.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/clock/ClockMock.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/support/clock/ClockMock.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/clock/ClockMock.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/support/clock/ClockTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/clock/ClockTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/support/clock/ClockTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/clock/ClockTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/support/concurrent/FairKeyedLockTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/concurrent/FairKeyedLockTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/support/concurrent/FairKeyedLockTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/concurrent/FairKeyedLockTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/support/http/HttpClientTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/http/HttpClientTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/support/http/HttpClientTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/http/HttpClientTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/support/http/HttpConnectionTimeoutTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/http/HttpConnectionTimeoutTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/support/http/HttpConnectionTimeoutTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/http/HttpConnectionTimeoutTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/support/http/HttpReadTimeoutTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/http/HttpReadTimeoutTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/support/http/HttpReadTimeoutTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/http/HttpReadTimeoutTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/support/http/HttpRequestTemplateTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/http/HttpRequestTemplateTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/support/http/HttpRequestTemplateTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/http/HttpRequestTemplateTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/support/http/HttpResponseTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/http/HttpResponseTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/support/http/HttpResponseTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/http/HttpResponseTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/support/text/TextTemplateTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/text/TextTemplateTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/support/text/TextTemplateTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/text/TextTemplateTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/support/text/xmustache/XMustacheScriptEngineTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/text/xmustache/XMustacheScriptEngineTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/support/text/xmustache/XMustacheScriptEngineTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/text/xmustache/XMustacheScriptEngineTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/support/text/xmustache/XMustacheTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/text/xmustache/XMustacheTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/support/text/xmustache/XMustacheTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/text/xmustache/XMustacheTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/support/xcontent/MapPathTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/xcontent/MapPathTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/support/xcontent/MapPathTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/xcontent/MapPathTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/support/xcontent/XContentSourceTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/xcontent/XContentSourceTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/support/xcontent/XContentSourceTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/support/xcontent/XContentSourceTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/test/AbstractWatcherIntegrationTestCase.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/AbstractWatcherIntegrationTestCase.java similarity index 96% rename from watcher/src/test/java/org/elasticsearch/watcher/test/AbstractWatcherIntegrationTestCase.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/AbstractWatcherIntegrationTestCase.java index b7335c93086..0f938d7aca2 100644 --- a/watcher/src/test/java/org/elasticsearch/watcher/test/AbstractWatcherIntegrationTestCase.java +++ b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/AbstractWatcherIntegrationTestCase.java @@ -20,7 +20,6 @@ import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.common.xcontent.support.XContentMapValues; import org.elasticsearch.index.IndexModule; import org.elasticsearch.index.query.QueryBuilder; -import org.elasticsearch.license.plugin.LicensePlugin; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.builder.SearchSourceBuilder; @@ -34,7 +33,6 @@ import org.elasticsearch.test.ESIntegTestCase.ClusterScope; import org.elasticsearch.test.TestCluster; import org.elasticsearch.watcher.WatcherLifeCycleService; import org.elasticsearch.watcher.WatcherModule; -import org.elasticsearch.watcher.WatcherPlugin; import org.elasticsearch.watcher.WatcherService; import org.elasticsearch.watcher.WatcherState; import org.elasticsearch.watcher.actions.email.service.Authentication; @@ -55,6 +53,8 @@ import org.elasticsearch.watcher.trigger.ScheduleTriggerEngineMock; import org.elasticsearch.watcher.trigger.TriggerService; import org.elasticsearch.watcher.trigger.schedule.ScheduleModule; import org.elasticsearch.watcher.watch.Watch; +import org.elasticsearch.xpack.TimeWarpedXPackPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.hamcrest.Matcher; import org.jboss.netty.util.internal.SystemPropertyUtil; import org.junit.After; @@ -67,25 +67,14 @@ import java.io.OutputStream; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.concurrent.atomic.AtomicReference; import static org.elasticsearch.index.query.QueryBuilders.boolQuery; import static org.elasticsearch.index.query.QueryBuilders.matchQuery; import static org.elasticsearch.test.ESIntegTestCase.Scope.SUITE; -import static org.elasticsearch.watcher.WatcherModule.HISTORY_TEMPLATE_NAME; -import static org.elasticsearch.watcher.WatcherModule.TRIGGERED_TEMPLATE_NAME; -import static org.elasticsearch.watcher.WatcherModule.WATCHES_TEMPLATE_NAME; -import static org.hamcrest.Matchers.emptyArray; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.greaterThanOrEqualTo; -import static org.hamcrest.Matchers.notNullValue; +import static org.elasticsearch.watcher.WatcherModule.*; +import static org.hamcrest.Matchers.*; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; @@ -117,6 +106,10 @@ public abstract class AbstractWatcherIntegrationTestCase extends ESIntegTestCase logger.info("using schedule engine [" + scheduleImplName + "]"); return Settings.builder() .put(super.nodeSettings(nodeOrdinal)) + + //TODO: for now lets isolate watcher tests from marvel (randomize this later) + .put("marvel.enabled", false) + // we do this by default in core, but for watcher this isn't needed and only adds noise. .put("index.store.mock.check_index_on_close", false) .put("scroll.size", randomIntBetween(1, 100)) @@ -147,14 +140,10 @@ public abstract class AbstractWatcherIntegrationTestCase extends ESIntegTestCase protected List> pluginTypes() { List> types = new ArrayList<>(); if (timeWarped()) { - types.add(TimeWarpedWatcherPlugin.class); + types.add(TimeWarpedXPackPlugin.class); } else { - types.add(WatcherPlugin.class); + types.add(XPackPlugin.class); } - if (shieldEnabled) { - types.add(ShieldPlugin.class); - } - types.add(licensePluginClass()); return types; } @@ -189,10 +178,6 @@ public abstract class AbstractWatcherIntegrationTestCase extends ESIntegTestCase return randomBoolean(); } - protected Class licensePluginClass() { - return LicensePlugin.class; - } - protected boolean checkWatcherRunningOnlyOnce() { return true; } diff --git a/watcher/src/test/java/org/elasticsearch/watcher/test/TimeWarpedWatcherPlugin.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/TimeWarpedWatcherPlugin.java similarity index 95% rename from watcher/src/test/java/org/elasticsearch/watcher/test/TimeWarpedWatcherPlugin.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/TimeWarpedWatcherPlugin.java index c0ad25f6ec3..b2293fede05 100644 --- a/watcher/src/test/java/org/elasticsearch/watcher/test/TimeWarpedWatcherPlugin.java +++ b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/TimeWarpedWatcherPlugin.java @@ -8,7 +8,6 @@ package org.elasticsearch.watcher.test; import org.elasticsearch.common.inject.Module; import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.script.ScriptModule; import org.elasticsearch.watcher.WatcherPlugin; import org.elasticsearch.watcher.execution.ExecutionModule; import org.elasticsearch.watcher.execution.SyncTriggerListener; @@ -16,8 +15,6 @@ import org.elasticsearch.watcher.execution.WatchExecutor; import org.elasticsearch.watcher.support.clock.Clock; import org.elasticsearch.watcher.support.clock.ClockMock; import org.elasticsearch.watcher.support.clock.ClockModule; -import org.elasticsearch.watcher.support.init.proxy.ScriptServiceProxy; -import org.elasticsearch.watcher.test.bench.WatcherExecutorServiceBenchmark; import org.elasticsearch.watcher.trigger.ScheduleTriggerEngineMock; import org.elasticsearch.watcher.trigger.TriggerModule; import org.elasticsearch.watcher.trigger.manual.ManualTriggerEngine; diff --git a/watcher/src/test/java/org/elasticsearch/watcher/test/WatchExecutionContextMockBuilder.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/WatchExecutionContextMockBuilder.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/test/WatchExecutionContextMockBuilder.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/WatchExecutionContextMockBuilder.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/test/WatcherMatchers.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/WatcherMatchers.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/test/WatcherMatchers.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/WatcherMatchers.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/test/WatcherTestUtils.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/WatcherTestUtils.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/test/WatcherTestUtils.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/WatcherTestUtils.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/test/bench/ScheduleEngineTriggerBenchmark.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/bench/ScheduleEngineTriggerBenchmark.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/test/bench/ScheduleEngineTriggerBenchmark.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/bench/ScheduleEngineTriggerBenchmark.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/test/bench/WatcherExecutorServiceBenchmark.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/bench/WatcherExecutorServiceBenchmark.java similarity index 98% rename from watcher/src/test/java/org/elasticsearch/watcher/test/bench/WatcherExecutorServiceBenchmark.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/bench/WatcherExecutorServiceBenchmark.java index 842b498d3f8..dc9c3842d72 100644 --- a/watcher/src/test/java/org/elasticsearch/watcher/test/bench/WatcherExecutorServiceBenchmark.java +++ b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/bench/WatcherExecutorServiceBenchmark.java @@ -11,12 +11,13 @@ import org.elasticsearch.client.Client; import org.elasticsearch.common.inject.Module; import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.license.plugin.LicensePlugin; +import org.elasticsearch.watcher.WatcherPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.node.MockNode; import org.elasticsearch.node.Node; import org.elasticsearch.node.NodeBuilder; import org.elasticsearch.search.builder.SearchSourceBuilder; -import org.elasticsearch.watcher.WatcherPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.watcher.client.WatchSourceBuilder; import org.elasticsearch.watcher.client.WatcherClient; import org.elasticsearch.watcher.support.http.HttpRequestTemplate; @@ -58,7 +59,7 @@ public class WatcherExecutorServiceBenchmark { private static ScheduleTriggerEngineMock scheduler; protected static void start() throws Exception { - Node node = new MockNode(Settings.builder().put(SETTINGS).put("node.data", false).build(), Version.CURRENT, Arrays.asList(WatcherBenchmarkPlugin.class, LicensePlugin.class)); + Node node = new MockNode(Settings.builder().put(SETTINGS).put("node.data", false).build(), Version.CURRENT, Arrays.asList(WatcherBenchmarkPlugin.class, XPackPlugin.class)); client = node.client(); client.admin().cluster().prepareHealth("*").setWaitForGreenStatus().get(); Thread.sleep(5000); diff --git a/watcher/src/test/java/org/elasticsearch/watcher/test/bench/WatcherScheduleEngineBenchmark.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/bench/WatcherScheduleEngineBenchmark.java similarity index 99% rename from watcher/src/test/java/org/elasticsearch/watcher/test/bench/WatcherScheduleEngineBenchmark.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/bench/WatcherScheduleEngineBenchmark.java index f4c2c1bd8bb..cd50a14eace 100644 --- a/watcher/src/test/java/org/elasticsearch/watcher/test/bench/WatcherScheduleEngineBenchmark.java +++ b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/bench/WatcherScheduleEngineBenchmark.java @@ -19,7 +19,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.ByteSizeValue; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.index.query.QueryBuilders; -import org.elasticsearch.license.plugin.LicensePlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.monitor.jvm.JvmInfo; import org.elasticsearch.node.MockNode; import org.elasticsearch.node.Node; @@ -30,7 +30,7 @@ import org.elasticsearch.search.aggregations.bucket.terms.Terms; import org.elasticsearch.search.aggregations.metrics.percentiles.Percentiles; import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.threadpool.ThreadPoolStats; -import org.elasticsearch.watcher.WatcherPlugin; +import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.watcher.WatcherState; import org.elasticsearch.watcher.actions.ActionBuilders; import org.elasticsearch.watcher.actions.logging.LoggingLevel; @@ -137,7 +137,7 @@ public class WatcherScheduleEngineBenchmark { .put("watcher.trigger.schedule.engine", engine) .put("node.data", false) .build(); - try (Node node = new MockNode(settings, Version.CURRENT, Arrays.asList(WatcherPlugin.class, LicensePlugin.class))) { + try (Node node = new MockNode(settings, Version.CURRENT, Arrays.asList(XPackPlugin.class, XPackPlugin.class))) { try (final Client client = node.client()) { client.admin().cluster().prepareHealth().setWaitForNodes("2").get(); client.admin().indices().prepareDelete(HistoryStore.INDEX_PREFIX + "*").get(); diff --git a/watcher/src/test/java/org/elasticsearch/watcher/test/integration/BasicWatcherTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/integration/BasicWatcherTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/test/integration/BasicWatcherTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/integration/BasicWatcherTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/test/integration/BootStrapTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/integration/BootStrapTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/test/integration/BootStrapTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/integration/BootStrapTests.java diff --git a/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/integration/ExecutionVarsIntegrationTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/integration/ExecutionVarsIntegrationTests.java new file mode 100644 index 00000000000..404c1acc4bf --- /dev/null +++ b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/integration/ExecutionVarsIntegrationTests.java @@ -0,0 +1,168 @@ +/* + * 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.integration; + +import org.apache.lucene.util.LuceneTestCase.AwaitsFix; +import org.elasticsearch.action.search.SearchRequestBuilder; +import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.common.util.Callback; +import org.elasticsearch.watcher.client.WatcherClient; +import org.elasticsearch.watcher.support.xcontent.ObjectPath; +import org.elasticsearch.watcher.support.xcontent.XContentSource; +import org.elasticsearch.watcher.test.AbstractWatcherIntegrationTestCase; +import org.elasticsearch.watcher.transport.actions.execute.ExecuteWatchResponse; +import org.elasticsearch.watcher.transport.actions.put.PutWatchResponse; + +import java.util.List; +import java.util.Map; + +import static org.elasticsearch.watcher.actions.ActionBuilders.loggingAction; +import static org.elasticsearch.watcher.client.WatchSourceBuilders.watchBuilder; +import static org.elasticsearch.watcher.condition.ConditionBuilders.scriptCondition; +import static org.elasticsearch.watcher.input.InputBuilders.simpleInput; +import static org.elasticsearch.watcher.transform.TransformBuilders.scriptTransform; +import static org.elasticsearch.watcher.trigger.TriggerBuilders.schedule; +import static org.elasticsearch.watcher.trigger.schedule.Schedules.cron; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +/** + */ +@AwaitsFix(bugUrl = "https://github.com/elastic/x-plugins/issues/724") +public class ExecutionVarsIntegrationTests extends AbstractWatcherIntegrationTestCase { + @Override + protected boolean timeWarped() { + return true; + } + + public void testVars() throws Exception { + WatcherClient watcherClient = watcherClient(); + + PutWatchResponse putWatchResponse = watcherClient.preparePutWatch("_id").setSource(watchBuilder() + .trigger(schedule(cron("0/1 * * * * ?"))) + .input(simpleInput("value", 5)) + .condition(scriptCondition("ctx.vars.condition_value = ctx.payload.value + 5; return ctx.vars.condition_value > 5;")) + .transform(scriptTransform("ctx.vars.watch_transform_value = ctx.vars.condition_value + 5; return ctx.payload;")) + .addAction( + "a1", + scriptTransform("ctx.vars.a1_transform_value = ctx.vars.watch_transform_value + 10; return ctx.payload;"), + loggingAction("condition_value={{ctx.vars.condition_value}}, watch_transform_value={{ctx.vars.watch_transform_value}}, a1_transform_value={{ctx.vars.a1_transform_value}}")) + .addAction( + "a2", + scriptTransform("ctx.vars.a2_transform_value = ctx.vars.watch_transform_value + 20; return ctx.payload;"), + loggingAction("condition_value={{ctx.vars.condition_value}}, watch_transform_value={{ctx.vars.watch_transform_value}}, a2_transform_value={{ctx.vars.a2_transform_value}}"))) + .get(); + + assertThat(putWatchResponse.isCreated(), is(true)); + + timeWarp().scheduler().trigger("_id"); + + flush(); + refresh(); + + SearchResponse searchResponse = searchWatchRecords(new Callback() { + @Override + public void handle(SearchRequestBuilder builder) { + // defaults to match all; + } + }); + + assertThat(searchResponse.getHits().getTotalHits(), is(1L)); + + Map source = searchResponse.getHits().getAt(0).getSource(); + + assertValue(source, "watch_id", is("_id")); + assertValue(source, "state", is("executed")); + + // we don't store the computed vars in history + assertValue(source, "vars", nullValue()); + + assertValue(source, "result.condition.status", is("success")); + assertValue(source, "result.transform.status", is("success")); + + List> actions = ObjectPath.eval("result.actions", source); + for (Map action : actions) { + String id = (String) action.get("id"); + switch (id) { + case "a1": + assertValue(action, "status", is("success")); + assertValue(action, "transform.status", is("success")); + assertValue(action, "logging.logged_text", is("condition_value=10, watch_transform_value=15, a1_transform_value=25")); + break; + case "a2": + assertValue(action, "status", is("success")); + assertValue(action, "transform.status", is("success")); + assertValue(action, "logging.logged_text", is("condition_value=10, watch_transform_value=15, a2_transform_value=35")); + break; + default: + fail("there should not be an action result for action with an id other than a1 or a2"); + } + } + } + + public void testVarsManual() throws Exception { + WatcherClient watcherClient = watcherClient(); + + PutWatchResponse putWatchResponse = watcherClient.preparePutWatch("_id").setSource(watchBuilder() + .trigger(schedule(cron("0/1 * * * * ? 2020"))) + .input(simpleInput("value", 5)) + .condition(scriptCondition("ctx.vars.condition_value = ctx.payload.value + 5; return ctx.vars.condition_value > 5;")) + .transform(scriptTransform("ctx.vars.watch_transform_value = ctx.vars.condition_value + 5; return ctx.payload;")) + .addAction( + "a1", + scriptTransform("ctx.vars.a1_transform_value = ctx.vars.watch_transform_value + 10; return ctx.payload;"), + loggingAction("condition_value={{ctx.vars.condition_value}}, watch_transform_value={{ctx.vars.watch_transform_value}}, a1_transform_value={{ctx.vars.a1_transform_value}}")) + .addAction( + "a2", + scriptTransform("ctx.vars.a2_transform_value = ctx.vars.watch_transform_value + 20; return ctx.payload;"), + loggingAction("condition_value={{ctx.vars.condition_value}}, watch_transform_value={{ctx.vars.watch_transform_value}}, a2_transform_value={{ctx.vars.a2_transform_value}}"))) + .get(); + + assertThat(putWatchResponse.isCreated(), is(true)); + + boolean debug = randomBoolean(); + + ExecuteWatchResponse executeWatchResponse = watcherClient + .prepareExecuteWatch("_id") + .setDebug(debug) + .get(); + assertThat(executeWatchResponse.getRecordId(), notNullValue()); + XContentSource source = executeWatchResponse.getRecordSource(); + + assertValue(source, "watch_id", is("_id")); + assertValue(source, "state", is("executed")); + + if (debug) { + assertValue(source, "vars.condition_value", is(10)); + assertValue(source, "vars.watch_transform_value", is(15)); + assertValue(source, "vars.a1_transform_value", is(25)); + assertValue(source, "vars.a2_transform_value", is(35)); + } + + assertValue(source, "result.condition.status", is("success")); + assertValue(source, "result.transform.status", is("success")); + + List> actions = source.getValue("result.actions"); + for (Map action : actions) { + String id = (String) action.get("id"); + switch (id) { + case "a1": + assertValue(action, "status", is("success")); + assertValue(action, "transform.status", is("success")); + assertValue(action, "logging.logged_text", is("condition_value=10, watch_transform_value=15, a1_transform_value=25")); + break; + case "a2": + assertValue(action, "status", is("success")); + assertValue(action, "transform.status", is("success")); + assertValue(action, "logging.logged_text", is("condition_value=10, watch_transform_value=15, a2_transform_value=35")); + break; + default: + fail("there should not be an action result for action with an id other than a1 or a2"); + } + } + } +} diff --git a/watcher/src/test/java/org/elasticsearch/watcher/test/integration/HttpSecretsIntegrationTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/integration/HttpSecretsIntegrationTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/test/integration/HttpSecretsIntegrationTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/integration/HttpSecretsIntegrationTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/test/integration/NoMasterNodeTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/integration/NoMasterNodeTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/test/integration/NoMasterNodeTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/integration/NoMasterNodeTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/test/integration/WatchMetadataTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/integration/WatchMetadataTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/test/integration/WatchMetadataTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/integration/WatchMetadataTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/test/integration/WatcherSettingsFilterTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/integration/WatcherSettingsFilterTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/test/integration/WatcherSettingsFilterTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/test/integration/WatcherSettingsFilterTests.java diff --git a/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/transform/TransformIntegrationTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/transform/TransformIntegrationTests.java new file mode 100644 index 00000000000..f6be9b031da --- /dev/null +++ b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/transform/TransformIntegrationTests.java @@ -0,0 +1,215 @@ +/* + * 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.transform; + +import org.apache.lucene.util.LuceneTestCase.AwaitsFix; +import org.elasticsearch.action.search.SearchRequest; +import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.common.collect.MapBuilder; +import org.elasticsearch.common.io.Streams; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.watcher.support.Script; +import org.elasticsearch.watcher.test.AbstractWatcherIntegrationTestCase; +import org.elasticsearch.watcher.test.WatcherTestUtils; +import org.elasticsearch.watcher.transport.actions.put.PutWatchResponse; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; + +import static org.elasticsearch.common.settings.Settings.settingsBuilder; +import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery; +import static org.elasticsearch.search.builder.SearchSourceBuilder.searchSource; +import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures; +import static org.elasticsearch.watcher.actions.ActionBuilders.indexAction; +import static org.elasticsearch.watcher.client.WatchSourceBuilders.watchBuilder; +import static org.elasticsearch.watcher.condition.ConditionBuilders.alwaysCondition; +import static org.elasticsearch.watcher.input.InputBuilders.searchInput; +import static org.elasticsearch.watcher.input.InputBuilders.simpleInput; +import static org.elasticsearch.watcher.transform.TransformBuilders.chainTransform; +import static org.elasticsearch.watcher.transform.TransformBuilders.scriptTransform; +import static org.elasticsearch.watcher.transform.TransformBuilders.searchTransform; +import static org.elasticsearch.watcher.trigger.TriggerBuilders.schedule; +import static org.elasticsearch.watcher.trigger.schedule.Schedules.interval; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.greaterThanOrEqualTo; +import static org.hamcrest.Matchers.is; + +/** + */ +@AwaitsFix(bugUrl = "https://github.com/elastic/x-plugins/issues/724") +public class TransformIntegrationTests extends AbstractWatcherIntegrationTestCase { + @Override + public Settings nodeSettings(int nodeOrdinal) { + Path configDir = createTempDir(); + Path scripts = configDir.resolve("scripts"); + try { + Files.createDirectories(scripts); + try (InputStream stream = TransformIntegrationTests.class.getResourceAsStream("/config/scripts/my-script.groovy"); + OutputStream output = Files.newOutputStream(scripts.resolve("my-script.groovy"))) { + Streams.copy(stream, output); + } + } catch (IOException ex) { + throw new RuntimeException(ex); + } + //Set path so ScriptService will pick up the test scripts + return settingsBuilder().put(super.nodeSettings(nodeOrdinal)).put("path.conf", configDir.toString()).build(); + } + + public void testScriptTransform() throws Exception { + final Script script; + if (randomBoolean()) { + logger.info("testing script transform with an inline script"); + script = Script.inline("return [key3 : ctx.payload.key1 + ctx.payload.key2]").lang("groovy").build(); + } else if (randomBoolean()) { + logger.info("testing script transform with an indexed script"); + client().preparePutIndexedScript("groovy", "_id", "{\"script\" : \"return [key3 : ctx.payload.key1 + ctx.payload.key2]\"}").get(); + script = Script.indexed("_id").lang("groovy").build(); + } else { + logger.info("testing script transform with a file script"); + script = Script.file("my-script").lang("groovy").build(); + } + + // put a watch that has watch level transform: + PutWatchResponse putWatchResponse = watcherClient().preparePutWatch("_id1") + .setSource(watchBuilder() + .trigger(schedule(interval("5s"))) + .input(simpleInput(MapBuilder.newMapBuilder().put("key1", 10).put("key2", 10))) + .condition(alwaysCondition()) + .transform(scriptTransform(script)) + .addAction("_id", indexAction("output1", "type"))) + .get(); + assertThat(putWatchResponse.isCreated(), is(true)); + // put a watch that has a action level transform: + putWatchResponse = watcherClient().preparePutWatch("_id2") + .setSource(watchBuilder() + .trigger(schedule(interval("5s"))) + .input(simpleInput(MapBuilder.newMapBuilder().put("key1", 10).put("key2", 10))) + .condition(alwaysCondition()) + .addAction("_id", scriptTransform(script), indexAction("output2", "type"))) + .get(); + assertThat(putWatchResponse.isCreated(), is(true)); + + if (timeWarped()) { + timeWarp().scheduler().trigger("_id1"); + timeWarp().scheduler().trigger("_id2"); + refresh(); + } + + assertWatchWithMinimumPerformedActionsCount("_id1", 1, false); + assertWatchWithMinimumPerformedActionsCount("_id2", 1, false); + refresh(); + + SearchResponse response = client().prepareSearch("output1").get(); + assertNoFailures(response); + assertThat(response.getHits().getTotalHits(), greaterThanOrEqualTo(1l)); + assertThat(response.getHits().getAt(0).sourceAsMap().size(), equalTo(1)); + assertThat(response.getHits().getAt(0).sourceAsMap().get("key3").toString(), equalTo("20")); + + response = client().prepareSearch("output2").get(); + assertNoFailures(response); + assertThat(response.getHits().getTotalHits(), greaterThanOrEqualTo(1l)); + assertThat(response.getHits().getAt(0).sourceAsMap().size(), equalTo(1)); + assertThat(response.getHits().getAt(0).sourceAsMap().get("key3").toString(), equalTo("20")); + } + + public void testSearchTransform() throws Exception { + createIndex("my-condition-index", "my-payload-index"); + ensureGreen("my-condition-index", "my-payload-index"); + + index("my-payload-index", "payload", "mytestresult"); + refresh(); + + SearchRequest inputRequest = WatcherTestUtils.newInputSearchRequest("my-condition-index").source(searchSource().query(matchAllQuery())); + SearchRequest transformRequest = WatcherTestUtils.newInputSearchRequest("my-payload-index").source(searchSource().query(matchAllQuery())); + + PutWatchResponse putWatchResponse = watcherClient().preparePutWatch("_id1") + .setSource(watchBuilder() + .trigger(schedule(interval("5s"))) + .input(searchInput(inputRequest)) + .transform(searchTransform(transformRequest)) + .addAction("_id", indexAction("output1", "result")) + ).get(); + assertThat(putWatchResponse.isCreated(), is(true)); + putWatchResponse = watcherClient().preparePutWatch("_id2") + .setSource(watchBuilder() + .trigger(schedule(interval("5s"))) + .input(searchInput(inputRequest)) + .addAction("_id", searchTransform(transformRequest), indexAction("output2", "result")) + ).get(); + assertThat(putWatchResponse.isCreated(), is(true)); + + if (timeWarped()) { + timeWarp().scheduler().trigger("_id1"); + timeWarp().scheduler().trigger("_id2"); + refresh(); + } + + assertWatchWithMinimumPerformedActionsCount("_id1", 1, false); + assertWatchWithMinimumPerformedActionsCount("_id2", 1, false); + refresh(); + + SearchResponse response = client().prepareSearch("output1").get(); + assertNoFailures(response); + assertThat(response.getHits().getTotalHits(), greaterThanOrEqualTo(1l)); + assertThat(response.getHits().getAt(0).sourceAsString(), containsString("mytestresult")); + + response = client().prepareSearch("output2").get(); + assertNoFailures(response); + assertThat(response.getHits().getTotalHits(), greaterThanOrEqualTo(1l)); + assertThat(response.getHits().getAt(0).sourceAsString(), containsString("mytestresult")); + } + + public void testChainTransform() throws Exception { + final Script script1 = Script.inline("return [key3 : ctx.payload.key1 + ctx.payload.key2]").lang("groovy").build(); + final Script script2 = Script.inline("return [key4 : ctx.payload.key3 + 10]").lang("groovy").build(); + // put a watch that has watch level transform: + PutWatchResponse putWatchResponse = watcherClient().preparePutWatch("_id1") + .setSource(watchBuilder() + .trigger(schedule(interval("5s"))) + .input(simpleInput(MapBuilder.newMapBuilder().put("key1", 10).put("key2", 10))) + .condition(alwaysCondition()) + .transform(chainTransform(scriptTransform(script1), scriptTransform(script2))) + .addAction("_id", indexAction("output1", "type"))) + .get(); + assertThat(putWatchResponse.isCreated(), is(true)); + // put a watch that has a action level transform: + putWatchResponse = watcherClient().preparePutWatch("_id2") + .setSource(watchBuilder() + .trigger(schedule(interval("5s"))) + .input(simpleInput(MapBuilder.newMapBuilder().put("key1", 10).put("key2", 10))) + .condition(alwaysCondition()) + .addAction("_id", chainTransform(scriptTransform(script1), scriptTransform(script2)), indexAction("output2", "type"))) + .get(); + assertThat(putWatchResponse.isCreated(), is(true)); + + if (timeWarped()) { + timeWarp().scheduler().trigger("_id1"); + timeWarp().scheduler().trigger("_id2"); + refresh(); + } + + assertWatchWithMinimumPerformedActionsCount("_id1", 1, false); + assertWatchWithMinimumPerformedActionsCount("_id2", 1, false); + refresh(); + + SearchResponse response = client().prepareSearch("output1").get(); + assertNoFailures(response); + assertThat(response.getHits().getTotalHits(), greaterThanOrEqualTo(1l)); + assertThat(response.getHits().getAt(0).sourceAsMap().size(), equalTo(1)); + assertThat(response.getHits().getAt(0).sourceAsMap().get("key4").toString(), equalTo("30")); + + response = client().prepareSearch("output2").get(); + assertNoFailures(response); + assertThat(response.getHits().getTotalHits(), greaterThanOrEqualTo(1l)); + assertThat(response.getHits().getAt(0).sourceAsMap().size(), equalTo(1)); + assertThat(response.getHits().getAt(0).sourceAsMap().get("key4").toString(), equalTo("30")); + } + +} diff --git a/watcher/src/test/java/org/elasticsearch/watcher/transform/chain/ChainTransformTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/transform/chain/ChainTransformTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/transform/chain/ChainTransformTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/transform/chain/ChainTransformTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/transform/script/ScriptTransformTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/transform/script/ScriptTransformTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/transform/script/ScriptTransformTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/transform/script/ScriptTransformTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/transform/search/SearchTransformTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/transform/search/SearchTransformTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/transform/search/SearchTransformTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/transform/search/SearchTransformTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/transport/action/ack/WatchAckTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/transport/action/ack/WatchAckTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/transport/action/ack/WatchAckTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/transport/action/ack/WatchAckTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/transport/action/activate/ActivateWatchTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/transport/action/activate/ActivateWatchTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/transport/action/activate/ActivateWatchTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/transport/action/activate/ActivateWatchTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/transport/action/delete/DeleteWatchTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/transport/action/delete/DeleteWatchTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/transport/action/delete/DeleteWatchTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/transport/action/delete/DeleteWatchTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/transport/action/delete/ForceDeleteWatchTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/transport/action/delete/ForceDeleteWatchTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/transport/action/delete/ForceDeleteWatchTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/transport/action/delete/ForceDeleteWatchTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/transport/action/execute/ExecuteWatchTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/transport/action/execute/ExecuteWatchTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/transport/action/execute/ExecuteWatchTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/transport/action/execute/ExecuteWatchTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/transport/action/execute/ExecuteWatchWithDateMathTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/transport/action/execute/ExecuteWatchWithDateMathTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/transport/action/execute/ExecuteWatchWithDateMathTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/transport/action/execute/ExecuteWatchWithDateMathTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/transport/action/get/GetWatchTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/transport/action/get/GetWatchTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/transport/action/get/GetWatchTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/transport/action/get/GetWatchTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/transport/action/put/PutWatchTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/transport/action/put/PutWatchTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/transport/action/put/PutWatchTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/transport/action/put/PutWatchTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/transport/action/stats/SlowWatchStatsTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/transport/action/stats/SlowWatchStatsTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/transport/action/stats/SlowWatchStatsTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/transport/action/stats/SlowWatchStatsTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/transport/action/stats/WatcherStatsTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/transport/action/stats/WatcherStatsTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/transport/action/stats/WatcherStatsTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/transport/action/stats/WatcherStatsTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/trigger/ScheduleTriggerEngineMock.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/ScheduleTriggerEngineMock.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/trigger/ScheduleTriggerEngineMock.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/ScheduleTriggerEngineMock.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/CronScheduleTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/CronScheduleTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/CronScheduleTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/CronScheduleTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/DailyScheduleTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/DailyScheduleTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/DailyScheduleTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/DailyScheduleTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/HourlyScheduleTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/HourlyScheduleTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/HourlyScheduleTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/HourlyScheduleTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/IntervalScheduleTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/IntervalScheduleTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/IntervalScheduleTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/IntervalScheduleTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/MonthlyScheduleTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/MonthlyScheduleTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/MonthlyScheduleTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/MonthlyScheduleTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/ScheduleRegistryTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/ScheduleRegistryTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/ScheduleRegistryTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/ScheduleRegistryTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/ScheduleTestCase.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/ScheduleTestCase.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/ScheduleTestCase.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/ScheduleTestCase.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/ScheduleTriggerEventTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/ScheduleTriggerEventTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/ScheduleTriggerEventTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/ScheduleTriggerEventTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/WeeklyScheduleTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/WeeklyScheduleTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/WeeklyScheduleTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/WeeklyScheduleTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/YearlyScheduleTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/YearlyScheduleTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/YearlyScheduleTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/YearlyScheduleTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/engine/BaseTriggerEngineTestCase.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/engine/BaseTriggerEngineTestCase.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/engine/BaseTriggerEngineTestCase.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/engine/BaseTriggerEngineTestCase.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/engine/SchedulerScheduleEngineTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/engine/SchedulerScheduleEngineTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/engine/SchedulerScheduleEngineTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/engine/SchedulerScheduleEngineTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/engine/TickerScheduleEngineTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/engine/TickerScheduleEngineTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/engine/TickerScheduleEngineTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/engine/TickerScheduleEngineTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/tool/CronEvalToolTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/tool/CronEvalToolTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/tool/CronEvalToolTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/tool/CronEvalToolTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/tool/EvalCron.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/tool/EvalCron.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/tool/EvalCron.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/trigger/schedule/tool/EvalCron.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/watch/WatchLockServiceTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/watch/WatchLockServiceTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/watch/WatchLockServiceTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/watch/WatchLockServiceTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/watch/WatchStoreTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/watch/WatchStoreTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/watch/WatchStoreTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/watch/WatchStoreTests.java diff --git a/watcher/src/test/java/org/elasticsearch/watcher/watch/WatchTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/watch/WatchTests.java similarity index 100% rename from watcher/src/test/java/org/elasticsearch/watcher/watch/WatchTests.java rename to elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/watch/WatchTests.java diff --git a/watcher/src/test/resources/config/scripts/my-script.groovy b/elasticsearch/x-pack/watcher/src/test/resources/config/scripts/my-script.groovy similarity index 100% rename from watcher/src/test/resources/config/scripts/my-script.groovy rename to elasticsearch/x-pack/watcher/src/test/resources/config/scripts/my-script.groovy diff --git a/watcher/src/test/resources/org/elasticsearch/shield/keystore/testnode-different-passwords.jks b/elasticsearch/x-pack/watcher/src/test/resources/org/elasticsearch/shield/keystore/testnode-different-passwords.jks similarity index 100% rename from watcher/src/test/resources/org/elasticsearch/shield/keystore/testnode-different-passwords.jks rename to elasticsearch/x-pack/watcher/src/test/resources/org/elasticsearch/shield/keystore/testnode-different-passwords.jks diff --git a/watcher/src/test/resources/org/elasticsearch/shield/keystore/testnode.cert b/elasticsearch/x-pack/watcher/src/test/resources/org/elasticsearch/shield/keystore/testnode.cert similarity index 100% rename from watcher/src/test/resources/org/elasticsearch/shield/keystore/testnode.cert rename to elasticsearch/x-pack/watcher/src/test/resources/org/elasticsearch/shield/keystore/testnode.cert diff --git a/watcher/src/test/resources/org/elasticsearch/shield/keystore/testnode.jks b/elasticsearch/x-pack/watcher/src/test/resources/org/elasticsearch/shield/keystore/testnode.jks similarity index 100% rename from watcher/src/test/resources/org/elasticsearch/shield/keystore/testnode.jks rename to elasticsearch/x-pack/watcher/src/test/resources/org/elasticsearch/shield/keystore/testnode.jks diff --git a/watcher/src/test/resources/org/elasticsearch/shield/keystore/truststore-testnode-only.jks b/elasticsearch/x-pack/watcher/src/test/resources/org/elasticsearch/shield/keystore/truststore-testnode-only.jks similarity index 100% rename from watcher/src/test/resources/org/elasticsearch/shield/keystore/truststore-testnode-only.jks rename to elasticsearch/x-pack/watcher/src/test/resources/org/elasticsearch/shield/keystore/truststore-testnode-only.jks diff --git a/watcher/src/test/resources/org/elasticsearch/watcher/actions/email/service/logo.png b/elasticsearch/x-pack/watcher/src/test/resources/org/elasticsearch/watcher/actions/email/service/logo.png similarity index 100% rename from watcher/src/test/resources/org/elasticsearch/watcher/actions/email/service/logo.png rename to elasticsearch/x-pack/watcher/src/test/resources/org/elasticsearch/watcher/actions/email/service/logo.png diff --git a/watcher/src/test/resources/org/elasticsearch/watcher/input/search/config/scripts/test_disk_template.mustache b/elasticsearch/x-pack/watcher/src/test/resources/org/elasticsearch/watcher/input/search/config/scripts/test_disk_template.mustache similarity index 100% rename from watcher/src/test/resources/org/elasticsearch/watcher/input/search/config/scripts/test_disk_template.mustache rename to elasticsearch/x-pack/watcher/src/test/resources/org/elasticsearch/watcher/input/search/config/scripts/test_disk_template.mustache diff --git a/watcher/src/test/resources/org/elasticsearch/watcher/transform/search/config/scripts/test_disk_template.mustache b/elasticsearch/x-pack/watcher/src/test/resources/org/elasticsearch/watcher/transform/search/config/scripts/test_disk_template.mustache similarity index 100% rename from watcher/src/test/resources/org/elasticsearch/watcher/transform/search/config/scripts/test_disk_template.mustache rename to elasticsearch/x-pack/watcher/src/test/resources/org/elasticsearch/watcher/transform/search/config/scripts/test_disk_template.mustache diff --git a/watcher/src/test/resources/rest-api-spec/api/watcher.ack_watch.json b/elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/api/watcher.ack_watch.json similarity index 100% rename from watcher/src/test/resources/rest-api-spec/api/watcher.ack_watch.json rename to elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/api/watcher.ack_watch.json diff --git a/watcher/src/test/resources/rest-api-spec/api/watcher.activate_watch.json b/elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/api/watcher.activate_watch.json similarity index 100% rename from watcher/src/test/resources/rest-api-spec/api/watcher.activate_watch.json rename to elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/api/watcher.activate_watch.json diff --git a/watcher/src/test/resources/rest-api-spec/api/watcher.deactivate_watch.json b/elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/api/watcher.deactivate_watch.json similarity index 100% rename from watcher/src/test/resources/rest-api-spec/api/watcher.deactivate_watch.json rename to elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/api/watcher.deactivate_watch.json diff --git a/watcher/src/test/resources/rest-api-spec/api/watcher.delete_watch.json b/elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/api/watcher.delete_watch.json similarity index 100% rename from watcher/src/test/resources/rest-api-spec/api/watcher.delete_watch.json rename to elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/api/watcher.delete_watch.json diff --git a/watcher/src/test/resources/rest-api-spec/api/watcher.execute_watch.json b/elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/api/watcher.execute_watch.json similarity index 100% rename from watcher/src/test/resources/rest-api-spec/api/watcher.execute_watch.json rename to elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/api/watcher.execute_watch.json diff --git a/watcher/src/test/resources/rest-api-spec/api/watcher.get_watch.json b/elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/api/watcher.get_watch.json similarity index 100% rename from watcher/src/test/resources/rest-api-spec/api/watcher.get_watch.json rename to elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/api/watcher.get_watch.json diff --git a/watcher/src/test/resources/rest-api-spec/api/watcher.info.json b/elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/api/watcher.info.json similarity index 100% rename from watcher/src/test/resources/rest-api-spec/api/watcher.info.json rename to elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/api/watcher.info.json diff --git a/watcher/src/test/resources/rest-api-spec/api/watcher.put_watch.json b/elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/api/watcher.put_watch.json similarity index 100% rename from watcher/src/test/resources/rest-api-spec/api/watcher.put_watch.json rename to elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/api/watcher.put_watch.json diff --git a/watcher/src/test/resources/rest-api-spec/api/watcher.restart.json b/elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/api/watcher.restart.json similarity index 100% rename from watcher/src/test/resources/rest-api-spec/api/watcher.restart.json rename to elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/api/watcher.restart.json diff --git a/watcher/src/test/resources/rest-api-spec/api/watcher.start.json b/elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/api/watcher.start.json similarity index 100% rename from watcher/src/test/resources/rest-api-spec/api/watcher.start.json rename to elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/api/watcher.start.json diff --git a/watcher/src/test/resources/rest-api-spec/api/watcher.stats.json b/elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/api/watcher.stats.json similarity index 100% rename from watcher/src/test/resources/rest-api-spec/api/watcher.stats.json rename to elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/api/watcher.stats.json diff --git a/watcher/src/test/resources/rest-api-spec/api/watcher.stop.json b/elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/api/watcher.stop.json similarity index 100% rename from watcher/src/test/resources/rest-api-spec/api/watcher.stop.json rename to elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/api/watcher.stop.json diff --git a/watcher/src/test/resources/rest-api-spec/test/ack_watch/10_basic.yaml b/elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/ack_watch/10_basic.yaml similarity index 100% rename from watcher/src/test/resources/rest-api-spec/test/ack_watch/10_basic.yaml rename to elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/ack_watch/10_basic.yaml diff --git a/watcher/src/test/resources/rest-api-spec/test/ack_watch/20_ack_individual_action.yaml b/elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/ack_watch/20_ack_individual_action.yaml similarity index 100% rename from watcher/src/test/resources/rest-api-spec/test/ack_watch/20_ack_individual_action.yaml rename to elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/ack_watch/20_ack_individual_action.yaml diff --git a/watcher/src/test/resources/rest-api-spec/test/activate_watch/10_basic.yaml b/elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/activate_watch/10_basic.yaml similarity index 100% rename from watcher/src/test/resources/rest-api-spec/test/activate_watch/10_basic.yaml rename to elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/activate_watch/10_basic.yaml diff --git a/watcher/src/test/resources/rest-api-spec/test/array_compare_watch/10_basic.yaml b/elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/array_compare_watch/10_basic.yaml similarity index 100% rename from watcher/src/test/resources/rest-api-spec/test/array_compare_watch/10_basic.yaml rename to elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/array_compare_watch/10_basic.yaml diff --git a/watcher/src/test/resources/rest-api-spec/test/delete_watch/10_basic.yaml b/elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/delete_watch/10_basic.yaml similarity index 100% rename from watcher/src/test/resources/rest-api-spec/test/delete_watch/10_basic.yaml rename to elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/delete_watch/10_basic.yaml diff --git a/watcher/src/test/resources/rest-api-spec/test/get_watch/10_basic.yaml b/elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/get_watch/10_basic.yaml similarity index 100% rename from watcher/src/test/resources/rest-api-spec/test/get_watch/10_basic.yaml rename to elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/get_watch/10_basic.yaml diff --git a/watcher/src/test/resources/rest-api-spec/test/get_watch/20_missing.yaml b/elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/get_watch/20_missing.yaml similarity index 100% rename from watcher/src/test/resources/rest-api-spec/test/get_watch/20_missing.yaml rename to elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/get_watch/20_missing.yaml diff --git a/watcher/src/test/resources/rest-api-spec/test/getting_started/10_monitor_cluster_health.yaml b/elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/getting_started/10_monitor_cluster_health.yaml similarity index 100% rename from watcher/src/test/resources/rest-api-spec/test/getting_started/10_monitor_cluster_health.yaml rename to elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/getting_started/10_monitor_cluster_health.yaml diff --git a/watcher/src/test/resources/rest-api-spec/test/hijack/10_basic.yaml b/elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/hijack/10_basic.yaml similarity index 100% rename from watcher/src/test/resources/rest-api-spec/test/hijack/10_basic.yaml rename to elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/hijack/10_basic.yaml diff --git a/watcher/src/test/resources/rest-api-spec/test/put_watch/10_basic.yaml b/elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/put_watch/10_basic.yaml similarity index 100% rename from watcher/src/test/resources/rest-api-spec/test/put_watch/10_basic.yaml rename to elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/put_watch/10_basic.yaml diff --git a/watcher/src/test/resources/rest-api-spec/test/put_watch/20_put_watch_with_throttle_period.yaml b/elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/put_watch/20_put_watch_with_throttle_period.yaml similarity index 100% rename from watcher/src/test/resources/rest-api-spec/test/put_watch/20_put_watch_with_throttle_period.yaml rename to elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/put_watch/20_put_watch_with_throttle_period.yaml diff --git a/watcher/src/test/resources/rest-api-spec/test/put_watch/30_put_watch_with_action_throttle_period.yaml b/elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/put_watch/30_put_watch_with_action_throttle_period.yaml similarity index 100% rename from watcher/src/test/resources/rest-api-spec/test/put_watch/30_put_watch_with_action_throttle_period.yaml rename to elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/put_watch/30_put_watch_with_action_throttle_period.yaml diff --git a/watcher/src/test/resources/rest-api-spec/test/put_watch/40_put_watch_as_inactive.yaml b/elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/put_watch/40_put_watch_as_inactive.yaml similarity index 100% rename from watcher/src/test/resources/rest-api-spec/test/put_watch/40_put_watch_as_inactive.yaml rename to elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/put_watch/40_put_watch_as_inactive.yaml diff --git a/watcher/src/test/resources/rest-api-spec/test/restart_watcher/10_basic.yaml b/elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/restart_watcher/10_basic.yaml similarity index 100% rename from watcher/src/test/resources/rest-api-spec/test/restart_watcher/10_basic.yaml rename to elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/restart_watcher/10_basic.yaml diff --git a/watcher/src/test/resources/rest-api-spec/test/start_watcher/10_basic.yaml b/elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/start_watcher/10_basic.yaml similarity index 100% rename from watcher/src/test/resources/rest-api-spec/test/start_watcher/10_basic.yaml rename to elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/start_watcher/10_basic.yaml diff --git a/watcher/src/test/resources/rest-api-spec/test/stats/10_basic.yaml b/elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/stats/10_basic.yaml similarity index 100% rename from watcher/src/test/resources/rest-api-spec/test/stats/10_basic.yaml rename to elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/stats/10_basic.yaml diff --git a/watcher/src/test/resources/rest-api-spec/test/stop_watcher/10_basic.yaml b/elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/stop_watcher/10_basic.yaml similarity index 100% rename from watcher/src/test/resources/rest-api-spec/test/stop_watcher/10_basic.yaml rename to elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/stop_watcher/10_basic.yaml diff --git a/watcher/src/test/resources/rest-api-spec/test/watch_info/10_basic.yaml b/elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/watch_info/10_basic.yaml similarity index 100% rename from watcher/src/test/resources/rest-api-spec/test/watch_info/10_basic.yaml rename to elasticsearch/x-pack/watcher/src/test/resources/rest-api-spec/test/watcher/watch_info/10_basic.yaml diff --git a/marvel/build.gradle b/marvel/build.gradle deleted file mode 100644 index a58367779e3..00000000000 --- a/marvel/build.gradle +++ /dev/null @@ -1,59 +0,0 @@ -import org.elasticsearch.gradle.MavenFilteringHack - -apply plugin: 'elasticsearch.esplugin' -esplugin { - name 'marvel-agent' - description 'Elasticsearch Marvel' - classname 'org.elasticsearch.marvel.MarvelPlugin' - isolated false -} - -ext.versions = [ - okhttp: '2.3.0' -] - -dependencies { - provided project(path: ':x-plugins:license:plugin', configuration: 'runtime') - provided project(path: ':x-plugins:shield', configuration: 'runtime') - testCompile 'org.elasticsearch:securemock:1.1' - - // mock web server - testCompile "com.squareup.okhttp:mockwebserver:${versions.okhttp}" - testCompile "com.squareup.okhttp:okhttp:${versions.okhttp}" - testCompile "com.squareup.okhttp:okhttp-ws:${versions.okhttp}" - testCompile 'com.squareup.okio:okio:1.3.0' - testCompile 'org.bouncycastle:bcprov-jdk15on:1.50' -} - -compileJava.options.compilerArgs << '-Xlint:-rawtypes,-unchecked' -compileTestJava.options.compilerArgs << '-Xlint:-rawtypes,-unchecked' - -ext.expansions = [ - 'project.version': version, - 'integ.http.port': integTest.cluster.baseHttpPort -] - -processResources { - inputs.properties(expansions) - MavenFilteringHack.filter(it, expansions) -} - -processTestResources { - inputs.properties(expansions) - MavenFilteringHack.filter(it, expansions) -} - -integTest { - cluster { - plugin 'license', project(':x-plugins:license:plugin') - } -} - -dependencyLicenses.enabled = false - -bundlePlugin { - from(projectDir) { - include 'LICENSE.txt' - include 'NOTICE.txt' - } -} diff --git a/marvel/src/test/java/org/elasticsearch/marvel/rest/MarvelRestIT.java b/marvel/src/test/java/org/elasticsearch/marvel/rest/MarvelRestIT.java deleted file mode 100644 index a2347e3da9b..00000000000 --- a/marvel/src/test/java/org/elasticsearch/marvel/rest/MarvelRestIT.java +++ /dev/null @@ -1,27 +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.marvel.rest; - -import com.carrotsearch.randomizedtesting.annotations.Name; -import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; -import org.elasticsearch.test.rest.ESRestTestCase; -import org.elasticsearch.test.rest.RestTestCandidate; -import org.elasticsearch.test.rest.parser.RestTestParseException; - -import java.io.IOException; - -public class MarvelRestIT extends ESRestTestCase { - - public MarvelRestIT(@Name("yaml") RestTestCandidate testCandidate) { - super(testCandidate); - } - - @ParametersFactory - public static Iterable parameters() throws IOException, RestTestParseException { - return ESRestTestCase.createParameters(0, 1); - } -} - diff --git a/shield/build.gradle b/shield/build.gradle deleted file mode 100644 index 38c142f9ba4..00000000000 --- a/shield/build.gradle +++ /dev/null @@ -1,44 +0,0 @@ -apply plugin: 'elasticsearch.esplugin' -esplugin { - name 'shield' - description 'Elasticsearch Shield (security)' - classname 'org.elasticsearch.shield.ShieldPlugin' - isolated false -} - -dependencies { - provided project(path: ':x-plugins:license:plugin', configuration: 'runtime') - compile project(':x-plugins:license:plugin-api') - compile 'dk.brics.automaton:automaton:1.11-8' - compile 'com.unboundid:unboundid-ldapsdk:2.3.8' - testCompile 'org.slf4j:slf4j-log4j12:1.6.2' - testCompile 'org.elasticsearch:securemock:1.1' - testCompile 'com.google.jimfs:jimfs:1.0' - testCompile 'com.google.guava:guava:16.0.1' // needed by jimfs -} - -forbiddenPatterns { - exclude '**/*.p12' -} - -compileJava.options.compilerArgs << "-Xlint:-deprecation,-rawtypes,-serial,-try,-unchecked" -compileTestJava.options.compilerArgs << "-Xlint:-deprecation,-rawtypes,-serial,-try,-unchecked" - -// no integ tests... -integTest.enabled = false - -dependencyLicenses.enabled = false - -// TODO: standardize packaging config for plugins -bundlePlugin { - from(projectDir) { - include 'LICENSE.txt' - include 'NOTICE.txt' - } - from('bin/shield') { - into 'bin' - } - from('config/shield') { - into 'config' - } -} diff --git a/shield/docs/private/indices_replace.asciidoc b/shield/docs/private/indices_replace.asciidoc deleted file mode 100644 index f4f5a79cfe3..00000000000 --- a/shield/docs/private/indices_replace.asciidoc +++ /dev/null @@ -1,19 +0,0 @@ -All the following scenario are run from a user authorized for: `test.*`: read - -[horizontal] -*Existing Indices*::*Action*::*Outcome (executed indices)* -`test1` `test2` `test3` `index1`::`GET _search`::`test1` `test2` `test3` -`test1` `test2` `test3` `index1`::`GET _search/*`::`test1` `test2` `test3` -`test1` `test2` `index1` `index2`::`GET _search/index*`::AuthorizationException -- empty cluster-::`GET _search`::IndexMissingException -- empty cluster-::`GET _search/*`::IndexMissingException -`index1` `index2`::`GET _search`::IndexMissingException -`index1` `index2`::`GET _search/*`::IndexMissingException -`test1` `test2` `index1`::`GET _search/test*,index1`::AuthorizationException -`test1` `test2` `index1`::`GET _search/missing`::AuthorizationException -`test1` `test2` `test3` `index1`::`GET _search/-test2`::`test1` `test3` -`test1` `test2` `test21` `test3` `index1`:: `GET _search/-test2*`::`test1` `test3` -`test1` `test2` `test3` `index1`::`GET msearch first item: all, second item: index1`:: AuthorizationException -`test1` `test2` `test3` `index1`::`GET msearch first item: all, second item: missing`:: AuthorizationException -`test1` `test2` `test3` `index1`::`GET msearch first item: all, second item: test4`:: 1st item:`test1` `test2` `test3`, 2nd item: IndexMissingException -`test1` `test2` `test3` `index1`::`GET msearch first item: all, second item: index*`:: IndexMissingException \ No newline at end of file diff --git a/shield/docs/private/ldap-testing.asciidoc b/shield/docs/private/ldap-testing.asciidoc deleted file mode 100644 index 32066b05fbd..00000000000 --- a/shield/docs/private/ldap-testing.asciidoc +++ /dev/null @@ -1,93 +0,0 @@ -== LDAP Configuration for INTERNAL only Test Servers - -We've two LDAP servers for testing: - -* Active Directory on Windows Server 2012 -* OpenLdap on Suse Enterprise Linux 10.x - -=== Configuration for OpenLdap - -Here is a configuration that works for openldap. This is using OpenSuse's method for creating ldap users that can -authenticate to the box. So it is probably close to a real-world scenario. For SSL the following truststore has both -public certificates in it: elasticsearch-shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks - -[source, yaml] ------------------------------------------------------------- -shield: - ssl.keystore: - path: "/path/to/elasticsearch-shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks" - password: testnode - authc.realms.openldap: - type: ldap - order: 0 - url: "ldaps://54.200.235.244:636" - user_dn_templates: [ "uid={0},ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com" ] - group_search: - base_dn: "ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com" - hostname_verification: false ------------------------------------------------------------- - -=== Configuration for Active Directory - -You could configure Active Directory the same way (with type ldap and user_dn_templates). But where is the fun in that! -Active directory has a simplified (non-standard) authentication workflow that helps us eliminate the templates. - -BUT this technique requires you use a DNS name for your active directory server. Do this adding the following to /etc/hosts: - -`54.213.145.20 ad.test.elasticsearch.com ForestDnsZones.ad.test.elasticsearch.com DomainDnsZones.ad.test.elasticsearch.com` - -[source, yaml] ------------------------------------------------------------- -shield: - authc.realms.ad: - type: active_directory - order: 0 - domain_name: ad.test.elasticsearch.com - ------------------------------------------------------------- - -The above configuration results in a plaintext LDAP connection. For SSL the following configuration is required: -[source, yaml] ------------------------------------------------------------- -shield: - ssl.keystore: - path: "/path/to/elasticsearch-shield/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks" - password: testnode - authc.realms.ad: - type: active_directory - order: 0 - domain_name: ad.test.elasticsearch.com - url: "ldaps://ad.test.elasticsearch.com:636" - hostname_verification: false - ------------------------------------------------------------- - -=== Users & Groups - -Isn't LDAP fun?! No? Well that's why we've created super heros! - -|======================= -| CN (common name) | uid | group memberships -| Commander Kraken | kraken | Hydra -| Bruce Banner | hulk | Geniuses, SHIELD, Philanthropists, Avengers -| Clint Barton | hawkeye | SHIELD, Avengers -| Jarvis | jarvis | -| Natasha Romanoff | blackwidow | SHIELD, Avengers -| Nick Fury | fury | SHIELD, Avengers -| Phil Colson | phil | SHIELD -| Steve Rogers | cap | SHIELD, Avengers -| Thor | thor | SHIELD, Avengers, Gods, Philanthropists -| Tony Stark | ironman | Geniuses, Billionaries, Playboys, Philanthropists, SHIELD, Avengers -| Odin | odin | Gods -|======================= - -They aren't very good super-heros because they all share the same password: `NickFuryHeartsES`. You'll use the uid -for the username. - -=== Groups -If you want to map group names to es roles, you'll use the fully distinguished names of the groups. The DNs for groups in ad is -`CN={group name},CN=Users,DC=ad,DC=test,DC=elasticsearch,DC=com` -the DNs for groups in openldap is -`cn={group name},ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com` - -Ping Cam Morris or Bill Hwang for more questions. diff --git a/shield/docs/public/configuring-auditing.asciidoc b/shield/docs/public/configuring-auditing.asciidoc deleted file mode 100644 index 0c13c9399b7..00000000000 --- a/shield/docs/public/configuring-auditing.asciidoc +++ /dev/null @@ -1,290 +0,0 @@ -[[configuring-auditing]] -== Configuring Auditing - -[IMPORTANT] -==== -Audit logs are **disabled** by default. To enable this functionality the following setting should be added to the -`elasticsearch.yml` file: - -[source,yaml] ----------------------------- -shield.audit.enabled: true ----------------------------- -==== - -The audit functionality was added to keep track of important events occurring in Elasticsearch, primarily around security -concerns. Keeping track and persisting these events is essential for any secured environment and potentially provides -evidence for suspicious/malicious activity on the Elasticsearch cluster. - -Shield provides two ways to output these events: in a dedicated `access.log` file stored on the host's file system, or -in an Elasticsearch index on the same or separate cluster. These options are not mutually exclusive. For example, both -options can be enabled through an entry in the `elasticsearch.yml` file: - -[source,yaml] ----------------------------- -shield.audit.outputs: [index, logfile] ----------------------------- - -It is expected that the `index` output type will be used in conjunction with the `logfile` output type. This is -because the `index` output type can lose messages if the target index is unavailable. For this reason, it is recommended -that, if auditing is enabled, then the `logfile` output type should be used as an official record of events. The `index` -output type can be enabled as a convenience to allow historical browsing of events. - -Please also note that, because audit events are batched together before being indexed, they may not appear immediately. -Please refer to the `shield.audit.index.flush_interval` setting below for instructions on how to modify the frequency -with which batched events are flushed. - -[float] -=== Log Entry Types - -Each audit related event that occurs is represented by a single log entry of a specific type (the type represents the -type of the event that occurred). Here are the possible log entry types: - -* `anonymous_access_denied` is logged when the request is denied due to missing authentication token. -* `authentication_failed` is logged when the authentication token cannot be matched to a known user. -* `authentication_failed []` is logged for every realm that fails to present a valid authentication token. - The value of __ is the realm type. -* `access_denied` is logged when an authenticated user attempts an action the user does not have the - <> to perform. -* `access_granted` is logged when an authenticated user attempts an action the user has the correct - privilege to perform. In TRACE level all system (internal) actions are logged as - well (in all other level they're not logged to avoid cluttering of the logs. -* `tampered_request` is logged when the request was detected to be tampered (typically relates to `search/scroll` requests when the scroll id is believed to be tampered) -* `connection_granted` is logged when an incoming tcp connection has passed the ip filtering for a specific profile -* `connection_denied` is logged when an incoming tcp connection did not pass the ip filtering for a specific profile - -To avoid needless proliferation of log entries, Shield enables you to control what entry types should be logged. This can -be done by setting the logging level. The following table lists the log entry types that will be logged for each of the -possible log levels: - -.Log Entry Types and Levels -[options="header"] -|====== -| Log Level | Entry Type -| `ERROR` | `authentication_failed`, `access_denied`, `tampered_request`, `connection_denied` -| `WARN` | `authentication_failed`, `access_denied`, `tampered_request`, `connection_denied`, `anonymous_access_denied` -| `INFO` | `authentication_failed`, `access_denied`, `tampered_request`, `connection_denied`, `anonymous_access_denied`, `access_granted` -| `DEBUG` | (doesn't output additional entry types beyond `INFO`, but extends the information emitted for each entry (see <> below) -| `TRACE` | `authentication_failed`, `access_denied`, `tampered_request`, `connection_denied`, `anonymous_access_denied`, `access_granted`, `connection_granted`, `authentication_failed []`. In addition, internal system requests (self-management requests triggered by Elasticsearch itself) will also be logged for `access_granted` entry type. -|====== - - -[float] -[[audit-log-entry-format]] -=== Log Entry Format - -As mentioned above, every log entry represents an event that occurred in the system. As such, each entry is associated with -a timestamp (at which the event occurred), the component/layer the event is associated with and the entry/event type. In -addition, every log entry (depending ot its type) carries addition information about the event. - -The format of a log entry is shown below: - -[source,txt] ----------------------------------------------------------------------------- -[] [] [] [] ----------------------------------------------------------------------------- - -Where: - -* `` - the timestamp of the entries (in the fomrat configured in `logging.yml` as shown above) -* `` - additional information about the local node that this log entry is printed from (the <> shows how this information can be controlled via settings) -* `` - the layer from which this entry relates to. Can be either `rest`, `transport` or `ip_filter` -* `` - the type of the entry as discussed above. Can be either `anonymous_access_denied`, `authentication_failed`, - `access_denied`, `access_granted`, `connection_granted`, `connection_denied`. -* `` - A comma-separated list of attribute carrying data relevant to the occurred event (formatted as `attr1=[val1], attr2=[val2],...`) - -[[audit-log-entry-local-node-info]] -.Local Node Info Settings -[options="header"] -|====== -| Name | Default | Description -| `shield.audit.logfile.prefix.emit_node_name` | true | When set to `true`, the local node's name will be emitted -| `shield.audit.logfile.prefix.emit_node_host_address` | false | When set to `true`, the local node's IP address will be emitted -| `shield.audit.logfile.prefix.emit_node_host_name` | false | When set to `true`, the local node's host name will be emitted -|====== - -The following tables describe the possible attributes each entry type can carry (the attributes that will be available depend on the configured log level): - -.`[rest] [anonymous_access_denied]` attributes -[options="header"] -|====== -| Attribute | Minimum Log Level | Description -| `origin_address` | WARN | The address the rest request origins from -| `uri` | WARN | The REST endpoint URI -| `request_body` | DEBUG | The body of the request -|====== - -.`[rest] [authentication_failed]` attributes -[options="header"] -|====== -| Attribute | Minimum Log Level | Description -| `origin_address` | ERROR | The address the rest request origins from -| `principal` | ERROR | The principal (username) that failed to authenticate -| `uri` | ERROR | The REST endpoint URI -| `request_body` | DEBUG | The body of the request -| `realm` | TRACE | The realm that failed to authenticate the user. NOTE: A separate entry will be printed for each of the consulted realms -|====== - -.`[transport] [anonymous_access_denied]` attributes -[options="header"] -|====== -| Attribute | Minimum Log Level | Description -| `origin_type` | WARN | The type of the origin the request originated from. Can be either `rest` (request was originated from a rest API request), `transport` (request received on the transport channel), `local_node` (the local node issued the request) -| `origin_address` | WARN | The address the request origins from -| `action` | WARN | The name of the action that was executed -| `request` | DEBUG | The type of the request that was executed -| `indices` | WARN | A comma-separated list of indices this request relates to (when applicable) -|====== - -.`[transport] [authentication_failed]` attributes -[options="header"] -|====== -| Attribute | Minimum Log Level | Description -| `origin_type` | ERROR | The type of the origin the request originated from. Can be either `rest` (request was originated from a rest API request), `transport` (request received on the transport channel), `local_node` (the local node issued the request) -| `origin_address` | ERROR | The address the request origins from -| `principal` | ERROR | The principal (username) that failed to authenticate -| `action` | ERROR | The name of the action that was executed -| `request` | DEBUG | The type of the request that was executed -| `indices` | ERROR | A comma-separated list of indices this request relates to (when applicable) -| `realm` | TRACE | The realm that failed to authenticate the user. NOTE: A separate entry will be printed for each of the consulted realms -|====== - -.`[transport] [access_granted]` attributes -[options="header"] -|====== -| Attribute | Minimum Log Level | Description -| `origin_type` | INFO | The type of the origin the request originated from. Can be either `rest` (request was originated from a rest API request), `transport` (request received on the transport channel), `local_node` (the local node issued the request) -| `origin_address` | INFO | The address the request origins from -| `principal` | INFO | The principal (username) that failed to authenticate -| `action` | INFO | The name of the action that was executed -| `request` | DEBUG | The type of the request that was executed -| `indices` | INFO | A comma-separated list of indices this request relates to (when applicable) -|====== - -.`[transport] [access_denied]` attributes -[options="header"] -|====== -| Attribute | Minimum Log Level | Description -| `origin_type` | ERROR | The type of the origin the request originated from. Can be either `rest` (request was originated from a rest API request), `transport` (request received on the transport channel), `local_node` (the local node issued the request) -| `origin_address` | ERROR | The address the request origins from -| `principal` | ERROR | The principal (username) that failed to authenticate -| `action` | ERROR | The name of the action that was executed -| `request` | DEBUG | The type of the request that was executed -| `indices` | ERROR | A comma-separated list of indices this request relates to (when applicable) -|====== - -.`[transport] [tampered_request]` attributes -[options="header"] -|====== -| Attribute | Minimum Log Level | Description -| `origin_type` | ERROR | The type of the origin the request originated from. Can be either `rest` (request was originated from a rest API request), `transport` (request received on the transport channel), `local_node` (the local node issued the request) -| `origin_address` | ERROR | The address the request origins from -| `principal` | ERROR | The principal (username) that failed to authenticate -| `action` | ERROR | The name of the action that was executed -| `request` | DEBUG | The type of the request that was executed -| `indices` | ERROR | A comma-separated list of indices this request relates to (when applicable) -|====== - -.`[ip_filter] [connection_granted]` attributes -[options="header"] -|====== -| Attribute | Minimum Log Level | Description -| `origin_address` | TRACE | The address the request origins from -| `transport_profile` | TRACE | The principal (username) that failed to authenticate -| `rule` | TRACE | The IP filtering rule that granted the request -|====== - -.`[ip_filter] [connection_denied]` attributes -[options="header"] -|====== -| Attribute | Minimum Log Level | Description -| `origin_address` | ERROR | The address the request origins from -| `transport_profile` | ERROR | The principal (username) that failed to authenticate -| `rule` | ERROR | The IP filtering rule that denied the request -|====== - - -[float] -=== Audit Logs Settings - -As mentioned above, the audit logs are configured in the `logging.yml` file located in `CONFIG_DIR/shield`. The following snippet shows the default logging configuration: - -[[logging-file]] - -.Default `logging.yml` File -[source,yaml] ----- -logger: - shield.audit.logfile: INFO, access_log - -additivity: - shield.audit.logfile: false - -appender: - - access_log: - type: dailyRollingFile - file: ${path.logs}/${cluster.name}-access.log - datePattern: "'.'yyyy-MM-dd" - layout: - type: pattern - conversionPattern: "[%d{ISO8601}] %m%n" ----- - -As can be seen above, by default audit information is appended to the `access.log` file located in the -standard Elasticsearch `logs` directory (typically located at `$ES_HOME/logs`). - -[float] -[[audit-index]] -=== Storing Audit Logs in an Elasticsearch Index - -It is possible to store audit logs in an Elasticsearch index. This index can be either on the same cluster, or on -a different cluster (see below). Several settings in `elasticsearch.yml` control this behavior. - -.`audit log indexing configuration` -[options="header"] -|====== -| Attribute | Default Setting | Description -| `shield.audit.outputs` | `logfile` | Must be set to *index* or *[index, logfile]* to enable -| `shield.audit.index.bulk_size` | `1000` | Controls how many audit events will be batched into a single write -| `shield.audit.index.flush_interval` | `1s` | Controls how often to flush buffered events into the index -| `shield.audit.index.rollover` | `daily` | Controls how often to roll over to a new index: hourly, daily, weekly, monthly. -| `shield.audit.index.events.include` | `anonymous_access_denied, authentication_failed, access_granted, access_denied, tampered_request, connection_granted, connection_denied`| The audit events to be indexed. Valid values are `anonymous_access_denied, authentication_failed, access_granted, access_denied, tampered_request, connection_granted, connection_denied`, `system_access_granted`. `_all` is a special value that includes all types. -| `shield.audit.index.events.exclude` | `system_access_granted` | The audit events to exclude from indexing. By default, `system_access_granted` events are excluded; enabling these events results in every internal node communication being indexed, which will make the index size much larger. -|====== - -.audit index settings -The settings for the index that the events are stored in, can also be configured. The index settings should be placed under -the `shield.audit.index.settings` namespace. For example, the following sets the number of shards and replicas to 1 for -the audit indices: - -[source,yaml] ----------------------------- -shield.audit.index.settings: - index: - number_of_shards: 1 - number_of_replicas: 1 ----------------------------- - -[float] -=== Forwarding Audit Logs to a Remote Cluster - -To have audit events stored into a remote Elasticsearch cluster, the additional following options are available. - -.`remote audit log indexing configuration` -[options="header"] -|====== -| Attribute | Default Setting | Description -| `shield.audit.index.client.hosts` | None | Comma separated list of host:port pairs. These hosts should be nodes in the cluster to which you want to index. -| `shield.audit.index.client.cluster.name` | None | The name of the remote cluster. -| `shield.audit.index.client.shield.user` | None | The username:password pair used to authenticate with the remote cluster. -|====== - -Additional settings may be passed to the remote client by placing them under the `shield.audit.index.client` namespace. -For example, to allow the remote client to discover all of the nodes in the remote cluster you could set -the *client.transport.sniff* option. - -[source,yaml] ----------------------------- -shield.audit.index.client.transport.sniff: true ----------------------------- diff --git a/shield/docs/public/configuring-clients-integrations.asciidoc b/shield/docs/public/configuring-clients-integrations.asciidoc deleted file mode 100644 index 1b7255adf12..00000000000 --- a/shield/docs/public/configuring-clients-integrations.asciidoc +++ /dev/null @@ -1,17 +0,0 @@ -[[configuring-clients-integrations]] -== Configuring Clients and Integrations - -You will need to update the configuration for several clients to work with the Shield security plugin. The jump list in -the right side bar lists the configuration information for the clients that support Shield. - -include::configuring-clients-integrations/java.asciidoc[] - -include::configuring-clients-integrations/http.asciidoc[] - -include::configuring-clients-integrations/hadoop.asciidoc[] - -include::configuring-clients-integrations/logstash.asciidoc[] - -include::configuring-clients-integrations/kibana.asciidoc[] - -include::configuring-clients-integrations/marvel.asciidoc[] \ No newline at end of file diff --git a/shield/docs/public/configuring-clients-integrations/hadoop.asciidoc b/shield/docs/public/configuring-clients-integrations/hadoop.asciidoc deleted file mode 100644 index 13b93105549..00000000000 --- a/shield/docs/public/configuring-clients-integrations/hadoop.asciidoc +++ /dev/null @@ -1,8 +0,0 @@ -[[hadoop]] -=== Using Elasticsearch for Apache Hadoop with Shield - -Elasticsearch for Apache Hadoop ("ES-Hadoop") is capable of using HTTP basic and PKI authentication and/or TLS/SSL when accessing an Elasticsearch cluster. For full details please refer to the ES-Hadoop documentation, in particular the `Security` section. - -For authentication purposes, select the user for your ES-Hadoop client (for maintenance purposes it is best to create a dedicated user). Then, assign that user to a role with the privileges required by your Hadoop/Spark/Storm job. Configure ES-Hadoop to use the user name and password through the `es.net.http.auth.user` and `es.net.http.auth.pass` properties. If PKI authentication is enabled, setup the appropriate `keystore` and `truststore` instead through `es.net.ssl.keystore.location` and `es.net.truststore.location` (and their respective `.pass` properties to specify the password). - -For secured transport, enable SSL/TLS through the `es.net.ssl` property by setting it to `true`. Depending on your SSL configuration (keystore, truststore, etc...) you might need to set other parameters as well - please refer to the http://www.elastic.co/guide/en/elasticsearch/hadoop/current/configuration.html[ES-Hadoop] documentation, specifically the `Configuration` and `Security` chapter. diff --git a/shield/docs/public/configuring-clients-integrations/http.asciidoc b/shield/docs/public/configuring-clients-integrations/http.asciidoc deleted file mode 100644 index b7c2aa7b60e..00000000000 --- a/shield/docs/public/configuring-clients-integrations/http.asciidoc +++ /dev/null @@ -1,58 +0,0 @@ -=== Using Elasticsearch HTTP/REST Clients with Shield - -Elasticsearch works with standard HTTP http://en.wikipedia.org/wiki/Basic_access_authentication[basic authentication] -headers to identify the requester. Since Elasticsearch is stateless, this header must be sent with every request: - -[source,shell] --------------------------------------------------- -Authorization: Basic <1> --------------------------------------------------- -<1> The `` is computed as `base64(USERNAME:PASSWORD)` - -[float] -==== Client examples - -This example uses `curl` without basic auth to create an index: - -[source,shell] -------------------------------------------------------------------------------- -curl -XPUT 'localhost:9200/idx' -------------------------------------------------------------------------------- - -[source,json] -------------------------------------------------------------------------------- -{ - "error": "AuthenticationException[Missing authentication token]", - "status": 401 -} -------------------------------------------------------------------------------- - -Since no user is associated with the request above, an authentication error is returned. Now we'll use `curl` with -basic auth to create an index as the `rdeniro` user: - -[source,shell] ---------------------------------------------------------- -curl --user rdeniro:taxidriver -XPUT 'localhost:9200/idx' ---------------------------------------------------------- - -[source,json] ---------------------------------------------------------- -{ - "acknowledged": true -} ---------------------------------------------------------- - -[float] -==== Client Libraries over HTTP - -For more information about how to use Shield with the language specific clients please refer to -https://github.com/elasticsearch/elasticsearch-ruby/tree/master/elasticsearch-transport#authentication[Ruby], -http://elasticsearch-py.readthedocs.org/en/master/#ssl-and-authentication[Python], -https://metacpan.org/pod/Search::Elasticsearch::Role::Cxn::HTTP#CONFIGURATION[Perl], -http://www.elastic.co/guide/en/elasticsearch/client/php-api/current/_security.html[PHP], -http://nest.azurewebsites.net/elasticsearch-net/security.html[.NET], -http://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/auth-reference.html[Javascript] - -//// -Groovy - TODO link -//// diff --git a/shield/docs/public/configuring-clients-integrations/java.asciidoc b/shield/docs/public/configuring-clients-integrations/java.asciidoc deleted file mode 100644 index 8c996d2be6b..00000000000 --- a/shield/docs/public/configuring-clients-integrations/java.asciidoc +++ /dev/null @@ -1,239 +0,0 @@ -=== Using Elasticsearch Java Clients with Shield - -Shield supports the Java http://www.elastic.co/guide/en/elasticsearch/client/java-api/current/transport-client.html[transport client] for Elasticsearch. The transport client uses the same transport protocol that the cluster nodes use for inter-node communication. It is very efficient as it does not have to marshall and unmarshall JSON requests like a typical REST client. - -NOTE: Using the Java Node Client with Shield is not recommended or supported. - -[float] -[[transport-client]] -==== Configuring the Transport Client to work with Shield - -To use the transport client with Shield, you need to: - -[[java-transport-client-role]] -. Configure a user with the privileges required to start the transport client. A default -`transport_client` role is defined in `roles.yml` that grants the `cluster:monitor/nodes/info` cluster permission. The transport client uses the node info API to fetch information about the nodes in the cluster. If the client is configured to use sniffing, you need to add the -`cluster:monitor/state` cluster permission to the `transport_client` role. - -. Add the Shield JAR file (`shield-2.1.0.jar`) to your CLASSPATH. You can download the Shield distribution and extract the JAR file manually or you can get it from the https://maven.elasticsearch.org/releases/org/elasticsearch/plugin/shield/{version}/shield-{version}.jar[Elasticsearch Maven repository]. -+ -If you are using Maven, you need to add the Shield JAR file as a dependency in your project's `pom.xml` file: -+ -[source,xml] --------------------------------------------------------------- - - - - - - elasticsearch-releases - https://maven.elasticsearch.org/releases - - true - - - false - - - ... - - ... - - - - - org.elasticsearch.plugin - shield - 2.1.0 - - ... - - ... - - --------------------------------------------------------------- -+ -If you are using Gradle, you need to add the Shield JAR file as a dependency in your `build.gradle` file: -+ -[source,groovy] --------------------------------------------------------------- -repositories { - /* ... Any other repositories ... */ - - // Add the Elasticsearch Maven Repository - maven { - url "https://maven.elasticsearch.org/releases" - } -} - -dependencies { - // Provide the Shield jar on the classpath for compilation and at runtime - // Note: Many projects can use the Shield jar as a runtime dependency - compile "org.elasticsearch.plugin:shield:2.1.0" - - /* ... */ -} --------------------------------------------------------------- - -. Set up the transport client. At a minimum, you must configure `shield.user` to include the name and password of your transport client user in your requests. The following snippet configures the user credentials globally--every request submitted with this client includes the `transport_client_user` credentials in its headers. -+ -[source,java] -------------------------------------------------------------------------------------------------- -import org.elasticsearch.client.transport.TransportClient; -import org.elasticsearch.shield.ShieldPlugin -... - -TransportClient client = TransportClient.builder() - .addPlugin(ShieldPlugin.class) - .settings(Settings.builder() - .put("cluster.name", "myClusterName") - .put("shield.user", "transport_client_user:changeme") - ... - .build()) - .addTransportAddress(new InetSocketTransportAddress("localhost", 9300)) - .addTransportAddress(new InetSocketTransportAddress("localhost", 9301)); -------------------------------------------------------------------------------------------------- -+ -WARNING: If you configure a transport client without SSL, passwords are sent in plaintext. -+ -You can also add an `Authorization` header to each request. If you've configured global authorization credentials, the `Authorization` header overrides the global authentication credentials. This is useful when an application has multiple users who access Elasticsearch using the same client. You can set the global token to a user that only has the `transport_client` role, and add the `transport_client` role to the individual users. -+ -For example, the following snippet adds the `Authorization` header to a search request: -+ -[source,java] --------------------------------------------------------------------------------------------------- -import org.elasticsearch.client.transport.TransportClient; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.transport.InetSocketTransportAddress; -import org.elasticsearch.shield.authc.support.SecuredString; -import org.elasticsearch.shield.ShieldPlugin - -import static org.elasticsearch.shield.authc.support.UsernamePasswordToken.basicAuthHeaderValue; -... - -TransportClient client = TransportClient.builder() - .addPlugin(ShieldPlugin.class) - .settings(Settings.builder() - .put("cluster.name", "myClusterName") - .put("shield.user", "transport_client_user:changeme") - ... - .build()) - .build() - .addTransportAddress(new InetSocketTransportAddress("localhost", 9300)) - .addTransportAddress(new InetSocketTransportAddress("localhost", 9301)); - -String token = basicAuthHeaderValue("test_user", new SecuredString("changeme".toCharArray())); - -client.prepareSearch().putHeader("Authorization", token).get(); --------------------------------------------------------------------------------------------------- - -. Enable SSL to authenticate clients and encrypt communications. To enable SSL, you need to: - -.. Configure the client's keystore path and password. Client authentication requires every -client to have a certification signed by a trusted CA. -+ -NOTE: Client authentication is enabled by default. For information about disabling client authentication, see <>. -+ -[source,java] --------------------------------------------------------------------------------------------------- -import org.elasticsearch.client.transport.TransportClient; -import org.elasticsearch.shield.ShieldPlugin -... - -TransportClient client = TransportClient.builder() - .addPlugin(ShieldPlugin.class) - .settings(Settings.builder() - .put("cluster.name", "myClusterName") - .put("shield.user", "transport_client_user:changeme") - .put("shield.ssl.keystore.path", "/path/to/client.jks") (1) - .put("shield.ssl.keystore.password", "password") - ... - .build()); --------------------------------------------------------------------------------------------------- -+ -(1) The `client.jks` keystore must contain the client's signed certificate and the CA certificate. -+ -.. Enable the SSL transport by setting `shield.transport.ssl` to `true` in the client configuration. -+ -[source,java] --------------------------------------------------------------------------------------------------- -import org.elasticsearch.client.transport.TransportClient; -import org.elasticsearch.shield.ShieldPlugin -... - -TransportClient client = TransportClient.builder() - .addPlugin(ShieldPlugin.class) - .settings(Settings.builder() - .put("cluster.name", "myClusterName") - .put("shield.user", "transport_client_user:changeme") - .put("shield.ssl.keystore.path", "/path/to/client.jks") (1) - .put("shield.ssl.keystore.password", "password") - .put("shield.transport.ssl", "true") - ... - .build()) - .addTransportAddress(new InetSocketTransportAddress("localhost", 9300)) - .addTransportAddress(new InetSocketTransportAddress("localhost", 9301)); --------------------------------------------------------------------------------------------------- - -[float] -[[disabling-client-auth]] -===== Disabling Client Authentication - -If you want to disable client authentication, you can use a client-specific transport protocol. For more information, <>. - -If you are not using client authentication and sign the Elasticsearch node certificates with your own CA, you need to set the truststore path and password in the client configuration: - -[source,java] ------------------------------------------------------------------------------------------------------- -import org.elasticsearch.client.transport.TransportClient; -import org.elasticsearch.shield.ShieldPlugin -... - -TransportClient client = TransportClient.builder() - .addPlugin(ShieldPlugin.class) - .settings(Settings.builder() - .put("cluster.name", "myClusterName") - .put("shield.user", "test_user:changeme") - .put("shield.ssl.truststore.path", "/path/to/truststore.jks") (1) - .put("shield.ssl.truststore.password", "password") - .put("shield.transport.ssl", "true") - ... - .build()) - .addTransportAddress(new InetSocketTransportAddress("localhost", 9300)) - .addTransportAddress(new InetSocketTransportAddress("localhost", 9301)); ------------------------------------------------------------------------------------------------------- -(1) The `truststore.jks` truststore must contain the certificate of the CA that signed the Elasticsearch node certificates. - -NOTE: If you are using a public CA that is already trusted by the Java runtime, you to not need to set the `shield.ssl.truststore.path` and `shield.ssl.truststore.password`. - -[float] -[[connecting-anonymously]] -===== Connecting Anonymously added[1.1.0] - -To enable the transport client to connect anonymously, you must assign the anonymous user the privileges defined in the <> role. Anonymous access must also be enabled, of course. For more information, see <>. - -[float] -[[shield-client]] -==== Shield Client - -Shield exposes its own API through the `ShieldClient` class. At the moment, this API only exposes one operation, for clearing the realm caches. `ShieldClient` is a wrapper around the existing clients (any client class implementing `org.elasticsearch.client.Client`). - -The following example shows how you can clear Shield's realm caches using `ShieldClient`: - -[source,java] ------------------------------------------------------------------------------------------------------- -import static org.elasticsearch.node.NodeBuilder.*; -... - -Client client = ... // create the transport client - -ShieldClient shieldClient = new ShieldClient(client); -ClearRealmCacheResponse response = shieldClient.authc().prepareClearRealmCache() - .realms("ldap1", "ad1") (1) - .usernames("rdeniro") - .get(); ------------------------------------------------------------------------------------------------------- - -(1) Clears the `ldap1` and `ad1` realm caches for the `rdeniro` user. - - diff --git a/shield/docs/public/configuring-clients-integrations/kibana.asciidoc b/shield/docs/public/configuring-clients-integrations/kibana.asciidoc deleted file mode 100644 index e38c962d016..00000000000 --- a/shield/docs/public/configuring-clients-integrations/kibana.asciidoc +++ /dev/null @@ -1,316 +0,0 @@ - -[[kibana]] -=== Using Kibana with Shield - -Shield supports both Kibana 3 and Kibana 4.0 and later. To set things up, you need to update your Kibana configuration and define and assign roles for your Kibana users in Shield. If you're using Kibana 3, you also need to enable cross-origin resource sharing (CORS) in Elasticsearch. -If you're using Kibana 4, you need to configure credentials for the Kibana server. The following sections provide step-by-step instructions for using <> and <> with Shield. - -NOTE: With Shield installed, if you load a Kibana dashboard that accesses data in an index that you are not authorized to view, you get an error that indicates the index does not exist. Kibana and Shield do not currently provide a way to control which users can load which dashboards. - -[[using-kibana3-with-shield]] -[float] -==== Using Kibana 3 with Shield - -Kibana users have to authenticate when your cluster has Shield installed. You configure Shield roles for your Kibana users to control what data those users can access. In addition, you can encrypt communications between the browser and Elasticsearch. - -[[cors]] -To use Kibana 3 with Shield: - -. Configure Kibana to use credentials when communicating with Elasticsearch. To do this, set `withCredentials` to `true` in the `elasticsearch` property in Kibana's `config.js` file: -+ -[source,yaml] ------------------------------------- -elasticsearch: {server: "http://YOUR_ELASTICSEARCH_SERVER:9200", withCredentials: true} ------------------------------------- -+ -IMPORTANT: If SSL encryption is enabled in Shield, specify the HTTPS protocol in the Elasticsearch URL rather than HTTP. - -. Enable CORS in Elasticsearch and allow credentialed requests. To do this, set the following properties in `elasticsearch.yml` on each node in your cluster and restart the nodes: -+ -[source,yaml] ------------------------------------- -http.cors.enabled: true <1> -http.cors.allow-origin: "https://MYHOST:MYPORT" <2> -http.cors.allow-credentials: true <3> ------------------------------------- -<1> Enables CORS. For more information, see http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-http.html[HTTP] in the Elasticsearch Reference. -<2> Specifies the webserver you are using for Kibana. Note that you must explicitly specify your server's protocol, hostname, and port--you cannot simply specify a wildcard `*` when using credentialed requests. -<3> Sends authentication headers to the browser. -+ -NOTE: If you are using a source build of Kibana 3, you might encounter authentication errors when trying to connect to Kibana 3 after deploying Shield and configuring the `http.cors.allow-credentials` property. If you do, simply clear your browser's cache and reconnect. - -. Derive Kibana 3 user roles from the default <> and add them to `roles.yml` to control which indices your Kibana users can access. Kibana users need access to the indices that they will be working with and the `kibana-int` index where their dashboards are stored. The default `kibana3` role grants read access to all indices and full access to the `kibana-int` index. -+ -IMPORTANT: We strongly recommend creating custom `kibana3` user roles -to limit access to specific indices according to your organization's goals and policies. You can define as many different roles for your Kibana users as you need. -+ -To constrain Kibana's access to specific indices, explicitly specify the index names in your role. When configuring a role for a Kibana user and granting access to a specific index, at a minimum the user needs the following privileges on the index: -+ --------------------------------------------------------------------------------- -indices:admin/mappings/fields/get -indices:admin/validate/query -indices:data/read/search -indices:data/read/msearch -indices:admin/get --------------------------------------------------------------------------------- -+ -For example, the following `kibana3_monitoring` role only allows users to build dashboards using data in the `logstash-*` indices. -+ -[source,yaml] --------------------------------------------------------------------------------- -kibana3_monitoring: - cluster: - - cluster:monitor/nodes/info <1> - indices: - 'logstash-*': - - indices:admin/mappings/fields/get - - indices:admin/validate/query - - indices:data/read/search - - indices:data/read/msearch - - indices:admin/get - '.kibana-int': <2> - - indices:data/read/get - - indices:data/read/search - - indices:data/write/delete - - indices:data/write/index - - create_index --------------------------------------------------------------------------------- -<1> Kibana 3 uses the cluster permission to access the `/_nodes` endpoint to check the node version. -<2> All Kibana users need access to the `kibana-int` index. - -. Assign the appropriate roles to your Kibana users or groups of users: - -** If you're using the default `esusers` realm, you can assign roles when you <>, or modify the role assignments with the <> command. For example, the following command creates a user named `jacknich` and assigns the `kibana3_monitoring` role: -+ -[source,console] --------------------------------------------------------------------------------- -esusers useradd jacknich -r kibana3_monitoring -p password --------------------------------------------------------------------------------- - -** If you are using an LDAP or Active Directory realm, you can either assign roles on a per user basis, or assign roles to groups of users. By default, role mappings are stored in <>. For example, the following snippet assigns the `kibana3_monitoring` role to the group named `admins` and the user named Jack Nicholson: -+ -[source,yaml] --------------------------------------------------------------------------------- -kibana3_monitoring: - - "cn=admins,dc=example,dc=com" - - "cn=Jack Nicholson,dc=example,dc=com" --------------------------------------------------------------------------------- - -. If you have <> in Shield and are using your own Certificate Authority (CA) to sign certificates for your nodes, configure your browser or operating system to trust your CA. When you access Kibana, your browser verifies that the certificate received from the Elasticsearch node is trusted before sending a request to the node. Establishing this trust requires that either your browser or operating system trust the CA that signed the node's certificate. Consult your local IT professional for information about the recommended procedure for adding trusted CAs in your organization. - -. Access Kibana 3 from your browser and verify that you can sign in as a user. For example, you could log in as the `jacknich` user created in step 4. - -[float] -[[using-kibana4-with-shield]] -==== Using Kibana 4 with Shield -Kibana users have to authenticate when your cluster has Shield installed. You configure Shield roles for your Kibana users to control what data those users can access. Kibana 4 runs a webserver that makes requests to Elasticsearch on the client's behalf, so you also need to configure credentials for the Kibana server so those requests can be authenticated. In addition, you can encrypt communications between the Kibana server and Elasticsearch. - -To use Kibana 4 with Shield: - -. Configure credentials for the Kibana server. The Kibana server needs access to the cluster monitoring APIs and the `.kibana` index. The server does _not_ need access to user indexes. The required privileges are specified in the <> provided in the default Shield <> file. - -.. Create a user account for the Kibana server and assign it the `kibana4_server` role. For example, if you're using the default `esusers` realm, you can create a `kibana-server` user with the <> command: -+ -[source,console] --------------------------------------------------------------------------------- -esusers useradd kibana4-server -r kibana4_server -p password --------------------------------------------------------------------------------- -+ -If you are using an LDAP, Active Directory, or PKI realm, you need to create a user for the -Kibana server and map the user's distinguished name to the `kibana4_server` role in the Shield <> file. By default, role mappings are stored in `config/shield/role_mapping.yml`. For example, the following snippet assigns the `kibana4_server` role to an LDAP or Active Directory user named `kibana-server`: -+ -[source,yaml] --------------------------------------------------------------------------------- -kibana4_server: - - "cn=kibana-server,cn=applications,dc=example,dc=com" --------------------------------------------------------------------------------- -+ -For PKI realms, you specify the user's common name, organizational unit, and organization: -+ -[source,yaml] --------------------------------------------------------------------------------- -kibana4_server: - - "cn=kibana-server,ou=example,o=com" --------------------------------------------------------------------------------- - -.. Specify the credentials for your Kibana server user in the Kibana configuration -file, `/config/kibana.yml`. -+ -[source,yaml] --------------------------------------------------------------------------------- -elasticsearch.username: kibana4-server -elasticsearch.password: password --------------------------------------------------------------------------------- - -[[kibana4-roles]] -. Derive Kibana 4 user roles from the default <> and add them to `roles.yml` to control which indices your Kibana users can access. Kibana users need access to the indices that they will be working with and the `.kibana` index where their saved searches, visualizations, and dashboards are stored. The default `kibana4` role grants read access to all indices and full access to the `.kibana` index. -+ -IMPORTANT: We strongly recommend creating custom `kibana4` user roles -to limit access to specific indices according to your organization's goals and policies. You can define as many different roles for your Kibana 4 users as you need. -+ -To constrain Kibana's access to specific indices, explicitly specify the index names in your role. When configuring a role for a Kibana user and granting access to a specific index, at a minimum the user needs the following privileges on the index: -+ --------------------------------------------------------------------------------- -indices:admin/mappings/fields/get -indices:admin/validate/query -indices:data/read/search -indices:data/read/msearch -indices:admin/get --------------------------------------------------------------------------------- -+ -For example, the following `kibana4_monitoring` role only allows users to discover and visualize data in the `logstash-*` indices. -+ -[source,yaml] --------------------------------------------------------------------------------- -kibana4_monitoring: - cluster: - - cluster:monitor/nodes/info - - cluster:monitor/health - indices: - 'logstash-*': - - indices:admin/mappings/fields/get - - indices:admin/validate/query - - indices:data/read/search - - indices:data/read/msearch - - indices:admin/get - '.kibana': <1> - - indices:admin/create - - 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 --------------------------------------------------------------------------------- -<1> All Kibana users need access to the `.kibana` index. - -. Assign the appropriate roles to your Kibana users or groups of users: - -** If you're using the default `esusers` realm, you can assign roles when you <>, or modify the role assignments with the <> command. For example, the following command creates a user named `jacknich` and assigns the `kibana4_monitoring` role: -+ -[source,console] --------------------------------------------------------------------------------- -esusers useradd jacknich -r kibana4_monitoring -p password --------------------------------------------------------------------------------- - -** If you are using an LDAP or Active Directory realm, you can either assign roles on a per user basis, or assign roles to groups of users. By default, role mappings are stored in <>. For example, the following snippet assigns the `kibana4_monitoring` role to the group named `admins` and the user named Jack Nicholson: -+ -[source,yaml] --------------------------------------------------------------------------------- -kibana4_monitoring: - - "cn=admins,dc=example,dc=com" - - "cn=Jack Nicholson,dc=example,dc=com" --------------------------------------------------------------------------------- - -. If you have enabled SSL encryption in Shield, configure Kibana 4 to connect to Elasticsearch via HTTPS. To do this: - -.. Specify the HTTPS protocol in the `elasticsearch.url` setting in the Kibana configuration file, `kibana.yml`: -+ -[source,yaml] --------------------------------------------------------------------------------- -elasticsearch.url: "https://.com:9200" --------------------------------------------------------------------------------- - -.. If you are using your own CA to sign certificates for Elasticsearch, set the `elasticsearch.ssl.ca` setting in `kibana.yml` to specify the location of the PEM file. -+ -[source,yaml] --------------------------------------------------------------------------------- -elasticsearch.ssl.ca: /path/to/your/cacert.pem --------------------------------------------------------------------------------- - -. Configure Kibana 4 to encrypt communications between the browser and the Kibana server. To do this, configure the `server.ssl.key` and `server.ssl.cert` properties in `kibana.yml`: -+ -[source,yaml] --------------------------------------------------------------------------------- -server.ssl.key: /path/to/your/server.key -server.ssl.cert: /path/to/your/server.crt --------------------------------------------------------------------------------- -+ -Once you enable SSL encryption between the browser and the Kibana server, access Kibana via HTTPS. For example, `https://localhost:5601`. -+ -NOTE: Enabling browser encryption is required to prevent passing user credentials in the clear. - -. Restart Kibana and verify that you can sign in as a user. If you are running Kibana locally, -go to `localhost:5601` and enter the credentials for a user you've assigned a Kibana user role. For example, you could log in as the `jacknich` user created in step 3. -+ -NOTE: Sign in as a Kibana user--the Kibana server credentials should only be used internally by the Kibana server. The `kibana4_server` role doesn't grant permission to create the `.kibana` index or access user indices. - -[float] -[[default-roles]] -==== Default Roles for Kibana - -Default roles for Kibana 3 and Kibana 4 are provided in `roles.yml`. - -IMPORTANT: The default user roles grant read access to all indices. We strongly recommend deriving custom roles for your Kibana users that limit access to specific indices according to your organization's goals and policies. - -[[kibana3-user-role]] -.Kibana 3 User Role -[source,yaml] --------------------------------------------------------------------------------- -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 --------------------------------------------------------------------------------- - -[[kibana4-user-role]] -.Kibana 4 User Role -[source,yaml] --------------------------------------------------------------------------------- -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 --------------------------------------------------------------------------------- - - -[[kibana4-server-role]] -.Kibana 4 Server Role -[source,yaml] --------------------------------------------------------------------------------- -kibana4_server: - cluster: - - cluster:monitor/nodes/info - - cluster:monitor/health - indices: - '.kibana': - - indices:admin/create - - 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 --------------------------------------------------------------------------------- - diff --git a/shield/docs/public/configuring-clients-integrations/logstash.asciidoc b/shield/docs/public/configuring-clients-integrations/logstash.asciidoc deleted file mode 100644 index b1ee1288e3a..00000000000 --- a/shield/docs/public/configuring-clients-integrations/logstash.asciidoc +++ /dev/null @@ -1,200 +0,0 @@ -[[logstash]] -=== Using Logstash with Shield - -IMPORTANT: Shield 2.0+ is compatible with Logstash 2.0 and above. - -Logstash provides Elasticsearch https://www.elastic.co/guide/en/logstash/current/plugins-outputs-elasticsearch.html[output], https://www.elastic.co/guide/en/logstash/current/plugins-inputs-elasticsearch.html[input] and https://www.elastic.co/guide/en/logstash/current/plugins-filters-elasticsearch.html[filter] plugins -used to index and retrieve documents through HTTP, transport or client node protocols. -All plugins support authentication and encryption over HTTP, while the output plugin additionally supports these -features over the transport protocol. - -NOTE: When using the `elasticsearch` output, only the `transport` and `http` protocol are supported (i.e. `node` protocol is unsupported) - -[float] -[[ls-user]] -==== Creating a user - -By default, the Shield plugin installs a dedicated user <> that enables the creation of indices with names -that match the `logstash-*` regular expression, along with privileges to read, scroll, index, update, and delete -documents on those indices: - -[source,yaml] --------------------------------------------------------------------------------------------- -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 --------------------------------------------------------------------------------------------- - -See the <> section for information on modifying roles. - -Create a user associated with the `logstash` role on the Elasticsearch cluster, using the <>: - -[source,shell] --------------------------------------------------- -esusers useradd -p -r logstash --------------------------------------------------- - -NOTE: When using the transport protocol, the logstash user requires the predefined `transport_client` role in addition to the `logstash` role shown above (`-r logstash,transport_client`). - -Once you've created the user, you are ready to configure Logstash. - -[float] -[[ls-http]] -==== Connecting with HTTP/HTTPS - -Logstash communicates with the Elasticsearch cluster through the REST APIs over HTTP. - -[float] -[[ls-http-auth]] -===== Authentication for HTTP protocol - -HTTP protocol supports both basic auth and client-certificate authentication through the use of Public Key Infrastructure (PKI). - -[float] -[[ls-http-auth-basic]] -===== Basic Authentication - -The  input, filter, and output plugins all support HTTP Basic Authentication. To use basic authentication when connecting to an instance of Elasticsearch with Shield, you configure the plugins to include username and password credentials with each request. For example, the following snippet configures credentials for the output plugin. The credentials are configured the same way for each plugin type. - -[source, shell] --------------------------------------------------- -input { ... } -output { - elasticsearch { - protocol => "http" - ... - user => ... # string - password => ... # string - } -} --------------------------------------------------- - -[float] -[[ls-http-auth-pki]] -===== PKI Authentication - -Elasticsearch Output supports the use of X.509 client-certificate to authenticate Logstash requests. To enable this you need to set up the following configuration parameters: - -[source, shell] --------------------------------------------------- -input { ... } -output { - elasticsearch { - ... - keystore => ... # string - keystore_password => ... # string - } -} --------------------------------------------------- - -[float] -[[ls-http-ssl]] -===== SSL/TLS Configuration for HTTPS - -To enable SSL/TLS encryption for HTTPS, use the following configuration block: - -[source, shell] --------------------------------------------------- -input { ... } -output { - elasticsearch { - ... - ssl => true - cacert => '/path/to/cert.pem' <1> - } -} --------------------------------------------------- -<1> The path to the `.pem` file in your filesystem that contains the Certificate Authority's certificate. - -[float] -[[ls-transport]] -==== Connecting with Transport protocol - -When using the `elasticsearch_java` plugins in Logstash, you can set the `protocol` option to `transport`. With `transport`, Logstash communicates with the Elasticsearch cluster through the same -protocol nodes use between each other. - -In order to unlock this option, it's necessary to install an additional plugin in Logstash using the following command: - -[source, shell] --------------------------------------------------- -bin/plugin install logstash-output-elasticsearch_java_shield --------------------------------------------------- - -[float] -[[ls-transport-auth]] -===== Authentication for Transport protocol - -Transport protocol supports both basic auth and client-certificate authentication through the use of Public Key Infrastructure (PKI). - -[float] -[[ls-transport-auth-basic]] -===== Basic Authentication - -To connect to an instance of Elasticsearch with Shield using basic auth, set up the username and password credentials with the following configuration parameters: - -[source, shell] --------------------------------------------------- -input { ... } -output { - elasticsearch_java { - protocol => "transport" - ... - user => ... # string - password => ... # string - } -} --------------------------------------------------- - -[float] -[[ls-transport-auth-pki]] -===== PKI Authentication - -To connect to an instance of Elasticsearch with Shield using client-certificate authentication you need to setup the keystore path which contain the client's certificate and the keystore password in the configuration: - -[source, shell] --------------------------------------------------- -input { ... } -output { - elasticsearch_java { - protocol => "transport" - ... - ssl => true - keystore => ... # string - keystore_password => ... # string - } -} --------------------------------------------------- - -[float] -[[ls-transport-conf]] -===== SSL Configuration for Transport protocols - -Specify the paths to the keystore and truststore `.jks` files with the following configuration parameters: - -[source, shell] --------------------------------------------------- -input { ... } -output { - elasticsearch_java { - protocol => "transport" - host => ... # string (optional) - cluster => ... # string (optional) - ... - ssl => true - keystore => ... # string - keystore_password => ... # string - truststore => ... # string - truststore_password => ... # string - } -} --------------------------------------------------- - -For more information on encryption and certificates, see the <> section: - -[float] -[[ls-failure]] -==== Failures - -Logstash raises an exception that halts the processing pipeline when the server's certificate does not validate over SSL -on any of the protocols discussed in this section. Same for the invalid user credentials. diff --git a/shield/docs/public/configuring-clients-integrations/marvel.asciidoc b/shield/docs/public/configuring-clients-integrations/marvel.asciidoc deleted file mode 100644 index 76b1f24f235..00000000000 --- a/shield/docs/public/configuring-clients-integrations/marvel.asciidoc +++ /dev/null @@ -1,115 +0,0 @@ -[[marvel]] -=== Using Marvel with Shield - -https://www.elastic.co/guide/en/marvel/current/introduction.html[Marvel] consists of two -components: a Marvel agent that you install on on each node in your cluster, and a Marvel application you install in https://www.elastic.co/guide/en/kibana/current/introduction.html[Kibana]. The Marvel agent collects and indexes metrics from Elasticsearch and you visualize the data through the Marvel dashboards in Kibana. The agent can index data on the same cluster, or send it to an external monitoring cluster. - -To use Marvel with Shield enabled, you need to <> and create at least one user for the Marvel app. If you are using an external monitoring cluster, you also need to configure a user for the Marvel agent and configure the agent to use the appropriate -credentials when communicating with the monitoring cluster. - -[float] -[[marvel-app-users]] -==== Setting Up Marvel App Users - -When Shield is enabled, Kibana users are prompted to log in when they access the UI. To use -the Marvel app, a user must have access to the Kibana indices and permission to read from the -Marvel indices. - -You set up Marvel app users on the cluster where the monitoring data is being stored. To grant -all of the necessary permissions, assign user the `kibana_user` and `marvel_user` roles defined -in `roles.yml`: - -* If you're using the default `esusers` realm, you can assign roles when you <>, or modify the role assignments with the <> command. For example, -the following command creates a user named `jacknich` and assigns the `marvel_user` role: -+ -[source,console] --------------------------------------------------------------------------------- -esusers useradd jacknich -r kibana_user,marvel_user -p password --------------------------------------------------------------------------------- - -* If you are using an LDAP or Active Directory realm, you can either assign roles on a per user -basis, or assign roles to groups of users. By default, role mappings are configured in -<>. For example, the following snippet assigns -the user named Jack Nicholson to the `kibana_user` and `marvel_user` roles: -+ -[source,yaml] --------------------------------------------------------------------------------- -kibana_user: - - "cn=Jack Nicholson,dc=example,dc=com" -marvel_user: - - "cn=Jack Nicholson,dc=example,dc=com" --------------------------------------------------------------------------------- - -[float] -[[configuring-marvel-agent-shield]] -==== Configuring Marvel Agent to Communicate with a Shield-Enabled Monitoring Cluster - -To configure the Marvel agent to communicate with a secured monitoring cluster: - -. Configure a user on the monitoring cluster who has the `marvel_agent` role, which is defined in -`roles.yml`. For example: -+ -[source,console] --------------------------------------------------------------------------------- -esusers useradd agent-user -r marvel_agent -p password --------------------------------------------------------------------------------- -+ -.Marvel Agent Role -[source,yaml] --------------------------------------------------- -marvel_agent: - cluster: indices:admin/template/get, indices:admin/template/put - indices: - '.marvel-*': indices:data/write/bulk, create_index --------------------------------------------------- - -. On each node in the cluster being monitored, configure a Marvel HTTP exporter -in `elasticsearch.yml` and resart Elasticsearch. In the exporter configuration, -you need to: -+ --- -.. Set the `type` to `http`. -.. Specify the location of the monitoring cluster in the `host` setting. -.. Provide the agent user credentials with the `username` and `password` settings. - -For example: - -[source,yaml] --------------------------------------------------- -marvel.agent.exporters: - id1: - type: http - host: ["http://es-mon1:9200", "http://es-mon2:9200"] - auth: - username: agent-user - password: password --------------------------------------------------- - -If SSL/TLS is enabled on the monitoring cluster: - -.. Specify the HTTPS protocol when setting the monitoring server host. -.. Specify a truststore that contains the CA certificate to use to verify the identities of the -nodes in the monitoring cluster. You need to set the `truststore.path` and -`truststore.password`. - -For example: - -[source,yaml] --------------------------------------------------- -marvel.agent.exporters: - id1: - type: http - host: ["https://es-mon1:9200", "https://es-mon2:9200"] - - auth: - username: agent-user - password: password - - ssl: - truststore.path: /path/to/file - truststore.password: password - id2: - type: local --------------------------------------------------- --- \ No newline at end of file diff --git a/shield/docs/public/configuring-rbac.asciidoc b/shield/docs/public/configuring-rbac.asciidoc deleted file mode 100644 index 3991afc6941..00000000000 --- a/shield/docs/public/configuring-rbac.asciidoc +++ /dev/null @@ -1,155 +0,0 @@ -[[configuring-rbac]] -== Configuring Role-based Access Control - -Shield introduces the concept of _action authorization_ to Elasticsearch. Action authorization restricts the actions -users can execute on the cluster. Shield implements authorization as Role Based Access Control (RBAC), where all -actions are restricted by default. Users are associated with roles that define a set of actions that are allowed -for those users. - -[[roles]] -[float] -=== Roles, Permissions and Privileges - -Privileges are actions or a set of actions that users may execute in Elasticsearch. For example, the ability to run a -query is a privilege. - -A permission is a set of privileges associated with one or more secured objects. For example, a permission could allow -querying or reading all documents of index `i1`. There are two types of secured objects in Elasticsearch - -cluster and indices. Cluster permissions grant access to cluster-wide administrative and monitoring actions. Index -permissions grant data access, including administrative and monitoring actions on specific indices in the cluster. - -A role is a named set of permissions. For example, you could define a role as a logging administrator. The logging -administrator is allowed to take all actions on indices named `logs-*`. - -As an administrator, you will need to define the roles that you want to use, then assign users to the roles. - -[[defining-roles]] -=== Defining Roles -Roles are defined in the role definition file `roles.yml` located in `CONFIG_DIR/shield`. -This is a YAML file where each entry defines the unique role name and the cluster and indices permissions associated -with it. - -[IMPORTANT] -============================== -The `roles.yml` file is managed locally by the node and is not managed globally by the cluster. This means that -with a typical multi-node cluster, the exact same changes need to be applied on each and every node in the cluster. - -A safer approach would be to apply the change on one of the nodes and have the `roles.yml` distributed/copied to -all other nodes in the cluster (either manually or using a configuration management system such as Puppet or Chef). -============================== - -The following snippet shows an example configuration: - -[source,yaml] ------------------------------------ -# All cluster rights -# All operations on all indices -admin: - cluster: all - indices: - '*': - privileges: all - -# Monitoring cluster privileges -# All operations on all indices -power_user: - cluster: monitor - indices: - '*': - privileges: all - -# Only read operations on indices -user: - indices: - '*': - privileges: read - -# Only read operations on indices named events_* -events_user: - indices: - 'events_*': - privileges: read ------------------------------------ - -[[valid-role-name]] -NOTE: A valid role name must be at least 1 character and no longer than 30 characters. It must begin with a letter - (`a-z`) or an underscore (`_`). Subsequent characters can be letters, underscores (`_`), digits (`0-9`) or any - of the following symbols `@`, `-`, `.` or `$` - - -The above example defines these roles: - -|======================= -| `admin` | Has full access (all privileges) on the cluster and full access on all indices in the cluster. -| `power_user` | Has monitoring-only access on the cluster, enabling the user to request cluster metrics, information, - and settings, without the ability to update settings. This user also has full access on all indices in - the cluster. -| `user` | Cannot update or monitor the cluster. Has read-only access to all indices in the cluster. -| `events_user` | Has read-only access to all indices with the `events_` prefix. -|======================= - -See the complete list of available <>. - - -=== Granting Privileges for Specific Actions - -The Shield security plugin enables access to specific actions in Elasticsearch. Access control using specific actions -provides a finer level of granularity than roles based on named privileges. - -The role in the following example allows access to document `GET` actions for a specific index and nothing else: - -.Example Role Using Action-level Access Control -[source,yaml] ---------------------------------------------------- -# Only GET read action on index named events_index -get_user: - indices: - 'events_index': - privileges: 'indices:data/read/get' ---------------------------------------------------- - -See the complete list of available <>. - -TIP: When specifying index names, you can use indices and aliases with their full names or regular expressions that - refer to multiple indices. - -* Wildcard (default) - simple wildcard matching where `*` is a placeholder for zero or more characters, `?` is a - placeholder for a single character and `\` may be used as an escape character. - -* Regular Expressions - A more powerful syntax for matching more complex patterns. This regular expression is based on - Lucene's regexp automaton syntax. To enable this syntax, it must be wrapped within a pair of forward slashes (`/`). - Any pattern starting with `/` and not ending with `/` is considered to be malformed. - -.Example Regular Expressions -[source,yaml] ------------------------------------------------------------------------------------- -"foo-bar": all # match the literal `foo-bar` -"foo-*": all # match anything beginning with "foo-" -"logstash-201?-*": all # ? matches any one character -"/.*-201[0-9]-.*/": all # use a regex to match anything containing 2010-2019 -"/foo": all # syntax error - missing final / ------------------------------------------------------------------------------------- - -TIP: Once the roles are defined, users can then be associated with any number of these roles. In -<> we'll learn more about authentication and see how users can be associated with the -configured roles. - -The privileges can also directly be set on an index expression. This notation is useful if no other security features -are configured. - -.Shorter privileges notation -[source,yaml] ---------------------------------------------------- -# Only GET read action on index named events_index -get_user: - indices: - 'events_index': 'indices:data/read/get' ---------------------------------------------------- - -include::granting-alias-privileges.asciidoc[] - -include::mapping-roles.asciidoc[] - -include::setting-up-field-and-document-level-security.asciidoc[] - -include::submitting-requests-for-other-users.asciidoc[] \ No newline at end of file diff --git a/shield/docs/public/example-deployments.asciidoc b/shield/docs/public/example-deployments.asciidoc deleted file mode 100644 index 12f01125446..00000000000 --- a/shield/docs/public/example-deployments.asciidoc +++ /dev/null @@ -1,6 +0,0 @@ -[[example-deployments]] -== Example Shield Deployments - -The examples in this section demonstrate how you might deploy Shield to secure an Elasticsearch cluster. - -include::example-deployments/e-commerce.asciidoc[] diff --git a/shield/docs/public/example-deployments/e-commerce.asciidoc b/shield/docs/public/example-deployments/e-commerce.asciidoc deleted file mode 100644 index 8469f210161..00000000000 --- a/shield/docs/public/example-deployments/e-commerce.asciidoc +++ /dev/null @@ -1,92 +0,0 @@ -[float] -[[example]] -=== E-commerce Example Using esusers - -The e-commerce store site in this example store has the following components: - -* A webshop application, which executes queries -* A nightly bulk import process, which reindexes the documents to ensure correct pricing for the following day -* A update mechanism that writes data concurrently during business hours on a per-document base -* A sales representative that needs to read sales-specific indices - -[float] -==== Defining the roles - -[source,yaml] --------------------------------------------------- -bulk: - indices: - 'products_*': write, manage, read - -updater: - indices: - 'products': index, delete, indices:admin/forcemerge - -webshop: - indices: - 'products': search, get - -monitoring: - cluster: monitor - indices: - '*': monitor - -sales_rep : - cluster : none - indices: - 'sales_*' : all - 'social_events' : data_access, monitor --------------------------------------------------- - -Let's step through each of the role definitions: - -* The `bulk` role definition has the privileges to create/delete all indices starting with `products_` as well as -indexing data into it. This set of privileges enables the user with this role to delete and repopulate a particular -index. - -* The `updater` role does not require any information about concrete indices. The only privileges required for updating -the `products` index are the `write` and `delete` privileges, as well as index optimization. - -* The `webshop` role is a read-only role that solely executes queries and GET requests. - -* The `monitoring` role extracts monitoring data for display on an internal screen of the web application. - -* The `sales_rep` role has write access on all indices starting with `sales` and read access to the `social_events` -index. - -[float] -==== Creating Users and Their Roles - -After creating the `roles.yml` file, you can use the `esusers` tool to create the needed users and the respective -user-to-role mapping. - -[source,shell] ------------------------------------------------------------ -bin/shield/esusers useradd webshop -r webshop,monitoring ------------------------------------------------------------ - -[source,shell] ------------------------------------------------------------ -bin/shield/esusers useradd bulk -r bulk ------------------------------------------------------------ - -[source,shell] ------------------------------------------------------------ -bin/shield/esusers useradd updater -r updater ------------------------------------------------------------ - -[source,shell] --------------------------------------------------------------------- -bin/shield/esusers useradd best_sales_guy_of_the_world -r sales_rep --------------------------------------------------------------------- - -[source,shell] ----------------------------------------------------------------------------- -bin/shield/esusers useradd second_best_sales_guy_of_the_world -r sales_rep ----------------------------------------------------------------------------- - -[float] -==== Modifying Your Application - -With the users and roles defined, you now need to modify your application. Each part of the application must -authenticate to Elasticsearch using the username and password you gave it in the previous steps. \ No newline at end of file diff --git a/shield/docs/public/getting-started.asciidoc b/shield/docs/public/getting-started.asciidoc deleted file mode 100644 index c1747c798d3..00000000000 --- a/shield/docs/public/getting-started.asciidoc +++ /dev/null @@ -1,56 +0,0 @@ -[[getting-started]] -== Getting Started with Shield - -This getting started guide walks you through installing Shield, setting up basic authentication, and getting started with role-based -access control. You can install Shield on nodes running Elasticsearch {version}. - -IMPORTANT: The Shield plugin must be installed on every node in the cluster. If you are installing -to a live cluster, you must stop all of the nodes, install Shield, and restart the nodes. You cannot -perform a rolling restart to install Shield. - -To install and run Shield: - -. Run `bin/plugin install` from `ES_HOME` to install the license plugin. -+ -[source,shell] ----------------------------------------------------------- -bin/plugin install license ----------------------------------------------------------- - -. Run `bin/plugin install` to install the Shield plugin. -+ -[source,shell] ----------------------------------------------------------- -bin/plugin install shield ----------------------------------------------------------- -+ -NOTE: If you are using a <> of Elasticsearch, you need to run the installation with superuser permissions. To perform an offline installation, <>. - -. Start Elasticsearch. -+ -[source,shell] ----------------------------------------------------------- -bin/elasticsearch ----------------------------------------------------------- - -. To verify that Shield is up and running, check the startup log entries. When Shield is operating -normally, the log indicates that the network transports are using Shield: -+ -[source,shell] ----------------- -[2014-10-09 13:47:38,841][INFO ][transport ] [Ezekiel Stane] Using [org.elasticsearch.shield.transport.ShieldServerTransportService] as transport service, overridden by [shield] -[2014-10-09 13:47:38,841][INFO ][transport ] [Ezekiel Stane] Using [org.elasticsearch.shield.transport.netty.ShieldNettyTransport] as transport, overridden by [shield] -[2014-10-09 13:47:38,842][INFO ][http ] [Ezekiel Stane] Using [org.elasticsearch.shield.transport.netty.ShieldNettyHttpServerTransport] as http transport, overridden by [shield] ----------------- - -Now you're ready to secure your cluster! Here are a few things -you might want to do to start with: - -* <> -* <> -* <> - -include::getting-started/enable-basic-auth.asciidoc[] -include::getting-started/enable-message-authentication.asciidoc[] -include::getting-started/enable-auditing.asciidoc[] -include::getting-started/moving-on.asciidoc[] diff --git a/shield/docs/public/getting-started/enable-auditing.asciidoc b/shield/docs/public/getting-started/enable-auditing.asciidoc deleted file mode 100644 index ba1a42cd799..00000000000 --- a/shield/docs/public/getting-started/enable-auditing.asciidoc +++ /dev/null @@ -1,17 +0,0 @@ -[[enable-auditing]] -=== Enable Auditing - -When you enable auditing, Shield stores a record of attempted and successful interactions with -your Elasticsearch cluster. You can use this information to keep track of who is doing what to -your cluster and identify potential security issues. - -To enable auditing, add the following setting to `elasticsearch.yml`: - -[source,yaml] ----------------------------- -shield.audit.enabled: true ----------------------------- - -By default, events are logged to a dedicated `elasticsearch-access.log` file in `ES_HOME/logs`. You can also store the events in an Elasticsearch index for easier analysis and control what events -are logged. For more information, see <>. - diff --git a/shield/docs/public/getting-started/enable-basic-auth.asciidoc b/shield/docs/public/getting-started/enable-basic-auth.asciidoc deleted file mode 100644 index 34a45e88d26..00000000000 --- a/shield/docs/public/getting-started/enable-basic-auth.asciidoc +++ /dev/null @@ -1,53 +0,0 @@ -[[enable-basic-auth]] -=== Control Access with Basic Authentication - -Shield makes it simple to password-protect your Elasticsearch cluster. Once Shield is installed, a username and password is required to communicate with the cluster. - -If you submit a request without a username and password, the request is rejected: - -[source,shell] ----------------------------------------------------------- -curl -XGET 'http://localhost:9200/' ----------------------------------------------------------- - -All you need to do to use basic authentication is set up users and assign them to one of the basic predefined roles: - -`admin` :: Can perform any cluster or index action. -`power_user` :: Can monitor the cluster and perform any index action. -`user` :: Can perform read actions on any index. - -To create a user and try out basic authentication: - -. Add a user called `es_admin` and assign the `admin` role. -+ -[source,shell] ----------------------------------------------------------- -bin/shield/esusers useradd es_admin -r admin ----------------------------------------------------------- - -. When prompted, enter a password for the new user. Passwords must be at least 6 characters long. - -. Submit a request using the newly-created user. -+ -[source,shell] ----------------------------------------------------------- -curl -u es_admin -XGET 'http://localhost:9200/' ----------------------------------------------------------- - -That's it! That's all it takes to set up the first layer of -security for your Elasticsearch cluster. However, Shield -offers much more that simple password protection. For example, -you can: - -* <> to verify that messages have not not been tampered with or corrupted in transit. -* <> to keep track of attempted and successful interactions with -your Elasticsearch cluster. - -And that's just the start. You can also: - -* <> for fine-grained access control. -* Integrate with <> or <>, or <> for authentication. -* Use <> to secure communications to and from nodes. -* Use <> to allow or deny requests from particular IP addresses or address ranges. - - diff --git a/shield/docs/public/getting-started/enable-message-authentication.asciidoc b/shield/docs/public/getting-started/enable-message-authentication.asciidoc deleted file mode 100644 index 83e407521ee..00000000000 --- a/shield/docs/public/getting-started/enable-message-authentication.asciidoc +++ /dev/null @@ -1,21 +0,0 @@ -[[enable-message-authentication]] -=== Enable Message Authentication - -Message authentication verifies that a message has not been tampered with or corrupted in transit. - -To enable message authentication: - -. Run the `syskeygen` tool from `ES_HOME` without any options: -+ -[source, shell] ----------------- -bin/shield/syskeygen ----------------- -+ -This creates a system key file in `CONFIG_DIR/shield/system_key`. - -. Copy the genererated system key to the rest of the nodes in the cluster. - -IMPORTANT: The system key is a symmetric key, so the same key must be on every node in the cluster. - -Now that you've enabled message authentication, you might also want to <> to keep track of attempted and successful interactions with your Elasticsearch cluster. diff --git a/shield/docs/public/getting-started/moving-on.asciidoc b/shield/docs/public/getting-started/moving-on.asciidoc deleted file mode 100644 index 500946f5e54..00000000000 --- a/shield/docs/public/getting-started/moving-on.asciidoc +++ /dev/null @@ -1,9 +0,0 @@ -[[moving-on]] -=== Moving On - -Now that you have Shield up and running, you might want to: - -* <> for fine-grained access control. -* Integrate with <> or <>, or <> for authentication. -* Use <> to secure communications to and from nodes. -* Use <> to allow or deny requests from particular IP addresses or address ranges. \ No newline at end of file diff --git a/shield/docs/public/granting-alias-privileges.asciidoc b/shield/docs/public/granting-alias-privileges.asciidoc deleted file mode 100644 index 797d50d47b8..00000000000 --- a/shield/docs/public/granting-alias-privileges.asciidoc +++ /dev/null @@ -1,101 +0,0 @@ -[[securing-aliases]] -=== Granting Privileges for Indices & Aliases - -Elasticsearch allows to execute operations against {ref}/indices-aliases.html[index aliases], -which are effectively virtual indices. An alias points to one or more indices, holds metadata and potentially a filter. -Shield treats aliases and indices the same. Privileges for indices actions are granted on specific indices or aliases. -In order for an indices action to be authorized by Shield, the user that executes it needs to have permissions for that -action on all the specific indices or aliases that the request relates to. - -Let's look at an example. Assuming we have an index called `2015`, an alias that points to it called `current_year`, -and a user with the following role: - -[source,yaml] --------------------------------------------------- -current_year_read: - indices: - '2015': read --------------------------------------------------- - -The user attempts to retrieve a document from `current_year`: - -[source,shell] -------------------------------------------------------------------------------- -curl -XGET 'localhost:9200/current_year/logs/1' -------------------------------------------------------------------------------- - -The above request gets rejected, although the user has read permissions on the concrete index that the `current_year` -alias points to. The correct permission would be as follows: - -[source,yaml] --------------------------------------------------- -current_year_read: - indices: - 'current_year': read --------------------------------------------------- - -[float] -==== Managing aliases - -Unlike creating indices, which requires `create_index` privilege, adding/removing/retrieving aliases requires -`manage_aliases` permission. Aliases can be added to an index directly as part of the index creation: - -[source,shell] -------------------------------------------------------------------------------- -curl -XPUT localhost:9200/2015 -d '{ - "aliases" : { - "current_year" : {} - } -}' -------------------------------------------------------------------------------- - -or via the dedicated aliases api if the index already exists: - -[source,shell] -------------------------------------------------------------------------------- -curl -XPOST 'http://localhost:9200/_aliases' -d ' -{ - "actions" : [ - { "add" : { "index" : "2015", "alias" : "current_year" } } - ] -}' -------------------------------------------------------------------------------- - -The above requests both require `manage_aliases` privilege on the alias name as well as the targeted index, as follows: - -[source,yaml] --------------------------------------------------- -admin: - indices: - '20*,current_year': create_index,manage_aliases --------------------------------------------------- - -Note also that the `manage` privilege includes both `create_index` and `manage_aliases` in addition to all of the other -management related privileges: - -[source,yaml] --------------------------------------------------- -admin: - indices: - '20*,current_year': manage --------------------------------------------------- - -The index aliases api allows also to delete aliases from existing indices, as follows. The privileges required for such -a request are the same as above. Both index and alias need the `manage_aliases` permission. - -[source,shell] -------------------------------------------------------------------------------- -curl -XPOST 'http://localhost:9200/_aliases' -d ' -{ - "actions" : [ - { "delete" : { "index" : "2015", "alias" : "current_year" } } - ] -}' -------------------------------------------------------------------------------- - -[float] -==== Filtered aliases - -Aliases can hold a filter, which allows to select a subset of documents that can be accessed out of all the documents that -the physical index contains. These filters are not always applied and should not be used -in place of <>. diff --git a/shield/docs/public/how-shield-works.asciidoc b/shield/docs/public/how-shield-works.asciidoc deleted file mode 100644 index f443909e686..00000000000 --- a/shield/docs/public/how-shield-works.asciidoc +++ /dev/null @@ -1,84 +0,0 @@ -[[how-shield-works]] -== How Shield Works - -Shield installs as a plugin into Elasticsearch. Once installed, the plugin intercepts inbound API calls in order to -enforce authentication and authorization. The plugin can also provide encryption using Secure Sockets Layer/Transport -Layer Security (SSL/TLS) for the network traffic to and from the Elasticsearch node. The plugin also uses the API -interception layer that enables authentication and authorization to provide audit logging capability. - - -[float] -=== User Authentication - -Shield defines a known set of users in order to authenticate users that make requests. These sets of users are defined -with an abstraction called a _realm_. A realm is a user database configured for the use of the Shield plugin. The -supported realms are _esusers_ and _LDAP_. - -In the _esusers_ realm, users exist exclusively within the Elasticsearch cluster. With the _esusers_ realm, the -administrator manages users with <>, and all the user operations occur within -the Elasticsearch cluster. Users authenticate with a username and password pair. - -In the _LDAP_ realm, the administrator manages users with the tools provided by the LDAP vendor. Elasticsearch -authenticates users by accessing the configured LDAP server. Users authenticate with a username and password pair. Shield -also enables mapping LDAP groups to roles in Shield (more on roles below). - -Your application can be a user in a Shield realm. Elasticsearch Clients authenticate to the cluster by providing a -username and password pair (a.k.a _Authentication Token_) with each request. To learn more on how different clients -can authenticate, see <>. - - -[float] -=== Authorization - -Shield's data model for action authorization consists of these elements: - -* _Secured Resource_, a resource against which security permissions are defined, including the cluster, an index/alias, - or a set of indices/aliases in the cluster - -* _Privilege_, one or more actions that a user may execute against a secured resource. This includes named groups of - actions (e.g. _read_), or a set specific actions (e.g. indices:/data/read/percolate) - -* _Permissions_, one or more privileges against a secured resource (e.g. _read on the "products" index_) - -* _Role_, named sets of permissions - -* _Users_, entities which may be assigned zero or more roles, authorizing them to perform the actions on the secure - resources described in the union of their roles - -A secure Elasticsearch cluster manages the privileges of users through <>. A role has a unique name and identifies -a set of permissions that translate to privileges on resources. A user can have an arbitrary number of roles. There are -two types of permissions: _cluster_ and _index_. The total set of permissions that a user has is defined by union of the -permissions in all its roles. - -Depending on the realm used, Shield provides the appropriate means to assign roles to users. - - -[float] -=== Node Authentication and Channel Encryption - -Nodes communicate to other nodes over port 9300. With Shield, you can use SSL/TLS to wrap this communication. When -SSL/TLS is enabled, the nodes validate each other's certificates, establishing trust between the nodes. This validation -prevents unauthenticated nodes from joining the cluster. Communications between nodes in the cluster are also encrypted -when SSL/TLS is in use. - -Users are responsible for generating and installing their own certificates. - -You can choose a variety of ciphers for encryption. See the <> -section for details. - -For more information on how to secure nodes see <>. - - -[float] -=== IP Filtering -Shield provides IP-based access control for Elasticsearch nodes. This access control allows you to restrict which -other servers, via their IP address, can connect to your Elasticsearch nodes and make requests. For example, you can -configure Shield to allow access to the cluster only from your application servers. The configuration provides for -whitelisting and blacklisting of subnets, specific IP addresses, and DNS domains. To read more about IP filtering see -<>. - - -[float] -=== Auditing -The <> in a secure Elasticsearch cluster logs particular events and activity on that -cluster. The events logged include authentication attempts, including granted and denied access. \ No newline at end of file diff --git a/shield/docs/public/index.asciidoc b/shield/docs/public/index.asciidoc deleted file mode 100644 index 59bb5f9652e..00000000000 --- a/shield/docs/public/index.asciidoc +++ /dev/null @@ -1,45 +0,0 @@ -[[shield]] - -= Shield Reference - -:ref: http://www.elastic.co/guide/en/elasticsearch/reference/2.0 -:ref-17: http://www.elastic.co/guide/en/elasticsearch/reference/1.7 - -:version: 2.1.0 - - -include::introduction.asciidoc[] - -include::getting-started.asciidoc[] - -include::how-shield-works.asciidoc[] - -include::installing-shield.asciidoc[] - -include::setting-up-authentication.asciidoc[] - -include::managing-users.asciidoc[] - -include::configuring-rbac.asciidoc[] - -include::configuring-auditing.asciidoc[] - -include::securing-communications.asciidoc[] - -include::configuring-clients-integrations.asciidoc[] - -include::managing-shield-licenses.asciidoc[] - -include::example-deployments.asciidoc[] - -include::reference.asciidoc[] - -include::limitations.asciidoc[] - -include::troubleshooting.asciidoc[] - -include::setting-up-certificate-authority.asciidoc[] - -include::release-notes.asciidoc[] - - diff --git a/shield/docs/public/installing-shield.asciidoc b/shield/docs/public/installing-shield.asciidoc deleted file mode 100644 index f00525bf26a..00000000000 --- a/shield/docs/public/installing-shield.asciidoc +++ /dev/null @@ -1,177 +0,0 @@ -[[installing-shield]] -== Installing Shield - -The <> steps through a basic Shield installation. This section provides some additional information about the installation prerequisites, deployment options, and the installation process for RPM/DEB package installations. - -IMPORTANT: The Shield plugin must be installed on every node in the cluster and every -node must be restarted after installation. Plan for a complete cluster restart before beginning the installation process. - -[float] -=== Shield Installation Prerequisites - -To install Shield {version}, you need: - -* Java 7 or later -* Elasticsearch {version} -* Elasticsearch License plugin {version} - -For information about installing the latest Oracle JDK, see http://www.oracle.com/technetwork/java/javase/downloads/index-jsp-138363.html[Java SE Downloads]. For information about installing Elasticsearch, see http://www.elastic.co/guide/en/elasticsearch/reference/current/_installation.html[Installation] in the Elasticsearch Reference. - -[float] -[[deb-rpm-install]] -=== Installing Shield on a DEB/RPM Package Installation - -If you use the DEB/RPM packages to install Elasticsearch, by default Elasticsearch is installed in -`/usr/share/elasticsearch` and the configuration files are stored in `/etc/elasticsearch`. (For the -complete list of default paths, see {ref}/setup-dir-layout.html#_deb_and_rpm[Directory Layout] in -the Elasticsearch Reference.) - -To install the Shield and License plugins on a DEB/RPM package installation, you need to run -`bin/plugin install` from the `/usr/share/elasticsearch` directory with superuser permissions. For example: - -[source,shell] ----------------------------------------------------------- -cd /usr/share/elasticsearch -sudo bin/plugin install license -sudo bin/plugin install shield ----------------------------------------------------------- - -[float] -[[offline-install]] -=== Installing Shield on Offline Machines - -Elasticsearch’s `bin/plugin` script requires direct Internet access to download and install the -License and Shield plugins. If your server doesn’t have Internet access, you can manually -download and install the plugins. - -To install Shield on a machine that doesn't have Internet access: - -. Manually download the appropriate License and Shield binaries: -** https://download.elastic.co/elasticsearch/release/org/elasticsearch/plugin/license/{version}/license-{version}.zip[ -https://download.elastic.co/elasticsearch/release/org/elasticsearch/plugin/license/{version}/license-{version}.zip] -** https://download.elastic.co/elasticsearch/release/org/elasticsearch/plugin/shield/{version}/shield-{version}.zip[ -https://download.elastic.co/elasticsearch/release/org/elasticsearch/plugin/shield/{version}/shield-{version}.zip] - -. Transfer the zip files to the offline machine. - -. Run `bin/plugin` with the `-u` option to install the plugins using the zip files. For example: -+ -[source,shell] ----------------------------------------------------------- -bin/plugin install file:///path/to/file/license-2.1.0.zip <1> -bin/plugin install file:///path/to/file/shield-2.1.0.zip ----------------------------------------------------------- -<1> Note that you must specify an absolute path to the zip file after the `file://` protocol. - -[float] -[[tribe-node]] -=== Installing Shield on Tribe Nodes - -Shield supports the {ref}/modules-tribe.html[Tribe Node], which acts as a federated client across multiple clusters. When using Tribe Nodes with Shield, you must have the same Shield configuration (users, roles, user-role mappings, SSL/TLS CA) on each cluster, and on the Tribe Node itself, where security checking is primarily done. This, of course, also means -that all clusters must be running Shield. - -To use a Tribe Node with Shield: - -. Configure the same privileges on all connected clusters. The Tribe Node has its own configuration and privileges, which need to grant access to actions and indices on all of the -connected clusters. Also, each cluster needs to grant access to indices belonging to other connected clusters as well. -+ -Let's look at an example: assuming we have two clusters, `cluster1` and `cluster2`, each one holding an index, `index1` -and `index2`. A search request that targets multiple clusters, as follows -+ -[source,shell] ------------------------------------------------------------ -curl -XGET tribe_node:9200/index1,index2/_search -u tribe_user:tribe_user ------------------------------------------------------------ -+ -requires `search` privileges for both `index1` and `index2` on the Tribe Node: -+ -[source,yaml] ------------------------------------------------------------ -tribe_user: - indices: - 'index*': search ------------------------------------------------------------ -+ -Also, the same privileges need to be granted on the connected clusters, meaning that `cluster1` has to grant access to -`index2` even though `index2` only exists on `cluster2`; the same requirement applies for `index1` on `cluster2`. This -applies to any indices action. As for cluster state read operations (e.g. cluster state api, get mapping api etc.), -they always get executed locally on the Tribe Node, to make sure that the merged cluster state gets returned; their -privileges are then required on the Tribe Node only. - -. Use the same system key on all clusters. For <> to properly work across multiple clusters, the Tribe Node -and all of the connected clusters need to share the same system key. - -. Enable encryption globally. Encrypted communication via SSL/TLS can only be enabled globally, meaning that either all of the connected clusters and the Tribe Node have SSL enabled, or none of them have. - -. Use the same certification authority on all clusters. When using encrypted communication, for simplicity, we recommend all of the connected clusters and the Tribe Node use -the same certification authority to generate their certificates. - -[float] -==== Tribe Node Example - -Let's see a complete example on how to use the Tribe Node with shield and the configuration required. First of all the -Shield and License plugins need to be installed and enabled on all clusters and on the Tribe Node. - -The system key needs to be generated on one node, as described in <>, -and then copied over to all of the other nodes in each cluster and the Tribe Node itself. - -Each cluster can have its own users with `admin` privileges that don't need to be present in the Tribe Node too. In fact, -administration tasks (e.g. create index) cannot be performed through the Tribe Node but need to be sent directly to the -corresponding cluster. The users that need to be created on Tribe Node are those that allow to get back data merged from -the different clusters through the Tribe Node itself. Let's for instance create as follows a `tribe_user` user, with -role `user`, that has `read` privileges on any index. - -[source,shell] ------------------------------------------------------------ -./bin/shield/esusers useradd tribe_user -p tribe_user -r user ------------------------------------------------------------ - -The above command needs to be executed on each cluster, since the same user needs to be present on the Tribe Node as well -as on every connected cluster. - -The following is the configuration required on the Tribe Node, that needs to be added to `elasticsearch.yml`. -Elasticsearch allows to list specific settings per cluster. We disable multicast discovery and configure the proper unicast discovery hosts for each cluster, -as well as their cluster names: - -[source,yaml] ------------------------------------------------------------ -tribe: - t1: - cluster.name: tribe1 - discovery.zen.ping.multicast.enabled: false - discovery.zen.ping.unicast.hosts: ["tribe1:9300"] - t2: - cluster.name: tribe2 - discovery.zen.ping.multicast.enabled: false - discovery.zen.ping.unicast.hosts: ["tribe2:9300"] ------------------------------------------------------------ - -The Tribe Node can then be started and once initialized it will be ready to accept requests like the following search, -which will return documents coming from the different connected clusters: - -[source,shell] ------------------------------------------------------------ -curl -XGET localhost:9200/_search -u tribe_user:tribe_user ------------------------------------------------------------ - -As for encrypted communication, the required settings are the same as described in <>, -but need to be specified per tribe as we did for discovery settings above. - -[float] -[[uninstalling-shield]] -=== Uninstalling Shield - -IMPORTANT: Uninstalling Shield requires a {ref}/restart-upgrade.html[full cluster restart]. - -To uninstall Shield: - -. Shut down Elasticsearch. - -. Remove the Shield plugin from Elasticsearch: -+ -[source,shell] ----------------------------------------------------------- -bin/plugin remove shield ----------------------------------------------------------- - -. Restart Elasticsearch. \ No newline at end of file diff --git a/shield/docs/public/introduction.asciidoc b/shield/docs/public/introduction.asciidoc deleted file mode 100644 index 8bfcfd74589..00000000000 --- a/shield/docs/public/introduction.asciidoc +++ /dev/null @@ -1,53 +0,0 @@ -[[introduction]] -== Introduction - -_Shield_ is a plugin for Elasticsearch that enables you to easily secure a cluster. With Shield, -you can password-protect your data as well as implement more advanced security measures such as encrypting communications, role-based access control, IP filtering, and auditing. This guide -describes how to install Shield, configure the security features you need, and interact with your secured cluster. - -[float] -=== Security for Elasticsearch - -Shield protects Elasticsearch clusters by: - -* <> with password protection, role-based access control, and IP filtering. -* <> with message authentication and SSL/TLS encryption. -* <> so you know who's doing what to your -data. - -[float] -[[preventing-unauthorized-access]] -==== Preventing Unauthorized Access - -To prevent unauthorized access to your Elasticsearch cluster, you must have a way to _authenticate_ users. This simply means that you need a way to validate that a user is who they claim to be. For example, you have to make sure only the person named _Kelsey Andorra_ can sign in as the user `kandorra`. Shield provides a standalone authentication mechanism that enables you to quickly <>. If you're already using <>, <>, or <>, Shield easily integrates with those systems to perform user authentication. - -In many cases, simply authenticating users isn't enough. You also need a way to control what data users have access to and what tasks they can perform. Shield enables you to _authorize_ users by -assigning access _privileges_ to a _role_, and assigning those roles to users. For example, this <> mechanism enables you to specify that the user `kandorra`can only perform read operations on the `events` index and can't do anything at all with other indices. - -Shield also supports <>. You can whitelist and blacklist specific IP addresses or subnets to control network-level access to a server. - -[float] -[[preserving-data-integrity]] -==== Preserving Data Integrity - -A critical part of security is keeping confidential data confidential. Elasticsearch has built-in protections against accidental data loss and corruption. However, there's nothing to stop deliberate tampering or data interception. Shield preserves the integrity of your data by <> to and from nodes and <> to verify that they have not been tampered with or corrupted in transit. For even greater protection, you can increase the <> and <>. - - -[float] -[[maintaining-audit-trail]] -==== Maintaining an Audit Trail - -Keeping a system secure takes vigilance. By using Shield to maintain an audit trail, you can easily see who is accessing your cluster and what they're doing. By analyzing access patterns and failed attempts to access your cluster, you can gain insights into attempted attacks and data breaches. Keeping an auditable log of the activity in your cluster can also help diagnose operational issues. - -[float] -=== Where to Go Next - -* <> steps through how to install and start using Shield for basic authentication. -* <> provides more information about how Shield supports user authentication, authorization, and encryption. -* <> shows you how to -interact with an Elasticsearch cluster protected by Shield. -* <> provides detailed information about the access privileges you can grant to users, the settings you can configure for Shield in `elasticsearch.yml`, and the files where Shield configuration information is stored. - -=== Have Comments, Questions, or Feedback? - -Head over to our https://discuss.elastic.co/c/shield[Shield Discussion Forum] to share your experience, questions, and suggestions. \ No newline at end of file diff --git a/shield/docs/public/limitations.asciidoc b/shield/docs/public/limitations.asciidoc deleted file mode 100644 index a07335bc21e..00000000000 --- a/shield/docs/public/limitations.asciidoc +++ /dev/null @@ -1,57 +0,0 @@ -[[limitations]] -== Limitations - -[float] -=== Plugins - -Elasticsearch's plugin infrastructure is extremely flexible in terms of what can be extended. While it opens up Elasticsearch -to a wide variety of (often custom) additional functionality, when it comes to security, this high extensibility level -comes at a cost. We have no control over the third-party plugins' code (open source or not) and therefore we cannot -guarantee their compliance with Shield. For this reason, third-party plugins are not officially supported on clusters -with the Shield security plugin installed. - -[float] -=== Changes in Index Wildcard Behavior - -Elasticsearch clusters with the Shield security plugin installed apply the `/_all` wildcard, and all other wildcards, -to the indices that the current user has privileges for, not the set of all indices on the cluster. There are two -notable results of this behavior: - -* Elasticsearch clusters with the Shield security plugin installed do not honor the `ignore_unavailable` option. - This behavior means that requests involving indices that the current user lacks authorization for throw an - `AuthorizationException` error, regardless of the option's setting. - -* The `allow_no_indices` option is ignored, resulting in the following behavior: when the final set of indices after - wildcard expansion and replacement is empty, the request throws a `IndexMissingException` error. - -As a general principle, core Elasticsearch will return empty results in scenarios where wildcard expansion returns no -indices, while Elasticsearch with Shield returns exceptions. Note that this behavior means that operations with -multiple items will fail the entire set of operations if any one operation throws an exception due to wildcard -expansion resulting in an empty set of authorized indices. - -[float] -=== Field and Document Level Security Limitations - -Bulk updates do not work when document and field level security is enabled. If you are not using document and field level -security, bulk updates can be enabled by setting `shield.dls_fls.enabled` to `false`. - -When document level security is enabled for an index: - -* The get, multi get, termsvector and multi termsvector APIs aren't executed in real time. The realtime option for these APIs is forcefully set to false. -* Document level security isn't applied for APIs that aren't document based. An example is the field stats API. -* Document level security doesn't affect global index statistics that relevancy scoring uses. So this means that scores are computed without taking the role query into account. - Note that documents not matching with the role query are never returned. -* The `has_child` and `has_parent` queries aren't supported as role query in the `roles.yml` file. - The `has_child` and `has_parent` queries can be used in the search API with document level security enabled. - -[float] -=== Document Expiration (_ttl) - -Document expiration handled using the built-in {ref}/mapping-ttl-field.html#mapping-ttl-field[`_ttl` (time to live) mechanism] -does not work with Shield. The document deletions will fail and the documents continue to live past their expiration. - -[float] -=== LDAP Realm - -The <> does not currently support the discovery of nested LDAP Groups. For example, if a user is a member -of GroupA and GroupA is a member of GroupB, only GroupA will be discovered. However, the <> _does_ support transitive group membership. diff --git a/shield/docs/public/managing-shield-licenses.asciidoc b/shield/docs/public/managing-shield-licenses.asciidoc deleted file mode 100644 index 052e03427ec..00000000000 --- a/shield/docs/public/managing-shield-licenses.asciidoc +++ /dev/null @@ -1,114 +0,0 @@ -[[license-management]] -== Managing Your License - -When you initially install Shield, a 30 day trial license is installed that allows access to all features. At the end of the trial period, you can https://www.elastic.co/subscriptions/[purchase a subscription] to keep using the full functionality of Shield along with Marvel and Watcher. - -IMPORTANT: When your license expires, Shield operates in a degraded mode where access to the Elasticsearch cluster health, cluster stats, and index stats APIs is blocked. Shield keeps on protecting your cluster, but you won't be able to monitor its operation until you update your license. For more information, see <>. - -[float] -[[installing-license]] -=== Updating Your License - -You can update your license at runtime without shutting down your nodes. License updates take -effect immediately. The license is provided as a _JSON_ file that you install with the `license` -API. You need cluster admin privileges to install the license. - -To update your license: - -. Send a request to the `license` API and specify the file that contains your new license: -+ -[source,shell] ------------------------------------------------------------------------ -curl -XPUT -u admin 'http://:/_license' -d @license.json ------------------------------------------------------------------------ -+ -Where: -+ -* `` is the hostname of the Elasticsearch node (`localhost` if executing locally) -* `` is the http port (defaults to `9200`) -* `license.json` is the license JSON file - -. If the license you are installing does not support all of the features available with your -previous license, you will be notified in the response. To complete the license installation, -you must resubmit the license update request and set the `acknowledge` parameter to `true` to -indicate that you are aware of the changes. -+ -[source,shell] ------------------------------------------------------------------------ -curl -XPUT -u admin 'http://:/_license?acknowledge=true' -d @license.json ------------------------------------------------------------------------ - -[float] -[[listing-licenses]] -=== Viewing the Installed License - -You can also use the `license` API to retrieve the currently installed license: - -[source,shell] ------------------------------------------------------ -curl -XGET -u admin:password 'http://:/_license' -{ - "license" : { - "status" : "active", - "uid" : "0a98411f-73f4-4c67-954c-724874ed5488", - "type" : "trial", - "issue_date" : "2015-10-13T18:18:20.709Z", - "issue_date_in_millis" : 1444760300709, - "expiry_date" : "2015-11-12T18:18:20.709Z", - "expiry_date_in_millis" : 1447352300709, - "max_nodes" : 1000, - "issued_to" : "elasticsearch", - "issuer" : "elasticsearch" - } -} --------------------------------------------- - -NOTE: You need cluster admin privileges to retrieve the license. - -[float] -[[license-expiration]] -=== License Expiration - -License expiration should never be a surprise. If you're using Marvel, a license expiration -warning is displayed prominently if your license expires within 30 days. Warnings are -also displayed on startup and written to the Elasticsearch log starting 30 days from the expiration date. These error messages tell you when the license expires and what features will be disabled if -you fail to update it: - -[source,sh] --------------------------------------------- -# License will expire on [Thursday, November 12, 2015]. If you have a new license, please update it. -# Otherwise, please reach out to your support contact. -# -# Commercial plugins operate with reduced functionality on license expiration: -# - marvel -# - The agent will stop collecting cluster and indices metrics -# - shield -# - Cluster health, cluster stats and indices stats operations are blocked -# - All data operations (read and write) continue to work --------------------------------------------- - -Once the license expires, calls to the cluster health, cluster stats, and index stats APIs -fail with a `ElasticsearchSecurityException` and return a 401 HTTP status code: - -[source,sh] --------------------------------------------- -{ - "error": { - "root_cause": [{ - "type": "security_exception", - "reason": "current license is non-compliant for [shield]", - "license.expired.feature": "shield" - }], - "type": "security_exception", - "reason": "current license is non-compliant for [shield]", - "license.expired.feature": "shield" - }, - "status": 401 -} --------------------------------------------- - -This enables automatic monitoring systems to easily detect the license failure without immediately impacting other users. - -IMPORTANT: You should update your license as soon as possible. You're essentially flying blind when running with an expired license. Access to the cluster health and stats APIs is critical -for monitoring and managing an Elasticsearch cluster. - diff --git a/shield/docs/public/managing-users.asciidoc b/shield/docs/public/managing-users.asciidoc deleted file mode 100644 index 335cdbb9462..00000000000 --- a/shield/docs/public/managing-users.asciidoc +++ /dev/null @@ -1,257 +0,0 @@ -[[managing-users]] -== Managing Users in an esusers Realm - -The `esusers` command line tool is located in `ES_HOME/bin/shield` and enables several -administrative tasks for managing users: - -* <> -* <> -* <> -* <> -* <> - -[float] -[[esusers-add]] -=== Adding Users - -The `esusers useradd` command adds a user to your cluster. - -NOTE: To ensure that Elasticsearch can read the user and role information at startup, run `esusers useradd` as the - same user you use to run Elasticsearch. Running the command as root or some other user will update the permissions - for the `users` and `users_roles` files and prevent Elasticsearch from accessing them. - -[source,shell] ----------------------------------------- -esusers useradd ----------------------------------------- - -A username must be at least 1 character and no longer than 30 characters. The first character must be a letter -(`a-z` or `A-Z`) or an underscore (`_`). Subsequent characters can be letters, underscores (`_`), digits (`0-9`), or any -of the following symbols `@`, `-`, `.` or `$` - -You can specify the user's password at the command line with the `-p` option. When this option is absent, the -`esusers` command prompts you for the password. Omit the `-p` option to keep plaintext passwords out of the terminal -session's command history. - -[source,shell] ----------------------------------------------------- -esusers useradd -p ----------------------------------------------------- - -Passwords must be at least 6 characters long. - -You can define a user's roles with the `-r` parameter. This parameter accepts a comma-separated list of role names to -associate with the user. - -[source,shell] -------------------------------------------------------------------- -esusers useradd -r -------------------------------------------------------------------- - -The following example adds a new user named `jacknich` to the _esusers_ realm. The password for this user is -`theshining`, and this user is associated with the `logstash` and `marvel` roles. - -[source,shell] ---------------------------------------------------------- -esusers useradd jacknich -p theshining -r logstash,marvel ---------------------------------------------------------- - -For valid role names please see <>. - -[float] -[[esusers-list]] -=== Listing Users -The `esusers list` command lists the users registered in the _esusers_ realm, as in the following example: - -[source, shell] ----------------------------------- -esusers list -rdeniro : admin -alpacino : power_user -jacknich : marvel,logstash ----------------------------------- - -Users are in the left-hand column and their corresponding roles are listed in the right-hand column. - -The `esusers list ` command lists a specific user. Use this command to verify that a user has been -successfully added to the cluster. - -[source,shell] ------------------------------------ -esusers list jacknich -jacknich : marvel,logstash ------------------------------------ - -[float] -[[esusers-pass]] -=== Managing User Passwords - -The `esusers passwd` command enables you to reset a user's password. You can specify the new password directly with the -`-p` option. When `-p` option is omitted, the tool will prompt you to enter and confirm a password in interactive mode. - -[source,shell] --------------------------------------------------- -esusers passwd --------------------------------------------------- - -[source,shell] --------------------------------------------------- -esusers passwd -p --------------------------------------------------- - -[float] -[[esusers-roles]] -=== Assigning Users to Roles - -The `esusers roles` command manages the roles associated to a particular user. The `-a` option adds a comma-separated -list of roles to a user. The `-r` option removes a comma-separated list of roles from a user. You can combine adding and -removing roles within the same command to change a user's roles. - -[source,shell] ------------------------------------------------------------------------------------------------------------- -esusers roles -a -r ------------------------------------------------------------------------------------------------------------- - -The following command removes the `logstash` and `marvel` roles from user `jacknich`, as well as adding the `user` role: - -[source,shell] ---------------------------------------------------------------- -esusers roles jacknich -r logstash,marvel -a user ---------------------------------------------------------------- - -Listing the user displays the new role assignment: - -[source,shell] ---------------------------------- -esusers list jacknich -jacknich : user ---------------------------------- - -[float] -[[esusers-del]] -=== Deleting Users - -The `esusers userdel` command deletes a user. - -[source,shell] --------------------------------------------------- -userdel --------------------------------------------------- - -[float] -=== About `esusers` - -The `esusers` tool manipulates two files, `users` and `users_roles`, in `CONFIG_DIR/shield/`. These two files store all user data for the _esusers_ realm and are read by Shield -on startup. - -By default, Shield checks these files for changes every 5 seconds. You can change this default behavior by changing the -value of the `watcher.interval.high` setting in the `elasticsearch.yml` file. - -[IMPORTANT] -============================== - -These files are managed locally by the node and are **not** managed -globally by the cluster. This means that with a typical multi-node cluster, -the exact same changes need to be applied on each and every node in the -cluster. - -A safer approach would be to apply the change on one of the nodes and have the -`users` and `users_roles` files distributed/copied to all other nodes in the -cluster (either manually or using a configuration management system such as -Puppet or Chef). - -============================== - -While it is possible to modify these files directly using any standard text -editor, we strongly recommend using the `esusers` command-line tool to apply -the required changes. - -[float] -[[users-file]] -==== The `users` File -The `users` file stores all the users and their passwords. Each line in the `users` file represents a single user entry -consisting of the username and **hashed** password. - -[source,bash] ----------------------------------------------------------------------- -rdeniro:$2a$10$BBJ/ILiyJ1eBTYoRKxkqbuDEdYECplvxnqQ47uiowE7yGqvCEgj9W -alpacino:$2a$10$cNwHnElYiMYZ/T3K4PvzGeJ1KbpXZp2PfoQD.gfaVdImnHOwIuBKS -jacknich:$2a$10$GYUNWyABV/Ols/.bcwxuBuuaQzV6WIauW6RdboojxcixBq3LtI3ni ----------------------------------------------------------------------- - -NOTE: The `esusers` command-line tool uses `bcrypt` to hash the password by default. - -[float] -[[users_defining-roles]] -==== The `users_roles` File - -The `users_roles` file stores the roles associated with the users, as in the following example: - -[source,shell] --------------------------------------------------- -admin:rdeniro -power_user:alpacino,jacknich -user:jacknich --------------------------------------------------- - -Each row maps a role to a comma-separated list of all the users that are associated with that role. - -[float] -[[user-cache]] -==== User Cache -The user credentials are not stored on disk in clear text. The esusers creates a `bcrypt` hashes of the passwords and -stores those. `bcrypt` is considered to be highly secured hash and by default it uses 10 rounds to generate the salts -it hashes with. While highly secured, it is also relatively slow. For this reason, Shield also introduce an in-memory -cache over the `esusers` store. This cache can use a different hashing algorithm for storing the passwords in memeory. -The default hashing algorithm that is used is `ssha256` - a salted SHA-256 algorithm. - -We've seen in the table <> that the cache characteristics can be configured. The following table -describes the different hash algorithm that can be set: - -[[esusers-cache-hash-algo]] - -.Cache hash algorithms -|======================= -| Algorithm | Description -| `ssha256` | Uses a salted `SHA-256` algorithm (default). -| `md5` | Uses `MD5` algorithm. -| `sha1` | Uses `SHA1` algorithm. -| `bcrypt` | Uses `bcrypt` algorithm with salt generated in 10 rounds. -| `bcrypt4` | Uses `bcrypt` algorithm with salt generated in 4 rounds. -| `bcrypt5` | Uses `bcrypt` algorithm with salt generated in 5 rounds. -| `bcrypt6` | Uses `bcrypt` algorithm with salt generated in 6 rounds. -| `bcrypt7` | Uses `bcrypt` algorithm with salt generated in 7 rounds. -| `bcrypt8` | Uses `bcrypt` algorithm with salt generated in 8 rounds. -| `bcrypt9` | Uses `bcrypt` algorithm with salt generated in 9 rounds. -| `noop`,`clear_text` | Doesn't hash the credentials and keeps it in clear text in memory. CAUTION: - keeping clear text is considered insecure and can be compromised at the OS - level (e.g. memory dumps and `ptrace`). -|======================= - -[float] -[[cache-eviction-api]] -==== Cache Eviction API -Shield exposes an API to force cached user eviction. The following example, evicts all users from the `esusers` -realm: - -[source, java] ------------------------------------------------------------- -$ curl -XPOST 'http://localhost:9200/_shield/realm/esusers/_cache/clear' ------------------------------------------------------------- - -NOTE: if no realm is defined, the default realm name, `default_esusers` can be used to clear the cache -of the default esusers realm. - -It is also possible to evict specific users: - -[source, java] ------------------------------------------------------------- -$ curl -XPOST 'http://localhost:9200/_shield/realm/esusers/_cache/clear?usernames=rdeniro,alpacino' ------------------------------------------------------------- - -Multiple realms can also be specified using comma-delimited list: - -[source, java] ------------------------------------------------------------- -$ curl -XPOST 'http://localhost:9200/_shield/realm/esusers,ldap1/_cache/clear' ------------------------------------------------------------- diff --git a/shield/docs/public/mapping-roles.asciidoc b/shield/docs/public/mapping-roles.asciidoc deleted file mode 100644 index c125a48d572..00000000000 --- a/shield/docs/public/mapping-roles.asciidoc +++ /dev/null @@ -1,61 +0,0 @@ -[[mapping-roles]] -=== Mapping Users and Groups to Roles - -If you authenticate users with an `esusers` realm, you can assign roles when you -<> and use the <> command to add or remove roles. - -For other types of realms, you configure role mappings for users and groups in a YAML file -and copy it to each node in the cluster. Tools like Puppet or Chef can help with this. - -By default, role mappings are stored in `CONF_DIR/shield/users/role_mapping.yml`, where `CONF_DIR` -is `ES_HOME/config` (zip/tar installations) or `/etc/elasticsearch` (package installations). -To specify a different location, you configure the `role_mapping` settings in `elasticsearch.yml`. -The `role_mapping` settings enable you to use a different set of mappings for each realm type: - - `shield.authc.ldap.files.role_mapping` :: The location of the role mappings for LDAP realms. - `shield.authc.active_directory.files.role_mapping` :: The location of the role mappings for Active Directory realms. - `shield.authc.pki.files.role_mapping` :: The location of the role mappings for PKI realms. - -IMPORTANT: For Shield to read the mapping file, it must be stored in the Elasticsearch `CONF_DIR`. - -Within the role mapping file, Shield roles are keys and groups and users are values. -The mappings can have a many-to-many relationship. When you map roles to groups, the roles of a -user in that group are the combination of the roles assigned to that group and the roles assigned -to that user. - -[[ad-role-mapping]] -The available roles are defined in the <>. To specify users and -groups in the role mappings, you use their _Distinguished Names_ (DNs). A DN -is a string that uniquely identifies the user or group, for example -`"cn=John Doe,cn=contractors,dc=example,dc=com"`. - -NOTE: Shield only supports Active Directory security groups. You cannot map distribution groups -to roles. - -[[ldap-role-mapping]] -For example, the following snippet maps the `admins` group to the `monitoring` role and maps -`John Doe`, the `users` group, and the `admins` group to the `user` role. - -[source, yaml] ------------------------------------------------------------- -monitoring: <1> - - "cn=admins,dc=example,dc=com" <2> -user: - - "cn=John Doe,cn=contractors,dc=example,dc=com" <3> - - "cn=users,dc=example,dc=com" - - "cn=admins,dc=example,dc=com" ------------------------------------------------------------- -<1> The name of a Shield role defined in the <>. -<2> The distinguished name of an LDAP group or an Active Directory security group. -<3> The distinguished name of an LDAP or Active Directory user. added[1.1.0] - -[[pki-role-mapping]] -PKI realms only support mapping users to roles, as there is no notion of a group in PKI. For example: - -[source, yaml] ------------------------------------------------------------- -monitoring: - - "cn=Admin,ou=example,o=com" -user: - - "cn=John Doe,ou=example,o=com" ------------------------------------------------------------- diff --git a/shield/docs/public/reference.asciidoc b/shield/docs/public/reference.asciidoc deleted file mode 100644 index 65fde4e4f52..00000000000 --- a/shield/docs/public/reference.asciidoc +++ /dev/null @@ -1,430 +0,0 @@ -[[reference]] -== Reference - -[[privileges-list]] - -[float] -=== Privileges - -[[privileges-list-cluster]] - -[float] -==== Cluster - -[horizontal] -`all`:: All cluster administration operations, like snapshotting, node shutdown/restart, settings update or rerouting -`monitor`:: All cluster read-ony operations, like cluster health & state, hot threads, node info, node & cluster -stats, snapshot/restore status, pending cluster tasks -`manage_shield`:: All Shield related operations (currently only exposing an API for clearing the realm caches) - -[[privileges-list-indices]] - -[float] -==== Indices - -[horizontal] -`all`:: Any action on an index -`manage`:: All `monitor` privileges plus index administration (aliases, analyze, cache clear, close, delete, exists, -flush, mapping, open, force merge, refresh, settings, search shards, templates, validate, warmers) -`monitor`:: All actions, that are required for monitoring and read-only (recovery, segments info, index stats & status) -`data_access`:: A shortcut of all of the below privileges -`crud`:: A shortcut of `read` and `write` privileges -`read`:: Read only access to actions (count, explain, get, mget, get indexed scripts, more like this, multi -percolate/search/termvector), percolate, scroll, clear_scroll, search, suggest, tv) -`search`:: All of `suggest` and executing an arbitrary search request (including multi-search API) -`get`:: Allow to execute a GET request for a single document or multiple documents via the multi-get API -`suggest`:: Allow to execute the `_suggest` API -`index`:: Privilege to index and update documents -`create_index`:: Privilege to create an index. A create index request may contain aliases to be added to the index once -created. In that case the request requires `manage_aliases` privilege as well, on both the index and the aliases names. -`manage_aliases`:: Privilege to add and remove aliases, as well as retrieve aliases information. Note that in order -to add an alias to an existing index, the `manage_aliases` privilege is required on the existing index as well as on the -alias name -`delete`:: Privilege to delete documents (includes delete by query) -`write`:: Privilege to index, update, delete, delete by query and bulk operations on documents, in addition to delete -and put indexed scripts - -[float] -==== Run As - -The `run_as` permission enables an authenticated user to submit requests on behalf of another -user. The value can be a user name or a comma-separated list of user names. (You can also specify -users as an array of strings or a YAML sequence.) For more information, -see <>. - -[horizontal] - -[[ref-actions-list]] - -[float] -==== Action level privileges - -Although rarely needed, it is also possible to define privileges on specific actions that are available in -Elasticsearch. This only applies to publicly available indices and cluster actions. - -[[ref-actions-list-cluster]] - -[float] -===== Cluster actions privileges - -* `cluster:admin/render/template/search` -* `cluster:admin/repository/delete` -* `cluster:admin/repository/get` -* `cluster:admin/repository/put` -* `cluster:admin/repository/verify` -* `cluster:admin/reroute` -* `cluster:admin/settings/update` -* `cluster:admin/snapshot/create` -* `cluster:admin/snapshot/delete` -* `cluster:admin/snapshot/get` -* `cluster:admin/snapshot/restore` -* `cluster:admin/snapshot/status` -* `cluster:admin/plugin/license/get` -* `cluster:admin/plugin/license/delete` -* `cluster:admin/plugin/license/put` -* `cluster:admin/shield/realm/cache/clear` -* `cluster:monitor/health` -* `cluster:monitor/nodes/hot_threads` -* `cluster:monitor/nodes/info` -* `cluster:monitor/nodes/stats` -* `cluster:monitor/state` -* `cluster:monitor/stats` -* `cluster:monitor/task` -* `indices:admin/template/delete` -* `indices:admin/template/get` -* `indices:admin/template/put` - -NOTE: While indices template actions typically relate to indices, they are categorized under cluster actions to avoid - potential security leaks. For example, having one user define a template that matches another user's index. - -[[ref-actions-list-indices]] - -[float] -===== Indices actions privileges - -* `indices:admin/aliases` -* `indices:admin/aliases/exists` -* `indices:admin/aliases/get` -* `indices:admin/analyze` -* `indices:admin/cache/clear` -* `indices:admin/close` -* `indices:admin/create` -* `indices:admin/delete` -* `indices:admin/get` -* `indices:admin/exists` -* `indices:admin/flush` -* `indices:admin/forcemerge` -* `indices:admin/mapping/put` -* `indices:admin/mappings/fields/get` -* `indices:admin/mappings/get` -* `indices:admin/open` -* `indices:admin/refresh` -* `indices:admin/settings/update` -* `indices:admin/shards/search_shards` -* `indices:admin/template/delete` -* `indices:admin/template/get` -* `indices:admin/template/put` -* `indices:admin/types/exists` -* `indices:admin/upgrade` -* `indices:admin/validate/query` -* `indices:admin/warmers/delete` -* `indices:admin/warmers/get` -* `indices:admin/warmers/put` -* `indices:monitor/recovery` -* `indices:monitor/segments` -* `indices:monitor/settings/get` -* `indices:monitor/shard_stores` -* `indices:monitor/stats` -* `indices:monitor/upgrade` -* `indices:data/read/explain` -* `indices:data/read/field_stats` -* `indices:data/read/get` -* `indices:data/read/mget` -* `indices:data/read/mpercolate` -* `indices:data/read/msearch` -* `indices:data/read/mtv` -* `indices:data/read/percolate` -* `indices:data/read/script/get` -* `indices:data/read/scroll` -* `indices:data/read/scroll/clear` -* `indices:data/read/search` -* `indices:data/read/suggest` -* `indices:data/read/tv` -* `indices:data/write/bulk` -* `indices:data/write/delete` -* `indices:data/write/index` -* `indices:data/write/script/delete` -* `indices:data/write/script/put` -* `indices:data/write/update` - -[[ref-shield-settings]] - -[float] -=== Shield Settings - -The parameters listed in this section are configured in the `config/elasticsearch.yml` configuration file. - -[[message-auth-settings]] - -.Shield Message Authentication Settings -[options="header"] -|====== -| Name | Default | Description -| `shield.system_key.file` |`CONFIG_DIR/shield/system_key` | Sets the <> of the `system_key` file. For more information, see <>. -|====== - -[[ref-anonymous-access]] - -.Shield Anonymous Access Settings added[1.1.0] -[options="header"] -|====== -| Name | Default | Description -| `shield.authc.anonymous.username` | `_es_anonymous_user` | The username/principal of the anonymous user (this setting is optional) -| `shield.authc.anonymous.roles` | - | The roles that will be associated with the anonymous user. This setting must be set to enable anonymous access. -| `shield.authc.anonymous.authz_exception` | `true` | When `true`, a HTTP 403 response will be returned when the anonymous user does not have the appropriate permissions for the requested action. The user will not be prompted to provide credentials to access the requested resource. When set to `false`, a HTTP 401 will be returned allowing for credentials to be provided for a user with the appropriate permissions. -|====== - -.Shield Document and Field Level Security Settings -[options="header"] -|====== -| Name | Default | Description -| `shield.dls_fls.enabled` | `false` | Set to `true` to enable document and field level security. -You cannot submit `_bulk` update requests when document and field level security is enabled. -|====== - - -[[ref-realm-settings]] - -[float] -==== Realm Settings - -All realms are configured under the `shield.authc.realms` settings, keyed by their names as follows: - -[source,yaml] ----------------------------------------- -shield.authc.realms: - - realm1: - type: esusers - order: 0 - ... - - realm2: - type: ldap - order: 1 - ... - - realm3: - type: active_directory - order: 2 - ... - ... ----------------------------------------- - -.Common Settings to All Realms -[options="header"] -|====== -| Name | Required | Default | Description -| `type` | yes | - | The type of the reamlm (currently `esusers`, `ldap` or `active_directory`) -| `order` | no | Integer.MAX_VALUE | The priority of the realm within the realm chain -| `enabled` | no | true | Enable/disable the realm -|====== - -[[ref-esusers-settings]] - -._esusers_ Realm -[options="header"] -|====== -| Name | Required | Default | Description -| `files.users` | no | `CONFIG_DIR/shield/users` | The <> of the <> file. -| `files.users_roles` | no | `CONFIG_DIR/shield/users_roles`| The <> of the <> file. -| `cache.ttl` | no | `20m` | The time-to-live for cached user entries--user credentials are cached for this configured period of time. Defaults to `20m`. Specify values using the standard Elasticsearch {ref}/common-options.html#time-units[time units]. -| `cache.max_users` | no | 100000 | The maximum number of user entries that can live in the cache at a given time. Defaults to 100,000. -| `cache.hash_algo` | no | `ssha256` | (Expert Setting) The hashing algorithm that is used for the in-memory cached user credentials. See the <> table for all possible values. -|====== - -[[ref-ldap-settings]] - -.Shield LDAP Settings -[options="header"] -|====== -| Name | Required | Default | Description -| `url` | yes | - | An LDAP URL in the format `ldap[s]://:`. -| `bind_dn` | no | Empty | The DN of the user that will be used to bind to the LDAP and perform searches. If this is not specified, an anonymous bind will be attempted. -| `bind_password` | no | Empty | The password for the user that will be used to bind to the LDAP. -| `user_dn_templates` | yes * | - | The DN template that replaces the user name with the string `{0}`. This element is multivalued, allowing for multiple user contexts. -| `user_group_attribute` | no | `memberOf` | Specifies the attribute to examine on the user for group membership. The default is `memberOf`. This setting will be ignored if any `group_search` settings are specified. -| `user_search.base_dn` | yes * | - | Specifies a container DN to search for users. -| `user_search.scope` | no | `sub_tree` | The scope of the user search. Valid values are `sub_tree`, `one_level` or `base`. `one_level` only searches objects directly contained within the `base_dn`. `sub_tree` searches all objects contained under `base_dn`. `base` specifies that the `base_dn` is the user object, and that it is the only user considered. -| `user_search.attribute` | no | `uid` | The attribute to match with the username presented to Shield. -| `user_search.pool.size` | no | `20` | The maximum number of connections to the LDAP server to allow in the connection pool. -| `user_search.pool.initial_size` | no | `5` | The initial number of connections to create to the LDAP server on startup. -| `user_search.pool.health_check.enabled` | no | `true` | Flag to enable or disable a health check on LDAP connections in the connection pool. Connections will be checked in the background at the specified interval. -| `user_search.pool.health_check.dn` | no | Value of `bind_dn` | The distinguished name to be retrieved as part of the health check. If `bind_dn` is not specified, a value must be specified. -| `user_search.pool.health_check.interval` | no | `60s` | The interval to perform background checks of connections in the pool. -| `group_search.base_dn` | no | - | The container DN to search for groups in which the user has membership. When this element is absent, Shield searches for the attribute specified by `user_group_attribute` set on the user in order to determine group membership. -| `group_search.scope` | no | `sub_tree` | Specifies whether the group search should be `sub_tree`, `one_level` or `base`. `one_level` only searches objects directly contained within the `base_dn`. `sub_tree` searches all objects contained under `base_dn`. `base` specifies that the `base_dn` is a group object, and that it is the only group considered. -| `group_search.filter` | no | See description | When not set, the realm will search for `group`, `groupOfNames`, or `groupOfUniqueNames`, with the attributes `member` or `memberOf`. Any instance of `{0}` in the filter will be replaced by the user attribute defined in `group_search.user_attribute` -| `group_search.user_attribute` | no | Empty | Specifies the user attribute that will be fetched and provided as a parameter to the filter. If not set, the user DN is passed into the filter. -| `unmapped_groups_as_roles` | no | false | Takes a boolean variable. When this element is set to `true`, the names of any unmapped LDAP groups are used as role names and assigned to the user. THe default value is `false`. -| `files.role_mapping` | no | `CONFIG_DIR/shield/users/role_mapping.yml` | The <> for the <>. -| `follow_referrals` | no | `true` | Boolean value that specifies whether Shield should follow referrals returned by the LDAP server. Referrals are URLs returned by the server that are to be used to continue the LDAP operation (e.g. search). -| `connect_timeout` | no | "5s" - for 5 seconds | The timeout period for establishing an LDAP connection. An `s` at the end indicates seconds, or `ms` indicates milliseconds. -| `read_timeout` | no | "5s" - for 5 seconds | The timeout period for an LDAP operation. An `s` at the end indicates seconds, or `ms` indicates milliseconds. -| `hostname_verification` | no | true | Performs hostname verification when using `ldaps` to protect against man in the middle attacks. -| `cache.ttl` | no | `20m` | Specified the time-to-live for cached user entries (a user and its credentials will be cached for this configured period of time). (use the standard Elasticsearch {ref}/common-options.html#time-units[time units]). -| `cache.max_users` | no | 100000 | Specified the maximum number of user entries that can live in the cache at a given time. -| `cache.hash_algo` | no | `ssha256` |(Expert Setting) Specifies the hashing algorithm that will be used for the in-memory cached user credentials (see <> table for all possible values). -|====== -NOTE: `user_dn_templates` is required to operate in user template mode and `user_search.base_dn` is required to operated in user search mode. Only one is required for a given realm configuration. For more information on the different modes, see <>. - -[[ref-ad-settings]] - -.Shield Active Directory Settings -[options="header"] -|====== -| Name | Required | Default | Description -| `url` | no | `ldap://:389` | A URL in the format `ldap[s]://:` If not specified the URL will be derived from the domain_name, assuming clear-text `ldap` and port `389` (e.g. `ldap://:389`). -| `domain_name` | yes | - | The domain name of Active Directory. The cluster can derive the URL and `user_search_dn` fields from values in this element if those fields are not otherwise specified. -| `unmapped_groups_as_roles` | no | false | Takes a boolean variable. When this element is set to `true`, the names of any unmapped groups and the user's relative distinguished name are used as role names and assigned to the user. THe default value is `false`. -| `files.role_mapping` | no | `CONFIG_DIR/shield/users/role_mapping.yml` | The <> for the <>. -| `user_search.base_dn` | no | Root of Active Directory | The context to search for a user. The default value for this element is the root of the Active Directory domain. -| `user_search.scope` | no | `sub_tree` | Specifies whether the user search should be `sub_tree`, `one_level` or `base`. `one_level` only searches users directly contained within the `base_dn`. `sub_tree` searches all objects contained under `base_dn`. `base` specifies that the `base_dn` is a user object, and that it is the only user considered. -| `user_search.filter` | no | See description | Specifies a filter to use to lookup a user given a username. The default filter looks up `user` objects with either `sAMAccountName` or `userPrincipalName` -| `group_search.base_dn` | no | Root of Active Directory | The context to search for groups in which the user has membership. The default value for this element is the root of the the Active Directory domain -| `group_search.scope` | no | `sub_tree` | Specifies whether the group search should be `sub_tree`, `one_level` or `base`. `one_level` searches for groups directly contained within the `base_dn`. `sub_tree` searches all objects contained under `base_dn`. `base` specifies that the `base_dn` is a group object, and that it is the only group considered. -| `timeout.tcp_connect` | no | `5s` - for 5 seconds | The TCP connect timeout period for establishing an LDAP connection. An `s` at the end indicates seconds, or `ms` indicates milliseconds. -| `timeout.tcp_read` | no | `5s` - for 5 seconds | The TCP read timeout period after establishing an LDAP connection. An `s` at the end indicates seconds, or `ms` indicates milliseconds. -| `timeout.ldap_search` | no | `5s` - for 5 seconds | The LDAP Server enforced timeout period for an LDAP search. An `s` at the end indicates seconds, or `ms` indicates milliseconds. -| `hostname_verification` | no | true | Performs hostname verification when using `ldaps` to protect against man in the middle attacks. -| `cache.ttl` | no | `20m` | Specified the time-to-live for cached user entries (a user and its credentials will be cached for this configured period of time). (use the standard Elasticsearch {ref}/common-options.html#time-units[time units]). -| `cache.max_users` | no | 100000 | Specified the maximum number of user entries that can live in the cache at a given time. -| `cache.hash_algo` | no | `ssha256` |(Expert Setting) Specifies the hashing algorithm that will be used for the in-memory cached user credentials (see <> table for all possible values). -|====== - -[[ref-pki-settings]] - -.Shield PKI Settings -[options="header"] -|====== -| Name | Required | Default | Description -| `username_pattern` | no | `CN=(.*?)(?:,\|$)` | The regular expression pattern used to extract the username from the certificate DN. The first match group is the used as the username. Default is `CN=(.*?)(?:,\|$)` -| `truststore.path` | no | `shield.ssl.keystore` | The path of a truststore to use. The default truststore is the one defined by <> -| `truststore.password` | no | - | The password to the truststore. Must be provided if `truststore.path` is set. -| `truststore.algorithm` | no | SunX509 | Algorithm for the trustsore. Default is `SunX509` -| `files.role_mapping` | no | `CONFIG_DIR/shield/users/role_mapping.yml` | Specifies the <> for the <>. -|====== - -[[ref-cache-hash-algo]] -.Cache hash algorithms -|======================= -| Algorithm | Description -| `ssha256` | Uses a salted `SHA-256` algorithm (default). -| `md5` | Uses `MD5` algorithm. -| `sha1` | Uses `SHA1` algorithm. -| `bcrypt` | Uses `bcrypt` algorithm with salt generated in 10 rounds. -| `bcrypt4` | Uses `bcrypt` algorithm with salt generated in 4 rounds. -| `bcrypt5` | Uses `bcrypt` algorithm with salt generated in 5 rounds. -| `bcrypt6` | Uses `bcrypt` algorithm with salt generated in 6 rounds. -| `bcrypt7` | Uses `bcrypt` algorithm with salt generated in 7 rounds. -| `bcrypt8` | Uses `bcrypt` algorithm with salt generated in 8 rounds. -| `bcrypt9` | Uses `bcrypt` algorithm with salt generated in 9 rounds. -| `noop`,`clear_text` | Doesn't hash the credentials and keeps it in clear text in memory. CAUTION: - keeping clear text is considered insecure and can be compromised at the OS - level (e.g. memory dumps and `ptrace`). -|======================= - -[[ref-roles-settings]] - -.Shield Roles Settings -[options="header"] -|====== -| Name | Default | Description -| `shield.authz.store.file.roles` | `CONFIG_DIR/shield/users/roles.yml` | The <> of the roles definition file. -|====== - -[[ref-ssl-tls-settings]] - -[float] -==== TLS/SSL Settings - -.Shield TLS/SSL Settings -[options="header"] -|====== -| Name | Default | Description -| `shield.ssl.keystore.path` | None | Absolute path to the keystore that holds the private keys -| `shield.ssl.keystore.password` | None | Password to the keystore -| `shield.ssl.keystore.key_password` | Same value as `shield.ssl.keystore.password` | Password for the private key in the keystore -| `shield.ssl.keystore.algorithm` | SunX509 | Format for the keystore -| `shield.ssl.truststore.path` | `shield.ssl.keystore.path` | If not set, this setting defaults to `shield.ssl.keystore` -| `shield.ssl.truststore.password` | `shield.ssl.keystore.password` | Password to the truststore -| `shield.ssl.truststore.algorithm` | SunX509 | Format for the truststore -| `shield.ssl.protocol` | `TLSv1.2` | Protocol for security: `SSL`, `SSLv2`, `SSLv3`, `TLS`, `TLSv1`, `TLSv1.1`, `TLSv1.2` -| `shield.ssl.supported_protocols` | `TLSv1`, `TLSv1.1`, `TLSv1.2` | Supported protocols with versions. Valid protocols: `SSLv2Hello`, `SSLv3`, `TLSv1`, `TLSv1.1`, `TLSv1.2` -| `shield.ssl.ciphers` | `TLS_RSA_WITH_AES_128_CBC_SHA256`, `TLS_RSA_WITH_AES_128_CBC_SHA`, `TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA` | Supported cipher suites can be found in Oracle's http://docs.oracle.com/javase/7/docs/technotes/guides/security/SunProviders.html[Java Cryptography Architecture documentation]. Cipher suites using key lengths greater than 128 bits require the <>. -| `shield.ssl.hostname_verification` | `true` | Performs hostname verification on transport connections. This is enabled by default to protect against man in the middle attacks. -| `shield.ssl.hostname_verification.resolve_name` | `true` | A reverse DNS lookup is necessary to find the hostname when connecting to a node via an IP Address. If this is disabled and IP addresses are used to connect to a node, the IP address must be specified as a `SubjectAlternativeName` when <> or hostname verification will fail. IP addresses will be used to connect to a node if they are used in following settings: `network.host`, `network.publish_host`, `transport.publish_host`, `transport.profiles.$PROFILE.publish_host`, `discovery.zen.ping.unicast.hosts` -| `shield.ssl.session.cache_size` | `1000` | Number of SSL Sessions to cache in order to support session resumption. Setting the value to `0` means there is no size limit. -| `shield.ssl.session.cache_timeout` | `24h` | The time after the creation of a SSL session before it times out. (uses the standard Elasticsearch {ref}/common-options.html#time-units[time units]). -| `shield.transport.ssl` | `false` | Set this parameter to `true` to enable SSL/TLS -| `shield.transport.ssl.client.auth` | `required` | Require client side certificates for transport protocol. Valid values are `required`, `optional`, and `no`. `required` forces a client to present a certificate, while `optional` requests a client certificate but the client is not required to present one. -| `shield.transport.filter.allow` | None | List of IP addresses to allow -| `shield.transport.filter.deny` | None | List of IP addresses to deny -| `shield.http.ssl` | `false` | Set this parameter to `true` to enable SSL/TLS -| `shield.http.ssl.client.auth` | `no` | Require client side certificates for HTTP. Valid values are `required`, `optional`, and `no`. `required` forces a client to present a certificate, while `optional` requests a client certificate but the client is not required to present one. -| `shield.http.filter.allow` | None | List of IP addresses to allow just for HTTP -| `shield.http.filter.deny` | None | List of IP addresses to deny just for HTTP -|====== - -[[ref-ssl-tls-profile-settings]] - -.Shield TLS/SSL settings per profile -[options="header"] -|====== -| Name | Default | Description -| `transport.profiles.$PROFILE.shield.ssl` | Same as `shield.transport.ssl`| Setting this parameter to true will enable SSL/TLS for this profile; false will disable SSL/TLS for this profile. -| `transport.profiles.$PROFILE.shield.truststore.path` | None | Absolute path to the truststore of this profile -| `transport.profiles.$PROFILE.shield.truststore.password` | None | Password to the truststore -| `transport.profiles.$PROFILE.shield.truststore.algorithm` | SunX509 | Format for the truststore -| `transport.profiles.$PROFILE.shield.keystore.path` | None | Absolute path to the keystore of this profile -| `transport.profiles.$PROFILE.shield.keystore.password` | None | Password to the keystore -| `transport.profiles.$PROFILE.shield.keystore.key_password` | Same value as `transport.profiles.$PROFILE.shield.keystore.password` | Password for the private key in the keystore -| `transport.profiles.$PROFILE.shield.keystore.algorithm` | SunX509 | Format for the keystore -| `transport.profiles.$PROFILE.shield.session.cache_size` | `1000` | Number of SSL Sessions to cache in order to support session resumption. Setting the value to `0` means there is no size limit. -| `transport.profiles.$PROFILE.shield.session.cache_timeout` | `24h` | The time after the creation of a SSL session before it times out. (uses the standard Elasticsearch {ref}/common-options.html#time-units[time units]). -| `transport.profiles.$PROFILE.shield.filter.allow` | None | List of IP addresses to allow for this profile -| `transport.profiles.$PROFILE.shield.filter.deny` | None | List of IP addresses to deny for this profile -| `transport.profiles.$PROFILE.shield.ssl.client.auth` | `required` | Require client side certificates. Valid values are `required`, `optional`, and `no`. `required` forces a client to present a certificate, while `optional` requests a client certificate but the client is not required to present one. -| `transport.profiles.$PROFILE.shield.type` | `node` | Defines allowed actions on this profile, allowed values: `node` and `client` -| `transport.profiles.$PROFILE.shield.ciphers` | `TLS_RSA_WITH_AES_128_CBC_SHA256`, `TLS_RSA_WITH_AES_128_CBC_SHA`, `TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA` | Supported cipher suites can be found in Oracle's http://docs.oracle.com/javase/7/docs/technotes/guides/security/SunProviders.html[Java Cryptography Architecture documentation]. Cipher suites using key lengths greater than 128 bits require the <>. -| `transport.profiles.$PROFILE.shield.protocol` | `TLSv1.2` | Protocol for security: `SSL`, `SSLv2`, `SSLv3`, `TLS`, `TLSv1`, `TLSv1.1`, `TLSv1.2` -| `transport.profiles.$PROFILE.shield.supported_protocols` | `TLSv1`, `TLSv1.1`, `TLSv1.2` | Supported protocols with versions. Valid protocols: `SSLv2Hello`, `SSLv3`, `TLSv1`, `TLSv1.1`, `TLSv1.2` -|====== - -[[ref-shield-files]] - -[float] -=== Files used by Shield - -The Shield security plugin uses the following files: - -* `CONFIG_DIR/shield/roles.yml` defines the roles in use on the cluster (read more <>). -* `CONFIG_DIR/shield/users` defines the hashed passwords for users on the cluster (read more <>). -* `CONFIG_DIR/shield/users_roles` defines the role assignments for users on the cluster (read more <>). -* `CONFIG_DIR/shield/role_mapping.yml` defines the role assignments for a Distinguished Name (DN) to a role. This allows for -LDAP and Active Directory groups and users and PKI users to be mapped to roles (read more <>). -* `CONFIG_DIR/shield/logging.yml` contains audit information (read more <>). -* `CONFIG_DIR/shield/system_key` holds a cluster secret key used for message authentication. For more information, see <>. - -[[ref-shield-files-location]] -IMPORTANT: Any files that Shield uses must be stored in the Elasticsearch {ref}/setup-dir-layout.html#setup-dir-layout[configuration directory]. -Elasticsearch runs with restricted permissions and is only permitted to read from the locations configured in the directory -layout for enhanced security. - -Several of these files are in the YAML format. When you edit these files, be aware that YAML is indentation-level -sensitive and indentation errors can lead to configuration errors. Avoid the tab character to set indentation levels, -or use an editor that automatically expands tabs to spaces. - -Be careful to properly escape YAML constructs such as `:` or leading exclamation points within quoted strings. Using -the `|` or `>` characters to define block literals instead of escaping the problematic characters can help avoid -problems. diff --git a/shield/docs/public/release-notes.asciidoc b/shield/docs/public/release-notes.asciidoc deleted file mode 100644 index 4512f716fde..00000000000 --- a/shield/docs/public/release-notes.asciidoc +++ /dev/null @@ -1,230 +0,0 @@ -[[release-notes]] -== Release Notes - -[float] -[[version-compatibility]] -=== Version Compatibility - -You must run the version of Shield that matches the version of Elasticsearch you are running. For -example, Shield {version} requires Elasticsearch {version}. - -[float] -[[upgrade-instructions]] -=== Upgrading Shield - -To upgrade Shield, just uninstall the current Shield plugin and install the new version of Shield. Your configuration -will be preserved and you do this with a rolling upgrade of Elasticsearch when upgrading to a new minor version; a full -cluster restart is required when upgrading from Elasticsearch 1.x. On each node, after you have stopped it run: - -[source,shell] ---------------------------------------------------- -bin/plugin remove shield -bin/plugin install shield ---------------------------------------------------- - -Then start the node. Larger sites should follow the steps in the {ref}/rolling-upgrades.html[rolling upgrade section] -to ensure recovery is as quick as possible. - -On upgrade, your current configuration files will remain untouched. The configuration files provided by the new version -of Shield will be added with a `.new` extension. - -[float] -==== Updated Role Definitions -The default role definitions in the `roles.yml` file may need to be changed to ensure proper functionality with other -applications such as Marvel and Kibana. Any role changes will be found in `roles.yml.new` after upgrading to the new -version of Shield. We recommend copying the changes listed below to your `roles.yml` file. - -* added[2.0.0] The permission on all the roles are updated to the verbose format to make it easier to enable field level and document level security. The `transport_client` role has been updated to work with Elasticsearch 2.0.0. - The `marvel_user` role has been updated to work with Marvel 2.0 and a `remote_marvel_agent` role has been added. The `kibana3` and `marvel_agent` roles have been removed. -* added[1.1.0] `kibana4_server` role added that defines the minimum set of permissions necessary for the Kibana 4 server. -* added[1.0.1] `kibana4` role updated to work with new features in Kibana 4 RC1 - -[float] -[[changelist]] -=== Change List - -[float] -==== 2.1.0 -November 24, 2015 - -.Breaking Changes -* Same as 2.0.1. <> is now disabled by default. Set `shield.dls_fls.enabled` to `true` in `elasticsearch.yml` to enable it. You cannot submit `_bulk` update requests when document and field level security is enabled. - -.Enhancements -* Adds support for Elasticsearch 2.1.0. - -[float] -==== 2.0.1 -November 24, 2015 - -.Breaking Changes -* <> is now disabled by default. Set `shield.dls_fls.enabled` to `true` in `elasticsearch.yml` to enable it. You cannot submit `_bulk` update requests when document and field level security is enabled. - -.Enhancement -* Adds support for Elasticsearch 2.0.1. - -[float] -==== 2.0.0 -October 28, 2015 - -.Breaking Changes -* All files that Shield uses must be kept in the <> due to the enhanced security of Elasticsearch 2.0. -* The network format has been changed from all previous versions of Shield and a full cluster restart is required to upgrade to Shield 2.0. - -.New Features -* <> support has been added and can be -configured per role. -* Support for <> has been added, allowing Shield to integrate with more authentication sources and methods. -* <> has also been added, which allows a user to send a request to elasticsearch that will be run -with the specified user's permissions. - -.Bug Fixes -* <> now captures requests from nodes using a different system key as tampered requests. -* The <> stores the type of request when available. -* `esusers` and `syskeygen` work when spaces are in the elasticsearch installation path. -* Fixed a rare issue where authentication fails even when the username and password are correct. - -[float] -==== 1.3.3 - -.Bug Fixes -* Fixed a rare issue where authentication fails even when the username and password are correct. -* The <> stores the type of request when available. - -.Enhancements -* Tampered requests with a bad header are now audited. - -[float] -==== 1.3.2 -August 10, 2015 - -.Bug Fixes -* When using the <> mechanism, connection errors during startup no longer cause the node to stop. -* The <> no longer generates invalid JSON. -* The <> starts properly when forwarding the audit events to a remote cluster and uses -the correct user to index the audit events. - -[float] -==== 1.3.1 -July 21, 2015 - -.Bug Fixes -* Fixes <> serialization to work with Shield 1.2.1 and earlier. -** NOTE: if you are upgrading from Shield 1.3.0 or Shield 1.2.2 a {ref-17}/setup-upgrade.html#restart-upgrade[cluster restart upgrade] -will be necessary. When upgrading from other versions of Shield, follow the normal <>. - -[float] -==== 1.3.0 -June 24, 2015 - -.Breaking Changes -* The `sha2` and `apr1` hashing algorithms have been removed as options for the <>. - If your existing Shield installation uses either of these options, remove the setting and use the default `ssha256` - algorithm. -* The `users` file now only supports `bcrypt` password hashing. All existing passwords stored using the `esusers` tool - have been hashed with `bcrypt` and are not affected. - -.New Features -* <>: Adds Public Key Infrastructure (PKI) authentication through the use of X.509 certificates in place of - username and password credentials. -* <>: An index based output has been added for storing audit events in an Elasticsearch index. - -.Enhancements -* TLS 1.2 is now the default protocol. -* Clients that do not support pre-emptive basic authentication can now support both anonymous and authenticated access - by specifying the `shield.authc.anonymous.authz_exception` <> with a value of `false`. -* Reduced logging for common SSL exceptions, such as a client closing the connection during a handshake. - -.Bug Fixes -* The `esusers` and `syskeygen` tools now work correctly with environment variables in the RPM and DEB installation - environment files `/etc/sysconfig/elasticsearch` and `/etc/default/elasticsearch`. -* Default ciphers no longer include `TLS_DHE_RSA_WITH_AES_128_CBC_SHA`. - -[float] -==== 1.2.3 -July 21, 2015 - -.Bug Fixes -* Fixes <> serialization to work with Shield 1.2.1 and earlier. -** NOTE: if you are upgrading from Shield 1.2.2 a {ref-17}/setup-upgrade.html#restart-upgrade[cluster restart upgrade] -will be necessary. When upgrading from other versions of Shield, follow the normal <>. - -[float] -==== 1.2.2 -June 24, 2015 - -.Bug Fixes -* The `esusers` tool no longer warns about missing roles that are properly defined in the `roles.yml` file. -* The period character, `.`, is now allowed in usernames and role names. -* The {ref-17}/query-dsl-terms-filter.html#_caching_19[terms filter lookup cache] has been disabled to ensure all requests - are properly authorized. This removes the need to manually disable the terms filter cache. -* For LDAP client connections, only the protocols and ciphers specified in the `shield.ssl.supported_protocols` and - `shield.ssl.ciphers` <> will be used. -* The auditing mechanism now logs authentication failed events when a request contains an invalid authentication token. - -[float] -==== 1.2.1 -April 29, 2015 - -.Bug Fixes -* Several bug fixes including a fix to ensure that {ref}/disk.html[Disk-based Shard Allocation] -works properly with Shield - -[float] -==== 1.2.0 -March 24, 2015 - -.Enhancements -* Adds support for Elasticsearch 1.5 - -[float] -==== 1.1.1 -April 29, 2015 - -.Bug Fixes -* Several bug fixes including a fix to ensure that {ref}/disk.html[Disk-based Shard Allocation] -works properly with Shield - -[float] -==== 1.1.0 -March 24, 2015 - -.New Features -* LDAP: -** Add the ability to bind as a specific user for LDAP searches, which removes the need to specify `user_dn_templates`. -This mode of operation also makes use of connection pooling for better performance. Please see <> -for more information. -** User distinguished names (DNs) can now be used for <>. -* Authentication: -** <> is now supported (disabled by default). -* IP Filtering: -** IP Filtering settings can now be <> using the {ref}/cluster-update-settings.html[Cluster Update Settings API]. - -.Enhancements -* Significant memory footprint reduction of internal data structures -* Test if SSL/TLS ciphers are supported and warn if any of the specified ciphers are not supported -* Reduce the amount of logging when a non-encrypted connection is opened and `https` is being used -* Added the <>, which is a role that contains the minimum set of permissions required for the Kibana 4 server. -* In-memory user credential caching hash algorithm defaults now to salted SHA-256 (see <> - -.Bug Fixes -* Filter out sensitive settings from the settings APIs - -[float] -==== 1.0.2 -March 24, 2015 - -.Bug Fixes -* Filter out sensitive settings from the settings APIs -* Significant memory footprint reduction of internal data structures - -[float] -==== 1.0.1 -February 13, 2015 - -.Bug Fixes -* Fixed dependency issues with Elasticsearch 1.4.3 and (Lucene 4.10.3 that comes with it) -* Fixed bug in how user roles were handled. When multiple roles were defined for a user, and one of the - roles only had cluster permissions, not all privileges were properly evaluated. -* Updated `kibana4` permissions to be compatible with Kibana 4 RC1 -* Ensure the mandatory `base_dn` settings is set in the `ldap` realm configuration diff --git a/shield/docs/public/securing-communications.asciidoc b/shield/docs/public/securing-communications.asciidoc deleted file mode 100644 index 4e11083d15d..00000000000 --- a/shield/docs/public/securing-communications.asciidoc +++ /dev/null @@ -1,19 +0,0 @@ -[[securing-communications]] -== Securing Communications with Encryption and IP Filtering - -Elasticsearch nodes store data that may be confidential. Attacks on the data may come from the network. These attacks -could include sniffing of the data, manipulation of the data, and attempts to gain access to the server and thus the -files storing the data. Securing your nodes with the procedures below helps to reduce risk from network-based attacks. - -This section shows how to: - -* Encrypt traffic to and from Elasticsearch nodes using SSL/TLS, -* Require that nodes authenticate new nodes that join the cluster using SSL certificates, and -* Make it more difficult for remote attackers to issue any commands to Elasticsearch. - -The authentication of new nodes helps prevent a rogue node from joining the cluster and receiving data through replication. - -include::securing-communications/setting-up-ssl.asciidoc[] -include::securing-communications/enabling-cipher-suites.asciidoc[] -include::securing-communications/separating-node-client-traffic.asciidoc[] -include::securing-communications/using-ip-filtering.asciidoc[] diff --git a/shield/docs/public/securing-communications/enabling-cipher-suites.asciidoc b/shield/docs/public/securing-communications/enabling-cipher-suites.asciidoc deleted file mode 100644 index acefe147696..00000000000 --- a/shield/docs/public/securing-communications/enabling-cipher-suites.asciidoc +++ /dev/null @@ -1,19 +0,0 @@ -[[ciphers]] -=== Enabling Cipher Suites for Stronger Encryption - -The SSL/TLS protocols use a cipher suite that determines the strength of encryption used to protect the data. You may -want to increase the strength of encryption used when using a Oracle JVM; the IcedTea OpenJDK ships without these -restrictions in place. This step is not required to successfully use Shield. - -The Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files enable additional cipher suites for -Java in a separate JAR file that you need to add to your Java installation. You can download this JAR file from -Oracle's http://www.oracle.com/technetwork/java/javase/downloads/index.html[download page]. The JCE Unlimited Strength -Jurisdiction Policy Files are required for encryption with key lengths greater than 128 bits, such as 256-bit AES -encryption. - -After installation, all cipher suites in the JCE are available for use. To enable the use of stronger cipher suites with -Shield, configure the `ciphers` parameter. See the <> section -of this document for specific parameter information. - -NOTE: The JCE Unlimited Strength Jurisdiction Policy Files must be installed on all nodes to establish an improved level -of encryption strength. diff --git a/shield/docs/public/securing-communications/separating-node-client-traffic.asciidoc b/shield/docs/public/securing-communications/separating-node-client-traffic.asciidoc deleted file mode 100644 index d1fcf77078f..00000000000 --- a/shield/docs/public/securing-communications/separating-node-client-traffic.asciidoc +++ /dev/null @@ -1,65 +0,0 @@ -[[separating-node-client-traffic]] -=== Separating node to node and client traffic - -Elasticsearch has the feature of so called {ref}/modules-transport.html#_tcp_transport_profiles[tcp transport profiles]. -This allows Elasticsearch to bind to several ports and addresses. Shield extends on this functionality to enhance the -security of the cluster by enabling the separation of node to node transport traffic from client transport traffic. This -is important if the client transport traffic is not trusted and could potentially be malicious. To separate the node to -node traffic from the client traffic, add the following to `elasticsearch.yml`: - -[source, yaml] --------------------------------------------------- -transport.profiles.client<1>: - port: 9500-9600 <2> - shield: - type: client <3> --------------------------------------------------- -<1> `client` is the name of this example profile -<2> The port range that will be used by transport clients to communicate with this cluster -<3> A type of `client` enables additional filters for added security by denying internal cluster operations (e.g shard -level actions and ping requests) - -If supported by your environment, an internal network can be used for node to node traffic and public network can be -used for client traffic by adding the following to `elasticsearch.yml`: -[source, yaml] --------------------------------------------------- -transport.profiles.default.bind_host: 10.0.0.1 <1> -transport.profiles.client.bind_host: 1.1.1.1 <2> --------------------------------------------------- -<1> The bind address for the network that will be used for node to node communication -<2> The bind address for the network used for client communication - -If separate networks are not available, then <> can be enabled to limit access to the profiles. - -The tcp transport profiles also allow for enabling SSL on a per profile basis. This is useful if you have a secured network -for the node to node communication, but the client is on an unsecured network. To enable SSL on a client profile when SSL is -disabled for node to node communication, add the following to `elasticsearch.yml`: -[source, yaml] --------------------------------------------------- -transport.profiles.client.ssl: true <1> --------------------------------------------------- -<1> This enables SSL on the client profile. The default value for this setting is the value of `shield.transport.ssl`. - -When using SSL for transport, a different set of certificates can also be used for the client traffic by adding the -following to `elasticsearch.yml`: -[source, yaml] --------------------------------------------------- -transport.profiles.client.shield.truststore: - path: /path/to/another/truststore - password: changeme - -transport.profiles.client.shield.keystore: - path: /path/to/another/keystore - password: changeme --------------------------------------------------- - -To change the default behavior that requires certificates for transport clients, set the following value in the `elasticsearch.yml` -file: - -[source, yaml] --------------------------------------------------- -transport.profiles.client.shield.ssl.client.auth: no --------------------------------------------------- - -This setting keeps certificate authentication active for node-to-node traffic, but removes the requirement to distribute -a signed certificate to transport clients. Please see the <> section. diff --git a/shield/docs/public/securing-communications/setting-up-ssl.asciidoc b/shield/docs/public/securing-communications/setting-up-ssl.asciidoc deleted file mode 100644 index fee8463e997..00000000000 --- a/shield/docs/public/securing-communications/setting-up-ssl.asciidoc +++ /dev/null @@ -1,267 +0,0 @@ -[[ssl-tls]] -=== Setting Up SSL/TLS on a Cluster - -Shield enables you to encrypt traffic to and from nodes in your Elasticsearch cluster. Connections -are secured using Transport Layer Security (TLS). - -WARNING: Nodes that do not have encryption enabled send passwords in plain text. - -To enable encryption, you need to perform the following steps on each node in the cluster: - -. <>. - -. <> to: -.. Identify itself using its signed certificate. -.. Enable SSL on the transport and HTTP layers. -.. Disable multicast. - -. Restart Elasticsearch. - -[[installing-node-certificates]] -==== Installing Node Certificates - -Node certificates should be signed by a certificate authority (CA) that is trusted by every node -in the cluster. You can use a third-party CA, your organization's existing CA, or -<> specifically for signing node certificates. - -When a client connects to a node using SSL/TLS, the node presents its certificate to the -client and proves that it owns the private key linked with the certificate. The client then -determines if the node's certificate is valid, trusted, and matches the hostname or IP address -it is trying to connect to. A node acts as a client when connecting to other nodes in the cluster, -so every node must trust all of the other nodes in the cluster. - -NOTE: While it is technically possible to use self-signed certificates, we strongly recommend using certificates signed by a CA to establish trust between nodes. Self-signed certificates must be trusted individually, which means that each node must have every other node's certificate installed. If you add a node to the cluster, you have to install the new node's self-signed certificate on all of the existing nodes and restart them. When you use CA-signed certificates, the existing nodes just need to trust the CA used to sign the new node's certificate. (You should use the same CA to sign all of your node certificates.) - -To install a signed certificate, you need to: - -. <>. -. <>. -. <>. -. <>. - -[[private-key]] -===== Creating a Keystore and Generating a Certificate -To create a keystore and generate a node certificate: - -. Create a node keystore and import your CA's certificate with https://docs.oracle.com/javase/8/docs/technotes/tools/unix/keytool.html[Java Keytool]. This configures the node to trust certificates signed by the CA. For Elasticsearch -to access the keystore, it must be located under the Elasticsearch configuration directory. For example, the following command creates a keystore for `node01` and and imports the CA certificate `cacert.pem`. -+ -[source,shell] --------------------------------------------------- -cd CONFIG_DIR/shield -keytool -importcert -keystore node01.jks -file cacert.pem -alias my_ca --------------------------------------------------- -+ -The Java keystore file (.jks) securely stores certificates for the node. The CA cert must be a -PEM encoded certificate. -+ -When you create a keystore, you are prompted to set a password. This password protects the -integrity of the keystore. You need to provide it whenever you interact with the keystore. -+ -IMPORTANT: When the CA certificate expires, you must update the node's keystore with the new CA -certificate. -+ -You can also store the CA certificate in a separate truststore. For more -information, see <>. - -. Generate a private key and certificate for the node with Java Keytool. For example, the following -command creates a key and certificate for `node01`: -+ -[source,shell] --------------------------------------------------- -keytool -genkey -alias node01 -keystore node01.jks -keyalg RSA -keysize 2048 -validity 712 -ext san=dns:node01.example.com,ip:192.168.1.1 --------------------------------------------------- -+ -This command creates an RSA private key with a key size of 2048 bits and a public certificate that -is valid for 712 days. The key and certificate are stored in the `node01.jks` keystore. -+ -The `san` value specifies all alternative names for the node. The generated certificate is valid for the DNS names and IP addresses specified as alternative names. You can specify multiple DNS or IP address entries as a comma-separated list. -+ -[IMPORTANT] -.Specifying the Node Identity -========================== -With SSL/TLS is enabled, when node A connects to node B, node A normally verifies the identity of -node B by checking the identity information specified in node B's certificate. This means that you -must include node identity information when you create a node's certificate. - -The recommended way to specify the node identity when creating a certificate is to specify the -`-ext` option and list all of the node's names and IP addresses in the `san` -(Subject Alternative Name) attribute. - -If you use a commercial CA, the DNS names and IP addresses used to identify a node must be publicly resolvable. Internal DNS names and private IP addresses are not accepted due to -https://cabforum.org/internal-names/[security concerns]. - -If you need to use private DNS names and IP addresses, using an internal CA is the most secure -option. It enables you to specify node identities and ensure node identities are verified when -nodes connect. If you must use a commercial CA and private DNS names or IP addresses, you cannot -include the node identity in the certificate, so the only option is to disable -<>. -========================== -+ -When you run `keytool -genkey`, Keytool prompts you for the information needed to populate the -node's distinguished name that's stored the certificate. For example: -+ -[source, shell] --------------------------------------------------- -What is your first and last name? - [Unknown]: Elasticsearch node01 <1> -What is the name of your organizational unit? - [Unknown]: test -What is the name of your organization? - [Unknown]: Elasticsearch -What is the name of your City or Locality? - [Unknown]: Amsterdam -What is the name of your State or Province? - [Unknown]: Amsterdam -What is the two-letter country code for this unit? - [Unknown]: NL -Is CN=Elasticsearch node01, OU=test, O=elasticsearch, L=Amsterdam, ST=Amsterdam, C=NL correct? - [no]: yes - -Enter key password for <2> - (RETURN if same as keystore password): --------------------------------------------------- -<1> Provides information about the node that this certificate is intended for. In the past, this field specified the node's identity using a DNS name, but that behavior has been deprecated. -<2> If you don't specify a password for the certificate, the keystore password is used. -+ -[IMPORTANT] -.Extended Key Usage -========================== -The Extended Key Usage attribute in a certificate is used to indicate the purpose of the key. By default `keytool` does not set this attribute in the certificate. If you are generating your certificates with another tool, please ensure the certificates support both `serverAuth` and `clientAuth` if the Extended Key Usage attribute is set. -========================== - -[float] -[[generate-csr]] -===== Creating a Certificate Signing Request - -A node's certificate needs to be signed by a trusted CA for the certificate to be trusted. To get a certificate signed, you need to create a certificate signing request (CSR) and send it to your CA. - -To create a CSR with Java Keytool, use the `keytool t-certreq` command. You specify the same alias, keystore, key algorithm, and DNS names and IP addresses that you used when you created the node certificate. Specify where you want to store the CSR with the `-file` option. - -[source, shell] --------------------------------------------------- -keytool -certreq -alias node01 -keystore node01.jks -file node01.csr -keyalg rsa -ext san=dns:node01.example.com,ip:192.168.1.1 --------------------------------------------------- - -[float] -[[send-csr]] -===== Send the Signing Request - -To get a signed certificate, send the generated CSR file to your CA. The CA will sign it and send -you the signed version of the certificate. - -NOTE: If you are running your own CA, see <> for signing instructions. - -[float] -[[install-signed-cert]] -===== Install the Signed Certificate - -To install the signed certificate, use `keytool -importcert` to add it to the node's keystore. You -specify the same alias and keystore that you used when you created the node certificate. - -[source, shell] --------------------------------------------------- -cd CONFIG_DIR/shield -keytool -importcert -keystore node01.jks -file node01-signed.crt -alias node01 --------------------------------------------------- - -[NOTE] -========================== -If you attempt to import a PEM-encoded certificate that contains extra text headers, you might get -the error: `java.security.cert.CertificateParsingException: invalid DER-encoded certificate data`. -Use the following `openssl` command to remove the extra headers and then use `keytool` to import -the certificate. - -[source, shell] --------------------------------------------------- -openssl x509 -in node01-signed.crt -out node01-signed-noheaders.crt --------------------------------------------------- -========================== - -[[enable-ssl]] -==== Enabling SSL in the Node Configuration - -Once you have added the signed certificate to the node's keystore, you need to modify the node -configuration to enable SSL. - -NOTE: All SSL/TLS related node settings that are considered to be highly sensitive and therefore -are not exposed via the {ref}/cluster-nodes-info.html#cluster-nodes-info[nodes info API]. - -[[configure-ssl]] -To enable SSL, make the following changes in `elasticsearch.yml`: - -. Specify the location of the node's keystore and the password(s) needed to access the node's -certificate. For example: -+ -[source, yaml] --------------------------------------------------- -shield.ssl.keystore.path: /home/es/config/shield/node01.jks <1> -shield.ssl.keystore.password: myPass <2> -shield.ssl.keystore.key_password: myKeyPass <3> --------------------------------------------------- -<1> The full path to the node keystore file. This must be a location within the Elasticsearch -configuration directory. -<2> The password used to access the keystore. -<3> The password used to access the certificate. This is only required if you specified a separate -certificate password when generating the certificate. - -. Enable SSL on the transport networking layer to ensure that communication between nodes is -encrypted: -+ -[source, yaml] --------------------------------------------------- -shield.transport.ssl: true --------------------------------------------------- -+ -NOTE: Transport clients can only connect to the cluster with a valid username and password even if -this setting is disabled. - -. Enable SSL on the HTTP layer to ensure that communication between HTTP clients and the cluster is encrypted: -+ -[source, yaml] --------------------------------------------------- -shield.http.ssl: true --------------------------------------------------- -+ -NOTE: HTTP clients can only connect to the cluster with a valid username and password even if this -setting is disabled. - -. Disable {ref}/modules-discovery.html[multicast discovery]: -+ -[source, yaml] --------------------------------------------------- -discovery.zen.ping.multicast.enabled: false -discovery.zen.ping.unicast.hosts: ["node01:9300", "node02:9301"] --------------------------------------------------- - -. Restart Elasticsearch so these configuration changes take effect. - -[[create-truststore]] -==== Configuring a Separate Truststore -You can store trusted CA certificates in a node's keystore, or create a separate truststore for CA -certificates. - -To use a separate truststore: - -. Create a node truststore and import the CA certificate(s) you want to trust with Java Keytool. For example, the following command imports the CA certificate `cacert.pem` into `truststore.jks`. If the specified truststore doesn't exist, it is created. -+ -[source,shell] --------------------------------------------------- -cd CONFIG_DIR/shield -keytool -importcert -keystore truststore.jks -file cacert.pem --------------------------------------------------- -+ -When you create a truststore, you are prompted to set a password. This password protects the -integrity of the truststore. You need to provide it whenever you interact with the truststore. - -. In `elasticsearch.yml`, specify the location of the node's truststore and the password needed to -access it. For example: -+ -[source, yaml] --------------------------------------------------- -shield.ssl.truststore.path: /home/es/config/shield/truststore.jks <1> -shield.ssl.truststore.password: myPass <2> --------------------------------------------------- -<1> The full path to the truststore file. This must be a location within the -Elasticsearch configuration directory. -<2> The password needed to access the truststore. diff --git a/shield/docs/public/securing-communications/using-ip-filtering.asciidoc b/shield/docs/public/securing-communications/using-ip-filtering.asciidoc deleted file mode 100644 index 701f87c412e..00000000000 --- a/shield/docs/public/securing-communications/using-ip-filtering.asciidoc +++ /dev/null @@ -1,131 +0,0 @@ -[[ip-filtering]] -=== Using IP Filtering - -You can apply IP filtering to application clients, node clients, or transport clients, in addition to other nodes that -are attempting to join the cluster. - -If a node's IP address is on the blacklist, Shield will still allow the connection to Elasticsearch. The connection will -be dropped immediately, and no requests will be processed. - -NOTE: Elasticsearch installations are not designed to be publicly accessible over the Internet. IP Filtering and the -other security capabilities of Shield do not change this condition. - -[float] -==== Enabling IP filtering - -Shield features an access control feature that allows or rejects hosts, domains, or subnets. - -You configure IP filtering by specifying the `shield.transport.filter.allow` and `shield.transport.filter.deny` settings in in `elasticsearch.yml`. Allow rules take prececence over the deny rules. - -.Example 1. Allow/Deny Statement Priority -[source,yaml] --------------------------------------------------- -shield.transport.filter.allow: "192.168.0.1" -shield.transport.filter.deny: "192.168.0.0/24" --------------------------------------------------- - -The `_all` keyword denies all connections that are not explicitly allowed earlier in the file. - -.Example 2. `_all` Keyword Usage -[source,yaml] --------------------------------------------------- -shield.transport.filter.allow: [ "192.168.0.1", "192.168.0.2", "192.168.0.3", "192.168.0.4" ] -shield.transport.filter.deny: _all --------------------------------------------------- - -IP Filtering configuration files support IPv6 addresses. - -.Example 3. IPv6 Filtering -[source,yaml] --------------------------------------------------- -shield.transport.filter.allow: "2001:0db8:1234::/48" -shield.transport.filter.deny: "1234:0db8:85a3:0000:0000:8a2e:0370:7334" --------------------------------------------------- - -Shield supports hostname filtering when DNS lookups are available. - -.Example 4. Hostname Filtering -[source,yaml] --------------------------------------------------- -shield.transport.filter.allow: localhost -shield.transport.filter.deny: '*.google.com' --------------------------------------------------- - -[float] -==== Disabling IP Filtering - -Disabling IP filtering can slightly improve performance under some conditions. To disable IP filtering entirely, set the -value of the `shield.transport.filter.enabled` attribute in the `elasticsearch.yml` configuration file to `false`. - -.Example 5. Disabled IP Filtering -[source,yaml] --------------------------------------------------- -shield.transport.filter.enabled: false --------------------------------------------------- - -You can also disable IP filtering for the transport protocol but enable it for HTTP only like this - -.Example 6. Enable HTTP based IP Filtering -[source,yaml] --------------------------------------------------- -shield.transport.filter.enabled: false -shield.http.filter.enabled: true --------------------------------------------------- - -[float] -==== Specifying TCP transport profiles - -In order to support bindings on multiple host, you can specify the profile name as a prefix in order to allow/deny based on profiles - -.Example 7. Profile based filtering -[source,yaml] --------------------------------------------------- -shield.transport.filter.allow: 172.16.0.0/24 -shield.transport.filter.deny: _all -transport.profiles.client.shield.filter.allow: 192.168.0.0/24 -transport.profiles.client.shield.filter.deny: _all --------------------------------------------------- - -Note: When you do not specify a profile, `default` is used automatically. - -[float] -==== HTTP Filtering - -You may want to have different filtering between the transport and HTTP protocol - -.Example 8. HTTP only filtering -[source,yaml] --------------------------------------------------- -shield.transport.filter.allow: localhost -shield.transport.filter.deny: '*.google.com' -shield.http.filter.allow: 172.16.0.0/16 -shield.http.filter.deny: _all --------------------------------------------------- - -[float] -[[dynamic-ip-filtering]] -==== Dynamically updating ip filter settings added[1.1.0] - -In case of running in an environment with highly dynamic IP addresses like cloud based hosting it is very hard to know the IP addresses upfront when provisioning a machine. Instead of changing the configuration file and restarting the node, you can use the Cluster Update Settings API like this - -[source,json] --------------------------------------------------- -curl -XPUT localhost:9200/_cluster/settings -d '{ - "persistent" : { - "shield.transport.filter.allow" : "172.16.0.0/24" - } -}' --------------------------------------------------- - -You can also disable filtering completely setting `shield.transport.filter.enabled` like this - -[source,json] --------------------------------------------------- -curl -XPUT localhost:9200/_cluster/settings -d '{ - "persistent" : { - "shield.transport.filter.enabled" : false - } -}' --------------------------------------------------- - -NOTE: In order to not lock yourself out, the default bound transport address will never be denied. This means you can always SSH into a system and use curl to apply changes. \ No newline at end of file diff --git a/shield/docs/public/setting-up-authentication.asciidoc b/shield/docs/public/setting-up-authentication.asciidoc deleted file mode 100644 index ac29733f2df..00000000000 --- a/shield/docs/public/setting-up-authentication.asciidoc +++ /dev/null @@ -1,117 +0,0 @@ -[[setting-up-authentication]] -== Setting Up User Authentication - -Authentication identifies an individual. To gain access to restricted resources, a user must prove their identity, via -passwords, credentials, or some other means (typically referred to as authentication tokens). - -NOTE: In Shield, an authenticated user can submit requests on behalf of other another user if they -have the appropriate `run_as` permission. For more information, see -<>. - -A _realm_ is an authentication mechanism, which Shield uses to resolve and authenticate users and their roles. Shield -currently provides four realm types: - -[horizontal] -_esusers_:: A native authentication system built into Shield and available by default. See <>. -_LDAP_:: Authentication via an external Lightweight Directory Protocol. See <>. -_Active Directory_:: Authentication via an external Active Directory service. See <>. -_PKI_:: Authentication through the use of trusted X.509 certificates. See <>. - -The _esusers_, _LDAP_, and _Active Directory_ realms authenticate using the username and password authentication tokens. - -Shield also supports custom realms. If you need to integrate with another authentication system, you -can build a custom realm plugin. For more information, see <>. - -Realms live within a _realm chain_. It is essentially a prioritized list of configured realms (typically of various types). -The order of the list determines the order in which the realms will be consulted. During the authentication process, -Shield will consult and try to authenticate the request one realm at a time. Once one of the realms successfully -authenticates the request, the authentication is considered to be successful and the authenticated user will be associated -with the request (which will then proceed to the authorization phase). If a realm cannot authenticate the request, the -next in line realm in the chain will be consulted. If all realms in the chain could not authenticate the request, the -authentication is then considered to be unsuccessful and an authentication error will be returned (as HTTP status code `401`). - -NOTE: Shield attempts to authenticate to each configured realm sequentially. Some systems (e.g. Active Directory) have a -temporary lock-out period after several successive failed login attempts. If the same username exists in multiple realms, -unintentional account lockouts are possible. For more information, please see <>. - -For example, if `UserA` exists in both Active Directory and esusers, and the Active Directory realm is checked first and -esusers is checked second, an attempt to authenticate as `UserA` in the esusers realm would first attempt to authenticate -against Active Directory and fail, before successfully authenticating against the esusers realm. Because authentication is -verified on each request, the Active Directory realm would be checked - and fail - on each request for `UserA` in the esusers -realm. In this case, while the Shield request completed successfully, the account on Active Directory would have received -several failed login attempts, and that account may become temporarily locked out. Plan the order of your realms accordingly. - -The realm chain can be configured in the `elasticsearch.yml` file. When not explicitly configured, a default chain will be -created that only holds the `esusers` realm in it. When explicitly configured, the created chain will be the exact reflection -of the configuration (e.g. the only realms in the chain will be those configured realms that are enabled) - -The following snippet shows an example of realms configuration: - - -[source,yaml] ----------------------------------------- -shield.authc: - - realms: - - esusers: - type: esusers - order: 0 - - ldap1: - type: ldap - order: 1 - enabled: false - url: 'url_to_ldap1' - ... - - ldap2: - type: ldap - order: 2 - url: 'url_to_ldap2' - ... - - ad1: - type: active_directory - order: 3 - url: 'url_to_ad' ----------------------------------------- - -As can be seen above, each realm has a unique name that identifies it. There are three settings that are common to all -realms: - -* `type` (required) - Identifies the type of the ream (currently can be `esusers`, `ldap` or `active_directory`). The realm - type determines what other settings the realms should be configured with. -* `order` (optional) - Defines the priority/index of the realm within the realm chain. This will determine when the realm - will be consulted during authentication. -* `enabled` (optional) - When set to `false` the realm will be disabled and will not be added to the realm chain. This is - useful for debugging purposes, where one can remove a realm from the chain without deleting and - losing its configuration. - -The realm types can roughly be categorized to two categories: - -* `internal` - Internal realm types are realms that are internal to Elasticsearch and don't require any communication with - external parties - they are fully managed by shield. There can only be a maximum of one configured realm - per internal realm type. (Currently, only one internal realm type exists - `esusers`). - -* `external` - External realm types are realms that require interaction with parties/components external to Elasticsearch, - typically, with enterprise level identity management systems. Unlike the `internal` realms, there can be - as many `external` realms as one would like - each with a unique name and different settings. (Currently - the only `external` realm types that exist are `ldap`, `active_directory`, and `pki`). - - -include::setting-up-authentication/enabling-anonymous-access.asciidoc[] - -include::setting-up-authentication/configuring-esusers-realm.asciidoc[] - -include::setting-up-authentication/configuring-ldap-realm.asciidoc[] - -include::setting-up-authentication/configuring-active-directory-realm.asciidoc[] - -include::setting-up-authentication/configuring-pki-realm.asciidoc[] - -include::setting-up-authentication/integrating-other-auth-systems.asciidoc[] - -include::setting-up-authentication/controlling-user-cache.asciidoc[] - diff --git a/shield/docs/public/setting-up-authentication/configuring-active-directory-realm.asciidoc b/shield/docs/public/setting-up-authentication/configuring-active-directory-realm.asciidoc deleted file mode 100644 index ee6d3db2348..00000000000 --- a/shield/docs/public/setting-up-authentication/configuring-active-directory-realm.asciidoc +++ /dev/null @@ -1,244 +0,0 @@ -[[active-directory]] -=== Using Active Directory to Authenticate Users - -You can configure Shield to communicate with Active Directory to authenticate users. To integrate -with Active Directory, you configure an Active Directory realm and assign Active Directory users -and groups to Shield roles in the <>. - -To protect passwords, communications between Shield and the LDAP server should be encrypted -using SSL/TLS. Clients and nodes that connect via SSL/TLS to the LDAP server need to have the -LDAP server's certificate or the server's root CA certificate installed in their keystore or -truststore. For more information about installing certificates, see <>. - -==== Configuring an Active Directory Realm - -Shield uses LDAP to communicate with Active Directory, so Active Directory realms are similar -to <>. Like LDAP directories, Active Directory stores users and groups -hierarchically. The directory's hierarchy is built from containers such as the _organizational -unit_ (`ou`), _organization_ (`o`), and _domain controller_ (`dc`). - -The path to a entry is a _Distinguished Name_ (DN) that uniquely identifies a user or group. User -and group names typically have attributes such as a _common name_ (`cn`) or _unique ID_ (`uid`). -A DN is specified as a string, for example `"cn=admin,dc=example,dc=com"`. White space is ignored. -Shield only supports Active Directory security groups. You cannot map distribution groups -to roles. - -NOTE: When you use Active Directory for authentication, the username entered by the user is expected - to match the `sAMAccountName` or `userPrincipalName`, not the common name. - -To configure an Active Directory realm: - -. Add a realm configuration of type `active_directory` to `elasticsearch.yml` in the -`shield.authc.realms` namespace. At a minimum, you must set the realm -`type` to `active_directory` and specify the Active Directory `domain_name`. To use SSL/TLS to -encrypt communications with the Active Directory server, you must also set the `url` attribute and -specify the LDAPS protocol and secure port number. If you are configuring multiple realms, you -should also explicitly set the `order` attribute to control the order in which the realms are -consulted during authentication. See <> -for all of the options you can set for an Active Directory realm. -+ -NOTE: Binding to Active Directory fails if the domain name is not mapped in DNS. If DNS is not - being provided by a Windows DNS server, add a mapping for the domain in the local - `/etc/hosts` file. -+ -For example, the following realm configuration configures Shield to connect to -`ldaps://example.com:636` to authenticate users through Active Directory. -+ -[source, yaml] ------------------------------------------------------------- -shield: - authc: - realms: - active_directory: - type: active_directory - order: 0 <1> - domain_name: ad.example.com - url: ldaps://ad.example.com:636 <2> - unmapped_groups_as_roles: true <3> - ... ------------------------------------------------------------- -<1> The realm order controls the order in which the configured realms are checked when -authenticating a user. -<2> If you don't specify the URL, it defaults to `ldap::389`. -<3> When this option is enabled, Shield automatically maps Active Directory groups to -roles of the same name defined in `roles.yml`. - -. Restart Elasticsearch. - -[[ad-settings]] -===== Active Directory Realm Settings - -|======================= -| Setting | Required | Description -| `type` | yes | Indicates the realm type. Must be set to - `active_directory`. -| `order` | no | Indicates the priority of this realm within the realm - chain. Realms with a lower order are consulted first. - Although not required, we recommend explicitly - setting this value when you configure multiple realms. - Defaults to `Integer.MAX_VALUE`. -| `enabled` | no | Indicates whether this realm is enabled or disabled. - Enables you to disable a realm without removing its - configuration. Defaults to `true`. -| `domain_name` | yes | Specifies the domain name of the Active Directory. Shield - uses the domain name to derive the LDAP URL and - `user_search_dn` if those fields are not specified. -| `url` | no | Specifies an LDAP URL of the form - `ldap[s]://:`. Shield attempts to - authenticate against this URL. If the URL is not - specified, Shield derives it from the `domain_name`, - assuming an unencrypted connection to port 389. For - example, `ldap://:389`. You must specify the - URL to connect using SSL/TLS or connect to a custom port. -| `user_search.base_dn` | no | Specifies the context to search for the user. Defaults to - the root of the Active Directory domain. -| `user_search.scope` | no | Specifies whether the user search should be `sub_tree` - (default), `one_level`, or `base`. `sub_tree` searches - all objects contained under `base_dn`. `one_level` only - searches users directly contained within the `base_dn`. - `base` specifies that the `base_dn` is a user object and - that it is the only user considered. -| `user_search.filter` | no | Specifies a filter to use to lookup a user given a - username. The default filter looks up `user` objects - with either `sAMAccountName` or `userPrincipalName`. If - specified, this must be a proper LDAP user search filter, - for example `(&(objectClass=user)(sAMAccountName={0}))`. - For more information, see https://msdn.microsoft.com/en-us/library/aa746475(v=vs.85).aspx[Search Filter Syntax]. -| `group_search.base_dn` | no | Specifies the context to search for groups in which the - user has membership. Defaults to the root of the Active - Directory domain. -| `group_search.scope` | no | Specifies whether the group search should be `sub_tree` - (default), `one_level` or `base`. `sub_tree` searches - all objects contained under `base_dn`. `one_level` - searches for groups directly contained within the - `base_dn`. `base` specifies that the `base_dn` is a - group object and that it is the only group considered. -| `unmapped_groups_as_roles` | no | Specifies whether the names of any unmapped LDAP groups - should be used as role names and assigned to the user. - Defaults to `false`. -| `files.role_mapping` | no | Specifies the path and file name of the - <>. - Defaults to `CONF_DIR/shield/users/role_mapping.yml`, - where `CONF_DIR` is `ES_HOME/config` (zip/tar installations) - or `/etc/elasticsearch` (package installations). -| `follow_referrals` | no | Specifies whether Shield should follow referrals returned - by the LDAP server. Referrals are URLs returned by the - server that are to be used to continue the LDAP operation - (such as `search`). Defaults to `true`. -| `hostname_verification` | no | Specifies whether hostname verification is performed when - connecting to an LDAP server. When `true`, the hostname - or IP address used in the `url` must match one of the - names in the certificate or the connection will not be - allowed. Due to its potential security impact, - `hostname_verification` is not exposed via the - {ref}/cluster-nodes-info.html#cluster-nodes-info[nodes info API]. - Defaults to `true`. -| `cache.ttl` | no | Specifies the time-to-live for cached user entries. A - user's credentials are cached for this period of time. - Specify the time period using the standard Elasticsearch - {ref}/common-options.html#time-units[time units]. - Defaults to `20m`. -| `cache.max_users` | no | Specifies the maximum number of user entries that can be - stored in the cache at one time. Defaults to 100,000. -| `cache.hash_algo` | no | Specifies the hashing algorithm that is used for the - cached user credentials. See <> for the possible values. - (Expert Setting) -|======================= - -[[assigning-roles-ad]] -==== Assigning Active Directory Users and Groups to Roles - -To configure privileges for Active Directory users and groups, you assign them to roles in -the role mapping file stored on each node. You specify users and groups using their distinguished -names. For example, the following mapping configuration assigns the Active Directory `admins` -group both the `monitoring` and `user` roles, and assigns the `user` role to the `users` -group and `John Doe`. - -[source, yaml] ------------------------------------------------------------- -monitoring: <1> - - "cn=admins,dc=example,dc=com" <2> -user: - - "cn=users,dc=example,dc=com" <3> - - "cn=admins,dc=example,dc=com" - - "cn=John Doe,cn=contractors,dc=example,dc=com" <4> ------------------------------------------------------------- -<1> The name of a role defined in <>. -<2> The distinguished name of the `admins` group. -<3> The distinguished name of the `users` group. -<4> The distinguished name of the user `John Doe`. - -For more information, see <>. - -[[active-directory-ssl]] -==== Encrypting Communications Between Shield and Active Directory with SSL/TLS - -You should encrypt communications between Shield and Active Directory to protect the user -credentials that are sent to Active Directory for authentication. Connecting via SSL/TLS -ensures that the identity of the Active Directory server is authenticated before Shield -transmits the user credentials, and the user names and passwords are encrypted in transit. - -To encrypt communications between Shield and Active Directory: - -. Configure each node to trust certificates signed by the CA that signed your Active Directory server -certificates. For example, the following command imports `cacert.pem` -into node01's keystore. (For information about using truststores, see <>.) -+ -[source,shell] --------------------------------------------------- -cd CONFIG_DIR/shield -keytool -importcert -keystore node01.jks -file cacert.pem -alias ad_ca --------------------------------------------------- -+ -The CA cert must be a PEM encoded certificate. -+ -[NOTE] -=============================== -You can also import the individual server certificates rather than the CA certificate, but -this is only recommended if you have a single Active Directory server. -You can fetch the Active Directory server certificate with `openssl`. -For example, the following command gets the certificate for `ad.example.com` and stores it locally -in `ldap.crt`. - -[source, shell] ----------------------------------------------------------------------------------------------- -echo | openssl s_client -connect ad.example.com:636 2>/dev/null | openssl x509 > ldap.crt ----------------------------------------------------------------------------------------------- - -If you are using an older version of openssl you might need to use use the `-host` and -`-port` options rather than the `-connect` option. -=============================== - -. If you haven't already configured the path to the node's keystore or truststore in -`elasticsearch.yml`, set the `shield.ssl.keystore.path` or `shield.ssl.truststore.path` -attributes. For example: -+ -[source, yaml] --------------------------------------------------- -shield.ssl.keystore.path: /home/es/config/shield/node01.jks <1> -shield.ssl.keystore.password: myPass <2> -shield.ssl.keystore.key_password: myKeyPass <3> --------------------------------------------------- -<1> The full path to the node keystore file. This must be a location within the Elasticsearch -configuration directory. -<2> The password used to access the keystore. -<3> The password used to access the certificate. This is only required if you specified a separate -certificate password when generating the certificate. -+ -For more information, see <>. - -. Set the `url` attribute in the realm configuration to specify the LDAPS protocol and -the secure port number. For example, `url: ldaps://ad.example.com:636`. - -. Restart Elasticsearch to pick up the changes to `elasticsearch.yml`. - -NOTE: By default, when you configure Shield to connect to Active Directory using SSL/TLS, - Shield attempts to verify the hostname or IP address specified with the `url` attribute in - the realm configuration with the values in the certificate. If the values in the certificate - and realm configuration do not match, Shield does not allow a connection to the Active - Directory server. This is done to protect against man in the middle attacks. If necessary, - you can disable this behavior by setting the <> - property to `false`. \ No newline at end of file diff --git a/shield/docs/public/setting-up-authentication/configuring-esusers-realm.asciidoc b/shield/docs/public/setting-up-authentication/configuring-esusers-realm.asciidoc deleted file mode 100644 index b83ce7ceb45..00000000000 --- a/shield/docs/public/setting-up-authentication/configuring-esusers-realm.asciidoc +++ /dev/null @@ -1,74 +0,0 @@ -[[esusers]] -=== Using esusers to Authenticate Users - -You can manage and authenticate users with Shield's built-in system, `esusers`. -An _esusers_ realm is created by default when you install Shield. You use the -<> to add and remove users, assign user roles, -and manage user passwords. - -==== Configuring an esusers Realm - -Like other realms, you can configure options for an `esusers` realm in the -`shield.authc.realms` namespace in `elasticsearch.yml`. - -To configure an esusers realm: - -. Add a realm configuration of type `esusers` to `elasticsearch.yml` in the -`shield.authc.realms` namespace. At a minimum, you must set the realm -`type` to `esusers`. If you are configuring multiple realms, you -should also explicitly set the `order` attribute. See <> -for all of the options you can set for an `esusers` realm. -+ -For example, the following snippet shows an `esusers` realm configuration that sets the `order` to -zero so the realm is checked first: -+ -[source, yaml] ------------------------------------------------------------- -shield: - authc: - realms: - esusers1: - type: esusers - order: 0 ------------------------------------------------------------- - -. Restart Elasticsearch. - -[[esusers-settings]] -===== esusers Realm Settings - -|======================= -| Setting | Required | Description -| `type` | yes | Indicates the realm type. Must be set to `esusers`. -| `order` | no | Indicates the priority of this realm within the realm - chain. Realms with a lower order are consulted first. - Although not required, we recommend explicitly - setting this value when you configure multiple realms. - Defaults to `Integer.MAX_VALUE`. -| `enabled` | no | Indicates whether this realm is enabled or disabled. - Enables you to disable a realm without removing its - configuration. Defaults to `true`. -| `files.users` | no | Points to the <> - of the `users` file where the users and their passwords - are stored. By default, it is `CONFIG_DIR/shield/users`. -| `files.users_roles` | no | Points to the <> - of the `users_roles` file where the users and their - roles are stored. Defaults to - `CONFIG_DIR/shield/users_roles`. -| `cache.ttl` | no | Specifies the time-to-live for cached user entries. A - user's credentials are cached for this period of time. - Specify the time period using the standard Elasticsearch - {ref}/common-options.html#time-units[time units]. - Defaults to `20m`. -| `cache.max_users` | no | Specifies the maximum number of user entries that can be - stored in the cache at one time. Defaults to 100,000. -| `cache.hash_algo` | no | Specifies the hashing algorithm that is used for the - cached user credentials. See <> for the possible values. - (Expert Setting) -|======================= - -NOTE: When no realms are explicitly configured in `elasticsearch.yml`, a default realm chain is - created that holds a single `esusers` realm. If you wish to only work with `esusers` realm - and you're satisfied with the default files paths, there is no real need to add the above - configuration. diff --git a/shield/docs/public/setting-up-authentication/configuring-ldap-realm.asciidoc b/shield/docs/public/setting-up-authentication/configuring-ldap-realm.asciidoc deleted file mode 100644 index 4e813bd4deb..00000000000 --- a/shield/docs/public/setting-up-authentication/configuring-ldap-realm.asciidoc +++ /dev/null @@ -1,341 +0,0 @@ -[[ldap]] -=== Using LDAP to Authenticate Users - -You can configure Shield to communicate with a Lightweight Directory Access Protocol -(LDAP) directory to authenticate users. To integrate with LDAP, you configure an LDAP realm and -assign LDAP groups to Shield roles in the <>. - -To protect passwords, communications between Shield and the LDAP server should be encrypted -using SSL/TLS. Clients and nodes that connect via SSL/TLS to the LDAP server need to have the -LDAP server's certificate or the server's root CA certificate installed in their keystore or -truststore. For more information about installing certificates, see <>. - -==== Configuring an LDAP Realm - -LDAP stores users and groups hierarchically, similar to the way folders are grouped in a file -system. An LDAP directory's hierarchy is built from containers such as the - _organizational unit_ (`ou`), _organization_ (`o`), and _domain controller_ (`dc`). - -The path to a entry is a _Distinguished Name_ (DN) that uniquely identifies a user or group. -User and group names typically have attributes such as a _common name_ (`cn`) or _unique ID_ (`uid`). -A DN is specified as a string, for example `"cn=admin,dc=example,dc=com"`. White space is ignored. - -The LDAP realm supports two modes of operation, a user search mode -and a mode with specific templates for user DNs. See <> -for all of the options you can set for an LDAP realm. - -[[ldap-user-search]] -===== Configuring an LDAP Realm with User Search added[1.1.0] -LDAP user search is the most common mode of operation. In this mode, a specific user with -permission to search the LDAP directory is used to search for the user DN based on the username -and an LDAP attribute. - -To configure an LDAP Realm with User Search: - -. Add a realm configuration of type `ldap` to `elasticsearch.yml` in the -`shield.authc.realms` namespace. At a minimum, you must set the realm -`type` to `ldap`, specify the `url` of the LDAP server, and specify the container DN to search for -users with the `user_search.base_dn` option. If you are configuring multiple realms, you -should also explicitly set the `order` attribute to control the order in which the realms are -consulted during authentication. See <> -for all of the options you can set for an LDAP realm. -+ -For example, the following snippet shows an LDAP realm configured with a user search: -+ -[source, yaml] ------------------------------------------------------------- -shield: - authc: - realms: - ldap1: - type: ldap - order: 0 - url: "ldaps://ldap.example.com:636" - bind_dn: "cn=ldapuser, ou=users, o=services, dc=example, dc=com" - bind_password: changeme - user_search: - base_dn: "dc=example,dc=com" - attribute: cn - group_search: - base_dn: "dc=example,dc=com" - files: - role_mapping: "/mnt/elasticsearch/group_to_role_mapping.yml" - unmapped_groups_as_roles: false ------------------------------------------------------------- - -. Restart Elasticsearch - -===== Configuring an LDAP Realm with User DN Templates -If your LDAP environment uses a few specific standard naming conditions for users, you can use -User DN templates to configure the realm. The advantage of this method is that a search does not -have to be performed to find the user DN. However, multiple bind operations might be needed to find -the correct user DN. - -To configure an LDAP Realm with User Search: - -. Add a realm configuration of type `ldap` to `elasticsearch.yml` in the -`shield.authc.realms` namespace. At a minimum, you must set the realm -`type` to `ldap`, specify the `url` of the LDAP server, and specify at least one template with -the `user_dn_templates` option. If you are configuring multiple realms, you -should also explicitly set the `order` attribute to control the order in which the realms are -consulted during authentication. See <> -for all of the options you can set for an LDAP realm. -+ -For example, the following snippet shows an LDAP realm configured with User DN templates: -+ -[source, yaml] ------------------------------------------------------------- -shield: - authc: - realms: - ldap1: - type: ldap - order: 0 - url: "ldaps://ldap.example.com:636" - user_dn_templates: - - "cn={0}, ou=users, o=marketing, dc=example, dc=com" - - "cn={0}, ou=users, o=engineering, dc=example, dc=com" - group_search: - base_dn: "dc=example,dc=com" - files: - role_mapping: "/mnt/elasticsearch/group_to_role_mapping.yml" - unmapped_groups_as_roles: false ------------------------------------------------------------- - -[[ldap-settings]] -===== LDAP Realm Settings - -.Common LDAP Realm Settings -|======================= -| Setting | Required | Description -| `type` | yes | Indicates the realm type. Must be set to `ldap`. -| `order` | no | Indicates the priority of this realm within the realm - chain. Realms with a lower order are consulted first. - Although not required, we recommend explicitly - setting this value when you configure multiple realms. - Defaults to `Integer.MAX_VALUE`. -| `enabled` | no | Indicates whether this realm is enabled or disabled. - Enables you to disable a realm without removing its - configuration. Defaults to `true`. -| `url` | yes | Specifies an LDAP URL of the form of - `ldap[s]://:`. Shield attempts to - authenticate against this URL. -| `user_group_attribute` | no | Specifies the attribute to examine on the user for group - membership. The default is `memberOf`. This setting will - be ignored if any `group_search` settings are specified. -| `group_search.base_dn` | no | Specifies a container DN to search for groups in which - the user has membership. When this element is absent, - Shield searches for the attribute specified by - `user_group_attribute` set on the user to determine - group membership. -| `group_search.scope` | no | Specifies whether the group search should be - `sub_tree`, `one_level` or `base`. `one_level` only - searches objects directly contained within the - `base_dn`. The default `sub_tree` searches all objects - contained under `base_dn`. `base` specifies that the - `base_dn` is a group object, and that it is the only - group considered. -| `group_search.filter` | no | Specifies a filter to use to lookup a group. If not - set, the realm searches for `group`, - `groupOfNames`, or `groupOfUniqueNames`, with the - attributes `member` or `memberOf`. Any instance of - `{0}` in the filter is replaced by the user - attribute defined in `group_search.user_attribute` -| `group_search.user_attribute` | no | Specifies the user attribute that is fetched and - provided as a parameter to the filter. If not set, - the user DN is passed to the filter. -| `unmapped_groups_as_roles` | no | Specifies whether the names of any unmapped LDAP groups - should be used as role names and assigned to the user. - Defaults to `false`. -| `connect_timeout` | no | Specifies the timeout period for establishing an - LDAP connection. An `s` at the end indicates seconds, - `ms` indicates milliseconds. Defaults to `5s` (5 seconds). -| `read_timeout` | no | The timeout period for an LDAP operation. An `s` at - the end indicates seconds, `ms` indicates - milliseconds. Defaults to `5s` (5 seconds). -| `files.role_mapping` | no | Specifies the path and file name for the - <>. Defaults to - `ES_HOME/config/shield/role_mapping.yml`. -| `follow_referrals` | no | Specifies whether Shield should - follow referrals returned by the LDAP server. Referrals - are URLs returned by the server that are to be used to - continue the LDAP operation (e.g. search). Defaults to - `true`. -| `hostname_verification` | no | Specifies whether hostname verification is performed when - connecting to an LDAP server. When `true`, the hostname - or IP address used in the `url` must match one of the - names in the certificate or the connection will not be - allowed. Due to its potential security impact, - `hostname_verification` is not exposed via the - {ref}/cluster-nodes-info.html#cluster-nodes-info[nodes - info API]. Defaults to `true`. -| `cache.ttl` | no | Specifies the time-to-live for cached user entries. A - user's credentials are cached for this period of time. - Specify the time period using the standard Elasticsearch - {ref}/common-options.html#time-units[time units]. - Defaults to `20m`. -| `cache.max_users` | no | Specifies the maximum number of user entries that can be - stored in the cache at one time. Defaults to 100,000. -| `cache.hash_algo` | no | Specifies the hashing algorithm that is used for the - cached user credentials. See <> for the possible values. - (Expert Setting) -|======================= - -.User Template LDAP Realm Settings -|======================= -| Setting | Required | Description -| `user_dn_templates` | yes | Specifies the DN template that replaces the user name - with the string `{0}`. This element is multivalued, - allowing for multiple user contexts. -|======================= - -.User Search LDAP Realm Settings added[1.1.0] -|======================= -| Setting | Required | Description -| `bind_dn` | no | The DN of the user that is used to - bind to the LDAP and perform searches. If - not specified, an anonymous bind - is attempted. Due to its potential security - impact, `hostname_verification` is not - exposed via the - {ref}/cluster-nodes-info.html#cluster-nodes-info[ - nodes info API]. -| `bind_password` | no | The password for the user that is used - to bind to the LDAP. Due to its potential - security impact, `hostname_verification` is - not exposed via the - {ref}/cluster-nodes-info.html#cluster-nodes-info[ - nodes info API]. -| `user_search.base_dn` | yes | Specifies a container DN to search for users. -| `user_search.scope` | no | The scope of the user search. Valid values - are `sub_tree`, `one_level` or `base`. - `one_level` only searches objects directly - contained within the `base_dn`. - `sub_tree` searches all objects contained - under `base_dn`. `base` specifies that the - `base_dn` is the user object, and that it is - the only user considered. Defaults to - `sub_tree`. -| `user_search.attribute` | no | Specifies the attribute to match with the - username presented to Shield. Defaults to - `uid`. -| `user_search.pool.size` | no | Specifies the maximum number of connections - to the LDAP server to allow in the connection - pool. Defaults to `20`. -| `user_search.pool.initial_size` | no | The initial number of connections to create - to the LDAP server on startup. Defaults to `5`. -| `user_search.pool.health_check.enabled` | no | Enables or disables a health check on - LDAP connections in the connection pool. - Connections are checked in the background at - the specified interval. Defaults to `true`. -| `user_search.pool.health_check.dn` | no | Specifies the distinguished name to retrieve - as part of the health check. Defaults to the - value of `bind_dn`. If `bind_dn` is not - configured, you must specify a value. -| `user_search.pool.health_check.interval` | no | How often to perform background checks - of connections in the pool. Defaults to - `60s`. -|======================= - -NOTE: If any settings starting with `user_search` are specified, the `user_dn_templates` - the settings are ignored. - -[[assigning-roles-ldap]] -==== Assigning LDAP Groups to Roles - -To configure privileges for LDAP users, you assign LDAP groups to roles in -the role mapping file stored on each node. When a user authenticates with LDAP, -the privileges for that user are the union of all privileges defined by -the roles assigned to the set of groups that the user belongs to. - -You specify groups using their distinguished names. For example, the following mapping -configuration assigns the LDAP `admins` group both the `monitoring` and `user` roles, and -assigns the `user` role to the `users` group. - -[source, yaml] ------------------------------------------------------------- -monitoring: <1> - - "cn=admins,dc=example,dc=com" <2> -user: - - "cn=users,dc=example,dc=com" <3> - - "cn=admins,dc=example,dc=com" ------------------------------------------------------------- -<1> The name of a role defined in <>. -<2> The distinguished name of the `admins` group. -<3> The distinguished name of the `users` group. - -For more information, see <>. - -==== Encrypting Communications Between Shield and LDAP with SSL/TLS - -You should encrypt communications between Shield and your LDAP server to protect the user -credentials that are sent to for authentication. Connecting via SSL/TLS -ensures that the identity of the LDAP server is authenticated before Shield -transmits the user credentials, and the user names and passwords are encrypted in transit. - -To encrypt communications between Shield and your LDAP server: - -. Configure each node to trust certificates signed by the CA that signed your LDAP server -certificates. For example, the following command imports `cacert.pem` -into node01's keystore. (For information about using truststores, see <>.) -+ -[source,shell] --------------------------------------------------- -cd CONFIG_DIR/shield -keytool -importcert -keystore node01.jks -file cacert.pem -alias ldap_ca --------------------------------------------------- -+ -The CA cert must be a PEM encoded certificate. -+ -[NOTE] -=============================== -You can also import the individual server certificates rather than the CA certificate, but -this is only recommended if you have a single LDAP server. -You can fetch the LDAP server certificate with `openssl`. -For example, the following command gets the certificate for `ldap.example.com` and stores it locally -in `ldap.crt`. - -[source, shell] ----------------------------------------------------------------------------------------------- -echo | openssl s_client -connect ldap.example.com:636 2>/dev/null | openssl x509 > ldap.crt ----------------------------------------------------------------------------------------------- - -If you are using an older version of openssl you might need to use use the `-host` and -`-port` options rather than the `-connect` option. -=============================== - -. If you haven't already configured the path to the node's keystore or truststore in -`elasticsearch.yml`, set the `shield.ssl.keystore.path` or `shield.ssl.truststore.path` -attributes. For example: -+ -[source, yaml] --------------------------------------------------- -shield.ssl.keystore.path: /home/es/config/shield/node01.jks <1> -shield.ssl.keystore.password: myPass <2> -shield.ssl.keystore.key_password: myKeyPass <3> --------------------------------------------------- -<1> The full path to the node keystore file. This must be a location within the Elasticsearch -configuration directory. -<2> The password used to access the keystore. -<3> The password used to access the certificate. This is only required if you specified a separate -certificate password when generating the certificate. -+ -For more information, see <>. - -. Set the `url` attribute in the realm configuration to specify the LDAPS protocol and -the secure port number. For example, `url: ldaps://ldap.example.com:636`. - -. Restart Elasticsearch to pick up the changes to `elasticsearch.yml`. - - -NOTE: By default, when you configure Shield to connect to an LDAP server using SSL/TLS, - Shield attempts to verify the hostname or IP address specified with the `url` attribute in - the realm configuration with the values in the certificate. If the values in the certificate - and realm configuration do not match, Shield does not allow a connection to the LDAP server. - This is done to protect against man in the middle attacks. If necessary, - you can disable this behavior by setting the <> - property to `false`. `hostname_verification` is considered to be a sensitive setting and - is not exposed via {ref}/cluster-nodes-info.html#cluster-nodes-info[nodes info API]. \ No newline at end of file diff --git a/shield/docs/public/setting-up-authentication/configuring-pki-realm.asciidoc b/shield/docs/public/setting-up-authentication/configuring-pki-realm.asciidoc deleted file mode 100644 index 16574d85241..00000000000 --- a/shield/docs/public/setting-up-authentication/configuring-pki-realm.asciidoc +++ /dev/null @@ -1,123 +0,0 @@ -[[pki]] -=== Using PKI to Authenticate Users added[1.3.0] - -You can configure Shield to use Public Key Infrastructure (PKI) certificates to authenticate users. -This requires clients to present X.509 certificates. To use PKI, you configure a PKI realm, -enable client authentication on the desired network layers (transport or http), -and map the DNs from the user certificates to Shield roles in the <>. - -You can use a combination of PKI encryption and username and password authentication. For example, -you can enable SSL/TLS on the transport layer and define a PKI realm to require transport clients to -authenticate with X.509 certificates, while still authenticating HTTP traffic using usernames and -passwords. You can also set `shield.transport.ssl.client.auth` to `optional` -to allow clients without certificates to authenticate with other credentials. - -IMPORTANT: You must enable SSL/TLS to use PKI. For more information, see -<>. - -==== PKI Realm Configuration - -Like realms, you configure options for a `pki` realm in the `shield.authc.realms` namespace in -`elasticsearch.yml`. - -To configure PKI realm: - -. Add a realm configuration of type `pki` to `elasticsearch.yml` in the -`shield.authc.realms` namespace. At a minimum, you must set the realm -`type` to `pki`. If you are configuring multiple realms, you -should also explicitly set the `order` attribute. See <> -for all of the options you can set for an `pki` realm. -+ -For example, the following snippet shows the most basic PKI realm configuration: -+ -[source, yaml] ------------------------------------------------------------- -shield: - authc: - realms: - pki1: - type: pki ------------------------------------------------------------- -+ -With this configuration, any certificate trusted by the SSL/TLS layer is accepted for -authentication. The username is the common name (CN) extracted from the DN of the certificate. -+ -If you want to use something other than the CN of the DN as the username, you can specify -a regex to extract the desired username. For example, the regex in the following configuration -extracts the email address from the DN: -+ -[source, yaml] ------------------------------------------------------------- -shield: - authc: - realms: - pki1: - type: pki - username_pattern: "EMAILADDRESS=(.*?)(?:,|$)" ------------------------------------------------------------- -+ -You can also specify which truststore to use for authentication. This is useful -when the SSL/TLS layer trusts clients with certificates that are signed by a different -CA than the one that signs your users' certificates. To specify the location of the truststore, -specify the `truststore.path` option: -+ -[source, yaml] ------------------------------------------------------------- -shield: - authc: - realms: - pki1: - type: pki - truststore: - path: "/path/to/pki_truststore.jks" - password: "changeme" ------------------------------------------------------------- - -. Restart Elasticsearch. - -[[pki-settings]] -===== PKI Realm Settings - -|======================= -| Setting | Required | Description -| `type` | yes | Indicates the realm type. Must be set to `pki` -| `order` | no | Indicates the priority of this realm within the realm - chain. Realms with a lower order are consulted first. - Although not required, we recommend explicitly - setting this value when you configure multiple realms. - Defaults to `Integer.MAX_VALUE`. -| `enabled` | no | Indicates whether this realm is enabled or disabled. - Enables you to disable a realm without removing its - configuration. Defaults to `true`. -| `username_pattern` | no | Specifies the regular expression pattern used to extract - the username from the certificate DN. The first match - group is used as the username. Defaults to - `CN=(.*?)(?:,\|$)`. -| `truststore.path` | no | The path to the truststore. Defaults to the path - defined by <>. -| `truststore.password` | no | Specifies the password for the truststore. Must be - provided if `truststore.path` is set. -| `truststore.algorithm` | no | Specifies the algorithm used for the trustsore. Defaults to - `SunX509`. -| `files.role_mapping` | no | Specifies the <> - for the <>. Defaults to - `CONFIG_DIR/shield/role_mapping.yml`. -|======================= - -[[assigning-roles-pki]] -==== Assigning Roles for PKI Users - -You assign roles for PKI users in the role mapping file stored on each node. You identify a user -by the distinguished name in their certificate. For example, the following mapping -configuration assigns `John Doe` the `user` role: - -[source, yaml] ------------------------------------------------------------- -user: <1> - - "cn=John Doe,ou=example,o=com" <2> ------------------------------------------------------------- -<1> The name of a Shield role defined in the <> -<2> The distinguished name of a PKI user. - -For more information, see <>. \ No newline at end of file diff --git a/shield/docs/public/setting-up-authentication/controlling-user-cache.asciidoc b/shield/docs/public/setting-up-authentication/controlling-user-cache.asciidoc deleted file mode 100644 index b1808076d47..00000000000 --- a/shield/docs/public/setting-up-authentication/controlling-user-cache.asciidoc +++ /dev/null @@ -1,61 +0,0 @@ -[[controlling-user-cache]] -=== Controlling the User Cache - -User credentials are cached in memory on each node to avoid connecting to a remote authentication -server or hitting the disk for every incoming request. You can configure characteristics of the -user cache with the `cache.ttl`, `cache.max_users`, and ``cache.hash_algo` realm settings. - -NOTE: PKI realms do not use the user cache. - -The cached user credentials are hashed in memory. By default, Shield uses a salted `sha-256` -hash algorigthm. You can use a different algorithm by setting the `cache-hash_algo` setting -to any of the supported <>. - -[[cache-hash-algo]] -.Cache hash algorithms -|======================= -| Algorithm | Description -| `ssha256` | Uses a salted `sha-256` algorithm (default). -| `md5` | Uses `MD5` algorithm. -| `sha1` | Uses `SHA1` algorithm. -| `bcrypt` | Uses `bcrypt` algorithm with salt generated in 10 rounds. -| `bcrypt4` | Uses `bcrypt` algorithm with salt generated in 4 rounds. -| `bcrypt5` | Uses `bcrypt` algorithm with salt generated in 5 rounds. -| `bcrypt6` | Uses `bcrypt` algorithm with salt generated in 6 rounds. -| `bcrypt7` | Uses `bcrypt` algorithm with salt generated in 7 rounds. -| `bcrypt8` | Uses `bcrypt` algorithm with salt generated in 8 rounds. -| `bcrypt9` | Uses `bcrypt` algorithm with salt generated in 9 rounds. -| `sha2` | Uses `SHA2` algorithm. -| `apr1` | Uses `apr1` algorithm (md5 crypt). -| `noop`,`clear_text` | Doesn't hash the credentials and keeps it in clear text in - memory. CAUTION: keeping clear text is considered insecure - and can be compromised at the OS level (for example through - memory dumps and using `ptrace`). -|======================= - -[float] -==== Evicting Users from the Cache - -Shield exposes an API to force the eviction of cached users. For example, the following request -evicts all users from the `ad1` realm: - -[source, java] ------------------------------------------------------------- -$ curl -XPOST 'http://localhost:9200/_shield/realm/ad1/_cache/clear' ------------------------------------------------------------- - -To clear the cache for multiple realms, specify the realms as a comma-separated list: - -[source, java] ------------------------------------------------------------- -$ curl -XPOST 'http://localhost:9200/_shield/realm/ad1,ad2/_cache/clear' ------------------------------------------------------------- - -You can also evict specific users: - -[source, java] ------------------------------------------------------------- -$ curl -XPOST 'http://localhost:9200/_shield/realm/ad1/_cache/clear?usernames=rdeniro,alpacino' ------------------------------------------------------------- - - diff --git a/shield/docs/public/setting-up-authentication/enabling-anonymous-access.asciidoc b/shield/docs/public/setting-up-authentication/enabling-anonymous-access.asciidoc deleted file mode 100644 index da1f6675f36..00000000000 --- a/shield/docs/public/setting-up-authentication/enabling-anonymous-access.asciidoc +++ /dev/null @@ -1,34 +0,0 @@ -[[anonymous-access]] -=== Enabling Anonymous Access added[1.1.0] - -The authentication process can be split into two phases - token extraction and user authentication. During the first -phase (token extraction phase), the configured realms are requested to try and extract/resolve an authentication token -from the incoming request. The first realm that finds an authentication token in the request "wins", meaning, the found -authentication token will be used for authentication (moving to the second phase - user authentication - where each realm -that support this authentication token type will try to authenticate the user). - -In the event where no authentication token was resolved by any of the active realms, the incoming request is considered -to be anonymous. - -By default, anonymous requests are rejected and an authentication error is returned (status code `401`). It is possible -to change this behaviour and instruct Shield to associate an default/anonymous user with the anonymous request. This can -be done by configuring the following settings in the `elasticsearch.yml` file: - -[source,yaml] ----------------------------------------- -shield.authc: - anonymous: - username: anonymous_user <1> - roles: role1, role2 <2> - authz_exception: true <3> ----------------------------------------- -<1> The username/principal of the anonymous user. This setting is optional and will be set to `_es_anonymous_user` by default - when not configured. -<2> The roles that will be associated with the anonymous user. This setting is mandatory - without it, anonymous access - will be disabled (i.e. anonymous requests will be rejected and return an authentication error) -<3> When `true`, a HTTP 403 response will be returned when the anonymous user does not have the appropriate permissions - for the requested action. The web browser will not be prompt the user to provide credentials to access the requested - resource. When set to `false`, a HTTP 401 will be returned allowing for credentials to be provided for a user with - the appropriate permissions. If you are using anonymous access in combination with HTTP, setting this to `false` may - be necessary if your client does not support preemptive basic authentication. This setting is optional and will be - set to `true` by default. \ No newline at end of file diff --git a/shield/docs/public/setting-up-authentication/integrating-other-auth-systems.asciidoc b/shield/docs/public/setting-up-authentication/integrating-other-auth-systems.asciidoc deleted file mode 100644 index 62f305ca949..00000000000 --- a/shield/docs/public/setting-up-authentication/integrating-other-auth-systems.asciidoc +++ /dev/null @@ -1,56 +0,0 @@ -[[custom-realms]] -=== Integrating with Other Authentication Systems - -If you are using an authentication system other than LDAP, Active Directory, or PKI, you can -create a custom realm to interact with the system to authenticate users. You implement a custom -realm as an Elasticsearch plugin. - -[[implementing-custom-realm]] -==== Implementing a Custom Realm - -Sample code that illustrates the structure and implementation of a custom realm is provided in the -https://github.com/elastic/shield-custom-realm-example[shield-custom-realm-example] repository on -GitHub. You can use this code as a starting point for creating your own realm. - -To create a custom realm, you need to: - -. Extend `org.elasticsearch.shield.authc.Realm` to communicate with your authentication system -to authenticate users. -. Extend `org.elasticsearch.shield.authc.Realm.Factory` to construct your new realm type. -. Extend `org.elasticsearch.shield.authc.DefaultAuthenticationFailureHandler` to handle authentication -failures when using your custom realm. - -To package your custom realm as an Elasticsearch plugin: - -. Implement a plugin class for your realm that extends `org.elasticsearch.plugins.Plugin`. -You need to: -.. Import your realm implementation files, `org.elasticsearch.plugins.Plugin`, and -`org.elasticsearch.shield.authc.AuthenticationModule`. -.. Implement the `name` and `description` methods. -.. Implement the `onModule` method to register the custom realm with the Shield `AuthenticationModule` -and specify your authentication failure handler. -. Create a Maven configuration file (`pom.xml`) for the plugin. -. Create a https://github.com/elastic/elasticsearch/blob/master/dev-tools/src/main/resources/plugin-metadata/plugin-descriptor.properties[plugin-descriptor.properties] file for the plugin. - -For more information about Elasticsearch plugins, see https://www.elastic.co/guide/en/elasticsearch/plugins/2.0/index.html[Elasticsearch Plugins and Integrations]. - -[[using-custom-realm]] -==== Using a Custom Realm to Authenticate Users - -To use a custom realm: - -. Install the realm plugin on each node in the cluster. You run `bin/plugin` with the `install` -option and specify the location of the zip file that contains the plugin. For example: -+ -[source,shell] ----------------------------------------- -bin/plugin install file:////example-realm-plugin-1.0.zip ----------------------------------------- - -. Add a realm configuration of the appropriate realm type to `elasticsearch.yml` in the -`shield.authc.realms` namespace. The options you can set depend on the settings exposed by your -custom realm. At a minimum, you must set the realm `type` to the type defined in the plugin -implementation. If you are configuring multiple realms, you should also explicitly set the -`order` attribute to control the order in which the realms are consulted during authentication. - -. Restart Elasticsearch. \ No newline at end of file diff --git a/shield/docs/public/setting-up-certificate-authority.asciidoc b/shield/docs/public/setting-up-certificate-authority.asciidoc deleted file mode 100644 index 6e2bc782a3c..00000000000 --- a/shield/docs/public/setting-up-certificate-authority.asciidoc +++ /dev/null @@ -1,190 +0,0 @@ -[[certificate-authority]] -== Setting Up a Certificate Authority - -You can set up your own Certificate Authority (CA) to sign node certificates. Using a CA -makes it easier to manage trust within your cluster than using self-signed certificates. Each node -only needs to trust the CA, rather that trusting all of the other nodes' certificates individually. When nodes are added to the cluster, as long as their certificates are signed by a trusted CA, the new nodes are trusted automatically. In contrast, if you use self-signed certificates, you would have to manually configure each node to trust the new node and restart Elasticsearch. - -This topic shows how you can use https://www.openssl.org/[OpenSSL] to create a self-signed CA -certificate and sign CSRs. While it demonstrates how you can set up a CA, it does not necessarily -address your organization's particular security requirements. Before moving to production, you -should consult your organization's security experts to discuss the security requirements for your -use case. - -IMPORTANT: Because a Certificate Authority is a central point of trust, the private keys to the - CA must be protected from compromise. - -To set up a CA: - -. Create the directory structure where the CA configuration and certificates will be stored. You -need to create a `ca` directory and three subdirectories: `private`, `certs`, and `conf`. -+ -[source,shell] --------------------------------------------------- -mkdir -p ca/private ca/certs ca/conf --------------------------------------------------- - -. Populate two required files, `serial` and `index.txt`. -+ -[source,shell] --------------------------------------------------- -cd ca -echo '01' > serial -touch index.txt --------------------------------------------------- - -. Create a CA configuration template and store it in `conf/caconfig.cnf`. You use the -configuration template to set options for the CA that cannot be passed in from the -command line. The following template defines a basic CA configuration you -can use as a starting point. -+ -[source,shell] -------------------------------------------------------------------------------------- -#.................................. -[ ca ] -default_ca = CA_default -[ CA_default ] -copy_extensions = copy <1> -dir = /PATH/TO/YOUR/DIR/ca <2> -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 <3> -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 <4> -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 ---------------------------------------------------------------------------------------- -<1> Copy extensions: Copies all X509 V3 extensions from a Certificate Signing Request into the -signed certificate. With the value set to `copy`, you need to ensure the extensions and their -values are valid for the certificate being requested prior to signing the certificate. -<2> CA directory: Add the full path to this newly created CA. -<3> Certificate validity period: The default number of days that a certificate signed by this -CA is valid for. Note that certificates signed by a CA must expire before the CA certificate -expires. -<4> Certificate defaults: The `OrganizationName`, `localityName`, `stateOrProvinceName`, -`countryName`, and `emailAddress` fields specify the default Distinguished Name information. - -. Generate a self-signed CA certificate to establish your CA as an authority. For example, the following command generates a key and certificate using the `caconfig.cnf` template. You specify -where you want to store the CA's private key and certificate with the `-keyout` and `-out` options, and specify how long the certificate is valid with the `-days` option. -+ -[source,shell] ------------------------------------------------------------------------------- -openssl req -new -x509 -extensions v3_ca -keyout private/cakey.pem -out certs/cacert.pem -days 1460 -config conf/caconfig.cnf ------------------------------------------------------------------------------- -+ -NOTE: When the CA certificate expires, trust in the CA is revoked and you need to generate a new CA certificate and re-sign your node certificates. -+ -When you run `openssl` to generate a CA certificate, you are prompted to enter a PEM passphrase to encrypt the CA's private key and can override the default Distinguished Name information. -+ -WARNING: You cannot recover the CA without the PEM passphrase. -+ -The following example shows what the interaction looks like: -+ -[source,shell] ---------------------------------------------------------------------------------------------------- -openssl req -new -x509 -extensions v3_ca -keyout private/cakey.pem -out certs/cacert.pem -days 1460 -config conf/caconfig.cnf -Generating a 2048 bit RSA private key -.....................++++++ -.......++++++ -writing new private key to 'private/cakey.pem' -Enter PEM pass phrase: -Verifying - Enter PEM pass phrase: -#----- -You are about to be asked to enter information that will be incorporated -into your certificate request. -What you are about to enter is what is called a Distinguished Name or a DN. -There are quite a few fields but you can leave some blank -For some fields there will be a default value, -If you enter '.', the field will be left blank. -#----- -Organization Name (company) [Elasticsearch Test Org]: -Organizational Unit Name (department, division) []:. -Email Address [cacerttest@YOUR.COMPANY.TLD]:. -Locality Name (city, district) [Amsterdam]:. -State or Province Name (full name) [Amsterdam]:. -Country Name (2 letter code) [NL]:. -Common Name (hostname, IP, or your name) []:Elasticsearch Test CA ---------------------------------------------------------------------------------------------------- - -Once you've generated a certificate for your CA, you can use it to enable trust between your nodes. -You sign each node's certificate using your CA, and install the CA certificate and signed node -certificate in each node's keystore or truststore. For more information, see -<> and <>. - -[float] -[[sign-csr]] -=== Signing CSRs - -You sign a node's certificate to vouch for that node's identity. If a node trusts your CA -certificate, it automatically trusts any certificates you sign. - -To sign a node's certificate: - -. <> from the node. - -. Use your CA to sign the CSR using `openssl`. For example, the following command signs -the `node01.csr` and saves the signed certificate in `node01-signed.crt`. You must specify -your CA's configuration file with the `-config` option. -+ -[source,shell] ------------------------------------------------------------------------------ -openssl ca -in node01.csr -notext -out node01-signed.crt -config conf/caconfig.cnf -extensions v3_req ------------------------------------------------------------------------------ -+ -The signed certificate contains the node's original unsigned certificate, your CA certificate, and -a signature. - -Once you've signed the CSR, you need to <> in the node's keystore. - - diff --git a/shield/docs/public/setting-up-field-and-document-level-security.asciidoc b/shield/docs/public/setting-up-field-and-document-level-security.asciidoc deleted file mode 100644 index 873693efb1c..00000000000 --- a/shield/docs/public/setting-up-field-and-document-level-security.asciidoc +++ /dev/null @@ -1,162 +0,0 @@ -[[setting-up-field-and-document-level-security]] -=== Setting Up Field and Document Level Security - -You can control access to data within an index by adding field and document level security permissions to a role. -Field level security permissions restrict access to particular fields within a document. -Document level security permissions restrict access to particular documents within an index. - -Field and document level permissions are specified separately, but a role can define both field and document level permissions. -Field and document level security permissions can be configured on a per-index basis. - -IMPORTANT: Document and Field Level Security is disabled by default. Set `shield.dls_fls.enabled` to `true` in `elasticsearch.yml` to enable it. You cannot submit `_bulk` update requests when document and field level security is enabled. - -==== Field Level Security - -To enable field level security, you specify the fields that each role can access in the `roles.yml` file. -You list the allowed fields with the `fields` option. Fields are associated with a particular index or index pattern and -operate in conjunction with the privileges specified for the indices. - -[source,yaml] --------------------------------------------------- -: - indices: - : - privileges: - fields: - - - - - - --------------------------------------------------- - -To allow access to the `_all` meta field, you must explicitly list it as an allowed field. Access to the following meta fields -is always allowed: _id, _type, _parent, _routing, _timestamp, _ttl, _size and _index. If you specify an empty list of fields, -only these meta fields are accessible. - -NOTE: Omitting the fields entry entirely disables field-level security. - -For example, the following `customer_care` role grants read access to six fields in any index: - -[source,yaml] --------------------------------------------------- -customer_care: - indices: - '*': - privileges: read - fields: - - issue_id - - description - - customer_handle - - customer_email - - customer_address - - customer_phone --------------------------------------------------- - -Also wildcard field expressions can be added to the `fields` options in the `roles.yml` file. For example the following -example has the same effect as the previous example: - -[source,yaml] --------------------------------------------------- -customer_care: - indices: - '*': - privileges: read - fields: - - issue_id - - description - - 'customer_*' --------------------------------------------------- - -If documents are more complex and contain json objects then the fields with dot notion should be used. - -Assume the following document: - -[source,json] --------------------------------------------------- -{ - "customer": { - "handle": "Jim", - "email": "jim@mycompany.com", - "phone": "555-555-5555" - } -} --------------------------------------------------- - -If only access to the `handle` field is allowed then the following role should be setup: - -[source,yaml] --------------------------------------------------- -my_role: - indices: - '*': - privileges: read - fields: - - customer.handle --------------------------------------------------- - -If access to the entire `customer` object is allowed then the wildcard dot notation can be used to make this easier: - -[source,yaml] --------------------------------------------------- -my_role: - indices: - '*': - privileges: read - fields: - - customer.* --------------------------------------------------- - -===== Limitations - -When field level security is enabled for an index: - -* The get, multi get, termsvector and multi termsvector APIs aren't executed in real time. The realtime option for these APIs is forcefully set to false. -* The query cache and the request cache are disabled for search requests. -* The update API is blocked. An update request needs to be executed via a role that doesn't have field level security enabled. - -[[document-level-security]] -==== Document Level Security - -Enabling document level security restricts which documents can be accessed from any document based API. -To enable document level security, you use a query to specify the documents that each role can access in the `roles.yml` file. -You specify the document query with the `query` option. The document query is associated with a particular index or index pattern and -operates in conjunction with the privileges specified for the indices. - -[source,yaml] --------------------------------------------------- -: - indices: - : - privileges: - query: - --------------------------------------------------- - -NOTE: Omitting the `query` entry entirely disables document-level security. - -The `query` should follow the same format as if a query was defined in the request body of a search request, -but here the format is YAML. Any query from the query-dsl can be defined in the `query` entry. - -For example, the following `customer_care` role grants read access to all indices, but restricts access to documents whose `department_id` equals `12`. - -[source,yaml] --------------------------------------------------- -customer_care: - indices: - '*': - privileges: read - query: - term: - department_id: 12 --------------------------------------------------- - -Alternatively the query can also be defined in JSON as a string. This makes it easier to define queries that already have -been defined in the JSON body of search request body elsewhere. - -[source,yaml] --------------------------------------------------- -customer_care: - indices: - '*': - privileges: read - query: '{"term" : {"department_id" : "12"}}'' --------------------------------------------------- diff --git a/shield/docs/public/submitting-requests-for-other-users.asciidoc b/shield/docs/public/submitting-requests-for-other-users.asciidoc deleted file mode 100644 index 1b3eda8922e..00000000000 --- a/shield/docs/public/submitting-requests-for-other-users.asciidoc +++ /dev/null @@ -1,31 +0,0 @@ -[[submitting-requests-for-other-users]] -=== Submitting Requests on Behalf of Other Users - -Shield supports a permission that enables an authenticated user to submit requests on behalf -of other users. If your application already authenticates users, you can use this -_run as_ mechanism to restrict data access according to Shield permissions without having -to re-authenticate each user through Shield. - -To run as another user, you must be able to retrieve the user from the realm you use -to authenticate. The `esusers` realm supports this out of the box. To use `run_as` with -an LDAP realm, it must be configured to enable user search. For more information, -see <>. - -To submit requests on behalf of other users, you need to have the `run_as` -permission. For example, the following `run_as_role` grants permision to submit request on -behalf of `jacknich` or `redeniro`: - -[source,yaml] ---------------------------------------------------- -run_as_role: - run_as: jacknich, rdeniro ---------------------------------------------------- - -For information about assigning roles, see <>. - -To submit a request as another user, you specify the user in the request header. For example: - -[source,console] ---------------------------------------------------- -curl -H "es-shield-runas-user: jacknich" -u es_admin -XGET 'http://localhost:9200/' ---------------------------------------------------- \ No newline at end of file diff --git a/shield/docs/public/troubleshooting.asciidoc b/shield/docs/public/troubleshooting.asciidoc deleted file mode 100644 index 2019f74c9d2..00000000000 --- a/shield/docs/public/troubleshooting.asciidoc +++ /dev/null @@ -1,218 +0,0 @@ -[[troubleshooting]] -== Troubleshooting - -[float] -=== `settings` - -Some settings are not returned via the nodes settings API:: -+ --- -This is intentional. Some of the settings are considered to be highly sensitive (e.g. all `ssl` settings, ldap `bind_dn`, -`bind_password` and `hostname_verification`). For this reason, we filter these settings and not exposing them via the -nodes info API rest endpoint. It is also possible to define additional sensitive settings that should be hidden using -the `shield.hide_settings` setting: - -[source, yaml] ------------------------------------------- -shield.hide_settings: shield.authc.realms.ldap1.url, shield.authc.realms.ad1.* ------------------------------------------- - -The snippet above will also hide the `url` settings of the `ldap1` realm and all settings of the `ad1` realm. --- - -[float] -=== `esusers` - -I configured the appropriate roles and the users, but I still get an authorization exception:: -+ --- -Verify that the role names associated with the users match the roles defined in the `roles.yml` file. You -can use the `esusers` tool to list all the users. Any unknown roles are marked with `*`. - -[source, shell] ------------------------------------------- -esusers list -rdeniro : admin -alpacino : power_user -jacknich : marvel,unknown_role* <1> ------------------------------------------- - -<1> `unknown_role` was not found in `roles.yml` --- - -ERROR: extra arguments [...] were provided:: -+ --- -This error occurs when the esusers tool is parsing the input and finds unexepected arguments. This can happen when there -are special characters used in some of the arguments. For example, on Windows systems the `,` character is considered -a parameter separator; in other words `-r role1,role2` is translated to `-r role1 role2` and the `esusers` tool only recognizes -`role1` as an expected parameter. The solution here is to quote the parameter: `-r "role1,role2"`. --- - -[[trouble-shoot-active-directory]] -[float] -=== Active Directory - -Certain users are being frequently locked out of Active Directory:: -+ --- -Check your realm configuration; realms are checked serially, one after another. If your Active Directory realm is being checked before other realms and there are usernames -that appear in both Active Directory and another realm, a valid login for one realm may be causing failed login attempts in another realm. - -For example, if `UserA` exists in both Active Directory and esusers, and the Active Directory realm is checked first and -esusers is checked second, an attempt to authenticate as `UserA` in the esusers realm would first attempt to authenticate -against Active Directory and fail, before successfully authenticating against the esusers realm. Because authentication is -verified on each request, the Active Directory realm would be checked - and fail - on each request for `UserA` in the esusers -realm. In this case, while the Shield request completed successfully, the account on Active Directory would have received -several failed login attempts, and that account may become temporarily locked out. Plan the order of your realms accordingly. - -Also note that it is not typically necessary to define multiple Active Directory realms to handle domain controller failures. When using Microsoft DNS, the DNS entry for -the domain should always point to an available domain controller. --- - -[float] -=== LDAP - -I can authenticate to LDAP, but I still get an authorization exception:: -+ --- -A number of configuration options can cause this error. - -|====================== -|_group identification_ | - -Groups are located by either an LDAP search or by the "memberOf" attribute on -the user. Also, If subtree search is turned off, it will search only one -level deep. See the <> for all the options. -There are many options here and sticking to the defaults will not work for all -scenarios. - -| _group to role mapping_| - -Either the `role_mapping.yml` file or the location for this file could be -misconfigured. See <> for more. - -|_role definition_| - -Either the `roles.yml` file or the location for this file could be -misconfigured. See <> for more. - -|====================== - -To help track down these possibilities, add `shield.authc: DEBUG` to the `logging.yml` configuration file in `CONFIG_DIR`. -A successful authentication should produce debug statements that list groups and role mappings. --- - - -[float] -=== Encryption & Certificates - -`curl` on the Mac returns a certificate verification error even when the `--cacert` option is used:: -+ --- -Apple's integration of `curl` with their keychain technology disables the `--cacert` option. -See http://curl.haxx.se/mail/archive-2013-10/0036.html for more information. - -You can use another tool, such as `wget`, to test certificates. Alternately, you can add the certificate for the -signing certificate authority MacOS system keychain, using a procedure similar to the one detailed at the -http://support.apple.com/kb/PH14003[Apple knowledge base]. Be sure to add the signing CA's certificate and not the server's certificate. --- - -[float] -==== SSLHandshakeException causing connections to fail - -A `SSLHandshakeException` will cause a connection to a node to fail and indicates that there is a configuration issue. Some of the -common exceptions are shown below with tips on how to resolve these issues. - -`java.security.cert.CertificateException: No name matching node01.example.com found`:: -+ --- -Indicates that a client connection was made to `node01.example.com` but the certificate returned did not contain the name `node01.example.com`. -In most cases, the issue can be resolved by ensuring the name is specified as a `SubjectAlternativeName` during <>. -Another scenario is when the environment does not wish to use DNS names in certificates at all. In this scenario, all settings -in `elasticsearch.yml` should only use IP addresses and the following setting needs to be set in `elasticsearch.yml`: -[source, yaml] --------------------------------------------------- -shield.ssl.hostname_verification.resolve_name: false --------------------------------------------------- --- - -`java.security.cert.CertificateException: No subject alternative names present`:: -+ --- -Indicates that a client connection was made to an IP address but the returned certificate did not contain any `SubjectAlternativeName` entries. -IP addresses are only used for hostname verification if they are specified as a `SubjectAlternativeName` during -<>. If the intent was to use IP addresses for hostname verification, then the certificate -will need to be regenerated. Also verify that `shield.ssl.hostname_verification.resolve_name: false` is *not* set in -`elasticsearch.yml`. --- - -`javax.net.ssl.SSLHandshakeException: null cert chain` and `javax.net.ssl.SSLException: Received fatal alert: bad_certificate`:: -+ --- -The `SSLHandshakeException` above indicates that a self-signed certificate was returned by the client that is not trusted -as it cannot be found in the `truststore` or `keystore`. The `SSLException` above is seen on the client side of the connection. --- - -`sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target` and `javax.net.ssl.SSLException: Received fatal alert: certificate_unknown`:: -+ --- -The `SunCertPathBuilderException` above indicates that a certificate was returned during the handshake that is not trusted. -This message is seen on the client side of the connection. The `SSLException` above is seen on the server side of the -connection. The CA certificate that signed the returned certificate was not found in the `keystore` or `truststore` and -needs to be added to trust this certificate. --- - -[float] -==== Other SSL/TLS related exceptions - -The are other exceptions related to SSL that may be seen in the logs. Below you will find some common exceptions and their -meaning. - -WARN: received plaintext http traffic on a https channel, closing connection:: -+ --- -Indicates that there was an incoming plaintext http request. This typically occurs when an external applications attempts -to make an unencrypted call to the REST interface. Please ensure that all applications are using `https` when calling the -REST interface with SSL enabled. --- - -`org.elasticsearch.common.netty.handler.ssl.NotSslRecordException: not an SSL/TLS record:`:: -+ --- -Indicates that there was incoming plaintext traffic on an SSL connection. This typically occurs when a node is not -configured to use encrypted communication and tries to connect to nodes that are using encrypted communication. Please -verify that all nodes are using the same setting for `shield.transport.ssl`. --- - -`java.io.StreamCorruptedException: invalid internal transport message format, got`:: -+ --- -Indicates an issue with data received on the transport interface in an unknown format. This can happen when a node with -encrypted communication enabled connects to a node that has encrypted communication disabled. Please verify that all -nodes are using the same setting for `shield.transport.ssl`. --- - -`java.lang.IllegalArgumentException: empty text`:: -+ --- -The exception is typically seen when a `https` request is made to a node that is not using `https`. If `https` is desired, -please ensure the following setting is in `elasticsearch.yml`: - -[source,yaml] ----------------- -shield.http.ssl: true ----------------- --- - -ERROR: unsupported ciphers [...] were requested but cannot be used in this JVM:: -+ --- -This error occurs when a SSL/TLS cipher suite is specified that cannot supported by the JVM that Elasticsearch is running -in. Shield will try to use the specified cipher suites that are supported by this JVM. This error can occur when using -the Shield defaults as some distributions of OpenJDK do not enable the PKCS11 provider by default. In this case, we -recommend consulting your JVM documentation for details on how to enable the PKCS11 provider. - -Another common source of this error is requesting cipher suites that use encrypting with a key length greater than 128 bits -when running on an Oracle JDK. In this case, you will need to install the <>. --- \ No newline at end of file diff --git a/watcher/build.gradle b/watcher/build.gradle deleted file mode 100644 index 7d2c5d7e4c3..00000000000 --- a/watcher/build.gradle +++ /dev/null @@ -1,75 +0,0 @@ -import org.elasticsearch.gradle.MavenFilteringHack - -apply plugin: 'elasticsearch.esplugin' -esplugin { - name 'watcher' - description 'Elasticsearch Watcher' - classname 'org.elasticsearch.watcher.WatcherPlugin' - isolated false -} - -ext.versions = [ - okhttp: '2.3.0' -] - -// TODO: fix this! https://github.com/elastic/x-plugins/issues/1066 -ext.compactProfile = 'full' - -dependencies { - provided project(path: ':x-plugins:license:plugin', configuration: 'runtime') - provided project(path: ':x-plugins:shield', configuration: 'runtime') - - compile 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:r239' - compile 'com.google.guava:guava:16.0.1' - compile 'com.google.code.findbugs:jsr305:3.0.1' - compile 'com.sun.mail:javax.mail:1.5.3' - compile 'javax.activation:activation:1.1.1' - - testCompile 'org.subethamail:subethasmtp:3.1.7' - - // mock web server - testCompile "com.squareup.okhttp:mockwebserver:${versions.okhttp}" - testCompile "com.squareup.okhttp:okhttp:${versions.okhttp}" - testCompile "com.squareup.okhttp:okhttp-ws:${versions.okhttp}" - testCompile 'com.squareup.okio:okio:1.3.0' - testCompile 'org.bouncycastle:bcprov-jdk15on:1.50' - - testCompile 'org.slf4j:slf4j-log4j12:1.6.2' - testCompile 'org.slf4j:slf4j-api:1.6.2' - testCompile 'org.elasticsearch:securemock:1.1' -} - -compileJava.options.compilerArgs << "-Xlint:-deprecation,-rawtypes,-serial,-try,-unchecked" -compileTestJava.options.compilerArgs << "-Xlint:-deprecation,-rawtypes,-serial,-try,-unchecked" - -integTest { - cluster { - plugin 'license', project(':x-plugins:license:plugin') - } -} - -// TODO: standardize packaging config for plugins -bundlePlugin { - from(projectDir) { - include 'LICENSE.txt' - include 'NOTICE.txt' - } - from('bin/watcher') { - into 'bin' - } -} - -dependencyLicenses.enabled = false - -// TODO: don't publish test artifacts just to run messy tests, fix the tests! -// https://github.com/elastic/x-plugins/issues/724 -configurations { - testArtifacts.extendsFrom testRuntime -} -task testJar(type: Jar) { - classifier "test" - from sourceSets.test.output -} -artifacts { - testArtifacts testJar -} diff --git a/watcher/docs/administering-watcher.asciidoc b/watcher/docs/administering-watcher.asciidoc deleted file mode 100644 index a16a195c390..00000000000 --- a/watcher/docs/administering-watcher.asciidoc +++ /dev/null @@ -1,25 +0,0 @@ -[[administering-watcher]] -== Administering Watcher - -This section describes how to configure options for watcher, use Shield to secure access to the -Watcher APIs, get information about Watcher, and monitor watch execution. - -include::administering-watcher/configuring-email.asciidoc[] - -include::administering-watcher/configuring-hipchat.asciidoc[] - -include::administering-watcher/configuring-slack.asciidoc[] - -include::administering-watcher/integrating-with-shield.asciidoc[] - -include::administering-watcher/integrating-with-logstash.asciidoc[] - -include::administering-watcher/configuring-default-throttle-period.asciidoc[] - -include::administering-watcher/configuring-default-http-timeouts.asciidoc[] - -include::administering-watcher/configuring-default-internal-ops-timeouts.asciidoc[] - -include::administering-watcher/getting-watcher-statistics.asciidoc[] - -include::administering-watcher/monitoring-watch-execution.asciidoc[] diff --git a/watcher/docs/administering-watcher/configuring-default-http-timeouts.asciidoc b/watcher/docs/administering-watcher/configuring-default-http-timeouts.asciidoc deleted file mode 100644 index 4afbf7d8e30..00000000000 --- a/watcher/docs/administering-watcher/configuring-default-http-timeouts.asciidoc +++ /dev/null @@ -1,21 +0,0 @@ -[[configuring-default-http-timeouts]] -=== Configuring the Default HTTP Timeouts - -All HTTP requests in watcher (e.g. used by the <> and <>) -are associated with two timeouts: - -Connection Timeout :: Determines how long should the request wait for the HTTP - connection to be established before failing the request. - -Read Timeout :: Assuming the connenction was established, this timeout - determines how long should the request wait for a - response before failing the request. - -By default, both timeouts are set to 10 seconds. It is possible to change this -default using the following settings in `elasticsearch.yml`: - -[source,yaml] --------------------------------------------------- -watcher.http.default_connection_timeout: 5s -watcher.http.default_read_timeout: 20s --------------------------------------------------- \ No newline at end of file diff --git a/watcher/docs/administering-watcher/configuring-default-internal-ops-timeouts.asciidoc b/watcher/docs/administering-watcher/configuring-default-internal-ops-timeouts.asciidoc deleted file mode 100644 index 0e806378b0a..00000000000 --- a/watcher/docs/administering-watcher/configuring-default-internal-ops-timeouts.asciidoc +++ /dev/null @@ -1,22 +0,0 @@ -[[configuring-default-internal-ops-timeouts]] -=== Configuring the Default Internal Operations Timeouts - -While Watcher is active, it often accesses different indices in Elasticsearch. -These can be internal indices used for its ongoing operation (such as the `.watches` -index where all the watches are stored) or as part of a watch execution via the -<>, <> or the -<>. - -To to ensure that Watcher's workflow doesn't hang on long running search or -indexing operations, these operations time out after a set period of time. You can -change the default timeouts in `elasticsearch.yml`. The timeouts you can configure -are shown in the following table. - -[[default-internal-ops-timeouts]] -[options="header"] -|====== -| Name | Default | Description -| `watcher.internal.ops.search.default_timeout` | 30s | The default timeout for all internal search operations. -| `watcher.internal.ops.index.default_timeout` | 60s | The default timeout for all internal index operations. -| `watcher.internal.ops.bulk.default_timeout` | 120s | The default timeout for all internal bulk operations. -|====== \ No newline at end of file diff --git a/watcher/docs/administering-watcher/configuring-default-throttle-period.asciidoc b/watcher/docs/administering-watcher/configuring-default-throttle-period.asciidoc deleted file mode 100644 index 1b12012152e..00000000000 --- a/watcher/docs/administering-watcher/configuring-default-throttle-period.asciidoc +++ /dev/null @@ -1,19 +0,0 @@ -[[configuring-default-throttle-period]] -=== Configuring the Default Throttle Period - -By default, Watcher uses a default throttle period of 5 seconds. You can override this -for particular actions by setting the throttle period in the action. You can also -define a throttle period on the watch level that will serve as a default period for -all those actions that don't specify a throttle period themselves. - -To change the default throttle period for all actions that are not configured with a -throttle period neither on the action level nor the watch level, you configure the -`watcher.execution.default_throttle_period` setting in `elasticsearch.yml`. - -For example, to set the default throttle period to 15 minutes, add the following entry -to your `elasticsearch.yml` file and restart Elasticsearch: - -[source,yaml] --------------------------------------------------- -watcher.execution.default_throttle_period: 15m --------------------------------------------------- \ No newline at end of file diff --git a/watcher/docs/administering-watcher/configuring-email.asciidoc b/watcher/docs/administering-watcher/configuring-email.asciidoc deleted file mode 100644 index 50b5a9a8254..00000000000 --- a/watcher/docs/administering-watcher/configuring-email.asciidoc +++ /dev/null @@ -1,270 +0,0 @@ -[[email-services]] -=== Configuring Watcher to Send Email -You can configure Watcher to send email from any SMTP email service. Email messages can contain -basic HTML tags. You can control which tags are allowed by -<>. - -[[email-account]] -==== Configuring Email Accounts -You configure the accounts Watcher can use to send email in your `elasticsearch.yml` configuration file. -Each account configuration has a unique name and specifies all of the SMTP information needed -to send email from that account. You can also specify defaults for all emails that are sent through -the account. For example, you can set defaults for the `from` and `bcc` fields to ensure that all -emails are sent from the same address and always blind copied to the same address. - -IMPORTANT: If your email account is configured to require two step verification, - you need to generate and use a unique App Password to send email from - Watcher. Authentication will fail if you use your primary password. - -If you configure multiple email accounts, you specify which account the email should be sent -with in the <> action. If there is only one account configured, you -do not have to specify the `account` attribute in the action definition. However, if you configure -multiple accounts and omit the `account` attribute, there is no guarantee which account will be -used to send the email. - -To add an email account, set the `watcher.actions.email.service.account` property in -`elasticsearch.yml`. See <> for the -supported attributes. - -For example, the following snippet configures a single Gmail account named `work`. - -[source,yaml] --------------------------------------------------- -watcher.actions.email.service.account: - work: - profile: gmail - email_defaults: - from: 'John Doe ' - bcc: archive@host.domain - smtp: - auth: true - starttls.enable: true - host: smtp.gmail.com - port: 587 - user: - password: --------------------------------------------------- - -[[email-profile]] -The _email profile_ defines a strategy for building a MIME message. As with almost every standard -out there, different email systems interpret the MIME standard differently and have slightly -different ways of structuring MIME messages. Watcher provides three email profiles: `standard` -(default), `gmail`, and `outlook`. - -If you are using Gmail or Outlook, we recommend using the corresponding profile. Use the `standard` -profile if you are using some other email system. For more information about configuring Watcher -to work with different email systems, see: - -* <> -* <> -* <> -* <> - -[[email-account-attributes]] -.Email Account Attributes -[options="header"] -|====== -| Name | Required | Default | Description -| `profile` | no | standard | The <> to use to - build the MIME messages that are sent from - the account. Valid values: `standard` - (default), `gmail` and `outlook`. -| `email_defaults.*` | no | - | An optional set of email attributes to use - as defaults for the emails sent from the - account. See <> for the supported - attributes. for the possible email - attributes) -| `smtp.auth` | no | false | When `true`, attempt to authenticate the - user using the AUTH command. -| `smtp.host` | yes | - | The SMTP server to connect to. -| `smtp.port` | no | 25 | The SMTP server port to connect to. -| `smtp.user` | yes | - | The user name for SMTP. -| `smtp.password` | no | - | The password for the specified SMTP user. -| `smtp.starttls.enable` | no | false | When `true`, enables the use of the - `STARTTLS` command (if supported by - the server) to switch the connection to a - TLS-protected connection before issuing any - login commands. Note that an appropriate - trust store must configured so that the - client will trust the server's certificate. - Defaults to `false`. -| `smtp.*` | no | - | SMTP attributes that enable fine control - over the SMTP protocol when sending messages. - See https://javamail.java.net/nonav/docs/api/com/sun/mail/smtp/package-summary.html[com.sun.mail.smtp] - for the full list of SMTP properties you can - set. -|====== - -[[gmail]] -===== Sending Email From Gmail - -Use the following email account settings to send email from the https://mail.google.com[Gmail] -SMTP service: - -[source,yaml] --------------------------------------------------- -watcher.actions.email.service.account: - gmail_account: - profile: gmail - smtp: - auth: true - starttls.enable: true - host: smtp.gmail.com - port: 587 - user: - password: --------------------------------------------------- - -If you get an authentication error that indicates that you need to continue the -sign-in process from a web browser when Watcher attempts to send email, you need -to configure Gmail to https://support.google.com/accounts/answer/6010255?hl=en[Allow Less -Secure Apps to access your account]. - -If two-step verification is enabled for your account, you must generate and use -a unique App Password to send email from Watcher.See -https://support.google.com/accounts/answer/185833?hl=en[Sign in using App Passwords] -for more information. - -[[outlook]] -===== Sending Email from Outlook.com - -Use the following email account settings to send email action from the -https://www.outlook.com/[Outlook.com] SMTP service: - -[source,yaml] --------------------------------------------------- -watcher.actions.email.service.account: - outlook_account: - profile: outlook - smtp: - auth: true - starttls.enable: true - host: smtp-mail.outlook.com - port: 587 - user: - password: --------------------------------------------------- - -NOTE: You need to use a unique App Password if two-step verification is enabled. - See http://windows.microsoft.com/en-us/windows/app-passwords-two-step-verification[App - passwords and two-step verification] for more information. - -[[amazon-ses]] -===== Sending Email from Amazon SES (Simple Email Service) - -Use the following email account settings to send email from the -http://aws.amazon.com/ses[Amazon Simple Email Service] (SES) SMTP service: - -[source,yaml] --------------------------------------------------- -watcher.actions.email.service.account: - ses_account: - smtp: - auth: true - starttls.enable: true - starttls.required: true - host: email-smtp.us-east-1.amazonaws.com <1> - port: 587 - user: - password: --------------------------------------------------- - -<1> `smtp.host` varies depending on the region - -NOTE: You need to use your Amazon SES SMTP credentials to send email through - Amazon SES. For more information, see http://docs.aws.amazon.com/ses/latest/DeveloperGuide/smtp-credentials.html[Obtaining Your Amazon SES SMTP Credentials]. - -[[exchange]] -===== Sending Email from Microsoft Exchange - -Use the following email account settings to send email action from Microsoft Exchange: - -[source,yaml] --------------------------------------------------- -watcher.actions.email.service.account: - exchange_account: - profile: outlook - email_defaults: - from: <1> - smtp: - auth: true - starttls.enable: true - host: - port: 587 - user: <2> - password: --------------------------------------------------- - -<1> Some organizations configure Exchange to validate that the `from` field is a - valid local email account. -<2> Many organizations support use of your email address as your username, though - it is a good idea to check with your system administrator if you receive - authentication-related failures. - - -// [[postfix]] -// ===== Sending Email from Postfix - -// Use the following email account settings to send email from the http://www.postfix.org[Postfix] SMTP service: - -// [source,yaml] -// -------------------------------------------------- -// TODO -// -------------------------------------------------- - -[[email-html-sanitization]] -==== Configuring HTML Sanitization Options - -The `email` action supports sending messages with an HTML body. However, for security reasons, -Watcher https://en.wikipedia.org/wiki/HTML_sanitization[sanitizes] the HTML. - -You can control which HTML features are allowed or disallowed by configuring the -`watcher.actions.email.html.sanitization.allow` and -`watcher.actions.email.html.sanitization.disallow` settings in `elasticsearch.yml`. You can specify -individual HTML elements and the feature groups described in the following table. By default, -Watcher allows the following features: `body`, `head`, `_tables`, `_links`, `_blocks`, `_formatting` -and `img:embedded`. - - -[options="header"] -|====== -| Name | Description - -| `_tables` | All table related elements: ``, `` and `
`, `
`. - -| `_blocks` | The following block elements: `

`, `

`, `

`, `

`, `

`, - `

`, `

`, `
`, `