From 43284305b6e130db51698e2c2232c8bddf6bb714 Mon Sep 17 00:00:00 2001 From: Areek Zillur Date: Fri, 21 Nov 2014 18:45:42 -0500 Subject: [PATCH] Make elasticsearch-license multi-module: - core-shaded - has CryptUtils (used by core and can be shared with consumer plugins) - core - License data structures & verifier - licensor - License Signer along with key-pair and license generation, verification - plugin - Enforce licensing on a deployment Original commit: elastic/x-pack-elasticsearch@041ef3a9f12132868f49e07521d99f7b3ccdfdb6 --- all-signatures.txt | 3 + core-shaded/pom.xml | 17 ++ .../license/core/shaded}/CryptUtils.java | 2 +- core-signatures.txt | 65 ++++ core/pom.xml | 138 +++++++++ .../elasticsearch/license/core/DateUtils.java | 0 .../elasticsearch/license/core/License.java | 17 +- .../license/core/LicenseVerifier.java | 69 ++++- .../elasticsearch/license/core/Licenses.java | 31 ++ .../core}/LicenseSerializationTests.java | 56 ++-- .../elasticsearch/license/core/TestUtils.java | 116 ++++---- .../src}/test/resources/log4j.properties | 0 {src => core/src}/test/resources/private.key | Bin {src => core/src}/test/resources/public.key | 0 licensor/bin/key-pair-generator | 55 ++++ licensor/bin/license-generator | 55 ++++ licensor/bin/verify-license | 55 ++++ licensor/pom.xml | 191 ++++++++++++ {sample => licensor/sample}/license_spec.json | 0 .../src}/main/assemblies/exec.xml | 2 +- .../license/licensor/LicenseSigner.java | 8 +- .../licensor/tools/KeyPairGeneratorTool.java | 11 +- .../licensor/tools/LicenseGeneratorTool.java | 5 +- .../tools/LicenseVerificationTool.java | 23 +- .../tools/licensor-key-pair-generator.help | 0 .../tools/licensor-license-generator.help | 4 +- .../tools/licensor-verify-license.help | 4 +- .../licensor/AbstractLicensingTestBase.java | 92 ++++++ .../licensor}/LicenseVerificationTests.java | 27 +- .../license/licensor/TestUtils.java | 201 +++++++++++++ .../tools/KeyPairGenerationToolTests.java | 3 +- .../tools/LicenseGenerationToolTests.java | 57 ++-- .../tools/LicenseVerificationToolTests.java | 61 +++- licensor/src/test/resources/log4j.properties | 11 + licensor/src/test/resources/private.key | Bin 0 -> 1232 bytes licensor/src/test/resources/public.key | 3 + plugin/pom.xml | 277 ++++++++++++++++++ .../src}/main/assemblies/plugin.xml | 0 .../license/plugin/LicenseModule.java | 0 .../license/plugin/LicensePlugin.java | 0 .../action/delete/DeleteLicenseAction.java | 0 .../action/delete/DeleteLicenseRequest.java | 0 .../delete/DeleteLicenseRequestBuilder.java | 0 .../action/delete/DeleteLicenseResponse.java | 0 .../delete/TransportDeleteLicenseAction.java | 0 .../plugin/action/get/GetLicenseAction.java | 0 .../plugin/action/get/GetLicenseRequest.java | 0 .../action/get/GetLicenseRequestBuilder.java | 0 .../plugin/action/get/GetLicenseResponse.java | 0 .../action/get/TransportGetLicenseAction.java | 0 .../plugin/action/put/PutLicenseAction.java | 0 .../plugin/action/put/PutLicenseRequest.java | 0 .../action/put/PutLicenseRequestBuilder.java | 0 .../plugin/action/put/PutLicenseResponse.java | 0 .../action/put/TransportPutLicenseAction.java | 0 .../plugin/core/LicenseExpiredException.java | 0 .../plugin/core/LicensesClientService.java | 0 .../plugin/core/LicensesManagerService.java | 2 +- .../license/plugin/core/LicensesMetaData.java | 5 +- .../license/plugin/core/LicensesService.java | 43 ++- .../license/plugin/core/LicensesStatus.java | 0 .../plugin/core/TrialLicenseUtils.java | 7 +- .../plugin/rest/RestDeleteLicenseAction.java | 0 .../plugin/rest/RestGetLicenseAction.java | 4 + .../plugin/rest/RestPutLicenseAction.java | 0 .../src}/main/resources/es-plugin.properties | 0 ...icensesConsumerPluginIntegrationTests.java | 5 +- .../AbstractLicensesIntegrationTests.java | 18 +- .../plugin/AbstractLicensesServiceTests.java | 0 .../plugin/LicensesClientServiceTests.java | 2 +- ...esEagerConsumerPluginIntegrationTests.java | 2 +- ...sesLazyConsumerPluginIntegrationTests.java | 0 .../plugin/LicensesManagerServiceTests.java | 3 +- .../LicensesMetaDataSerializationTests.java | 11 +- .../LicensesPluginIntegrationTests.java | 0 .../LicensesPluginsIntegrationTests.java | 14 +- .../plugin/LicensesServiceClusterTest.java | 3 +- .../plugin/LicensesServiceNodeTests.java | 2 +- .../plugin/LicensesTransportTests.java | 4 +- .../license/plugin}/TestUtils.java | 2 +- .../TrailLicenseSerializationTests.java | 6 +- ...agerLicenseRegistrationConsumerPlugin.java | 2 +- ...EagerLicenseRegistrationPluginService.java | 0 ...LazyLicenseRegistrationConsumerPlugin.java | 2 +- .../LazyLicenseRegistrationPluginService.java | 0 .../consumer/TestConsumerPluginBase.java | 0 .../consumer/TestPluginServiceBase.java | 2 +- plugin/src/test/resources/log4j.properties | 11 + plugin/src/test/resources/private.key | Bin 0 -> 1232 bytes plugin/src/test/resources/public.key | 3 + pom.xml | 220 +++++++------- test-signatures.txt | 0 92 files changed, 1694 insertions(+), 338 deletions(-) create mode 100644 all-signatures.txt create mode 100644 core-shaded/pom.xml rename {src/main/java/org/elasticsearch/license/core => core-shaded/src/main/java/org/elasticsearch/license/core/shaded}/CryptUtils.java (99%) create mode 100644 core-signatures.txt create mode 100644 core/pom.xml rename {src => core/src}/main/java/org/elasticsearch/license/core/DateUtils.java (100%) rename {src => core/src}/main/java/org/elasticsearch/license/core/License.java (95%) rename {src => core/src}/main/java/org/elasticsearch/license/core/LicenseVerifier.java (58%) rename {src => core/src}/main/java/org/elasticsearch/license/core/Licenses.java (80%) rename {src/test/java/org/elasticsearch/license => core/src/test/java/org/elasticsearch/license/core}/LicenseSerializationTests.java (62%) rename src/test/java/org/elasticsearch/license/AbstractLicensingTestBase.java => core/src/test/java/org/elasticsearch/license/core/TestUtils.java (70%) rename {src => core/src}/test/resources/log4j.properties (100%) rename {src => core/src}/test/resources/private.key (100%) rename {src => core/src}/test/resources/public.key (100%) create mode 100755 licensor/bin/key-pair-generator create mode 100755 licensor/bin/license-generator create mode 100755 licensor/bin/verify-license create mode 100644 licensor/pom.xml rename {sample => licensor/sample}/license_spec.json (100%) rename {src => licensor/src}/main/assemblies/exec.xml (98%) rename {src => licensor/src}/main/java/org/elasticsearch/license/licensor/LicenseSigner.java (94%) rename {src => licensor/src}/main/java/org/elasticsearch/license/licensor/tools/KeyPairGeneratorTool.java (90%) rename {src => licensor/src}/main/java/org/elasticsearch/license/licensor/tools/LicenseGeneratorTool.java (95%) rename {src => licensor/src}/main/java/org/elasticsearch/license/licensor/tools/LicenseVerificationTool.java (84%) rename src/main/resources/org/elasticsearch/license/licensor/tools/key-pair-generator.help => licensor/src/main/resources/org/elasticsearch/license/licensor/tools/licensor-key-pair-generator.help (100%) rename src/main/resources/org/elasticsearch/license/licensor/tools/license-generator.help => licensor/src/main/resources/org/elasticsearch/license/licensor/tools/licensor-license-generator.help (79%) rename src/main/resources/org/elasticsearch/license/licensor/tools/verify-license.help => licensor/src/main/resources/org/elasticsearch/license/licensor/tools/licensor-verify-license.help (87%) create mode 100644 licensor/src/test/java/org/elasticsearch/license/licensor/AbstractLicensingTestBase.java rename {src/test/java/org/elasticsearch/license => licensor/src/test/java/org/elasticsearch/license/licensor}/LicenseVerificationTests.java (62%) create mode 100644 licensor/src/test/java/org/elasticsearch/license/licensor/TestUtils.java rename {src/test/java/org/elasticsearch/license => licensor/src/test/java/org/elasticsearch/license/licensor}/tools/KeyPairGenerationToolTests.java (97%) rename {src/test/java/org/elasticsearch/license => licensor/src/test/java/org/elasticsearch/license/licensor}/tools/LicenseGenerationToolTests.java (75%) rename {src/test/java/org/elasticsearch/license => licensor/src/test/java/org/elasticsearch/license/licensor}/tools/LicenseVerificationToolTests.java (71%) create mode 100644 licensor/src/test/resources/log4j.properties create mode 100644 licensor/src/test/resources/private.key create mode 100644 licensor/src/test/resources/public.key create mode 100644 plugin/pom.xml rename {src => plugin/src}/main/assemblies/plugin.xml (100%) rename {src => plugin/src}/main/java/org/elasticsearch/license/plugin/LicenseModule.java (100%) rename {src => plugin/src}/main/java/org/elasticsearch/license/plugin/LicensePlugin.java (100%) rename {src => plugin/src}/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseAction.java (100%) rename {src => plugin/src}/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseRequest.java (100%) rename {src => plugin/src}/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseRequestBuilder.java (100%) rename {src => plugin/src}/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseResponse.java (100%) rename {src => plugin/src}/main/java/org/elasticsearch/license/plugin/action/delete/TransportDeleteLicenseAction.java (100%) rename {src => plugin/src}/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseAction.java (100%) rename {src => plugin/src}/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseRequest.java (100%) rename {src => plugin/src}/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseRequestBuilder.java (100%) rename {src => plugin/src}/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseResponse.java (100%) rename {src => plugin/src}/main/java/org/elasticsearch/license/plugin/action/get/TransportGetLicenseAction.java (100%) rename {src => plugin/src}/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseAction.java (100%) rename {src => plugin/src}/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseRequest.java (100%) rename {src => plugin/src}/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseRequestBuilder.java (100%) rename {src => plugin/src}/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseResponse.java (100%) rename {src => plugin/src}/main/java/org/elasticsearch/license/plugin/action/put/TransportPutLicenseAction.java (100%) rename {src => plugin/src}/main/java/org/elasticsearch/license/plugin/core/LicenseExpiredException.java (100%) rename {src => plugin/src}/main/java/org/elasticsearch/license/plugin/core/LicensesClientService.java (100%) rename {src => plugin/src}/main/java/org/elasticsearch/license/plugin/core/LicensesManagerService.java (95%) rename {src => plugin/src}/main/java/org/elasticsearch/license/plugin/core/LicensesMetaData.java (98%) rename {src => plugin/src}/main/java/org/elasticsearch/license/plugin/core/LicensesService.java (95%) rename {src => plugin/src}/main/java/org/elasticsearch/license/plugin/core/LicensesStatus.java (100%) rename {src => plugin/src}/main/java/org/elasticsearch/license/plugin/core/TrialLicenseUtils.java (94%) rename {src => plugin/src}/main/java/org/elasticsearch/license/plugin/rest/RestDeleteLicenseAction.java (100%) rename {src => plugin/src}/main/java/org/elasticsearch/license/plugin/rest/RestGetLicenseAction.java (92%) rename {src => plugin/src}/main/java/org/elasticsearch/license/plugin/rest/RestPutLicenseAction.java (100%) rename {src => plugin/src}/main/resources/es-plugin.properties (100%) rename {src => plugin/src}/test/java/org/elasticsearch/license/plugin/AbstractLicensesConsumerPluginIntegrationTests.java (95%) rename {src => plugin/src}/test/java/org/elasticsearch/license/plugin/AbstractLicensesIntegrationTests.java (89%) rename {src => plugin/src}/test/java/org/elasticsearch/license/plugin/AbstractLicensesServiceTests.java (100%) rename {src => plugin/src}/test/java/org/elasticsearch/license/plugin/LicensesClientServiceTests.java (99%) rename {src => plugin/src}/test/java/org/elasticsearch/license/plugin/LicensesEagerConsumerPluginIntegrationTests.java (87%) rename {src => plugin/src}/test/java/org/elasticsearch/license/plugin/LicensesLazyConsumerPluginIntegrationTests.java (100%) rename {src => plugin/src}/test/java/org/elasticsearch/license/plugin/LicensesManagerServiceTests.java (98%) rename {src => plugin/src}/test/java/org/elasticsearch/license/plugin/LicensesMetaDataSerializationTests.java (95%) rename {src => plugin/src}/test/java/org/elasticsearch/license/plugin/LicensesPluginIntegrationTests.java (100%) rename {src => plugin/src}/test/java/org/elasticsearch/license/plugin/LicensesPluginsIntegrationTests.java (95%) rename {src => plugin/src}/test/java/org/elasticsearch/license/plugin/LicensesServiceClusterTest.java (98%) rename {src => plugin/src}/test/java/org/elasticsearch/license/plugin/LicensesServiceNodeTests.java (97%) rename {src => plugin/src}/test/java/org/elasticsearch/license/plugin/LicensesTransportTests.java (98%) rename {src/test/java/org/elasticsearch/license => plugin/src/test/java/org/elasticsearch/license/plugin}/TestUtils.java (99%) rename {src => plugin/src}/test/java/org/elasticsearch/license/plugin/TrailLicenseSerializationTests.java (84%) rename {src => plugin/src}/test/java/org/elasticsearch/license/plugin/consumer/EagerLicenseRegistrationConsumerPlugin.java (92%) rename {src => plugin/src}/test/java/org/elasticsearch/license/plugin/consumer/EagerLicenseRegistrationPluginService.java (100%) rename {src => plugin/src}/test/java/org/elasticsearch/license/plugin/consumer/LazyLicenseRegistrationConsumerPlugin.java (92%) rename {src => plugin/src}/test/java/org/elasticsearch/license/plugin/consumer/LazyLicenseRegistrationPluginService.java (100%) rename {src => plugin/src}/test/java/org/elasticsearch/license/plugin/consumer/TestConsumerPluginBase.java (100%) rename {src => plugin/src}/test/java/org/elasticsearch/license/plugin/consumer/TestPluginServiceBase.java (98%) create mode 100644 plugin/src/test/resources/log4j.properties create mode 100644 plugin/src/test/resources/private.key create mode 100644 plugin/src/test/resources/public.key create mode 100644 test-signatures.txt diff --git a/all-signatures.txt b/all-signatures.txt new file mode 100644 index 00000000000..5f13cea4af7 --- /dev/null +++ b/all-signatures.txt @@ -0,0 +1,3 @@ +@defaultMessage Convert to URI +java.net.URL#getPath() +java.net.URL#getFile() diff --git a/core-shaded/pom.xml b/core-shaded/pom.xml new file mode 100644 index 00000000000..6be3c61bda4 --- /dev/null +++ b/core-shaded/pom.xml @@ -0,0 +1,17 @@ + + + + elasticsearch-license + org.elasticsearch + 1.0.0-SNAPSHOT + + 4.0.0 + + elasticsearch-license-core-shaded + + + ${project.parent.basedir} + + \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/license/core/CryptUtils.java b/core-shaded/src/main/java/org/elasticsearch/license/core/shaded/CryptUtils.java similarity index 99% rename from src/main/java/org/elasticsearch/license/core/CryptUtils.java rename to core-shaded/src/main/java/org/elasticsearch/license/core/shaded/CryptUtils.java index 939b5192828..854bda0c3b3 100644 --- a/src/main/java/org/elasticsearch/license/core/CryptUtils.java +++ b/core-shaded/src/main/java/org/elasticsearch/license/core/shaded/CryptUtils.java @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.license.core; +package org.elasticsearch.license.core.shaded; import org.elasticsearch.common.Base64; diff --git a/core-signatures.txt b/core-signatures.txt new file mode 100644 index 00000000000..c79b58a227c --- /dev/null +++ b/core-signatures.txt @@ -0,0 +1,65 @@ +@defaultMessage spawns threads with vague names; use a custom thread factory and name threads so that you can tell (by its name) which executor it is associated with + +java.util.concurrent.Executors#newFixedThreadPool(int) +java.util.concurrent.Executors#newSingleThreadExecutor() +java.util.concurrent.Executors#newCachedThreadPool() +java.util.concurrent.Executors#newSingleThreadScheduledExecutor() +java.util.concurrent.Executors#newScheduledThreadPool(int) +java.util.concurrent.Executors#defaultThreadFactory() +java.util.concurrent.Executors#privilegedThreadFactory() + +java.lang.Character#codePointBefore(char[],int) @ Implicit start offset is error-prone when the char[] is a buffer and the first chars are random chars +java.lang.Character#codePointAt(char[],int) @ Implicit end offset is error-prone when the char[] is a buffer and the last chars are random chars + +@defaultMessage Collections.sort dumps data into an array, sorts the array and reinserts data into the list, one should rather use Lucene's CollectionUtil sort methods which sort in place + +java.util.Collections#sort(java.util.List) +java.util.Collections#sort(java.util.List,java.util.Comparator) + +java.io.StringReader#(java.lang.String) @ Use FastStringReader instead + +@defaultMessage Reference management is tricky, leave it to SearcherManager +org.apache.lucene.index.IndexReader#decRef() +org.apache.lucene.index.IndexReader#incRef() +org.apache.lucene.index.IndexReader#tryIncRef() + +@defaultMessage QueryWrapperFilter is cachable by default - use Queries#wrap instead +org.apache.lucene.search.QueryWrapperFilter#(org.apache.lucene.search.Query) + +@defaultMessage Because the filtercache doesn't take deletes into account FilteredQuery can't be used - use XFilteredQuery instead +org.apache.lucene.search.FilteredQuery#(org.apache.lucene.search.Query,org.apache.lucene.search.Filter) +org.apache.lucene.search.FilteredQuery#(org.apache.lucene.search.Query,org.apache.lucene.search.Filter,org.apache.lucene.search.FilteredQuery$FilterStrategy) + +@defaultMessage Pass the precision step from the mappings explicitly instead +org.apache.lucene.search.NumericRangeQuery#newDoubleRange(java.lang.String,java.lang.Double,java.lang.Double,boolean,boolean) +org.apache.lucene.search.NumericRangeQuery#newFloatRange(java.lang.String,java.lang.Float,java.lang.Float,boolean,boolean) +org.apache.lucene.search.NumericRangeQuery#newIntRange(java.lang.String,java.lang.Integer,java.lang.Integer,boolean,boolean) +org.apache.lucene.search.NumericRangeQuery#newLongRange(java.lang.String,java.lang.Long,java.lang.Long,boolean,boolean) +org.apache.lucene.search.NumericRangeFilter#newDoubleRange(java.lang.String,java.lang.Double,java.lang.Double,boolean,boolean) +org.apache.lucene.search.NumericRangeFilter#newFloatRange(java.lang.String,java.lang.Float,java.lang.Float,boolean,boolean) +org.apache.lucene.search.NumericRangeFilter#newIntRange(java.lang.String,java.lang.Integer,java.lang.Integer,boolean,boolean) +org.apache.lucene.search.NumericRangeFilter#newLongRange(java.lang.String,java.lang.Long,java.lang.Long,boolean,boolean) + +@defaultMessage Only use wait / notify when really needed try to use concurrency primitives, latches or callbacks instead. +java.lang.Object#wait() +java.lang.Object#wait(long) +java.lang.Object#wait(long,int) +java.lang.Object#notify() +java.lang.Object#notifyAll() + +@defaultMessage Beware of the behavior of this method on MIN_VALUE +java.lang.Math#abs(int) +java.lang.Math#abs(long) + +@defaultMessage Please do not try to stop the world +java.lang.System#gc() + +@defaultMessage Use Channels.* methods to write to channels. Do not write directly. +java.nio.channels.WritableByteChannel#write(java.nio.ByteBuffer) +java.nio.channels.FileChannel#write(java.nio.ByteBuffer, long) +java.nio.channels.GatheringByteChannel#write(java.nio.ByteBuffer[], int, int) +java.nio.channels.GatheringByteChannel#write(java.nio.ByteBuffer[]) +java.nio.channels.ReadableByteChannel#read(java.nio.ByteBuffer) +java.nio.channels.ScatteringByteChannel#read(java.nio.ByteBuffer[]) +java.nio.channels.ScatteringByteChannel#read(java.nio.ByteBuffer[], int, int) +java.nio.channels.FileChannel#read(java.nio.ByteBuffer, long) diff --git a/core/pom.xml b/core/pom.xml new file mode 100644 index 00000000000..ff0f2322a61 --- /dev/null +++ b/core/pom.xml @@ -0,0 +1,138 @@ + + + + elasticsearch-license + org.elasticsearch + 1.0.0-SNAPSHOT + + 4.0.0 + + ${project.parent.basedir} + + elasticsearch-license-core + + + + org.elasticsearch + elasticsearch-license-core-shaded + 1.0.0-SNAPSHOT + + + + + + com.carrotsearch.randomizedtesting + junit4-maven-plugin + 2.1.2 + + + tests + test + + junit4 + + + ${project.basedir}/target + ${project.basedir}/target/classes + 20 + pipe,warn + true + + + + + + + + + + + ${tests.jvms} + + + + + + + **/*Tests.class + **/*Test.class + + + **/Abstract*.class + **/*StressTest.class + + + -Xmx${tests.heap.size} + -Xms${tests.heap.size} + -Xss256k + -XX:MaxPermSize=128m + -XX:MaxDirectMemorySize=512m + -Des.logger.prefix= + + ${tests.shuffle} + ${tests.verbose} + ${tests.seed} + ${tests.failfast} + false + + . + + + ${tests.bwc} + ${tests.bwc.path} + ${tests.bwc.version} + ${tests.jvm.argline} + ${tests.processors} + ${tests.appendseed} + ${tests.iters} + ${tests.maxfailures} + ${tests.failfast} + ${tests.class} + ${tests.method} + ${tests.nightly} + ${tests.verbose} + ${tests.badapples} + ${tests.weekly} + ${tests.slow} + ${tests.awaitsfix} + ${tests.slow} + ${tests.timeoutSuite} + ${tests.showSuccess} + ${tests.integration} + ${tests.client.ratio} + ${tests.enable_mock_modules} + ${tests.assertion.disabled} + ${tests.rest} + ${tests.rest.suite} + ${tests.rest.blacklist} + ${tests.rest.spec} + ${tests.network} + ${tests.cluster} + ${tests.heap.size} + ${tests.filter} + ${env.ES_TEST_LOCAL} + ${es.node.mode} + ${es.logger.level} + ${tests.security.manager} + ${tests.compatibility} + true + + + + + + + + \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/license/core/DateUtils.java b/core/src/main/java/org/elasticsearch/license/core/DateUtils.java similarity index 100% rename from src/main/java/org/elasticsearch/license/core/DateUtils.java rename to core/src/main/java/org/elasticsearch/license/core/DateUtils.java diff --git a/src/main/java/org/elasticsearch/license/core/License.java b/core/src/main/java/org/elasticsearch/license/core/License.java similarity index 95% rename from src/main/java/org/elasticsearch/license/core/License.java rename to core/src/main/java/org/elasticsearch/license/core/License.java index d3a8874e888..0aa7d2c1857 100644 --- a/src/main/java/org/elasticsearch/license/core/License.java +++ b/core/src/main/java/org/elasticsearch/license/core/License.java @@ -8,10 +8,17 @@ package org.elasticsearch.license.core; import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.common.xcontent.*; +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 { private final String uid; @@ -168,8 +175,13 @@ public class License implements ToXContent { 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) { @@ -188,6 +200,9 @@ public class License implements ToXContent { builder.field(XFields.SIGNATURE, signature); } builder.endObject(); + if (restViewMode) { + builder.humanReadable(previouslyHumanReadable); + } return builder; } diff --git a/src/main/java/org/elasticsearch/license/core/LicenseVerifier.java b/core/src/main/java/org/elasticsearch/license/core/LicenseVerifier.java similarity index 58% rename from src/main/java/org/elasticsearch/license/core/LicenseVerifier.java rename to core/src/main/java/org/elasticsearch/license/core/LicenseVerifier.java index 2a73d86deda..49273fdebf7 100644 --- a/src/main/java/org/elasticsearch/license/core/LicenseVerifier.java +++ b/core/src/main/java/org/elasticsearch/license/core/LicenseVerifier.java @@ -7,32 +7,75 @@ package org.elasticsearch.license.core; import org.elasticsearch.common.Base64; import org.elasticsearch.common.io.Streams; -import org.elasticsearch.common.xcontent.*; +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.shaded.CryptUtils; import java.io.IOException; import java.io.InputStream; 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.*; +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)} + * Verifies Licenses using {@link #verifyLicense(License, byte[])} using the public key from the + * resources */ public static boolean verifyLicenses(final Collection licenses) { - for (License license : licenses) { - if (!verifyLicense(license)) { - return false; + 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); } - return true; } /** @@ -40,16 +83,16 @@ public class LicenseVerifier { * @param license to verify * @return true if valid, false otherwise */ - public static boolean verifyLicense(final License license) { + 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(contentBuilder.bytes().toBytes(), licenseSignature.contentSignature)) { + if(!verifyContent(encryptedPublicKeyData, contentBuilder.bytes().toBytes(), licenseSignature.contentSignature)) { return false; } - final byte[] hash = Base64.encodeBytesToBytes(getPublicKeyContent("/public.key")); + final byte[] hash = Base64.encodeBytesToBytes(encryptedPublicKeyData); return Arrays.equals(hash, licenseSignature.hash); } catch (IOException e) { throw new IllegalStateException(e); @@ -60,10 +103,10 @@ public class LicenseVerifier { } } - private static boolean verifyContent(byte[] data, byte[] contentSignature) { + private static boolean verifyContent(byte[] encryptedPublicKeyData, byte[] data, byte[] contentSignature) { try { Signature rsa = Signature.getInstance("SHA512withRSA"); - rsa.initVerify(CryptUtils.readEncryptedPublicKey(getPublicKeyContent("/public.key"))); + rsa.initVerify(CryptUtils.readEncryptedPublicKey(encryptedPublicKeyData)); rsa.update(data); return rsa.verify(contentSignature); } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) { @@ -71,7 +114,7 @@ public class LicenseVerifier { } } - private static byte[] getPublicKeyContent(String resource) { + private static byte[] getPublicKeyContentFromResource(String resource) { try (InputStream inputStream = LicenseVerifier.class.getResourceAsStream(resource)) { return Streams.copyToByteArray(inputStream); } catch (IOException ex) { diff --git a/src/main/java/org/elasticsearch/license/core/Licenses.java b/core/src/main/java/org/elasticsearch/license/core/Licenses.java similarity index 80% rename from src/main/java/org/elasticsearch/license/core/Licenses.java rename to core/src/main/java/org/elasticsearch/license/core/Licenses.java index adeedebb4c5..d4076be380d 100644 --- a/src/main/java/org/elasticsearch/license/core/Licenses.java +++ b/core/src/main/java/org/elasticsearch/license/core/Licenses.java @@ -15,9 +15,25 @@ 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 { @@ -96,6 +112,13 @@ public final class Licenses { } } + /** + * 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) { @@ -104,6 +127,14 @@ public final class Licenses { 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)) { diff --git a/src/test/java/org/elasticsearch/license/LicenseSerializationTests.java b/core/src/test/java/org/elasticsearch/license/core/LicenseSerializationTests.java similarity index 62% rename from src/test/java/org/elasticsearch/license/LicenseSerializationTests.java rename to core/src/test/java/org/elasticsearch/license/core/LicenseSerializationTests.java index cea6fd7d8b4..ca0973ca16d 100644 --- a/src/test/java/org/elasticsearch/license/LicenseSerializationTests.java +++ b/core/src/test/java/org/elasticsearch/license/core/LicenseSerializationTests.java @@ -3,33 +3,28 @@ * 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; +package org.elasticsearch.license.core; import org.elasticsearch.common.collect.ImmutableMap; import org.elasticsearch.common.xcontent.*; -import org.elasticsearch.license.AbstractLicensingTestBase; -import org.elasticsearch.license.core.DateUtils; -import org.elasticsearch.license.core.License; -import org.elasticsearch.license.core.Licenses; +import org.elasticsearch.test.ElasticsearchTestCase; import org.junit.Test; import java.nio.charset.StandardCharsets; import java.util.*; -import static com.carrotsearch.randomizedtesting.RandomizedTest.randomIntBetween; import static org.hamcrest.core.IsEqual.equalTo; import static org.hamcrest.core.IsNull.notNullValue; import static org.hamcrest.core.IsNull.nullValue; -import static org.junit.Assert.assertThat; -public class LicenseSerializationTests extends AbstractLicensingTestBase { +public class LicenseSerializationTests extends ElasticsearchTestCase { @Test public void testSimpleIssueExpiryDate() throws Exception { long now = System.currentTimeMillis(); - String issueDate = dateMathString("now", now); - String expiryDate = dateMathString("now+10d/d", now); - String licenseSpecs = generateLicenseSpecString(Arrays.asList(new LicenseSpec("shield", issueDate, expiryDate))); + 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(); @@ -41,12 +36,12 @@ public class LicenseSerializationTests extends AbstractLicensingTestBase { @Test public void testMultipleIssueExpiryDate() throws Exception { long now = System.currentTimeMillis(); - String shieldIssueDate = dateMathString("now", now); - String shieldExpiryDate = dateMathString("now+30d/d", now); - String marvelIssueDate = dateMathString("now", now); - String marvelExpiryDate = dateMathString("now+60d/d", now); - String licenseSpecs = generateLicenseSpecString(Arrays.asList(new LicenseSpec("shield", shieldIssueDate, shieldExpiryDate))); - String licenseSpecs1 = generateLicenseSpecString(Arrays.asList(new LicenseSpec("marvel", marvelIssueDate, marvelExpiryDate))); + 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)); @@ -59,32 +54,33 @@ public class LicenseSerializationTests extends AbstractLicensingTestBase { @Test public void testLicensesFields() throws Exception { - Map licenseSpecs = new HashMap<>(); + Map licenseSpecs = new HashMap<>(); for (int i = 0; i < randomIntBetween(1, 5); i++) { - LicenseSpec randomLicenseSpec = generateRandomLicenseSpec(); + TestUtils.LicenseSpec randomLicenseSpec = TestUtils.generateRandomLicenseSpec(); licenseSpecs.put(randomLicenseSpec.feature, randomLicenseSpec); } - ArrayList specs = new ArrayList<>(licenseSpecs.values()); - String licenseSpecsSource = generateLicenseSpecString(specs); + 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) { - LicenseSpec spec = licenseSpecs.get(license.feature()); + TestUtils.LicenseSpec spec = licenseSpecs.get(license.feature()); assertThat(spec, notNullValue()); - assertLicenseSpec(spec, license); + TestUtils.assertLicenseSpec(spec, license); } } @Test public void testLicenseRestView() throws Exception { long now = System.currentTimeMillis(); - String expiredLicenseExpiryDate = dateMathString("now-1d/d", now); - String validLicenseIssueDate = dateMathString("now-10d/d", now); - String validLicenseExpiryDate = dateMathString("now+1d/d", now); - Set licenses = generateSignedLicenses(Arrays.asList(new LicenseSpec("expired_feature", validLicenseIssueDate, expiredLicenseExpiryDate) - , new LicenseSpec("valid_feature", validLicenseIssueDate, validLicenseExpiryDate))); + String expiredLicenseExpiryDate = TestUtils.dateMathString("now-1d/d", now); + String validLicenseIssueDate = TestUtils.dateMathString("now-10d/d", now); + String validLicenseExpiryDate = TestUtils.dateMathString("now+1d/d", now); + + Set licenses = TestUtils.generateLicenses(Arrays.asList(new TestUtils.LicenseSpec("expired_feature", validLicenseIssueDate, expiredLicenseExpiryDate) + , new TestUtils.LicenseSpec("valid_feature", validLicenseIssueDate, validLicenseExpiryDate))); assertThat(licenses.size(), equalTo(2)); for (License license : licenses) { @@ -92,7 +88,11 @@ public class LicenseSerializationTests extends AbstractLicensingTestBase { 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 { diff --git a/src/test/java/org/elasticsearch/license/AbstractLicensingTestBase.java b/core/src/test/java/org/elasticsearch/license/core/TestUtils.java similarity index 70% rename from src/test/java/org/elasticsearch/license/AbstractLicensingTestBase.java rename to core/src/test/java/org/elasticsearch/license/core/TestUtils.java index 4e3a8b61216..1aa1ed50e4b 100644 --- a/src/test/java/org/elasticsearch/license/AbstractLicensingTestBase.java +++ b/core/src/test/java/org/elasticsearch/license/core/TestUtils.java @@ -3,50 +3,60 @@ * 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; +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.unit.TimeValue; +import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.license.core.DateUtils; -import org.elasticsearch.license.core.License; -import org.elasticsearch.license.licensor.LicenseSigner; -import org.elasticsearch.license.core.LicenseVerifier; -import org.junit.BeforeClass; -import org.junit.runner.RunWith; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentType; +import org.hamcrest.MatcherAssert; import java.io.IOException; -import java.net.URL; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.UUID; +import java.util.*; import java.util.concurrent.TimeUnit; -import static com.carrotsearch.randomizedtesting.RandomizedTest.randomBoolean; -import static com.carrotsearch.randomizedtesting.RandomizedTest.randomInt; -import static com.carrotsearch.randomizedtesting.RandomizedTest.randomIntBetween; +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.MatcherAssert.assertThat; import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.assertThat; -@RunWith(value = com.carrotsearch.randomizedtesting.RandomizedRunner.class) -public abstract class AbstractLicensingTestBase { - - protected static String pubKeyPath = null; - protected static String priKeyPath = null; +public class TestUtils { private final static FormatDateTimeFormatter formatDateTimeFormatter = Joda.forPattern("yyyy-MM-dd"); - private final static org.elasticsearch.common.joda.time.format.DateTimeFormatter dateTimeFormatter = formatDateTimeFormatter.printer(); private final static DateMathParser dateMathParser = new DateMathParser(formatDateTimeFormatter, TimeUnit.MILLISECONDS); + private final static org.elasticsearch.common.joda.time.format.DateTimeFormatter dateTimeFormatter = formatDateTimeFormatter.printer(); - @BeforeClass - public static void setup() throws Exception { - pubKeyPath = getResourcePath("/public.key"); - priKeyPath = getResourcePath("/private.key"); + 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, long now) { @@ -57,11 +67,6 @@ public abstract class AbstractLicensingTestBase { return dateMathParser.parse(time, now); } - public static String getResourcePath(String resource) throws Exception { - URL url = LicenseVerifier.class.getResource(resource); - return url.toURI().getPath(); - } - public static LicenseSpec generateRandomLicenseSpec() { boolean datesInMillis = randomBoolean(); long now = System.currentTimeMillis(); @@ -114,10 +119,9 @@ public abstract class AbstractLicensingTestBase { return licenses.string(); } - public static Set generateSignedLicenses(List licenseSpecs) throws Exception { - LicenseSigner signer = new LicenseSigner(priKeyPath, pubKeyPath); + public static Set generateLicenses(List licenseSpecs) { Set unSignedLicenses = new HashSet<>(); - for (LicenseSpec spec : licenseSpecs) { + for (TestUtils.LicenseSpec spec : licenseSpecs) { License.Builder builder = License.builder() .uid(spec.uid) .feature(spec.feature) @@ -139,7 +143,27 @@ public abstract class AbstractLicensingTestBase { } unSignedLicenses.add(builder.build()); } - return signer.sign(unSignedLicenses); + 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 { @@ -189,24 +213,4 @@ public abstract class AbstractLicensingTestBase { this.maxNodes = maxNodes; } } - - public static void assertLicenseSpec(LicenseSpec spec, License license) { - assertThat(license.uid(), equalTo(spec.uid)); - assertThat(license.feature(), equalTo(spec.feature)); - assertThat(license.issuedTo(), equalTo(spec.issuedTo)); - assertThat(license.issuer(), equalTo(spec.issuer)); - assertThat(license.type(), equalTo(spec.type)); - assertThat(license.subscriptionType(), equalTo(spec.subscriptionType)); - assertThat(license.maxNodes(), equalTo(spec.maxNodes)); - if (spec.issueDate != null) { - assertThat(license.issueDate(), equalTo(DateUtils.beginningOfTheDay(spec.issueDate))); - } else { - assertThat(license.issueDate(), equalTo(spec.issueDateInMillis)); - } - if (spec.expiryDate != null) { - assertThat(license.expiryDate(), equalTo(DateUtils.endOfTheDay(spec.expiryDate))); - } else { - assertThat(license.expiryDate(), equalTo(spec.expiryDateInMillis)); - } - } } diff --git a/src/test/resources/log4j.properties b/core/src/test/resources/log4j.properties similarity index 100% rename from src/test/resources/log4j.properties rename to core/src/test/resources/log4j.properties diff --git a/src/test/resources/private.key b/core/src/test/resources/private.key similarity index 100% rename from src/test/resources/private.key rename to core/src/test/resources/private.key diff --git a/src/test/resources/public.key b/core/src/test/resources/public.key similarity index 100% rename from src/test/resources/public.key rename to core/src/test/resources/public.key diff --git a/licensor/bin/key-pair-generator b/licensor/bin/key-pair-generator new file mode 100755 index 00000000000..4a72e028ab4 --- /dev/null +++ b/licensor/bin/key-pair-generator @@ -0,0 +1,55 @@ +#!/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 new file mode 100755 index 00000000000..97c8ae9631c --- /dev/null +++ b/licensor/bin/license-generator @@ -0,0 +1,55 @@ +#!/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 new file mode 100755 index 00000000000..492e3b75bb3 --- /dev/null +++ b/licensor/bin/verify-license @@ -0,0 +1,55 @@ +#!/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 new file mode 100644 index 00000000000..b2a4e328367 --- /dev/null +++ b/licensor/pom.xml @@ -0,0 +1,191 @@ + + + + elasticsearch-license + org.elasticsearch + 1.0.0-SNAPSHOT + + 4.0.0 + + elasticsearch-license-licensor + + + ${project.parent.basedir} + + + + + org.elasticsearch + elasticsearch-license-core + 1.0.0-SNAPSHOT + + + + + + + src/main/resources + true + + + + + + maven-assembly-plugin + 2.4 + + ${project.build.directory}/releases/ + + + + exec + package + + single + + + true + + ${basedir}/src/main/assemblies/exec.xml + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.4 + + + for-exec + prepare-package + + jar + + + exec + + + public.key + + + + + + + com.carrotsearch.randomizedtesting + junit4-maven-plugin + 2.1.2 + + + tests + test + + junit4 + + + ${project.basedir}/target + ${project.basedir}/target/classes + 20 + pipe,warn + true + + + + + + + + + + + ${tests.jvms} + + + + + + + **/*Tests.class + **/*Test.class + + + **/Abstract*.class + **/*StressTest.class + + + -Xmx${tests.heap.size} + -Xms${tests.heap.size} + -Xss256k + -XX:MaxPermSize=128m + -XX:MaxDirectMemorySize=512m + -Des.logger.prefix= + + ${tests.shuffle} + ${tests.verbose} + ${tests.seed} + ${tests.failfast} + false + + . + + + ${tests.bwc} + ${tests.bwc.path} + ${tests.bwc.version} + ${tests.jvm.argline} + ${tests.processors} + ${tests.appendseed} + ${tests.iters} + ${tests.maxfailures} + ${tests.failfast} + ${tests.class} + ${tests.method} + ${tests.nightly} + ${tests.verbose} + ${tests.badapples} + ${tests.weekly} + ${tests.slow} + ${tests.awaitsfix} + ${tests.slow} + ${tests.timeoutSuite} + ${tests.showSuccess} + ${tests.integration} + ${tests.client.ratio} + ${tests.enable_mock_modules} + ${tests.assertion.disabled} + ${tests.rest} + ${tests.rest.suite} + ${tests.rest.blacklist} + ${tests.rest.spec} + ${tests.network} + ${tests.cluster} + ${tests.heap.size} + ${tests.filter} + ${env.ES_TEST_LOCAL} + ${es.node.mode} + ${es.logger.level} + ${tests.security.manager} + ${tests.compatibility} + true + + + + + + + + \ No newline at end of file diff --git a/sample/license_spec.json b/licensor/sample/license_spec.json similarity index 100% rename from sample/license_spec.json rename to licensor/sample/license_spec.json diff --git a/src/main/assemblies/exec.xml b/licensor/src/main/assemblies/exec.xml similarity index 98% rename from src/main/assemblies/exec.xml rename to licensor/src/main/assemblies/exec.xml index 006a1d331a7..7eb1e0d1549 100644 --- a/src/main/assemblies/exec.xml +++ b/licensor/src/main/assemblies/exec.xml @@ -27,7 +27,7 @@ true true - org.elasticsearch:elasticsearch-license:*:exec + org.elasticsearch:elasticsearch-license-licensor:*:exec org.elasticsearch:elasticsearch diff --git a/src/main/java/org/elasticsearch/license/licensor/LicenseSigner.java b/licensor/src/main/java/org/elasticsearch/license/licensor/LicenseSigner.java similarity index 94% rename from src/main/java/org/elasticsearch/license/licensor/LicenseSigner.java rename to licensor/src/main/java/org/elasticsearch/license/licensor/LicenseSigner.java index f97511e7be1..10f6ee80169 100644 --- a/src/main/java/org/elasticsearch/license/licensor/LicenseSigner.java +++ b/licensor/src/main/java/org/elasticsearch/license/licensor/LicenseSigner.java @@ -13,7 +13,7 @@ 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 org.elasticsearch.license.core.shaded.CryptUtils; import java.io.IOException; import java.nio.ByteBuffer; @@ -24,6 +24,10 @@ 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 + */ public class LicenseSigner { private final static int VERSION_START = 0; @@ -59,7 +63,7 @@ public class LicenseSigner { * | VERSION | MAGIC | PUB_KEY_DIGEST | SIGNED_LICENSE_CONTENT | * * @return a signed License - * @throws IOException + * @throws java.io.IOException */ public License sign(License licenseSpec) throws IOException { XContentBuilder contentBuilder = XContentFactory.contentBuilder(XContentType.JSON); diff --git a/src/main/java/org/elasticsearch/license/licensor/tools/KeyPairGeneratorTool.java b/licensor/src/main/java/org/elasticsearch/license/licensor/tools/KeyPairGeneratorTool.java similarity index 90% rename from src/main/java/org/elasticsearch/license/licensor/tools/KeyPairGeneratorTool.java rename to licensor/src/main/java/org/elasticsearch/license/licensor/tools/KeyPairGeneratorTool.java index 92ff1cbf73a..1e3334fc95c 100644 --- a/src/main/java/org/elasticsearch/license/licensor/tools/KeyPairGeneratorTool.java +++ b/licensor/src/main/java/org/elasticsearch/license/licensor/tools/KeyPairGeneratorTool.java @@ -16,18 +16,21 @@ import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; -import java.security.*; +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; +import static org.elasticsearch.license.core.shaded.CryptUtils.writeEncryptedPrivateKey; +import static org.elasticsearch.license.core.shaded.CryptUtils.writeEncryptedPublicKey; public class KeyPairGeneratorTool extends CliTool { public static final String NAME = "key-pair-generator"; - private static final CliToolConfig CONFIG = config(NAME, KeyPairGeneratorTool.class) + private static final CliToolConfig CONFIG = config("licensor", KeyPairGeneratorTool.class) .cmds(KeyGenerator.CMD) .build(); diff --git a/src/main/java/org/elasticsearch/license/licensor/tools/LicenseGeneratorTool.java b/licensor/src/main/java/org/elasticsearch/license/licensor/tools/LicenseGeneratorTool.java similarity index 95% rename from src/main/java/org/elasticsearch/license/licensor/tools/LicenseGeneratorTool.java rename to licensor/src/main/java/org/elasticsearch/license/licensor/tools/LicenseGeneratorTool.java index e64f3c473ed..8943896e19c 100644 --- a/src/main/java/org/elasticsearch/license/licensor/tools/LicenseGeneratorTool.java +++ b/licensor/src/main/java/org/elasticsearch/license/licensor/tools/LicenseGeneratorTool.java @@ -36,7 +36,7 @@ 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(NAME, LicenseGeneratorTool.class) + private static final CliToolConfig CONFIG = config("licensor", LicenseGeneratorTool.class) .cmds(LicenseGenerator.CMD) .build(); @@ -109,8 +109,7 @@ public class LicenseGeneratorTool extends CliTool { public ExitStatus execute(Settings settings, Environment env) throws Exception { // sign - LicenseSigner signer = new LicenseSigner(privateKeyFilePath, publicKeyFilePath); - ImmutableSet signedLicences = signer.sign(licenseSpecs); + ImmutableSet signedLicences = new LicenseSigner(privateKeyFilePath, publicKeyFilePath).sign(licenseSpecs); // dump XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON); diff --git a/src/main/java/org/elasticsearch/license/licensor/tools/LicenseVerificationTool.java b/licensor/src/main/java/org/elasticsearch/license/licensor/tools/LicenseVerificationTool.java similarity index 84% rename from src/main/java/org/elasticsearch/license/licensor/tools/LicenseVerificationTool.java rename to licensor/src/main/java/org/elasticsearch/license/licensor/tools/LicenseVerificationTool.java index 8e781966f84..53fbb40d785 100644 --- a/src/main/java/org/elasticsearch/license/licensor/tools/LicenseVerificationTool.java +++ b/licensor/src/main/java/org/elasticsearch/license/licensor/tools/LicenseVerificationTool.java @@ -36,8 +36,8 @@ 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(NAME, LicenseVerificationTool.class) - .cmds(LicenseVerificationTool.LicenseVerifier.CMD) + private static final CliToolConfig CONFIG = config("licensor", LicenseVerificationTool.class) + .cmds(LicenseVerifier.CMD) .build(); public LicenseVerificationTool() { @@ -46,25 +46,29 @@ public class LicenseVerificationTool extends CliTool { @Override protected Command parse(String s, CommandLine commandLine) throws Exception { - return LicenseVerificationTool.LicenseVerifier.parse(terminal, commandLine); + return LicenseVerifier.parse(terminal, commandLine); } 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) { + public LicenseVerifier(Terminal terminal, Set licenses, Path publicKeyPath) { super(terminal); this.licenses = licenses; + this.publicKeyPath = publicKeyPath; } public static Command parse(Terminal terminal, CommandLine commandLine) throws IOException { + String publicKeyPath = commandLine.getOptionValue("publicKeyPath"); String[] licenseSources = commandLine.getOptionValues("license"); String[] licenseSourceFiles = commandLine.getOptionValues("licenseFile"); @@ -88,7 +92,12 @@ public class LicenseVerificationTool extends CliTool { if (licenses.size() == 0) { return exitCmd(ExitStatus.USAGE, terminal, "no license provided"); } - return new LicenseVerifier(terminal, licenses); + + if (!exists(publicKeyPath)) { + return exitCmd(ExitStatus.USAGE, terminal, publicKeyPath + " does not exist"); + } + + return new LicenseVerifier(terminal, licenses, Paths.get(publicKeyPath)); } @Override @@ -96,9 +105,9 @@ public class LicenseVerificationTool extends CliTool { // verify Map effectiveLicenses = Licenses.reduceAndMap(licenses); - org.elasticsearch.license.core.LicenseVerifier licenseVerifier = new org.elasticsearch.license.core.LicenseVerifier(); - if (!org.elasticsearch.license.core.LicenseVerifier.verifyLicenses(effectiveLicenses.values())) { + if (!org.elasticsearch.license.core.LicenseVerifier.verifyLicenses(effectiveLicenses.values(), publicKeyPath)) { + terminal.println("Invalid License(s)!"); return ExitStatus.DATA_ERROR; } diff --git a/src/main/resources/org/elasticsearch/license/licensor/tools/key-pair-generator.help b/licensor/src/main/resources/org/elasticsearch/license/licensor/tools/licensor-key-pair-generator.help similarity index 100% rename from src/main/resources/org/elasticsearch/license/licensor/tools/key-pair-generator.help rename to licensor/src/main/resources/org/elasticsearch/license/licensor/tools/licensor-key-pair-generator.help diff --git a/src/main/resources/org/elasticsearch/license/licensor/tools/license-generator.help b/licensor/src/main/resources/org/elasticsearch/license/licensor/tools/licensor-license-generator.help similarity index 79% rename from src/main/resources/org/elasticsearch/license/licensor/tools/license-generator.help rename to licensor/src/main/resources/org/elasticsearch/license/licensor/tools/licensor-license-generator.help index 022c88f155d..75d507f7dd9 100644 --- a/src/main/resources/org/elasticsearch/license/licensor/tools/license-generator.help +++ b/licensor/src/main/resources/org/elasticsearch/license/licensor/tools/licensor-license-generator.help @@ -20,7 +20,7 @@ OPTIONS -lf,--licenseFile Path to a license spec file - -pub,--publicKeyPath Save the generated public key to path + -pub,--publicKeyPath Path to public key to be used - -pri,--privateKeyPath Save the generated private key to path + -pri,--privateKeyPath Path to private key to be used diff --git a/src/main/resources/org/elasticsearch/license/licensor/tools/verify-license.help b/licensor/src/main/resources/org/elasticsearch/license/licensor/tools/licensor-verify-license.help similarity index 87% rename from src/main/resources/org/elasticsearch/license/licensor/tools/verify-license.help rename to licensor/src/main/resources/org/elasticsearch/license/licensor/tools/licensor-verify-license.help index f4254c4dc31..e36007f3838 100644 --- a/src/main/resources/org/elasticsearch/license/licensor/tools/verify-license.help +++ b/licensor/src/main/resources/org/elasticsearch/license/licensor/tools/licensor-verify-license.help @@ -4,7 +4,7 @@ NAME SYNOPSIS - verify-license -l signedLicense + verify-license -l signedLicense -pub publicKeyPath DESCRIPTION @@ -24,3 +24,5 @@ OPTIONS -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 new file mode 100644 index 00000000000..6e43f42d45e --- /dev/null +++ b/licensor/src/test/java/org/elasticsearch/license/licensor/AbstractLicensingTestBase.java @@ -0,0 +1,92 @@ +/* + * 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.BeforeClass; + +import java.net.URL; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.UUID; + +public abstract class AbstractLicensingTestBase extends ElasticsearchTestCase { + + protected static String pubKeyPath = null; + protected static String priKeyPath = null; + + @BeforeClass + public static void setup() throws Exception { + pubKeyPath = getResourcePath("/public.key"); + priKeyPath = getResourcePath("/private.key"); + } + + public static Set generateSignedLicenses(List licenseSpecs) 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) 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); + } + + public static String getTestPriKeyPath() throws Exception { + return getResourcePath("/private.key"); + } + + public static String getTestPubKeyPath() throws Exception { + return getResourcePath("/public.key"); + } + + private static String getResourcePath(String resource) throws Exception { + URL url = TestUtils.class.getResource(resource); + return url.toURI().getPath(); + } +} diff --git a/src/test/java/org/elasticsearch/license/LicenseVerificationTests.java b/licensor/src/test/java/org/elasticsearch/license/licensor/LicenseVerificationTests.java similarity index 62% rename from src/test/java/org/elasticsearch/license/LicenseVerificationTests.java rename to licensor/src/test/java/org/elasticsearch/license/licensor/LicenseVerificationTests.java index 8ee528eea79..64d8844058e 100644 --- a/src/test/java/org/elasticsearch/license/LicenseVerificationTests.java +++ b/licensor/src/test/java/org/elasticsearch/license/licensor/LicenseVerificationTests.java @@ -3,44 +3,39 @@ * 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; +package org.elasticsearch.license.licensor; import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.common.xcontent.ToXContent; -import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.common.xcontent.XContentFactory; -import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.license.core.License; import org.elasticsearch.license.core.LicenseVerifier; -import org.elasticsearch.license.plugin.core.LicensesMetaData; import org.junit.Test; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; -import static com.carrotsearch.randomizedtesting.RandomizedTest.randomIntBetween; import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; public class LicenseVerificationTests extends AbstractLicensingTestBase { @Test public void testGeneratedLicenses() throws Exception { - License shieldLicense = TestUtils.generateSignedLicense("shield", TimeValue.timeValueHours(2 * 24)); + License shieldLicense = generateSignedLicense("shield", TimeValue.timeValueHours(2 * 24)); assertThat(LicenseVerifier.verifyLicense(shieldLicense), equalTo(true)); } @Test public void testMultipleFeatureLicenses() throws Exception { - License shieldLicense = TestUtils.generateSignedLicense("shield", TimeValue.timeValueHours(2 * 24)); - License marvelLicense = TestUtils.generateSignedLicense("marvel", TimeValue.timeValueHours(2 * 24)); + License shieldLicense = generateSignedLicense("shield", TimeValue.timeValueHours(2 * 24)); + License marvelLicense = generateSignedLicense("marvel", TimeValue.timeValueHours(2 * 24)); assertThat(LicenseVerifier.verifyLicenses(Arrays.asList(shieldLicense, marvelLicense)), equalTo(true)); } @Test public void testLicenseTampering() throws Exception { - License license = TestUtils.generateSignedLicense("shield", TimeValue.timeValueHours(2)); + License license = generateSignedLicense("shield", TimeValue.timeValueHours(2)); final License tamperedLicense = License.builder() .fromLicenseSpec(license, license.signature()) @@ -54,9 +49,9 @@ public class LicenseVerificationTests extends AbstractLicensingTestBase { @Test public void testRandomLicenseVerification() throws Exception { int n = randomIntBetween(5, 15); - List licenseSpecs = new ArrayList<>(); + List licenseSpecs = new ArrayList<>(); for (int i = 0; i < n; i++) { - licenseSpecs.add(generateRandomLicenseSpec()); + licenseSpecs.add(TestUtils.generateRandomLicenseSpec()); } Set generatedLicenses = generateSignedLicenses(licenseSpecs); diff --git a/licensor/src/test/java/org/elasticsearch/license/licensor/TestUtils.java b/licensor/src/test/java/org/elasticsearch/license/licensor/TestUtils.java new file mode 100644 index 00000000000..c8b8a86e1e3 --- /dev/null +++ b/licensor/src/test/java/org/elasticsearch/license/licensor/TestUtils.java @@ -0,0 +1,201 @@ +/* + * 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 java.io.IOException; +import java.util.*; +import java.util.concurrent.TimeUnit; + +import static com.carrotsearch.randomizedtesting.RandomizedTest.randomBoolean; +import static com.carrotsearch.randomizedtesting.RandomizedTest.randomInt; +import static com.carrotsearch.randomizedtesting.RandomizedTest.randomIntBetween; +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, TimeUnit.MILLISECONDS); + private final static org.elasticsearch.common.joda.time.format.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, long now) { + return dateTimeFormatter.print(dateMathParser.parse(time, now)); + } + + public static long dateMath(String time, long now) { + return dateMathParser.parse(time, 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/src/test/java/org/elasticsearch/license/tools/KeyPairGenerationToolTests.java b/licensor/src/test/java/org/elasticsearch/license/licensor/tools/KeyPairGenerationToolTests.java similarity index 97% rename from src/test/java/org/elasticsearch/license/tools/KeyPairGenerationToolTests.java rename to licensor/src/test/java/org/elasticsearch/license/licensor/tools/KeyPairGenerationToolTests.java index 36069e29931..896315c6596 100644 --- a/src/test/java/org/elasticsearch/license/tools/KeyPairGenerationToolTests.java +++ b/licensor/src/test/java/org/elasticsearch/license/licensor/tools/KeyPairGenerationToolTests.java @@ -3,13 +3,12 @@ * 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.tools; +package org.elasticsearch.license.licensor.tools; import org.elasticsearch.common.cli.CliToolTestCase; import org.elasticsearch.common.cli.commons.MissingOptionException; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.env.Environment; -import org.elasticsearch.license.licensor.tools.KeyPairGeneratorTool; import org.elasticsearch.license.licensor.tools.KeyPairGeneratorTool.KeyGenerator; import org.junit.Rule; import org.junit.Test; diff --git a/src/test/java/org/elasticsearch/license/tools/LicenseGenerationToolTests.java b/licensor/src/test/java/org/elasticsearch/license/licensor/tools/LicenseGenerationToolTests.java similarity index 75% rename from src/test/java/org/elasticsearch/license/tools/LicenseGenerationToolTests.java rename to licensor/src/test/java/org/elasticsearch/license/licensor/tools/LicenseGenerationToolTests.java index 8a49c0b185e..1aca73d3cde 100644 --- a/src/test/java/org/elasticsearch/license/tools/LicenseGenerationToolTests.java +++ b/licensor/src/test/java/org/elasticsearch/license/licensor/tools/LicenseGenerationToolTests.java @@ -3,9 +3,8 @@ * 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.tools; +package org.elasticsearch.license.licensor.tools; -import org.elasticsearch.common.cli.CliTool; import org.elasticsearch.common.cli.CliToolTestCase; import org.elasticsearch.common.cli.commons.MissingOptionException; import org.elasticsearch.common.settings.ImmutableSettings; @@ -13,7 +12,8 @@ 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.tools.LicenseGeneratorTool; +import org.elasticsearch.license.licensor.AbstractLicensingTestBase; +import org.elasticsearch.license.licensor.TestUtils; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; @@ -26,8 +26,7 @@ import java.nio.file.Paths; import java.util.*; import static org.elasticsearch.common.cli.CliTool.ExitStatus; -import static org.elasticsearch.license.AbstractLicensingTestBase.*; -import static org.elasticsearch.license.licensor.tools.LicenseGeneratorTool.Command; +import static org.elasticsearch.common.cli.CliTool.Command; import static org.elasticsearch.license.licensor.tools.LicenseGeneratorTool.LicenseGenerator; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.instanceOf; @@ -45,16 +44,16 @@ public class LicenseGenerationToolTests extends CliToolTestCase { @BeforeClass public static void setup() throws Exception { - pubKeyPath = getResourcePath("/public.key"); - priKeyPath = getResourcePath("/private.key"); + pubKeyPath = AbstractLicensingTestBase.getTestPubKeyPath(); + priKeyPath = AbstractLicensingTestBase.getTestPriKeyPath(); } @Test public void testParsingNonExistentKeyFile() throws Exception { - LicenseSpec inputLicenseSpec = generateRandomLicenseSpec(); + TestUtils.LicenseSpec inputLicenseSpec = TestUtils.generateRandomLicenseSpec(); LicenseGeneratorTool licenseGeneratorTool = new LicenseGeneratorTool(); Command command = licenseGeneratorTool.parse(LicenseGeneratorTool.NAME, - args("--license " + generateLicenseSpecString(Arrays.asList(inputLicenseSpec)) + args("--license " + TestUtils.generateLicenseSpecString(Arrays.asList(inputLicenseSpec)) + " --publicKeyPath " + pubKeyPath.concat("invalid") + " --privateKeyPath " + priKeyPath)); @@ -63,7 +62,7 @@ public class LicenseGenerationToolTests extends CliToolTestCase { assertThat(exitCommand.status(), equalTo(ExitStatus.USAGE)); command = licenseGeneratorTool.parse(LicenseGeneratorTool.NAME, - args("--license " + generateLicenseSpecString(Arrays.asList(inputLicenseSpec)) + args("--license " + TestUtils.generateLicenseSpecString(Arrays.asList(inputLicenseSpec)) + " --privateKeyPath " + priKeyPath.concat("invalid") + " --publicKeyPath " + pubKeyPath)); @@ -86,12 +85,12 @@ public class LicenseGenerationToolTests extends CliToolTestCase { @Test public void testParsingMissingArgs() throws Exception { - LicenseSpec inputLicenseSpec = generateRandomLicenseSpec(); + TestUtils.LicenseSpec inputLicenseSpec = TestUtils.generateRandomLicenseSpec(); LicenseGeneratorTool licenseGeneratorTool = new LicenseGeneratorTool(); boolean pubKeyMissing = randomBoolean(); try { licenseGeneratorTool.parse(LicenseGeneratorTool.NAME, - args("--license " + generateLicenseSpecString(Arrays.asList(inputLicenseSpec)) + args("--license " + TestUtils.generateLicenseSpecString(Arrays.asList(inputLicenseSpec)) + ((!pubKeyMissing) ? " --publicKeyPath " + pubKeyPath : "") + ((pubKeyMissing) ? " --privateKeyPath " + priKeyPath : ""))); fail("missing argument: " + ((pubKeyMissing) ? "publicKeyPath" : "privateKeyPath") + " should throw an exception"); @@ -102,10 +101,10 @@ public class LicenseGenerationToolTests extends CliToolTestCase { @Test public void testParsingSimple() throws Exception { - LicenseSpec inputLicenseSpec = generateRandomLicenseSpec(); + TestUtils.LicenseSpec inputLicenseSpec = TestUtils.generateRandomLicenseSpec(); LicenseGeneratorTool licenseGeneratorTool = new LicenseGeneratorTool(); Command command = licenseGeneratorTool.parse(LicenseGeneratorTool.NAME, - args("--license " + generateLicenseSpecString(Arrays.asList(inputLicenseSpec)) + args("--license " + TestUtils.generateLicenseSpecString(Arrays.asList(inputLicenseSpec)) + " --publicKeyPath " + pubKeyPath + " --privateKeyPath " + priKeyPath)); @@ -116,14 +115,14 @@ public class LicenseGenerationToolTests extends CliToolTestCase { assertThat(licenseGenerator.licenseSpecs.size(), equalTo(1)); License outputLicenseSpec = licenseGenerator.licenseSpecs.iterator().next(); - assertLicenseSpec(inputLicenseSpec, outputLicenseSpec); + TestUtils.assertLicenseSpec(inputLicenseSpec, outputLicenseSpec); } @Test public void testParsingLicenseFile() throws Exception { - LicenseSpec inputLicenseSpec = generateRandomLicenseSpec(); + TestUtils.LicenseSpec inputLicenseSpec = TestUtils.generateRandomLicenseSpec(); File tempFile = temporaryFolder.newFile("license_spec.json"); - Files.write(Paths.get(tempFile.getAbsolutePath()), generateLicenseSpecString(Arrays.asList(inputLicenseSpec)).getBytes(StandardCharsets.UTF_8)); + Files.write(Paths.get(tempFile.getAbsolutePath()), TestUtils.generateLicenseSpecString(Arrays.asList(inputLicenseSpec)).getBytes(StandardCharsets.UTF_8)); LicenseGeneratorTool licenseGeneratorTool = new LicenseGeneratorTool(); Command command = licenseGeneratorTool.parse(LicenseGeneratorTool.NAME, @@ -138,20 +137,20 @@ public class LicenseGenerationToolTests extends CliToolTestCase { assertThat(licenseGenerator.licenseSpecs.size(), equalTo(1)); License outputLicenseSpec = licenseGenerator.licenseSpecs.iterator().next(); - assertLicenseSpec(inputLicenseSpec, outputLicenseSpec); + TestUtils.assertLicenseSpec(inputLicenseSpec, outputLicenseSpec); } @Test public void testParsingMultipleLicense() throws Exception { int n = randomIntBetween(2, 5); - Map inputLicenseSpecs = new HashMap<>(); + Map inputLicenseSpecs = new HashMap<>(); for (int i = 0; i < n; i++) { - LicenseSpec licenseSpec = generateRandomLicenseSpec(); + TestUtils.LicenseSpec licenseSpec = TestUtils.generateRandomLicenseSpec(); inputLicenseSpecs.put(licenseSpec.feature, licenseSpec); } LicenseGeneratorTool licenseGeneratorTool = new LicenseGeneratorTool(); Command command = licenseGeneratorTool.parse(LicenseGeneratorTool.NAME, - args("--license " + generateLicenseSpecString(new ArrayList<>(inputLicenseSpecs.values())) + args("--license " + TestUtils.generateLicenseSpecString(new ArrayList<>(inputLicenseSpecs.values())) + " --publicKeyPath " + pubKeyPath + " --privateKeyPath " + priKeyPath)); @@ -162,30 +161,30 @@ public class LicenseGenerationToolTests extends CliToolTestCase { assertThat(licenseGenerator.licenseSpecs.size(), equalTo(inputLicenseSpecs.size())); for (License outputLicenseSpec : licenseGenerator.licenseSpecs) { - LicenseSpec inputLicenseSpec = inputLicenseSpecs.get(outputLicenseSpec.feature()); + TestUtils.LicenseSpec inputLicenseSpec = inputLicenseSpecs.get(outputLicenseSpec.feature()); assertThat(inputLicenseSpec, notNullValue()); - assertLicenseSpec(inputLicenseSpec, outputLicenseSpec); + TestUtils.assertLicenseSpec(inputLicenseSpec, outputLicenseSpec); } } @Test public void testTool() throws Exception { int n = randomIntBetween(1, 5); - Map inputLicenseSpecs = new HashMap<>(); + Map inputLicenseSpecs = new HashMap<>(); for (int i = 0; i < n; i++) { - LicenseSpec licenseSpec = generateRandomLicenseSpec(); + TestUtils.LicenseSpec licenseSpec = TestUtils.generateRandomLicenseSpec(); inputLicenseSpecs.put(licenseSpec.feature, licenseSpec); } - List licenseSpecs = Licenses.fromSource(generateLicenseSpecString(new ArrayList<>(inputLicenseSpecs.values())).getBytes(StandardCharsets.UTF_8), false); + 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) { - LicenseSpec inputLicenseSpec = inputLicenseSpecs.get(outputLicense.feature()); + TestUtils.LicenseSpec inputLicenseSpec = inputLicenseSpecs.get(outputLicense.feature()); assertThat(inputLicenseSpec, notNullValue()); - assertLicenseSpec(inputLicenseSpec, outputLicense); + TestUtils.assertLicenseSpec(inputLicenseSpec, outputLicense); } } @@ -198,7 +197,7 @@ public class LicenseGenerationToolTests extends CliToolTestCase { } - private ExitStatus execute(CliTool.Command cmd, Settings settings) throws Exception { + private ExitStatus execute(Command cmd, Settings settings) throws Exception { Environment env = new Environment(settings); return cmd.execute(settings, env); } diff --git a/src/test/java/org/elasticsearch/license/tools/LicenseVerificationToolTests.java b/licensor/src/test/java/org/elasticsearch/license/licensor/tools/LicenseVerificationToolTests.java similarity index 71% rename from src/test/java/org/elasticsearch/license/tools/LicenseVerificationToolTests.java rename to licensor/src/test/java/org/elasticsearch/license/licensor/tools/LicenseVerificationToolTests.java index dd926256366..cf99b2323d4 100644 --- a/src/test/java/org/elasticsearch/license/tools/LicenseVerificationToolTests.java +++ b/licensor/src/test/java/org/elasticsearch/license/licensor/tools/LicenseVerificationToolTests.java @@ -3,17 +3,18 @@ * 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.tools; +package org.elasticsearch.license.licensor.tools; import org.elasticsearch.common.cli.CliToolTestCase; +import org.elasticsearch.common.cli.commons.MissingOptionException; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.env.Environment; -import org.elasticsearch.license.TestUtils; +import org.elasticsearch.license.licensor.AbstractLicensingTestBase; +import org.elasticsearch.license.licensor.TestUtils; import org.elasticsearch.license.core.License; import org.elasticsearch.license.core.Licenses; -import org.elasticsearch.license.licensor.tools.LicenseVerificationTool; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -21,15 +22,16 @@ import org.junit.rules.TemporaryFolder; import java.io.File; import java.nio.charset.StandardCharsets; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.*; import static org.elasticsearch.common.cli.CliTool.Command; import static org.elasticsearch.common.cli.CliTool.ExitStatus; -import static org.elasticsearch.license.TestUtils.generateSignedLicense; 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 { @@ -40,7 +42,31 @@ public class LicenseVerificationToolTests extends CliToolTestCase { @Test public void testParsingMissingLicense() throws Exception { LicenseVerificationTool licenseVerificationTool = new LicenseVerificationTool(); - Command command = licenseVerificationTool.parse(LicenseVerificationTool.NAME, args("")); + Command command = licenseVerificationTool.parse(LicenseVerificationTool.NAME, args(" --publicKeyPath " + AbstractLicensingTestBase.getTestPubKeyPath())); + + assertThat(command, instanceOf(Command.Exit.class)); + Command.Exit exitCommand = (Command.Exit) command; + assertThat(exitCommand.status(), equalTo(ExitStatus.USAGE)); + } + + @Test + public void testParsingMissingPublicKeyPath() throws Exception { + License inputLicense = AbstractLicensingTestBase.generateSignedLicense("feature__1", + TimeValue.timeValueHours(1)); + 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(); + Command command = licenseVerificationTool.parse(LicenseVerificationTool.NAME, args(" --publicKeyPath " + + AbstractLicensingTestBase.getTestPubKeyPath().concat(".invalid"))); assertThat(command, instanceOf(Command.Exit.class)); Command.Exit exitCommand = (Command.Exit) command; @@ -49,11 +75,12 @@ public class LicenseVerificationToolTests extends CliToolTestCase { @Test public void testParsingSimple() throws Exception { - License inputLicense = TestUtils.generateSignedLicense("feature__1", + License inputLicense = AbstractLicensingTestBase.generateSignedLicense("feature__1", TimeValue.timeValueHours(1)); LicenseVerificationTool licenseVerificationTool = new LicenseVerificationTool(); Command command = licenseVerificationTool.parse(LicenseVerificationTool.NAME, - args("--license " + TestUtils.dumpLicense(inputLicense))); + args("--license " + TestUtils.dumpLicense(inputLicense) + + " --publicKeyPath " + AbstractLicensingTestBase.getTestPubKeyPath())); assertThat(command, instanceOf(LicenseVerifier.class)); LicenseVerifier licenseVerifier = (LicenseVerifier) command; assertThat(licenseVerifier.licenses.size(), equalTo(1)); @@ -63,12 +90,13 @@ public class LicenseVerificationToolTests extends CliToolTestCase { @Test public void testParsingLicenseFile() throws Exception { - License inputLicense = TestUtils.generateSignedLicense("feature__1", + License inputLicense = AbstractLicensingTestBase.generateSignedLicense("feature__1", TimeValue.timeValueHours(1)); LicenseVerificationTool licenseVerificationTool = new LicenseVerificationTool(); Command command = licenseVerificationTool.parse(LicenseVerificationTool.NAME, - args("--licenseFile " + dumpLicenseAsFile(inputLicense))); + args("--licenseFile " + dumpLicenseAsFile(inputLicense) + + " --publicKeyPath " + AbstractLicensingTestBase.getTestPubKeyPath())); assertThat(command, instanceOf(LicenseVerifier.class)); LicenseVerifier licenseVerifier = (LicenseVerifier) command; assertThat(licenseVerifier.licenses.size(), equalTo(1)); @@ -82,7 +110,7 @@ public class LicenseVerificationToolTests extends CliToolTestCase { int n = randomIntBetween(2, 5); Map inputLicenses = new HashMap<>(); for (int i = 0; i < n; i++) { - License license = TestUtils.generateSignedLicense("feature__" + i, + License license = AbstractLicensingTestBase.generateSignedLicense("feature__" + i, TimeValue.timeValueHours(1)); inputLicenses.put(license.feature(), license); } @@ -92,6 +120,7 @@ public class LicenseVerificationToolTests extends CliToolTestCase { argsBuilder.append(" --license ") .append(TestUtils.dumpLicense(inputLicense)); } + argsBuilder.append(" --publicKeyPath ").append(AbstractLicensingTestBase.getTestPubKeyPath()); LicenseVerificationTool licenseVerificationTool = new LicenseVerificationTool(); Command command = licenseVerificationTool.parse(LicenseVerificationTool.NAME, args(argsBuilder.toString())); @@ -111,12 +140,12 @@ public class LicenseVerificationToolTests extends CliToolTestCase { int n = randomIntBetween(2, 5); Map inputLicenses = new HashMap<>(); for (int i = 0; i < n; i++) { - License license = TestUtils.generateSignedLicense("feature__" + i, + License license = AbstractLicensingTestBase.generateSignedLicense("feature__" + i, TimeValue.timeValueHours(1)); inputLicenses.put(license.feature(), license); } - String output = runLicenseVerificationTool(new HashSet<>(inputLicenses.values()), ExitStatus.OK); + String output = runLicenseVerificationTool(new HashSet<>(inputLicenses.values()), Paths.get(AbstractLicensingTestBase.getTestPubKeyPath()), ExitStatus.OK); List outputLicenses = Licenses.fromSource(output.getBytes(StandardCharsets.UTF_8), true); assertThat(outputLicenses.size(), equalTo(inputLicenses.size())); @@ -129,14 +158,14 @@ public class LicenseVerificationToolTests extends CliToolTestCase { @Test public void testToolInvalidLicense() throws Exception { - License signedLicense = TestUtils.generateSignedLicense("feature__1" + License signedLicense = AbstractLicensingTestBase.generateSignedLicense("feature__1" , TimeValue.timeValueHours(1)); License tamperedLicense = License.builder() .fromLicenseSpec(signedLicense, signedLicense.signature()) .expiryDate(signedLicense.expiryDate() + randomIntBetween(1, 1000)).build(); - runLicenseVerificationTool(Collections.singleton(tamperedLicense), ExitStatus.DATA_ERROR); + runLicenseVerificationTool(Collections.singleton(tamperedLicense), Paths.get(AbstractLicensingTestBase.getTestPubKeyPath()), ExitStatus.DATA_ERROR); } private String dumpLicenseAsFile(License license) throws Exception { @@ -145,9 +174,9 @@ public class LicenseVerificationToolTests extends CliToolTestCase { return tempFile.getAbsolutePath(); } - private String runLicenseVerificationTool(Set licenses, ExitStatus expectedExitStatus) throws Exception { + private String runLicenseVerificationTool(Set licenses, Path publicKeyPath, ExitStatus expectedExitStatus) throws Exception { CaptureOutputTerminal outputTerminal = new CaptureOutputTerminal(); - LicenseVerifier licenseVerifier = new LicenseVerifier(outputTerminal, licenses); + LicenseVerifier licenseVerifier = new LicenseVerifier(outputTerminal, licenses, publicKeyPath); assertThat(execute(licenseVerifier, ImmutableSettings.EMPTY), equalTo(expectedExitStatus)); if (expectedExitStatus == ExitStatus.OK) { assertThat(outputTerminal.getTerminalOutput().size(), equalTo(1)); diff --git a/licensor/src/test/resources/log4j.properties b/licensor/src/test/resources/log4j.properties new file mode 100644 index 00000000000..76defc8660c --- /dev/null +++ b/licensor/src/test/resources/log4j.properties @@ -0,0 +1,11 @@ +es.logger.level=INFO +log4j.rootLogger=${es.logger.level}, out + +log4j.logger.org.apache.http=INFO, out +log4j.additivity.org.apache.http=false + +log4j.logger.org.elasticsearch.license=TRACE + +log4j.appender.out=org.apache.log4j.ConsoleAppender +log4j.appender.out.layout=org.apache.log4j.PatternLayout +log4j.appender.out.layout.conversionPattern=[%d{ISO8601}][%-5p][%-25c] %m%n diff --git a/licensor/src/test/resources/private.key b/licensor/src/test/resources/private.key new file mode 100644 index 0000000000000000000000000000000000000000..1f545803d875598d976b206250d5e95667c794ef GIT binary patch literal 1232 zcmV;>1TXv1%Bc_wbLO>E3}&#D<@-rDJ$(p047kR zkI3mLE>J{X5~_|GE5>Bxd81`fV@~0j8z81fwu78=uPV1?-b_fL$snD`NE}Zsv(l}S z+Dr52K=W~W#&Y(zE)IK9$=-71EtPe#X0XhttX&@1ia@?lvh&>PD=A#>rfdl2Ru)*H zKaKRTp&qI~gmO-)fq;gzrbngk1r$cUKd~25@6;rjPJf6eLtCHTaDU8Rbt#KGKlZ%g zPd`h6iZ4kWgcXo9P=@b~YoN9WQmtytp^dd%)MXVsW%n~=T9#TzSWvr*YCR25X&mo6 zJoJz>&ju@jBz@-J;se7XMiU5&x@g8>FTI*r^O6Xv2(VF_R@Vk3wQBmIE>&XqH^t=M z5_c~f_`fm)R~9ZqEv|Ma3$nQ}LvHLD`h~L2VKXBZwZnP`c6%Qwnwq8Z0!hd2+^*Gk z6R7QdYCwK?kavUU0Vd*Mq5K{M!Vk zzSLrHwA_oZsoml1+m@@Wyh8$ZA^E2_FpxTTRz7~A$x?V+XFW0!aa4^L&A*^Evlz{gN8ae8h9=J=b zC8F19FN`xNpxA!48b`dGRK3GbQMOho1>byaB*psVh{^^yqVL4J0~$j7viqxma>pYOhkH~PwpJT1j6^yHDMWGO{vw8PyI zIrYD&$F3e@0!346r3BY7JkLDD+7E5EE6oiV(gQ62K@eQRE&#pRq81Tut!V+1TCM~srn6-g`!g_`uozhhJEnN6u9$5|& zLC>$@xw*^CD*fb$ngUWU)yZ%TqX*wM!HU2(O2RRFnw&?^e*xOZWZ?n`No9lb?BLpV=@K}hkB uJ-}qCO)pTE(AWQ24*9x_mu179!iEY^J(*;5;=+=*kZC+fDbTdAaQBAù<}[Á2ÖÓàZÖ|5‹¯ÊÊ7%ØêD +Yå‘xn:¼lúLÈæHò¢«Ë2˜ŸHvEEWÇ\¦H:“6Žh9 [!š…Ûæ©Š¤+;Ö.w7Cì©_|Þ ÓªÏÁ*ñ§D`ƒÚ?‚ùxU/3>x­UÓ“+ è \ No newline at end of file diff --git a/plugin/pom.xml b/plugin/pom.xml new file mode 100644 index 00000000000..38f648e37be --- /dev/null +++ b/plugin/pom.xml @@ -0,0 +1,277 @@ + + + + elasticsearch-license + org.elasticsearch + 1.0.0-SNAPSHOT + + 4.0.0 + + elasticsearch-license-plugin + + + + ${basedir}/src/test/resources + ${project.parent.basedir} + + + + + org.elasticsearch + elasticsearch-license-licensor + 1.0.0-SNAPSHOT + test + + + org.elasticsearch + elasticsearch-license-core + 1.0.0-SNAPSHOT + compile + + + + + + + ${keys.path} + false + + public.key + + + + src/main/resources + true + + + + + + org.apache.maven.plugins + maven-shade-plugin + 2.3 + + + package + + shade + + + + + true + true + true + + + org.elasticsearch:elasticsearch-license-core + org.elasticsearch:elasticsearch-license-core-shaded + + + + + org.elasticsearch.license + org.elasticsearch.license + + + + + *:* + + META-INF/license/** + META-INF/* + META-INF/maven/** + LICENSE + NOTICE + /*.txt + build.properties + + + + + + + maven-assembly-plugin + 2.4 + + ${project.build.directory}/releases/ + + + + plugin + package + + single + + + false + + ${basedir}/src/main/assemblies/plugin.xml + + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 1.3.1 + + + + 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 + 2.4 + + + for-plugin + prepare-package + + jar + + + + + + + com.carrotsearch.randomizedtesting + junit4-maven-plugin + 2.1.2 + + + tests + test + + junit4 + + + ${project.basedir}/target + ${project.basedir}/target/classes + 40 + pipe,warn + true + + + + + + + + + + + ${tests.jvms} + + + + + + + **/*Tests.class + **/*Test.class + + + **/Abstract*.class + **/*StressTest.class + + + -Xmx${tests.heap.size} + -Xms${tests.heap.size} + -Xss256k + -XX:MaxPermSize=128m + -XX:MaxDirectMemorySize=512m + -Des.logger.prefix= + + ${tests.shuffle} + ${tests.verbose} + ${tests.seed} + ${tests.failfast} + false + + . + + + ${tests.bwc} + ${tests.bwc.path} + ${tests.bwc.version} + ${tests.jvm.argline} + ${tests.processors} + ${tests.appendseed} + ${tests.iters} + ${tests.maxfailures} + ${tests.failfast} + ${tests.class} + ${tests.method} + ${tests.nightly} + ${tests.verbose} + ${tests.badapples} + ${tests.weekly} + ${tests.slow} + ${tests.awaitsfix} + ${tests.slow} + ${tests.timeoutSuite} + ${tests.showSuccess} + ${tests.integration} + ${tests.client.ratio} + ${tests.enable_mock_modules} + ${tests.assertion.disabled} + ${tests.rest} + ${tests.rest.suite} + ${tests.rest.blacklist} + ${tests.rest.spec} + ${tests.network} + ${tests.cluster} + ${tests.heap.size} + ${tests.filter} + ${env.ES_TEST_LOCAL} + ${es.node.mode} + ${es.logger.level} + ${tests.security.manager} + ${tests.compatibility} + true + + + + + + + + + \ No newline at end of file diff --git a/src/main/assemblies/plugin.xml b/plugin/src/main/assemblies/plugin.xml similarity index 100% rename from src/main/assemblies/plugin.xml rename to plugin/src/main/assemblies/plugin.xml diff --git a/src/main/java/org/elasticsearch/license/plugin/LicenseModule.java b/plugin/src/main/java/org/elasticsearch/license/plugin/LicenseModule.java similarity index 100% rename from src/main/java/org/elasticsearch/license/plugin/LicenseModule.java rename to plugin/src/main/java/org/elasticsearch/license/plugin/LicenseModule.java diff --git a/src/main/java/org/elasticsearch/license/plugin/LicensePlugin.java b/plugin/src/main/java/org/elasticsearch/license/plugin/LicensePlugin.java similarity index 100% rename from src/main/java/org/elasticsearch/license/plugin/LicensePlugin.java rename to plugin/src/main/java/org/elasticsearch/license/plugin/LicensePlugin.java diff --git a/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseAction.java b/plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseAction.java similarity index 100% rename from src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseAction.java rename to plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseAction.java diff --git a/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseRequest.java b/plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseRequest.java similarity index 100% rename from src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseRequest.java rename to plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseRequest.java diff --git a/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseRequestBuilder.java b/plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseRequestBuilder.java similarity index 100% rename from src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseRequestBuilder.java rename to plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseRequestBuilder.java diff --git a/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseResponse.java b/plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseResponse.java similarity index 100% rename from src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseResponse.java rename to plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/DeleteLicenseResponse.java diff --git a/src/main/java/org/elasticsearch/license/plugin/action/delete/TransportDeleteLicenseAction.java b/plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/TransportDeleteLicenseAction.java similarity index 100% rename from src/main/java/org/elasticsearch/license/plugin/action/delete/TransportDeleteLicenseAction.java rename to plugin/src/main/java/org/elasticsearch/license/plugin/action/delete/TransportDeleteLicenseAction.java diff --git a/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseAction.java b/plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseAction.java similarity index 100% rename from src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseAction.java rename to plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseAction.java diff --git a/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseRequest.java b/plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseRequest.java similarity index 100% rename from src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseRequest.java rename to plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseRequest.java diff --git a/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseRequestBuilder.java b/plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseRequestBuilder.java similarity index 100% rename from src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseRequestBuilder.java rename to plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseRequestBuilder.java diff --git a/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseResponse.java b/plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseResponse.java similarity index 100% rename from src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseResponse.java rename to plugin/src/main/java/org/elasticsearch/license/plugin/action/get/GetLicenseResponse.java diff --git a/src/main/java/org/elasticsearch/license/plugin/action/get/TransportGetLicenseAction.java b/plugin/src/main/java/org/elasticsearch/license/plugin/action/get/TransportGetLicenseAction.java similarity index 100% rename from src/main/java/org/elasticsearch/license/plugin/action/get/TransportGetLicenseAction.java rename to plugin/src/main/java/org/elasticsearch/license/plugin/action/get/TransportGetLicenseAction.java diff --git a/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseAction.java b/plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseAction.java similarity index 100% rename from src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseAction.java rename to plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseAction.java diff --git a/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseRequest.java b/plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseRequest.java similarity index 100% rename from src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseRequest.java rename to plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseRequest.java diff --git a/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseRequestBuilder.java b/plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseRequestBuilder.java similarity index 100% rename from src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseRequestBuilder.java rename to plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseRequestBuilder.java diff --git a/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseResponse.java b/plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseResponse.java similarity index 100% rename from src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseResponse.java rename to plugin/src/main/java/org/elasticsearch/license/plugin/action/put/PutLicenseResponse.java diff --git a/src/main/java/org/elasticsearch/license/plugin/action/put/TransportPutLicenseAction.java b/plugin/src/main/java/org/elasticsearch/license/plugin/action/put/TransportPutLicenseAction.java similarity index 100% rename from src/main/java/org/elasticsearch/license/plugin/action/put/TransportPutLicenseAction.java rename to plugin/src/main/java/org/elasticsearch/license/plugin/action/put/TransportPutLicenseAction.java diff --git a/src/main/java/org/elasticsearch/license/plugin/core/LicenseExpiredException.java b/plugin/src/main/java/org/elasticsearch/license/plugin/core/LicenseExpiredException.java similarity index 100% rename from src/main/java/org/elasticsearch/license/plugin/core/LicenseExpiredException.java rename to plugin/src/main/java/org/elasticsearch/license/plugin/core/LicenseExpiredException.java diff --git a/src/main/java/org/elasticsearch/license/plugin/core/LicensesClientService.java b/plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesClientService.java similarity index 100% rename from src/main/java/org/elasticsearch/license/plugin/core/LicensesClientService.java rename to plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesClientService.java diff --git a/src/main/java/org/elasticsearch/license/plugin/core/LicensesManagerService.java b/plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesManagerService.java similarity index 95% rename from src/main/java/org/elasticsearch/license/plugin/core/LicensesManagerService.java rename to plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesManagerService.java index 3645b840b14..38082371e4c 100644 --- a/src/main/java/org/elasticsearch/license/plugin/core/LicensesManagerService.java +++ b/plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesManagerService.java @@ -24,7 +24,7 @@ public interface LicensesManagerService { * 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); + public void registerLicenses(final PutLicenseRequestHolder requestHolder, final ActionListener listener); /** * Remove only signed license(s) for provided features from the cluster state metadata diff --git a/src/main/java/org/elasticsearch/license/plugin/core/LicensesMetaData.java b/plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesMetaData.java similarity index 98% rename from src/main/java/org/elasticsearch/license/plugin/core/LicensesMetaData.java rename to plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesMetaData.java index 2d9f7c8a80a..e34dd2f3801 100644 --- a/src/main/java/org/elasticsearch/license/plugin/core/LicensesMetaData.java +++ b/plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesMetaData.java @@ -7,7 +7,6 @@ package org.elasticsearch.license.plugin.core; import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.common.collect.ImmutableList; -import org.elasticsearch.common.collect.Sets; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.xcontent.ToXContent; @@ -17,7 +16,9 @@ import org.elasticsearch.license.core.License; import org.elasticsearch.license.core.Licenses; import java.io.IOException; -import java.util.*; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; /** * Contains metadata about registered licenses diff --git a/src/main/java/org/elasticsearch/license/plugin/core/LicensesService.java b/plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesService.java similarity index 95% rename from src/main/java/org/elasticsearch/license/plugin/core/LicensesService.java rename to plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesService.java index 8e79545b358..8a6e6a28111 100644 --- a/src/main/java/org/elasticsearch/license/plugin/core/LicensesService.java +++ b/plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesService.java @@ -5,6 +5,7 @@ */ package org.elasticsearch.license.plugin.core; +import org.apache.lucene.util.CollectionUtil; import org.elasticsearch.ElasticsearchException; import org.elasticsearch.action.ActionListener; import org.elasticsearch.cluster.*; @@ -55,7 +56,7 @@ import static org.elasticsearch.license.core.Licenses.reduceAndMap; * A consumer plugin (feature) is registered with {@link LicensesClientService#register(String, TrialLicenseOptions, 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 GatewayService#STATE_NOT_RECOVERED_BLOCK} block + * no {@link org.elasticsearch.gateway.GatewayService#STATE_NOT_RECOVERED_BLOCK} block * Upon successful registration, the feature(s) are notified appropriately using the notification scheme *

*

@@ -71,7 +72,7 @@ import static org.elasticsearch.license.core.Licenses.reduceAndMap; *

* 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 GatewayService#STATE_NOT_RECOVERED_BLOCK} + * {@link org.elasticsearch.gateway.GatewayService#STATE_NOT_RECOVERED_BLOCK} *

* Upon successful registration of a new feature: * - {@link #notifyFeaturesAndScheduleNotification(LicensesMetaData)} is called @@ -80,8 +81,8 @@ import static org.elasticsearch.license.core.Licenses.reduceAndMap; * - {@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 GatewayService#STATE_NOT_RECOVERED_BLOCK} - * - no-op in case of global block on {@link GatewayService#STATE_NOT_RECOVERED_BLOCK} + * - 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 { @@ -216,6 +217,16 @@ public class LicensesService extends AbstractLifecycleComponent 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; } @@ -246,7 +257,7 @@ public class LicensesService extends AbstractLifecycleComponent // sort the licenses by issue date List reducedLicenses = new ArrayList<>(licenseMap.values()); - Collections.sort(reducedLicenses, new Comparator() { + CollectionUtil.introSort(reducedLicenses, new Comparator() { @Override public int compare(License license1, License license2) { return (int) (license2.issueDate() - license1.issueDate()); @@ -359,10 +370,10 @@ public class LicensesService extends AbstractLifecycleComponent } /** - * When there is no global block on {@link GatewayService#STATE_NOT_RECOVERED_BLOCK}: + * 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 GatewayService#STATE_NOT_RECOVERED_BLOCK}, calls + * {@link org.elasticsearch.gateway.GatewayService#STATE_NOT_RECOVERED_BLOCK}, calls * {@link #notifyFeaturesAndScheduleNotification(LicensesMetaData)} * - else calls {@link #notifyFeaturesAndScheduleNotificationIfNeeded(LicensesMetaData)} */ @@ -409,7 +420,7 @@ public class LicensesService extends AbstractLifecycleComponent *

* Upon completion sets currentLicensesMetaData to {@link #lastObservedLicensesState} * to ensure the same license(s) are not notified on from - * {@link #clusterChanged(ClusterChangedEvent)} + * {@link #clusterChanged(org.elasticsearch.cluster.ClusterChangedEvent)} */ private void notifyFeaturesAndScheduleNotificationIfNeeded(final LicensesMetaData currentLicensesMetaData) { final LicensesMetaData lastNotifiedLicensesMetaData = lastObservedLicensesState.get(); @@ -492,13 +503,17 @@ public class LicensesService extends AbstractLifecycleComponent if (licensesMetaData != null) { StringBuilder signedFeatures = new StringBuilder(); for (License license : licensesMetaData.getSignedLicenses()) { + if (signedFeatures.length() != 0) { + signedFeatures.append(", "); + } signedFeatures.append(license.feature()); - signedFeatures.append(", "); } StringBuilder trialFeatures = new StringBuilder(); for (License license : licensesMetaData.getTrialLicenses()) { + if (trialFeatures.length() != 0) { + trialFeatures.append(", "); + } trialFeatures.append(license.feature()); - trialFeatures.append(", "); } logger.debug(prefix + " LicensesMetaData: signedLicenses: [" + signedFeatures.toString() + "] trialLicenses: [" + trialFeatures.toString() + "]"); } else { @@ -531,7 +546,7 @@ public class LicensesService extends AbstractLifecycleComponent * * @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 GatewayService#STATE_NOT_RECOVERED_BLOCK} + * 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); @@ -641,9 +656,9 @@ public class LicensesService extends AbstractLifecycleComponent /** * Job for notifying on expired license(s) to registered feature(s) - * In case of a global block on {@link GatewayService#STATE_NOT_RECOVERED_BLOCK}, + * 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(ClusterChangedEvent)} with no global block + * {@link #clusterChanged(org.elasticsearch.cluster.ClusterChangedEvent)} with no global block */ private class LicensingClientNotificationJob implements Runnable { @@ -704,7 +719,7 @@ public class LicensesService extends AbstractLifecycleComponent final TrialLicenseOptions trialLicenseOptions; final Listener listener; - final AtomicBoolean enabled = new AtomicBoolean(false); // by default, a consumer plugin should be disabled + volatile AtomicBoolean enabled = new AtomicBoolean(false); // by default, a consumer plugin should be disabled private ListenerHolder(String feature, TrialLicenseOptions trialLicenseOptions, Listener listener) { this.feature = feature; diff --git a/src/main/java/org/elasticsearch/license/plugin/core/LicensesStatus.java b/plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesStatus.java similarity index 100% rename from src/main/java/org/elasticsearch/license/plugin/core/LicensesStatus.java rename to plugin/src/main/java/org/elasticsearch/license/plugin/core/LicensesStatus.java diff --git a/src/main/java/org/elasticsearch/license/plugin/core/TrialLicenseUtils.java b/plugin/src/main/java/org/elasticsearch/license/plugin/core/TrialLicenseUtils.java similarity index 94% rename from src/main/java/org/elasticsearch/license/plugin/core/TrialLicenseUtils.java rename to plugin/src/main/java/org/elasticsearch/license/plugin/core/TrialLicenseUtils.java index 8dd6c53a807..3623c0c02f2 100644 --- a/src/main/java/org/elasticsearch/license/plugin/core/TrialLicenseUtils.java +++ b/plugin/src/main/java/org/elasticsearch/license/plugin/core/TrialLicenseUtils.java @@ -12,10 +12,11 @@ import org.elasticsearch.license.core.License; import org.elasticsearch.license.core.Licenses; import java.io.IOException; -import java.util.*; +import java.util.Collections; +import java.util.UUID; -import static org.elasticsearch.license.core.CryptUtils.decrypt; -import static org.elasticsearch.license.core.CryptUtils.encrypt; +import static org.elasticsearch.license.core.shaded.CryptUtils.decrypt; +import static org.elasticsearch.license.core.shaded.CryptUtils.encrypt; public class TrialLicenseUtils { diff --git a/src/main/java/org/elasticsearch/license/plugin/rest/RestDeleteLicenseAction.java b/plugin/src/main/java/org/elasticsearch/license/plugin/rest/RestDeleteLicenseAction.java similarity index 100% rename from src/main/java/org/elasticsearch/license/plugin/rest/RestDeleteLicenseAction.java rename to plugin/src/main/java/org/elasticsearch/license/plugin/rest/RestDeleteLicenseAction.java diff --git a/src/main/java/org/elasticsearch/license/plugin/rest/RestGetLicenseAction.java b/plugin/src/main/java/org/elasticsearch/license/plugin/rest/RestGetLicenseAction.java similarity index 92% rename from src/main/java/org/elasticsearch/license/plugin/rest/RestGetLicenseAction.java rename to plugin/src/main/java/org/elasticsearch/license/plugin/rest/RestGetLicenseAction.java index 4797250dae3..219291e317c 100644 --- a/src/main/java/org/elasticsearch/license/plugin/rest/RestGetLicenseAction.java +++ b/plugin/src/main/java/org/elasticsearch/license/plugin/rest/RestGetLicenseAction.java @@ -46,6 +46,10 @@ public class RestGetLicenseAction extends BaseRestHandler { 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/src/main/java/org/elasticsearch/license/plugin/rest/RestPutLicenseAction.java b/plugin/src/main/java/org/elasticsearch/license/plugin/rest/RestPutLicenseAction.java similarity index 100% rename from src/main/java/org/elasticsearch/license/plugin/rest/RestPutLicenseAction.java rename to plugin/src/main/java/org/elasticsearch/license/plugin/rest/RestPutLicenseAction.java diff --git a/src/main/resources/es-plugin.properties b/plugin/src/main/resources/es-plugin.properties similarity index 100% rename from src/main/resources/es-plugin.properties rename to plugin/src/main/resources/es-plugin.properties diff --git a/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesConsumerPluginIntegrationTests.java b/plugin/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesConsumerPluginIntegrationTests.java similarity index 95% rename from src/test/java/org/elasticsearch/license/plugin/AbstractLicensesConsumerPluginIntegrationTests.java rename to plugin/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesConsumerPluginIntegrationTests.java index 7d8c1da024b..f05f14b9e47 100644 --- a/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesConsumerPluginIntegrationTests.java +++ b/plugin/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesConsumerPluginIntegrationTests.java @@ -10,7 +10,8 @@ import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.gateway.GatewayService; -import org.elasticsearch.license.plugin.consumer.*; +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; @@ -24,7 +25,7 @@ import static org.hamcrest.CoreMatchers.equalTo; /** * Framework to test licensing plugin integration for existing/new consumer plugins - * see {@link LicensesEagerConsumerPluginIntegrationTests} and {@link LicensesLazyConsumerPluginIntegrationTests} + * 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) diff --git a/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesIntegrationTests.java b/plugin/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesIntegrationTests.java similarity index 89% rename from src/test/java/org/elasticsearch/license/plugin/AbstractLicensesIntegrationTests.java rename to plugin/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesIntegrationTests.java index 475130c497b..a5e257525f8 100644 --- a/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesIntegrationTests.java +++ b/plugin/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesIntegrationTests.java @@ -12,6 +12,9 @@ import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.base.Predicate; import org.elasticsearch.common.collect.Lists; +import org.elasticsearch.common.joda.DateMathParser; +import org.elasticsearch.common.joda.FormatDateTimeFormatter; +import org.elasticsearch.common.joda.Joda; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; @@ -32,12 +35,23 @@ import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import static org.elasticsearch.license.TestUtils.generateSignedLicense; +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 org.elasticsearch.common.joda.time.format.DateTimeFormatter dateTimeFormatter = formatDateTimeFormatter.printer(); + private final static DateMathParser dateMathParser = new DateMathParser(formatDateTimeFormatter, TimeUnit.MILLISECONDS); + + public static String dateMathString(String time, long now) { + return dateTimeFormatter.print(dateMathParser.parse(time, now)); + } + + public static long dateMath(String time, long now) { + return dateMathParser.parse(time, now); + } @Override protected Settings nodeSettings(int nodeOrdinal) { return ImmutableSettings.settingsBuilder() @@ -93,7 +107,7 @@ public abstract class AbstractLicensesIntegrationTests extends ElasticsearchInte } protected void assertLicenseManagerStatusFor(final String feature, final boolean expectedEnabled) throws InterruptedException { - assertThat("LicenseManager for feature " + feature + " should have enabled status of " + expectedEnabled, awaitBusy(new Predicate() { + assertThat("LicensesManagerService for feature " + feature + " should have enabled status of " + expectedEnabled, awaitBusy(new Predicate() { @Override public boolean apply(Object o) { for (LicensesManagerService managerService : licensesManagerServices()) { diff --git a/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesServiceTests.java b/plugin/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesServiceTests.java similarity index 100% rename from src/test/java/org/elasticsearch/license/plugin/AbstractLicensesServiceTests.java rename to plugin/src/test/java/org/elasticsearch/license/plugin/AbstractLicensesServiceTests.java diff --git a/src/test/java/org/elasticsearch/license/plugin/LicensesClientServiceTests.java b/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesClientServiceTests.java similarity index 99% rename from src/test/java/org/elasticsearch/license/plugin/LicensesClientServiceTests.java rename to plugin/src/test/java/org/elasticsearch/license/plugin/LicensesClientServiceTests.java index 3d7ee0239f7..f4ec906c7fd 100644 --- a/src/test/java/org/elasticsearch/license/plugin/LicensesClientServiceTests.java +++ b/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesClientServiceTests.java @@ -19,7 +19,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; -import static org.elasticsearch.license.TestUtils.generateSignedLicense; +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; diff --git a/src/test/java/org/elasticsearch/license/plugin/LicensesEagerConsumerPluginIntegrationTests.java b/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesEagerConsumerPluginIntegrationTests.java similarity index 87% rename from src/test/java/org/elasticsearch/license/plugin/LicensesEagerConsumerPluginIntegrationTests.java rename to plugin/src/test/java/org/elasticsearch/license/plugin/LicensesEagerConsumerPluginIntegrationTests.java index 41bb027cb3d..a47ceb6080d 100644 --- a/src/test/java/org/elasticsearch/license/plugin/LicensesEagerConsumerPluginIntegrationTests.java +++ b/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesEagerConsumerPluginIntegrationTests.java @@ -6,7 +6,7 @@ package org.elasticsearch.license.plugin; import org.elasticsearch.common.settings.ImmutableSettings; -import org.elasticsearch.license.plugin.consumer.*; +import org.elasticsearch.license.plugin.consumer.EagerLicenseRegistrationConsumerPlugin; public class LicensesEagerConsumerPluginIntegrationTests extends AbstractLicensesConsumerPluginIntegrationTests { diff --git a/src/test/java/org/elasticsearch/license/plugin/LicensesLazyConsumerPluginIntegrationTests.java b/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesLazyConsumerPluginIntegrationTests.java similarity index 100% rename from src/test/java/org/elasticsearch/license/plugin/LicensesLazyConsumerPluginIntegrationTests.java rename to plugin/src/test/java/org/elasticsearch/license/plugin/LicensesLazyConsumerPluginIntegrationTests.java diff --git a/src/test/java/org/elasticsearch/license/plugin/LicensesManagerServiceTests.java b/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesManagerServiceTests.java similarity index 98% rename from src/test/java/org/elasticsearch/license/plugin/LicensesManagerServiceTests.java rename to plugin/src/test/java/org/elasticsearch/license/plugin/LicensesManagerServiceTests.java index 504f38700ef..bdbcdfab20f 100644 --- a/src/test/java/org/elasticsearch/license/plugin/LicensesManagerServiceTests.java +++ b/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesManagerServiceTests.java @@ -9,7 +9,6 @@ import org.elasticsearch.action.ActionListener; import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse; import org.elasticsearch.common.collect.Sets; import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.license.TestUtils; import org.elasticsearch.license.core.License; import org.elasticsearch.license.plugin.action.delete.DeleteLicenseRequest; import org.elasticsearch.license.plugin.core.*; @@ -22,7 +21,7 @@ import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; -import static org.elasticsearch.license.TestUtils.generateSignedLicense; +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; diff --git a/src/test/java/org/elasticsearch/license/plugin/LicensesMetaDataSerializationTests.java b/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesMetaDataSerializationTests.java similarity index 95% rename from src/test/java/org/elasticsearch/license/plugin/LicensesMetaDataSerializationTests.java rename to plugin/src/test/java/org/elasticsearch/license/plugin/LicensesMetaDataSerializationTests.java index e23087880c9..13078b58faa 100644 --- a/src/test/java/org/elasticsearch/license/plugin/LicensesMetaDataSerializationTests.java +++ b/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesMetaDataSerializationTests.java @@ -10,21 +10,20 @@ import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentParser; -import org.elasticsearch.license.AbstractLicensingTestBase; -import org.elasticsearch.license.TestUtils; 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.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; -import static com.carrotsearch.randomizedtesting.RandomizedTest.randomIntBetween; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; -public class LicensesMetaDataSerializationTests extends AbstractLicensingTestBase { +public class LicensesMetaDataSerializationTests extends ElasticsearchTestCase { @Test public void testXContentSerializationOneSignedLicense() throws Exception { diff --git a/src/test/java/org/elasticsearch/license/plugin/LicensesPluginIntegrationTests.java b/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesPluginIntegrationTests.java similarity index 100% rename from src/test/java/org/elasticsearch/license/plugin/LicensesPluginIntegrationTests.java rename to plugin/src/test/java/org/elasticsearch/license/plugin/LicensesPluginIntegrationTests.java diff --git a/src/test/java/org/elasticsearch/license/plugin/LicensesPluginsIntegrationTests.java b/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesPluginsIntegrationTests.java similarity index 95% rename from src/test/java/org/elasticsearch/license/plugin/LicensesPluginsIntegrationTests.java rename to plugin/src/test/java/org/elasticsearch/license/plugin/LicensesPluginsIntegrationTests.java index dc038a33b1e..72e591f0ec0 100644 --- a/src/test/java/org/elasticsearch/license/plugin/LicensesPluginsIntegrationTests.java +++ b/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesPluginsIntegrationTests.java @@ -27,8 +27,6 @@ public class LicensesPluginsIntegrationTests extends AbstractLicensesIntegration protected Settings nodeSettings(int nodeOrdinal) { return ImmutableSettings.settingsBuilder() .put(super.nodeSettings(nodeOrdinal)) - .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()) .build(); } @@ -44,7 +42,7 @@ public class LicensesPluginsIntegrationTests extends AbstractLicensesIntegration } @After - public void beforeTest() throws Exception { + public void afterTest() throws Exception { wipeAllLicenses(); } @@ -62,7 +60,7 @@ public class LicensesPluginsIntegrationTests extends AbstractLicensesIntegration @Test public void testOneTrialAndNonTrialConsumer() throws Exception { int nNodes = randomIntBetween(2, 10); - int consumer2TrialLicenseDuration = 2; + int consumer2TrialLicenseDuration = 5; startNodesWithConsumerPlugins(nNodes, -1, consumer2TrialLicenseDuration); logger.info(" --> trial license generated for " + FEATURE_NAME_2 + " no trial license for " + FEATURE_NAME_1); @@ -92,8 +90,8 @@ public class LicensesPluginsIntegrationTests extends AbstractLicensesIntegration public void testMultipleConsumerPlugins() throws Exception { int nNodes = randomIntBetween(2, 10); - int consumer1TrialLicenseExpiry = 2; - int consumer2TrialLicenseExpiry = 2; + int consumer1TrialLicenseExpiry = 5; + int consumer2TrialLicenseExpiry = 5; startNodesWithConsumerPlugins(nNodes, consumer1TrialLicenseExpiry, consumer2TrialLicenseExpiry); logger.info(" --> trial license generated"); @@ -133,8 +131,8 @@ public class LicensesPluginsIntegrationTests extends AbstractLicensesIntegration @Test public void testRandomFeatureLicensesActions() throws Exception { int nNodes = randomIntBetween(2, 10); - int trialLicenseDuration1 = rarely() ? -1 : randomIntBetween(2, 3); - int trialLicenseDuration2 = rarely() ? -1 : randomIntBetween(2, 3); + int trialLicenseDuration1 = rarely() ? -1 : randomIntBetween(4, 6); + int trialLicenseDuration2 = rarely() ? -1 : randomIntBetween(4, 6); startNodesWithConsumerPlugins(nNodes, trialLicenseDuration1, trialLicenseDuration2); diff --git a/src/test/java/org/elasticsearch/license/plugin/LicensesServiceClusterTest.java b/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesServiceClusterTest.java similarity index 98% rename from src/test/java/org/elasticsearch/license/plugin/LicensesServiceClusterTest.java rename to plugin/src/test/java/org/elasticsearch/license/plugin/LicensesServiceClusterTest.java index edc5fd47e00..98fc5908ee3 100644 --- a/src/test/java/org/elasticsearch/license/plugin/LicensesServiceClusterTest.java +++ b/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesServiceClusterTest.java @@ -9,7 +9,6 @@ import org.elasticsearch.client.ClusterAdminClient; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.license.TestUtils; import org.elasticsearch.license.core.License; import org.elasticsearch.license.plugin.action.get.GetLicenseRequestBuilder; import org.elasticsearch.license.plugin.action.get.GetLicenseResponse; @@ -28,7 +27,7 @@ import java.util.ArrayList; import java.util.List; import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder; -import static org.elasticsearch.license.TestUtils.generateSignedLicense; +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; diff --git a/src/test/java/org/elasticsearch/license/plugin/LicensesServiceNodeTests.java b/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesServiceNodeTests.java similarity index 97% rename from src/test/java/org/elasticsearch/license/plugin/LicensesServiceNodeTests.java rename to plugin/src/test/java/org/elasticsearch/license/plugin/LicensesServiceNodeTests.java index 30238167802..59855b10b21 100644 --- a/src/test/java/org/elasticsearch/license/plugin/LicensesServiceNodeTests.java +++ b/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesServiceNodeTests.java @@ -29,7 +29,7 @@ public class LicensesServiceNodeTests extends AbstractLicensesIntegrationTests { protected Settings nodeSettings(int nodeOrdinal) { return ImmutableSettings.settingsBuilder() .put(super.nodeSettings(nodeOrdinal)) - .put(EagerLicenseRegistrationConsumerPlugin.NAME + ".trial_license_duration_in_seconds", 5) + .put(EagerLicenseRegistrationConsumerPlugin.NAME + ".trial_license_duration_in_seconds", 60 * 5) .putArray("plugin.types", LicensePlugin.class.getName(), EagerLicenseRegistrationConsumerPlugin.class.getName()) .put(InternalNode.HTTP_ENABLED, true) .build(); diff --git a/src/test/java/org/elasticsearch/license/plugin/LicensesTransportTests.java b/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesTransportTests.java similarity index 98% rename from src/test/java/org/elasticsearch/license/plugin/LicensesTransportTests.java rename to plugin/src/test/java/org/elasticsearch/license/plugin/LicensesTransportTests.java index 6bd809dd4c2..a41efd2e8c8 100644 --- a/src/test/java/org/elasticsearch/license/plugin/LicensesTransportTests.java +++ b/plugin/src/test/java/org/elasticsearch/license/plugin/LicensesTransportTests.java @@ -8,7 +8,6 @@ package org.elasticsearch.license.plugin; import org.elasticsearch.action.ActionFuture; import org.elasticsearch.common.collect.Sets; import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.license.TestUtils; import org.elasticsearch.license.core.License; import org.elasticsearch.license.plugin.action.delete.DeleteLicenseRequestBuilder; import org.elasticsearch.license.plugin.action.delete.DeleteLicenseResponse; @@ -24,8 +23,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import static org.elasticsearch.license.AbstractLicensingTestBase.dateMath; -import static org.elasticsearch.license.TestUtils.generateSignedLicense; +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; diff --git a/src/test/java/org/elasticsearch/license/TestUtils.java b/plugin/src/test/java/org/elasticsearch/license/plugin/TestUtils.java similarity index 99% rename from src/test/java/org/elasticsearch/license/TestUtils.java rename to plugin/src/test/java/org/elasticsearch/license/plugin/TestUtils.java index 45aad9fe6d0..311ec249c9b 100644 --- a/src/test/java/org/elasticsearch/license/TestUtils.java +++ b/plugin/src/test/java/org/elasticsearch/license/plugin/TestUtils.java @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.license; +package org.elasticsearch.license.plugin; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.xcontent.ToXContent; diff --git a/src/test/java/org/elasticsearch/license/plugin/TrailLicenseSerializationTests.java b/plugin/src/test/java/org/elasticsearch/license/plugin/TrailLicenseSerializationTests.java similarity index 84% rename from src/test/java/org/elasticsearch/license/plugin/TrailLicenseSerializationTests.java rename to plugin/src/test/java/org/elasticsearch/license/plugin/TrailLicenseSerializationTests.java index dd532f75ec4..877c5a6346c 100644 --- a/src/test/java/org/elasticsearch/license/plugin/TrailLicenseSerializationTests.java +++ b/plugin/src/test/java/org/elasticsearch/license/plugin/TrailLicenseSerializationTests.java @@ -6,18 +6,16 @@ package org.elasticsearch.license.plugin; import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.license.AbstractLicensingTestBase; -import org.elasticsearch.license.TestUtils; 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; -import static com.carrotsearch.randomizedtesting.RandomizedTest.randomIntBetween; -public class TrailLicenseSerializationTests extends AbstractLicensingTestBase { +public class TrailLicenseSerializationTests extends ElasticsearchTestCase { @Test public void testSerialization() throws Exception { diff --git a/src/test/java/org/elasticsearch/license/plugin/consumer/EagerLicenseRegistrationConsumerPlugin.java b/plugin/src/test/java/org/elasticsearch/license/plugin/consumer/EagerLicenseRegistrationConsumerPlugin.java similarity index 92% rename from src/test/java/org/elasticsearch/license/plugin/consumer/EagerLicenseRegistrationConsumerPlugin.java rename to plugin/src/test/java/org/elasticsearch/license/plugin/consumer/EagerLicenseRegistrationConsumerPlugin.java index 4627a982247..eeef14a3e48 100644 --- a/src/test/java/org/elasticsearch/license/plugin/consumer/EagerLicenseRegistrationConsumerPlugin.java +++ b/plugin/src/test/java/org/elasticsearch/license/plugin/consumer/EagerLicenseRegistrationConsumerPlugin.java @@ -10,7 +10,7 @@ import org.elasticsearch.common.settings.Settings; /** * Registers licenses upon the start of the service lifecycle - * see {@link org.elasticsearch.license.plugin.consumer.EagerLicenseRegistrationPluginService} + * see {@link EagerLicenseRegistrationPluginService} *

* License registration might happen before clusterService start() */ diff --git a/src/test/java/org/elasticsearch/license/plugin/consumer/EagerLicenseRegistrationPluginService.java b/plugin/src/test/java/org/elasticsearch/license/plugin/consumer/EagerLicenseRegistrationPluginService.java similarity index 100% rename from src/test/java/org/elasticsearch/license/plugin/consumer/EagerLicenseRegistrationPluginService.java rename to plugin/src/test/java/org/elasticsearch/license/plugin/consumer/EagerLicenseRegistrationPluginService.java diff --git a/src/test/java/org/elasticsearch/license/plugin/consumer/LazyLicenseRegistrationConsumerPlugin.java b/plugin/src/test/java/org/elasticsearch/license/plugin/consumer/LazyLicenseRegistrationConsumerPlugin.java similarity index 92% rename from src/test/java/org/elasticsearch/license/plugin/consumer/LazyLicenseRegistrationConsumerPlugin.java rename to plugin/src/test/java/org/elasticsearch/license/plugin/consumer/LazyLicenseRegistrationConsumerPlugin.java index 6ede4f07021..a0202b0651b 100644 --- a/src/test/java/org/elasticsearch/license/plugin/consumer/LazyLicenseRegistrationConsumerPlugin.java +++ b/plugin/src/test/java/org/elasticsearch/license/plugin/consumer/LazyLicenseRegistrationConsumerPlugin.java @@ -10,7 +10,7 @@ import org.elasticsearch.common.settings.Settings; /** * Registers licenses only after cluster has recovered - * see {@link org.elasticsearch.license.plugin.consumer.LazyLicenseRegistrationPluginService} + * see {@link LazyLicenseRegistrationPluginService} *

* License registration happens after clusterservice start() */ diff --git a/src/test/java/org/elasticsearch/license/plugin/consumer/LazyLicenseRegistrationPluginService.java b/plugin/src/test/java/org/elasticsearch/license/plugin/consumer/LazyLicenseRegistrationPluginService.java similarity index 100% rename from src/test/java/org/elasticsearch/license/plugin/consumer/LazyLicenseRegistrationPluginService.java rename to plugin/src/test/java/org/elasticsearch/license/plugin/consumer/LazyLicenseRegistrationPluginService.java diff --git a/src/test/java/org/elasticsearch/license/plugin/consumer/TestConsumerPluginBase.java b/plugin/src/test/java/org/elasticsearch/license/plugin/consumer/TestConsumerPluginBase.java similarity index 100% rename from src/test/java/org/elasticsearch/license/plugin/consumer/TestConsumerPluginBase.java rename to plugin/src/test/java/org/elasticsearch/license/plugin/consumer/TestConsumerPluginBase.java diff --git a/src/test/java/org/elasticsearch/license/plugin/consumer/TestPluginServiceBase.java b/plugin/src/test/java/org/elasticsearch/license/plugin/consumer/TestPluginServiceBase.java similarity index 98% rename from src/test/java/org/elasticsearch/license/plugin/consumer/TestPluginServiceBase.java rename to plugin/src/test/java/org/elasticsearch/license/plugin/consumer/TestPluginServiceBase.java index 40d123a8b04..f7586ca06de 100644 --- a/src/test/java/org/elasticsearch/license/plugin/consumer/TestPluginServiceBase.java +++ b/plugin/src/test/java/org/elasticsearch/license/plugin/consumer/TestPluginServiceBase.java @@ -31,7 +31,7 @@ public abstract class TestPluginServiceBase extends AbstractLifecycleComponent1TXv1%Bc_wbLO>E3}&#D<@-rDJ$(p047kR zkI3mLE>J{X5~_|GE5>Bxd81`fV@~0j8z81fwu78=uPV1?-b_fL$snD`NE}Zsv(l}S z+Dr52K=W~W#&Y(zE)IK9$=-71EtPe#X0XhttX&@1ia@?lvh&>PD=A#>rfdl2Ru)*H zKaKRTp&qI~gmO-)fq;gzrbngk1r$cUKd~25@6;rjPJf6eLtCHTaDU8Rbt#KGKlZ%g zPd`h6iZ4kWgcXo9P=@b~YoN9WQmtytp^dd%)MXVsW%n~=T9#TzSWvr*YCR25X&mo6 zJoJz>&ju@jBz@-J;se7XMiU5&x@g8>FTI*r^O6Xv2(VF_R@Vk3wQBmIE>&XqH^t=M z5_c~f_`fm)R~9ZqEv|Ma3$nQ}LvHLD`h~L2VKXBZwZnP`c6%Qwnwq8Z0!hd2+^*Gk z6R7QdYCwK?kavUU0Vd*Mq5K{M!Vk zzSLrHwA_oZsoml1+m@@Wyh8$ZA^E2_FpxTTRz7~A$x?V+XFW0!aa4^L&A*^Evlz{gN8ae8h9=J=b zC8F19FN`xNpxA!48b`dGRK3GbQMOho1>byaB*psVh{^^yqVL4J0~$j7viqxma>pYOhkH~PwpJT1j6^yHDMWGO{vw8PyI zIrYD&$F3e@0!346r3BY7JkLDD+7E5EE6oiV(gQ62K@eQRE&#pRq81Tut!V+1TCM~srn6-g`!g_`uozhhJEnN6u9$5|& zLC>$@xw*^CD*fb$ngUWU)yZ%TqX*wM!HU2(O2RRFnw&?^e*xOZWZ?n`No9lb?BLpV=@K}hkB uJ-}qCO)pTE(AWQ24*9x_mu179!iEY^J(*;5;=+=*kZC+fDbTdAaQBAù<}[Á2ÖÓàZÖ|5‹¯ÊÊ7%ØêD +Yå‘xn:¼lúLÈæHò¢«Ë2˜ŸHvEEWÇ\¦H:“6Žh9 [!š…Ûæ©Š¤+;Ö.w7Cì©_|Þ ÓªÏÁ*ñ§D`ƒÚ?‚ùxU/3>x­UÓ“+ è \ No newline at end of file diff --git a/pom.xml b/pom.xml index fe93e4411b7..8cc082af52a 100644 --- a/pom.xml +++ b/pom.xml @@ -6,13 +6,28 @@ org.elasticsearch elasticsearch-license + pom 1.0.0-SNAPSHOT + + core-shaded + core + licensor + plugin + + UTF-8 1.4.0 4.10.2 - - ${basedir}/src/test/resources + auto + true + onerror + ${project.basedir}/backwards + INFO + 512m + 5 + .local-${project.version}-execution-hints.log + ${project.basedir} @@ -117,6 +132,12 @@ ${lucene.version} compile + + org.apache.lucene + lucene-expressions + ${lucene.version} + compile + @@ -128,19 +149,6 @@ - - - ${keys.path} - false - - public.key - - - - src/main/resources - true - - org.apache.maven.plugins @@ -164,49 +172,96 @@ + org.apache.maven.plugins maven-surefire-plugin 2.16 - 1 - false - - **/*Tests.java - + true - maven-assembly-plugin - 2.4 - - ${project.build.directory}/releases/ - + de.thetaphi + forbiddenapis + 1.6.1 + - plugin - package - - single - + check-forbidden-apis - false - - ${basedir}/src/main/assemblies/plugin.xml - + 1.7 + + true + + false + + jsr166e/** + + org/elasticsearch/shield/support/cli/Terminal* + org/elasticsearch/common/logging/log4j/ConsoleAppender* + org/elasticsearch/plugins/PluginManager.class + org/elasticsearch/bootstrap/Bootstrap.class + org/elasticsearch/Version.class + + org/elasticsearch/common/lucene/search/Queries$QueryWrapperFilterFactory.class + + + + org/elasticsearch/common/util/UnsafeUtils.class + + + org/elasticsearch/common/util/MathUtils.class + org/elasticsearch/common/math/UnboxedMathUtils.class + org/elasticsearch/cluster/routing/operation/plain/PlainOperationRouting.class + + + + org/elasticsearch/common/lucene/search/XFilteredQuery.class + + + org/elasticsearch/common/io/Channels.class + + + + + jdk-unsafe + jdk-deprecated + jdk-system-out + + + ${license.basedir}/core-signatures.txt + ${license.basedir}/all-signatures.txt + + ${forbidden.signatures} + compile + + check + - exec - package - - single - + check-forbidden-test-apis - true - - ${basedir}/src/main/assemblies/exec.xml - + 1.7 + + true + + false + + + jdk-unsafe + jdk-deprecated + + + ${license.basedir}/test-signatures.txt + ${license.basedir}/all-signatures.txt + + ${forbidden.test.signatures} + test-compile + + testCheck + @@ -228,59 +283,6 @@ - - - enforce-property - - enforce - - - - - keys.path - "You must set a keys.path property!" - - - true - - - - - - org.apache.maven.plugins - maven-jar-plugin - 2.4 - - - for-plugin - prepare-package - - jar - - - - - org/elasticsearch/license/licensor/**/* - - - - - for-exec - prepare-package - - jar - - - exec - - - public.key - - es-plugin.properties - org/elasticsearch/license/plugin/**/* - - - @@ -288,13 +290,13 @@ license-maven-plugin 2.5 -

dev-tools/elasticsearch_license_header.txt
+
${license.basedir}/dev-tools/elasticsearch_license_header.txt
- dev-tools/license_header_definition.xml + ${license.basedir}/dev-tools/license_header_definition.xml - src/main/java/org/elasticsearch/**/*.java - src/test/java/org/elasticsearch/**/*.java + **/src/main/java/org/elasticsearch/**/*.java + **/src/test/java/org/elasticsearch/**/*.java @@ -319,5 +321,23 @@ + + default + + true + + + + + com.carrotsearch.randomizedtesting + junit4-maven-plugin + 2.1.2 + + ${tests.jvm.argline} + + + + + diff --git a/test-signatures.txt b/test-signatures.txt new file mode 100644 index 00000000000..e69de29bb2d