- added serialization tests

- added license signature tests
- refactor unit tests
- testing infra
- cleanup license tools
- nuked FileBasedLicenseProvider

Original commit: elastic/x-pack-elasticsearch@2af36aecfa
This commit is contained in:
Areek Zillur 2014-11-03 20:57:25 -05:00
parent e0ec8f6059
commit 6c116e2fb3
14 changed files with 591 additions and 537 deletions

View File

@ -1,36 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.license.licensor.tools;
import org.elasticsearch.common.collect.ImmutableMap;
import org.elasticsearch.license.core.ESLicense;
import org.elasticsearch.license.core.ESLicenses;
import java.util.Map;
import java.util.Set;
/**
*/
public class FileBasedESLicenseProvider {
private ImmutableMap<String, ESLicense> esLicenses;
public FileBasedESLicenseProvider(Set<ESLicense> esLicenses) {
this.esLicenses = ESLicenses.reduceAndMap(esLicenses);
}
public ESLicense getESLicense(String feature) {
return esLicenses.get(feature);
}
public Map<String, ESLicense> getEffectiveLicenses() {
return esLicenses;
}
// For testing
public void setLicenses(Set<ESLicense> esLicenses) {
this.esLicenses = ESLicenses.reduceAndMap(esLicenses);
}
}

View File

@ -69,13 +69,17 @@ public class LicenseGeneratorTool {
}
if (licenseSpecs.size() == 0) {
throw new IllegalArgumentException("at least one of '--licenses' or '--licenseFile' has to be provided");
throw new IllegalArgumentException("at least one of '--license' or '--licenseFile' has to be provided");
}
if (publicKeyPath == null) {
throw new IllegalArgumentException("mandatory option '--publicKeyPath' is missing");
} else if (!Paths.get(publicKeyPath).toFile().exists()) {
throw new IllegalArgumentException("Public key file: " + publicKeyPath + " does not exist!");
}
if (privateKeyPath == null) {
throw new IllegalArgumentException("mandatory option '--privateKeyPath' is missing");
} else if (!Paths.get(privateKeyPath).toFile().exists()) {
throw new IllegalArgumentException("Private key file: " + privateKeyPath + " does not exist!");
}
return new Options(licenseSpecs, publicKeyPath, privateKeyPath);

View File

@ -5,6 +5,7 @@
*/
package org.elasticsearch.license.licensor.tools;
import org.elasticsearch.common.collect.ImmutableMap;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
@ -23,15 +24,7 @@ import java.util.Set;
public class LicenseVerificationTool {
static class Options {
private final Set<ESLicense> licenses;
Options(Set<ESLicense> licenses) {
this.licenses = licenses;
}
}
private static Options parse(String[] args) throws IOException {
private static Set<ESLicense> parse(String[] args) throws IOException {
Set<ESLicense> licenses = new HashSet<>();
for (int i = 0; i < args.length; i++) {
@ -55,7 +48,7 @@ public class LicenseVerificationTool {
if (licenses.size() == 0) {
throw new IllegalArgumentException("mandatory option '--licensesFiles' or '--licenses' is missing");
}
return new Options(licenses);
return licenses;
}
public static void main(String[] args) throws IOException {
@ -63,16 +56,16 @@ public class LicenseVerificationTool {
}
public static void run(String[] args, OutputStream out) throws IOException {
Options options = parse(args);
Set<ESLicense> licenses = parse(args);
// verify licenses
FileBasedESLicenseProvider licenseProvider = new FileBasedESLicenseProvider(options.licenses);
// reduce & verify licenses
ImmutableMap<String, ESLicense> effectiveLicenses = ESLicenses.reduceAndMap(licenses);
ESLicenseManager licenseManager = new ESLicenseManager();
licenseManager.verifyLicenses(licenseProvider.getEffectiveLicenses());
licenseManager.verifyLicenses(effectiveLicenses);
// dump effective licences
XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON, out);
ESLicenses.toXContent(licenseProvider.getEffectiveLicenses().values(), builder, ToXContent.EMPTY_PARAMS);
ESLicenses.toXContent(effectiveLicenses.values(), builder, ToXContent.EMPTY_PARAMS);
builder.flush();
}

View File

@ -483,9 +483,9 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
if (logger.isDebugEnabled()) {
String status;
if (expiryDate != -1l) {
status = "license expires in : " + TimeValue.timeValueMillis(expiryDate - System.currentTimeMillis());
status = " status: license expires in : " + TimeValue.timeValueMillis(expiryDate - System.currentTimeMillis());
} else {
status = "no trial/signed license found";
status = " status: no trial/signed license found";
}
if (expiryDuration > 0l) {
status += " action: enableFeatureIfNeeded";
@ -496,13 +496,15 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
}
}
logLicenseMetaDataStats("Setting last observed metaData", currentLicensesMetaData);
lastObservedLicensesState.set(currentLicensesMetaData);
if (nextScheduleFrequency == -1l) {
logger.debug("no need to schedule next notification");
} else {
logger.debug("next notification time: " + TimeValue.timeValueMillis(nextScheduleFrequency).toString());
if (logger.isDebugEnabled()) {
logLicenseMetaDataStats("Setting last observed metaData", currentLicensesMetaData);
if (nextScheduleFrequency == -1l) {
logger.debug("no need to schedule next notification");
} else {
logger.debug("next notification time: " + TimeValue.timeValueMillis(nextScheduleFrequency).toString());
}
}
return nextScheduleFrequency;
@ -531,19 +533,14 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
* if new feature has a non-null trial license option, a master node request is made to generate the trial license
* if no trial license option is specified for the feature and no signed license is found,
* then notifies features to be disabled
* then notifies features to be disabled
*
* @param listenerHolder of the feature to register
* @return true if registration has been completed, false otherwise (if masterNode is not available & trail license spec is provided
* or if there is a global block on {@link org.elasticsearch.gateway.GatewayService#STATE_NOT_RECOVERED_BLOCK})
*/
private boolean registerListener(final ListenerHolder listenerHolder) {
logger.debug("Registering listener for " + listenerHolder.feature);
ClusterState currentState = clusterService.state();
if (currentState.blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK)) {
logger.debug("Store as pendingRegistration [cluster has NOT_RECOVERED_BLOCK]");
return false;
}
LicensesMetaData currentMetaData = currentState.metaData().custom(LicensesMetaData.TYPE);
if (expiryDateForFeature(listenerHolder.feature, currentMetaData) == -1l) {
// does not have any license so generate a trial license

View File

@ -5,24 +5,51 @@
*/
package org.elasticsearch.license;
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.XContentBuilder;
import org.elasticsearch.license.core.DateUtils;
import org.elasticsearch.license.core.ESLicense;
import org.elasticsearch.license.licensor.ESLicenseSigner;
import org.elasticsearch.license.manager.ESLicenseManager;
import org.elasticsearch.test.ElasticsearchTestCase;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import java.io.IOException;
import java.net.URL;
import java.text.ParseException;
import java.util.Map;
import java.util.*;
import java.util.concurrent.TimeUnit;
import static com.carrotsearch.randomizedtesting.RandomizedTest.randomIntBetween;
import static com.carrotsearch.randomizedtesting.RandomizedTest.randomRealisticUnicodeOfCodepointLengthBetween;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.elasticsearch.test.ElasticsearchTestCase.randomFrom;
@RunWith(value = com.carrotsearch.randomizedtesting.RandomizedRunner.class)
public class AbstractLicensingTestBase {
protected static String pubKeyPath = null;
protected static String priKeyPath = null;
private final FormatDateTimeFormatter formatDateTimeFormatter = Joda.forPattern("yyyy-MM-dd");
private final org.elasticsearch.common.joda.time.format.DateTimeFormatter dateTimeFormatter = formatDateTimeFormatter.printer();
private final DateMathParser dateMathParser = new DateMathParser(formatDateTimeFormatter, TimeUnit.MILLISECONDS);
@BeforeClass
public static void setup() throws Exception {
pubKeyPath = getResourcePath("/public.key");
priKeyPath = getResourcePath("/private.key");
}
protected String dateMathString(String time, long now) {
return dateTimeFormatter.print(dateMathParser.parse(time, now));
}
protected long dateMath(String time, long now) {
return dateMathParser.parse(time, now);
}
public static String getTestPriKeyPath() throws Exception {
@ -38,8 +65,112 @@ public class AbstractLicensingTestBase {
return url.toURI().getPath();
}
public String generateSignedLicenses(Map<String, TestUtils.FeatureAttributes> map) throws IOException, ParseException {
String licenseString = TestUtils.generateESLicenses(map);
return TestUtils.runLicenseGenerationTool(licenseString, pubKeyPath, priKeyPath);
protected LicenseSpec generateRandomLicenseSpec() {
long now = System.currentTimeMillis();
String issueDate = dateMathString("now", now);
String expiryDate = dateMathString("now+10d/d", now);
String uid = randomRealisticUnicodeOfCodepointLengthBetween(2, 10);
String feature = randomRealisticUnicodeOfCodepointLengthBetween(5, 15);
String issuer = randomRealisticUnicodeOfCodepointLengthBetween(5, 15);
String issuedTo = randomRealisticUnicodeOfCodepointLengthBetween(5, 15);
String type = randomFrom("subscription", "internal", "development");
String subscriptionType = randomFrom("none", "gold", "silver", "platinum");
int maxNodes = randomIntBetween(5, 100);
return new LicenseSpec(uid, feature, issueDate, expiryDate, type, subscriptionType, issuedTo, issuer, maxNodes);
}
public static String generateESLicenseSpecString(List<LicenseSpec> 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("issue_date", licenseSpec.issueDate)
.field("expiry_date", licenseSpec.expiryDate)
.field("feature", licenseSpec.feature)
.field("max_nodes", licenseSpec.maxNodes)
.endObject();
}
licenses.endArray();
licenses.endObject();
return licenses.string();
}
public static Set<ESLicense> generateSignedLicenses(List<LicenseSpec> licenseSpecs) throws Exception {
ESLicenseSigner signer = new ESLicenseSigner(getTestPriKeyPath(), getTestPubKeyPath());
Set<ESLicense> unSignedLicenses = new HashSet<>();
for (LicenseSpec spec : licenseSpecs) {
unSignedLicenses.add(ESLicense.builder()
.uid(spec.uid)
.feature(spec.feature)
.expiryDate(DateUtils.endOfTheDay(spec.expiryDate))
.issueDate(DateUtils.beginningOfTheDay(spec.issueDate))
.type(spec.type)
.subscriptionType(spec.subscriptionType)
.issuedTo(spec.issuedTo)
.issuer(spec.issuer)
.maxNodes(spec.maxNodes)
.build()
);
}
return signer.sign(unSignedLicenses);
}
public static ESLicense generateSignedLicense(String feature, TimeValue expiryDuration) throws Exception {
return generateSignedLicense(feature, -1, expiryDuration);
}
public static ESLicense generateSignedLicense(String feature, long issueDate, TimeValue expiryDuration) throws Exception {
long issue = (issueDate != -1l) ? issueDate : System.currentTimeMillis();
final ESLicense licenseSpec = ESLicense.builder()
.uid(UUID.randomUUID().toString())
.feature(feature)
.expiryDate(issue + expiryDuration.getMillis())
.issueDate(issue)
.type("subscription")
.subscriptionType("gold")
.issuedTo("customer")
.issuer("elasticsearch")
.maxNodes(5)
.build();
ESLicenseSigner signer = new ESLicenseSigner(getTestPriKeyPath(), getTestPubKeyPath());
return signer.sign(licenseSpec);
}
public static class LicenseSpec {
public final String feature;
public final String issueDate;
public final String expiryDate;
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, String issueDate, String expiryDate, String type,
String subscriptionType, String issuedTo, String issuer, int maxNodes) {
this.feature = feature;
this.issueDate = issueDate;
this.expiryDate = expiryDate;
this.uid = uid;
this.type = type;
this.subscriptionType = subscriptionType;
this.issuedTo = issuedTo;
this.issuer = issuer;
this.maxNodes = maxNodes;
}
}
}

View File

@ -5,96 +5,15 @@
*/
package org.elasticsearch.license;
import org.apache.commons.io.FileUtils;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.license.core.DateUtils;
import org.elasticsearch.license.core.ESLicense;
import org.elasticsearch.license.core.ESLicenses;
import org.elasticsearch.license.licensor.tools.LicenseGeneratorTool;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.ParseException;
import java.util.*;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.junit.Assert.assertTrue;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertThat;
public class TestUtils {
public final static String SHIELD = "shield";
public final static String MARVEL = "marvel";
public static String generateESLicenses(Map<String, FeatureAttributes> featureAttributes) throws IOException {
XContentBuilder licenses = jsonBuilder();
licenses.startObject();
licenses.startArray("licenses");
for (FeatureAttributes attributes : featureAttributes.values()) {
licenses.startObject()
.field("uid", attributes.uid)
.field("type", attributes.type)
.field("subscription_type", attributes.subscriptionType)
.field("issued_to", attributes.issuedTo)
.field("issuer", attributes.issuer)
.field("issue_date", attributes.issueDate)
.field("expiry_date", attributes.expiryDate)
.field("feature", attributes.featureType)
.field("max_nodes", attributes.maxNodes)
.endObject();
}
licenses.endArray();
licenses.endObject();
return licenses.string();
}
public static String runLicenseGenerationTool(String licenseInput, String pubKeyPath, String priKeyPath) throws IOException, ParseException {
String args[] = new String[6];
args[0] = "--license";
args[1] = licenseInput;
args[2] = "--publicKeyPath";
args[3] = pubKeyPath;
args[4] = "--privateKeyPath";
args[5] = priKeyPath;
return runLicenseGenerationTool(args);
}
public static String runLicenseGenerationTool(String[] args) throws IOException, ParseException {
File temp = File.createTempFile("temp", ".out");
temp.deleteOnExit();
try (FileOutputStream outputStream = new FileOutputStream(temp)) {
LicenseGeneratorTool.run(args, outputStream);
}
return FileUtils.readFileToString(temp);
}
public static void verifyESLicenses(Set<ESLicense> esLicenses, Map<String, FeatureAttributes> featureAttributesMap) throws ParseException {
verifyESLicenses(ESLicenses.reduceAndMap(esLicenses), featureAttributesMap);
}
public static void verifyESLicenses(Map<String, ESLicense> esLicenses, Map<String, FeatureAttributes> featureAttributes) throws ParseException {
assertTrue("Number of feature licenses should be " + featureAttributes.size(), esLicenses.size() == featureAttributes.size());
for (Map.Entry<String, FeatureAttributes> featureAttrTuple : featureAttributes.entrySet()) {
String featureType = featureAttrTuple.getKey();
FeatureAttributes attributes = featureAttrTuple.getValue();
final ESLicense esLicense = esLicenses.get(featureType);
assertTrue("license for " + featureType + " should be present", esLicense != null);
assertTrue("expected value for issuedTo was: " + attributes.issuedTo + " but got: " + esLicense.issuedTo(), esLicense.issuedTo().equals(attributes.issuedTo));
assertTrue("expected value for type was: " + attributes.type + " but got: " + esLicense.type(), esLicense.type().equals(attributes.type));
assertTrue("expected value for subscriptionType was: " + attributes.subscriptionType + " but got: " + esLicense.subscriptionType(), esLicense.subscriptionType().equals(attributes.subscriptionType));
assertTrue("expected value for feature was: " + attributes.featureType + " but got: " + esLicense.feature(), esLicense.feature().equals(attributes.featureType));
assertTrue("expected value for issueDate was: " + DateUtils.beginningOfTheDay(attributes.issueDate) + " but got: " + esLicense.issueDate(), esLicense.issueDate() == DateUtils.beginningOfTheDay(attributes.issueDate));
assertTrue("expected value for expiryDate: " + DateUtils.endOfTheDay(attributes.expiryDate) + " but got: " + esLicense.expiryDate(), esLicense.expiryDate() == DateUtils.endOfTheDay(attributes.expiryDate));
assertTrue("expected value for maxNodes: " + attributes.maxNodes + " but got: " + esLicense.maxNodes(), esLicense.maxNodes() == attributes.maxNodes);
assertTrue("generated licenses should have non-null uid field", esLicense.uid() != null);
assertTrue("generated licenses should have non-null signature field", esLicense.signature() != null);
}
}
public static void isSame(Collection<ESLicense> firstLicenses, Collection<ESLicense> secondLicenses) {
isSame(new HashSet<>(firstLicenses), new HashSet<>(secondLicenses));
}
@ -106,58 +25,25 @@ public class TestUtils {
final Map<String, ESLicense> licenses2 = ESLicenses.reduceAndMap(secondLicenses);
// check if the effective licenses have the same feature set
assertTrue("Both licenses should have the same number of features", licenses1.size() == licenses2.size());
assertThat(licenses1.size(), equalTo(licenses2.size()));
// for every feature license, check if all the attributes are the same
for (String featureType : licenses1.keySet()) {
ESLicense license1 = licenses1.get(featureType);
ESLicense license2 = licenses2.get(featureType);
isSame(license1, license2);
}
}
public static void isSame(ESLicense license1, ESLicense license2) {
assertTrue("Should have same uid; got: " + license1.uid() + " and " + license2.uid(), license1.uid().equals(license2.uid()));
assertTrue("Should have same feature; got: " + license1.feature() + " and " + license2.feature(), license1.feature().equals(license2.feature()));
assertTrue("Should have same subscriptType; got: " + license1.subscriptionType() + " and " + license2.subscriptionType(), license1.subscriptionType().equals(license2.subscriptionType()));
assertTrue("Should have same type; got: " + license1.type() + " and " + license2.type(), license1.type().equals(license2.type()));
assertTrue("Should have same issuedTo; got: " + license1.issuedTo() + " and " + license2.issuedTo(), license1.issuedTo().equals(license2.issuedTo()));
assertTrue("Should have same signature; got: " + license1.signature() + " and " + license2.signature(), license1.signature().equals(license2.signature()));
assertTrue("Should have same expiryDate; got: " + license1.expiryDate() + " and " + license2.expiryDate(), license1.expiryDate() == license2.expiryDate());
assertTrue("Should have same issueDate; got: " + license1.issueDate() + " and " + license2.issueDate(), license1.issueDate() == license2.issueDate());
assertTrue("Should have same maxNodes; got: " + license1.maxNodes() + " and " + license2.maxNodes(), license1.maxNodes() == license2.maxNodes());
}
public static class FeatureAttributes {
public final String uid;
public final String featureType;
public final String type;
public final String subscriptionType;
public final String issuedTo;
public final int maxNodes;
public final String issueDate;
public final String expiryDate;
public final String issuer;
public FeatureAttributes(String featureType, String type, String subscriptionType, String issuedTo, String issuer, int maxNodes, String issueDateStr, String expiryDateStr) throws ParseException {
this(UUID.randomUUID().toString(), featureType, type, subscriptionType, issuedTo, issuer, maxNodes, issueDateStr, expiryDateStr);
}
public FeatureAttributes(String uid, String featureType, String type, String subscriptionType, String issuedTo, String issuer, int maxNodes, String issueDateStr, String expiryDateStr) throws ParseException {
this.uid = uid;
this.featureType = featureType;
this.type = type;
this.subscriptionType = subscriptionType;
this.issuedTo = issuedTo;
this.issuer = issuer;
this.maxNodes = maxNodes;
this.issueDate = issueDateStr;
this.expiryDate = expiryDateStr;
}
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()));
}
}

View File

@ -1,80 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.license.licensor;
import org.elasticsearch.license.AbstractLicensingTestBase;
import org.elasticsearch.license.TestUtils;
import org.elasticsearch.license.core.ESLicense;
import org.elasticsearch.license.core.ESLicenses;
import org.junit.Test;
import java.io.IOException;
import java.text.ParseException;
import java.util.*;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
public class LicenseGenerationTests extends AbstractLicensingTestBase {
@Test
public void testSimpleLicenseGeneration() throws ParseException, IOException {
Map<String, TestUtils.FeatureAttributes> map = new HashMap<>();
TestUtils.FeatureAttributes featureAttributes =
new TestUtils.FeatureAttributes("shield", "subscription", "platinum", "foo bar Inc.", "elasticsearch", 2, "2014-12-13", "2015-12-13");
map.put(TestUtils.SHIELD, featureAttributes);
String licenseOutput = generateSignedLicenses(map);
Set<ESLicense> esLicensesOutput = new HashSet<>(ESLicenses.fromSource(licenseOutput));
TestUtils.verifyESLicenses(esLicensesOutput, map);
}
@Test
public void testMultipleStrings() throws ParseException, IOException {
Map<String, TestUtils.FeatureAttributes> map = new HashMap<>();
TestUtils.FeatureAttributes shildFeatureAttributes =
new TestUtils.FeatureAttributes("shield", "trial", "none", "foo bar Inc.", "elasticsearch", 2, "2014-12-13", "2015-12-13");
TestUtils.FeatureAttributes marvelFeatureAttributes =
new TestUtils.FeatureAttributes("marvel", "subscription", "silver", "foo1 bar Inc.", "elasticsearc3h", 10, "2014-01-13", "2014-12-13");
map.put(TestUtils.SHIELD, shildFeatureAttributes);
map.put(TestUtils.MARVEL, marvelFeatureAttributes);
String licenseOutput = generateSignedLicenses(map);
Set<ESLicense> esLicensesOutput = new HashSet<>(ESLicenses.fromSource(licenseOutput));
TestUtils.verifyESLicenses(esLicensesOutput, map);
}
@Test
public void testMissingCLTArgs() throws ParseException, IOException {
Map<String, TestUtils.FeatureAttributes> map = new HashMap<>();
TestUtils.FeatureAttributes featureAttributes =
new TestUtils.FeatureAttributes("shiedgdsld", "internal", "none", "foo bar Inc.", "elasticsearch", 23, "2014-12-13", "2015-12-13");
map.put(TestUtils.SHIELD, featureAttributes);
String licenseString = TestUtils.generateESLicenses(map);
String[] args = new String[6];
args[0] = "--linse";
args[1] = licenseString;
args[2] = "--publicKeyPath";
args[3] = pubKeyPath;
args[4] = "--privateKeyPath";
args[5] = priKeyPath;
try {
String licenseOutput = TestUtils.runLicenseGenerationTool(args);
fail();
} catch (IllegalArgumentException e) {
assertTrue("Exception should indicate mandatory param --license, got: " + e.getMessage(), e.getMessage().contains("license"));
}
}
}

View File

@ -0,0 +1,134 @@
/*
* 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.apache.commons.io.FileUtils;
import org.elasticsearch.license.AbstractLicensingTestBase;
import org.elasticsearch.license.TestUtils;
import org.elasticsearch.license.core.ESLicense;
import org.elasticsearch.license.core.ESLicenses;
import org.elasticsearch.license.licensor.tools.LicenseGeneratorTool;
import org.junit.Test;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.text.ParseException;
import java.util.*;
import static com.carrotsearch.randomizedtesting.RandomizedTest.randomAsciiOfLength;
import static com.carrotsearch.randomizedtesting.RandomizedTest.randomBoolean;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.*;
public class LicenseGenerationToolTests extends AbstractLicensingTestBase {
@Test
public void testSimple() throws Exception {
LicenseSpec inputLicenseSpec = generateRandomLicenseSpec();
String[] args = new String[6];
args[0] = "--license";
args[1] = generateESLicenseSpecString(Arrays.asList(inputLicenseSpec));
args[2] = "--publicKeyPath";
args[3] = pubKeyPath;
args[4] = "--privateKeyPath";
args[5] = priKeyPath;
String licenseOutput = runLicenseGenerationTool(args);
List<ESLicense> outputLicenses = ESLicenses.fromSource(licenseOutput);
assertThat(outputLicenses.size(), equalTo(1));
assertThat(outputLicenses.get(0).signature(), notNullValue());
Set<ESLicense> expectedLicenses = generateSignedLicenses(Arrays.asList(inputLicenseSpec));
ESLicense expectedLicense = ESLicense.builder()
.fromLicenseSpec(expectedLicenses.iterator().next(), outputLicenses.get(0).signature())
.build();
TestUtils.isSame(expectedLicense, outputLicenses.get(0));
}
@Test
public void testWithLicenseFile() throws Exception {
LicenseSpec inputLicenseSpec = generateRandomLicenseSpec();
Path tempFilePath = Files.createTempFile("license_spec", "json");
File tempFile = tempFilePath.toFile();
FileUtils.write(tempFile, generateESLicenseSpecString(Arrays.asList(inputLicenseSpec)));
tempFile.deleteOnExit();
String[] args = new String[6];
args[0] = "--licenseFile";
args[1] = tempFile.getAbsolutePath();
args[2] = "--publicKeyPath";
args[3] = pubKeyPath;
args[4] = "--privateKeyPath";
args[5] = priKeyPath;
String licenseOutput = runLicenseGenerationTool(args);
List<ESLicense> outputLicenses = ESLicenses.fromSource(licenseOutput);
assertThat(outputLicenses.size(), equalTo(1));
assertThat(outputLicenses.get(0).signature(), notNullValue());
Set<ESLicense> expectedLicenses = generateSignedLicenses(Arrays.asList(inputLicenseSpec));
ESLicense expectedLicense = ESLicense.builder()
.fromLicenseSpec(expectedLicenses.iterator().next(), outputLicenses.get(0).signature())
.build();
TestUtils.isSame(expectedLicense, outputLicenses.get(0));
}
@Test
public void testBadKeyPath() throws Exception {
boolean pubKey = randomBoolean();
String[] args = new String[6];
args[0] = "--license";
args[1] = generateESLicenseSpecString(Arrays.asList(generateRandomLicenseSpec()));
args[2] = "--publicKeyPath";
args[3] = (pubKey) ? pubKeyPath + randomAsciiOfLength(3) : pubKeyPath;
args[4] = "--privateKeyPath";
args[5] = (!pubKey) ? priKeyPath + randomAsciiOfLength(3) : priKeyPath;
try {
runLicenseGenerationTool(args);
fail("Should not accept non-existent key paths");
} catch (IllegalArgumentException e) {
assertThat(e.getMessage(), containsString("does not exist"));
}
}
@Test
public void testMissingCLTArgs() throws Exception {
String[] args = new String[6];
args[0] = "--linse";
args[1] = generateESLicenseSpecString(Arrays.asList(generateRandomLicenseSpec()));
args[2] = "--publicKeyPath";
args[3] = pubKeyPath;
args[4] = "--privateKeyPath";
args[5] = priKeyPath;
try {
runLicenseGenerationTool(args);
fail("should not accept arguments without --license");
} catch (IllegalArgumentException e) {
assertThat(e.getMessage(), containsString("'--license'"));
}
}
private static String runLicenseGenerationTool(String[] args) throws Exception {
File temp = File.createTempFile("temp", ".out");
temp.deleteOnExit();
try (FileOutputStream outputStream = new FileOutputStream(temp)) {
LicenseGeneratorTool.run(args, outputStream);
}
return FileUtils.readFileToString(temp);
}
}

View File

@ -0,0 +1,94 @@
/*
* 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.license.AbstractLicensingTestBase;
import org.elasticsearch.license.TestUtils;
import org.elasticsearch.license.core.DateUtils;
import org.elasticsearch.license.core.ESLicense;
import org.elasticsearch.license.core.ESLicenses;
import org.elasticsearch.license.core.LicensesCharset;
import org.hamcrest.core.IsNull;
import org.junit.Test;
import java.io.IOException;
import java.text.ParseException;
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.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
public class LicenseSerializationTests extends AbstractLicensingTestBase {
@Test
public void testSimpleIssueExpiryDate() throws Exception {
long now = System.currentTimeMillis();
String issueDate = dateMathString("now", now);
String expiryDate = dateMathString("now+10d/d", now);
String licenseSpecs = generateESLicenseSpecString(Arrays.asList(new LicenseSpec("shield", issueDate, expiryDate)));
Set<ESLicense> esLicensesOutput = new HashSet<>(ESLicenses.fromSource(licenseSpecs.getBytes(LicensesCharset.UTF_8), false));
ESLicense generatedLicense = esLicensesOutput.iterator().next();
assertThat(esLicensesOutput.size(), equalTo(1));
assertThat(generatedLicense.issueDate(), equalTo(DateUtils.beginningOfTheDay(issueDate)));
assertThat(generatedLicense.expiryDate(), equalTo(DateUtils.endOfTheDay(expiryDate)));
}
@Test
public void testMultipleIssueExpiryDate() throws Exception {
long now = System.currentTimeMillis();
String shieldIssueDate = dateMathString("now", now);
String shieldExpiryDate = dateMathString("now+30d/d", now);
String marvelIssueDate = dateMathString("now", now);
String marvelExpiryDate = dateMathString("now+60d/d", now);
String licenseSpecs = generateESLicenseSpecString(Arrays.asList(new LicenseSpec("shield", shieldIssueDate, shieldExpiryDate)));
String licenseSpecs1 = generateESLicenseSpecString(Arrays.asList(new LicenseSpec("marvel", marvelIssueDate, marvelExpiryDate)));
Set<ESLicense> esLicensesOutput = new HashSet<>();
esLicensesOutput.addAll(ESLicenses.fromSource(licenseSpecs.getBytes(LicensesCharset.UTF_8), false));
esLicensesOutput.addAll(ESLicenses.fromSource(licenseSpecs1.getBytes(LicensesCharset.UTF_8), false));
assertThat(esLicensesOutput.size(), equalTo(2));
for (ESLicense esLicense : esLicensesOutput) {
assertThat(esLicense.issueDate(), equalTo(DateUtils.beginningOfTheDay((esLicense.feature().equals("shield")) ? shieldIssueDate : marvelIssueDate)));
assertThat(esLicense.expiryDate(), equalTo(DateUtils.endOfTheDay((esLicense.feature().equals("shield")) ? shieldExpiryDate : marvelExpiryDate)));
}
}
@Test
public void testLicensesFields() throws Exception {
Map<String, LicenseSpec> licenseSpecs = new HashMap<>();
for (int i = 0; i < randomIntBetween(1, 5); i++) {
LicenseSpec randomLicenseSpec = generateRandomLicenseSpec();
licenseSpecs.put(randomLicenseSpec.feature, randomLicenseSpec);
}
ArrayList<LicenseSpec> specs = new ArrayList<>(licenseSpecs.values());
String licenseSpecsSource = generateESLicenseSpecString(specs);
Set<ESLicense> esLicensesOutput = new HashSet<>(ESLicenses.fromSource(licenseSpecsSource.getBytes(LicensesCharset.UTF_8), false));
assertThat(esLicensesOutput.size(), equalTo(licenseSpecs.size()));
for (ESLicense license : esLicensesOutput) {
LicenseSpec spec = licenseSpecs.get(license.feature());
assertThat(spec, notNullValue());
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));
assertThat(license.issueDate(), equalTo(DateUtils.beginningOfTheDay(spec.issueDate)));
assertThat(license.expiryDate(), equalTo(DateUtils.endOfTheDay(spec.expiryDate)));
}
}
}

View File

@ -6,6 +6,11 @@
package org.elasticsearch.license.licensor;
import org.apache.commons.io.FileUtils;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.license.AbstractLicensingTestBase;
import org.elasticsearch.license.TestUtils;
import org.elasticsearch.license.core.ESLicense;
@ -16,113 +21,112 @@ import org.junit.Test;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.ParseException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import static com.carrotsearch.randomizedtesting.RandomizedTest.randomIntBetween;
import static com.carrotsearch.randomizedtesting.RandomizedTest.randomRealisticUnicodeOfCodepointLengthBetween;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
public class LicenseVerificationToolTests extends AbstractLicensingTestBase {
@Test
public void testEffectiveLicenseGeneration() throws Exception {
Map<String, TestUtils.FeatureAttributes> map = new HashMap<>();
TestUtils.FeatureAttributes featureWithLongerExpiryDate =
new TestUtils.FeatureAttributes("shield", "subscription", "platinum", "foo bar Inc.", "elasticsearch", 10, "2014-12-13", "2015-12-13");
map.put(TestUtils.SHIELD, featureWithLongerExpiryDate);
public void testMissingCLTArgs() throws Exception {
ESLicense singedLicense = generateSignedLicense(randomRealisticUnicodeOfCodepointLengthBetween(5, 15),
TimeValue.timeValueHours(1));
String signedLicense = runLicenseGenerationTool(TestUtils.generateESLicenses(map));
String firstLicenseFile = getAsFilePath(signedLicense);
String[] args = new String[2];
args[0] = "--licenssFiles";
args[1] = dumpLicense(singedLicense);
TestUtils.FeatureAttributes featureWithShorterExpiryDate =
new TestUtils.FeatureAttributes("shield", "trial", "none", "foo bar Inc.", "elasticsearch", 2, "2014-12-13", "2015-01-13");
map.put(TestUtils.SHIELD, featureWithShorterExpiryDate);
signedLicense = runLicenseGenerationTool(TestUtils.generateESLicenses(map));
String secondLicenseFile = getAsFilePath(signedLicense);
String effectiveLicenseStr = runLicenseVerificationTool(new String[]{firstLicenseFile, secondLicenseFile});
Set<ESLicense> esLicensesOutput = new HashSet<>(ESLicenses.fromSource(effectiveLicenseStr));
map.put(TestUtils.SHIELD, featureWithLongerExpiryDate);
// verify that the effective license strips out license for the same feature with earlier expiry dates
TestUtils.verifyESLicenses(esLicensesOutput, map);
try {
runLicenseVerificationTool(args);
fail("mandatory param '--licensesFiles' should throw an exception");
} catch (IllegalArgumentException e) {
assertThat(e.getMessage(), containsString("--licensesFiles"));
}
}
@Test
public void testEffectiveLicenseForMultiFeatures() throws Exception {
Map<String, TestUtils.FeatureAttributes> map = new HashMap<>();
TestUtils.FeatureAttributes shieldFeatureWithLongerExpiryDate =
new TestUtils.FeatureAttributes("shield", "subscription", "platinum", "foo bar Inc.", "elasticsearch", 10, "2014-12-13", "2015-12-13");
map.put(TestUtils.SHIELD, shieldFeatureWithLongerExpiryDate);
public void testSimple() throws Exception {
ESLicense singedLicense = generateSignedLicense(randomRealisticUnicodeOfCodepointLengthBetween(5, 15),
TimeValue.timeValueHours(1));
String signedLicense = runLicenseGenerationTool(TestUtils.generateESLicenses(map));
String firstLicenseFile = getAsFilePath(signedLicense);
String[] args = new String[2];
args[0] = "--licensesFiles";
args[1] = dumpLicense(singedLicense);
TestUtils.FeatureAttributes marvelFeatureWithShorterExpiryDate =
new TestUtils.FeatureAttributes("marvel", "trial", "none", "foo bar Inc.", "elasticsearch", 2, "2014-12-13", "2015-01-13");
map.put(TestUtils.MARVEL, marvelFeatureWithShorterExpiryDate);
String licenseOutput = runLicenseVerificationTool(args);
List<ESLicense> licensesOutput = ESLicenses.fromSource(licenseOutput);
signedLicense = runLicenseGenerationTool(TestUtils.generateESLicenses(map));
String secondLicenseFile = getAsFilePath(signedLicense);
assertThat(licensesOutput.size(), equalTo(1));
String effectiveLicenseStr = runLicenseVerificationTool(new String[]{firstLicenseFile, secondLicenseFile});
Set<ESLicense> esLicensesOutput = new HashSet<>(ESLicenses.fromSource(effectiveLicenseStr));
ESLicense expectedLicense = ESLicense.builder()
.fromLicenseSpec(singedLicense, licensesOutput.get(0).signature())
.build();
// verify that the effective license contains both feature licenses
TestUtils.verifyESLicenses(esLicensesOutput, map);
TestUtils.isSame(expectedLicense, licensesOutput.get(0));
}
@Test
public void testEffectiveLicenseForMultiFeatures2() throws Exception {
Map<String, TestUtils.FeatureAttributes> map = new HashMap<>();
public void testWithLicenseFiles() throws Exception {
int n = randomIntBetween(3, 10);
Set<ESLicense> signedLicenses = new HashSet<>();
for (int i = 0; i < n; i++) {
signedLicenses.add(generateSignedLicense(randomRealisticUnicodeOfCodepointLengthBetween(5, 15),
TimeValue.timeValueHours(1)));
}
TestUtils.FeatureAttributes shieldFeatureWithLongerExpiryDate =
new TestUtils.FeatureAttributes("shield", "subscription", "platinum", "foo bar Inc.", "elasticsearch", 10, "2014-12-13", "2015-12-13");
TestUtils.FeatureAttributes marvelFeatureWithShorterExpiryDate =
new TestUtils.FeatureAttributes("marvel", "trial", "none", "foo bar Inc.", "elasticsearch", 2, "2014-12-13", "2015-01-13");
map.put(TestUtils.SHIELD, shieldFeatureWithLongerExpiryDate);
map.put(TestUtils.MARVEL, marvelFeatureWithShorterExpiryDate);
String signedLicense = runLicenseGenerationTool(TestUtils.generateESLicenses(map));
String firstLicenseFile = getAsFilePath(signedLicense);
TestUtils.FeatureAttributes shieldFeatureWithShorterExpiryDate =
new TestUtils.FeatureAttributes("shield", "subscription", "platinum", "foo bar Inc.", "elasticsearch", 10, "2014-12-13", "2015-11-13");
TestUtils.FeatureAttributes marvelFeatureWithLongerExpiryDate =
new TestUtils.FeatureAttributes("marvel", "trial", "none", "foo bar Inc.", "elasticsearch", 2, "2014-12-13", "2015-11-13");
map.put(TestUtils.SHIELD, shieldFeatureWithShorterExpiryDate);
map.put(TestUtils.MARVEL, marvelFeatureWithLongerExpiryDate);
signedLicense = runLicenseGenerationTool(TestUtils.generateESLicenses(map));
String secondLicenseFile = getAsFilePath(signedLicense);
String effectiveLicenseStr = runLicenseVerificationTool(new String[]{firstLicenseFile, secondLicenseFile});
Set<ESLicense> esLicensesOutput = new HashSet<>(ESLicenses.fromSource(effectiveLicenseStr));
map.put(TestUtils.SHIELD, shieldFeatureWithLongerExpiryDate);
map.put(TestUtils.MARVEL, marvelFeatureWithLongerExpiryDate);
// verify that the generated effective license is generated from choosing individual licences from multiple files
TestUtils.verifyESLicenses(esLicensesOutput, map);
}
public static String runLicenseVerificationTool(String[] licenseFiles) throws IOException {
StringBuilder licenseFilePathString = new StringBuilder();
for (int i = 0; i < licenseFiles.length; i++) {
licenseFilePathString.append(licenseFiles[i]);
if (i != licenseFiles.length - 1) {
ESLicense[] esLicenses = signedLicenses.toArray(new ESLicense[n]);
for (int i = 0; i < n; i++) {
licenseFilePathString.append(dumpLicense(esLicenses[i]));
if (i != esLicenses.length - 1) {
licenseFilePathString.append(":");
}
}
String[] args = new String[4];
String[] args = new String[2];
args[0] = "--licensesFiles";
args[1] = licenseFilePathString.toString();
args[2] = "--publicKeyPath";
args[3] = pubKeyPath;
String licenseOutput = runLicenseVerificationTool(args);
List<ESLicense> output = ESLicenses.fromSource(licenseOutput);
assertThat(output.size(), equalTo(n));
Set<ESLicense> licensesOutput = new HashSet<>();
Map<String, ESLicense> expectedLicenses = ESLicenses.reduceAndMap(signedLicenses);
for (ESLicense license : output) {
licensesOutput.add(
ESLicense.builder()
.fromLicenseSpec(license, expectedLicenses.get(license.feature()).signature())
.build()
);
}
TestUtils.isSame(signedLicenses, licensesOutput);
}
private String dumpLicense(ESLicense license) throws Exception {
Path tempFilePath = Files.createTempFile("license_spec", "json");
File tempFile = tempFilePath.toFile();
tempFile.deleteOnExit();
try (FileOutputStream outputStream = new FileOutputStream(tempFile)) {
XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON, outputStream);
ESLicenses.toXContent(Collections.singletonList(license), builder, ToXContent.EMPTY_PARAMS);
builder.flush();
}
return tempFile.getAbsolutePath();
}
private static String runLicenseVerificationTool(String[] args) throws IOException {
File temp = File.createTempFile("temp", ".out");
temp.deleteOnExit();
try (FileOutputStream outputStream = new FileOutputStream(temp)) {
@ -130,21 +134,4 @@ public class LicenseVerificationToolTests extends AbstractLicensingTestBase {
}
return FileUtils.readFileToString(temp);
}
public String runLicenseGenerationTool(String licenseInput) throws IOException, ParseException {
return TestUtils.runLicenseGenerationTool(licenseInput, pubKeyPath, priKeyPath);
}
private static String getAsFilePath(String content) throws IOException {
File temp = File.createTempFile("license", ".out");
temp.deleteOnExit();
FileUtils.write(temp, content);
String tempFilePath = temp.getAbsolutePath();
while (tempFilePath.contains(":")) {
assert temp.delete();
tempFilePath = getAsFilePath(content);
}
return tempFilePath;
}
}

View File

@ -0,0 +1,48 @@
/*
* 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.manager;
import org.elasticsearch.license.AbstractLicensingTestBase;
import org.elasticsearch.license.TestUtils;
import org.elasticsearch.license.core.ESLicense;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.*;
import static com.carrotsearch.randomizedtesting.RandomizedTest.randomIntBetween;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.*;
public class LicenseSignatureTest extends AbstractLicensingTestBase {
private static ESLicenseManager esLicenseManager;
@BeforeClass
public static void setupManager() {
esLicenseManager = new ESLicenseManager();
}
@Test
public void testLicenseGeneration() throws Exception {
int n = randomIntBetween(5, 15);
List<LicenseSpec> licenseSpecs = new ArrayList<>();
for (int i = 0; i < n; i++) {
licenseSpecs.add(generateRandomLicenseSpec());
}
Set<ESLicense> generatedLicenses = generateSignedLicenses(licenseSpecs);
assertThat(generatedLicenses.size(), equalTo(n));
Set<String> signatures = new HashSet<>();
for (ESLicense license : generatedLicenses) {
signatures.add(license.signature());
}
Set<ESLicense> licenseFromSignatures = esLicenseManager.fromSignatures(signatures);
TestUtils.isSame(generatedLicenses, licenseFromSignatures);
}
}

View File

@ -6,137 +6,71 @@
package org.elasticsearch.license.manager;
import net.nicholaswilliams.java.licensing.exception.InvalidLicenseException;
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.license.AbstractLicensingTestBase;
import org.elasticsearch.license.TestUtils;
import org.elasticsearch.license.core.DateUtils;
import org.elasticsearch.license.core.ESLicense;
import org.elasticsearch.license.core.ESLicenses;
import org.elasticsearch.license.licensor.tools.FileBasedESLicenseProvider;
import org.junit.After;
import org.junit.BeforeClass;
import org.junit.Test;
import java.text.ParseException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.*;
public class LicenseVerificationTests extends AbstractLicensingTestBase {
private static ESLicenseManager esLicenseManager;
private static FileBasedESLicenseProvider esLicenseProvider;
private final static Set<ESLicense> EMPTY_LICENSES = new HashSet<>();
private final FormatDateTimeFormatter formatDateTimeFormatter = Joda.forPattern("yyyy-MM-dd");
private final org.elasticsearch.common.joda.time.format.DateTimeFormatter dateTimeFormatter = formatDateTimeFormatter.printer();
private final DateMathParser dateMathParser = new DateMathParser(formatDateTimeFormatter, TimeUnit.MILLISECONDS);
@BeforeClass
public static void setupManager() {
esLicenseProvider = new FileBasedESLicenseProvider(EMPTY_LICENSES);
esLicenseManager = new ESLicenseManager();
}
@After
public void clearManager() {
esLicenseProvider.setLicenses(EMPTY_LICENSES);
}
private String dateMathString(String time, long now) {
return dateTimeFormatter.print(dateMathParser.parse(time, now));
}
@Test
public void testGeneratedLicenses() throws Exception {
long now = System.currentTimeMillis();
String issueDateStr = dateMathString("now/d", now);
String expiryDateStr = dateMathString("now+2d/d", now);
Map<String, TestUtils.FeatureAttributes> map = new HashMap<>();
TestUtils.FeatureAttributes featureAttributes =
new TestUtils.FeatureAttributes("shield", "subscription", "platinum", "foo bar Inc.", "elasticsearch", 2, issueDateStr, expiryDateStr);
map.put(TestUtils.SHIELD, featureAttributes);
Set<ESLicense> esLicensesOutput = new HashSet<>(ESLicenses.fromSource(generateSignedLicenses(map)));
esLicenseProvider.setLicenses(esLicensesOutput);
esLicenseManager.verifyLicenses(esLicenseProvider.getEffectiveLicenses());
verifyLicenses(esLicenseProvider, map);
ESLicense shieldLicense = generateSignedLicense("shield", TimeValue.timeValueHours(2 * 24));
Map<String, ESLicense> shieldLicenseMap = new HashMap<>();
shieldLicenseMap.put("shield", shieldLicense);
esLicenseManager.verifyLicenses(shieldLicenseMap);
}
@Test
public void testMultipleFeatureLicenses() throws Exception {
long now = System.currentTimeMillis();
String issueDateStr = dateMathString("now/d", now);
String expiryDateStr = dateMathString("now+2d/d", now);
Map<String, TestUtils.FeatureAttributes> map = new HashMap<>();
TestUtils.FeatureAttributes shildFeatureAttributes =
new TestUtils.FeatureAttributes("shield", "trial", "none", "foo bar Inc.", "elasticsearch", 2, issueDateStr, expiryDateStr);
TestUtils.FeatureAttributes marvelFeatureAttributes =
new TestUtils.FeatureAttributes("marvel", "subscription", "silver", "foo1 bar Inc.", "elasticsearc3h", 10, issueDateStr, expiryDateStr);
map.put(TestUtils.SHIELD, shildFeatureAttributes);
map.put(TestUtils.MARVEL, marvelFeatureAttributes);
Set<ESLicense> esLicensesOutput = new HashSet<>(ESLicenses.fromSource(generateSignedLicenses(map)));
esLicenseProvider.setLicenses(esLicensesOutput);
esLicenseManager.verifyLicenses(esLicenseProvider.getEffectiveLicenses());
verifyLicenses(esLicenseProvider, map);
ESLicense shieldLicense = generateSignedLicense("shield", TimeValue.timeValueHours(2 * 24));
ESLicense marvelLicense = generateSignedLicense("marvel", TimeValue.timeValueHours(2 * 24));
Map<String, ESLicense> licenseMap = new HashMap<>();
licenseMap.put("shield", shieldLicense);
licenseMap.put("marvel", marvelLicense);
esLicenseManager.verifyLicenses(licenseMap);
}
@Test
public void testLicenseExpiry() throws Exception {
long now = System.currentTimeMillis();
String issueDateStr = dateMathString("now-60d/d", now);
String expiryDateStr = dateMathString("now+30d/d", now);
String expiredExpiryDateStr = dateMathString("now-10d/d", now);
long marvelIssueDate = dateMath("now-10d/d", now);
Map<String, TestUtils.FeatureAttributes> map = new HashMap<>();
TestUtils.FeatureAttributes shildFeatureAttributes =
new TestUtils.FeatureAttributes("shield", "trial", "none", "foo bar Inc.", "elasticsearch", 2, issueDateStr, expiryDateStr);
TestUtils.FeatureAttributes marvelFeatureAttributes =
new TestUtils.FeatureAttributes("marvel", "internal", "silver", "foo1 bar Inc.", "elasticsearc3h", 10, issueDateStr, expiredExpiryDateStr);
map.put(TestUtils.SHIELD, shildFeatureAttributes);
map.put(TestUtils.MARVEL, marvelFeatureAttributes);
ESLicense shieldLicense = generateSignedLicense("shield", TimeValue.timeValueHours(2 * 24));
ESLicense marvelLicense = generateSignedLicense("marvel", marvelIssueDate, TimeValue.timeValueHours(2 * 24));
Map<String, ESLicense> licenseMap = new HashMap<>();
licenseMap.put("shield", shieldLicense);
licenseMap.put("marvel", marvelLicense);
Set<ESLicense> esLicensesOutput = new HashSet<>(ESLicenses.fromSource(generateSignedLicenses(map)));
esLicenseProvider.setLicenses(esLicensesOutput);
// All validation for shield license should be normal as expected
verifyLicenses(esLicenseProvider, Collections.singletonMap(TestUtils.SHIELD, shildFeatureAttributes));
try {
esLicenseManager.verifyLicenses(licenseMap);
fail("verifyLicenses should throw InvalidLicenseException [expired license]");
} catch (InvalidLicenseException e) {
assertThat(e.getMessage(), containsString("Expired License"));
}
licenseMap.clear();
licenseMap.put("shield", shieldLicense);
esLicenseManager.verifyLicenses(licenseMap);
}
@Test
public void testLicenseTampering() throws Exception {
long now = System.currentTimeMillis();
String issueDateStr = dateMathString("now/d", now);
String expiryDateStr = dateMathString("now+2d/d", now);
Map<String, TestUtils.FeatureAttributes> map = new HashMap<>();
TestUtils.FeatureAttributes featureAttributes =
new TestUtils.FeatureAttributes("shield", "subscription", "platinum", "foo bar Inc.", "elasticsearch", 2, issueDateStr, expiryDateStr);
map.put(TestUtils.SHIELD, featureAttributes);
Set<ESLicense> esLicensesOutput = new HashSet<>(ESLicenses.fromSource(generateSignedLicenses(map)));
ESLicense esLicense = ESLicenses.reduceAndMap(esLicensesOutput).get(TestUtils.SHIELD);
ESLicense esLicense = generateSignedLicense("shield", TimeValue.timeValueHours(2));
final ESLicense tamperedLicense = ESLicense.builder()
.fromLicenseSpec(esLicense, esLicense.signature())
@ -144,31 +78,14 @@ public class LicenseVerificationTests extends AbstractLicensingTestBase {
.verify()
.build();
Map<String, ESLicense> licenseMap = new HashMap<>();
licenseMap.put("shield", tamperedLicense);
try {
esLicenseProvider.setLicenses(Collections.singleton(tamperedLicense));
esLicenseManager.verifyLicenses(esLicenseProvider.getEffectiveLicenses());
fail();
esLicenseManager.verifyLicenses(licenseMap);
fail("Tampered license should throw exception");
} catch (InvalidLicenseException e) {
assertTrue("Exception should contain 'Invalid License' but got: " + e.getMessage(), e.getMessage().contains("Invalid License"));
}
}
// TODO: move to TestUtils
public static void verifyLicenses(FileBasedESLicenseProvider licenseProvider, Map<String, TestUtils.FeatureAttributes> featureAttributeMap) throws ParseException {
for (Map.Entry<String, TestUtils.FeatureAttributes> entry : featureAttributeMap.entrySet()) {
TestUtils.FeatureAttributes featureAttributes = entry.getValue();
String featureType = entry.getKey();
ESLicense license = licenseProvider.getESLicense(featureType);
assertTrue("License should have issuedTo of " + featureAttributes.issuedTo, license.issuedTo().equals(featureAttributes.issuedTo));
assertTrue("License should have issuer of " + featureAttributes.issuer, license.issuer().equals(featureAttributes.issuer));
assertTrue("License should have issue date of " + DateUtils.beginningOfTheDay(featureAttributes.issueDate), license.issueDate() == DateUtils.beginningOfTheDay(featureAttributes.issueDate));
assertTrue("License should have expiry date of " + DateUtils.endOfTheDay(featureAttributes.expiryDate) + " got: " + license.expiryDate(), license.expiryDate() == DateUtils.endOfTheDay(featureAttributes.expiryDate));
assertTrue("License should have type of " + featureAttributes.type + " got: " + license.type(), license.type().equals(featureAttributes.type));
assertTrue("License should have subscription type of " + featureAttributes.subscriptionType, license.subscriptionType().equals(featureAttributes.subscriptionType));
assertTrue("License should be valid for maxNodes = " + (featureAttributes.maxNodes), license.maxNodes() == featureAttributes.maxNodes);
assertThat(e.getMessage(), containsString("Invalid License"));
}
}
}

View File

@ -6,7 +6,6 @@
package org.elasticsearch.license.plugin;
import org.elasticsearch.action.ActionFuture;
import org.elasticsearch.common.collect.Lists;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.license.TestUtils;
import org.elasticsearch.license.core.ESLicense;
@ -44,7 +43,7 @@ public class LicenseTransportTests extends AbstractLicensesIntegrationTests {
@Test
public void testPutLicense() throws Exception {
ESLicense signedLicense = generateSignedLicense(TestUtils.SHIELD, TimeValue.timeValueMinutes(2));
ESLicense signedLicense = generateSignedLicense("shield", TimeValue.timeValueMinutes(2));
List<ESLicense> actualLicenses = Collections.singletonList(signedLicense);
// put license
@ -64,7 +63,7 @@ public class LicenseTransportTests extends AbstractLicensesIntegrationTests {
@Test
public void testPutInvalidLicense() throws Exception {
ESLicense signedLicense = generateSignedLicense(TestUtils.SHIELD, TimeValue.timeValueMinutes(2));
ESLicense signedLicense = generateSignedLicense("shield", TimeValue.timeValueMinutes(2));
// modify content of signed license
ESLicense tamperedLicense = ESLicense.builder()
@ -88,8 +87,8 @@ public class LicenseTransportTests extends AbstractLicensesIntegrationTests {
@Test
public void testPutLicensesForSameFeature() throws Exception {
ESLicense shortedSignedLicense = generateSignedLicense(TestUtils.SHIELD, TimeValue.timeValueMinutes(2));
ESLicense longerSignedLicense = generateSignedLicense(TestUtils.SHIELD, TimeValue.timeValueMinutes(5));
ESLicense shortedSignedLicense = generateSignedLicense("shield", TimeValue.timeValueMinutes(2));
ESLicense longerSignedLicense = generateSignedLicense("shield", TimeValue.timeValueMinutes(5));
List<ESLicense> actualLicenses = Arrays.asList(longerSignedLicense, shortedSignedLicense);
// put license
@ -109,8 +108,8 @@ public class LicenseTransportTests extends AbstractLicensesIntegrationTests {
@Test
public void testPutLicensesForMultipleFeatures() throws Exception {
ESLicense shieldLicense = generateSignedLicense(TestUtils.SHIELD, TimeValue.timeValueMinutes(2));
ESLicense marvelLicense = generateSignedLicense(TestUtils.MARVEL, TimeValue.timeValueMinutes(5));
ESLicense shieldLicense = generateSignedLicense("shield", TimeValue.timeValueMinutes(2));
ESLicense marvelLicense = generateSignedLicense("marvel", TimeValue.timeValueMinutes(5));
List<ESLicense> actualLicenses = Arrays.asList(marvelLicense, shieldLicense);
// put license
@ -130,9 +129,9 @@ public class LicenseTransportTests extends AbstractLicensesIntegrationTests {
@Test
public void testPutMultipleLicensesForMultipleFeatures() throws Exception {
ESLicense shortedSignedLicense = generateSignedLicense(TestUtils.SHIELD, TimeValue.timeValueMinutes(2));
ESLicense longerSignedLicense = generateSignedLicense(TestUtils.SHIELD, TimeValue.timeValueMinutes(5));
ESLicense marvelLicense = generateSignedLicense(TestUtils.MARVEL, TimeValue.timeValueMinutes(5));
ESLicense shortedSignedLicense = generateSignedLicense("shield", TimeValue.timeValueMinutes(2));
ESLicense longerSignedLicense = generateSignedLicense("shield", TimeValue.timeValueMinutes(5));
ESLicense marvelLicense = generateSignedLicense("marvel", TimeValue.timeValueMinutes(5));
List<ESLicense> actualLicenses = Arrays.asList(marvelLicense, shortedSignedLicense, longerSignedLicense);
// put license

View File

@ -6,10 +6,13 @@
package org.elasticsearch.license.plugin;
import org.elasticsearch.client.ClusterAdminClient;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.block.ClusterBlockLevel;
import org.elasticsearch.common.base.Predicate;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.discovery.DiscoverySettings;
import org.elasticsearch.gateway.GatewayService;
import org.elasticsearch.license.TestUtils;
import org.elasticsearch.license.core.ESLicense;
@ -21,7 +24,6 @@ import org.elasticsearch.license.plugin.consumer.TestConsumerPlugin1;
import org.elasticsearch.license.plugin.consumer.TestPluginService1;
import org.elasticsearch.license.plugin.core.LicensesStatus;
import org.elasticsearch.node.internal.InternalNode;
import org.junit.Before;
import org.junit.Test;
import java.util.Arrays;
@ -31,12 +33,13 @@ import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilde
import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope.TEST;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.Matchers.hasItem;
@ClusterScope(scope = TEST, numDataNodes = 0, numClientNodes = 0, maxNumDataNodes = 0, transportClientRatio = 0)
public class LicensesServiceClusterTest extends AbstractLicensesIntegrationTests {
private final String FEATURE_NAME = TestPluginService1.FEATURE_NAME;
private final int trialLicenseDurationInSeconds = 2;
protected Settings transportClientSettings() {
return super.transportClientSettings();
@ -54,18 +57,14 @@ public class LicensesServiceClusterTest extends AbstractLicensesIntegrationTests
.put("plugins.load_classpath_plugins", false)
.put("node.data", true)
.put("format", "json")
.put(TestConsumerPlugin1.NAME + ".trial_license_duration_in_seconds", 5)
.put(TestConsumerPlugin1.NAME + ".trial_license_duration_in_seconds", trialLicenseDurationInSeconds)
.putArray("plugin.types", LicensePlugin.class.getName(), TestConsumerPlugin1.class.getName())
.put(InternalNode.HTTP_ENABLED, true);
}
@Before
public void beforeTest() throws Exception {
wipeAllLicenses();
}
@Test
public void testClusterRestart() throws Exception {
wipeAllLicenses();
int numNodes = randomIntBetween(1, 5);
logger.info("--> starting " + numNodes + " node(s)");
@ -83,40 +82,21 @@ public class LicensesServiceClusterTest extends AbstractLicensesIntegrationTests
logger.info("--> get and check signed license");
getAndCheckLicense(esLicenses);
wipeAllLicenses();
}
@Test
public void testClusterNotRecovered() throws Exception {
logger.info("--> start first node (should not recover)");
String name = internalCluster().startNode(nodeSettingsBuilder(0).put("gateway.recover_after_master_nodes", 2).put("node.master", true));
/* TODO: figure out why STATE_NOT_RECOVERED_BLOCK is not on
assertThat(internalCluster().client(name).admin().cluster().prepareState().setLocal(true).execute().actionGet()
.getState().blocks().global(ClusterBlockLevel.METADATA),
hasItem(GatewayService.STATE_NOT_RECOVERED_BLOCK));
*/
assertLicenseManagerEnabledFeatureFor(FEATURE_NAME);
assertConsumerPlugin1EnableNotification(1);
logger.info("--> start second node (should recover)");
internalCluster().startNode(nodeSettingsBuilder(1).put("gateway.recover_after_master_nodes", 2).put("node.master", true));
assertLicenseManagerEnabledFeatureFor(FEATURE_NAME);
assertConsumerPlugin1EnableNotification(1);
//internalCluster().startNode(nodeSettingsBuilder(2).put("gateway.expected_master_nodes", 3));
//assertLicenseManagerEnabledFeatureFor(TestPluginService.FEATURE_NAME);
//assertConsumerPlugin1EnableNotification(1);
logger.info("--> kill master node");
internalCluster().stopCurrentMasterNode();
assertLicenseManagerEnabledFeatureFor(FEATURE_NAME);
assertConsumerPlugin1EnableNotification(1);
Thread.sleep(5 * 1050l);
internalCluster().startNode(nodeSettingsBuilder(3).put("gateway.recover_after_master_nodes", 2).put("node.master", true));
logger.info("--> start one master out of two [recovery state]");
internalCluster().startNode(nodeSettingsBuilder(0).put("discovery.zen.minimum_master_nodes", 2).put("node.master", true));
assertLicenseManagerDisabledFeatureFor(FEATURE_NAME);
assertConsumerPlugin1DisableNotification(1);
logger.info("--> start second master out of two [recovered state]");
internalCluster().startNode(nodeSettingsBuilder(1).put("discovery.zen.minimum_master_nodes", 2).put("node.master", true));
assertLicenseManagerEnabledFeatureFor(FEATURE_NAME);
assertConsumerPlugin1EnableNotification(1);
}
private List<ESLicense> generateAndPutLicense() throws Exception {