diff --git a/README.md b/README.md deleted file mode 100644 index 37aecd4c25f..00000000000 --- a/README.md +++ /dev/null @@ -1,36 +0,0 @@ -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/core/pom.xml b/core/pom.xml deleted file mode 100644 index f00cc1bd64a..00000000000 --- a/core/pom.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - elasticsearch-license - org.elasticsearch - 2.0.0.beta1-SNAPSHOT - - 4.0.0 - - ${project.parent.basedir} - - true - - elasticsearch-license-core - diff --git a/core/src/main/java/org/elasticsearch/license/core/CryptUtils.java b/core/src/main/java/org/elasticsearch/license/core/CryptUtils.java deleted file mode 100644 index 939b5192828..00000000000 --- a/core/src/main/java/org/elasticsearch/license/core/CryptUtils.java +++ /dev/null @@ -1,245 +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.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/core/src/main/java/org/elasticsearch/license/core/DateUtils.java b/core/src/main/java/org/elasticsearch/license/core/DateUtils.java deleted file mode 100644 index 80b42aa82bf..00000000000 --- a/core/src/main/java/org/elasticsearch/license/core/DateUtils.java +++ /dev/null @@ -1,44 +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.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/core/src/main/java/org/elasticsearch/license/core/License.java b/core/src/main/java/org/elasticsearch/license/core/License.java deleted file mode 100644 index a1495a67c17..00000000000 --- a/core/src/main/java/org/elasticsearch/license/core/License.java +++ /dev/null @@ -1,433 +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.license.core; - -import org.elasticsearch.ElasticsearchException; -import org.elasticsearch.ElasticsearchParseException; -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.XContentBuilderString; -import org.elasticsearch.common.xcontent.XContentParser; - -import java.io.IOException; - -/** - * 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_CURRENT = VERSION_START; - - 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 License(String uid, String issuer, String issuedTo, long issueDate, String type, - String subscriptionType, String feature, String signature, long expiryDate, int maxNodes) { - 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; - } - - - /** - * @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 subscription type of the license [none, silver, gold, platinum] - */ - public String subscriptionType() { - return subscriptionType; - } - - /** - * @return the issueDate in milliseconds - */ - public long issueDate() { - return issueDate; - } - - /** - * @return the featureType for the license [shield, marvel] - */ - public String feature() { - return feature; - } - - /** - * @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; - } - - public 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) { - throw new IllegalStateException("subscriptionType can not be null"); - } else if (uid == null) { - throw new IllegalStateException("uid can not be null"); - } else if (feature == null) { - throw new IllegalStateException("at least one feature has to be enabled"); - } 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"); - } - } - - 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.uid(in.readString()); - builder.type(in.readString()); - builder.subscriptionType(in.readString()); - builder.issueDate(in.readLong()); - 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_CURRENT); - out.writeString(uid); - out.writeString(type); - out.writeString(subscriptionType); - out.writeLong(issueDate); - out.writeString(feature); - out.writeLong(expiryDate); - out.writeInt(maxNodes); - out.writeString(issuedTo); - out.writeString(issuer); - out.writeOptionalString(signature); - } - - @Override - public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - boolean licenseSpecMode = params.paramAsBoolean(Licenses.LICENSE_SPEC_VIEW_MODE, false); - boolean restViewMode = params.paramAsBoolean(Licenses.REST_VIEW_MODE, false); - boolean previouslyHumanReadable = builder.humanReadable(); - if (licenseSpecMode && restViewMode) { - throw new IllegalArgumentException("can have either " + Licenses.REST_VIEW_MODE + " or " + Licenses.LICENSE_SPEC_VIEW_MODE); - } else if (restViewMode) { - if (!previouslyHumanReadable) { - builder.humanReadable(true); - } - } - builder.startObject(); - if (restViewMode) { - String status = "active"; - long now = System.currentTimeMillis(); - if (issueDate > now) { - status = "invalid"; - } else if (expiryDate < now) { - status = "expired"; - } - builder.field(XFields.STATUS, status); - } - builder.field(XFields.UID, uid); - builder.field(XFields.TYPE, type); - builder.field(XFields.SUBSCRIPTION_TYPE, subscriptionType); - builder.dateValueField(XFields.ISSUE_DATE_IN_MILLIS, XFields.ISSUE_DATE, issueDate); - 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); - } - builder.endObject(); - if (restViewMode) { - builder.humanReadable(previouslyHumanReadable); - } - return builder; - } - - - 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 SIGNATURE = "signature"; - } - - private final static class XFields { - static final XContentBuilderString STATUS = new XContentBuilderString(Fields.STATUS); - static final XContentBuilderString UID = new XContentBuilderString(Fields.UID); - static final XContentBuilderString TYPE = new XContentBuilderString(Fields.TYPE); - static final XContentBuilderString SUBSCRIPTION_TYPE = new XContentBuilderString(Fields.SUBSCRIPTION_TYPE); - static final XContentBuilderString ISSUE_DATE_IN_MILLIS = new XContentBuilderString(Fields.ISSUE_DATE_IN_MILLIS); - static final XContentBuilderString ISSUE_DATE = new XContentBuilderString(Fields.ISSUE_DATE); - static final XContentBuilderString FEATURE = new XContentBuilderString(Fields.FEATURE); - static final XContentBuilderString EXPIRY_DATE_IN_MILLIS = new XContentBuilderString(Fields.EXPIRY_DATE_IN_MILLIS); - static final XContentBuilderString EXPIRY_DATE = new XContentBuilderString(Fields.EXPIRY_DATE); - static final XContentBuilderString MAX_NODES = new XContentBuilderString(Fields.MAX_NODES); - static final XContentBuilderString ISSUED_TO = new XContentBuilderString(Fields.ISSUED_TO); - static final XContentBuilderString ISSUER = new XContentBuilderString(Fields.ISSUER); - static final 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 String uid; - private String issuer; - private String issuedTo; - private long issueDate = -1; - private String type; - private String subscriptionType = "none"; - 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 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()) - .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); - } - - public Builder fromXContent(XContentParser parser) throws IOException { - XContentParser.Token token = parser.currentToken(); - if (token == XContentParser.Token.START_OBJECT) { - 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)) { - uid(parser.text()); - } else if (Fields.TYPE.equals(currentFieldName)) { - type(parser.text()); - } else if (Fields.SUBSCRIPTION_TYPE.equals(currentFieldName)) { - subscriptionType(parser.text()); - } else if (Fields.ISSUE_DATE.equals(currentFieldName)) { - issueDate(parseDate(parser, "issue", false)); - } else if (Fields.ISSUE_DATE_IN_MILLIS.equals(currentFieldName)) { - issueDate(parser.longValue()); - } else if (Fields.FEATURE.equals(currentFieldName)) { - feature(parser.text()); - } else if (Fields.EXPIRY_DATE.equals(currentFieldName)) { - expiryDate(parseDate(parser, "expiration", true)); - } else if (Fields.EXPIRY_DATE_IN_MILLIS.equals(currentFieldName)) { - expiryDate(parser.longValue()); - } else if (Fields.MAX_NODES.equals(currentFieldName)) { - maxNodes(parser.intValue()); - } else if (Fields.ISSUED_TO.equals(currentFieldName)) { - issuedTo(parser.text()); - } else if (Fields.ISSUER.equals(currentFieldName)) { - issuer(parser.text()); - } else if (Fields.SIGNATURE.equals(currentFieldName)) { - signature(parser.text()); - } - // 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(); - } - } - } - } else { - throw new ElasticsearchParseException("failed to parse licenses expected a license object"); - } - return this; - } - - public License build() { - return new License(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 (subscriptionType == null) { - throw new IllegalStateException("subscriptionType can not be null"); - } else if (uid == null) { - throw new IllegalStateException("uid can not be null"); - } else if (feature == null) { - throw new IllegalStateException("at least one feature has to be enabled"); - } 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; - } - } - -} diff --git a/core/src/main/java/org/elasticsearch/license/core/LicenseVerifier.java b/core/src/main/java/org/elasticsearch/license/core/LicenseVerifier.java deleted file mode 100644 index ff007986049..00000000000 --- a/core/src/main/java/org/elasticsearch/license/core/LicenseVerifier.java +++ /dev/null @@ -1,159 +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.license.core; - -import org.elasticsearch.common.Base64; -import org.elasticsearch.common.io.Streams; -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.nio.file.Files; -import java.nio.file.Path; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.security.Signature; -import java.security.SignatureException; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; - -/** - * Responsible for verifying signed licenses - * The signed licenses are expected to have signatures with the appropriate spec - * (see {@link org.elasticsearch.license.core.LicenseVerifier}) - * along with the appropriate encrypted public key - */ -public class LicenseVerifier { - - /** - * Verifies Licenses using {@link #verifyLicense(License, byte[])} using the public key from the - * resources - */ - public static boolean verifyLicenses(final Collection licenses) { - final byte[] encryptedPublicKeyData = getPublicKeyContentFromResource("/public.key"); - try { - for (License license : licenses) { - if (!verifyLicense(license, encryptedPublicKeyData)) { - return false; - } - } - return true; - } finally { - Arrays.fill(encryptedPublicKeyData, (byte) 0); - } - } - - /** - * Verifies Licenses using {@link #verifyLicense(License, byte[])} using the provided public key - */ - public static boolean verifyLicenses(final Collection licenses, final Path publicKeyPath) throws IOException { - final byte[] encryptedPublicKeyData = Files.readAllBytes(publicKeyPath); - try { - for (License license : licenses) { - if (!verifyLicense(license, encryptedPublicKeyData)) { - return false; - } - } - return true; - } finally { - Arrays.fill(encryptedPublicKeyData, (byte) 0); - } - } - - public static boolean verifyLicense(final License license) { - final byte[] encryptedPublicKeyData = getPublicKeyContentFromResource("/public.key"); - try { - return verifyLicense(license, encryptedPublicKeyData); - } finally { - Arrays.fill(encryptedPublicKeyData, (byte) 0); - } - } - - /** - * verifies the license content with the signature and ensures that an expected public key is used - * @param license to verify - * @return true if valid, false otherwise - */ - public static boolean verifyLicense(final License license, final byte[] encryptedPublicKeyData) { - LicenseSignature licenseSignature = null; - try { - XContentBuilder contentBuilder = XContentFactory.contentBuilder(XContentType.JSON); - license.toXContent(contentBuilder, new ToXContent.MapParams(Collections.singletonMap(Licenses.LICENSE_SPEC_VIEW_MODE, "true"))); - licenseSignature = parseSignature(license.signature()); - if(!verifyContent(encryptedPublicKeyData, contentBuilder.bytes().toBytes(), licenseSignature.contentSignature)) { - return false; - } - final byte[] hash = Base64.encodeBytesToBytes(encryptedPublicKeyData); - return Arrays.equals(hash, licenseSignature.hash); - } catch (IOException e) { - throw new IllegalStateException(e); - } finally { - if (licenseSignature != null) { - licenseSignature.clear(); - } - } - } - - private static boolean verifyContent(byte[] encryptedPublicKeyData, byte[] data, byte[] contentSignature) { - try { - Signature rsa = Signature.getInstance("SHA512withRSA"); - rsa.initVerify(CryptUtils.readEncryptedPublicKey(encryptedPublicKeyData)); - rsa.update(data); - return rsa.verify(contentSignature); - } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) { - throw new IllegalStateException(e); - } - } - - private static byte[] getPublicKeyContentFromResource(String resource) { - try { - return Streams.copyToBytesFromClasspath(resource); - } catch (IOException ex) { - throw new IllegalStateException(ex); - } - } - - /** - * Signature structure: - * | VERSION | MAGIC | PUB_KEY_DIGEST | SIGNED_LICENSE_CONTENT | - */ - private static LicenseSignature parseSignature(String signature) throws IOException { - byte[] signatureBytes = Base64.decode(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(); - byte[] hash = new byte[hashLen]; - byteBuffer.get(hash); - int signedContentLen = byteBuffer.getInt(); - byte[] signedContent = new byte[signedContentLen]; - byteBuffer.get(signedContent); - return new LicenseSignature(version, hash, signedContent); - } - - private static class LicenseSignature { - private final int version; - private final byte[] hash; - private final byte[] contentSignature; - - private LicenseSignature(int version, byte[] hash, byte[] contentSignature) { - this.version = version; - this.hash = hash; - this.contentSignature = contentSignature; - } - - private void clear() { - Arrays.fill(hash, (byte)0); - Arrays.fill(contentSignature, (byte)0); - } - } -} diff --git a/core/src/main/java/org/elasticsearch/license/core/Licenses.java b/core/src/main/java/org/elasticsearch/license/core/Licenses.java deleted file mode 100644 index e4e37b6b5ba..00000000000 --- a/core/src/main/java/org/elasticsearch/license/core/Licenses.java +++ /dev/null @@ -1,149 +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.license.core; - -import com.google.common.collect.ImmutableMap; -import org.elasticsearch.ElasticsearchParseException; -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.charset.StandardCharsets; -import java.util.*; - -/** - * Utility class for operating on a collection of {@link License}s. - * Provides serialization/deserialization methods and reduce - * operations - */ -public final class Licenses { - - /** - * 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"; - - private final static class Fields { - static final String LICENSES = "licenses"; - } - - private final static class XFields { - static final XContentBuilderString LICENSES = new XContentBuilderString(Fields.LICENSES); - } - - private Licenses() {} - - public static void toXContent(Collection licenses, XContentBuilder builder, ToXContent.Params params) throws IOException { - builder.startObject(); - builder.startArray(XFields.LICENSES); - for (License license : licenses) { - license.toXContent(builder, params); - } - builder.endArray(); - builder.endObject(); - } - - public static List fromSource(String content) throws IOException { - return fromSource(content.getBytes(StandardCharsets.UTF_8), true); - } - - public static List fromSource(byte[] bytes) throws IOException { - return fromXContent(XContentFactory.xContent(bytes).createParser(bytes), true); - } - - public static List fromSource(byte[] bytes, boolean verify) throws IOException { - return fromXContent(XContentFactory.xContent(bytes).createParser(bytes), verify); - } - - public static List fromXContent(XContentParser parser, boolean verify) throws IOException { - List licenses = new ArrayList<>(); - if (parser.nextToken() == XContentParser.Token.START_OBJECT) { - if (parser.nextToken() == XContentParser.Token.FIELD_NAME) { - String currentFieldName = parser.currentName(); - if (Fields.LICENSES.equals(currentFieldName)) { - if (parser.nextToken() == XContentParser.Token.START_ARRAY) { - while (parser.nextToken() != XContentParser.Token.END_ARRAY) { - License.Builder builder = License.builder().fromXContent(parser); - if (verify) { - builder.validate(); - } - licenses.add(builder.build()); - } - } else { - throw new ElasticsearchParseException("failed to parse licenses expected an array of licenses"); - } - } - // 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 licenses; - } - - public static List readFrom(StreamInput in) throws IOException { - int size = in.readVInt(); - List licenses = new ArrayList<>(size); - for (int i = 0; i < size; i++) { - licenses.add(License.readLicense(in)); - } - return licenses; - } - - public static void writeTo(List licenses, StreamOutput out) throws IOException { - out.writeVInt(licenses.size()); - for (License license : licenses) { - license.writeTo(out); - } - } - - /** - * Given a set of {@link License}s, reduces the set to one license per feature. - * Uses {@link #putIfAppropriate(java.util.Map, License)} to reduce. - * - * @param licensesSet a set of licenses to be reduced - * @return a map of (feature, license) - */ - public static ImmutableMap reduceAndMap(Set licensesSet) { - Map map = new HashMap<>(licensesSet.size()); - for (License license : licensesSet) { - putIfAppropriate(map, license); - } - return ImmutableMap.copyOf(map); - } - - /** - * Adds or updates the license to licenseMap if the license - * has not expired already and if the license has a later expiry date from any - * existing licenses in licenseMap for the same feature - * - * @param licenseMap a map of (feature, license) - * @param license a new license to be added to licenseMap - */ - private static void putIfAppropriate(Map licenseMap, License license) { - final String featureType = license.feature(); - if (licenseMap.containsKey(featureType)) { - final License previousLicense = licenseMap.get(featureType); - if (license.expiryDate() > previousLicense.expiryDate()) { - licenseMap.put(featureType, license); - } - } else { - licenseMap.put(featureType, license); - } - } -} diff --git a/core/src/test/java/org/elasticsearch/license/core/LicenseSerializationTests.java b/core/src/test/java/org/elasticsearch/license/core/LicenseSerializationTests.java deleted file mode 100644 index ee790c8dc41..00000000000 --- a/core/src/test/java/org/elasticsearch/license/core/LicenseSerializationTests.java +++ /dev/null @@ -1,115 +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.license.core; - -import com.google.common.collect.ImmutableMap; -import org.elasticsearch.common.xcontent.*; -import org.elasticsearch.test.ElasticsearchTestCase; -import org.junit.Test; - -import java.nio.charset.StandardCharsets; -import java.util.*; - -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 ElasticsearchTestCase { - - @Test - 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(Arrays.asList(new TestUtils.LicenseSpec("shield", issueDate, expiryDate))); - Set licensesOutput = new HashSet<>(Licenses.fromSource(licenseSpecs.getBytes(StandardCharsets.UTF_8), false)); - License generatedLicense = licensesOutput.iterator().next(); - - assertThat(licensesOutput.size(), equalTo(1)); - assertThat(generatedLicense.issueDate(), equalTo(DateUtils.beginningOfTheDay(issueDate))); - assertThat(generatedLicense.expiryDate(), equalTo(DateUtils.endOfTheDay(expiryDate))); - } - - @Test - public void testMultipleIssueExpiryDate() throws Exception { - long now = System.currentTimeMillis(); - String shieldIssueDate = TestUtils.dateMathString("now", now); - String shieldExpiryDate = TestUtils.dateMathString("now+30d/d", now); - String marvelIssueDate = TestUtils.dateMathString("now", now); - String marvelExpiryDate = TestUtils.dateMathString("now+60d/d", now); - String licenseSpecs = TestUtils.generateLicenseSpecString(Arrays.asList(new TestUtils.LicenseSpec("shield", shieldIssueDate, shieldExpiryDate))); - String licenseSpecs1 = TestUtils.generateLicenseSpecString(Arrays.asList(new TestUtils.LicenseSpec("marvel", marvelIssueDate, marvelExpiryDate))); - Set licensesOutput = new HashSet<>(); - licensesOutput.addAll(Licenses.fromSource(licenseSpecs.getBytes(StandardCharsets.UTF_8), false)); - licensesOutput.addAll(Licenses.fromSource(licenseSpecs1.getBytes(StandardCharsets.UTF_8), false)); - assertThat(licensesOutput.size(), equalTo(2)); - for (License license : licensesOutput) { - assertThat(license.issueDate(), equalTo(DateUtils.beginningOfTheDay((license.feature().equals("shield")) ? shieldIssueDate : marvelIssueDate))); - assertThat(license.expiryDate(), equalTo(DateUtils.endOfTheDay((license.feature().equals("shield")) ? shieldExpiryDate : marvelExpiryDate))); - } - } - - @Test - public void testLicensesFields() throws Exception { - Map licenseSpecs = new HashMap<>(); - for (int i = 0; i < randomIntBetween(1, 5); i++) { - TestUtils.LicenseSpec randomLicenseSpec = TestUtils.generateRandomLicenseSpec(); - licenseSpecs.put(randomLicenseSpec.feature, randomLicenseSpec); - } - - ArrayList specs = new ArrayList<>(licenseSpecs.values()); - String licenseSpecsSource = TestUtils.generateLicenseSpecString(specs); - Set licensesOutput = new HashSet<>(Licenses.fromSource(licenseSpecsSource.getBytes(StandardCharsets.UTF_8), false)); - assertThat(licensesOutput.size(), equalTo(licenseSpecs.size())); - - for (License license : licensesOutput) { - TestUtils.LicenseSpec spec = licenseSpecs.get(license.feature()); - assertThat(spec, notNullValue()); - TestUtils.assertLicenseSpec(spec, license); - } - } - - @Test - 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); - - Set licenses = TestUtils.generateLicenses(Arrays.asList(new TestUtils.LicenseSpec("expired_feature", validLicenseIssueDate, expiredLicenseExpiryDate) - , new TestUtils.LicenseSpec("valid_feature", validLicenseIssueDate, validLicenseExpiryDate), - new TestUtils.LicenseSpec("invalid_feature", invalidLicenseIssueDate, validLicenseExpiryDate))); - - assertThat(licenses.size(), equalTo(3)); - for (License license : licenses) { - XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON); - license.toXContent(builder, new ToXContent.MapParams(ImmutableMap.of(Licenses.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()); - if (license.feature().equals("valid_feature")) { - assertThat((String) map.get("status"), equalTo("active")); - } else if (license.feature().equals("expired_feature")) { - assertThat((String) map.get("status"), equalTo("expired")); - } else if (license.feature().equals("invalid_feature")) { - assertThat((String) map.get("status"), equalTo("invalid")); - } - } - - for (License license : licenses) { - XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON); - license.toXContent(builder, ToXContent.EMPTY_PARAMS); - builder.flush(); - Map map = XContentHelper.convertToMap(builder.bytesStream().bytes(), false).v2(); - assertThat(map.get("status"), nullValue()); - } - } -} diff --git a/core/src/test/java/org/elasticsearch/license/core/TestUtils.java b/core/src/test/java/org/elasticsearch/license/core/TestUtils.java deleted file mode 100644 index 5465a7d2b40..00000000000 --- a/core/src/test/java/org/elasticsearch/license/core/TestUtils.java +++ /dev/null @@ -1,224 +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.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.ElasticsearchTestCase.randomFrom; -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); - private final static DateTimeFormatter dateTimeFormatter = formatDateTimeFormatter.printer(); - - public static void isSame(Set firstLicenses, Set secondLicenses) { - - // we do the verifyAndBuild to make sure we weed out any expired licenses - final Map licenses1 = Licenses.reduceAndMap(firstLicenses); - final Map licenses2 = Licenses.reduceAndMap(secondLicenses); - - // check if the effective licenses have the same feature set - assertThat(licenses1.size(), equalTo(licenses2.size())); - - // for every feature license, check if all the attributes are the same - for (String featureType : licenses1.keySet()) { - License license1 = licenses1.get(featureType); - License license2 = licenses2.get(featureType); - isSame(license1, license2); - } - } - - public static void isSame(License license1, License license2) { - assertThat(license1.uid(), equalTo(license2.uid())); - assertThat(license1.feature(), equalTo(license2.feature())); - assertThat(license1.subscriptionType(), equalTo(license2.subscriptionType())); - assertThat(license1.type(), equalTo(license2.type())); - assertThat(license1.issuedTo(), equalTo(license2.issuedTo())); - assertThat(license1.signature(), equalTo(license2.signature())); - assertThat(license1.expiryDate(), equalTo(license2.expiryDate())); - assertThat(license1.issueDate(), equalTo(license2.issueDate())); - assertThat(license1.maxNodes(), equalTo(license2.maxNodes())); - } - - 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() { - boolean datesInMillis = randomBoolean(); - long now = System.currentTimeMillis(); - String uid = UUID.randomUUID().toString(); - String feature = "feature__" + randomInt(); - String issuer = "issuer__" + randomInt(); - String issuedTo = "issuedTo__" + randomInt(); - String type = randomFrom("subscription", "internal", "development"); - String subscriptionType = randomFrom("none", "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(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(uid, feature, issueDate, expiryDate, type, subscriptionType, issuedTo, issuer, maxNodes); - } - } - - public static String generateLicenseSpecString(List licenseSpecs) throws IOException { - XContentBuilder licenses = jsonBuilder(); - licenses.startObject(); - licenses.startArray("licenses"); - for (LicenseSpec licenseSpec : licenseSpecs) { - 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.endObject(); - } - licenses.endArray(); - licenses.endObject(); - return licenses.string(); - } - - public static Set generateLicenses(List licenseSpecs) { - Set unSignedLicenses = new HashSet<>(); - for (TestUtils.LicenseSpec spec : licenseSpecs) { - 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); - } - unSignedLicenses.add(builder.build()); - } - return unSignedLicenses; - } - - public static void assertLicenseSpec(LicenseSpec spec, License license) { - MatcherAssert.assertThat(license.uid(), equalTo(spec.uid)); - MatcherAssert.assertThat(license.feature(), equalTo(spec.feature)); - MatcherAssert.assertThat(license.issuedTo(), equalTo(spec.issuedTo)); - MatcherAssert.assertThat(license.issuer(), equalTo(spec.issuer)); - MatcherAssert.assertThat(license.type(), equalTo(spec.type)); - MatcherAssert.assertThat(license.subscriptionType(), equalTo(spec.subscriptionType)); - 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 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 feature, String issueDate, String expiryDate) { - this(UUID.randomUUID().toString(), feature, issueDate, expiryDate, "trial", "none", "customer", "elasticsearch", 5); - } - - public LicenseSpec(String uid, String feature, long issueDateInMillis, long expiryDateInMillis, String type, - String subscriptionType, String issuedTo, String issuer, int maxNodes) { - 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(String uid, String feature, String issueDate, String expiryDate, String type, - String subscriptionType, String issuedTo, String issuer, int maxNodes) { - 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/core/src/test/resources/log4j.properties b/core/src/test/resources/log4j.properties deleted file mode 100644 index 76defc8660c..00000000000 --- a/core/src/test/resources/log4j.properties +++ /dev/null @@ -1,11 +0,0 @@ -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/core/src/test/resources/private.key b/core/src/test/resources/private.key deleted file mode 100644 index 1f545803d87..00000000000 Binary files a/core/src/test/resources/private.key and /dev/null differ diff --git a/core/src/test/resources/public.key b/core/src/test/resources/public.key deleted file mode 100644 index 2a9f272e0b3..00000000000 --- a/core/src/test/resources/public.key +++ /dev/null @@ -1,3 +0,0 @@ -qngwM}UiK0b2غq]쇴c+I &IJf~ ]d}oOId -5A(쵴^WDJ}-O?uN5vp{t7 #Vqktwm]Lz"| QlQs><}[2Z|57%D -Yxn:lLH2HvEEW\H:6h9 [!+;.w7C_| Ӫ*D`?xU/3>xUӓ+ \ No newline at end of file diff --git a/dev-tools/license/elasticsearch_license_header.txt b/dev-tools/license/elasticsearch_license_header.txt deleted file mode 100644 index 16883fa729d..00000000000 --- a/dev-tools/license/elasticsearch_license_header.txt +++ /dev/null @@ -1,15 +0,0 @@ -ELASTICSEARCH CONFIDENTIAL -__________________ - - [2014] Elasticsearch Incorporated - All Rights Reserved. - -NOTICE: All information contained herein is, and remains -the property of Elasticsearch Incorporated and its suppliers, -if any. The intellectual and technical concepts contained -herein are proprietary to Elasticsearch Incorporated -and its suppliers and may be covered by U.S. and Foreign Patents, -patents in process, and are protected by trade secret or copyright law. -Dissemination of this information or reproduction of this material -is strictly forbidden unless prior written permission is obtained -from Elasticsearch Incorporated. diff --git a/dev-tools/license/license_header_definition.xml b/dev-tools/license/license_header_definition.xml deleted file mode 100644 index 1cc53bda001..00000000000 --- a/dev-tools/license/license_header_definition.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - /* - * - */ - - (\s|\t)*/\*.*$ - .*\*/(\s|\t)*$ - false - true - - diff --git a/licensor/bin/key-pair-generator b/licensor/bin/key-pair-generator deleted file mode 100755 index 4a72e028ab4..00000000000 --- a/licensor/bin/key-pair-generator +++ /dev/null @@ -1,55 +0,0 @@ -#!/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 - -# real getopt cannot be used because we need to hand options over to the KeyPairGeneratorTool -while [ $# -gt 0 ]; do - case $1 in - -D*=*) - properties="$properties $1" - ;; - -D*) - var=$1 - shift - properties="$properties $var=$1" - ;; - *) - args="$args $1" - esac - shift -done - -exec "$JAVA" $JAVA_OPTS -Xmx64m -Xms16m $properties -cp "$LICENSE_CLASSPATH" org.elasticsearch.license.licensor.tools.KeyPairGeneratorTool $args - diff --git a/licensor/bin/license-generator b/licensor/bin/license-generator deleted file mode 100755 index 97c8ae9631c..00000000000 --- a/licensor/bin/license-generator +++ /dev/null @@ -1,55 +0,0 @@ -#!/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 - -# real getopt cannot be used because we need to hand options over to the LicenseGeneratorTool -while [ $# -gt 0 ]; do - case $1 in - -D*=*) - properties="$properties $1" - ;; - -D*) - var=$1 - shift - properties="$properties $var=$1" - ;; - *) - args="$args $1" - esac - shift -done - -exec "$JAVA" $JAVA_OPTS -Xmx64m -Xms16m $properties -cp "$LICENSE_CLASSPATH" org.elasticsearch.license.licensor.tools.LicenseGeneratorTool $args - diff --git a/licensor/bin/verify-license b/licensor/bin/verify-license deleted file mode 100755 index 492e3b75bb3..00000000000 --- a/licensor/bin/verify-license +++ /dev/null @@ -1,55 +0,0 @@ -#!/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 - -# real getopt cannot be used because we need to hand options over to the LicenseVerificationTool -while [ $# -gt 0 ]; do - case $1 in - -D*=*) - properties="$properties $1" - ;; - -D*) - var=$1 - shift - properties="$properties $var=$1" - ;; - *) - args="$args $1" - esac - shift -done - -exec "$JAVA" $JAVA_OPTS -Xmx64m -Xms16m $properties -cp "$LICENSE_CLASSPATH" org.elasticsearch.license.licensor.tools.LicenseVerificationTool $args - diff --git a/licensor/pom.xml b/licensor/pom.xml deleted file mode 100644 index a8290c535e8..00000000000 --- a/licensor/pom.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - elasticsearch-license - org.elasticsearch - 2.0.0.beta1-SNAPSHOT - - 4.0.0 - - elasticsearch-license-licensor - - - ${project.parent.basedir} - ${basedir}/src/main/assemblies/exec.xml - true - - true - - - - - org.elasticsearch - elasticsearch-license-core - 2.0.0.beta1-SNAPSHOT - - - - - - - org.apache.maven.plugins - maven-assembly-plugin - - - org.apache.maven.plugins - maven-jar-plugin - - - for-exec - prepare-package - - jar - - - exec - - - public.key - - - - - - - - diff --git a/licensor/sample/license_spec.json b/licensor/sample/license_spec.json deleted file mode 100644 index b2c60e97613..00000000000 --- a/licensor/sample/license_spec.json +++ /dev/null @@ -1 +0,0 @@ -{"licenses":[{"uid": "893361dc-9749-4997-93cb-802e3d7fa4a8", "type":"internal","subscription_type":"none","issued_to":"issuedTo","issuer":"issuer","issue_date":"2014-09-29","expiry_date":"2015-08-29","feature":"shield","max_nodes":1}]} diff --git a/licensor/src/main/assemblies/exec.xml b/licensor/src/main/assemblies/exec.xml deleted file mode 100644 index 7eb1e0d1549..00000000000 --- a/licensor/src/main/assemblies/exec.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - exec - - zip - - true - - - true - bin - bin - 0755 - 0755 - unix - - key-pair-generator - license-generator - verify-license - - - - - - /lib - false - true - true - - org.elasticsearch:elasticsearch-license-licensor:*:exec - org.elasticsearch:elasticsearch - - - org.apache.lucene:* - - - - /lib - false - true - true - - org.apache.lucene:lucene-core - - - - \ No newline at end of file diff --git a/licensor/src/main/java/org/elasticsearch/license/licensor/LicenseSigner.java b/licensor/src/main/java/org/elasticsearch/license/licensor/LicenseSigner.java deleted file mode 100644 index d5361219a1c..00000000000 --- a/licensor/src/main/java/org/elasticsearch/license/licensor/LicenseSigner.java +++ /dev/null @@ -1,104 +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.license.licensor; - -import com.google.common.collect.ImmutableSet; -import org.elasticsearch.common.Base64; -import org.elasticsearch.common.SuppressForbidden; -import org.elasticsearch.common.io.PathUtils; -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.Licenses; -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; -import java.util.Set; - -/** - * Responsible for generating a license signature according to - * the signature spec and sign it with the provided encrypted private key - */ -@SuppressForbidden(reason = "can we avoid bare string paths and resolve from Environment or similar?") -public class LicenseSigner { - - private final static int MAGIC_LENGTH = 13; - - private final Path publicKeyPath; - - private final Path privateKeyPath; - - public LicenseSigner(final String privateKeyPath, final String publicKeyPath) { - this(PathUtils.get(privateKeyPath), PathUtils.get(publicKeyPath)); - } - - public LicenseSigner(final Path privateKeyPath, final Path publicKeyPath) { - this.publicKeyPath = publicKeyPath; - this.privateKeyPath = privateKeyPath; - } - - - public ImmutableSet sign(Set licenseSpecs) throws IOException { - final ImmutableSet.Builder builder = ImmutableSet.builder(); - for (License licenseSpec : licenseSpecs) { - builder.add(sign(licenseSpec)); - } - return builder.build(); - } - - /** - * Generates a signature for the licenseSpec. - * Signature structure: - * | VERSION | MAGIC | PUB_KEY_DIGEST | SIGNED_LICENSE_CONTENT | - * - * @return a signed License - * @throws java.io.IOException - */ - public License sign(License licenseSpec) throws IOException { - XContentBuilder contentBuilder = XContentFactory.contentBuilder(XContentType.JSON); - licenseSpec.toXContent(contentBuilder, new ToXContent.MapParams(Collections.singletonMap(Licenses.LICENSE_SPEC_VIEW_MODE, "true"))); - - final byte[] signedContent = sign(contentBuilder.bytes().toBytes(), privateKeyPath); - 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(License.VERSION_CURRENT) - .putInt(magic.length) - .put(magic) - .putInt(hash.length) - .put(hash) - .putInt(signedContent.length) - .put(signedContent); - - return License.builder() - .fromLicenseSpec(licenseSpec, Base64.encodeBytes(bytes)) - .validate() - .build(); - } - - private static byte[] sign(byte[] data, Path privateKeyPath) { - try { - final Signature rsa = Signature.getInstance("SHA512withRSA"); - rsa.initSign(CryptUtils.readEncryptedPrivateKey(Files.readAllBytes(privateKeyPath))); - rsa.update(data); - return rsa.sign(); - } catch (InvalidKeyException | IOException | NoSuchAlgorithmException | SignatureException e) { - throw new IllegalStateException(e); - } - } -} diff --git a/licensor/src/main/java/org/elasticsearch/license/licensor/tools/KeyPairGeneratorTool.java b/licensor/src/main/java/org/elasticsearch/license/licensor/tools/KeyPairGeneratorTool.java deleted file mode 100644 index ec9cfb7a97b..00000000000 --- a/licensor/src/main/java/org/elasticsearch/license/licensor/tools/KeyPairGeneratorTool.java +++ /dev/null @@ -1,102 +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.license.licensor.tools; - -import org.apache.commons.cli.CommandLine; -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.homeFile().resolve(commandLine.getOptionValue("publicKeyPath")); - Path privateKeyPath = environment.homeFile().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 { - int status = new KeyPairGeneratorTool().execute(args); - System.exit(status); - } -} diff --git a/licensor/src/main/java/org/elasticsearch/license/licensor/tools/LicenseGeneratorTool.java b/licensor/src/main/java/org/elasticsearch/license/licensor/tools/LicenseGeneratorTool.java deleted file mode 100644 index 9bbd915c815..00000000000 --- a/licensor/src/main/java/org/elasticsearch/license/licensor/tools/LicenseGeneratorTool.java +++ /dev/null @@ -1,126 +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.license.licensor.tools; - -import com.google.common.collect.ImmutableSet; -import org.apache.commons.cli.CommandLine; -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.core.Licenses; -import org.elasticsearch.license.licensor.LicenseSigner; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.HashSet; -import java.util.Set; - -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 Set licenseSpecs; - public final Path publicKeyFilePath; - public final Path privateKeyFilePath; - - public LicenseGenerator(Terminal terminal, Path publicKeyFilePath, Path privateKeyFilePath, Set licenseSpecs) { - super(terminal); - this.licenseSpecs = licenseSpecs; - this.privateKeyFilePath = privateKeyFilePath; - this.publicKeyFilePath = publicKeyFilePath; - } - - public static Command parse(Terminal terminal, CommandLine commandLine, Environment environment) throws IOException { - Path publicKeyPath = environment.homeFile().resolve(commandLine.getOptionValue("publicKeyPath")); - Path privateKeyPath = environment.homeFile().resolve(commandLine.getOptionValue("privateKeyPath")); - String[] licenseSpecSources = commandLine.getOptionValues("license"); - String[] licenseSpecSourceFiles = commandLine.getOptionValues("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"); - } - - Set licenseSpecs = new HashSet<>(); - if (licenseSpecSources != null) { - for (String licenseSpec : licenseSpecSources) { - licenseSpecs.addAll(Licenses.fromSource(licenseSpec.getBytes(StandardCharsets.UTF_8), false)); - } - } - - if (licenseSpecSourceFiles != null) { - for (String licenseSpecFilePath : licenseSpecSourceFiles) { - Path licenseSpecPath = environment.homeFile().resolve(licenseSpecFilePath); - if (!Files.exists(licenseSpecPath)) { - return exitCmd(ExitStatus.USAGE, terminal, licenseSpecFilePath + " does not exist"); - } - licenseSpecs.addAll(Licenses.fromSource(Files.readAllBytes(licenseSpecPath), false)); - } - } - - if (licenseSpecs.size() == 0) { - return exitCmd(ExitStatus.USAGE, terminal, "no license spec provided"); - } - return new LicenseGenerator(terminal, publicKeyPath, privateKeyPath, licenseSpecs); - } - - @Override - public ExitStatus execute(Settings settings, Environment env) throws Exception { - - // sign - ImmutableSet signedLicences = new LicenseSigner(privateKeyFilePath, publicKeyFilePath).sign(licenseSpecs); - - // dump - XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON); - Licenses.toXContent(signedLicences, builder, ToXContent.EMPTY_PARAMS); - builder.flush(); - terminal.print(builder.string()); - - return ExitStatus.OK; - } - } - - public static void main(String[] args) throws Exception { - int status = new LicenseGeneratorTool().execute(args); - System.exit(status); - } -} diff --git a/licensor/src/main/java/org/elasticsearch/license/licensor/tools/LicenseVerificationTool.java b/licensor/src/main/java/org/elasticsearch/license/licensor/tools/LicenseVerificationTool.java deleted file mode 100644 index 27a0a87a244..00000000000 --- a/licensor/src/main/java/org/elasticsearch/license/licensor/tools/LicenseVerificationTool.java +++ /dev/null @@ -1,126 +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.license.licensor.tools; - -import org.apache.commons.cli.CommandLine; -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.core.Licenses; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -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 Set licenses; - public final Path publicKeyPath; - - public LicenseVerifier(Terminal terminal, Set licenses, Path publicKeyPath) { - super(terminal); - this.licenses = licenses; - this.publicKeyPath = publicKeyPath; - } - - public static Command parse(Terminal terminal, CommandLine commandLine, Environment environment) throws IOException { - String publicKeyPathString = commandLine.getOptionValue("publicKeyPath"); - String[] licenseSources = commandLine.getOptionValues("license"); - String[] licenseSourceFiles = commandLine.getOptionValues("licenseFile"); - - Set licenses = new HashSet<>(); - if (licenseSources != null) { - for (String licenseSpec : licenseSources) { - licenses.addAll(Licenses.fromSource(licenseSpec.getBytes(StandardCharsets.UTF_8))); - } - } - - if (licenseSourceFiles != null) { - for (String licenseFilePath : licenseSourceFiles) { - Path licensePath = environment.homeFile().resolve(licenseFilePath); - if (!Files.exists(licensePath)) { - return exitCmd(ExitStatus.USAGE, terminal, licenseFilePath + " does not exist"); - } - licenses.addAll(Licenses.fromSource(Files.readAllBytes(licensePath))); - } - } - - if (licenses.size() == 0) { - return exitCmd(ExitStatus.USAGE, terminal, "no license provided"); - } - - Path publicKeyPath = environment.homeFile().resolve(publicKeyPathString); - if (!Files.exists(publicKeyPath)) { - return exitCmd(ExitStatus.USAGE, terminal, publicKeyPath + " does not exist"); - } - - return new LicenseVerifier(terminal, licenses, publicKeyPath); - } - - @Override - public ExitStatus execute(Settings settings, Environment env) throws Exception { - - // verify - Map effectiveLicenses = Licenses.reduceAndMap(licenses); - - if (!org.elasticsearch.license.core.LicenseVerifier.verifyLicenses(effectiveLicenses.values(), publicKeyPath)) { - terminal.println("Invalid License(s)!"); - return ExitStatus.DATA_ERROR; - } - - // dump effective licences - XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON); - Licenses.toXContent(effectiveLicenses.values(), builder, ToXContent.EMPTY_PARAMS); - builder.flush(); - terminal.print(builder.string()); - - return ExitStatus.OK; - } - } - - public static void main(String[] args) throws Exception { - int status = new LicenseVerificationTool().execute(args); - System.exit(status); - } -} diff --git a/licensor/src/main/resources/org/elasticsearch/license/licensor/tools/licensor-key-pair-generator.help b/licensor/src/main/resources/org/elasticsearch/license/licensor/tools/licensor-key-pair-generator.help deleted file mode 100644 index c41ed5c0ed7..00000000000 --- a/licensor/src/main/resources/org/elasticsearch/license/licensor/tools/licensor-key-pair-generator.help +++ /dev/null @@ -1,22 +0,0 @@ -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/licensor/src/main/resources/org/elasticsearch/license/licensor/tools/licensor-license-generator.help b/licensor/src/main/resources/org/elasticsearch/license/licensor/tools/licensor-license-generator.help deleted file mode 100644 index 75d507f7dd9..00000000000 --- a/licensor/src/main/resources/org/elasticsearch/license/licensor/tools/licensor-license-generator.help +++ /dev/null @@ -1,26 +0,0 @@ -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/licensor/src/main/resources/org/elasticsearch/license/licensor/tools/licensor-verify-license.help b/licensor/src/main/resources/org/elasticsearch/license/licensor/tools/licensor-verify-license.help deleted file mode 100644 index e36007f3838..00000000000 --- a/licensor/src/main/resources/org/elasticsearch/license/licensor/tools/licensor-verify-license.help +++ /dev/null @@ -1,28 +0,0 @@ -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/licensor/src/test/java/org/elasticsearch/license/licensor/AbstractLicensingTestBase.java b/licensor/src/test/java/org/elasticsearch/license/licensor/AbstractLicensingTestBase.java deleted file mode 100644 index 1cf7fea6219..00000000000 --- a/licensor/src/test/java/org/elasticsearch/license/licensor/AbstractLicensingTestBase.java +++ /dev/null @@ -1,97 +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.license.licensor;/* -import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.license.core.DateUtils; -import org.elasticsearch.license.core.License; -import org.elasticsearch.test.ElasticsearchTestCase; -import org.junit.After; -import org.junit.Before; - -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.UUID; - -public abstract class AbstractLicensingTestBase extends ElasticsearchTestCase { - - protected String pubKeyPath = null; - protected String priKeyPath = null; - - @Before - public void setup() throws Exception { - pubKeyPath = getResourcePath("/public.key"); - priKeyPath = getResourcePath("/private.key"); - } - - @After - public void cleanUp() { - pubKeyPath = null; - priKeyPath = null; - } - - public static Set generateSignedLicenses(List licenseSpecs, String pubKeyPath, String priKeyPath) throws Exception { - LicenseSigner signer = new LicenseSigner(priKeyPath, pubKeyPath); - Set unSignedLicenses = new HashSet<>(); - for (TestUtils.LicenseSpec spec : licenseSpecs) { - 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); - } - unSignedLicenses.add(builder.build()); - } - return signer.sign(unSignedLicenses); - } - - public static License generateSignedLicense(String feature, TimeValue expiryDuration, String pubKeyPath, String priKeyPath) throws Exception { - return generateSignedLicense(feature, -1, expiryDuration, pubKeyPath, priKeyPath); - } - - public static License generateSignedLicense(String feature, long issueDate, TimeValue expiryDuration, String pubKeyPath, String priKeyPath) throws Exception { - long issue = (issueDate != -1l) ? issueDate : System.currentTimeMillis(); - final License licenseSpec = License.builder() - .uid(UUID.randomUUID().toString()) - .feature(feature) - .expiryDate(issue + expiryDuration.getMillis()) - .issueDate(issue) - .type("subscription") - .subscriptionType("gold") - .issuedTo("customer") - .issuer("elasticsearch") - .maxNodes(5) - .build(); - - LicenseSigner signer = new LicenseSigner(priKeyPath, pubKeyPath); - return signer.sign(licenseSpec); - } - - public String getTestPriKeyPath() throws Exception { - return getResourcePath("/private.key"); - } - - public String getTestPubKeyPath() throws Exception { - return getResourcePath("/public.key"); - } - - private String getResourcePath(String resource) throws Exception { - return getDataPath(resource).toString(); - } -} diff --git a/licensor/src/test/java/org/elasticsearch/license/licensor/LicenseVerificationTests.java b/licensor/src/test/java/org/elasticsearch/license/licensor/LicenseVerificationTests.java deleted file mode 100644 index 92191464997..00000000000 --- a/licensor/src/test/java/org/elasticsearch/license/licensor/LicenseVerificationTests.java +++ /dev/null @@ -1,64 +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.license.licensor; - -import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.license.core.License; -import org.elasticsearch.license.core.LicenseVerifier; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Set; - -import static org.hamcrest.Matchers.equalTo; - -public class LicenseVerificationTests extends AbstractLicensingTestBase { - - @Test - public void testGeneratedLicenses() throws Exception { - License shieldLicense = generateSignedLicense("shield", TimeValue.timeValueHours(2 * 24), pubKeyPath, priKeyPath); - assertThat(LicenseVerifier.verifyLicense(shieldLicense), equalTo(true)); - } - - @Test - public void testMultipleFeatureLicenses() throws Exception { - License shieldLicense = generateSignedLicense("shield", TimeValue.timeValueHours(2 * 24), pubKeyPath, priKeyPath); - License marvelLicense = generateSignedLicense("marvel", TimeValue.timeValueHours(2 * 24), pubKeyPath, priKeyPath); - - assertThat(LicenseVerifier.verifyLicenses(Arrays.asList(shieldLicense, marvelLicense)), equalTo(true)); - } - - @Test - public void testLicenseTampering() throws Exception { - License license = generateSignedLicense("shield", 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), equalTo(false)); - } - - @Test - public void testRandomLicenseVerification() throws Exception { - int n = randomIntBetween(5, 15); - List licenseSpecs = new ArrayList<>(); - for (int i = 0; i < n; i++) { - licenseSpecs.add(TestUtils.generateRandomLicenseSpec()); - } - - Set generatedLicenses = generateSignedLicenses(licenseSpecs, pubKeyPath, priKeyPath); - assertThat(generatedLicenses.size(), equalTo(n)); - - for (License generatedLicense: generatedLicenses) { - assertThat(LicenseVerifier.verifyLicense(generatedLicense), equalTo(true)); - } - } -} diff --git a/licensor/src/test/java/org/elasticsearch/license/licensor/TestUtils.java b/licensor/src/test/java/org/elasticsearch/license/licensor/TestUtils.java deleted file mode 100644 index e8473b01054..00000000000 --- a/licensor/src/test/java/org/elasticsearch/license/licensor/TestUtils.java +++ /dev/null @@ -1,213 +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.license.licensor; - -import org.elasticsearch.common.joda.DateMathParser; -import org.elasticsearch.common.joda.FormatDateTimeFormatter; -import org.elasticsearch.common.joda.Joda; -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.license.core.Licenses; -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.ElasticsearchTestCase.randomFrom; -import static org.hamcrest.core.IsEqual.equalTo; -import static org.junit.Assert.assertThat; - -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 void isSame(Set firstLicenses, Set secondLicenses) { - - // we do the verifyAndBuild to make sure we weed out any expired licenses - final Map licenses1 = Licenses.reduceAndMap(firstLicenses); - final Map licenses2 = Licenses.reduceAndMap(secondLicenses); - - // check if the effective licenses have the same feature set - assertThat(licenses1.size(), equalTo(licenses2.size())); - - // for every feature license, check if all the attributes are the same - for (String featureType : licenses1.keySet()) { - License license1 = licenses1.get(featureType); - License license2 = licenses2.get(featureType); - isSame(license1, license2); - } - } - - public static void isSame(License license1, License license2) { - assertThat(license1.uid(), equalTo(license2.uid())); - assertThat(license1.feature(), equalTo(license2.feature())); - assertThat(license1.subscriptionType(), equalTo(license2.subscriptionType())); - assertThat(license1.type(), equalTo(license2.type())); - assertThat(license1.issuedTo(), equalTo(license2.issuedTo())); - assertThat(license1.signature(), equalTo(license2.signature())); - assertThat(license1.expiryDate(), equalTo(license2.expiryDate())); - assertThat(license1.issueDate(), equalTo(license2.issueDate())); - assertThat(license1.maxNodes(), equalTo(license2.maxNodes())); - } - - public static String dumpLicense(License license) throws Exception { - XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON); - Licenses.toXContent(Collections.singletonList(license), builder, ToXContent.EMPTY_PARAMS); - builder.flush(); - 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() { - boolean datesInMillis = randomBoolean(); - long now = System.currentTimeMillis(); - String uid = UUID.randomUUID().toString(); - String feature = "feature__" + randomInt(); - String issuer = "issuer__" + randomInt(); - String issuedTo = "issuedTo__" + randomInt(); - String type = randomFrom("subscription", "internal", "development"); - String subscriptionType = randomFrom("none", "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(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(uid, feature, issueDate, expiryDate, type, subscriptionType, issuedTo, issuer, maxNodes); - } - } - - public static String generateLicenseSpecString(List licenseSpecs) throws IOException { - XContentBuilder licenses = jsonBuilder(); - licenses.startObject(); - licenses.startArray("licenses"); - for (LicenseSpec licenseSpec : licenseSpecs) { - 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.endObject(); - } - licenses.endArray(); - licenses.endObject(); - return licenses.string(); - } - - public static void assertLicenseSpec(LicenseSpec spec, License license) { - MatcherAssert.assertThat(license.uid(), equalTo(spec.uid)); - MatcherAssert.assertThat(license.feature(), equalTo(spec.feature)); - MatcherAssert.assertThat(license.issuedTo(), equalTo(spec.issuedTo)); - MatcherAssert.assertThat(license.issuer(), equalTo(spec.issuer)); - MatcherAssert.assertThat(license.type(), equalTo(spec.type)); - MatcherAssert.assertThat(license.subscriptionType(), equalTo(spec.subscriptionType)); - 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 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 feature, String issueDate, String expiryDate) { - this(UUID.randomUUID().toString(), feature, issueDate, expiryDate, "trial", "none", "customer", "elasticsearch", 5); - } - - public LicenseSpec(String uid, String feature, long issueDateInMillis, long expiryDateInMillis, String type, - String subscriptionType, String issuedTo, String issuer, int maxNodes) { - 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(String uid, String feature, String issueDate, String expiryDate, String type, - String subscriptionType, String issuedTo, String issuer, int maxNodes) { - 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/licensor/src/test/java/org/elasticsearch/license/licensor/tools/KeyPairGenerationToolTests.java b/licensor/src/test/java/org/elasticsearch/license/licensor/tools/KeyPairGenerationToolTests.java deleted file mode 100644 index b7854d4e8b6..00000000000 --- a/licensor/src/test/java/org/elasticsearch/license/licensor/tools/KeyPairGenerationToolTests.java +++ /dev/null @@ -1,100 +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.license.licensor.tools; - -import org.apache.commons.cli.MissingOptionException; -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 org.junit.Test; - -import java.nio.file.Files; -import java.nio.file.Path; - -import static org.elasticsearch.common.cli.CliTool.Command; -import static org.elasticsearch.common.cli.CliTool.ExitStatus; -import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.CoreMatchers.instanceOf; -import static org.hamcrest.core.IsEqual.equalTo; - -public class KeyPairGenerationToolTests extends CliToolTestCase { - - @Test - public void testParsingMissingPath() throws Exception { - KeyPairGeneratorTool keyPairGeneratorTool = new KeyPairGeneratorTool(); - Path tempFile = createTempFile(); - try { - keyPairGeneratorTool.parse(KeyPairGeneratorTool.NAME, args( - "--privateKeyPath " + tempFile.toAbsolutePath())); - fail("no public key path provided"); - } catch (MissingOptionException e) { - assertThat(e.getMessage(), containsString("pub")); - } - try { - keyPairGeneratorTool.parse(KeyPairGeneratorTool.NAME, args( - "--publicKeyPath " + tempFile.toAbsolutePath())); - fail("no private key path provided"); - } catch (MissingOptionException e) { - assertThat(e.getMessage(), containsString("pri")); - } - } - - @Test - 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)); - } - - @Test - 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/licensor/src/test/java/org/elasticsearch/license/licensor/tools/LicenseGenerationToolTests.java b/licensor/src/test/java/org/elasticsearch/license/licensor/tools/LicenseGenerationToolTests.java deleted file mode 100644 index d09fdcd53a4..00000000000 --- a/licensor/src/test/java/org/elasticsearch/license/licensor/tools/LicenseGenerationToolTests.java +++ /dev/null @@ -1,197 +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.license.licensor.tools; - -import org.apache.commons.cli.MissingOptionException; -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.core.Licenses; -import org.elasticsearch.license.licensor.TestUtils; -import org.junit.Before; -import org.junit.Test; - -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.*; - -import static org.elasticsearch.common.cli.CliTool.Command; -import static org.elasticsearch.common.cli.CliTool.ExitStatus; -import static org.elasticsearch.license.licensor.tools.LicenseGeneratorTool.LicenseGenerator; -import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.CoreMatchers.instanceOf; -import static org.hamcrest.Matchers.notNullValue; -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); - } - - @Test - public void testParsingNonExistentKeyFile() throws Exception { - TestUtils.LicenseSpec inputLicenseSpec = TestUtils.generateRandomLicenseSpec(); - LicenseGeneratorTool licenseGeneratorTool = new LicenseGeneratorTool(); - Command command = licenseGeneratorTool.parse(LicenseGeneratorTool.NAME, - new String[] {"--license", TestUtils.generateLicenseSpecString(Arrays.asList(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(Arrays.asList(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)); - } - - @Test - 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)); - } - - @Test - public void testParsingMissingArgs() throws Exception { - TestUtils.LicenseSpec inputLicenseSpec = TestUtils.generateRandomLicenseSpec(); - LicenseGeneratorTool licenseGeneratorTool = new LicenseGeneratorTool(); - boolean pubKeyMissing = randomBoolean(); - try { - licenseGeneratorTool.parse(LicenseGeneratorTool.NAME, - new String[] { "--license", TestUtils.generateLicenseSpecString(Arrays.asList(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")); - } - } - - @Test - public void testParsingSimple() throws Exception { - TestUtils.LicenseSpec inputLicenseSpec = TestUtils.generateRandomLicenseSpec(); - LicenseGeneratorTool licenseGeneratorTool = new LicenseGeneratorTool(); - Command command = licenseGeneratorTool.parse(LicenseGeneratorTool.NAME, - new String[]{"--license", TestUtils.generateLicenseSpecString(Arrays.asList(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)); - assertThat(licenseGenerator.licenseSpecs.size(), equalTo(1)); - License outputLicenseSpec = licenseGenerator.licenseSpecs.iterator().next(); - - TestUtils.assertLicenseSpec(inputLicenseSpec, outputLicenseSpec); - } - - @Test - public void testParsingLicenseFile() throws Exception { - TestUtils.LicenseSpec inputLicenseSpec = TestUtils.generateRandomLicenseSpec(); - Path tempFile = createTempFile(); - Files.write(tempFile, TestUtils.generateLicenseSpecString(Arrays.asList(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)); - assertThat(licenseGenerator.licenseSpecs.size(), equalTo(1)); - License outputLicenseSpec = licenseGenerator.licenseSpecs.iterator().next(); - - TestUtils.assertLicenseSpec(inputLicenseSpec, outputLicenseSpec); - } - - @Test - public void testParsingMultipleLicense() throws Exception { - int n = randomIntBetween(2, 5); - Map inputLicenseSpecs = new HashMap<>(); - for (int i = 0; i < n; i++) { - TestUtils.LicenseSpec licenseSpec = TestUtils.generateRandomLicenseSpec(); - inputLicenseSpecs.put(licenseSpec.feature, licenseSpec); - } - LicenseGeneratorTool licenseGeneratorTool = new LicenseGeneratorTool(); - Command command = licenseGeneratorTool.parse(LicenseGeneratorTool.NAME, - new String[] { "--license", TestUtils.generateLicenseSpecString(new ArrayList<>(inputLicenseSpecs.values())), - "--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)); - assertThat(licenseGenerator.licenseSpecs.size(), equalTo(inputLicenseSpecs.size())); - - for (License outputLicenseSpec : licenseGenerator.licenseSpecs) { - TestUtils.LicenseSpec inputLicenseSpec = inputLicenseSpecs.get(outputLicenseSpec.feature()); - assertThat(inputLicenseSpec, notNullValue()); - TestUtils.assertLicenseSpec(inputLicenseSpec, outputLicenseSpec); - } - } - - @Test - public void testTool() throws Exception { - int n = randomIntBetween(1, 5); - Map inputLicenseSpecs = new HashMap<>(); - for (int i = 0; i < n; i++) { - TestUtils.LicenseSpec licenseSpec = TestUtils.generateRandomLicenseSpec(); - inputLicenseSpecs.put(licenseSpec.feature, licenseSpec); - } - List licenseSpecs = Licenses.fromSource(TestUtils.generateLicenseSpecString(new ArrayList<>(inputLicenseSpecs.values())).getBytes(StandardCharsets.UTF_8), false); - - String output = runLicenseGenerationTool(pubKeyPath, priKeyPath, new HashSet<>(licenseSpecs), ExitStatus.OK); - List outputLicenses = Licenses.fromSource(output.getBytes(StandardCharsets.UTF_8), true); - assertThat(outputLicenses.size(), equalTo(inputLicenseSpecs.size())); - - for (License outputLicense : outputLicenses) { - TestUtils.LicenseSpec inputLicenseSpec = inputLicenseSpecs.get(outputLicense.feature()); - assertThat(inputLicenseSpec, notNullValue()); - TestUtils.assertLicenseSpec(inputLicenseSpec, outputLicense); - } - } - - private String runLicenseGenerationTool(Path pubKeyPath, Path priKeyPath, Set licenseSpecs, 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, licenseSpecs); - 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/licensor/src/test/java/org/elasticsearch/license/licensor/tools/LicenseVerificationToolTests.java b/licensor/src/test/java/org/elasticsearch/license/licensor/tools/LicenseVerificationToolTests.java deleted file mode 100644 index ec7601e0618..00000000000 --- a/licensor/src/test/java/org/elasticsearch/license/licensor/tools/LicenseVerificationToolTests.java +++ /dev/null @@ -1,203 +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.license.licensor.tools; - -import org.apache.commons.cli.MissingOptionException; -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.core.Licenses; -import org.elasticsearch.license.licensor.AbstractLicensingTestBase; -import org.elasticsearch.license.licensor.TestUtils; -import org.junit.Test; - -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.*; - -import static org.elasticsearch.common.cli.CliTool.Command; -import static org.elasticsearch.common.cli.CliTool.ExitStatus; -import static org.elasticsearch.license.licensor.tools.LicenseVerificationTool.LicenseVerifier; -import static org.hamcrest.CoreMatchers.instanceOf; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.core.IsEqual.equalTo; - -public class LicenseVerificationToolTests extends CliToolTestCase { - - @Test - public void testParsingMissingLicense() throws Exception { - LicenseVerificationTool licenseVerificationTool = new LicenseVerificationTool(); - Path path = getDataPath(TestUtils.PUBLIC_KEY_RESOURCE); - Command command = licenseVerificationTool.parse(LicenseVerificationTool.NAME, args(" --publicKeyPath " + path)); - - assertThat(command, instanceOf(Command.Exit.class)); - Command.Exit exitCommand = (Command.Exit) command; - assertThat(exitCommand.status(), equalTo(ExitStatus.USAGE)); - } - - @Test - public void testParsingMissingPublicKeyPath() throws Exception { - Path pubKeyPath = getDataPath(TestUtils.PUBLIC_KEY_RESOURCE); - Path priKeyPath = getDataPath(TestUtils.PRIVATE_KEY_RESOURCE); - License inputLicense = AbstractLicensingTestBase.generateSignedLicense("feature__1", - TimeValue.timeValueHours(1), pubKeyPath.toString(), priKeyPath.toString()); - LicenseVerificationTool licenseVerificationTool = new LicenseVerificationTool(); - try { - licenseVerificationTool.parse(LicenseVerificationTool.NAME, - args("--license " + TestUtils.dumpLicense(inputLicense))); - } catch (MissingOptionException e) { - assertThat(e.getMessage(), containsString("pub")); - } - } - - @Test - public void testParsingNonExistentPublicKeyPath() throws Exception { - LicenseVerificationTool licenseVerificationTool = new LicenseVerificationTool(); - Path path = getDataPath(TestUtils.PUBLIC_KEY_RESOURCE); - Command command = licenseVerificationTool.parse(LicenseVerificationTool.NAME, args(" --publicKeyPath " - + path.toString().concat(".invalid"))); - - assertThat(command, instanceOf(Command.Exit.class)); - Command.Exit exitCommand = (Command.Exit) command; - assertThat(exitCommand.status(), equalTo(ExitStatus.USAGE)); - } - - @Test - public void testParsingSimple() throws Exception { - Path pubKeyPath = getDataPath(TestUtils.PUBLIC_KEY_RESOURCE); - Path priKeyPath = getDataPath(TestUtils.PRIVATE_KEY_RESOURCE); - License inputLicense = AbstractLicensingTestBase.generateSignedLicense("feature__1", - TimeValue.timeValueHours(1), pubKeyPath.toString(), priKeyPath.toString()); - LicenseVerificationTool licenseVerificationTool = new LicenseVerificationTool(); - Command command = licenseVerificationTool.parse(LicenseVerificationTool.NAME, - args("--license " + TestUtils.dumpLicense(inputLicense) - + " --publicKeyPath " + getDataPath(TestUtils.PUBLIC_KEY_RESOURCE))); - assertThat(command, instanceOf(LicenseVerifier.class)); - LicenseVerifier licenseVerifier = (LicenseVerifier) command; - assertThat(licenseVerifier.licenses.size(), equalTo(1)); - License outputLicense = licenseVerifier.licenses.iterator().next(); - TestUtils.isSame(inputLicense, outputLicense); - } - - @Test - public void testParsingLicenseFile() throws Exception { - Path pubKeyPath = getDataPath(TestUtils.PUBLIC_KEY_RESOURCE); - Path priKeyPath = getDataPath(TestUtils.PRIVATE_KEY_RESOURCE); - License inputLicense = AbstractLicensingTestBase.generateSignedLicense("feature__1", - TimeValue.timeValueHours(1), pubKeyPath.toString(), priKeyPath.toString()); - - 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(licenseVerifier.licenses.size(), equalTo(1)); - License outputLicense = licenseVerifier.licenses.iterator().next(); - TestUtils.isSame(inputLicense, outputLicense); - - } - - @Test - public void testParsingMultipleLicense() throws Exception { - Path pubKeyPath = getDataPath(TestUtils.PUBLIC_KEY_RESOURCE); - Path priKeyPath = getDataPath(TestUtils.PRIVATE_KEY_RESOURCE); - - int n = randomIntBetween(2, 5); - Map inputLicenses = new HashMap<>(); - for (int i = 0; i < n; i++) { - License license = AbstractLicensingTestBase.generateSignedLicense("feature__" + i, - TimeValue.timeValueHours(1), pubKeyPath.toString(), priKeyPath.toString()); - inputLicenses.put(license.feature(), license); - } - - StringBuilder argsBuilder = new StringBuilder(); - for (License inputLicense : inputLicenses.values()) { - argsBuilder.append(" --license ") - .append(TestUtils.dumpLicense(inputLicense)); - } - argsBuilder.append(" --publicKeyPath ").append(getDataPath(TestUtils.PUBLIC_KEY_RESOURCE).toString()); - LicenseVerificationTool licenseVerificationTool = new LicenseVerificationTool(); - Command command = licenseVerificationTool.parse(LicenseVerificationTool.NAME, args(argsBuilder.toString())); - - assertThat(command, instanceOf(LicenseVerifier.class)); - LicenseVerifier licenseVerifier = (LicenseVerifier) command; - assertThat(licenseVerifier.licenses.size(), equalTo(inputLicenses.size())); - - for (License outputLicense : licenseVerifier.licenses) { - License inputLicense = inputLicenses.get(outputLicense.feature()); - assertThat(inputLicense, notNullValue()); - TestUtils.isSame(inputLicense, outputLicense); - } - } - - @Test - public void testToolSimple() throws Exception { - Path pubKeyPath = getDataPath(TestUtils.PUBLIC_KEY_RESOURCE); - Path priKeyPath = getDataPath(TestUtils.PRIVATE_KEY_RESOURCE); - - int n = randomIntBetween(2, 5); - Map inputLicenses = new HashMap<>(); - for (int i = 0; i < n; i++) { - License license = AbstractLicensingTestBase.generateSignedLicense("feature__" + i, - TimeValue.timeValueHours(1), pubKeyPath.toString(), priKeyPath.toString()); - inputLicenses.put(license.feature(), license); - } - - String output = runLicenseVerificationTool(new HashSet<>(inputLicenses.values()), getDataPath(TestUtils.PUBLIC_KEY_RESOURCE), ExitStatus.OK); - List outputLicenses = Licenses.fromSource(output.getBytes(StandardCharsets.UTF_8), true); - assertThat(outputLicenses.size(), equalTo(inputLicenses.size())); - - for (License outputLicense : outputLicenses) { - License inputLicense = inputLicenses.get(outputLicense.feature()); - assertThat(inputLicense, notNullValue()); - TestUtils.isSame(inputLicense, outputLicense); - } - } - - @Test - public void testToolInvalidLicense() throws Exception { - Path pubKeyPath = getDataPath(TestUtils.PUBLIC_KEY_RESOURCE); - Path priKeyPath = getDataPath(TestUtils.PRIVATE_KEY_RESOURCE); - License signedLicense = AbstractLicensingTestBase.generateSignedLicense("feature__1" - , TimeValue.timeValueHours(1), pubKeyPath.toString(), priKeyPath.toString()); - - License tamperedLicense = License.builder() - .fromLicenseSpec(signedLicense, signedLicense.signature()) - .expiryDate(signedLicense.expiryDate() + randomIntBetween(1, 1000)).build(); - - runLicenseVerificationTool(Collections.singleton(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(Set licenses, 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, licenses, 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/licensor/src/test/resources/log4j.properties b/licensor/src/test/resources/log4j.properties deleted file mode 100644 index 76defc8660c..00000000000 --- a/licensor/src/test/resources/log4j.properties +++ /dev/null @@ -1,11 +0,0 @@ -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/licensor/src/test/resources/private.key b/licensor/src/test/resources/private.key deleted file mode 100644 index 1f545803d87..00000000000 Binary files a/licensor/src/test/resources/private.key and /dev/null differ diff --git a/licensor/src/test/resources/public.key b/licensor/src/test/resources/public.key deleted file mode 100644 index 2a9f272e0b3..00000000000 --- a/licensor/src/test/resources/public.key +++ /dev/null @@ -1,3 +0,0 @@ -qngwM}UiK0b2غq]쇴c+I &IJf~ ]d}oOId -5A(쵴^WDJ}-O?uN5vp{t7 #Vqktwm]Lz"| QlQs><}[2Z|57%D -Yxn:lLH2HvEEW\H:6h9 [!+;.w7C_| Ӫ*D`?xU/3>xUӓ+ \ No newline at end of file diff --git a/plugin-api/.gitignore b/plugin-api/.gitignore deleted file mode 100644 index ab956abf6f9..00000000000 --- a/plugin-api/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/eclipse-build/ diff --git a/plugin-api/pom.xml b/plugin-api/pom.xml deleted file mode 100644 index ca17dbd05b9..00000000000 --- a/plugin-api/pom.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - elasticsearch-license - org.elasticsearch - 2.0.0.beta1-SNAPSHOT - - 4.0.0 - - elasticsearch-license-plugin-api - - ${project.parent.basedir} - - true - - - - - - org.elasticsearch - elasticsearch-license-licensor - 2.0.0.beta1-SNAPSHOT - test - - - org.elasticsearch - elasticsearch-license-core - 2.0.0.beta1-SNAPSHOT - compile - - - - - - - src/main/resources - true - - - - diff --git a/plugin-api/src/main/java/org/elasticsearch/license/plugin/LicenseVersion.java b/plugin-api/src/main/java/org/elasticsearch/license/plugin/LicenseVersion.java deleted file mode 100644 index dc15b59625e..00000000000 --- a/plugin-api/src/main/java/org/elasticsearch/license/plugin/LicenseVersion.java +++ /dev/null @@ -1,191 +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.license.plugin; - -import org.elasticsearch.Version; -import org.elasticsearch.common.Nullable; -import org.elasticsearch.common.Strings; -import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.license.core.License; - -import java.io.IOException; -import java.io.Serializable; - -@SuppressWarnings("deprecation") -public class LicenseVersion implements Serializable { - - // The logic for ID is: XXYYZZAA, where XX is major version, YY is minor version, ZZ is revision, and AA is Beta/RC indicator - // AA values below 50 are beta builds, and below 99 are RC builds, with 99 indicating a release - // the (internal) format of the id is there so we can easily do after/before checks on the id - - public static final int V_1_0_0_ID = /*00*/1000099; - public static final int V_2_0_0_beta1_ID = /*00*/2000001; - public static final LicenseVersion V_1_0_0 = new LicenseVersion(V_1_0_0_ID, false, License.VERSION_START, Version.V_1_4_0_Beta1); - public static final LicenseVersion V_2_0_0_beta1 = new LicenseVersion(V_2_0_0_beta1_ID, true, License.VERSION_START, Version.V_2_0_0_beta1); - - public static final LicenseVersion CURRENT = V_2_0_0_beta1; - - public static LicenseVersion readVersion(StreamInput in) throws IOException { - return fromId(in.readVInt()); - } - - public static LicenseVersion fromId(int id) { - switch (id) { - case V_1_0_0_ID: - return V_1_0_0; - - default: - return new LicenseVersion(id, null, License.VERSION_CURRENT, Version.CURRENT); - } - } - - public static void writeVersion(LicenseVersion version, StreamOutput out) throws IOException { - out.writeVInt(version.id); - } - - /** - * Returns the smallest version between the 2. - */ - public static LicenseVersion smallest(LicenseVersion version1, LicenseVersion version2) { - return version1.id < version2.id ? version1 : version2; - } - - /** - * Returns the version given its string representation, current version if the argument is null or empty - */ - public static LicenseVersion fromString(String version) { - if (!Strings.hasLength(version)) { - return LicenseVersion.CURRENT; - } - - String[] parts = version.split("\\.|\\-"); - if (parts.length < 3 || parts.length > 4) { - throw new IllegalArgumentException("the version needs to contain major, minor and revision, and optionally the build"); - } - - try { - //we reverse the version id calculation based on some assumption as we can't reliably reverse the modulo - int major = Integer.parseInt(parts[0]) * 1000000; - int minor = Integer.parseInt(parts[1]) * 10000; - int revision = Integer.parseInt(parts[2]) * 100; - - int build = 99; - if (parts.length == 4) { - String buildStr = parts[3]; - if (buildStr.startsWith("beta")) { - build = Integer.parseInt(buildStr.substring(4)); - } - if (buildStr.startsWith("rc")) { - build = Integer.parseInt(buildStr.substring(2)) + 50; - } - } - - return fromId(major + minor + revision + build); - - } catch(NumberFormatException e) { - throw new IllegalArgumentException("unable to parse version " + version, e); - } - } - - public final int id; - public final byte major; - public final byte minor; - public final byte revision; - public final byte build; - public final Boolean snapshot; - public final int minSignatureVersion; - public final Version minEsCompatibilityVersion; - - LicenseVersion(int id, @Nullable Boolean snapshot, int minSignatureVersion, Version minEsCompatibilityVersion) { - this.id = id; - this.major = (byte) ((id / 1000000) % 100); - this.minor = (byte) ((id / 10000) % 100); - this.revision = (byte) ((id / 100) % 100); - this.build = (byte) (id % 100); - this.snapshot = snapshot; - this.minSignatureVersion = minSignatureVersion; - this.minEsCompatibilityVersion = minEsCompatibilityVersion; - } - - public boolean snapshot() { - return snapshot != null && snapshot; - } - - public boolean after(LicenseVersion version) { - return version.id < id; - } - - public boolean before(LicenseVersion version) { - return version.id > id; - } - - /** - * Returns the minimum compatible version based on the current - * version. Ie a node needs to have at least the return version in order - * to communicate with a node running the current version. The returned version - * is in most of the cases the smallest major version release unless the current version - * is a beta or RC release then the version itself is returned. - */ - public LicenseVersion minimumCompatibilityVersion() { - return LicenseVersion.smallest(this, fromId(major * 1000000 + 99)); - } - - /** - * @return The minimum elasticsearch version this license version is compatible with. - */ - public Version minimumEsCompatiblityVersion() { - return minEsCompatibilityVersion; - } - - /** - * @return The minimum license signature version this license plugin is compatible with. - */ - public int minimumSignatureVersion() { - return minSignatureVersion; - } - - /** - * Just the version number (without -SNAPSHOT if snapshot). - */ - public String number() { - StringBuilder sb = new StringBuilder(); - sb.append(major).append('.').append(minor).append('.').append(revision); - if (build < 50) { - sb.append("-beta").append(build); - } else if (build < 99) { - sb.append("-rc").append(build - 50); - } - return sb.toString(); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(number()); - if (snapshot()) { - sb.append("-SNAPSHOT"); - } - return sb.toString(); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - LicenseVersion that = (LicenseVersion) o; - - if (id != that.id) return false; - - return true; - } - - @Override - public int hashCode() { - return id; - } -} diff --git a/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/LicenseUtils.java b/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/LicenseUtils.java deleted file mode 100644 index ba400cc3d17..00000000000 --- a/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/LicenseUtils.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.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 newExpirationException(String feature) { - ElasticsearchSecurityException e = new ElasticsearchSecurityException("license expired for feature [{}]", RestStatus.UNAUTHORIZED, feature); - e.addHeader(EXPIRED_FEATURE_HEADER, feature); - return e; - } -} diff --git a/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/LicensesClientService.java b/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/LicensesClientService.java deleted file mode 100644 index 73e188f985c..00000000000 --- a/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/LicensesClientService.java +++ /dev/null @@ -1,163 +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.license.plugin.core; - -import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.license.core.License; - -import java.util.Collection; - - -public interface LicensesClientService { - - public interface Listener { - - /** - * Called to enable a feature - */ - public void onEnabled(License license); - - /** - * Called to disable a feature - */ - public void onDisabled(License license); - - } - - /** - * Registers a feature for licensing - * - * @param feature - name of the feature to register (must be in sync with license Generator feature name) - * @param trialLicenseOptions - Trial license specification used to generate a one-time trial license for the feature; - * use null if no trial license should be generated for the feature - * @param expirationCallbacks - A collection of Pre and/or Post expiration callbacks - * @param listener - used to notify on feature enable/disable - */ - void register(String feature, TrialLicenseOptions trialLicenseOptions, Collection expirationCallbacks, Listener listener); - - public static class TrialLicenseOptions { - final TimeValue duration; - final int maxNodes; - - public TrialLicenseOptions(TimeValue duration, int maxNodes) { - this.duration = duration; - this.maxNodes = maxNodes; - } - } - - - public static interface LicenseCallback { - void on(License license, ExpirationStatus status); - } - - public static abstract class ExpirationCallback implements LicenseCallback { - - 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; - } - } - - 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; - } - } - - private final Orientation orientation; - private final TimeValue min; - private 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; - if (frequency == null) { - throw new IllegalArgumentException("frequency can not be null"); - } - } - - public Orientation orientation() { - return orientation; - } - - public TimeValue min() { - return min; - } - - public TimeValue max() { - return max; - } - - public TimeValue frequency() { - return frequency; - } - - public abstract boolean matches(long expirationDate, long now); - } - - public static class ExpirationStatus { - private final boolean expired; - private final TimeValue time; - - ExpirationStatus(boolean expired, TimeValue time) { - this.expired = expired; - this.time = time; - } - - public boolean expired() { - return expired; - } - - public TimeValue time() { - return time; - } - } - - -} diff --git a/plugin-api/src/test/java/org/elasticsearch/license/plugin/LicenseVersionTests.java b/plugin-api/src/test/java/org/elasticsearch/license/plugin/LicenseVersionTests.java deleted file mode 100644 index fa3080fd676..00000000000 --- a/plugin-api/src/test/java/org/elasticsearch/license/plugin/LicenseVersionTests.java +++ /dev/null @@ -1,54 +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.license.plugin; - -import org.elasticsearch.test.ElasticsearchTestCase; -import org.junit.Test; - -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.is; - -/** - * - */ -public class LicenseVersionTests extends ElasticsearchTestCase { - - @Test - public void testStrings() throws Exception { - boolean beta = randomBoolean(); - int buildNumber = beta ? randomIntBetween(0, 49) : randomIntBetween(0, 48); - int major = randomIntBetween(0, 20); - int minor = randomIntBetween(0, 20); - int revision = randomIntBetween(0, 20); - - String build = buildNumber == 0 ? "" : - beta ? "-beta" + buildNumber : "-rc" + buildNumber; - - - String versionName = new StringBuilder() - .append(major) - .append(".").append(minor) - .append(".").append(revision) - .append(build).toString(); - LicenseVersion version = LicenseVersion.fromString(versionName); - - logger.info("version: {}", versionName); - - assertThat(version.major, is((byte) major)); - assertThat(version.minor, is((byte) minor)); - assertThat(version.revision, is((byte) revision)); - if (buildNumber == 0) { - assertThat(version.build, is((byte) 99)); - } else if (beta) { - assertThat(version.build, is((byte) buildNumber)); - } else { - assertThat(version.build, is((byte) (buildNumber + 50))); - } - - assertThat(version.number(), equalTo(versionName)); - } - -} diff --git a/plugin/.gitignore b/plugin/.gitignore deleted file mode 100644 index ab956abf6f9..00000000000 --- a/plugin/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/eclipse-build/ diff --git a/plugin/pom.xml b/plugin/pom.xml deleted file mode 100644 index 8e910af3285..00000000000 --- a/plugin/pom.xml +++ /dev/null @@ -1,125 +0,0 @@ - - - - elasticsearch-license - org.elasticsearch - 2.0.0.beta1-SNAPSHOT - - 4.0.0 - - elasticsearch-license-plugin - - - - ${basedir}/src/test/resources - ${project.parent.basedir} - license - false - - - - - org.elasticsearch - elasticsearch-license-licensor - 2.0.0.beta1-SNAPSHOT - test - - - org.elasticsearch - elasticsearch-license-core - 2.0.0.beta1-SNAPSHOT - - - org.elasticsearch - elasticsearch-license-plugin-api - 2.0.0.beta1-SNAPSHOT - - - - - - - ${keys.path} - false - - public.key - - - - src/main/resources - true - - - - - - org.apache.maven.plugins - maven-assembly-plugin - - - - org.apache.maven.plugins - maven-enforcer-plugin - - - - enforce-property - - enforce - - - - - keys.path - "You must set a keys.path property!" - - - - ${keys.path}/public.key - - "public.key file does not exist in ${keys.path} directory!" - - - true - - - - - - - org.apache.maven.plugins - maven-jar-plugin - - - for-plugin - prepare-package - - jar - - - - - - - com.carrotsearch.randomizedtesting - junit4-maven-plugin - - - tests - test - - junit4 - - - 40 - - - - - - - - diff --git a/plugin/rest-api-spec/api/licenses.json b/plugin/rest-api-spec/api/licenses.json deleted file mode 100644 index 1ab8197c227..00000000000 --- a/plugin/rest-api-spec/api/licenses.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "licenses": { - "documentation": "https://www.elastic.co/guide/en/shield/current/license-management.html", - "methods": ["GET"], - "url": { - "path": "/_licenses", - "paths": ["/_licenses"], - "parts" : { - }, - "params": { - "local": { - "type" : "boolean", - "description" : "Return local information, do not retrieve the state from master node (default: false)" - } - } - }, - "body": null - } -} diff --git a/plugin/rest-api-spec/test/license/10_basic.yaml b/plugin/rest-api-spec/test/license/10_basic.yaml deleted file mode 100644 index 30d9f3e3d49..00000000000 --- a/plugin/rest-api-spec/test/license/10_basic.yaml +++ /dev/null @@ -1,4 +0,0 @@ ---- -"licenses endpoint exists": - - do: {licenses: {}} - - match: {licenses: []} diff --git a/plugin/src/main/assemblies/plugin.xml b/plugin/src/main/assemblies/plugin.xml deleted file mode 100644 index ff3c003a5d2..00000000000 --- a/plugin/src/main/assemblies/plugin.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - plugin - - zip - - false - - - / - true - - org.elasticsearch:elasticsearch-license-plugin - org.elasticsearch:elasticsearch-license-plugin-api - org.elasticsearch:elasticsearch-license-core - - - org.elasticsearch:elasticsearch - - - - \ No newline at end of file diff --git a/plugin/src/main/java/org/elasticsearch/license/plugin/LicenseModule.java b/plugin/src/main/java/org/elasticsearch/license/plugin/LicenseModule.java deleted file mode 100644 index 4ec46ec33f0..00000000000 --- a/plugin/src/main/java/org/elasticsearch/license/plugin/LicenseModule.java +++ /dev/null @@ -1,21 +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.license.plugin; - -import org.elasticsearch.common.inject.AbstractModule; -import org.elasticsearch.common.inject.Scopes; -import org.elasticsearch.license.core.LicenseVerifier; -import org.elasticsearch.license.plugin.core.LicensesClientService; -import org.elasticsearch.license.plugin.core.LicensesService; - -public class LicenseModule extends AbstractModule { - @Override - protected void configure() { - bind(LicenseVerifier.class).in(Scopes.SINGLETON); - bind(LicensesService.class).in(Scopes.SINGLETON); - bind(LicensesClientService.class).to(LicensesService.class).in(Scopes.SINGLETON); - } -} diff --git a/plugin/src/main/java/org/elasticsearch/license/plugin/LicensePlugin.java b/plugin/src/main/java/org/elasticsearch/license/plugin/LicensePlugin.java deleted file mode 100644 index 425ca301943..00000000000 --- a/plugin/src/main/java/org/elasticsearch/license/plugin/LicensePlugin.java +++ /dev/null @@ -1,93 +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.license.plugin; - -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Lists; -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.AbstractPlugin; -import org.elasticsearch.rest.RestModule; - -import java.util.Collection; - -public class LicensePlugin extends AbstractPlugin { - - 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> services() { - Collection> services = Lists.newArrayList(); - if (isEnabled) { - services.add(LicensesService.class); - } - return services; - } - - - @Override - public Collection> modules() { - if (isEnabled) { - return ImmutableSet.>of(LicenseModule.class); - } - return ImmutableSet.of(); - } -} diff --git a/plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseAction.java b/plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseAction.java deleted file mode 100644 index c7c8a675f84..00000000000 --- a/plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseAction.java +++ /dev/null @@ -1,29 +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.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/plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseRequest.java b/plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseRequest.java deleted file mode 100644 index 66aeb014370..00000000000 --- a/plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseRequest.java +++ /dev/null @@ -1,56 +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.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.Arrays; -import java.util.HashSet; -import java.util.Set; - - -public class DeleteLicenseRequest extends AcknowledgedRequest { - - private String[] features; - - public DeleteLicenseRequest() { - } - - public DeleteLicenseRequest(String... features) { - this.features = features; - } - - public void features(Set features) { - this.features = features.toArray(new String[features.size()]); - } - - public Set features() { - return new HashSet<>(Arrays.asList(features)); - } - - @Override - public ActionRequestValidationException validate() { - return null; - } - - @Override - public void readFrom(StreamInput in) throws IOException { - super.readFrom(in); - features = in.readStringArray(); - readTimeout(in); - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - super.writeTo(out); - out.writeStringArray(features); - writeTimeout(out); - } -} \ No newline at end of file diff --git a/plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseRequestBuilder.java b/plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseRequestBuilder.java deleted file mode 100644 index b03e9dc7fca..00000000000 --- a/plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseRequestBuilder.java +++ /dev/null @@ -1,29 +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.license.plugin.action.delete; - -import org.elasticsearch.action.support.master.AcknowledgedRequestBuilder; -import org.elasticsearch.client.ClusterAdminClient; -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()); - } - - public DeleteLicenseRequestBuilder setFeatures(Set features) { - request.features(features); - return this; - } -} \ No newline at end of file diff --git a/plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseResponse.java b/plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseResponse.java deleted file mode 100644 index 2b5d35edeae..00000000000 --- a/plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseResponse.java +++ /dev/null @@ -1,35 +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.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/plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/TransportDeleteLicenseAction.java b/plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/TransportDeleteLicenseAction.java deleted file mode 100644 index 4b7347c518f..00000000000 --- a/plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/TransportDeleteLicenseAction.java +++ /dev/null @@ -1,67 +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.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.threadpool.ThreadPool; -import org.elasticsearch.transport.TransportService; - -import static org.elasticsearch.license.plugin.core.LicensesService.DeleteLicenseRequestHolder; - -public class TransportDeleteLicenseAction extends TransportMasterNodeAction { - - private final LicensesManagerService licensesManagerService; - - @Inject - public TransportDeleteLicenseAction(Settings settings, TransportService transportService, ClusterService clusterService, LicensesManagerService licensesManagerService, - ThreadPool threadPool, ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver) { - super(settings, DeleteLicenseAction.NAME, transportService, clusterService, threadPool, actionFilters, indexNameExpressionResolver, DeleteLicenseRequest.class); - this.licensesManagerService = licensesManagerService; - } - - @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 { - final DeleteLicenseRequestHolder requestHolder = new DeleteLicenseRequestHolder(request, "delete licenses []"); - licensesManagerService.removeLicenses(requestHolder, new ActionListener() { - @Override - public void onResponse(ClusterStateUpdateResponse clusterStateUpdateResponse) { - listener.onResponse(new DeleteLicenseResponse(clusterStateUpdateResponse.isAcknowledged())); - } - - @Override - public void onFailure(Throwable e) { - listener.onFailure(e); - } - }); - } -} \ No newline at end of file diff --git a/plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseAction.java b/plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseAction.java deleted file mode 100644 index d426b1b8aab..00000000000 --- a/plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseAction.java +++ /dev/null @@ -1,29 +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.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/plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseRequest.java b/plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseRequest.java deleted file mode 100644 index 7f8d20512a1..00000000000 --- a/plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseRequest.java +++ /dev/null @@ -1,21 +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.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/plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseRequestBuilder.java b/plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseRequestBuilder.java deleted file mode 100644 index a837141e194..00000000000 --- a/plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseRequestBuilder.java +++ /dev/null @@ -1,21 +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.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/plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseResponse.java b/plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseResponse.java deleted file mode 100644 index 14476cd3227..00000000000 --- a/plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseResponse.java +++ /dev/null @@ -1,45 +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.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 org.elasticsearch.license.core.Licenses; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -public class GetLicenseResponse extends ActionResponse { - - private List licenses = new ArrayList<>(); - - GetLicenseResponse() { - } - - GetLicenseResponse(List licenses) { - this.licenses = licenses; - } - - public List licenses() { - return licenses; - } - - @Override - public void readFrom(StreamInput in) throws IOException { - super.readFrom(in); - licenses = Licenses.readFrom(in); - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - super.writeTo(out); - Licenses.writeTo(licenses, out); - } - -} \ No newline at end of file diff --git a/plugin/src/main/java/org/elasticsearch/license/plugin/action/get/TransportGetLicenseAction.java b/plugin/src/main/java/org/elasticsearch/license/plugin/action/get/TransportGetLicenseAction.java deleted file mode 100644 index bea492cd0dc..00000000000 --- a/plugin/src/main/java/org/elasticsearch/license/plugin/action/get/TransportGetLicenseAction.java +++ /dev/null @@ -1,53 +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.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.class); - 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.getLicenses())); - } -} \ No newline at end of file diff --git a/plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseAction.java b/plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseAction.java deleted file mode 100644 index e90523b9c1d..00000000000 --- a/plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseAction.java +++ /dev/null @@ -1,29 +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.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/plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseRequest.java b/plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseRequest.java deleted file mode 100644 index 8a83b89c8f4..00000000000 --- a/plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseRequest.java +++ /dev/null @@ -1,66 +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.license.plugin.action.put; - -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 org.elasticsearch.license.core.License; -import org.elasticsearch.license.core.Licenses; - -import java.io.IOException; -import java.util.List; - - -public class PutLicenseRequest extends AcknowledgedRequest { - - private List licenses; - - public PutLicenseRequest() { - } - - @Override - public ActionRequestValidationException validate() { - return null; - } - - /** - * Parses licenses from json format to an instance of {@link org.elasticsearch.license.core.Licenses} - * - * @param licenseDefinition licenses definition - */ - public PutLicenseRequest licenses(String licenseDefinition) { - try { - return licenses(Licenses.fromSource(licenseDefinition)); - } catch (IOException e) { - throw new IllegalArgumentException("failed to parse licenses source", e); - } - } - - public PutLicenseRequest licenses(List licenses) { - this.licenses = licenses; - return this; - } - - public List licenses() { - return licenses; - } - - @Override - public void readFrom(StreamInput in) throws IOException { - super.readFrom(in); - licenses = Licenses.readFrom(in); - readTimeout(in); - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - super.writeTo(out); - Licenses.writeTo(licenses, out); - writeTimeout(out); - } -} diff --git a/plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseRequestBuilder.java b/plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseRequestBuilder.java deleted file mode 100644 index a8d68cf0051..00000000000 --- a/plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseRequestBuilder.java +++ /dev/null @@ -1,43 +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.license.plugin.action.put; - -import org.elasticsearch.action.support.master.AcknowledgedRequestBuilder; -import org.elasticsearch.client.ElasticsearchClient; -import org.elasticsearch.license.core.License; - -import java.util.List; - -/** - * 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 licenses license - * @return this builder - */ - public PutLicenseRequestBuilder setLicense(List licenses) { - request.licenses(licenses); - return this; - } - - public PutLicenseRequestBuilder setLicense(String licenseSource) { - request.licenses(licenseSource); - return this; - } -} diff --git a/plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseResponse.java b/plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseResponse.java deleted file mode 100644 index f52a0b0fb31..00000000000 --- a/plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseResponse.java +++ /dev/null @@ -1,45 +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.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.license.plugin.core.LicensesStatus; - -import java.io.IOException; - -public class PutLicenseResponse extends AcknowledgedResponse { - - private LicensesStatus status; - - PutLicenseResponse() { - } - - PutLicenseResponse(boolean acknowledged, LicensesStatus status) { - super(acknowledged); - this.status = status; - } - - public LicensesStatus status() { - return status; - } - - @Override - public void readFrom(StreamInput in) throws IOException { - super.readFrom(in); - readAcknowledged(in); - status = LicensesStatus.fromId(in.readVInt()); - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - super.writeTo(out); - writeAcknowledged(out); - out.writeVInt(status.id()); - } - -} diff --git a/plugin/src/main/java/org/elasticsearch/license/plugin/action/put/TransportPutLicenseAction.java b/plugin/src/main/java/org/elasticsearch/license/plugin/action/put/TransportPutLicenseAction.java deleted file mode 100644 index 849c1d2fcee..00000000000 --- a/plugin/src/main/java/org/elasticsearch/license/plugin/action/put/TransportPutLicenseAction.java +++ /dev/null @@ -1,68 +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.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.threadpool.ThreadPool; -import org.elasticsearch.transport.TransportService; - -import static org.elasticsearch.license.plugin.core.LicensesService.LicensesUpdateResponse; -import static org.elasticsearch.license.plugin.core.LicensesService.PutLicenseRequestHolder; - -public class TransportPutLicenseAction extends TransportMasterNodeAction { - - private final LicensesManagerService licensesManagerService; - - @Inject - public TransportPutLicenseAction(Settings settings, TransportService transportService, ClusterService clusterService, - LicensesManagerService licensesManagerService, ThreadPool threadPool, ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver) { - super(settings, PutLicenseAction.NAME, transportService, clusterService, threadPool, actionFilters, indexNameExpressionResolver, PutLicenseRequest.class); - this.licensesManagerService = licensesManagerService; - } - - - @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 { - licensesManagerService.registerLicenses(new PutLicenseRequestHolder(request, "put licenses []"), new ActionListener() { - @Override - public void onResponse(LicensesUpdateResponse licensesUpdateResponse) { - listener.onResponse(new PutLicenseResponse(licensesUpdateResponse.isAcknowledged(), licensesUpdateResponse.status())); - } - - @Override - public void onFailure(Throwable e) { - listener.onFailure(e); - } - }); - } - -} diff --git a/plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesManagerService.java b/plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesManagerService.java deleted file mode 100644 index 38082371e4c..00000000000 --- a/plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesManagerService.java +++ /dev/null @@ -1,43 +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.license.plugin.core; - -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse; -import org.elasticsearch.common.inject.ImplementedBy; -import org.elasticsearch.license.core.License; - -import java.util.List; -import java.util.Set; - -import static org.elasticsearch.license.plugin.core.LicensesService.*; - -@ImplementedBy(LicensesService.class) -public interface LicensesManagerService { - - /** - * Registers new licenses in the cluster - *

- * This method can be only called on the master node. It tries to create a new licenses on the master - * and if provided license(s) is VALID it is added to cluster state metadata {@link org.elasticsearch.license.plugin.core.LicensesMetaData} - */ - public void registerLicenses(final PutLicenseRequestHolder requestHolder, final ActionListener listener); - - /** - * Remove only signed license(s) for provided features from the cluster state metadata - */ - public void removeLicenses(final DeleteLicenseRequestHolder requestHolder, final ActionListener listener); - - /** - * @return the set of features that are currently enabled - */ - public Set enabledFeatures(); - - /** - * @return a list of licenses, contains one license (with the latest expiryDate) per registered features sorted by latest issueDate - */ - public List getLicenses(); -} diff --git a/plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesMetaData.java b/plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesMetaData.java deleted file mode 100644 index 1cf9809e48a..00000000000 --- a/plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesMetaData.java +++ /dev/null @@ -1,155 +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.license.plugin.core; - -import com.google.common.collect.ImmutableList; -import org.elasticsearch.cluster.AbstractDiffable; -import org.elasticsearch.cluster.metadata.MetaData; -import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.common.xcontent.XContentParser; -import org.elasticsearch.license.core.License; -import org.elasticsearch.license.core.Licenses; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.EnumSet; -import java.util.List; - -/** - * Contains metadata about registered licenses - */ -public class LicensesMetaData extends AbstractDiffable implements MetaData.Custom { - - public static final String TYPE = "licenses"; - - public static final LicensesMetaData PROTO = new LicensesMetaData(Collections.emptyList(), Collections.emptyList()); - - private final ImmutableList signedLicenses; - - private final ImmutableList trialLicenses; - - /** - * Constructs new licenses metadata - * - * @param signedLicenses list of signed Licenses - * @param trialLicenses set of encoded trial licenses - */ - public LicensesMetaData(List signedLicenses, List trialLicenses) { - this.signedLicenses = ImmutableList.copyOf(signedLicenses); - this.trialLicenses = ImmutableList.copyOf(trialLicenses); - } - - public List getSignedLicenses() { - return signedLicenses; - } - - public List getTrialLicenses() { - return trialLicenses; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null || getClass() != obj.getClass()) { - return false; - } - LicensesMetaData that = (LicensesMetaData) obj; - return signedLicenses.equals(that.signedLicenses) - && trialLicenses.equals(that.trialLicenses); - } - - @Override - public int hashCode() { - return signedLicenses.hashCode() + 31 * trialLicenses.hashCode(); - } - - @Override - public String type() { - return TYPE; - } - - @Override - public LicensesMetaData fromXContent(XContentParser parser) throws IOException { - List trialLicenses = new ArrayList<>(); - List signedLicenses = new ArrayList<>(); - XContentParser.Token token; - while (parser.currentToken() != XContentParser.Token.END_OBJECT) { - token = parser.nextToken(); - if (token == XContentParser.Token.FIELD_NAME) { - String fieldName = parser.text(); - if (fieldName != null) { - if (fieldName.equals(Fields.TRIAL_LICENSES)) { - if (parser.nextToken() == XContentParser.Token.START_ARRAY) { - while (parser.nextToken() != XContentParser.Token.END_ARRAY) { - if (parser.currentToken().isValue()) { - trialLicenses.add(TrialLicenseUtils.fromEncodedTrialLicense(parser.text())); - } - } - } - } - if (fieldName.equals(Fields.SIGNED_LICENCES)) { - if (parser.nextToken() == XContentParser.Token.START_ARRAY) { - while (parser.nextToken() != XContentParser.Token.END_ARRAY) { - License.Builder builder = License.builder().fromXContent(parser); - signedLicenses.add(builder.build()); - } - } - } - } - } - } - return new LicensesMetaData(signedLicenses, trialLicenses); - } - - @Override - public EnumSet context() { - return EnumSet.of(MetaData.XContentContext.GATEWAY); - } - - @Override - public void writeTo(StreamOutput streamOutput) throws IOException { - Licenses.writeTo(signedLicenses, streamOutput); - streamOutput.writeVInt(trialLicenses.size()); - for (License trialLicense : trialLicenses) { - streamOutput.writeString(TrialLicenseUtils.toEncodedTrialLicense(trialLicense)); - } - } - - @Override - public MetaData.Custom readFrom(StreamInput streamInput) throws IOException { - List signedLicenses = Licenses.readFrom(streamInput); - int numTrialLicenses = streamInput.readVInt(); - List trialLicenses = new ArrayList<>(numTrialLicenses); - for (int i = 0; i < numTrialLicenses; i++) { - trialLicenses.add(TrialLicenseUtils.fromEncodedTrialLicense(streamInput.readString())); - } - return new LicensesMetaData(signedLicenses, trialLicenses); - } - - @Override - public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startArray(Fields.TRIAL_LICENSES); - for (License trailLicense : trialLicenses) { - builder.value(TrialLicenseUtils.toEncodedTrialLicense(trailLicense)); - } - builder.endArray(); - - builder.startArray(Fields.SIGNED_LICENCES); - for (License license : signedLicenses) { - license.toXContent(builder, params); - } - builder.endArray(); - return builder; - } - - private final static class Fields { - private static final String SIGNED_LICENCES = "signed_licenses"; - private static final String TRIAL_LICENSES = "trial_licenses"; - } -} \ No newline at end of file diff --git a/plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesService.java b/plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesService.java deleted file mode 100644 index ba638ab83bd..00000000000 --- a/plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesService.java +++ /dev/null @@ -1,986 +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.license.plugin.core; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Iterables; -import com.google.common.collect.Sets; -import org.apache.lucene.util.CollectionUtil; -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.stream.StreamInput; -import org.elasticsearch.common.io.stream.StreamOutput; -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.IOException; -import java.util.*; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicReference; - -import static org.elasticsearch.license.core.Licenses.reduceAndMap; - -/** - * 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 feature registration and notification to consumer plugin(s) - *

- *

- * Registration Scheme: - *

- * A consumer plugin (feature) is registered with {@link LicensesClientService#register(String, TrialLicenseOptions, java.util.Collection, LicensesClientService.Listener)} - * This method can be called at any time during the life-cycle of the consumer plugin. - * If the feature 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 feature(s) are notified appropriately using the notification scheme - *

- *

- * Notification Scheme: - *

- * All registered feature(s) are notified using {@link #notifyFeatures(LicensesMetaData)} (depends on the current - * {@link #registeredListeners}). It is idempotent with respect to all the feature listeners. - *

- * The notification scheduling is done by {@link #notifyFeaturesAndScheduleNotification(LicensesMetaData)} which does the following: - * - calls {@link #notifyFeatures(LicensesMetaData)} to notify all registered feature(s) - * - if there is any license(s) with a future expiry date in the current cluster state: - * - schedules a delayed {@link LicensingClientNotificationJob} on the MIN of all the expiry dates of all the registered feature(s) - *

- * The {@link LicensingClientNotificationJob} calls {@link #notifyFeaturesAndScheduleNotification(LicensesMetaData)} to schedule - * another delayed {@link LicensingClientNotificationJob} as stated above. It is a no-op in case of a global block on - * {@link org.elasticsearch.gateway.GatewayService#STATE_NOT_RECOVERED_BLOCK} - *

- * Upon successful registration of a new feature: - * - {@link #notifyFeaturesAndScheduleNotification(LicensesMetaData)} is called - *

- * Upon clusterChanged(): - * - {@link #notifyFeaturesAndScheduleNotification(LicensesMetaData)} is called if: - * - new trial/signed license(s) are found in the cluster state meta data - * - if new feature(s) are added to the registeredListener - * - if the previous cluster state had a global block on {@link org.elasticsearch.gateway.GatewayService#STATE_NOT_RECOVERED_BLOCK} - * - no-op in case of global block on {@link org.elasticsearch.gateway.GatewayService#STATE_NOT_RECOVERED_BLOCK} - */ -@Singleton -public class LicensesService extends AbstractLifecycleComponent implements ClusterStateListener, LicensesManagerService, LicensesClientService { - - 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 registeredListeners = new CopyOnWriteArrayList<>(); - - /** - * Currently pending consumers that has to be registered - */ - private final Queue pendingListeners = new ConcurrentLinkedQueue<>(); - - /** - * Currently active scheduledNotifications - * All finished notifications will be cleared by {@link #scheduleNextNotification(long)} - */ - private final Queue scheduledNotifications = new ConcurrentLinkedQueue<>(); - - /** - * Currently active event notifications for every registered feature - */ - private final Map> eventNotificationsMap = new HashMap<>(); - - /** - * The last licensesMetaData that has been notified by {@link #notifyFeatures(LicensesMetaData)} - */ - private final AtomicReference lastObservedLicensesState; - - @Inject - public LicensesService(Settings settings, ClusterService clusterService, ThreadPool threadPool, TransportService transportService) { - super(settings); - this.clusterService = clusterService; - this.threadPool = threadPool; - this.transportService = transportService; - this.lastObservedLicensesState = new AtomicReference<>(null); - if (DiscoveryNode.masterNode(settings)) { - transportService.registerRequestHandler(REGISTER_TRIAL_LICENSE_ACTION_NAME, RegisterTrialLicenseRequest.class, - ThreadPool.Names.SAME, new RegisterTrialLicenseRequestHandler()); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void registerLicenses(final PutLicenseRequestHolder requestHolder, final ActionListener listener) { - final PutLicenseRequest request = requestHolder.request; - final Set newLicenses = Sets.newHashSet(request.licenses()); - LicensesStatus status = checkLicenses(newLicenses); - if (status == LicensesStatus.VALID) { - clusterService.submitStateUpdateTask(requestHolder.source, 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 metaData = currentState.metaData(); - MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData()); - LicensesMetaData currentLicenses = metaData.custom(LicensesMetaData.TYPE); - final LicensesWrapper licensesWrapper = LicensesWrapper.wrap(currentLicenses); - List updatedSignedLicenses = licensesWrapper.addAndGetSignedLicenses(newLicenses); - if (updatedSignedLicenses.size() != licensesWrapper.signedLicenses.size()) { - LicensesMetaData newLicensesMetaData = new LicensesMetaData(updatedSignedLicenses, licensesWrapper.trialLicenses); - mdBuilder.putCustom(LicensesMetaData.TYPE, newLicensesMetaData); - return ClusterState.builder(currentState).metaData(mdBuilder).build(); - } - return currentState; - } - }); - } else { - listener.onResponse(new LicensesUpdateResponse(true, status)); - } - } - - public static class LicensesUpdateResponse extends ClusterStateUpdateResponse { - private final LicensesStatus status; - - public LicensesUpdateResponse(boolean acknowledged, LicensesStatus status) { - super(acknowledged); - this.status = status; - } - - public LicensesStatus status() { - return status; - } - } - - /** - * {@inheritDoc} - */ - @Override - public void removeLicenses(final DeleteLicenseRequestHolder requestHolder, final ActionListener listener) { - final DeleteLicenseRequest request = requestHolder.request; - clusterService.submitStateUpdateTask(requestHolder.source, 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(); - LicensesMetaData currentLicenses = metaData.custom(LicensesMetaData.TYPE); - final LicensesWrapper licensesWrapper = LicensesWrapper.wrap(currentLicenses); - List updatedSignedLicenses = licensesWrapper.removeAndGetSignedLicenses(request.features()); - if (updatedSignedLicenses.size() != licensesWrapper.signedLicenses.size()) { - LicensesMetaData newLicensesMetaData = new LicensesMetaData(updatedSignedLicenses, licensesWrapper.trialLicenses); - MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData()); - mdBuilder.putCustom(LicensesMetaData.TYPE, newLicensesMetaData); - return ClusterState.builder(currentState).metaData(mdBuilder).build(); - } else { - return currentState; - } - } - }); - } - - /** - * {@inheritDoc} - */ - @Override - public Set enabledFeatures() { - Set enabledFeatures = Sets.newHashSet(); - for (ListenerHolder holder : registeredListeners) { - if (holder.enabled) { - enabledFeatures.add(holder.feature); - } - } - if (logger.isDebugEnabled()) { - StringBuilder stringBuilder = new StringBuilder(); - for (String feature: enabledFeatures) { - if (stringBuilder.length() != 0) { - stringBuilder.append(", "); - } - stringBuilder.append(feature); - } - logger.debug("LicensesManagerService: Enabled Features: [" + stringBuilder.toString() + "]"); - } - return enabledFeatures; - } - - /** - * {@inheritDoc} - */ - @Override - public List getLicenses() { - final LicensesMetaData currentMetaData = clusterService.state().metaData().custom(LicensesMetaData.TYPE); - if (currentMetaData != null) { - // don't use ESLicenses.reduceAndMap, as it will merge out expired licenses - List currentLicenses = new ArrayList<>(); - currentLicenses.addAll(currentMetaData.getSignedLicenses()); - currentLicenses.addAll(currentMetaData.getTrialLicenses()); - - // bucket license for feature with the latest expiry date - Map licenseMap = new HashMap<>(); - for (License license : currentLicenses) { - if (!licenseMap.containsKey(license.feature())) { - licenseMap.put(license.feature(), license); - } else { - License prevLicense = licenseMap.get(license.feature()); - if (license.expiryDate() > prevLicense.expiryDate()) { - licenseMap.put(license.feature(), license); - } - } - } - - // sort the licenses by issue date - List reducedLicenses = new ArrayList<>(licenseMap.values()); - CollectionUtil.introSort(reducedLicenses, new Comparator() { - @Override - public int compare(License license1, License license2) { - return (int) (license2.issueDate() - license1.issueDate()); - } - }); - return reducedLicenses; - } - return Collections.emptyList(); - } - - private LicensesStatus checkLicenses(Set licenses) { - final ImmutableMap map = reduceAndMap(licenses); - if (LicenseVerifier.verifyLicenses(map.values())) { - return LicensesStatus.VALID; - } else { - return LicensesStatus.INVALID; - } - } - - /** - * Master-only operation to generate a one-time trial license for a feature. - * The trial license is only generated and stored if the current cluster state metaData - * has no signed/one-time-trial license for the feature in question - */ - private void registerTrialLicense(final RegisterTrialLicenseRequest request) { - clusterService.submitStateUpdateTask("register trial license []", new ProcessedClusterStateUpdateTask() { - @Override - public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) { - LicensesMetaData licensesMetaData = newState.metaData().custom(LicensesMetaData.TYPE); - logLicenseMetaDataStats("after trial license registration", licensesMetaData); - } - - @Override - public ClusterState execute(ClusterState currentState) throws Exception { - MetaData metaData = currentState.metaData(); - MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData()); - LicensesMetaData currentLicensesMetaData = metaData.custom(LicensesMetaData.TYPE); - final LicensesWrapper licensesWrapper = LicensesWrapper.wrap(currentLicensesMetaData); - // do not generate a trial license for a feature that already has a signed/trial license - if (checkTrialLicenseGenerationCondition(request.feature, licensesWrapper)) { - List currentTrailLicenses = new ArrayList<>(licensesWrapper.trialLicenses); - currentTrailLicenses.add(generateEncodedTrialLicense(request.feature, request.duration, request.maxNodes)); - final LicensesMetaData newLicensesMetaData = new LicensesMetaData( - licensesWrapper.signedLicenses, ImmutableList.copyOf(currentTrailLicenses)); - mdBuilder.putCustom(LicensesMetaData.TYPE, newLicensesMetaData); - return ClusterState.builder(currentState).metaData(mdBuilder).build(); - } - return currentState; - } - - @Override - public void onFailure(String source, @Nullable Throwable t) { - logger.debug("LicensesService: " + source, t); - } - - private boolean checkTrialLicenseGenerationCondition(String feature, LicensesWrapper licensesWrapper) { - final List currentLicenses = new ArrayList<>(); - currentLicenses.addAll(licensesWrapper.signedLicenses); - currentLicenses.addAll(licensesWrapper.trialLicenses); - for (License license : currentLicenses) { - if (license.feature().equals(feature)) { - return false; - } - } - return true; - } - - private License generateEncodedTrialLicense(String feature, TimeValue duration, int maxNodes) { - return TrialLicenseUtils.builder() - .issuedTo(clusterService.state().getClusterName().value()) - .issueDate(System.currentTimeMillis()) - .duration(duration) - .feature(feature) - .maxNodes(maxNodes) - .build(); - } - }); - } - - @Override - protected void doStart() throws ElasticsearchException { - clusterService.add(this); - } - - @Override - protected void doStop() throws ElasticsearchException { - clusterService.remove(this); - - // cancel all notifications - for (ScheduledFuture scheduledNotification : scheduledNotifications) { - FutureUtils.cancel(scheduledNotification); - } - - for (Queue queue : eventNotificationsMap.values()) { - for (ScheduledFuture scheduledFuture : queue) { - FutureUtils.cancel(scheduledFuture); - } - queue.clear(); - } - - LicensesMetaData currentLicensesMetaData = clusterService.state().metaData().custom(LicensesMetaData.TYPE); - final Map effectiveLicenses = getEffectiveLicenses(currentLicensesMetaData); - // notify features to be disabled - for (ListenerHolder holder : registeredListeners) { - holder.disableFeatureIfNeeded(effectiveLicenses.get(holder.feature), false); - } - // clear all handlers - registeredListeners.clear(); - - // empty out notification queue - scheduledNotifications.clear(); - - lastObservedLicensesState.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}: - * - tries to register any {@link #pendingListeners} by calling {@link #registeredListeners} - * - if any {@link #pendingListeners} are registered successfully or if previous cluster state had a block on - * {@link org.elasticsearch.gateway.GatewayService#STATE_NOT_RECOVERED_BLOCK}, calls - * {@link #notifyFeaturesAndScheduleNotification(LicensesMetaData)} - * - else calls {@link #notifyFeaturesAndScheduleNotificationIfNeeded(LicensesMetaData)} - */ - @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 oldLicensesMetaData = previousClusterState.getMetaData().custom(LicensesMetaData.TYPE); - final LicensesMetaData currentLicensesMetaData = currentClusterState.getMetaData().custom(LicensesMetaData.TYPE); - logLicenseMetaDataStats("old", oldLicensesMetaData); - logLicenseMetaDataStats("new", currentLicensesMetaData); - - // register any pending listeners - if (!pendingListeners.isEmpty()) { - ListenerHolder pendingRegistrationListener; - while ((pendingRegistrationListener = pendingListeners.poll()) != null) { - boolean masterAvailable = registerListener(pendingRegistrationListener); - if (logger.isDebugEnabled()) { - logger.debug("trying to register pending listener for " + pendingRegistrationListener.feature + " masterAvailable: " + masterAvailable); - } - if (!masterAvailable) { - // if the master is not available do not, break out of trying pendingListeners - pendingListeners.add(pendingRegistrationListener); - break; - } - } - } - - // notify all interested plugins - if (previousClusterState.blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK)) { - notifyFeaturesAndScheduleNotification(currentLicensesMetaData); - } else { - notifyFeaturesAndScheduleNotificationIfNeeded(currentLicensesMetaData); - } - final Map effectiveLicenses = getEffectiveLicenses(currentLicensesMetaData); - for (ListenerHolder listenerHolder : registeredListeners) { - listenerHolder.scheduleNotificationIfNeeded(effectiveLicenses.get(listenerHolder.feature)); - } - } else if (logger.isDebugEnabled()) { - logger.debug("clusterChanged: no action [has STATE_NOT_RECOVERED_BLOCK]"); - } - } - - /** - * Calls {@link #notifyFeaturesAndScheduleNotification(LicensesMetaData)} with currentLicensesMetaData - * if it was not already notified on. - *

- * Upon completion sets currentLicensesMetaData to {@link #lastObservedLicensesState} - * to ensure the same license(s) are not notified on from - * {@link #clusterChanged(org.elasticsearch.cluster.ClusterChangedEvent)} - */ - private void notifyFeaturesAndScheduleNotificationIfNeeded(final LicensesMetaData currentLicensesMetaData) { - final LicensesMetaData lastNotifiedLicensesMetaData = lastObservedLicensesState.get(); - if (lastNotifiedLicensesMetaData != null && lastNotifiedLicensesMetaData.equals(currentLicensesMetaData)) { - if (logger.isDebugEnabled()) { - logger.debug("currentLicensesMetaData has been already notified on"); - } - return; - } - notifyFeaturesAndScheduleNotification(currentLicensesMetaData); - lastObservedLicensesState.set(currentLicensesMetaData); - logLicenseMetaDataStats("Setting last observed metaData", currentLicensesMetaData); - } - - /** - * Calls {@link #notifyFeatures(LicensesMetaData)} with currentLicensesMetaData - * and schedules the earliest expiry (if any) notification for registered feature(s) - */ - private void notifyFeaturesAndScheduleNotification(final LicensesMetaData currentLicensesMetaData) { - long nextScheduleFrequency = notifyFeatures(currentLicensesMetaData); - if (nextScheduleFrequency != -1l) { - scheduleNextNotification(nextScheduleFrequency); - } - } - - /** - * Checks license expiry for all the registered feature(s) - * - * @return -1 if there are no expiring license(s) for any registered feature(s), else - * returns the minimum of the expiry times of all the registered feature(s) to - * schedule an expiry notification - */ - private long notifyFeatures(final LicensesMetaData currentLicensesMetaData) { - long nextScheduleFrequency = -1l; - for (ListenerHolder listenerHolder : registeredListeners) { - final Map effectiveLicenses = getEffectiveLicenses(currentLicensesMetaData); - License license = effectiveLicenses.get(listenerHolder.feature); - if (license == null) { - continue; - } - long expiryDate = license.expiryDate(); - long issueDate = license.issueDate(); - long now = System.currentTimeMillis(); - long expiryDuration = expiryDate - now; - - if (expiryDuration > 0l && (now - issueDate) >= 0l) { - listenerHolder.enableFeatureIfNeeded(license); - if (nextScheduleFrequency == -1l) { - nextScheduleFrequency = expiryDuration; - } else { - nextScheduleFrequency = Math.min(expiryDuration, nextScheduleFrequency); - } - } else { - listenerHolder.disableFeatureIfNeeded(license, true); - } - - if (logger.isDebugEnabled()) { - String status; - if (expiryDate != -1l) { - status = " status: license expires in : " + TimeValue.timeValueMillis(expiryDate - System.currentTimeMillis()); - } else { - status = " status: no trial/signed license found"; - } - if (expiryDuration > 0l) { - status += " action: enableFeatureIfNeeded"; - } else { - status += " action: disableFeatureIfNeeded"; - } - logger.debug(listenerHolder.toString() + "" + status); - } - } - - if (logger.isDebugEnabled()) { - if (nextScheduleFrequency == -1l) { - logger.debug("no need to schedule next notification"); - } else { - logger.debug("next notification time: " + TimeValue.timeValueMillis(nextScheduleFrequency).toString()); - } - } - - return nextScheduleFrequency; - - } - - private void logLicenseMetaDataStats(String prefix, LicensesMetaData licensesMetaData) { - if (logger.isDebugEnabled()) { - if (licensesMetaData != null) { - StringBuilder signedFeatures = new StringBuilder(); - for (License license : licensesMetaData.getSignedLicenses()) { - if (signedFeatures.length() != 0) { - signedFeatures.append(", "); - } - signedFeatures.append(license.feature()); - } - StringBuilder trialFeatures = new StringBuilder(); - for (License license : licensesMetaData.getTrialLicenses()) { - if (trialFeatures.length() != 0) { - trialFeatures.append(", "); - } - trialFeatures.append(license.feature()); - } - logger.debug(prefix + " LicensesMetaData: signedLicenses: [" + signedFeatures.toString() + "] trialLicenses: [" + trialFeatures.toString() + "]"); - } else { - logger.debug(prefix + " LicensesMetaData: signedLicenses: [] trialLicenses: []"); - } - } - } - - /** - * {@inheritDoc} - */ - @Override - public void register(String feature, TrialLicenseOptions trialLicenseOptions, Collection expirationCallbacks, Listener listener) { - for (final ListenerHolder listenerHolder : Iterables.concat(registeredListeners, pendingListeners)) { - if (listenerHolder.feature.equals(feature)) { - throw new IllegalStateException("feature: [" + feature + "] has been already registered"); - } - } - Queue notificationQueue = new ConcurrentLinkedQueue<>(); - eventNotificationsMap.put(feature, notificationQueue); - final ListenerHolder listenerHolder = new ListenerHolder(feature, trialLicenseOptions, expirationCallbacks, listener, notificationQueue); - // don't trust the clusterState for blocks just yet! - final Lifecycle.State clusterServiceState = clusterService.lifecycleState(); - if (clusterServiceState != Lifecycle.State.STARTED) { - pendingListeners.add(listenerHolder); - } else { - if (!registerListener(listenerHolder)) { - pendingListeners.add(listenerHolder); - } - } - } - - /** - * Notifies new feature listener if it already has a signed license - * if new feature has a non-null trial license option, a master node request is made to generate the trial license - * then notifies features if needed - * - * @param listenerHolder of the feature to register - * @return true if registration has been completed, false otherwise (if masterNode is not available & trail license spec is provided) - * or if there is a global block on {@link org.elasticsearch.gateway.GatewayService#STATE_NOT_RECOVERED_BLOCK} - */ - private boolean registerListener(final ListenerHolder listenerHolder) { - logger.debug("Registering listener for " + listenerHolder.feature); - final ClusterState currentState = clusterService.state(); - if (currentState.blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK)) { - return false; - } - - final LicensesMetaData currentMetaData = currentState.metaData().custom(LicensesMetaData.TYPE); - if (expiryDateForFeature(listenerHolder.feature, currentMetaData) == -1l) { - // does not have any license so generate a trial license - TrialLicenseOptions options = listenerHolder.trialLicenseOptions; - if (options != null) { - // Trial license option is provided - RegisterTrialLicenseRequest request = new RegisterTrialLicenseRequest(listenerHolder.feature, - options.duration, options.maxNodes); - if (currentState.nodes().localNodeMaster()) { - registerTrialLicense(request); - } else { - DiscoveryNode masterNode = currentState.nodes().masterNode(); - if (masterNode != null) { - transportService.sendRequest(masterNode, - REGISTER_TRIAL_LICENSE_ACTION_NAME, request, EmptyTransportResponseHandler.INSTANCE_SAME); - } else { - // could not sent register trial license request to master - logger.debug("Store as pendingRegistration [master not available yet]"); - } - // make sure trial license is available before registration - return false; - } - } else if (logger.isDebugEnabled()) { - // notify feature as clusterChangedEvent may not happen - // as no trial or signed license has been found for feature - logger.debug("Calling notifyFeaturesAndScheduleNotification [no trial license spec provided]"); - } - } else if (logger.isDebugEnabled()) { - // signed license already found for the new registered - // feature, notify feature on registration - logger.debug("Calling notifyFeaturesAndScheduleNotification [signed/trial license available]"); - } - - if (currentMetaData == null) { - return false; - } - registeredListeners.add(listenerHolder); - notifyFeaturesAndScheduleNotification(currentMetaData); - final Map effectiveLicenses = getEffectiveLicenses(currentMetaData); - listenerHolder.scheduleNotificationIfNeeded(effectiveLicenses.get(listenerHolder.feature)); - return true; - } - - private static long expiryDateForFeature(String feature, final LicensesMetaData currentLicensesMetaData) { - final Map effectiveLicenses = getEffectiveLicenses(currentLicensesMetaData); - License featureLicense; - if ((featureLicense = effectiveLicenses.get(feature)) != null) { - return featureLicense.expiryDate(); - } - return -1l; - } - - private static Map getEffectiveLicenses(final LicensesMetaData metaData) { - Map map = new HashMap<>(); - if (metaData != null) { - Set licenses = new HashSet<>(); - for (License license : metaData.getSignedLicenses()) { - if (LicenseVerifier.verifyLicense(license)) { - licenses.add(license); - } - } - licenses.addAll(metaData.getTrialLicenses()); - return reduceAndMap(licenses); - } - return ImmutableMap.copyOf(map); - - } - - /** - * Clears out any completed notification futures - */ - private static void clearFinishedNotifications(Queue scheduledNotifications) { - while (!scheduledNotifications.isEmpty()) { - ScheduledFuture notification = scheduledNotifications.peek(); - if (notification != null && notification.isDone()) { - // remove the notifications that are done - scheduledNotifications.poll(); - } else { - // stop emptying out the queue as soon as the first undone future hits - break; - } - } - } - - private String executorName() { - return ThreadPool.Names.GENERIC; - } - - /** - * Schedules an expiry notification with a delay of nextScheduleDelay - */ - private void scheduleNextNotification(long nextScheduleDelay) { - clearFinishedNotifications(scheduledNotifications); - - try { - final TimeValue delay = TimeValue.timeValueMillis(nextScheduleDelay); - scheduledNotifications.add(threadPool.schedule(delay, executorName(), new LicensingClientNotificationJob())); - if (logger.isDebugEnabled()) { - logger.debug("Scheduling next notification after: " + delay); - } - } catch (EsRejectedExecutionException ex) { - logger.debug("Couldn't re-schedule licensing client notification job", ex); - } - } - - /** - * Job for notifying on expired license(s) to registered feature(s) - * In case of a global block on {@link org.elasticsearch.gateway.GatewayService#STATE_NOT_RECOVERED_BLOCK}, - * the notification is not run, instead the feature(s) would be notified on the next - * {@link #clusterChanged(org.elasticsearch.cluster.ClusterChangedEvent)} with no global block - */ - private class LicensingClientNotificationJob implements Runnable { - - public LicensingClientNotificationJob() { - } - - @Override - public void run() { - logger.debug("Performing LicensingClientNotificationJob"); - - // next clusterChanged event will deal with the missed notifications - final ClusterState currentClusterState = clusterService.state(); - if (!currentClusterState.blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK)) { - final LicensesMetaData currentLicensesMetaData = currentClusterState.metaData().custom(LicensesMetaData.TYPE); - notifyFeaturesAndScheduleNotification(currentLicensesMetaData); - } else if (logger.isDebugEnabled()) { - logger.debug("skip notification [STATE_NOT_RECOVERED_BLOCK]"); - } - } - } - - public static class PutLicenseRequestHolder { - private final PutLicenseRequest request; - private final String source; - - public PutLicenseRequestHolder(PutLicenseRequest request, String source) { - this.request = request; - this.source = source; - } - } - - public static class DeleteLicenseRequestHolder { - private final DeleteLicenseRequest request; - private final String source; - - public DeleteLicenseRequestHolder(DeleteLicenseRequest request, String source) { - this.request = request; - this.source = source; - } - } - - - - - /** - * Stores configuration and listener for a feature - */ - private class ListenerHolder { - final String feature; - final TrialLicenseOptions trialLicenseOptions; - final Collection expirationCallbacks; - final Listener listener; - final AtomicLong currentExpiryDate = new AtomicLong(-1l); - final Queue notificationQueue; - - volatile boolean initialized = false; - volatile boolean enabled = false; // by default, a consumer plugin should be disabled - - private ListenerHolder(String feature, TrialLicenseOptions trialLicenseOptions, Collection expirationCallbacks, Listener listener, Queue notificationQueue) { - this.feature = feature; - this.trialLicenseOptions = trialLicenseOptions; - this.expirationCallbacks = expirationCallbacks; - this.listener = listener; - this.notificationQueue = notificationQueue; - } - - private synchronized void enableFeatureIfNeeded(License license) { - if (!initialized || !enabled) { - listener.onEnabled(license); - initialized = true; - enabled = true; - logger.info("license for [" + feature + "] - valid"); - } - } - - private synchronized void disableFeatureIfNeeded(License license, boolean log) { - if (!initialized || enabled) { - listener.onDisabled(license); - initialized = true; - enabled = false; - if (log) { - logger.info("license for [" + feature + "] - expired"); - } - } - } - - private Runnable triggerJob(final ExpirationCallback callback) { - return new Runnable() { - @Override - public void run() { - LicensesMetaData currentLicensesMetaData = clusterService.state().metaData().custom(LicensesMetaData.TYPE); - final Map effectiveLicenses = getEffectiveLicenses(currentLicensesMetaData); - triggerEvent(effectiveLicenses.get(feature), System.currentTimeMillis(), callback); - } - }; - } - - /** - * schedules all {@link ExpirationCallback} associated with license - * If callbacks are already scheduled clear up finished notifications from the queue - */ - private void scheduleNotificationIfNeeded(final License license) { - long expiryDate = ((license != null) ? license.expiryDate() : -1l); - if (currentExpiryDate.get() == expiryDate) { - clearFinishedNotifications(notificationQueue); - return; - } - currentExpiryDate.set(expiryDate); - - // clear out notification queue - while (!notificationQueue.isEmpty()) { - ScheduledFuture notification = notificationQueue.peek(); - if (notification != null) { - // cancel - FutureUtils.cancel(notification); - notificationQueue.poll(); - } - } - - long now = System.currentTimeMillis(); - // Schedule the first for all the callbacks - long expiryDuration = expiryDate - now; - - //schedule first event of callbacks that will be activated in the future - for (ExpirationCallback expirationCallback : expirationCallbacks) { - if (!expirationCallback.matches(expiryDate, now)) { - long delay = -1l; - switch (expirationCallback.orientation()) { - case PRE: - delay = expiryDuration - expirationCallback.max().getMillis(); - break; - case POST: - if (expiryDuration >= 0l) { - delay = expiryDuration + expirationCallback.min().getMillis(); - } else { - delay = (-1l * expiryDuration) - expirationCallback.min().getMillis(); - } - break; - } - if (delay > 0l) { - if (logger.isDebugEnabled()) { - logger.debug("Adding first notification for: orientation: " + expirationCallback.orientation().name() - + " min: " + expirationCallback.min() - + " max: " + expirationCallback.max() - + " with delay: " + TimeValue.timeValueMillis(delay) - + " license expiry duration: " + TimeValue.timeValueMillis(expiryDuration)); - } - notificationQueue.add(threadPool.schedule(TimeValue.timeValueMillis(delay), executorName(), triggerJob(expirationCallback))); - } - } - } - if (license != null) { - // schedule first event of callbacks that match - logger.debug("Calling TRIGGER_EVENTS with license for " + license.feature() + " expiry: " + license.expiryDate()); - for (ExpirationCallback expirationCallback : expirationCallbacks) { - triggerEvent(license, now, expirationCallback); - } - } - } - - private void triggerEvent(final License license, long now, final ExpirationCallback expirationCallback) { - if (expirationCallback.matches(license.expiryDate(), now)) { - long expiryDuration = license.expiryDate() - now; - boolean expired = expiryDuration <= 0l; - if (logger.isDebugEnabled()) { - logger.debug("Calling notification on: orientation: " + expirationCallback.orientation().name() - + " min: " + expirationCallback.min() - + " max: " + expirationCallback.max() - + " scheduled after: " + expirationCallback.frequency().getMillis() - + " next interval match: " + expirationCallback.matches(license.expiryDate(), System.currentTimeMillis() + expirationCallback.frequency().getMillis())); - } - expirationCallback.on(license, new ExpirationStatus(expired, TimeValue.timeValueMillis((!expired) ? expiryDuration : (-1l * expiryDuration)))); - notificationQueue.add(threadPool.schedule(expirationCallback.frequency(), executorName(), triggerJob(expirationCallback))); - } - } - - @Override - public String toString() { - return "(feature: " + feature + ", enabled: " + enabled + ")"; - } - } - - /** - * Thin wrapper to work with {@link LicensesMetaData} - * Never mutates the wrapped metaData - */ - private static class LicensesWrapper { - - public static LicensesWrapper wrap(LicensesMetaData licensesMetaData) { - return new LicensesWrapper(licensesMetaData); - } - - private ImmutableList signedLicenses = ImmutableList.of(); - private ImmutableList trialLicenses = ImmutableList.of(); - - private LicensesWrapper(LicensesMetaData licensesMetaData) { - if (licensesMetaData != null) { - this.signedLicenses = ImmutableList.copyOf(licensesMetaData.getSignedLicenses()); - this.trialLicenses = ImmutableList.copyOf(licensesMetaData.getTrialLicenses()); - } - } - - /** - * Returns existingLicenses + newLicenses. - * A new license is added if: - * - there is no current license for the feature - * - current license for feature has a earlier expiry date - */ - private List addAndGetSignedLicenses(Set newLicenses) { - final ImmutableMap newLicensesMap = reduceAndMap(newLicenses); - List newSignedLicenses = new ArrayList<>(signedLicenses); - final ImmutableMap oldLicenseMap = reduceAndMap(Sets.newHashSet(signedLicenses)); - for (String newFeature : newLicensesMap.keySet()) { - final License newFeatureLicense = newLicensesMap.get(newFeature); - if (oldLicenseMap.containsKey(newFeature)) { - final License oldFeatureLicense = oldLicenseMap.get(newFeature); - if (oldFeatureLicense.expiryDate() < newFeatureLicense.expiryDate()) { - newSignedLicenses.add(newFeatureLicense); - } - } else { - newSignedLicenses.add(newFeatureLicense); - } - } - return ImmutableList.copyOf(newSignedLicenses); - } - - private List removeAndGetSignedLicenses(Set features) { - List updatedSignedLicenses = new ArrayList<>(); - for (License license : signedLicenses) { - if (!features.contains(license.feature())) { - updatedSignedLicenses.add(license); - } - } - return ImmutableList.copyOf(updatedSignedLicenses); - } - } - - /** - * Request for trial license generation to master - */ - private static class RegisterTrialLicenseRequest extends TransportRequest { - private int maxNodes; - private String feature; - private TimeValue duration; - - private RegisterTrialLicenseRequest() { - } - - private RegisterTrialLicenseRequest(String feature, TimeValue duration, int maxNodes) { - this.maxNodes = maxNodes; - this.feature = feature; - this.duration = duration; - } - - @Override - public void readFrom(StreamInput in) throws IOException { - super.readFrom(in); - maxNodes = in.readVInt(); - feature = in.readString(); - duration = new TimeValue(in.readVLong(), TimeUnit.MILLISECONDS); - } - - - @Override - public void writeTo(StreamOutput out) throws IOException { - super.writeTo(out); - out.writeVInt(maxNodes); - out.writeString(feature); - out.writeVLong(duration.getMillis()); - } - } - - /** - * Request handler for trial license generation to master - */ - private class RegisterTrialLicenseRequestHandler implements TransportRequestHandler { - - @Override - public void messageReceived(RegisterTrialLicenseRequest request, TransportChannel channel) throws Exception { - registerTrialLicense(request); - channel.sendResponse(TransportResponse.Empty.INSTANCE); - } - } -} diff --git a/plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesStatus.java b/plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesStatus.java deleted file mode 100644 index 3bd18d58770..00000000000 --- a/plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesStatus.java +++ /dev/null @@ -1,34 +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.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/plugin/src/main/java/org/elasticsearch/license/plugin/core/TrialLicenseUtils.java b/plugin/src/main/java/org/elasticsearch/license/plugin/core/TrialLicenseUtils.java deleted file mode 100644 index 52e56c49da9..00000000000 --- a/plugin/src/main/java/org/elasticsearch/license/plugin/core/TrialLicenseUtils.java +++ /dev/null @@ -1,113 +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.license.plugin.core; - -import org.elasticsearch.common.Base64; -import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.common.xcontent.*; -import org.elasticsearch.license.core.License; -import org.elasticsearch.license.core.Licenses; - -import java.io.IOException; -import java.util.Collections; -import java.util.UUID; - -import static org.elasticsearch.license.core.CryptUtils.decrypt; -import static org.elasticsearch.license.core.CryptUtils.encrypt; - -public class TrialLicenseUtils { - - public static TrialLicenseBuilder builder() { - return new TrialLicenseBuilder(); - } - - public static class TrialLicenseBuilder { - private static final String DEFAULT_ISSUER = "elasticsearch"; - private static final String DEFAULT_TYPE = "trial"; - private static final String DEFAULT_SUBSCRIPTION_TYPE = "none"; - - private String feature; - private long expiryDate = -1; - private long issueDate = -1; - private TimeValue duration; - private int maxNodes = -1; - private String uid = null; - private String issuedTo; - - public TrialLicenseBuilder() { - } - - public TrialLicenseBuilder uid(String uid) { - this.uid = uid; - return this; - } - - public TrialLicenseBuilder issuedTo(String issuedTo) { - this.issuedTo = issuedTo; - return this; - } - - public TrialLicenseBuilder maxNodes(int maxNodes) { - this.maxNodes = maxNodes; - return this; - } - - public TrialLicenseBuilder feature(String featureType) { - this.feature = featureType; - return this; - } - - public TrialLicenseBuilder issueDate(long issueDate) { - this.issueDate = issueDate; - return this; - } - - public TrialLicenseBuilder duration(TimeValue duration) { - this.duration = duration; - return this; - } - - public TrialLicenseBuilder expiryDate(long expiryDate) { - this.expiryDate = expiryDate; - return this; - } - - public License build() { - if (expiryDate == -1) { - expiryDate = issueDate + duration.millis(); - } - if (uid == null) { - uid = UUID.randomUUID().toString(); - } - return License.builder() - .type(DEFAULT_TYPE) - .subscriptionType(DEFAULT_SUBSCRIPTION_TYPE) - .issuer(DEFAULT_ISSUER) - .uid(uid) - .issuedTo(issuedTo) - .issueDate(issueDate) - .feature(feature) - .maxNodes(maxNodes) - .expiryDate(expiryDate) - .build(); - } - - } - - public static License fromEncodedTrialLicense(String encodedTrialLicense) throws IOException { - byte[] data = decrypt(Base64.decode(encodedTrialLicense)); - XContentParser parser = XContentFactory.xContent(XContentType.JSON).createParser(data); - parser.nextToken(); - return License.builder().fromXContent(parser).build(); - } - - public static String toEncodedTrialLicense(License trialLicense) throws IOException { - XContentBuilder contentBuilder = XContentFactory.contentBuilder(XContentType.JSON); - // trial license is equivalent to a license spec (no signature) - trialLicense.toXContent(contentBuilder, new ToXContent.MapParams(Collections.singletonMap(Licenses.LICENSE_SPEC_VIEW_MODE, "true"))); - return Base64.encodeBytes(encrypt(contentBuilder.bytes().toBytes())); - } -} diff --git a/plugin/src/main/java/org/elasticsearch/license/plugin/rest/RestDeleteLicenseAction.java b/plugin/src/main/java/org/elasticsearch/license/plugin/rest/RestDeleteLicenseAction.java deleted file mode 100644 index 43ce98e7a9b..00000000000 --- a/plugin/src/main/java/org/elasticsearch/license/plugin/rest/RestDeleteLicenseAction.java +++ /dev/null @@ -1,41 +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.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, "/_licenses/{features}", this); - } - - - @Override - public void handleRequest(final RestRequest request, final RestChannel channel, final Client client) { - final String[] features = Strings.splitStringByCommaToArray(request.param("features")); - if (features.length == 0) { - throw new IllegalArgumentException("no feature specified for license deletion"); - } - DeleteLicenseRequest deleteLicenseRequest = new DeleteLicenseRequest(features); - client.admin().cluster().execute(DeleteLicenseAction.INSTANCE, deleteLicenseRequest, new AcknowledgedRestListener(channel)); - } -} diff --git a/plugin/src/main/java/org/elasticsearch/license/plugin/rest/RestGetLicenseAction.java b/plugin/src/main/java/org/elasticsearch/license/plugin/rest/RestGetLicenseAction.java deleted file mode 100644 index 71b9fd5d423..00000000000 --- a/plugin/src/main/java/org/elasticsearch/license/plugin/rest/RestGetLicenseAction.java +++ /dev/null @@ -1,59 +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.license.plugin.rest; - -import com.google.common.collect.ImmutableMap; -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.Licenses; -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.Map; - -import static org.elasticsearch.rest.RestRequest.Method.GET; -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, "/_licenses", 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 = ImmutableMap.of(Licenses.REST_VIEW_MODE, "true"); - 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(); - } - Licenses.toXContent(response.licenses(), builder, params); - return new BytesRestResponse(OK, builder); - } - }); - } - -} diff --git a/plugin/src/main/java/org/elasticsearch/license/plugin/rest/RestPutLicenseAction.java b/plugin/src/main/java/org/elasticsearch/license/plugin/rest/RestPutLicenseAction.java deleted file mode 100644 index c469d0a0f8c..00000000000 --- a/plugin/src/main/java/org/elasticsearch/license/plugin/rest/RestPutLicenseAction.java +++ /dev/null @@ -1,69 +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.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.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.license.plugin.core.LicensesStatus; -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 java.io.IOException; - -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, "/_licenses", this); - controller.registerHandler(POST, "/_licenses", this); - } - - - @Override - public void handleRequest(final RestRequest request, final RestChannel channel, final Client client) { - PutLicenseRequest putLicenseRequest = new PutLicenseRequest(); - putLicenseRequest.licenses(request.content().toUtf8()); - client.admin().cluster().execute(PutLicenseAction.INSTANCE, putLicenseRequest, new LicensesAcknowledgedListener(channel)); - } - - private class LicensesAcknowledgedListener extends AcknowledgedRestListener { - - - public LicensesAcknowledgedListener(RestChannel channel) { - super(channel); - } - - @Override - protected void addCustomFields(XContentBuilder builder, PutLicenseResponse response) throws IOException { - LicensesStatus status = response.status(); - String statusString = null; - switch (status) { - case VALID: - statusString = "valid"; - break; - case INVALID: - statusString = "invalid"; - break; - case EXPIRED: - statusString = "expired"; - break; - } - builder.field("licenses_status", statusString); - } - } -} diff --git a/plugin/src/main/resources/es-plugin.properties b/plugin/src/main/resources/es-plugin.properties deleted file mode 100644 index c3e279e70bf..00000000000 --- a/plugin/src/main/resources/es-plugin.properties +++ /dev/null @@ -1,2 +0,0 @@ -plugin=org.elasticsearch.license.plugin.LicensePlugin -version=${project.version} diff --git a/plugin/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesConsumerPluginIntegrationTests.java b/plugin/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesConsumerPluginIntegrationTests.java deleted file mode 100644 index b18c99786d2..00000000000 --- a/plugin/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesConsumerPluginIntegrationTests.java +++ /dev/null @@ -1,154 +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.license.plugin; - -import com.google.common.base.Predicate; -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.test.InternalTestCluster; -import org.junit.After; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.List; - -import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope; -import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope.TEST; -import static org.hamcrest.CoreMatchers.equalTo; - -/** - * 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 = 10, numClientNodes = 0, transportClientRatio = 0.0) -public abstract class AbstractLicensesConsumerPluginIntegrationTests extends AbstractLicensesIntegrationTests { - - protected final TestConsumerPluginBase consumerPlugin; - - public AbstractLicensesConsumerPluginIntegrationTests(TestConsumerPluginBase consumerPlugin) { - this.consumerPlugin = consumerPlugin; - } - - private final int trialLicenseDurationInSeconds = 10; - - protected Settings nodeSettings(int nodeOrdinal) { - return Settings.settingsBuilder() - .put(super.nodeSettings(nodeOrdinal)) - .put(consumerPlugin.name() - + ".trial_license_duration_in_seconds", trialLicenseDurationInSeconds) - .putArray("plugin.types", LicensePlugin.class.getName(), consumerPlugin.getClass().getName()) - .build(); - } - - @After - public void afterTest() throws Exception { - wipeAllLicenses(); - assertThat(awaitBusy(new Predicate() { - @Override - public boolean apply(Object o) { - return !clusterService().state().blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK); - } - }), equalTo(true)); - } - - @Test - 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 - assertLicenseManagerEnabledFeatureFor(consumerPlugin.featureName()); - // 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); - assertLicenseManagerDisabledFeatureFor(consumerPlugin.featureName()); - - logger.info(" --> put signed license"); - putLicense(consumerPlugin.featureName(), TimeValue.timeValueSeconds(trialLicenseDurationInSeconds)); - - logger.info(" --> check signed license enabled notification"); - // consumer plugin should notify onEnabled on all data nodes (signed license) - assertConsumerPluginEnabledNotification(1); - assertLicenseManagerEnabledFeatureFor(consumerPlugin.featureName()); - - logger.info(" --> check signed license expiry notification"); - // consumer plugin should notify onDisabled on all data nodes (expired signed license) - assertConsumerPluginDisabledNotification(trialLicenseDurationInSeconds * 2); - assertLicenseManagerDisabledFeatureFor(consumerPlugin.featureName()); - } - - @Test - public void testTrialLicenseNotification() throws Exception { - logger.info(" --> check onEnabled for trial license"); - // managerService should report feature to be enabled on all data nodes - assertLicenseManagerEnabledFeatureFor(consumerPlugin.featureName()); - // consumer plugin service should return enabled on all data nodes - assertConsumerPluginEnabledNotification(1); - - logger.info(" --> sleep for rest of trailLicense duration"); - Thread.sleep(trialLicenseDurationInSeconds * 1000l); - - logger.info(" --> check trial license expiry notification"); - // consumer plugin should notify onDisabled on all data nodes (expired signed license) - assertConsumerPluginDisabledNotification(trialLicenseDurationInSeconds); - assertLicenseManagerDisabledFeatureFor(consumerPlugin.featureName()); - } - - @Test - public void testOverlappingTrialAndSignedLicenseNotification() throws Exception { - logger.info(" --> check onEnabled for trial license"); - // managerService should report feature to be enabled on all data nodes - assertLicenseManagerEnabledFeatureFor(consumerPlugin.featureName()); - // consumer plugin service should return enabled on all data nodes - assertConsumerPluginEnabledNotification(1); - - logger.info(" --> put signed license while trial license is in effect"); - putLicense(consumerPlugin.featureName(), TimeValue.timeValueSeconds(trialLicenseDurationInSeconds * 2)); - - logger.info(" --> check signed license enabled notification"); - // consumer plugin should notify onEnabled on all data nodes (signed license) - assertConsumerPluginEnabledNotification(1); - assertLicenseManagerEnabledFeatureFor(consumerPlugin.featureName()); - - 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); - assertLicenseManagerEnabledFeatureFor(consumerPlugin.featureName()); - - logger.info(" --> check signed license expiry notification"); - // consumer plugin should notify onDisabled on all data nodes (expired signed license) - assertConsumerPluginDisabledNotification(trialLicenseDurationInSeconds * 2 * 2); - assertLicenseManagerDisabledFeatureFor(consumerPlugin.featureName()); - } - - private void assertConsumerPluginEnabledNotification(int timeoutInSec) throws InterruptedException { - assertConsumerPluginNotification(consumerPluginServices(), true, timeoutInSec); - } - - private void assertConsumerPluginDisabledNotification(int timeoutInSec) throws InterruptedException { - assertConsumerPluginNotification(consumerPluginServices(), false, timeoutInSec); - } - - - 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/plugin/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesIntegrationTests.java b/plugin/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesIntegrationTests.java deleted file mode 100644 index bffa917ab80..00000000000 --- a/plugin/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesIntegrationTests.java +++ /dev/null @@ -1,205 +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.license.plugin; - -import com.google.common.base.Predicate; -import com.google.common.collect.Lists; -import org.elasticsearch.cluster.ClusterService; -import org.elasticsearch.cluster.ClusterState; -import org.elasticsearch.cluster.ProcessedClusterStateUpdateTask; -import org.elasticsearch.cluster.metadata.MetaData; -import org.elasticsearch.common.Nullable; -import org.elasticsearch.common.joda.DateMathParser; -import org.elasticsearch.common.joda.FormatDateTimeFormatter; -import org.elasticsearch.common.joda.Joda; -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.LicensesManagerService; -import org.elasticsearch.license.plugin.core.LicensesMetaData; -import org.elasticsearch.license.plugin.core.LicensesStatus; -import org.elasticsearch.test.ElasticsearchIntegrationTest; -import org.elasticsearch.test.InternalTestCluster; -import org.joda.time.format.DateTimeFormatter; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Callable; -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 AbstractLicensesIntegrationTests extends ElasticsearchIntegrationTest { - - private final static FormatDateTimeFormatter formatDateTimeFormatter = Joda.forPattern("yyyy-MM-dd"); - private final static DateTimeFormatter dateTimeFormatter = formatDateTimeFormatter.printer(); - private final static DateMathParser dateMathParser = new DateMathParser(formatDateTimeFormatter); - - 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; - } - }); - } - @Override - protected Settings nodeSettings(int nodeOrdinal) { - return Settings.settingsBuilder() - .put("plugins.load_classpath_plugins", false) - .put("plugin.types", LicensePlugin.class.getName()) - .build(); - } - - @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 ProcessedClusterStateUpdateTask() { - @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(String feature, TimeValue expiryDuration) throws Exception { - License license1 = generateSignedLicense(feature, expiryDuration); - final PutLicenseResponse putLicenseResponse = new PutLicenseRequestBuilder(client().admin().cluster(), PutLicenseAction.INSTANCE).setLicense(Lists.newArrayList(license1)).get(); - assertThat(putLicenseResponse.isAcknowledged(), equalTo(true)); - assertThat(putLicenseResponse.status(), equalTo(LicensesStatus.VALID)); - } - - - protected void assertLicenseManagerEnabledFeatureFor(final String feature) throws InterruptedException { - assertLicenseManagerStatusFor(feature, true); - } - - protected void assertLicenseManagerDisabledFeatureFor(final String feature) throws InterruptedException { - assertLicenseManagerStatusFor(feature, false); - } - - protected void assertLicenseManagerStatusFor(final String feature, final boolean expectedEnabled) throws InterruptedException { - assertThat("LicensesManagerService for feature " + feature + " should have enabled status of " + expectedEnabled, awaitBusy(new Predicate() { - @Override - public boolean apply(Object o) { - for (LicensesManagerService managerService : licensesManagerServices()) { - if (expectedEnabled != managerService.enabledFeatures().contains(feature)) { - return false; - } - } - return true; - } - }, 5, TimeUnit.SECONDS), equalTo(true)); - } - - protected void assertEagerConsumerPluginDisableNotification(int timeoutInSec) throws InterruptedException { - assertEagerConsumerPluginNotification(false, timeoutInSec); - } - - protected void assertEagerConsumerPluginEnableNotification(int timeoutInSec) throws InterruptedException { - assertEagerConsumerPluginNotification(true, timeoutInSec); - } - - protected void assertLazyConsumerPluginDisableNotification(int timeoutInSec) throws InterruptedException { - assertLazyConsumerPluginNotification(false, timeoutInSec); - } - - protected void assertLazyConsumerPluginEnableNotification(int timeoutInSec) throws InterruptedException { - assertLazyConsumerPluginNotification(true, timeoutInSec); - } - - protected void assertLazyConsumerPluginNotification(final boolean expectedEnabled, int timeoutInSec) throws InterruptedException { - final List consumerPluginServices = consumerLazyPluginServices(); - assertConsumerPluginNotification(consumerPluginServices, expectedEnabled, timeoutInSec); - } - - protected void assertEagerConsumerPluginNotification(final boolean expectedEnabled, int timeoutInSec) throws InterruptedException { - final List consumerPluginServices = consumerEagerPluginServices(); - assertConsumerPluginNotification(consumerPluginServices, expectedEnabled, timeoutInSec); - } - - protected void assertConsumerPluginNotification(final List consumerPluginServices, final boolean expectedEnabled, int timeoutInSec) throws InterruptedException { - assertThat("At least one instance has to be present", consumerPluginServices.size(), greaterThan(0)); - assertConsumerPluginNotification(consumerPluginServices.get(0).getClass().getName() + " should have license status of: " + expectedEnabled, consumerPluginServices, expectedEnabled, timeoutInSec); - } - - private void assertConsumerPluginNotification(String msg, final Iterable consumerPluginServices, final boolean expectedEnabled, int timeoutInSec) throws InterruptedException { - boolean success = awaitBusy(new Predicate() { - @Override - public boolean apply(Object o) { - for (TestPluginServiceBase pluginService : consumerPluginServices) { - if (expectedEnabled != pluginService.enabled()) { - return false; - } - } - return true; - } - }, timeoutInSec + 1, TimeUnit.SECONDS); - logger.debug("Notification assertion complete"); - assertThat(msg, 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; - } - - private Iterable licensesManagerServices() { - final InternalTestCluster clients = internalCluster(); - return clients.getDataNodeInstances(LicensesManagerService.class); - } -} diff --git a/plugin/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesServiceTests.java b/plugin/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesServiceTests.java deleted file mode 100644 index 782d9cf5040..00000000000 --- a/plugin/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesServiceTests.java +++ /dev/null @@ -1,195 +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.license.plugin; - -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.cluster.ClusterChangedEvent; -import org.elasticsearch.cluster.ClusterService; -import org.elasticsearch.cluster.node.DiscoveryNode; -import org.elasticsearch.cluster.node.DiscoveryNodes; -import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.license.core.License; -import org.elasticsearch.license.plugin.action.put.PutLicenseRequest; -import org.elasticsearch.license.plugin.core.LicensesClientService; -import org.elasticsearch.license.plugin.core.LicensesManagerService; -import org.elasticsearch.license.plugin.core.LicensesService; -import org.elasticsearch.license.plugin.core.LicensesStatus; -import org.elasticsearch.test.InternalTestCluster; -import org.junit.Before; - -import java.util.*; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; - -import static org.elasticsearch.license.plugin.core.LicensesService.LicensesUpdateResponse; -import static org.hamcrest.Matchers.equalTo; - -public abstract class AbstractLicensesServiceTests extends AbstractLicensesIntegrationTests { - - private static String node = null; - private static String[] nodes; - - @Before - public void beforeTest() throws Exception { - wipeAllLicenses(); - - DiscoveryNodes discoveryNodes = masterClusterService().state().getNodes(); - Set dataNodeSet = new HashSet<>(); - for (DiscoveryNode discoveryNode : discoveryNodes) { - if (discoveryNode.dataNode()) { - dataNodeSet.add(discoveryNode.getName()); - } - } - nodes = dataNodeSet.toArray(new String[dataNodeSet.size()]); - node = nodes[randomIntBetween(0, nodes.length - 1)]; - } - - protected void registerAndAckSignedLicenses(final LicensesManagerService masterLicensesManagerService, final List license, final LicensesStatus expectedStatus) { - PutLicenseRequest putLicenseRequest = new PutLicenseRequest().licenses(license); - LicensesService.PutLicenseRequestHolder requestHolder = new LicensesService.PutLicenseRequestHolder(putLicenseRequest, "test"); - final CountDownLatch latch = new CountDownLatch(1); - final AtomicBoolean success = new AtomicBoolean(false); - masterLicensesManagerService.registerLicenses(requestHolder, new ActionListener() { - @Override - public void onResponse(LicensesUpdateResponse licensesUpdateResponse) { - if (licensesUpdateResponse.isAcknowledged() && licensesUpdateResponse.status() == expectedStatus) { - success.set(true); - } - latch.countDown(); - } - - @Override - public void onFailure(Throwable e) { - latch.countDown(); - } - }); - try { - latch.await(); - } catch (InterruptedException e) { - fail(e.getMessage()); - } - assertThat("register license(s) failed", success.get(), equalTo(true)); - } - - protected Action registerWithTrialLicense(final LicensesClientService clientService, final LicensesClientService.Listener clientListener, final String feature, final TimeValue expiryDuration) { - return new Action(new Runnable() { - @Override - public void run() { - clientService.register(feature, new LicensesService.TrialLicenseOptions(expiryDuration, 10), Collections.emptyList(), - clientListener); - - // invoke clusterChanged event to flush out pendingRegistration - LicensesService licensesService = (LicensesService) clientService; - ClusterChangedEvent event = new ClusterChangedEvent("", clusterService().state(), clusterService().state()); - licensesService.clusterChanged(event); - } - }, 0, 1, "should trigger onEnable for " + feature + " once [trial license]"); - } - - protected Action registerWithEventNotification(final LicensesClientService clientService, final LicensesClientService.Listener clientListener, final String feature, final TimeValue expiryDuration, final Collection expirationCallbacks) { - return new Action(new Runnable() { - @Override - public void run() { - clientService.register(feature, new LicensesService.TrialLicenseOptions(expiryDuration, 10), expirationCallbacks, - clientListener); - - // invoke clusterChanged event to flush out pendingRegistration - LicensesService licensesService = (LicensesService) clientService; - ClusterChangedEvent event = new ClusterChangedEvent("", clusterService().state(), clusterService().state()); - licensesService.clusterChanged(event); - } - }, 0, 1, "should trigger onEnable for " + feature + " once [trial license]"); - } - - protected class TestTrackingClientListener implements LicensesClientService.Listener { - CountDownLatch enableLatch; - CountDownLatch disableLatch; - AtomicBoolean enabled = new AtomicBoolean(false); - - final boolean track; - final String featureName; - - public TestTrackingClientListener(String featureName) { - this(featureName, true); - } - - public TestTrackingClientListener(String featureName, boolean track) { - this.track = track; - this.featureName = featureName; - } - - public synchronized void latch(CountDownLatch enableLatch, CountDownLatch disableLatch) { - this.enableLatch = enableLatch; - this.disableLatch = disableLatch; - } - - @Override - public void onEnabled(License license) { - assertNotNull(license); - assertThat(license.feature(), equalTo(featureName)); - enabled.set(true); - if (track) { - this.enableLatch.countDown(); - } - } - - @Override - public void onDisabled(License license) { - assertNotNull(license); - assertThat(license.feature(), equalTo(featureName)); - enabled.set(false); - if (track) { - this.disableLatch.countDown(); - } - } - } - - protected class Action { - final int expectedDisabledCount; - final int expectedEnabledCount; - final TimeValue timeout; - final Runnable action; - final String msg; - - protected Action(Runnable action, int expectedEnabledCount, int expectedDisabledCount, String msg) { - this(action, expectedEnabledCount, expectedDisabledCount, TimeValue.timeValueSeconds(1), msg); - } - - protected Action(Runnable action, int expectedDisabledCount, int expectedEnabledCount, TimeValue timeout, String msg) { - this.expectedDisabledCount = expectedDisabledCount; - this.expectedEnabledCount = expectedEnabledCount; - this.action = action; - this.timeout = timeout; - this.msg = msg; - } - - public void run() { - action.run(); - } - } - - - protected LicensesManagerService masterLicensesManagerService() { - final InternalTestCluster clients = internalCluster(); - return clients.getInstance(LicensesManagerService.class, clients.getMasterName()); - } - - protected LicensesClientService licensesClientService() { - final InternalTestCluster clients = internalCluster(); - return internalCluster().getInstance(LicensesClientService.class, clients.getMasterName()); - } - - protected LicensesService licensesService() { - final InternalTestCluster clients = internalCluster(); - return internalCluster().getInstance(LicensesService.class, clients.getMasterName()); - } - - protected static ClusterService masterClusterService() { - final InternalTestCluster clients = internalCluster(); - return clients.getInstance(ClusterService.class, clients.getMasterName()); - } -} diff --git a/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesClientServiceTests.java b/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesClientServiceTests.java deleted file mode 100644 index 950dc4ca779..00000000000 --- a/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesClientServiceTests.java +++ /dev/null @@ -1,467 +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.license.plugin; - -import com.google.common.base.Predicate; -import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.license.core.License; -import org.elasticsearch.license.plugin.core.*; -import org.junit.Test; - -import java.util.*; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; - -import static org.elasticsearch.license.plugin.TestUtils.generateSignedLicense; -import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope; -import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope.TEST; -import static org.hamcrest.Matchers.*; - -@ClusterScope(scope = TEST, numDataNodes = 1) -public class LicensesClientServiceTests extends AbstractLicensesServiceTests { - - @Test - public void testTrialLicenseEnforcement() throws Exception { - // register with trial license and assert onEnable and onDisable notification - - final LicensesClientService clientService = licensesClientService(); - String feature1 = "feature1"; - final TestTrackingClientListener clientListener = new TestTrackingClientListener(feature1); - List actions = new ArrayList<>(); - - final TimeValue expiryDuration = TimeValue.timeValueSeconds(2); - actions.add(registerWithTrialLicense(clientService, clientListener, feature1, expiryDuration)); - actions.add(assertExpiryAction(feature1, "trial", expiryDuration)); - assertClientListenerNotificationCount(clientListener, actions); - } - - @Test - public void testLicenseWithFutureIssueDate() throws Exception { - final LicensesClientService clientService = licensesClientService(); - String feature = "feature"; - final TestTrackingClientListener clientListener = new TestTrackingClientListener(feature); - List actions = new ArrayList<>(); - long now = System.currentTimeMillis(); - long issueDate = dateMath("now+10d/d", now); - - actions.add(registerWithoutTrialLicense(clientService, clientListener, feature)); - actions.add(generateAndPutSignedLicenseAction(masterLicensesManagerService(), feature, issueDate, TimeValue.timeValueHours(24 * 20))); - actions.add(assertExpiryAction(feature, "signed", TimeValue.timeValueSeconds(4))); - assertClientListenerNotificationCount(clientListener, actions); - assertThat(clientListener.enabled.get(), equalTo(false)); - } - - @Test - 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, LicensesService.ExpirationStatus status) { - } - }; - long now = System.currentTimeMillis(); - assertThat(post.matches(now - postExpiryDuration.millis(), now), equalTo(true)); - assertThat(post.matches(now + postExpiryDuration.getMillis(), now), equalTo(false)); - } - - @Test - 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, LicensesService.ExpirationStatus status) { - } - }; - long now = System.currentTimeMillis(); - assertThat(post.matches(now - postExpiryDuration.millis(), now), equalTo(true)); - } - - @Test - 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, LicensesService.ExpirationStatus status) { - } - }; - long now = System.currentTimeMillis(); - assertThat(pre.matches(expiryDuration.millis() + now, now), equalTo(true)); - } - - @Test - 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, LicensesService.ExpirationStatus status) { - } - }; - long now = System.currentTimeMillis(); - assertThat(pre.matches(expiryDuration.millis() + now, now), equalTo(true)); - assertThat(pre.matches(now - expiryDuration.getMillis(), now), equalTo(false)); - } - - @Test - public void testMultipleEventNotification() throws Exception { - final LicensesManagerService licensesManagerService = masterLicensesManagerService(); - final LicensesClientService clientService = licensesClientService(); - final String feature = "feature"; - TestTrackingClientListener clientListener = new TestTrackingClientListener(feature, true); - - List callbacks = new ArrayList<>(); - final AtomicInteger preTriggerCountStartingFromOneSecond = new AtomicInteger(0); - callbacks.add(preCallbackLatch(TimeValue.timeValueMillis(499), TimeValue.timeValueMillis(999), TimeValue.timeValueMillis(100), preTriggerCountStartingFromOneSecond)); - final AtomicInteger postTriggerCount = new AtomicInteger(0); - callbacks.add(postCallbackLatch(TimeValue.timeValueMillis(10), null, TimeValue.timeValueMillis(200), postTriggerCount)); - final AtomicInteger preTriggerCountStartingFromTwoSeconds = new AtomicInteger(0); - callbacks.add(preCallbackLatch(TimeValue.timeValueSeconds(1), TimeValue.timeValueSeconds(2), TimeValue.timeValueMillis(500), preTriggerCountStartingFromTwoSeconds)); - - List actions = new ArrayList<>(); - actions.add(registerWithEventNotification(clientService, clientListener, feature, TimeValue.timeValueSeconds(3), callbacks)); - actions.add(assertExpiryAction(feature, "trial", TimeValue.timeValueMinutes(1))); - assertClientListenerNotificationCount(clientListener, actions); - assertThat(preTriggerCountStartingFromTwoSeconds.get(), greaterThanOrEqualTo(2)); - assertThat(preTriggerCountStartingFromTwoSeconds.get(), lessThan(4)); - assertThat(preTriggerCountStartingFromOneSecond.get(), greaterThan(4)); - int initialPreTriggerStartingFromTwoSeconds = preTriggerCountStartingFromTwoSeconds.get(); - int initialPreTriggerCountStartingFromOneSecond = preTriggerCountStartingFromOneSecond.get(); - assertThat(awaitBusy(new Predicate() { - @Override - public boolean apply(Object o) { - if (postTriggerCount.get() > 2) { - return true; - } - return false; - } - }, 2, TimeUnit.SECONDS), equalTo(true)); - int previousTriggerCount = postTriggerCount.get(); - - // Update license - generateAndPutSignedLicenseAction(licensesManagerService, feature, TimeValue.timeValueSeconds(10)).run(); - assertThat(previousTriggerCount, lessThanOrEqualTo(postTriggerCount.get() + 1)); - assertThat(initialPreTriggerCountStartingFromOneSecond, equalTo(preTriggerCountStartingFromOneSecond.get())); - assertThat(initialPreTriggerStartingFromTwoSeconds, equalTo(preTriggerCountStartingFromTwoSeconds.get())); - } - - @Test - public void testPreEventNotification() throws Exception { - final LicensesClientService clientService = licensesClientService(); - final String feature = "feature"; - TestTrackingClientListener clientListener = new TestTrackingClientListener(feature, true); - AtomicInteger counter = new AtomicInteger(0); - List actions = new ArrayList<>(); - actions.add( - registerWithEventNotification(clientService, clientListener, feature, TimeValue.timeValueSeconds(3), - Arrays.asList( - preCallbackLatch(TimeValue.timeValueMillis(500), TimeValue.timeValueSeconds(2), TimeValue.timeValueMillis(500), counter) - )) - ); - actions.add(assertExpiryAction(feature, "trial", TimeValue.timeValueSeconds(3))); - assertClientListenerNotificationCount(clientListener, actions); - assertThat(counter.get(), greaterThanOrEqualTo(3)); - assertThat(counter.get(), lessThan(5)); - } - - @Test - public void testPostEventNotification() throws Exception { - final LicensesClientService clientService = licensesClientService(); - final String feature = "feature"; - TestTrackingClientListener clientListener = new TestTrackingClientListener(feature, true); - AtomicInteger counter = new AtomicInteger(0); - List actions = new ArrayList<>(); - actions.add( - registerWithEventNotification(clientService, clientListener, feature, TimeValue.timeValueSeconds(1), - Arrays.asList( - postCallbackLatch(TimeValue.timeValueMillis(500), TimeValue.timeValueSeconds(2), TimeValue.timeValueMillis(500), counter) - )) - ); - actions.add(assertExpiryAction(feature, "trial", TimeValue.timeValueSeconds(1))); - assertClientListenerNotificationCount(clientListener, actions); - Thread.sleep(50 + 2000); - assertThat(counter.get(), greaterThanOrEqualTo(3)); - assertThat(counter.get(), lessThan(5)); - } - - private LicensesService.ExpirationCallback preCallbackLatch(TimeValue min, TimeValue max, TimeValue frequency, final AtomicInteger triggerCount) { - return new LicensesService.ExpirationCallback.Pre(min, max, frequency) { - @Override - public void on(License license, LicensesService.ExpirationStatus status) { - triggerCount.incrementAndGet(); - } - }; - } - - private LicensesService.ExpirationCallback postCallbackLatch(TimeValue min, TimeValue max, TimeValue frequency, final AtomicInteger triggerCount) { - return new LicensesService.ExpirationCallback.Post(min, max, frequency) { - @Override - public void on(License license, LicensesService.ExpirationStatus status) { - triggerCount.incrementAndGet(); - } - }; - } - - - @Test - public void testMultipleClientSignedLicenseEnforcement() throws Exception { - // multiple client registration with null trial license and then different expiry signed license - - final LicensesManagerService masterLicensesManagerService = masterLicensesManagerService(); - final LicensesService licensesService = licensesService(); - String feature1 = "feature1"; - String feature2 = "feature2"; - final TestTrackingClientListener clientListener1 = new TestTrackingClientListener(feature1); - final TestTrackingClientListener clientListener2 = new TestTrackingClientListener(feature2); - List firstClientActions = new ArrayList<>(); - List secondClientActions = new ArrayList<>(); - - final TimeValue firstExpiryDuration = TimeValue.timeValueSeconds(5); - firstClientActions.add(registerWithoutTrialLicense(licensesService, clientListener1, feature1)); - firstClientActions.add(generateAndPutSignedLicenseAction(masterLicensesManagerService, feature1, firstExpiryDuration)); - firstClientActions.add(assertExpiryAction(feature1, "signed", firstExpiryDuration)); - - final TimeValue secondExpiryDuration = TimeValue.timeValueSeconds(4); - secondClientActions.add(registerWithoutTrialLicense(licensesService, clientListener2, feature2)); - secondClientActions.add(generateAndPutSignedLicenseAction(masterLicensesManagerService, feature2, secondExpiryDuration)); - secondClientActions.add(assertExpiryAction(feature2, "signed", secondExpiryDuration)); - - if (randomBoolean()) { - assertClientListenerNotificationCount(clientListener1, firstClientActions); - assertClientListenerNotificationCount(clientListener2, secondClientActions); - } else { - assertClientListenerNotificationCount(clientListener2, secondClientActions); - assertClientListenerNotificationCount(clientListener1, firstClientActions); - } - } - - @Test - public void testMultipleClientTrialAndSignedLicenseEnforcement() throws Exception { - // multiple client registration: one with trial license and another with signed license (different expiry duration) - - final LicensesManagerService masterLicensesManagerService = masterLicensesManagerService(); - final LicensesService licensesService = licensesService(); - String feature1 = "feature1"; - String feature2 = "feature2"; - final TestTrackingClientListener clientListener1 = new TestTrackingClientListener(feature1); - final TestTrackingClientListener clientListener2 = new TestTrackingClientListener(feature2); - List firstClientActions = new ArrayList<>(); - List secondClientActions = new ArrayList<>(); - - final TimeValue firstExpiryDuration = TimeValue.timeValueSeconds(5); - firstClientActions.add(registerWithoutTrialLicense(licensesService, clientListener1, feature1)); - firstClientActions.add(generateAndPutSignedLicenseAction(masterLicensesManagerService, feature1, firstExpiryDuration)); - firstClientActions.add(assertExpiryAction(feature1, "signed", firstExpiryDuration)); - - final TimeValue secondExpiryDuration = TimeValue.timeValueSeconds(4); - secondClientActions.add(registerWithTrialLicense(licensesService, clientListener2, feature2, secondExpiryDuration)); - secondClientActions.add(assertExpiryAction(feature2, "trial", secondExpiryDuration)); - - if (randomBoolean()) { - assertClientListenerNotificationCount(clientListener1, firstClientActions); - assertClientListenerNotificationCount(clientListener2, secondClientActions); - } else { - assertClientListenerNotificationCount(clientListener2, secondClientActions); - assertClientListenerNotificationCount(clientListener1, firstClientActions); - } - } - - @Test - public void testMultipleClientTrialLicenseRegistration() throws Exception { - // multiple client registration: both with trail license of different expiryDuration - - final LicensesService licensesService = licensesService(); - String feature1 = "feature1"; - String feature2 = "feature2"; - final TestTrackingClientListener clientListener1 = new TestTrackingClientListener(feature1); - final TestTrackingClientListener clientListener2 = new TestTrackingClientListener(feature2); - List firstClientActions = new ArrayList<>(); - List secondClientActions = new ArrayList<>(); - - TimeValue firstExpiryDuration = TimeValue.timeValueSeconds(5); - firstClientActions.add(registerWithTrialLicense(licensesService, clientListener1, feature1, firstExpiryDuration)); - firstClientActions.add(assertExpiryAction(feature1, "trial", firstExpiryDuration)); - - TimeValue secondExpiryDuration = TimeValue.timeValueSeconds(4); - secondClientActions.add(registerWithTrialLicense(licensesService, clientListener2, feature2, secondExpiryDuration)); - secondClientActions.add(assertExpiryAction(feature2, "trial", secondExpiryDuration)); - - if (randomBoolean()) { - assertClientListenerNotificationCount(clientListener1, firstClientActions); - assertClientListenerNotificationCount(clientListener2, secondClientActions); - } else { - assertClientListenerNotificationCount(clientListener2, secondClientActions); - assertClientListenerNotificationCount(clientListener1, firstClientActions); - } - } - - @Test - public void testFeatureWithoutLicense() throws Exception { - // client registration with no trial license + no signed license - final LicensesClientService clientService = licensesClientService(); - String feature = "feature1"; - final TestTrackingClientListener clientListener = new TestTrackingClientListener(feature); - List actions = new ArrayList<>(); - - actions.add(registerWithoutTrialLicense(clientService, clientListener, feature)); - assertClientListenerNotificationCount(clientListener, actions); - } - - @Test - public void testLicenseExpiry() throws Exception { - final LicensesClientService clientService = licensesClientService(); - String feature = "feature1"; - final TestTrackingClientListener clientListener = new TestTrackingClientListener(feature); - List actions = new ArrayList<>(); - - TimeValue expiryDuration = TimeValue.timeValueSeconds(2); - actions.add(registerWithTrialLicense(clientService, clientListener, feature, expiryDuration)); - actions.add(assertExpiryAction(feature, "trial", expiryDuration)); - - assertClientListenerNotificationCount(clientListener, actions); - } - - @Test - public void testRandomActionSequenceMultipleFeature() throws Exception { - LicensesService licensesService = licensesService(); - LicensesManagerService masterLicensesManagerService = masterLicensesManagerService(); - Map> clientListenersWithActions = new HashMap<>(); - - TimeValue expiryDuration = TimeValue.timeValueSeconds(0); - for (int i = 0; i < randomIntBetween(5, 10); i++) { - String feature = "feature_" + String.valueOf(i); - final TestTrackingClientListener clientListener = new TestTrackingClientListener(feature); - expiryDuration = TimeValue.timeValueMillis(randomIntBetween(2, 4) * 1000l + expiryDuration.millis()); - List actions = new ArrayList<>(); - - if (randomBoolean()) { - actions.add(registerWithTrialLicense(licensesService, clientListener, feature, expiryDuration)); - actions.add(assertExpiryAction(feature, "trial", expiryDuration)); - } else { - actions.add(registerWithoutTrialLicense(licensesService, clientListener, feature)); - actions.add(generateAndPutSignedLicenseAction(masterLicensesManagerService, feature, expiryDuration)); - actions.add(assertExpiryAction(feature, "signed", expiryDuration)); - } - clientListenersWithActions.put(clientListener, actions); - } - - for (Map.Entry> entry : clientListenersWithActions.entrySet()) { - assertClientListenerNotificationCount(entry.getKey(), entry.getValue()); - } - - } - - private Action generateAndPutSignedLicenseAction(final LicensesManagerService masterLicensesManagerService, final String feature, final TimeValue expiryDuration) throws Exception { - return generateAndPutSignedLicenseAction(masterLicensesManagerService, feature, -1, expiryDuration); - } - private Action generateAndPutSignedLicenseAction(final LicensesManagerService masterLicensesManagerService, final String feature, final long issueDate, final TimeValue expiryDuration) throws Exception { - return new Action(new Runnable() { - @Override - public void run() { - License license; - try { - license = generateSignedLicense(feature, issueDate, expiryDuration); - } catch (Exception e) { - fail(e.getMessage()); - return; - } - registerAndAckSignedLicenses(masterLicensesManagerService, Arrays.asList(license), LicensesStatus.VALID); - } - }, 0, (issueDate <= System.currentTimeMillis()) ? 1 : 0, "should trigger onEnable for " + feature + " once [signed license]"); - } - - private Action registerWithoutTrialLicense(final LicensesClientService clientService, final LicensesClientService.Listener clientListener, final String feature) { - return new Action(new Runnable() { - @Override - public void run() { - clientService.register(feature, null, Collections.emptyList(), clientListener); - } - }, 0, 0, "should not trigger any notification [disabled by default]"); - } - - private Action assertExpiryAction(String feature, String licenseType, TimeValue expiryDuration) { - return new Action(new Runnable() { - @Override - public void run() { - } - }, 1, 0, TimeValue.timeValueMillis(expiryDuration.getMillis() * 2), - "should trigger onDisable for " + feature + " once [" + licenseType + " license expiry]"); - } - - private void assertClientListenerNotificationCount(final TestTrackingClientListener clientListener, List actions) throws Exception { - final AtomicInteger expectedEnabledCount = new AtomicInteger(0); - final AtomicInteger expectedDisableCount = new AtomicInteger(0); - - for (final Action action : actions) { - expectedEnabledCount.addAndGet(action.expectedEnabledCount); - expectedDisableCount.addAndGet(action.expectedDisabledCount); - } - - final CountDownLatch enableLatch = new CountDownLatch(expectedEnabledCount.get()); - final CountDownLatch disableLatch = new CountDownLatch(expectedDisableCount.get()); - final AtomicLong cumulativeTimeoutMillis = new AtomicLong(0); - clientListener.latch(enableLatch, disableLatch); - for (final Action action : actions) { - action.run(); - cumulativeTimeoutMillis.addAndGet(action.timeout.getMillis()); - } - - if (expectedDisableCount.get() > 0) { - assertThat(getActionMsg(true, enableLatch.getCount(), actions), enableLatch.await((cumulativeTimeoutMillis.get() * 2), TimeUnit.MILLISECONDS), equalTo(true)); - } - if (expectedDisableCount.get() > 0) { - assertThat(getActionMsg(false, disableLatch.getCount(), actions), disableLatch.await((cumulativeTimeoutMillis.get() * 2), TimeUnit.MILLISECONDS), equalTo(true)); - } - } - - private static String getActionMsg(final boolean enabledCount, final long latchCount, final List actions) { - LicensesMetaData licensesMetaData = masterClusterService().state().metaData().custom(LicensesMetaData.TYPE); - Set featureLicenses = new HashSet<>(); - if (licensesMetaData != null) { - for (License license : licensesMetaData.getSignedLicenses()) { - featureLicenses.add(license.feature()); - } - for (License license : licensesMetaData.getTrialLicenses()) { - featureLicenses.add(license.feature()); - } - } - - StringBuilder featureLicensesString = new StringBuilder(); - for (String featureLicense : featureLicenses) { - if (featureLicensesString.length() != 0) { - featureLicensesString.append(", "); - } - featureLicensesString.append(featureLicense); - } - - AtomicLong cumulativeCount = new AtomicLong(0); - for (Action action : actions) { - cumulativeCount.addAndGet((enabledCount) ? action.expectedEnabledCount : action.expectedDisabledCount); - if (latchCount <= cumulativeCount.get()) { - return action.msg + "\n Current licenses in cluster state: [" + featureLicensesString.toString() + "]"; - } - } - return "there should be no errors"; - } -} diff --git a/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesEagerConsumerPluginIntegrationTests.java b/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesEagerConsumerPluginIntegrationTests.java deleted file mode 100644 index c00a91eea1c..00000000000 --- a/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesEagerConsumerPluginIntegrationTests.java +++ /dev/null @@ -1,16 +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.license.plugin; - -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.license.plugin.consumer.EagerLicenseRegistrationConsumerPlugin; - -public class LicensesEagerConsumerPluginIntegrationTests extends AbstractLicensesConsumerPluginIntegrationTests { - - public LicensesEagerConsumerPluginIntegrationTests() { - super(new EagerLicenseRegistrationConsumerPlugin(Settings.EMPTY)); - } -} diff --git a/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesLazyConsumerPluginIntegrationTests.java b/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesLazyConsumerPluginIntegrationTests.java deleted file mode 100644 index 984763dea0a..00000000000 --- a/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesLazyConsumerPluginIntegrationTests.java +++ /dev/null @@ -1,16 +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.license.plugin; - -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.license.plugin.consumer.LazyLicenseRegistrationConsumerPlugin; - -public class LicensesLazyConsumerPluginIntegrationTests extends AbstractLicensesConsumerPluginIntegrationTests { - - public LicensesLazyConsumerPluginIntegrationTests() { - super(new LazyLicenseRegistrationConsumerPlugin(Settings.EMPTY)); - } -} diff --git a/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesManagerServiceTests.java b/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesManagerServiceTests.java deleted file mode 100644 index 958a3264225..00000000000 --- a/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesManagerServiceTests.java +++ /dev/null @@ -1,135 +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.license.plugin; - -import com.google.common.collect.Sets; -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse; -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.core.*; -import org.junit.Test; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.atomic.AtomicBoolean; - -import static org.elasticsearch.license.plugin.TestUtils.generateSignedLicense; -import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope; -import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope.TEST; -import static org.hamcrest.Matchers.equalTo; - -@ClusterScope(scope = TEST, numDataNodes = 10) -public class LicensesManagerServiceTests extends AbstractLicensesServiceTests { - - @Test - public void testStoreAndGetLicenses() throws Exception { - LicensesManagerService licensesManagerService = masterLicensesManagerService(); - License shieldShortLicense = generateSignedLicense("shield", TimeValue.timeValueHours(1)); - License shieldLongLicense = generateSignedLicense("shield", TimeValue.timeValueHours(2)); - License marvelShortLicense = generateSignedLicense("marvel", TimeValue.timeValueHours(1)); - License marvelLongLicense = generateSignedLicense("marvel", TimeValue.timeValueHours(2)); - - List licenses = Arrays.asList(shieldLongLicense, shieldShortLicense, marvelLongLicense, marvelShortLicense); - Collections.shuffle(licenses); - registerAndAckSignedLicenses(licensesManagerService, licenses, LicensesStatus.VALID); - - LicensesMetaData licensesMetaData = clusterService().state().metaData().custom(LicensesMetaData.TYPE); - - // all licenses should be stored in the metaData - TestUtils.isSame(licenses, licensesMetaData.getSignedLicenses()); - - // only the latest expiry date license for each feature should be returned by getLicenses() - final List getLicenses = licensesManagerService.getLicenses(); - TestUtils.isSame(getLicenses, Arrays.asList(shieldLongLicense, marvelLongLicense)); - } - - @Test - public void testInvalidLicenseStorage() throws Exception { - LicensesManagerService licensesManagerService = masterLicensesManagerService(); - License signedLicense = generateSignedLicense("shield", 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(); - - registerAndAckSignedLicenses(licensesManagerService, Arrays.asList(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.getSignedLicenses().size(), equalTo(0)); - } - } - - @Test - public void testRemoveLicenses() throws Exception { - LicensesManagerService licensesManagerService = masterLicensesManagerService(); - - // generate a trial license for one feature - final LicensesClientService clientService = licensesClientService(); - final TestTrackingClientListener clientListener = new TestTrackingClientListener("shield", false); - registerWithTrialLicense(clientService, clientListener, "shield", TimeValue.timeValueHours(1)).run(); - - // generate signed licenses for multiple features - License shieldShortLicense = generateSignedLicense("shield", TimeValue.timeValueHours(1)); - License shieldLongLicense = generateSignedLicense("shield", TimeValue.timeValueHours(2)); - License marvelShortLicense = generateSignedLicense("marvel", TimeValue.timeValueHours(1)); - License marvelLongLicense = generateSignedLicense("marvel", TimeValue.timeValueHours(2)); - - List licenses = Arrays.asList(shieldLongLicense, shieldShortLicense, marvelLongLicense, marvelShortLicense); - Collections.shuffle(licenses); - registerAndAckSignedLicenses(licensesManagerService, licenses, LicensesStatus.VALID); - - // remove license(s) for one feature out of two - removeAndAckSignedLicenses(licensesManagerService, Sets.newHashSet("shield")); - LicensesMetaData licensesMetaData = clusterService().state().metaData().custom(LicensesMetaData.TYPE); - TestUtils.isSame(Arrays.asList(marvelLongLicense, marvelShortLicense), licensesMetaData.getSignedLicenses()); - // check that trial license is not removed - assertThat(licensesMetaData.getTrialLicenses().size(), equalTo(1)); - - // remove license(s) for all features - removeAndAckSignedLicenses(licensesManagerService, Sets.newHashSet("shield", "marvel")); - licensesMetaData = clusterService().state().metaData().custom(LicensesMetaData.TYPE); - assertThat(licensesMetaData.getSignedLicenses().size(), equalTo(0)); - // check that trial license is not removed - assertThat(licensesMetaData.getTrialLicenses().size(), equalTo(1)); - } - - private void removeAndAckSignedLicenses(final LicensesManagerService masterLicensesManagerService, final Set featuresToDelete) { - DeleteLicenseRequest deleteLicenseRequest = new DeleteLicenseRequest(featuresToDelete.toArray(new String[featuresToDelete.size()])); - LicensesService.DeleteLicenseRequestHolder requestHolder = new LicensesService.DeleteLicenseRequestHolder(deleteLicenseRequest, "test"); - final CountDownLatch latch = new CountDownLatch(1); - final AtomicBoolean success = new AtomicBoolean(false); - masterLicensesManagerService.removeLicenses(requestHolder, 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/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesMetaDataSerializationTests.java b/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesMetaDataSerializationTests.java deleted file mode 100644 index c72ba2cc100..00000000000 --- a/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesMetaDataSerializationTests.java +++ /dev/null @@ -1,152 +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.license.plugin; - -import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.common.xcontent.*; -import org.elasticsearch.license.core.License; -import org.elasticsearch.license.plugin.core.LicensesMetaData; -import org.elasticsearch.license.plugin.core.TrialLicenseUtils; -import org.elasticsearch.test.ElasticsearchTestCase; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.nullValue; - -public class LicensesMetaDataSerializationTests extends ElasticsearchTestCase { - - @Test - public void testXContentSerializationOneSignedLicense() throws Exception { - License license = TestUtils.generateSignedLicense("feature", TimeValue.timeValueHours(2)); - LicensesMetaData licensesMetaData = new LicensesMetaData(Arrays.asList(license), new ArrayList()); - XContentBuilder builder = XContentFactory.jsonBuilder(); - builder.startObject("licensesMetaData"); - licensesMetaData.toXContent(builder, ToXContent.EMPTY_PARAMS); - builder.endObject(); - byte[] serializedBytes = builder.bytes().toBytes(); - - LicensesMetaData licensesMetaDataFromXContent = getLicensesMetaDataFromXContent(serializedBytes); - - assertThat(licensesMetaDataFromXContent.getSignedLicenses().size(), equalTo(1)); - TestUtils.isSame(licensesMetaDataFromXContent.getSignedLicenses().get(0), license); - assertThat(licensesMetaDataFromXContent.getTrialLicenses().size(), equalTo(0)); - } - - @Test - public void testXContentSerializationManySignedLicense() throws Exception { - List licenses = new ArrayList<>(); - int n = randomIntBetween(2, 5); - for (int i = 0; i < n; i++) { - licenses.add(TestUtils.generateSignedLicense("feature__" + String.valueOf(i), TimeValue.timeValueHours(2))); - } - LicensesMetaData licensesMetaData = new LicensesMetaData(licenses, new ArrayList()); - XContentBuilder builder = XContentFactory.jsonBuilder(); - builder.startObject("licensesMetaData"); - licensesMetaData.toXContent(builder, ToXContent.EMPTY_PARAMS); - builder.endObject(); - byte[] serializedBytes = builder.bytes().toBytes(); - - LicensesMetaData licensesMetaDataFromXContent = getLicensesMetaDataFromXContent(serializedBytes); - - assertThat(licensesMetaDataFromXContent.getSignedLicenses().size(), equalTo(n)); - TestUtils.isSame(licensesMetaDataFromXContent.getSignedLicenses(), licenses); - assertThat(licensesMetaDataFromXContent.getTrialLicenses().size(), equalTo(0)); - } - - @Test - public void testXContentSerializationOneTrial() throws Exception { - final License trialLicense = TrialLicenseUtils.builder() - .feature("feature") - .duration(TimeValue.timeValueHours(2)) - .maxNodes(5) - .issuedTo("customer") - .issueDate(System.currentTimeMillis()) - .build(); - LicensesMetaData licensesMetaData = new LicensesMetaData(new ArrayList(), Arrays.asList(trialLicense)); - XContentBuilder builder = XContentFactory.jsonBuilder(); - builder.startObject("licensesMetaData"); - licensesMetaData.toXContent(builder, ToXContent.EMPTY_PARAMS); - builder.endObject(); - byte[] serializedBytes = builder.bytes().toBytes(); - - LicensesMetaData licensesMetaDataFromXContent = getLicensesMetaDataFromXContent(serializedBytes); - - assertThat(licensesMetaDataFromXContent.getTrialLicenses().size(), equalTo(1)); - TestUtils.isSame(licensesMetaDataFromXContent.getTrialLicenses().iterator().next(), trialLicense); - assertThat(licensesMetaDataFromXContent.getSignedLicenses().size(), equalTo(0)); - } - - @Test - public void testXContentSerializationManyTrial() throws Exception { - final TrialLicenseUtils.TrialLicenseBuilder trialLicenseBuilder = TrialLicenseUtils.builder() - .duration(TimeValue.timeValueHours(2)) - .maxNodes(5) - .issuedTo("customer") - .issueDate(System.currentTimeMillis()); - int n = randomIntBetween(2, 5); - List trialLicenses = new ArrayList<>(n); - for (int i = 0; i < n; i++) { - trialLicenses.add(trialLicenseBuilder.feature("feature__" + String.valueOf(i)).build()); - } - LicensesMetaData licensesMetaData = new LicensesMetaData(new ArrayList(), trialLicenses); - XContentBuilder builder = XContentFactory.jsonBuilder(); - builder.startObject("licensesMetaData"); - licensesMetaData.toXContent(builder, ToXContent.EMPTY_PARAMS); - builder.endObject(); - byte[] serializedBytes = builder.bytes().toBytes(); - - LicensesMetaData licensesMetaDataFromXContent = getLicensesMetaDataFromXContent(serializedBytes); - - assertThat(licensesMetaDataFromXContent.getTrialLicenses().size(), equalTo(n)); - TestUtils.isSame(licensesMetaDataFromXContent.getTrialLicenses(), trialLicenses); - assertThat(licensesMetaDataFromXContent.getSignedLicenses().size(), equalTo(0)); - } - - @Test - public void testXContentSerializationManyTrialAndSignedLicenses() throws Exception { - final TrialLicenseUtils.TrialLicenseBuilder trialLicenseBuilder = TrialLicenseUtils.builder() - .duration(TimeValue.timeValueHours(2)) - .maxNodes(5) - .issuedTo("customer") - .issueDate(System.currentTimeMillis()); - int n = randomIntBetween(2, 5); - List trialLicenses = new ArrayList<>(n); - for (int i = 0; i < n; i++) { - trialLicenses.add(trialLicenseBuilder.feature("feature__" + String.valueOf(i)).build()); - } - List licenses = new ArrayList<>(); - for (int i = 0; i < n; i++) { - licenses.add(TestUtils.generateSignedLicense("feature__" + String.valueOf(i), TimeValue.timeValueHours(2))); - } - LicensesMetaData licensesMetaData = new LicensesMetaData(licenses, trialLicenses); - XContentBuilder builder = XContentFactory.jsonBuilder(); - builder.startObject("licensesMetaData"); - licensesMetaData.toXContent(builder, ToXContent.EMPTY_PARAMS); - builder.endObject(); - byte[] serializedBytes = builder.bytes().toBytes(); - - LicensesMetaData licensesMetaDataFromXContent = getLicensesMetaDataFromXContent(serializedBytes); - - assertThat(licensesMetaDataFromXContent.getTrialLicenses().size(), equalTo(n)); - assertThat(licensesMetaDataFromXContent.getSignedLicenses().size(), equalTo(n)); - TestUtils.isSame(licensesMetaDataFromXContent.getTrialLicenses(), trialLicenses); - TestUtils.isSame(licensesMetaDataFromXContent.getSignedLicenses(), licenses); - } - - private static LicensesMetaData getLicensesMetaDataFromXContent(byte[] bytes) throws Exception { - final XContentParser parser = XContentFactory.xContent(XContentType.JSON).createParser(bytes); - parser.nextToken(); // consume null - parser.nextToken(); // consume "licensesMetaData" - LicensesMetaData licensesMetaDataFromXContent = LicensesMetaData.PROTO.fromXContent(parser); - parser.nextToken(); // consume endObject - assertThat(parser.nextToken(), nullValue()); - return licensesMetaDataFromXContent; - } -} diff --git a/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesPluginIntegrationTests.java b/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesPluginIntegrationTests.java deleted file mode 100644 index df4a5caf6b6..00000000000 --- a/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesPluginIntegrationTests.java +++ /dev/null @@ -1,150 +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.license.plugin; - -import com.google.common.base.Predicate; -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.junit.After; -import org.junit.Test; - -import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope; -import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope.TEST; -import static org.hamcrest.CoreMatchers.equalTo; - -@ClusterScope(scope = TEST, numDataNodes = 10, numClientNodes = 0) -public class LicensesPluginIntegrationTests extends AbstractLicensesIntegrationTests { - - private final boolean useEagerLicenseRegistrationPlugin = randomBoolean(); - - private final int trialLicenseDurationInSeconds = 10; - - protected Settings nodeSettings(int nodeOrdinal) { - return Settings.settingsBuilder() - .put(super.nodeSettings(nodeOrdinal)) - .put(((useEagerLicenseRegistrationPlugin) ? EagerLicenseRegistrationConsumerPlugin.NAME : LazyLicenseRegistrationConsumerPlugin.NAME) - + ".trial_license_duration_in_seconds", trialLicenseDurationInSeconds) - .putArray("plugin.types", LicensePlugin.class.getName(), - (useEagerLicenseRegistrationPlugin) ? EagerLicenseRegistrationConsumerPlugin.class.getName() : LazyLicenseRegistrationConsumerPlugin.class.getName()) - .build(); - } - - @After - public void afterTest() throws Exception { - wipeAllLicenses(); - assertThat(awaitBusy(new Predicate() { - @Override - public boolean apply(Object o) { - return !clusterService().state().blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK); - } - }), equalTo(true)); - } - - @Test - 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 - assertLicenseManagerEnabledFeatureFor(getCurrentFeatureName()); - // 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); - assertLicenseManagerDisabledFeatureFor(getCurrentFeatureName()); - - logger.info(" --> put signed license"); - putLicense(getCurrentFeatureName(), TimeValue.timeValueSeconds(trialLicenseDurationInSeconds)); - - logger.info(" --> check signed license enabled notification"); - // consumer plugin should notify onEnabled on all data nodes (signed license) - assertConsumerPluginEnabledNotification(1); - assertLicenseManagerEnabledFeatureFor(getCurrentFeatureName()); - - logger.info(" --> check signed license expiry notification"); - // consumer plugin should notify onDisabled on all data nodes (expired signed license) - assertConsumerPluginDisabledNotification(trialLicenseDurationInSeconds * 2); - assertLicenseManagerDisabledFeatureFor(getCurrentFeatureName()); - } - - @Test - public void testTrialLicenseNotification() throws Exception { - logger.info(" --> check onEnabled for trial license"); - // managerService should report feature to be enabled on all data nodes - assertLicenseManagerEnabledFeatureFor(getCurrentFeatureName()); - // consumer plugin service should return enabled on all data nodes - assertConsumerPluginEnabledNotification(1); - - logger.info(" --> sleep for rest of trailLicense duration"); - Thread.sleep(trialLicenseDurationInSeconds * 1000l); - - logger.info(" --> check trial license expiry notification"); - // consumer plugin should notify onDisabled on all data nodes (expired signed license) - assertConsumerPluginDisabledNotification(trialLicenseDurationInSeconds * 2); - assertLicenseManagerDisabledFeatureFor(getCurrentFeatureName()); - } - - @Test - public void testOverlappingTrialAndSignedLicenseNotification() throws Exception { - logger.info(" --> check onEnabled for trial license"); - // managerService should report feature to be enabled on all data nodes - assertLicenseManagerEnabledFeatureFor(getCurrentFeatureName()); - // consumer plugin service should return enabled on all data nodes - assertConsumerPluginEnabledNotification(1); - - logger.info(" --> put signed license while trial license is in effect"); - putLicense(getCurrentFeatureName(), TimeValue.timeValueSeconds(trialLicenseDurationInSeconds * 2)); - - logger.info(" --> check signed license enabled notification"); - // consumer plugin should notify onEnabled on all data nodes (signed license) - assertConsumerPluginEnabledNotification(1); - assertLicenseManagerEnabledFeatureFor(getCurrentFeatureName()); - - 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); - assertLicenseManagerEnabledFeatureFor(getCurrentFeatureName()); - - logger.info(" --> check signed license expiry notification"); - // consumer plugin should notify onDisabled on all data nodes (expired signed license) - assertConsumerPluginDisabledNotification(trialLicenseDurationInSeconds * 2 * 2); - assertLicenseManagerDisabledFeatureFor(getCurrentFeatureName()); - } - - private String getCurrentFeatureName() { - if (useEagerLicenseRegistrationPlugin) { - return EagerLicenseRegistrationPluginService.FEATURE_NAME; - } else { - return LazyLicenseRegistrationPluginService.FEATURE_NAME; - } - } - - private void assertConsumerPluginEnabledNotification(int timeoutInSec) throws InterruptedException { - if (useEagerLicenseRegistrationPlugin) { - assertEagerConsumerPluginEnableNotification(timeoutInSec); - } else { - assertLazyConsumerPluginEnableNotification(timeoutInSec); - } - } - - private void assertConsumerPluginDisabledNotification(int timeoutInSec) throws InterruptedException { - if (useEagerLicenseRegistrationPlugin) { - assertEagerConsumerPluginDisableNotification(timeoutInSec); - } else { - assertLazyConsumerPluginDisableNotification(timeoutInSec); - } - } - -} diff --git a/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesPluginsIntegrationTests.java b/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesPluginsIntegrationTests.java deleted file mode 100644 index 8a72d56d344..00000000000 --- a/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesPluginsIntegrationTests.java +++ /dev/null @@ -1,176 +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.license.plugin; - -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.junit.After; -import org.junit.Test; - -import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope; -import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope.TEST; - -@ClusterScope(scope = TEST, numDataNodes = 0, numClientNodes = 0) -public class LicensesPluginsIntegrationTests extends AbstractLicensesIntegrationTests { - - private final String FEATURE_NAME_1 = EagerLicenseRegistrationPluginService.FEATURE_NAME; - private final String FEATURE_NAME_2 = LazyLicenseRegistrationPluginService.FEATURE_NAME; - - protected Settings nodeSettings(int nodeOrdinal) { - return Settings.settingsBuilder() - .put(super.nodeSettings(nodeOrdinal)) - .putArray("plugin.types", LicensePlugin.class.getName(), EagerLicenseRegistrationConsumerPlugin.class.getName(), LazyLicenseRegistrationConsumerPlugin.class.getName()) - .build(); - } - - private Settings nodeSettingsWithConsumerPlugin(int consumer1TrialLicenseDuration, int consumer2TrialLicenseDuration) { - return Settings.settingsBuilder() - .put(super.nodeSettings(0)) - .put(EagerLicenseRegistrationConsumerPlugin.NAME + ".trial_license_duration_in_seconds", consumer1TrialLicenseDuration) - .put(LazyLicenseRegistrationConsumerPlugin.NAME + ".trial_license_duration_in_seconds", consumer2TrialLicenseDuration) - .putArray("plugin.types", LicensePlugin.class.getName(), EagerLicenseRegistrationConsumerPlugin.class.getName(), LazyLicenseRegistrationConsumerPlugin.class.getName()) - .build(); - - } - - @After - public void afterTest() throws Exception { - wipeAllLicenses(); - } - - @Test - public void testWithNoTrialLicense() throws Exception { - int nNodes = randomIntBetween(2, 10); - startNodesWithConsumerPlugins(nNodes, -1, -1); - - assertEagerConsumerPluginDisableNotification(1); - assertLazyConsumerPluginDisableNotification(1); - assertLicenseManagerDisabledFeatureFor(FEATURE_NAME_1); - assertLicenseManagerDisabledFeatureFor(FEATURE_NAME_2); - } - - @Test - public void testOneTrialAndNonTrialConsumer() throws Exception { - int nNodes = randomIntBetween(2, 10); - int consumer2TrialLicenseDuration = 5; - startNodesWithConsumerPlugins(nNodes, -1, consumer2TrialLicenseDuration); - - logger.info(" --> trial license generated for " + FEATURE_NAME_2 + " no trial license for " + FEATURE_NAME_1); - // managerService should report feature to be enabled on all data nodes - assertLicenseManagerDisabledFeatureFor(FEATURE_NAME_1); - assertLicenseManagerEnabledFeatureFor(FEATURE_NAME_2); - // consumer plugin service should return enabled on all data nodes - assertEagerConsumerPluginDisableNotification(1); - assertLazyConsumerPluginEnableNotification(1); - - logger.info(" --> put signed license for " + FEATURE_NAME_1); - putLicense(FEATURE_NAME_1, TimeValue.timeValueSeconds(consumer2TrialLicenseDuration)); - - logger.info(" --> check that both " + FEATURE_NAME_1 + " and " + FEATURE_NAME_2 + " are enabled"); - assertEagerConsumerPluginEnableNotification(1); - assertLicenseManagerEnabledFeatureFor(FEATURE_NAME_1); - - logger.info(" --> check signed license expiry notification"); - // consumer plugin should notify onDisabled on all data nodes (expired signed license) - assertEagerConsumerPluginDisableNotification(consumer2TrialLicenseDuration * 2); - assertLazyConsumerPluginDisableNotification(consumer2TrialLicenseDuration * 2); - assertLicenseManagerDisabledFeatureFor(FEATURE_NAME_1); - assertLicenseManagerDisabledFeatureFor(FEATURE_NAME_2); - } - - @Test - public void testMultipleConsumerPlugins() throws Exception { - - int nNodes = randomIntBetween(2, 10); - int consumer1TrialLicenseExpiry = 5; - int consumer2TrialLicenseExpiry = 5; - startNodesWithConsumerPlugins(nNodes, consumer1TrialLicenseExpiry, consumer2TrialLicenseExpiry); - - logger.info(" --> trial license generated"); - // managerService should report feature to be enabled on all data nodes - assertLicenseManagerEnabledFeatureFor(FEATURE_NAME_1); - assertLicenseManagerEnabledFeatureFor(FEATURE_NAME_2); - // consumer plugin service should return enabled on all data nodes - assertEagerConsumerPluginEnableNotification(1); - assertLazyConsumerPluginEnableNotification(1); - - logger.info(" --> check trial license expiry notification"); - // consumer plugin should notify onDisabled on all data nodes (expired trial license) - assertEagerConsumerPluginDisableNotification(consumer1TrialLicenseExpiry * 2); - assertLazyConsumerPluginDisableNotification(consumer2TrialLicenseExpiry * 2); - assertLicenseManagerDisabledFeatureFor(FEATURE_NAME_1); - assertLicenseManagerDisabledFeatureFor(FEATURE_NAME_2); - - logger.info(" --> put signed license"); - putLicense(FEATURE_NAME_1, TimeValue.timeValueSeconds(consumer1TrialLicenseExpiry)); - putLicense(FEATURE_NAME_2, TimeValue.timeValueSeconds(consumer2TrialLicenseExpiry)); - - logger.info(" --> check signed license enabled notification"); - // consumer plugin should notify onEnabled on all data nodes (signed license) - assertEagerConsumerPluginEnableNotification(1); - assertLazyConsumerPluginEnableNotification(1); - assertLicenseManagerEnabledFeatureFor(FEATURE_NAME_1); - assertLicenseManagerEnabledFeatureFor(FEATURE_NAME_2); - - logger.info(" --> check signed license expiry notification"); - // consumer plugin should notify onDisabled on all data nodes (expired signed license) - assertEagerConsumerPluginDisableNotification(consumer1TrialLicenseExpiry * 2); - assertLazyConsumerPluginDisableNotification(consumer2TrialLicenseExpiry * 2); - assertLicenseManagerDisabledFeatureFor(FEATURE_NAME_1); - assertLicenseManagerDisabledFeatureFor(FEATURE_NAME_2); - } - - @Test - public void testRandomFeatureLicensesActions() throws Exception { - int nNodes = randomIntBetween(2, 10); - int trialLicenseDuration1 = rarely() ? -1 : randomIntBetween(6, 8); - int trialLicenseDuration2 = rarely() ? -1 : randomIntBetween(6, 8); - - startNodesWithConsumerPlugins(nNodes, trialLicenseDuration1, trialLicenseDuration2); - - if (trialLicenseDuration1 != -1) { - assertEagerConsumerPluginEnableNotification(trialLicenseDuration1); - assertLicenseManagerEnabledFeatureFor(FEATURE_NAME_1); - } else { - assertEagerConsumerPluginDisableNotification(3 * 2); - assertLicenseManagerDisabledFeatureFor(FEATURE_NAME_1); - putLicense(FEATURE_NAME_1, TimeValue.timeValueSeconds(5)); - } - - if (trialLicenseDuration2 != -1) { - assertLazyConsumerPluginEnableNotification(trialLicenseDuration2); - assertLicenseManagerEnabledFeatureFor(FEATURE_NAME_2); - } else { - assertLazyConsumerPluginDisableNotification(3 * 2); - assertLicenseManagerDisabledFeatureFor(FEATURE_NAME_2); - putLicense(FEATURE_NAME_2, TimeValue.timeValueSeconds(5)); - } - - logger.info(" --> check license enabled notification"); - assertEagerConsumerPluginEnableNotification(1); - assertLazyConsumerPluginEnableNotification(1); - assertLicenseManagerEnabledFeatureFor(FEATURE_NAME_1); - assertLicenseManagerEnabledFeatureFor(FEATURE_NAME_2); - - logger.info(" --> check license expiry notification"); - // consumer plugin should notify onDisabled on all data nodes (expired signed license) - assertEagerConsumerPluginDisableNotification(8 * 2); - assertLazyConsumerPluginDisableNotification(8 * 2); - assertLicenseManagerDisabledFeatureFor(FEATURE_NAME_1); - assertLicenseManagerDisabledFeatureFor(FEATURE_NAME_2); - - } - - private void startNodesWithConsumerPlugins(int nNodes, int consumer1TrialLicenseDuration, int consumer2TrialLicenseDuration) { - for (int i = 0; i < nNodes; i++) { - internalCluster().startNode(nodeSettingsWithConsumerPlugin(consumer1TrialLicenseDuration, consumer2TrialLicenseDuration)); - } - } -} diff --git a/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesServiceClusterTest.java b/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesServiceClusterTest.java deleted file mode 100644 index 711ec29e255..00000000000 --- a/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesServiceClusterTest.java +++ /dev/null @@ -1,172 +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.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.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.LicensesMetaData; -import org.elasticsearch.license.plugin.core.LicensesStatus; -import org.elasticsearch.node.Node; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.List; - -import static org.elasticsearch.license.plugin.TestUtils.generateSignedLicense; -import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope; -import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope.TEST; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.notNullValue; - -@ClusterScope(scope = TEST, numDataNodes = 0, numClientNodes = 0, maxNumDataNodes = 0, transportClientRatio = 0) -public class LicensesServiceClusterTest extends AbstractLicensesIntegrationTests { - - private final String[] FEATURES = {EagerLicenseRegistrationPluginService.FEATURE_NAME, LazyLicenseRegistrationPluginService.FEATURE_NAME}; - - 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("gateway.type", "local") - .put("plugins.load_classpath_plugins", false) - .put("node.data", true) - .put("format", "json") - .put(EagerLicenseRegistrationConsumerPlugin.NAME + ".trial_license_duration_in_seconds", 2) - .put(LazyLicenseRegistrationConsumerPlugin.NAME + ".trial_license_duration_in_seconds", 2) - .putArray("plugin.types", LicensePlugin.class.getName(), EagerLicenseRegistrationConsumerPlugin.class.getName(), LazyLicenseRegistrationConsumerPlugin.class.getName()) - .put(Node.HTTP_ENABLED, true); - } - - @Test - public void testClusterRestart() 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"); - final List licenses = generateAndPutLicenses(); - getAndCheckLicense(licenses); - logger.info("--> restart all nodes"); - internalCluster().fullRestart(); - ensureYellow(); - - logger.info("--> get and check signed license"); - getAndCheckLicense(licenses); - - wipeAllLicenses(); - } - - @Test - 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)); - // license plugin should not be active when cluster is still recovering - assertLicenseManagerFeatureDisabled(); - assertConsumerPluginDisabledNotification(1); - - 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)); - assertLicenseManagerFeatureEnabled(); - assertConsumerPluginEnabledNotification(1); - } - - @Test - public void testAtMostOnceTrialLicenseGeneration() throws Exception { - wipeAllLicenses(); - logger.info("--> start one node [trial license should be generated & enabled]"); - internalCluster().startNode(nodeSettingsBuilder(0)); - assertLicenseManagerFeatureEnabled(); - assertConsumerPluginEnabledNotification(1); - - logger.info("--> start another node [trial license should be propagated from the old master not generated]"); - internalCluster().startNode(nodeSettings(1)); - assertLicenseManagerFeatureEnabled(); - assertConsumerPluginEnabledNotification(1); - - logger.info("--> check if multiple trial licenses are found for a feature"); - LicensesMetaData licensesMetaData = clusterService().state().metaData().custom(LicensesMetaData.TYPE); - assertThat(licensesMetaData.getTrialLicenses().size(), equalTo(FEATURES.length)); - - wipeAllLicenses(); - } - - private List generateAndPutLicenses() throws Exception { - ClusterAdminClient cluster = internalCluster().client().admin().cluster(); - List putLicenses = new ArrayList<>(FEATURES.length); - for (String feature : FEATURES) { - putLicenses.add(generateSignedLicense(feature, TimeValue.timeValueMinutes(1))); - } - PutLicenseRequestBuilder putLicenseRequestBuilder = new PutLicenseRequestBuilder(cluster, PutLicenseAction.INSTANCE); - putLicenseRequestBuilder.setLicense(putLicenses); - ensureGreen(); - - final PutLicenseResponse putLicenseResponse = putLicenseRequestBuilder.get(); - - assertThat(putLicenseResponse.isAcknowledged(), equalTo(true)); - assertThat(putLicenseResponse.status(), equalTo(LicensesStatus.VALID)); - - return putLicenses; - } - - private void getAndCheckLicense(List licenses) { - ClusterAdminClient cluster = internalCluster().client().admin().cluster(); - final GetLicenseResponse response = new GetLicenseRequestBuilder(cluster, GetLicenseAction.INSTANCE).get(); - assertThat(response.licenses().size(), equalTo(licenses.size())); - TestUtils.isSame(licenses, response.licenses()); - - LicensesMetaData licensesMetaData = clusterService().state().metaData().custom(LicensesMetaData.TYPE); - assertThat(licensesMetaData, notNullValue()); - assertThat(licensesMetaData.getTrialLicenses().size(), equalTo(2)); - } - - private void assertLicenseManagerFeatureEnabled() throws Exception { - for (String feature : FEATURES) { - assertLicenseManagerEnabledFeatureFor(feature); - } - } - - private void assertLicenseManagerFeatureDisabled() throws Exception { - for (String feature : FEATURES) { - assertLicenseManagerDisabledFeatureFor(feature); - } - } - - private void assertConsumerPluginEnabledNotification(int timeoutInSec) throws InterruptedException { - assertEagerConsumerPluginEnableNotification(timeoutInSec); - assertLazyConsumerPluginEnableNotification(timeoutInSec); - } - - private void assertConsumerPluginDisabledNotification(int timeoutInSec) throws InterruptedException { - assertEagerConsumerPluginDisableNotification(timeoutInSec); - assertLazyConsumerPluginDisableNotification(timeoutInSec); - } - -} diff --git a/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesServiceNodeTests.java b/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesServiceNodeTests.java deleted file mode 100644 index c6de70b35ab..00000000000 --- a/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesServiceNodeTests.java +++ /dev/null @@ -1,55 +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.license.plugin; - -import com.google.common.base.Predicate; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.license.plugin.consumer.EagerLicenseRegistrationConsumerPlugin; -import org.elasticsearch.license.plugin.consumer.EagerLicenseRegistrationPluginService; -import org.elasticsearch.node.Node; -import org.elasticsearch.test.ElasticsearchIntegrationTest; -import org.elasticsearch.test.junit.annotations.TestLogging; -import org.junit.Test; - -import java.util.concurrent.TimeUnit; - -import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope.TEST; -import static org.hamcrest.Matchers.equalTo; - -/** - */ -@ElasticsearchIntegrationTest.ClusterScope(scope = TEST, numDataNodes = 10, numClientNodes = 0) -public class LicensesServiceNodeTests extends AbstractLicensesIntegrationTests { - - @Override - protected Settings nodeSettings(int nodeOrdinal) { - return Settings.settingsBuilder() - .put(super.nodeSettings(nodeOrdinal)) - .put(EagerLicenseRegistrationConsumerPlugin.NAME + ".trial_license_duration_in_seconds", 60 * 5) - .putArray("plugin.types", LicensePlugin.class.getName(), EagerLicenseRegistrationConsumerPlugin.class.getName()) - .put(Node.HTTP_ENABLED, true) - .build(); - } - - @Test - @TestLogging("_root:DEBUG") - public void testPluginStatus() throws Exception { - final Iterable testPluginServices = internalCluster().getDataNodeInstances(EagerLicenseRegistrationPluginService.class); - assertThat(awaitBusy(new Predicate() { - @Override - public boolean apply(Object o) { - for (EagerLicenseRegistrationPluginService pluginService : testPluginServices) { - if (!pluginService.enabled()) { - return false; - } - } - return true; - } - }, 10, TimeUnit.SECONDS), equalTo(true)); - - } - -} diff --git a/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesTransportTests.java b/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesTransportTests.java deleted file mode 100644 index ee5ee6c5ce2..00000000000 --- a/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesTransportTests.java +++ /dev/null @@ -1,265 +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.license.plugin; - -import com.google.common.collect.Sets; -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.junit.After; -import org.junit.Test; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import static org.elasticsearch.license.plugin.TestUtils.generateSignedLicense; -import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope; -import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope.TEST; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.notNullValue; - -@ClusterScope(scope = TEST, numDataNodes = 10) -public class LicensesTransportTests extends AbstractLicensesIntegrationTests { - - @After - public void beforeTest() throws Exception { - wipeAllLicenses(); - } - - @Test - public void testEmptyGetLicense() throws Exception { - final ActionFuture getLicenseFuture = new GetLicenseRequestBuilder(client().admin().cluster(), GetLicenseAction.INSTANCE).execute(); - final GetLicenseResponse getLicenseResponse = getLicenseFuture.get(); - assertThat("expected 0 licenses; but got: " + getLicenseResponse.licenses().size(), getLicenseResponse.licenses().size(), equalTo(0)); - } - - @Test - public void testPutLicense() throws Exception { - License signedLicense = generateSignedLicense("shield", TimeValue.timeValueMinutes(2)); - List actualLicenses = Collections.singletonList(signedLicense); - - // put license - PutLicenseRequestBuilder putLicenseRequestBuilder = new PutLicenseRequestBuilder(client().admin().cluster(), PutLicenseAction.INSTANCE) - .setLicense(actualLicenses); - PutLicenseResponse putLicenseResponse = putLicenseRequestBuilder.get(); - assertThat(putLicenseResponse.isAcknowledged(), equalTo(true)); - assertThat(putLicenseResponse.status(), equalTo(LicensesStatus.VALID)); - - // get license - GetLicenseResponse getLicenseResponse = new GetLicenseRequestBuilder(client().admin().cluster(), GetLicenseAction.INSTANCE).get(); - assertThat(getLicenseResponse.licenses(), notNullValue()); - assertThat(getLicenseResponse.licenses().size(), equalTo(1)); - - // check license - TestUtils.isSame(signedLicense, getLicenseResponse.licenses().get(0)); - } - - @Test - public void testPutLicenseFromString() throws Exception { - License signedLicense = generateSignedLicense("shield", 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 license - GetLicenseResponse getLicenseResponse = new GetLicenseRequestBuilder(client().admin().cluster(), GetLicenseAction.INSTANCE).get(); - assertThat(getLicenseResponse.licenses(), notNullValue()); - assertThat(getLicenseResponse.licenses().size(), equalTo(1)); - - // check license - TestUtils.isSame(signedLicense, getLicenseResponse.licenses().get(0)); - } - - @Test - public void testPutInvalidLicense() throws Exception { - License signedLicense = generateSignedLicense("shield", 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(Collections.singletonList(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.licenses().size(), equalTo(0)); - } - - @Test - public void testPutExpiredLicense() throws Exception { - License expiredLicense = generateSignedLicense("feature", dateMath("now-10d/d", System.currentTimeMillis()), TimeValue.timeValueMinutes(2)); - License signedLicense = generateSignedLicense("feature", TimeValue.timeValueMinutes(2)); - - PutLicenseRequestBuilder builder = new PutLicenseRequestBuilder(client().admin().cluster(), PutLicenseAction.INSTANCE); - builder.setLicense(Arrays.asList(signedLicense, expiredLicense)); - - // put license should return valid (as there is one valid license) - final PutLicenseResponse putLicenseResponse = builder.get(); - assertThat(putLicenseResponse.status(), equalTo(LicensesStatus.VALID)); - - // get license should not return the expired license - GetLicenseResponse getLicenseResponse = new GetLicenseRequestBuilder(client().admin().cluster(), GetLicenseAction.INSTANCE).get(); - assertThat(getLicenseResponse.licenses().size(), equalTo(1)); - - TestUtils.isSame(getLicenseResponse.licenses().get(0), signedLicense); - } - - @Test - public void testPutLicensesForSameFeature() throws Exception { - License shortedSignedLicense = generateSignedLicense("shield", TimeValue.timeValueMinutes(2)); - License longerSignedLicense = generateSignedLicense("shield", TimeValue.timeValueMinutes(5)); - List actualLicenses = Arrays.asList(longerSignedLicense, shortedSignedLicense); - - // put license - PutLicenseRequestBuilder putLicenseRequestBuilder = new PutLicenseRequestBuilder(client().admin().cluster(), PutLicenseAction.INSTANCE) - .setLicense(actualLicenses); - PutLicenseResponse putLicenseResponse = putLicenseRequestBuilder.get(); - assertThat(putLicenseResponse.isAcknowledged(), equalTo(true)); - assertThat(putLicenseResponse.status(), equalTo(LicensesStatus.VALID)); - - // get should return only one license (with longer expiry date) - GetLicenseResponse getLicenseResponse = new GetLicenseRequestBuilder(client().admin().cluster(), GetLicenseAction.INSTANCE).get(); - assertThat(getLicenseResponse.licenses(), notNullValue()); - assertThat(getLicenseResponse.licenses().size(), equalTo(1)); - - // check license - TestUtils.isSame(longerSignedLicense, getLicenseResponse.licenses().get(0)); - } - - @Test - public void testPutLicensesForMultipleFeatures() throws Exception { - License shieldLicense = generateSignedLicense("shield", TimeValue.timeValueMinutes(2)); - License marvelLicense = generateSignedLicense("marvel", TimeValue.timeValueMinutes(5)); - List actualLicenses = Arrays.asList(marvelLicense, shieldLicense); - - // put license - PutLicenseRequestBuilder putLicenseRequestBuilder = new PutLicenseRequestBuilder(client().admin().cluster(), PutLicenseAction.INSTANCE) - .setLicense(actualLicenses); - PutLicenseResponse putLicenseResponse = putLicenseRequestBuilder.get(); - assertThat(putLicenseResponse.isAcknowledged(), equalTo(true)); - assertThat(putLicenseResponse.status(), equalTo(LicensesStatus.VALID)); - - // get should return both the licenses - GetLicenseResponse getLicenseResponse = new GetLicenseRequestBuilder(client().admin().cluster(), GetLicenseAction.INSTANCE).get(); - assertThat(getLicenseResponse.licenses(), notNullValue()); - - // check license - TestUtils.isSame(actualLicenses, getLicenseResponse.licenses()); - } - - @Test - public void testPutMultipleLicensesForMultipleFeatures() throws Exception { - License shortedSignedLicense = generateSignedLicense("shield", TimeValue.timeValueMinutes(2)); - License longerSignedLicense = generateSignedLicense("shield", TimeValue.timeValueMinutes(5)); - License marvelLicense = generateSignedLicense("marvel", TimeValue.timeValueMinutes(5)); - List actualLicenses = Arrays.asList(marvelLicense, shortedSignedLicense, longerSignedLicense); - - // put license - PutLicenseRequestBuilder putLicenseRequestBuilder = new PutLicenseRequestBuilder(client().admin().cluster(), PutLicenseAction.INSTANCE) - .setLicense(actualLicenses); - PutLicenseResponse putLicenseResponse = putLicenseRequestBuilder.get(); - assertThat(putLicenseResponse.isAcknowledged(), equalTo(true)); - assertThat(putLicenseResponse.status(), equalTo(LicensesStatus.VALID)); - - // get should return both the licenses - GetLicenseResponse getLicenseResponse = new GetLicenseRequestBuilder(client().admin().cluster(), GetLicenseAction.INSTANCE).get(); - assertThat(getLicenseResponse.licenses(), notNullValue()); - assertThat(getLicenseResponse.licenses().size(), equalTo(2)); - - // check license (should get the longest expiry time for all unique features) - TestUtils.isSame(Arrays.asList(marvelLicense, longerSignedLicense), getLicenseResponse.licenses()); - } - - @Test - public void testRemoveLicenseSimple() throws Exception { - License shieldLicense = generateSignedLicense("shield", TimeValue.timeValueMinutes(2)); - License marvelLicense = generateSignedLicense("marvel", TimeValue.timeValueMinutes(5)); - List actualLicenses = Arrays.asList(marvelLicense, shieldLicense); - - // put two licenses - PutLicenseRequestBuilder putLicenseRequestBuilder = new PutLicenseRequestBuilder(client().admin().cluster(), PutLicenseAction.INSTANCE) - .setLicense(actualLicenses); - PutLicenseResponse putLicenseResponse = putLicenseRequestBuilder.get(); - assertThat(putLicenseResponse.isAcknowledged(), equalTo(true)); - assertThat(putLicenseResponse.status(), equalTo(LicensesStatus.VALID)); - - // get and check licenses - GetLicenseResponse getLicenseResponse = new GetLicenseRequestBuilder(client().admin().cluster(), GetLicenseAction.INSTANCE).get(); - assertThat(getLicenseResponse.licenses(), notNullValue()); - assertThat(getLicenseResponse.licenses().size(), equalTo(2)); - - // delete all licenses - DeleteLicenseRequestBuilder deleteLicenseRequestBuilder = new DeleteLicenseRequestBuilder(client().admin().cluster(), DeleteLicenseAction.INSTANCE) - .setFeatures(Sets.newHashSet("shield", "marvel")); - DeleteLicenseResponse deleteLicenseResponse = deleteLicenseRequestBuilder.get(); - assertThat(deleteLicenseResponse.isAcknowledged(), equalTo(true)); - - // get licenses (expected no licenses) - getLicenseResponse = new GetLicenseRequestBuilder(client().admin().cluster(), GetLicenseAction.INSTANCE).get(); - assertThat(getLicenseResponse.licenses(), notNullValue()); - assertThat(getLicenseResponse.licenses().size(), equalTo(0)); - } - - @Test - public void testRemoveLicenses() throws Exception { - License shieldLicense = generateSignedLicense("shield", TimeValue.timeValueMinutes(2)); - License marvelLicense = generateSignedLicense("marvel", TimeValue.timeValueMinutes(5)); - List actualLicenses = Arrays.asList(marvelLicense, shieldLicense); - - // put two licenses - PutLicenseRequestBuilder putLicenseRequestBuilder = new PutLicenseRequestBuilder(client().admin().cluster(), PutLicenseAction.INSTANCE) - .setLicense(actualLicenses); - PutLicenseResponse putLicenseResponse = putLicenseRequestBuilder.get(); - assertThat(putLicenseResponse.isAcknowledged(), equalTo(true)); - assertThat(putLicenseResponse.status(), equalTo(LicensesStatus.VALID)); - - // delete one license - DeleteLicenseRequestBuilder deleteLicenseRequestBuilder = new DeleteLicenseRequestBuilder(client().admin().cluster(), DeleteLicenseAction.INSTANCE) - .setFeatures(Sets.newHashSet("shield")); - DeleteLicenseResponse deleteLicenseResponse = deleteLicenseRequestBuilder.get(); - assertThat(deleteLicenseResponse.isAcknowledged(), equalTo(true)); - - // check other license - GetLicenseResponse getLicenseResponse = new GetLicenseRequestBuilder(client().admin().cluster(), GetLicenseAction.INSTANCE).get(); - assertThat(getLicenseResponse.licenses(), notNullValue()); - assertThat(getLicenseResponse.licenses().size(), equalTo(1)); - - // delete another license - deleteLicenseRequestBuilder = new DeleteLicenseRequestBuilder(client().admin().cluster(), DeleteLicenseAction.INSTANCE) - .setFeatures(Sets.newHashSet("marvel")); - deleteLicenseResponse = deleteLicenseRequestBuilder.get(); - assertThat(deleteLicenseResponse.isAcknowledged(), equalTo(true)); - - // check no license - getLicenseResponse = new GetLicenseRequestBuilder(client().admin().cluster(), GetLicenseAction.INSTANCE).get(); - assertThat(getLicenseResponse.licenses(), notNullValue()); - assertThat(getLicenseResponse.licenses().size(), equalTo(0)); - } -} diff --git a/plugin/src/test/java/org/elasticsearch/license/plugin/TestUtils.java b/plugin/src/test/java/org/elasticsearch/license/plugin/TestUtils.java deleted file mode 100644 index 311ec249c9b..00000000000 --- a/plugin/src/test/java/org/elasticsearch/license/plugin/TestUtils.java +++ /dev/null @@ -1,99 +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.license.plugin; - -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.core.Licenses; -import org.elasticsearch.license.licensor.LicenseSigner; - -import java.net.URL; -import java.util.*; - -import static org.hamcrest.core.IsEqual.equalTo; -import static org.junit.Assert.assertThat; - -public class TestUtils { - - public static String getTestPriKeyPath() throws Exception { - return getResourcePath("/private.key"); - } - - public static String getTestPubKeyPath() throws Exception { - return getResourcePath("/public.key"); - } - - public static void isSame(Collection firstLicenses, Collection secondLicenses) { - isSame(new HashSet<>(firstLicenses), new HashSet<>(secondLicenses)); - } - - public static void isSame(Set firstLicenses, Set secondLicenses) { - - // we do the verifyAndBuild to make sure we weed out any expired licenses - final Map licenses1 = Licenses.reduceAndMap(firstLicenses); - final Map licenses2 = Licenses.reduceAndMap(secondLicenses); - - // check if the effective licenses have the same feature set - assertThat(licenses1.size(), equalTo(licenses2.size())); - - // for every feature license, check if all the attributes are the same - for (String featureType : licenses1.keySet()) { - License license1 = licenses1.get(featureType); - License license2 = licenses2.get(featureType); - isSame(license1, license2); - } - } - - public static void isSame(License license1, License license2) { - assertThat(license1.uid(), equalTo(license2.uid())); - assertThat(license1.feature(), equalTo(license2.feature())); - assertThat(license1.subscriptionType(), equalTo(license2.subscriptionType())); - assertThat(license1.type(), equalTo(license2.type())); - assertThat(license1.issuedTo(), equalTo(license2.issuedTo())); - assertThat(license1.signature(), equalTo(license2.signature())); - assertThat(license1.expiryDate(), equalTo(license2.expiryDate())); - assertThat(license1.issueDate(), equalTo(license2.issueDate())); - assertThat(license1.maxNodes(), equalTo(license2.maxNodes())); - } - - public static String dumpLicense(License license) throws Exception { - XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON); - Licenses.toXContent(Collections.singletonList(license), builder, ToXContent.EMPTY_PARAMS); - builder.flush(); - return builder.string(); - } - - public static License generateSignedLicense(String feature, TimeValue expiryDuration) throws Exception { - return generateSignedLicense(feature, -1, expiryDuration); - } - - public static License generateSignedLicense(String feature, long issueDate, TimeValue expiryDuration) throws Exception { - long issue = (issueDate != -1l) ? issueDate : System.currentTimeMillis(); - final License licenseSpec = License.builder() - .uid(UUID.randomUUID().toString()) - .feature(feature) - .expiryDate(issue + expiryDuration.getMillis()) - .issueDate(issue) - .type("subscription") - .subscriptionType("gold") - .issuedTo("customer") - .issuer("elasticsearch") - .maxNodes(5) - .build(); - - LicenseSigner signer = new LicenseSigner(getTestPriKeyPath(), getTestPubKeyPath()); - return signer.sign(licenseSpec); - } - - private static String getResourcePath(String resource) throws Exception { - URL url = TestUtils.class.getResource(resource); - return url.toURI().getPath(); - } -} diff --git a/plugin/src/test/java/org/elasticsearch/license/plugin/TrailLicenseSerializationTests.java b/plugin/src/test/java/org/elasticsearch/license/plugin/TrailLicenseSerializationTests.java deleted file mode 100644 index 877c5a6346c..00000000000 --- a/plugin/src/test/java/org/elasticsearch/license/plugin/TrailLicenseSerializationTests.java +++ /dev/null @@ -1,38 +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.license.plugin; - -import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.license.core.License; -import org.elasticsearch.license.plugin.core.TrialLicenseUtils; -import org.elasticsearch.test.ElasticsearchTestCase; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.List; - - -public class TrailLicenseSerializationTests extends ElasticsearchTestCase { - - @Test - public void testSerialization() throws Exception { - final TrialLicenseUtils.TrialLicenseBuilder trialLicenseBuilder = TrialLicenseUtils.builder() - .duration(TimeValue.timeValueHours(2)) - .maxNodes(5) - .issuedTo("customer") - .issueDate(System.currentTimeMillis()); - int n = randomIntBetween(2, 5); - List trialLicenses = new ArrayList<>(n); - for (int i = 0; i < n; i++) { - trialLicenses.add(trialLicenseBuilder.feature("feature__" + String.valueOf(i)).build()); - } - for (License trialLicense : trialLicenses) { - String encodedTrialLicense = TrialLicenseUtils.toEncodedTrialLicense(trialLicense); - final License fromEncodedTrialLicense = TrialLicenseUtils.fromEncodedTrialLicense(encodedTrialLicense); - TestUtils.isSame(fromEncodedTrialLicense, trialLicense); - } - } -} diff --git a/plugin/src/test/java/org/elasticsearch/license/plugin/consumer/EagerLicenseRegistrationConsumerPlugin.java b/plugin/src/test/java/org/elasticsearch/license/plugin/consumer/EagerLicenseRegistrationConsumerPlugin.java deleted file mode 100644 index eeef14a3e48..00000000000 --- a/plugin/src/test/java/org/elasticsearch/license/plugin/consumer/EagerLicenseRegistrationConsumerPlugin.java +++ /dev/null @@ -1,40 +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.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 featureName() { - return EagerLicenseRegistrationPluginService.FEATURE_NAME; - } -} diff --git a/plugin/src/test/java/org/elasticsearch/license/plugin/consumer/EagerLicenseRegistrationPluginService.java b/plugin/src/test/java/org/elasticsearch/license/plugin/consumer/EagerLicenseRegistrationPluginService.java deleted file mode 100644 index d29b0d26218..00000000000 --- a/plugin/src/test/java/org/elasticsearch/license/plugin/consumer/EagerLicenseRegistrationPluginService.java +++ /dev/null @@ -1,32 +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.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.LicensesClientService; - -@Singleton -public class EagerLicenseRegistrationPluginService extends TestPluginServiceBase { - - public static String FEATURE_NAME = "feature1"; - - @Inject - public EagerLicenseRegistrationPluginService(Settings settings, LicensesClientService licensesClientService) { - super(true, settings, licensesClientService, null); - } - - @Override - public String featureName() { - return FEATURE_NAME; - } - - @Override - public String settingPrefix() { - return EagerLicenseRegistrationConsumerPlugin.NAME; - } -} diff --git a/plugin/src/test/java/org/elasticsearch/license/plugin/consumer/LazyLicenseRegistrationConsumerPlugin.java b/plugin/src/test/java/org/elasticsearch/license/plugin/consumer/LazyLicenseRegistrationConsumerPlugin.java deleted file mode 100644 index a0202b0651b..00000000000 --- a/plugin/src/test/java/org/elasticsearch/license/plugin/consumer/LazyLicenseRegistrationConsumerPlugin.java +++ /dev/null @@ -1,40 +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.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 featureName() { - return LazyLicenseRegistrationPluginService.FEATURE_NAME; - } -} diff --git a/plugin/src/test/java/org/elasticsearch/license/plugin/consumer/LazyLicenseRegistrationPluginService.java b/plugin/src/test/java/org/elasticsearch/license/plugin/consumer/LazyLicenseRegistrationPluginService.java deleted file mode 100644 index 7d54f1eb764..00000000000 --- a/plugin/src/test/java/org/elasticsearch/license/plugin/consumer/LazyLicenseRegistrationPluginService.java +++ /dev/null @@ -1,34 +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.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.LicensesClientService; - -@Singleton -public class LazyLicenseRegistrationPluginService extends TestPluginServiceBase { - - - public static String FEATURE_NAME = "feature2"; - - @Inject - public LazyLicenseRegistrationPluginService(Settings settings, LicensesClientService licensesClientService, ClusterService clusterService) { - super(false, settings, licensesClientService, clusterService); - } - - @Override - public String featureName() { - return FEATURE_NAME; - } - - @Override - public String settingPrefix() { - return LazyLicenseRegistrationConsumerPlugin.NAME; - } -} diff --git a/plugin/src/test/java/org/elasticsearch/license/plugin/consumer/TestConsumerPluginBase.java b/plugin/src/test/java/org/elasticsearch/license/plugin/consumer/TestConsumerPluginBase.java deleted file mode 100644 index c28682cc2a8..00000000000 --- a/plugin/src/test/java/org/elasticsearch/license/plugin/consumer/TestConsumerPluginBase.java +++ /dev/null @@ -1,55 +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.license.plugin.consumer; - -import com.google.common.collect.Lists; -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.AbstractPlugin; - -import java.util.Collection; - -public abstract class TestConsumerPluginBase extends AbstractPlugin { - - 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> services() { - Collection> services = Lists.newArrayList(); - if (isEnabled) { - services.add(service()); - } - return services; - } - - public abstract Class service(); - - protected abstract String pluginName(); - - public abstract String featureName(); -} diff --git a/plugin/src/test/java/org/elasticsearch/license/plugin/consumer/TestPluginServiceBase.java b/plugin/src/test/java/org/elasticsearch/license/plugin/consumer/TestPluginServiceBase.java deleted file mode 100644 index 89a968041a8..00000000000 --- a/plugin/src/test/java/org/elasticsearch/license/plugin/consumer/TestPluginServiceBase.java +++ /dev/null @@ -1,147 +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.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.LicensesClientService; -import org.elasticsearch.license.plugin.core.LicensesService; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.concurrent.atomic.AtomicBoolean; - -public abstract class TestPluginServiceBase extends AbstractLifecycleComponent implements ClusterStateListener { - - private LicensesClientService licensesClientService; - - private final ClusterService clusterService; - // specify the trial license spec for the feature - // example: 30 day trial on 1000 nodes - final LicensesService.TrialLicenseOptions trialLicenseOptions; - - final boolean eagerLicenseRegistration; - - final static Collection expirationCallbacks; - - static { - // Callback triggered every 24 hours from 30 days to 7 days of license expiry - final LicensesService.ExpirationCallback.Pre LEVEL_1 = new LicensesService.ExpirationCallback.Pre(TimeValue.timeValueHours(7 * 24), TimeValue.timeValueHours(30 * 24), TimeValue.timeValueHours(24)) { - @Override - public void on(License license, LicensesService.ExpirationStatus status) { - } - }; - - // Callback triggered every 10 minutes from 7 days to license expiry - final LicensesService.ExpirationCallback.Pre LEVEL_2 = new LicensesService.ExpirationCallback.Pre(null, TimeValue.timeValueHours(7 * 24), TimeValue.timeValueMinutes(10)) { - @Override - public void on(License license, LicensesService.ExpirationStatus status) { - } - }; - - // Callback triggered every 10 minutes after license expiry - final LicensesService.ExpirationCallback.Post LEVEL_3 = new LicensesService.ExpirationCallback.Post(TimeValue.timeValueMillis(0), null, TimeValue.timeValueMinutes(10)) { - @Override - public void on(License license, LicensesService.ExpirationStatus status) { - } - }; - - expirationCallbacks = new ArrayList<>(); - expirationCallbacks.add(LEVEL_1); - expirationCallbacks.add(LEVEL_2); - expirationCallbacks.add(LEVEL_3); - } - - - public final AtomicBoolean registered = new AtomicBoolean(false); - - private volatile AtomicBoolean enabled = new AtomicBoolean(false); - - public TestPluginServiceBase(boolean eagerLicenseRegistration, Settings settings, LicensesClientService licensesClientService, ClusterService clusterService) { - super(settings); - this.eagerLicenseRegistration = eagerLicenseRegistration; - this.licensesClientService = licensesClientService; - int durationInSec = settings.getAsInt(settingPrefix() + ".trial_license_duration_in_seconds", -1); - if (durationInSec == -1) { - this.trialLicenseOptions = null; - } else { - this.trialLicenseOptions = new LicensesService.TrialLicenseOptions(TimeValue.timeValueSeconds(durationInSec), 1000); - } - 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 featureName(); - - public abstract String settingPrefix(); - - // check if feature is enabled - public boolean enabled() { - return enabled.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(featureName(), - trialLicenseOptions, expirationCallbacks, - new LicensingClientListener()); - } - } - } - - protected void doStart() throws ElasticsearchException { - if (eagerLicenseRegistration) { - if (registered.compareAndSet(false, true)) { - logger.info("Registering to licensesService [eager]"); - licensesClientService.register(featureName(), - trialLicenseOptions, expirationCallbacks, - new LicensingClientListener()); - } - } - } - - @Override - protected void doStop() throws ElasticsearchException { - if (clusterService != null) { - clusterService.remove(this); - } - } - - @Override - protected void doClose() throws ElasticsearchException { - } - - private class LicensingClientListener implements LicensesClientService.Listener { - - @Override - public void onEnabled(License license) { - enabled.set(true); - } - - @Override - public void onDisabled(License license) { - enabled.set(false); - } - - } -} diff --git a/plugin/src/test/java/org/elasticsearch/license/plugin/rest/LicensesRestIT.java b/plugin/src/test/java/org/elasticsearch/license/plugin/rest/LicensesRestIT.java deleted file mode 100644 index 158aac9bf0a..00000000000 --- a/plugin/src/test/java/org/elasticsearch/license/plugin/rest/LicensesRestIT.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.license.plugin.rest; - - -import com.carrotsearch.randomizedtesting.annotations.Name; -import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; -import org.elasticsearch.test.rest.ElasticsearchRestTestCase; -import org.elasticsearch.test.rest.RestTestCandidate; -import org.elasticsearch.test.rest.parser.RestTestParseException; - -import java.io.IOException; - -public class LicensesRestIT extends ElasticsearchRestTestCase { - - public LicensesRestIT(@Name("yaml") RestTestCandidate testCandidate) { - super(testCandidate); - } - - @ParametersFactory - public static Iterable parameters() throws IOException, RestTestParseException { - return ElasticsearchRestTestCase.createParameters(0, 1); - } -} diff --git a/plugin/src/test/resources/log4j.properties b/plugin/src/test/resources/log4j.properties deleted file mode 100644 index bad42d74b70..00000000000 --- a/plugin/src/test/resources/log4j.properties +++ /dev/null @@ -1,11 +0,0 @@ -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/plugin/src/test/resources/private.key b/plugin/src/test/resources/private.key deleted file mode 100644 index 1f545803d87..00000000000 Binary files a/plugin/src/test/resources/private.key and /dev/null differ diff --git a/plugin/src/test/resources/public.key b/plugin/src/test/resources/public.key deleted file mode 100644 index 2a9f272e0b3..00000000000 --- a/plugin/src/test/resources/public.key +++ /dev/null @@ -1,3 +0,0 @@ -qngwM}UiK0b2غq]쇴c+I &IJf~ ]d}oOId -5A(쵴^WDJ}-O?uN5vp{t7 #Vqktwm]Lz"| QlQs><}[2Z|57%D -Yxn:lLH2HvEEW\H:6h9 [!+;.w7C_| Ӫ*D`?xU/3>xUӓ+ \ No newline at end of file diff --git a/pom.xml b/pom.xml deleted file mode 100644 index cf6801aeac8..00000000000 --- a/pom.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - 4.0.0 - - - org.elasticsearch.plugin - elasticsearch-plugin - 2.0.0.beta1-SNAPSHOT - - - org.elasticsearch - elasticsearch-license - pom - 2.0.0.beta1-SNAPSHOT - - core - licensor - plugin - plugin-api - - - - ${project.basedir} - ${license.basedir}/dev-tools/license/elasticsearch_license_header.txt - ${license.basedir}/dev-tools/license/license_header_definition.xml - - - - - oss-snapshots - Sonatype OSS Snapshots - https://oss.sonatype.org/content/repositories/snapshots/ - - - - - - deploy-internal - - - elasticsearch-internal-releases - Elasticsearch Internal Releases - http://maven.elasticsearch.org/artifactory/internal-releases - - - elasticsearch-internal-snapshots - Elasticsearch Internal Snapshots - http://maven.elasticsearch.org/artifactory/internal-snapshots - - - - - deploy-public - - - elasticsearch-public-releases - Elasticsearch Public Releases - http://maven.elasticsearch.org/artifactory/public-releases - - - - - default - - true - - - - - com.carrotsearch.randomizedtesting - junit4-maven-plugin - - ${tests.jvm.argline} - - - - - - -