Major refactoring of LicenseManager; Initial integration with LicenseService; still a lot of TODOs
Original commit: elastic/x-pack-elasticsearch@880984062a
This commit is contained in:
parent
0bcdb016be
commit
d7ec84afd7
|
@ -49,6 +49,16 @@ public class LicenseBuilders {
|
|||
}
|
||||
}
|
||||
|
||||
public static ESLicenses removeFeatures(ESLicenses licenses, Set<FeatureType> featureTypesToDelete) {
|
||||
final LicensesBuilder licensesBuilder = licensesBuilder();
|
||||
for (ESLicense license : licenses) {
|
||||
if (!featureTypesToDelete.contains(license.feature())) {
|
||||
licensesBuilder.license(license);
|
||||
}
|
||||
}
|
||||
return licensesBuilder.build();
|
||||
}
|
||||
|
||||
public static class LicensesBuilder {
|
||||
private Map<FeatureType, ESLicense> licenseMap = new HashMap<>();
|
||||
|
||||
|
|
|
@ -95,7 +95,7 @@ public class LicenseVerificationTool {
|
|||
Options options = parse(args);
|
||||
|
||||
// verify licenses
|
||||
ESLicenseManager licenseManager = new ESLicenseManager(options.licenses, options.publicKeyFilePath);
|
||||
ESLicenseManager licenseManager = ESLicenseManager.createLocalBasedInstance(options.licenses, options.publicKeyFilePath);
|
||||
licenseManager.verifyLicenses();
|
||||
|
||||
// dump effective licences
|
||||
|
|
|
@ -11,51 +11,111 @@ import net.nicholaswilliams.java.licensing.encryption.Hasher;
|
|||
import net.nicholaswilliams.java.licensing.encryption.PasswordProvider;
|
||||
import net.nicholaswilliams.java.licensing.exception.ExpiredLicenseException;
|
||||
import net.nicholaswilliams.java.licensing.exception.InvalidLicenseException;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.elasticsearch.cluster.ClusterService;
|
||||
import org.elasticsearch.license.core.ESLicenses;
|
||||
import org.elasticsearch.license.core.LicenseBuilders;
|
||||
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.elasticsearch.license.core.ESLicenses.*;
|
||||
import static org.elasticsearch.license.manager.ESLicenseProvider.ClusterStateLicenseProvider;
|
||||
import static org.elasticsearch.license.manager.ESLicenseProvider.FileBasedESLicenseProvider;
|
||||
import static org.elasticsearch.license.manager.ESLicenseProvider.extractSignedLicence;
|
||||
|
||||
/**
|
||||
* Class responsible for reading signed licenses, maintaining an effective esLicenses instance, verification of licenses
|
||||
* and querying against licenses on a feature basis
|
||||
*
|
||||
* <p/>
|
||||
* TODO:
|
||||
* - integration with cluster state
|
||||
* - use ESLicenseProvider to query license from cluster state
|
||||
* - integration with cluster state
|
||||
* - use ESLicenseProvider to query license from cluster state
|
||||
*/
|
||||
public class ESLicenseManager {
|
||||
|
||||
private final LicenseManager licenseManager;
|
||||
private final ESLicenses esLicenses;
|
||||
private final FilePublicKeyDataProvider publicKeyDataProvider;
|
||||
private static ESLicenseManager instance = null;
|
||||
private static FilePublicKeyDataProvider publicKeyDataProvider;
|
||||
private final ESLicenseProvider licenseProvider;
|
||||
|
||||
public ESLicenseManager(Set<ESLicenses> esLicensesSet, String publicKeyFile) throws IOException {
|
||||
this.publicKeyDataProvider = new FilePublicKeyDataProvider(publicKeyFile);
|
||||
this.esLicenses = merge(esLicensesSet);
|
||||
LicenseManagerProperties.setLicenseProvider(new ESLicenseProvider());
|
||||
private final LicenseManager licenseManager;
|
||||
|
||||
public static ESLicenseManager getInstance() {
|
||||
if (ESLicenseManager.instance == null) {
|
||||
throw new IllegalStateException("License manager has not been created!");
|
||||
}
|
||||
return ESLicenseManager.instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a LicenseManager instance where the Licenses are queried from the cluster state
|
||||
*
|
||||
* @param clusterService used to query for appropriate license(s) for validation
|
||||
* @param publicKeyPath used to decrypt the licenses
|
||||
* @return {@link org.elasticsearch.license.manager.ESLicenseManager} instance backed by licenses residing
|
||||
* in the cluster state
|
||||
*/
|
||||
public static ESLicenseManager createClusterStateBasedInstance(ClusterService clusterService, String publicKeyPath) {
|
||||
if (ESLicenseManager.instance == null) {
|
||||
ESLicenseManager.publicKeyDataProvider = new FilePublicKeyDataProvider(publicKeyPath);
|
||||
return new ESLicenseManager(ESLicenseProvider.createClusterBasedLicenseProvider(clusterService, publicKeyPath));
|
||||
} else if (ESLicenseManager.instance.licenseProvider instanceof ClusterStateLicenseProvider) {
|
||||
return ESLicenseManager.instance;
|
||||
} else {
|
||||
throw new IllegalStateException("Manager already initiated with File based license provider");
|
||||
}
|
||||
}
|
||||
|
||||
public static ESLicenseManager createClusterStateBasedInstance(ClusterService clusterService) {
|
||||
return createClusterStateBasedInstance(clusterService, getPublicKeyPath());
|
||||
}
|
||||
|
||||
public static ESLicenseManager createLocalBasedInstance(ESLicenses esLicenses, String publicKeyPath) {
|
||||
return createLocalBasedInstance(Collections.singleton(esLicenses), publicKeyPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a LicenseManager instance where the Licenses are queried from a set of pre-generated licenses
|
||||
* @param esLicensesSet a set of pre-generated licenses stored in the license manager
|
||||
* @param publicKeyPath used to decrypt the licenses
|
||||
* @return {@link org.elasticsearch.license.manager.ESLicenseManager} instance backed by pre-generated licenses
|
||||
*/
|
||||
public static ESLicenseManager createLocalBasedInstance(Set<ESLicenses> esLicensesSet, String publicKeyPath) {
|
||||
if (ESLicenseManager.instance == null) {
|
||||
ESLicenseManager.publicKeyDataProvider = new FilePublicKeyDataProvider(publicKeyPath);
|
||||
return new ESLicenseManager(ESLicenseProvider.createFileBasedLicenseProvider(merge(esLicensesSet), publicKeyPath));
|
||||
} else if (ESLicenseManager.instance.licenseProvider instanceof FileBasedESLicenseProvider) {
|
||||
return ESLicenseManager.instance;
|
||||
} else {
|
||||
throw new IllegalStateException("Manager already initiated with Cluster state based license provider");
|
||||
}
|
||||
}
|
||||
|
||||
private static String getPublicKeyPath() {
|
||||
URL resource = ESLicenseManager.class.getResource("public.key");
|
||||
if (resource == null) {
|
||||
//test REMOVE NOCOMMIT!!!!
|
||||
resource = ESLicenseManager.class.getResource("/org.elasticsearch.license.plugin/test_pub.key");
|
||||
}
|
||||
try {
|
||||
return Paths.get(resource.toURI()).toFile().getAbsolutePath();
|
||||
} catch (URISyntaxException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private ESLicenseManager(ESLicenseProvider licenseProvider) {
|
||||
LicenseManagerProperties.setLicenseProvider(licenseProvider);
|
||||
LicenseManagerProperties.setPublicKeyDataProvider(publicKeyDataProvider);
|
||||
LicenseManagerProperties.setLicenseValidator(new DefaultLicenseValidator());
|
||||
LicenseManagerProperties.setPublicKeyPasswordProvider(new ESPublicKeyPasswordProvider());
|
||||
this.licenseProvider = licenseProvider;
|
||||
this.licenseManager = LicenseManager.getInstance();
|
||||
}
|
||||
|
||||
|
||||
public ESLicenseManager(ESLicenses esLicenses, String publicKeyFile) throws IOException {
|
||||
this(Collections.singleton(esLicenses), publicKeyFile);
|
||||
}
|
||||
|
||||
private static ESLicenses merge(Set<ESLicenses> esLicensesSet) {
|
||||
ESLicenses mergedLicenses = null;
|
||||
for (ESLicenses licenses : esLicensesSet) {
|
||||
|
@ -65,65 +125,38 @@ public class ESLicenseManager {
|
|||
}
|
||||
|
||||
public ESLicenses getEffectiveLicenses() {
|
||||
return esLicenses;
|
||||
return licenseProvider.getEffectiveLicenses();
|
||||
}
|
||||
|
||||
private License getLicense(FeatureType featureType) {
|
||||
ESLicense esLicense = esLicenses.get(featureType);
|
||||
if (esLicense != null) {
|
||||
String signature = esLicense.signature();
|
||||
try {
|
||||
License license = this.licenseManager.decryptAndVerifyLicense(extractSignedLicence(signature));
|
||||
public void verifyLicenses(ESLicenses esLicenses) {
|
||||
try {
|
||||
for (FeatureType featureType : esLicenses.features()) {
|
||||
ESLicense esLicense = esLicenses.get(featureType);
|
||||
// verify signature
|
||||
final License license = this.licenseManager.decryptAndVerifyLicense(
|
||||
extractSignedLicence(
|
||||
esLicense.signature(),
|
||||
publicKeyDataProvider.getPublicKeyFile().getAbsolutePath()));
|
||||
// validate license
|
||||
this.licenseManager.validateLicense(license);
|
||||
return license;
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException("bogus");
|
||||
|
||||
// verify all readable license fields
|
||||
verifyLicenseFields(license, esLicense);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a signedLicense (SIGNED_LICENSE_CONTENT) from the signature.
|
||||
* Validates the public key used to decrypt the license by comparing their hashes
|
||||
* <p/>
|
||||
* Signature structure:
|
||||
* | MAGIC | HEADER_LENGTH | VERSION | PUB_KEY_DIGEST | SIGNED_LICENSE_CONTENT |
|
||||
*
|
||||
* @param signature of a single license
|
||||
* @return signed license content for the license
|
||||
* @throws IOException
|
||||
*/
|
||||
private SignedLicense extractSignedLicence(String signature) throws IOException {
|
||||
byte[] signatureBytes = Base64.decodeBase64(signature);
|
||||
ByteBuffer byteBuffer = ByteBuffer.wrap(signatureBytes);
|
||||
byteBuffer = (ByteBuffer) byteBuffer.position(13);
|
||||
int start = byteBuffer.getInt();
|
||||
int version = byteBuffer.getInt();
|
||||
byte[] hash = new byte[start - 13 - 4 - 4];
|
||||
byteBuffer.get(hash);
|
||||
|
||||
final byte[] computedHash = Hasher.hash(Base64.encodeBase64String(
|
||||
Files.readAllBytes(Paths.get(publicKeyDataProvider.getPublicKeyFile().getAbsolutePath())))
|
||||
).getBytes(Charset.forName("UTF-8"));
|
||||
|
||||
if (!Arrays.equals(hash, computedHash)) {
|
||||
} catch (ExpiredLicenseException e) {
|
||||
throw new InvalidLicenseException("Expired License");
|
||||
} catch (InvalidLicenseException e) {
|
||||
throw new InvalidLicenseException("Invalid License");
|
||||
} catch (IOException e) {
|
||||
// bogus
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
|
||||
return new ObjectSerializer().readObject(SignedLicense.class, Arrays.copyOfRange(signatureBytes, start, signatureBytes.length));
|
||||
}
|
||||
|
||||
|
||||
public void verifyLicenses() {
|
||||
for (FeatureType featureType : esLicenses.features()) {
|
||||
final License license = getLicense(featureType);
|
||||
assert license != null : "license should not be null for feature: " + featureType.string();
|
||||
verifyLicenseFields(license, esLicenses.get(featureType));
|
||||
}
|
||||
verifyLicenses(getEffectiveLicenses());
|
||||
}
|
||||
|
||||
|
||||
private static void verifyLicenseFields(License license, ESLicense eslicense) {
|
||||
boolean licenseValid = license.getProductKey().equals(eslicense.uid())
|
||||
&& license.getHolder().equals(eslicense.issuedTo())
|
||||
|
@ -163,13 +196,15 @@ public class ESLicenseManager {
|
|||
}
|
||||
|
||||
|
||||
//TODO wrap License validation methods so a plugin does not have to provide featureType param
|
||||
|
||||
public boolean hasLicenseForFeature(FeatureType featureType) {
|
||||
try {
|
||||
final License license = getLicense(featureType);
|
||||
if (license == null) {
|
||||
return false;
|
||||
final License license = licenseManager.getLicense(featureType);
|
||||
if (license != null) {
|
||||
return license.hasLicenseForFeature(featureType.string());
|
||||
}
|
||||
return license.hasLicenseForFeature(featureType.string());
|
||||
return false;
|
||||
} catch (ExpiredLicenseException e) {
|
||||
return false;
|
||||
} catch (InvalidLicenseException e) {
|
||||
|
@ -178,42 +213,42 @@ public class ESLicenseManager {
|
|||
}
|
||||
|
||||
public boolean hasLicenseForNodes(FeatureType featureType, int nodes) {
|
||||
ESLicense esLicense = generateESLicense(featureType);
|
||||
ESLicense esLicense = getESLicense(featureType);
|
||||
return esLicense.maxNodes() >= nodes;
|
||||
}
|
||||
|
||||
public String getIssuerForLicense(FeatureType featureType) {
|
||||
final License license = getLicense(featureType);
|
||||
final License license = licenseManager.getLicense(featureType);
|
||||
return license.getIssuer();
|
||||
}
|
||||
|
||||
public long getIssueDateForLicense(FeatureType featureType) {
|
||||
final License license = getLicense(featureType);
|
||||
final License license = licenseManager.getLicense(featureType);
|
||||
return license.getIssueDate();
|
||||
}
|
||||
|
||||
public long getExpiryDateForLicense(FeatureType featureType) {
|
||||
final License license = getLicense(featureType);
|
||||
final License license = licenseManager.getLicense(featureType);
|
||||
return license.getGoodBeforeDate();
|
||||
}
|
||||
|
||||
public String getIssuedToForLicense(FeatureType featureType) {
|
||||
final License license = getLicense(featureType);
|
||||
final License license = licenseManager.getLicense(featureType);
|
||||
return license.getHolder();
|
||||
}
|
||||
|
||||
public Type getTypeForLicense(FeatureType featureType) {
|
||||
ESLicense esLicense = generateESLicense(featureType);
|
||||
ESLicense esLicense = getESLicense(featureType);
|
||||
return esLicense.type();
|
||||
}
|
||||
|
||||
public SubscriptionType getSubscriptionTypeForLicense(FeatureType featureType) {
|
||||
ESLicense esLicense = generateESLicense(featureType);
|
||||
ESLicense esLicense = getESLicense(featureType);
|
||||
return esLicense.subscriptionType();
|
||||
}
|
||||
|
||||
private ESLicense generateESLicense(FeatureType featureType) {
|
||||
final License license = getLicense(featureType);
|
||||
ESLicense getESLicense(FeatureType featureType) {
|
||||
final License license = licenseManager.getLicense(featureType);
|
||||
return convertToESLicense(license);
|
||||
}
|
||||
|
||||
|
@ -245,18 +280,15 @@ public class ESLicenseManager {
|
|||
return licenseBuilder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by the underlying license manager (make sure it is never called for now)
|
||||
* This should be retrieving licenses from the custom metadata in the cluster state
|
||||
*/
|
||||
public class ESLicenseProvider implements LicenseProvider {
|
||||
@Override
|
||||
public SignedLicense getLicense(Object context) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
// only for testing
|
||||
public void clearAndAddLicenses(ESLicenses licenses) {
|
||||
this.licenseManager.clearLicenseCache();
|
||||
assert this.licenseProvider instanceof FileBasedESLicenseProvider;
|
||||
this.licenseProvider.addLicenses(licenses);
|
||||
}
|
||||
|
||||
private class ESPublicKeyPasswordProvider implements PasswordProvider {
|
||||
private static class ESPublicKeyPasswordProvider implements PasswordProvider {
|
||||
private final String DEFAULT_PASS_PHRASE = "elasticsearch-license";
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
* 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 net.nicholaswilliams.java.licensing.LicenseProvider;
|
||||
import net.nicholaswilliams.java.licensing.ObjectSerializer;
|
||||
import net.nicholaswilliams.java.licensing.SignedLicense;
|
||||
import net.nicholaswilliams.java.licensing.encryption.Hasher;
|
||||
import net.nicholaswilliams.java.licensing.exception.InvalidLicenseException;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.elasticsearch.cluster.ClusterService;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.license.core.ESLicenses;
|
||||
import org.elasticsearch.license.plugin.core.LicensesMetaData;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.elasticsearch.license.core.ESLicenses.ESLicense;
|
||||
import static org.elasticsearch.license.core.ESLicenses.FeatureType;
|
||||
|
||||
public abstract class ESLicenseProvider implements LicenseProvider {
|
||||
|
||||
/**
|
||||
* Factory for {@link org.elasticsearch.license.manager.ESLicenseProvider.ClusterStateLicenseProvider}
|
||||
*/
|
||||
public static ESLicenseProvider createClusterBasedLicenseProvider(ClusterService clusterService, String publicKeyPath) {
|
||||
return new ClusterStateLicenseProvider(clusterService, publicKeyPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory for {@link org.elasticsearch.license.manager.ESLicenseProvider.FileBasedESLicenseProvider}
|
||||
*/
|
||||
public static ESLicenseProvider createFileBasedLicenseProvider(ESLicenses esLicenses, String publicKeyPath) {
|
||||
return new FileBasedESLicenseProvider(esLicenses, publicKeyPath);
|
||||
}
|
||||
|
||||
public abstract ESLicense getESLicense(FeatureType featureType);
|
||||
|
||||
public abstract ESLicenses getEffectiveLicenses();
|
||||
|
||||
// only for testing
|
||||
public abstract void addLicenses(ESLicenses esLicenses);
|
||||
|
||||
/**
|
||||
* LicenseProvider backed by the current cluster state
|
||||
* Uses the clusterService to query for the latest licenses
|
||||
* for {@link org.elasticsearch.license.manager.ESLicenseManager}
|
||||
* consumption
|
||||
*/
|
||||
public static class ClusterStateLicenseProvider extends ESLicenseProvider {
|
||||
private final ClusterService clusterService;
|
||||
private final String publicKeyPath;
|
||||
|
||||
private ClusterStateLicenseProvider(ClusterService clusterService, String publicKeyPath) {
|
||||
this.clusterService = clusterService;
|
||||
this.publicKeyPath = publicKeyPath;
|
||||
}
|
||||
|
||||
private ESLicenses getLicensesFromClusterState() {
|
||||
final ClusterState state = clusterService.state();
|
||||
return (ESLicenses) state.metaData().custom(LicensesMetaData.TYPE);
|
||||
}
|
||||
|
||||
|
||||
public ESLicenses getESLicenses() {
|
||||
return getLicensesFromClusterState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignedLicense getLicense(Object context) {
|
||||
assert context instanceof FeatureType;
|
||||
FeatureType featureType = (FeatureType) context;
|
||||
final ESLicenses licenses = getLicensesFromClusterState();
|
||||
final ESLicense esLicense = licenses.get(featureType);
|
||||
if (esLicense == null) {
|
||||
throw new InvalidLicenseException("Invalid License");
|
||||
}
|
||||
try {
|
||||
return extractSignedLicence(esLicense.signature(), publicKeyPath);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ESLicense getESLicense(FeatureType featureType) {
|
||||
return getLicensesFromClusterState().get(featureType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ESLicenses getEffectiveLicenses() {
|
||||
return getLicensesFromClusterState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLicenses(ESLicenses esLicenses) {
|
||||
throw new UnsupportedOperationException("Licenses can only be added by updating the cluster state");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a signedLicense (SIGNED_LICENSE_CONTENT) from the signature.
|
||||
* Validates the public key used to decrypt the license by comparing their hashes
|
||||
* <p/>
|
||||
* Signature structure:
|
||||
* | MAGIC | HEADER_LENGTH | VERSION | PUB_KEY_DIGEST | SIGNED_LICENSE_CONTENT |
|
||||
*
|
||||
* @param signature of a single license
|
||||
* @param publicKeyPath location of the public key used to decode the signature
|
||||
* @return signed license content for the license
|
||||
* @throws IOException
|
||||
*/
|
||||
static SignedLicense extractSignedLicence(String signature, String publicKeyPath) throws IOException {
|
||||
byte[] signatureBytes = Base64.decodeBase64(signature);
|
||||
ByteBuffer byteBuffer = ByteBuffer.wrap(signatureBytes);
|
||||
byteBuffer = (ByteBuffer) byteBuffer.position(13);
|
||||
int start = byteBuffer.getInt();
|
||||
int version = byteBuffer.getInt();
|
||||
byte[] hash = new byte[start - 13 - 4 - 4];
|
||||
byteBuffer.get(hash);
|
||||
|
||||
final byte[] computedHash = Hasher.hash(Base64.encodeBase64String(
|
||||
Files.readAllBytes(Paths.get(publicKeyPath))
|
||||
)).getBytes(Charset.forName("UTF-8"));
|
||||
|
||||
if (!Arrays.equals(hash, computedHash)) {
|
||||
throw new InvalidLicenseException("Invalid License");
|
||||
}
|
||||
|
||||
return new ObjectSerializer().readObject(SignedLicense.class, Arrays.copyOfRange(signatureBytes, start, signatureBytes.length));
|
||||
}
|
||||
|
||||
/**
|
||||
* Not thread-safe (allows setting licenses); used only for testing and in command-line tools
|
||||
*/
|
||||
public static class FileBasedESLicenseProvider extends ESLicenseProvider {
|
||||
private ESLicenses esLicenses;
|
||||
private final String publicKeyPath;
|
||||
|
||||
private FileBasedESLicenseProvider(ESLicenses esLicenses, String publicKeyPath) {
|
||||
this.esLicenses = esLicenses;
|
||||
this.publicKeyPath = publicKeyPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignedLicense getLicense(Object context) {
|
||||
assert context instanceof FeatureType;
|
||||
FeatureType featureType = (FeatureType) context;
|
||||
ESLicense esLicense = esLicenses.get(featureType);
|
||||
if (esLicense == null) {
|
||||
throw new InvalidLicenseException("Invalid License");
|
||||
}
|
||||
try {
|
||||
return extractSignedLicence(esLicense.signature(), publicKeyPath);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ESLicense getESLicense(FeatureType featureType) {
|
||||
return esLicenses.get(featureType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ESLicenses getEffectiveLicenses() {
|
||||
return esLicenses;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLicenses(ESLicenses esLicenses) {
|
||||
this.esLicenses = esLicenses;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,9 +20,6 @@ import static org.elasticsearch.license.core.ESLicenses.ESLicense;
|
|||
|
||||
public class Utils {
|
||||
|
||||
private Utils() {
|
||||
}
|
||||
|
||||
public static ESLicenses getESLicensesFromSignatures(final LicenseManager licenseManager, Set<String> signatures) {
|
||||
final LicenseBuilders.LicensesBuilder licensesBuilder = LicenseBuilders.licensesBuilder();
|
||||
for (String signature : signatures) {
|
||||
|
@ -41,5 +38,34 @@ public class Utils {
|
|||
return ESLicenseManager.convertToESLicense(licenseManager.decryptAndVerifyLicense(signedLicense));
|
||||
}
|
||||
|
||||
public static boolean isSame(ESLicenses firstLicenses, ESLicenses secondLicenses) {
|
||||
|
||||
// we do the build to make sure we weed out any expired licenses
|
||||
final ESLicenses licenses1 = LicenseBuilders.licensesBuilder().licenses(firstLicenses).build();
|
||||
final ESLicenses licenses2 = LicenseBuilders.licensesBuilder().licenses(secondLicenses).build();
|
||||
|
||||
// check if the effective licenses have the same feature set
|
||||
if (!licenses1.features().equals(licenses2.features())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// for every feature license, check if all the attributes are the same
|
||||
for (ESLicenses.FeatureType featureType : licenses1.features()) {
|
||||
ESLicense license1 = licenses1.get(featureType);
|
||||
ESLicense license2 = licenses2.get(featureType);
|
||||
|
||||
if (!license1.uid().equals(license2.uid())
|
||||
|| license1.feature() != license2.feature()
|
||||
|| license1.subscriptionType() != license2.subscriptionType()
|
||||
|| license1.type() != license2.type()
|
||||
|| license1.expiryDate() != license2.expiryDate()
|
||||
|| license1.issueDate() != license2.issueDate()
|
||||
|| !license1.issuedTo().equals(license2.issuedTo())
|
||||
|| license1.maxNodes() != license2.maxNodes()
|
||||
|| license1.signature().equals(license2.signature())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import org.elasticsearch.license.plugin.core.LicensesService;
|
|||
public class LicenseModule extends AbstractModule {
|
||||
@Override
|
||||
protected void configure() {
|
||||
//requestInjection(LicensesService.class);
|
||||
//TODO: bind LicensesManagementService and LicensesValidationService to LicensesServices instead
|
||||
bind(LicensesService.class).asEagerSingleton();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,11 +11,14 @@ import org.elasticsearch.cluster.metadata.MetaData;
|
|||
import org.elasticsearch.common.collect.ImmutableSet;
|
||||
import org.elasticsearch.common.component.LifecycleComponent;
|
||||
import org.elasticsearch.common.inject.Module;
|
||||
import org.elasticsearch.license.plugin.action.delete.DeleteLicenseAction;
|
||||
import org.elasticsearch.license.plugin.action.delete.TransportDeleteLicenseAction;
|
||||
import org.elasticsearch.license.plugin.action.get.GetLicenseAction;
|
||||
import org.elasticsearch.license.plugin.action.get.TransportGetLicenseAction;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseAction;
|
||||
import org.elasticsearch.license.plugin.action.put.TransportPutLicenseAction;
|
||||
import org.elasticsearch.license.plugin.core.LicensesMetaData;
|
||||
import org.elasticsearch.license.plugin.rest.RestDeleteLicenseAction;
|
||||
import org.elasticsearch.license.plugin.rest.RestGetLicenseAction;
|
||||
import org.elasticsearch.license.plugin.rest.RestPutLicenseAction;
|
||||
import org.elasticsearch.license.plugin.core.LicensesService;
|
||||
|
@ -24,7 +27,6 @@ import org.elasticsearch.rest.RestModule;
|
|||
|
||||
import java.util.Collection;
|
||||
|
||||
//TODO: plugin hooks
|
||||
public class LicensePlugin extends AbstractPlugin {
|
||||
|
||||
static {
|
||||
|
@ -45,11 +47,13 @@ public class LicensePlugin extends AbstractPlugin {
|
|||
// Register REST endpoint
|
||||
module.addRestAction(RestPutLicenseAction.class);
|
||||
module.addRestAction(RestGetLicenseAction.class);
|
||||
module.addRestAction(RestDeleteLicenseAction.class);
|
||||
}
|
||||
|
||||
public void onModule(ActionModule module) {
|
||||
module.registerAction(PutLicenseAction.INSTANCE, TransportPutLicenseAction.class);
|
||||
module.registerAction(GetLicenseAction.INSTANCE, TransportGetLicenseAction.class);
|
||||
module.registerAction(DeleteLicenseAction.INSTANCE, TransportDeleteLicenseAction.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -62,5 +66,4 @@ public class LicensePlugin extends AbstractPlugin {
|
|||
public Collection<Class<? extends Module>> modules() {
|
||||
return ImmutableSet.<Class<? extends Module>>of(LicenseModule.class);
|
||||
}
|
||||
//TODO: module binding? (LicenseModule)
|
||||
}
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.license.plugin;
|
||||
|
||||
public class Utils {
|
||||
}
|
|
@ -27,8 +27,9 @@ public class Utils {
|
|||
for (int i = 0; i < size; i++) {
|
||||
licensesBuilder.licenseAsIs(licenseFromMap(in.readMap()));
|
||||
}
|
||||
return licensesBuilder.build();
|
||||
}
|
||||
return licensesBuilder.build();
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void writeLicensesTo(ESLicenses esLicenses, StreamOutput out) throws IOException {
|
||||
|
|
|
@ -61,7 +61,7 @@ public class TransportDeleteLicenseAction extends TransportMasterNodeOperationAc
|
|||
//listener.onResponse(new DeleteLicenseResponse(licenses));
|
||||
|
||||
//TODO:: add features of the license to be deleted
|
||||
licensesService.unregisteredLicenses(clusterService, "delete_licenses []", request, new ActionListener<ClusterStateUpdateResponse>() {
|
||||
licensesService.unregisteredLicenses("delete_licenses []", request, new ActionListener<ClusterStateUpdateResponse>() {
|
||||
@Override
|
||||
public void onResponse(ClusterStateUpdateResponse clusterStateUpdateResponse) {
|
||||
listener.onResponse(new DeleteLicenseResponse(clusterStateUpdateResponse.isAcknowledged()));
|
||||
|
|
|
@ -9,6 +9,7 @@ import org.elasticsearch.action.ActionResponse;
|
|||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.license.core.ESLicenses;
|
||||
import org.elasticsearch.license.core.LicenseBuilders;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
@ -27,10 +28,9 @@ public class GetLicenseResponse extends ActionResponse {
|
|||
}
|
||||
|
||||
public ESLicenses licenses() {
|
||||
return licenses;
|
||||
return (licenses != null) ? licenses : LicenseBuilders.licensesBuilder().build();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void readFrom(StreamInput in) throws IOException {
|
||||
super.readFrom(in);
|
||||
|
|
|
@ -55,8 +55,9 @@ public class TransportPutLicenseAction extends TransportMasterNodeOperationActio
|
|||
|
||||
@Override
|
||||
protected void masterOperation(final PutLicenseRequest request, ClusterState state, final ActionListener<PutLicenseResponse> listener) throws ElasticsearchException {
|
||||
//TODO
|
||||
licensesService.registerLicenses(clusterService, "put_licenses []",request, new ActionListener<ClusterStateUpdateResponse>() {
|
||||
//TODO license validation
|
||||
|
||||
licensesService.registerLicenses("put_licenses []",request, new ActionListener<ClusterStateUpdateResponse>() {
|
||||
@Override
|
||||
public void onResponse(ClusterStateUpdateResponse clusterStateUpdateResponse) {
|
||||
listener.onResponse(new PutLicenseResponse(clusterStateUpdateResponse.isAcknowledged()));
|
||||
|
|
|
@ -46,8 +46,10 @@ public class LicensesMetaData implements MetaData.Custom, ESLicenses {
|
|||
|
||||
private static ImmutableMap<FeatureType, ESLicense> map(Iterable<ESLicense> esLicenses) {
|
||||
final ImmutableMap.Builder<FeatureType, ESLicense> builder = ImmutableMap.builder();
|
||||
for (ESLicense esLicense : esLicenses) {
|
||||
builder.put(esLicense.feature(), esLicense);
|
||||
if (esLicenses != null) {
|
||||
for (ESLicense esLicense : esLicenses) {
|
||||
builder.put(esLicense.feature(), esLicense);
|
||||
}
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
|
|
@ -8,19 +8,22 @@ package org.elasticsearch.license.plugin.core;
|
|||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.cluster.*;
|
||||
import org.elasticsearch.cluster.ack.ClusterStateUpdateRequest;
|
||||
import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.cluster.node.DiscoveryNode;
|
||||
import org.elasticsearch.common.component.AbstractLifecycleComponent;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.inject.Injector;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.license.core.ESLicenses;
|
||||
import org.elasticsearch.license.core.LicenseBuilders;
|
||||
import org.elasticsearch.license.manager.ESLicenseManager;
|
||||
import org.elasticsearch.license.plugin.action.delete.DeleteLicenseRequest;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseRequest;
|
||||
import org.elasticsearch.node.Node;
|
||||
import org.elasticsearch.node.internal.InternalNode;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Service responsible for maintaining and providing access to licenses on nodes.
|
||||
|
@ -31,11 +34,16 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||
*/
|
||||
public class LicensesService extends AbstractLifecycleComponent<LicensesService> implements ClusterStateListener {
|
||||
|
||||
private AtomicBoolean registerClusterStateListener = new AtomicBoolean(false);
|
||||
private ESLicenseManager esLicenseManager;
|
||||
|
||||
private InternalNode node;
|
||||
|
||||
private ClusterService clusterService;
|
||||
|
||||
@Inject
|
||||
public LicensesService(Settings settings) {
|
||||
public LicensesService(Settings settings, Node node) {
|
||||
super(settings);
|
||||
this.node = (InternalNode) node;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -44,14 +52,8 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
* This method can be only called on the master node. It tries to create a new licenses on the master
|
||||
* and if it was successful it adds the license to cluster metadata.
|
||||
*/
|
||||
public void registerLicenses(ClusterService clusterService, String source, final PutLicenseRequest request, final ActionListener<ClusterStateUpdateResponse> listener) {
|
||||
if (registerClusterStateListener.compareAndSet(false, true)) {
|
||||
if (DiscoveryNode.dataNode(settings) || DiscoveryNode.masterNode(settings)) {
|
||||
clusterService.add(this);
|
||||
}
|
||||
}
|
||||
public void registerLicenses(String source, final PutLicenseRequest request, final ActionListener<ClusterStateUpdateResponse> listener) {
|
||||
final LicensesMetaData newLicenseMetaData = new LicensesMetaData(request.license());
|
||||
//TODO: add a source field to request
|
||||
clusterService.submitStateUpdateTask(source, new AckedClusterStateUpdateTask<ClusterStateUpdateResponse>(request, listener) {
|
||||
@Override
|
||||
protected ClusterStateUpdateResponse newResponse(boolean acknowledged) {
|
||||
|
@ -60,11 +62,12 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
|
||||
@Override
|
||||
public ClusterState execute(ClusterState currentState) throws Exception {
|
||||
// TODO check if newLicenseMetaData actually needs a cluster update
|
||||
MetaData metaData = currentState.metaData();
|
||||
MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData());
|
||||
LicensesMetaData currentLicenses = metaData.custom(LicensesMetaData.TYPE);
|
||||
|
||||
esLicenseManager.verifyLicenses(newLicenseMetaData);
|
||||
|
||||
if (currentLicenses == null) {
|
||||
// no licenses were registered
|
||||
currentLicenses = newLicenseMetaData;
|
||||
|
@ -72,6 +75,7 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
// merge previous license with new one
|
||||
currentLicenses = new LicensesMetaData(LicenseBuilders.merge(currentLicenses, newLicenseMetaData));
|
||||
}
|
||||
|
||||
mdBuilder.putCustom(LicensesMetaData.TYPE, currentLicenses);
|
||||
return ClusterState.builder(currentState).metaData(mdBuilder).build();
|
||||
}
|
||||
|
@ -79,8 +83,8 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
|
||||
}
|
||||
|
||||
//TODO
|
||||
public void unregisteredLicenses(ClusterService clusterService, String source, final DeleteLicenseRequest request, final ActionListener<ClusterStateUpdateResponse> listener) {
|
||||
public void unregisteredLicenses(String source, final DeleteLicenseRequest request, final ActionListener<ClusterStateUpdateResponse> listener) {
|
||||
final Set<ESLicenses.FeatureType> featuresToDelete = asFeatureTypes(request.features());
|
||||
clusterService.submitStateUpdateTask(source, new AckedClusterStateUpdateTask<ClusterStateUpdateResponse>(request, listener) {
|
||||
@Override
|
||||
protected ClusterStateUpdateResponse newResponse(boolean acknowledged) {
|
||||
|
@ -89,18 +93,12 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
|
||||
@Override
|
||||
public ClusterState execute(ClusterState currentState) throws Exception {
|
||||
// TODO check if newLicenseMetaData actually needs a cluster update
|
||||
MetaData metaData = currentState.metaData();
|
||||
MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData());
|
||||
LicensesMetaData currentLicenses = metaData.custom(LicensesMetaData.TYPE);
|
||||
|
||||
//TODO: implement deletion
|
||||
if (currentLicenses == null) {
|
||||
// no licenses were registered
|
||||
//currentLicenses = newLicenseMetaData;
|
||||
} else {
|
||||
// merge previous license with new one
|
||||
//currentLicenses = new LicensesMetaData(LicenseBuilders.merge(currentLicenses, newLicenseMetaData));
|
||||
if (currentLicenses != null) {
|
||||
currentLicenses = new LicensesMetaData(LicenseBuilders.removeFeatures(currentLicenses, featuresToDelete));
|
||||
}
|
||||
mdBuilder.putCustom(LicensesMetaData.TYPE, currentLicenses);
|
||||
return ClusterState.builder(currentState).metaData(mdBuilder).build();
|
||||
|
@ -110,7 +108,12 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
|
||||
@Override
|
||||
protected void doStart() throws ElasticsearchException {
|
||||
//TODO
|
||||
clusterService = node.injector().getInstance(ClusterService.class);
|
||||
esLicenseManager = ESLicenseManager.createClusterStateBasedInstance(clusterService);
|
||||
|
||||
if (DiscoveryNode.dataNode(settings) || DiscoveryNode.masterNode(settings)) {
|
||||
clusterService.add(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -127,4 +130,12 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
public void clusterChanged(ClusterChangedEvent event) {
|
||||
//TODO
|
||||
}
|
||||
|
||||
private static Set<ESLicenses.FeatureType> asFeatureTypes(Set<String> featureTypeStrings) {
|
||||
Set<ESLicenses.FeatureType> featureTypes = new HashSet<>(featureTypeStrings.size());
|
||||
for (String featureString : featureTypeStrings) {
|
||||
featureTypes.add(ESLicenses.FeatureType.fromString(featureString));
|
||||
}
|
||||
return featureTypes;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
package org.elasticsearch.license.plugin.rest;
|
||||
|
||||
import org.elasticsearch.ElasticsearchIllegalArgumentException;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
|
@ -38,7 +39,6 @@ public class RestDeleteLicenseAction extends BaseRestHandler {
|
|||
@Inject
|
||||
public RestDeleteLicenseAction(Settings settings, RestController controller, Client client, TransportDeleteLicenseAction transportDeleteLicenseAction) {
|
||||
super(settings, controller, client);
|
||||
controller.registerHandler(DELETE, "/_cluster/license/", this);
|
||||
controller.registerHandler(DELETE, "/_cluster/license/{features}", this);
|
||||
this.transportDeleteLicenseAction = transportDeleteLicenseAction;
|
||||
}
|
||||
|
@ -47,10 +47,11 @@ public class RestDeleteLicenseAction extends BaseRestHandler {
|
|||
@Override
|
||||
public void handleRequest(final RestRequest request, final RestChannel channel, final Client client) {
|
||||
final String[] features = Strings.splitStringByCommaToArray(request.param("features"));
|
||||
|
||||
if (features.length == 0) {
|
||||
throw new ElasticsearchIllegalArgumentException("no features specified for license deletion");
|
||||
}
|
||||
DeleteLicenseRequest deleteLicenseRequest = new DeleteLicenseRequest(getFeaturesToDelete(features));
|
||||
deleteLicenseRequest.listenerThreaded(false);
|
||||
//deleteLicenseRequest.license(request.content().toUtf8());
|
||||
transportDeleteLicenseAction.execute(deleteLicenseRequest, new AcknowledgedRestListener<DeleteLicenseResponse>(channel));
|
||||
}
|
||||
|
||||
|
@ -64,7 +65,6 @@ public class RestDeleteLicenseAction extends BaseRestHandler {
|
|||
break;
|
||||
} else {
|
||||
result.add(FeatureType.fromString(feature).string());
|
||||
|
||||
}
|
||||
}
|
||||
return result.toArray(new String[result.size()]);
|
||||
|
|
|
@ -52,6 +52,5 @@ public class RestGetLicenseAction extends BaseRestHandler {
|
|||
return new BytesRestResponse(OK, builder);
|
||||
}
|
||||
});
|
||||
//client.admin().cluster().execute(GetLicenseAction.INSTANCE, getLicenseRequest, )
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,5 @@ public class RestPutLicenseAction extends BaseRestHandler {
|
|||
putLicenseRequest.listenerThreaded(false);
|
||||
putLicenseRequest.license(request.content().toUtf8());
|
||||
transportPutLicensesAction.execute(putLicenseRequest, new AcknowledgedRestListener<PutLicenseResponse>(channel));
|
||||
// client.admin().cluster().execute(PutLicenseAction.INSTANCE, putLicenseRequest, );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import org.elasticsearch.license.core.ESLicenses;
|
||||
import org.elasticsearch.license.licensor.tools.KeyPairGeneratorTool;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
public class AbstractLicensingTestBase {
|
||||
|
||||
protected static String pubKeyPath = null;
|
||||
protected static String priKeyPath = null;
|
||||
|
||||
@BeforeClass
|
||||
public static void setup() throws IOException {
|
||||
|
||||
// Generate temp KeyPair spec
|
||||
File privateKeyFile = File.createTempFile("privateKey", ".key");
|
||||
File publicKeyFile = File.createTempFile("publicKey", ".key");
|
||||
AbstractLicensingTestBase.pubKeyPath = publicKeyFile.getAbsolutePath();
|
||||
AbstractLicensingTestBase.priKeyPath = privateKeyFile.getAbsolutePath();
|
||||
assert privateKeyFile.delete();
|
||||
assert publicKeyFile.delete();
|
||||
|
||||
// Generate keyPair
|
||||
String[] args = new String[4];
|
||||
args[0] = "--publicKeyPath";
|
||||
args[1] = AbstractLicensingTestBase.pubKeyPath;
|
||||
args[2] = "--privateKeyPath";
|
||||
args[3] = AbstractLicensingTestBase.priKeyPath;
|
||||
KeyPairGeneratorTool.main(args);
|
||||
}
|
||||
|
||||
public String generateSignedLicenses(Map<ESLicenses.FeatureType, TestUtils.FeatureAttributes> map) throws IOException {
|
||||
String licenseString = TestUtils.generateESLicenses(map);
|
||||
return TestUtils.runLicenseGenerationTool(licenseString, pubKeyPath, priKeyPath);
|
||||
}
|
||||
}
|
|
@ -48,6 +48,18 @@ public class TestUtils {
|
|||
|
||||
}
|
||||
|
||||
public static String runLicenseGenerationTool(String licenseInput, String pubKeyPath, String priKeyPath) throws IOException {
|
||||
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 {
|
||||
File temp = File.createTempFile("temp", ".out");
|
||||
temp.deleteOnExit();
|
||||
|
|
|
@ -5,14 +5,12 @@
|
|||
*/
|
||||
package org.elasticsearch.license.licensor;
|
||||
|
||||
import org.elasticsearch.license.AbstractLicensingTestBase;
|
||||
import org.elasticsearch.license.TestUtils;
|
||||
import org.elasticsearch.license.core.ESLicenses;
|
||||
import org.elasticsearch.license.core.LicenseUtils;
|
||||
import org.elasticsearch.license.licensor.tools.KeyPairGeneratorTool;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.util.HashMap;
|
||||
|
@ -22,30 +20,7 @@ import static org.elasticsearch.license.core.ESLicenses.FeatureType;
|
|||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
public class LicenseGenerationTests {
|
||||
|
||||
private static String pubKeyPath = null;
|
||||
private static String priKeyPath = null;
|
||||
|
||||
@BeforeClass
|
||||
public static void setup() throws IOException {
|
||||
|
||||
// Generate temp KeyPair spec
|
||||
File privateKeyFile = File.createTempFile("privateKey", ".key");
|
||||
File publicKeyFile = File.createTempFile("publicKey", ".key");
|
||||
LicenseGenerationTests.pubKeyPath = publicKeyFile.getAbsolutePath();
|
||||
LicenseGenerationTests.priKeyPath = privateKeyFile.getAbsolutePath();
|
||||
assert privateKeyFile.delete();
|
||||
assert publicKeyFile.delete();
|
||||
|
||||
// Generate keyPair
|
||||
String[] args = new String[4];
|
||||
args[0] = "--publicKeyPath";
|
||||
args[1] = LicenseGenerationTests.pubKeyPath;
|
||||
args[2] = "--privateKeyPath";
|
||||
args[3] = LicenseGenerationTests.priKeyPath;
|
||||
KeyPairGeneratorTool.main(args);
|
||||
}
|
||||
public class LicenseGenerationTests extends AbstractLicensingTestBase {
|
||||
|
||||
@Test
|
||||
public void testSimpleLicenseGeneration() throws ParseException, IOException {
|
||||
|
@ -54,17 +29,7 @@ public class LicenseGenerationTests {
|
|||
new TestUtils.FeatureAttributes("shield", "subscription", "platinum", "foo bar Inc.", "elasticsearch", 2, "2014-12-13", "2015-12-13");
|
||||
map.put(FeatureType.SHIELD, featureAttributes);
|
||||
|
||||
String licenseString = TestUtils.generateESLicenses(map);
|
||||
|
||||
String[] args = new String[6];
|
||||
args[0] = "--license";
|
||||
args[1] = licenseString;
|
||||
args[2] = "--publicKeyPath";
|
||||
args[3] = pubKeyPath;
|
||||
args[4] = "--privateKeyPath";
|
||||
args[5] = priKeyPath;
|
||||
|
||||
String licenseOutput = TestUtils.runLicenseGenerationTool(args);
|
||||
String licenseOutput = generateSignedLicenses(map);
|
||||
|
||||
ESLicenses esLicensesOutput = LicenseUtils.readLicensesFromString(licenseOutput);
|
||||
|
||||
|
@ -82,16 +47,7 @@ public class LicenseGenerationTests {
|
|||
map.put(FeatureType.SHIELD, shildFeatureAttributes);
|
||||
map.put(FeatureType.MARVEL, marvelFeatureAttributes);
|
||||
|
||||
String licenseString = TestUtils.generateESLicenses(map);
|
||||
String[] args = new String[6];
|
||||
args[0] = "--license";
|
||||
args[1] = licenseString;
|
||||
args[2] = "--publicKeyPath";
|
||||
args[3] = pubKeyPath;
|
||||
args[4] = "--privateKeyPath";
|
||||
args[5] = priKeyPath;
|
||||
|
||||
String licenseOutput = TestUtils.runLicenseGenerationTool(args);
|
||||
String licenseOutput = generateSignedLicenses(map);
|
||||
|
||||
ESLicenses esLicensesOutput = LicenseUtils.readLicensesFromString(licenseOutput);
|
||||
|
||||
|
|
|
@ -6,13 +6,11 @@
|
|||
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.ESLicenses;
|
||||
import org.elasticsearch.license.core.LicenseUtils;
|
||||
import org.elasticsearch.license.licensor.tools.KeyPairGeneratorTool;
|
||||
import org.elasticsearch.license.licensor.tools.LicenseVerificationTool;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -21,30 +19,7 @@ import java.io.IOException;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class LicenseVerificationToolTests {
|
||||
|
||||
private static String pubKeyPath = null;
|
||||
private static String priKeyPath = null;
|
||||
|
||||
@BeforeClass
|
||||
public static void setup() throws IOException {
|
||||
|
||||
// Generate temp KeyPair spec
|
||||
File privateKeyFile = File.createTempFile("privateKey", ".key");
|
||||
File publicKeyFile = File.createTempFile("publicKey", ".key");
|
||||
LicenseVerificationToolTests.pubKeyPath = publicKeyFile.getAbsolutePath();
|
||||
LicenseVerificationToolTests.priKeyPath = privateKeyFile.getAbsolutePath();
|
||||
assert privateKeyFile.delete();
|
||||
assert publicKeyFile.delete();
|
||||
|
||||
// Generate keyPair
|
||||
String[] args = new String[4];
|
||||
args[0] = "--publicKeyPath";
|
||||
args[1] = LicenseVerificationToolTests.pubKeyPath;
|
||||
args[2] = "--privateKeyPath";
|
||||
args[3] = LicenseVerificationToolTests.priKeyPath;
|
||||
KeyPairGeneratorTool.main(args);
|
||||
}
|
||||
public class LicenseVerificationToolTests extends AbstractLicensingTestBase {
|
||||
|
||||
@Test
|
||||
public void testEffectiveLicenseGeneration() throws Exception {
|
||||
|
@ -63,13 +38,7 @@ public class LicenseVerificationToolTests {
|
|||
signedLicense = runLicenseGenerationTool(TestUtils.generateESLicenses(map));
|
||||
String secondLicenseFile = getAsFilePath(signedLicense);
|
||||
|
||||
String[] args = new String[4];
|
||||
args[0] = "--licensesFiles";
|
||||
args[1] = firstLicenseFile + ":" + secondLicenseFile;
|
||||
args[2] = "--publicKeyPath";
|
||||
args[3] = pubKeyPath;
|
||||
|
||||
String effectiveLicenseStr = runLicenseVerificationTool(args);
|
||||
String effectiveLicenseStr = runLicenseVerificationTool(new String[]{firstLicenseFile, secondLicenseFile});
|
||||
ESLicenses effectiveLicense = LicenseUtils.readLicensesFromString(effectiveLicenseStr);
|
||||
|
||||
map.put(ESLicenses.FeatureType.SHIELD, featureWithLongerExpiryDate);
|
||||
|
@ -95,13 +64,7 @@ public class LicenseVerificationToolTests {
|
|||
signedLicense = runLicenseGenerationTool(TestUtils.generateESLicenses(map));
|
||||
String secondLicenseFile = getAsFilePath(signedLicense);
|
||||
|
||||
String[] args = new String[4];
|
||||
args[0] = "--licensesFiles";
|
||||
args[1] = firstLicenseFile + ":" + secondLicenseFile;
|
||||
args[2] = "--publicKeyPath";
|
||||
args[3] = pubKeyPath;
|
||||
|
||||
String effectiveLicenseStr = runLicenseVerificationTool(args);
|
||||
String effectiveLicenseStr = runLicenseVerificationTool(new String[]{firstLicenseFile, secondLicenseFile});
|
||||
ESLicenses effectiveLicense = LicenseUtils.readLicensesFromString(effectiveLicenseStr);
|
||||
|
||||
// verify that the effective license contains both feature licenses
|
||||
|
@ -134,13 +97,7 @@ public class LicenseVerificationToolTests {
|
|||
signedLicense = runLicenseGenerationTool(TestUtils.generateESLicenses(map));
|
||||
String secondLicenseFile = getAsFilePath(signedLicense);
|
||||
|
||||
String[] args = new String[4];
|
||||
args[0] = "--licensesFiles";
|
||||
args[1] = firstLicenseFile + ":" + secondLicenseFile;
|
||||
args[2] = "--publicKeyPath";
|
||||
args[3] = pubKeyPath;
|
||||
|
||||
String effectiveLicenseStr = runLicenseVerificationTool(args);
|
||||
String effectiveLicenseStr = runLicenseVerificationTool(new String[]{firstLicenseFile, secondLicenseFile});
|
||||
ESLicenses effectiveLicense = LicenseUtils.readLicensesFromString(effectiveLicenseStr);
|
||||
|
||||
map.put(ESLicenses.FeatureType.SHIELD, shieldFeatureWithLongerExpiryDate);
|
||||
|
@ -150,7 +107,19 @@ public class LicenseVerificationToolTests {
|
|||
TestUtils.verifyESLicenses(effectiveLicense, map);
|
||||
}
|
||||
|
||||
public static String runLicenseVerificationTool(String[] args) throws IOException {
|
||||
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) {
|
||||
licenseFilePathString.append(":");
|
||||
}
|
||||
}
|
||||
String[] args = new String[4];
|
||||
args[0] = "--licensesFiles";
|
||||
args[1] = licenseFilePathString.toString();
|
||||
args[2] = "--publicKeyPath";
|
||||
args[3] = pubKeyPath;
|
||||
File temp = File.createTempFile("temp", ".out");
|
||||
temp.deleteOnExit();
|
||||
try (FileOutputStream outputStream = new FileOutputStream(temp)) {
|
||||
|
@ -159,16 +128,8 @@ public class LicenseVerificationToolTests {
|
|||
return FileUtils.readFileToString(temp);
|
||||
}
|
||||
|
||||
public static String runLicenseGenerationTool(String licenseInput) throws IOException {
|
||||
String args[] = new String[6];
|
||||
args[0] = "--license";
|
||||
args[1] = licenseInput;
|
||||
args[2] = "--publicKeyPath";
|
||||
args[3] = pubKeyPath;
|
||||
args[4] = "--privateKeyPath";
|
||||
args[5] = priKeyPath;
|
||||
|
||||
return TestUtils.runLicenseGenerationTool(args);
|
||||
public String runLicenseGenerationTool(String licenseInput) throws IOException {
|
||||
return TestUtils.runLicenseGenerationTool(licenseInput, pubKeyPath, priKeyPath);
|
||||
}
|
||||
|
||||
private static String getAsFilePath(String content) throws IOException {
|
||||
|
|
|
@ -6,52 +6,39 @@
|
|||
package org.elasticsearch.license.manager;
|
||||
|
||||
import net.nicholaswilliams.java.licensing.exception.InvalidLicenseException;
|
||||
import org.elasticsearch.license.AbstractLicensingTestBase;
|
||||
import org.elasticsearch.license.TestUtils;
|
||||
import org.elasticsearch.license.core.DateUtils;
|
||||
import org.elasticsearch.license.core.ESLicenses;
|
||||
import org.elasticsearch.license.core.LicenseBuilders;
|
||||
import org.elasticsearch.license.licensor.tools.KeyPairGeneratorTool;
|
||||
import org.junit.After;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
import static org.elasticsearch.license.core.ESLicenses.FeatureType;
|
||||
import static org.elasticsearch.license.core.LicenseUtils.readLicensesFromString;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class LicenseVerificationTests {
|
||||
public class LicenseVerificationTests extends AbstractLicensingTestBase {
|
||||
|
||||
private static String pubKeyPath = null;
|
||||
private static String priKeyPath = null;
|
||||
private static ESLicenseManager esLicenseManager;
|
||||
|
||||
private final static ESLicenses EMPTY_LICENSES = LicenseBuilders.licensesBuilder().build();
|
||||
|
||||
@BeforeClass
|
||||
public static void setup() throws IOException {
|
||||
|
||||
// Generate temp KeyPair spec
|
||||
File privateKeyFile = File.createTempFile("privateKey", ".key");
|
||||
File publicKeyFile = File.createTempFile("publicKey", ".key");
|
||||
LicenseVerificationTests.pubKeyPath = publicKeyFile.getAbsolutePath();
|
||||
LicenseVerificationTests.priKeyPath = privateKeyFile.getAbsolutePath();
|
||||
assert privateKeyFile.delete();
|
||||
assert publicKeyFile.delete();
|
||||
|
||||
// Generate keyPair
|
||||
String[] args = new String[4];
|
||||
args[0] = "--publicKeyPath";
|
||||
args[1] = LicenseVerificationTests.pubKeyPath;
|
||||
args[2] = "--privateKeyPath";
|
||||
args[3] = LicenseVerificationTests.priKeyPath;
|
||||
KeyPairGeneratorTool.main(args);
|
||||
public static void setupManager() {
|
||||
esLicenseManager = ESLicenseManager.createLocalBasedInstance(LicenseBuilders.licensesBuilder().build(), pubKeyPath);
|
||||
}
|
||||
|
||||
@After
|
||||
public void clearManager() {
|
||||
esLicenseManager.clearAndAddLicenses(EMPTY_LICENSES);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGeneratedLicenses() throws Exception {
|
||||
Date issueDate = new Date();
|
||||
|
@ -62,25 +49,14 @@ public class LicenseVerificationTests {
|
|||
new TestUtils.FeatureAttributes("shield", "subscription", "platinum", "foo bar Inc.", "elasticsearch", 2, issueDateStr, expiryDateStr);
|
||||
map.put(FeatureType.SHIELD, featureAttributes);
|
||||
|
||||
String licenseString = TestUtils.generateESLicenses(map);
|
||||
ESLicenses esLicensesOutput = readLicensesFromString(generateSignedLicenses(map));
|
||||
|
||||
String[] args = new String[6];
|
||||
args[0] = "--license";
|
||||
args[1] = licenseString;
|
||||
args[2] = "--publicKeyPath";
|
||||
args[3] = pubKeyPath;
|
||||
args[4] = "--privateKeyPath";
|
||||
args[5] = priKeyPath;
|
||||
|
||||
String licenseOutput = TestUtils.runLicenseGenerationTool(args);
|
||||
|
||||
ESLicenses esLicensesOutput = readLicensesFromString(licenseOutput);
|
||||
|
||||
ESLicenseManager esLicenseManager = new ESLicenseManager(esLicensesOutput, pubKeyPath);
|
||||
esLicenseManager.clearAndAddLicenses(esLicensesOutput);
|
||||
|
||||
esLicenseManager.verifyLicenses();
|
||||
|
||||
verifyLicenseManager(esLicenseManager, map);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -97,59 +73,66 @@ public class LicenseVerificationTests {
|
|||
map.put(FeatureType.SHIELD, shildFeatureAttributes);
|
||||
map.put(FeatureType.MARVEL, marvelFeatureAttributes);
|
||||
|
||||
String licenseString = TestUtils.generateESLicenses(map);
|
||||
ESLicenses esLicensesOutput = readLicensesFromString(generateSignedLicenses(map));
|
||||
|
||||
String[] args = new String[6];
|
||||
args[0] = "--license";
|
||||
args[1] = licenseString;
|
||||
args[2] = "--publicKeyPath";
|
||||
args[3] = pubKeyPath;
|
||||
args[4] = "--privateKeyPath";
|
||||
args[5] = priKeyPath;
|
||||
esLicenseManager.clearAndAddLicenses(esLicensesOutput);
|
||||
|
||||
String licenseOutput = TestUtils.runLicenseGenerationTool(args);
|
||||
|
||||
ESLicenses esLicensesOutput = readLicensesFromString(licenseOutput);
|
||||
|
||||
ESLicenseManager esLicenseManager = new ESLicenseManager(esLicensesOutput, pubKeyPath);
|
||||
//printLicense(esLicenseManager.getEffectiveLicenses());
|
||||
|
||||
esLicenseManager.verifyLicenses();
|
||||
|
||||
verifyLicenseManager(esLicenseManager, map);
|
||||
|
||||
}
|
||||
|
||||
private static Date getDateBeforeDays(Date originalDate, int days) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.clear();
|
||||
calendar.setTimeZone(DateUtils.TIME_ZONE);
|
||||
calendar.setTimeInMillis(originalDate.getTime());
|
||||
|
||||
int originalDays = calendar.get(Calendar.DAY_OF_YEAR);
|
||||
calendar.set(Calendar.DAY_OF_YEAR, originalDays - days);
|
||||
|
||||
return calendar.getTime();
|
||||
}
|
||||
|
||||
private static Date getDateAfterDays(Date originalDate, int days) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.clear();
|
||||
calendar.setTimeZone(DateUtils.TIME_ZONE);
|
||||
calendar.setTimeInMillis(originalDate.getTime());
|
||||
|
||||
calendar.add(Calendar.DAY_OF_YEAR, days);
|
||||
|
||||
return calendar.getTime();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testLicenseExpiry() throws Exception {
|
||||
|
||||
Date issueDate = new Date();
|
||||
Date issueDate = getDateBeforeDays(new Date(), 60);
|
||||
Date expiryDate = getDateAfterDays(new Date(), 30);
|
||||
Date expiredExpiryDate = getDateBeforeDays(new Date(), 10);
|
||||
String issueDateStr = DateUtils.dateStringFromLongDate(issueDate.getTime());
|
||||
String expiryDateStr = DateUtils.dateStringFromLongDate(DateUtils.longExpiryDateFromDate(issueDate.getTime() + 24 * 60 * 60l));
|
||||
String expiryDateStr = DateUtils.dateStringFromLongDate(DateUtils.longExpiryDateFromDate(expiryDate.getTime()));
|
||||
|
||||
String expiredExpiryDateStr = DateUtils.dateStringFromLongDate(DateUtils.longExpiryDateFromDate(issueDate.getTime() - 5 * 24 * 60 * 60 * 1000l));
|
||||
final long longExpiryDateFromDate = DateUtils.longExpiryDateFromDate(expiredExpiryDate.getTime());
|
||||
assert longExpiryDateFromDate < System.currentTimeMillis();
|
||||
String expiredExpiryDateStr = DateUtils.dateStringFromLongDate(longExpiryDateFromDate);
|
||||
|
||||
Map<FeatureType, 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, expiredExpiryDateStr);
|
||||
new TestUtils.FeatureAttributes("marvel", "internal", "silver", "foo1 bar Inc.", "elasticsearc3h", 10, issueDateStr, expiredExpiryDateStr);
|
||||
map.put(FeatureType.SHIELD, shildFeatureAttributes);
|
||||
map.put(FeatureType.MARVEL, marvelFeatureAttributes);
|
||||
|
||||
String licenseString = TestUtils.generateESLicenses(map);
|
||||
ESLicenses esLicensesOutput = readLicensesFromString(generateSignedLicenses(map));
|
||||
|
||||
String[] args = new String[6];
|
||||
args[0] = "--license";
|
||||
args[1] = licenseString;
|
||||
args[2] = "--publicKeyPath";
|
||||
args[3] = pubKeyPath;
|
||||
args[4] = "--privateKeyPath";
|
||||
args[5] = priKeyPath;
|
||||
|
||||
String licenseOutput = TestUtils.runLicenseGenerationTool(args);
|
||||
|
||||
ESLicenses esLicensesOutput = readLicensesFromString(licenseOutput);
|
||||
|
||||
ESLicenseManager esLicenseManager = new ESLicenseManager(esLicensesOutput, pubKeyPath);
|
||||
esLicenseManager.clearAndAddLicenses(esLicensesOutput);
|
||||
|
||||
// All validation for shield license should be normal as expected
|
||||
verifyLicenseManager(esLicenseManager, Collections.singletonMap(FeatureType.SHIELD, shildFeatureAttributes));
|
||||
|
@ -168,19 +151,7 @@ public class LicenseVerificationTests {
|
|||
new TestUtils.FeatureAttributes("shield", "subscription", "platinum", "foo bar Inc.", "elasticsearch", 2, issueDateStr, expiryDateStr);
|
||||
map.put(FeatureType.SHIELD, featureAttributes);
|
||||
|
||||
String licenseString = TestUtils.generateESLicenses(map);
|
||||
|
||||
String[] args = new String[6];
|
||||
args[0] = "--license";
|
||||
args[1] = licenseString;
|
||||
args[2] = "--publicKeyPath";
|
||||
args[3] = pubKeyPath;
|
||||
args[4] = "--privateKeyPath";
|
||||
args[5] = priKeyPath;
|
||||
|
||||
String licenseOutput = TestUtils.runLicenseGenerationTool(args);
|
||||
|
||||
ESLicenses esLicensesOutput = readLicensesFromString(licenseOutput);
|
||||
ESLicenses esLicensesOutput = readLicensesFromString(generateSignedLicenses(map));
|
||||
|
||||
ESLicenses.ESLicense esLicense = esLicensesOutput.get(FeatureType.SHIELD);
|
||||
|
||||
|
@ -194,14 +165,13 @@ public class LicenseVerificationTests {
|
|||
|
||||
ESLicenses tamperedLicenses = LicenseBuilders.licensesBuilder().license(tamperedLicense).build();
|
||||
|
||||
ESLicenseManager esLicenseManager = null;
|
||||
try {
|
||||
esLicenseManager = new ESLicenseManager(tamperedLicenses, pubKeyPath);
|
||||
assertTrue("License manager should always report the original (signed) expiry date", esLicenseManager.getExpiryDateForLicense(FeatureType.SHIELD) == originalExpiryDate);
|
||||
esLicenseManager.clearAndAddLicenses(tamperedLicenses);
|
||||
assertTrue("License manager should always report the original (signed) expiry date of: " + originalExpiryDate + " but got: " + esLicenseManager.getExpiryDateForLicense(FeatureType.SHIELD), esLicenseManager.getExpiryDateForLicense(FeatureType.SHIELD) == originalExpiryDate);
|
||||
esLicenseManager.verifyLicenses();
|
||||
fail();
|
||||
} catch (InvalidLicenseException e) {
|
||||
assertTrue("Exception should contain 'Invalid License' ", e.getMessage().contains("Invalid License"));
|
||||
assertTrue("Exception should contain 'Invalid License' but got: " + e.getMessage(), e.getMessage().contains("Invalid License"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -213,12 +183,12 @@ public class LicenseVerificationTests {
|
|||
assertTrue("License should have issuedTo of " + featureAttributes.issuedTo, esLicenseManager.getIssuedToForLicense(featureType).equals(featureAttributes.issuedTo));
|
||||
assertTrue("License should have issuer of " + featureAttributes.issuer, esLicenseManager.getIssuerForLicense(featureType).equals(featureAttributes.issuer));
|
||||
assertTrue("License should have issue date of " + DateUtils.longFromDateString(featureAttributes.issueDate), esLicenseManager.getIssueDateForLicense(featureType) == DateUtils.longFromDateString(featureAttributes.issueDate));
|
||||
assertTrue("License should have expiry date of " + DateUtils.longExpiryDateFromString(featureAttributes.expiryDate), esLicenseManager.getExpiryDateForLicense(featureType) == DateUtils.longExpiryDateFromString(featureAttributes.expiryDate));
|
||||
assertTrue("License should have type of " + featureAttributes.featureType, esLicenseManager.getTypeForLicense(featureType) == ESLicenses.Type.fromString(featureAttributes.type));
|
||||
assertTrue("License should have expiry date of " + DateUtils.longExpiryDateFromString(featureAttributes.expiryDate) + " got: " + esLicenseManager.getExpiryDateForLicense(featureType), esLicenseManager.getExpiryDateForLicense(featureType) == DateUtils.longExpiryDateFromString(featureAttributes.expiryDate));
|
||||
assertTrue("License should have type of " + featureAttributes.type + " got: " + esLicenseManager.getTypeForLicense(featureType).string(), esLicenseManager.getTypeForLicense(featureType) == ESLicenses.Type.fromString(featureAttributes.type));
|
||||
assertTrue("License should have subscription type of " + featureAttributes.subscriptionType, esLicenseManager.getSubscriptionTypeForLicense(featureType) == ESLicenses.SubscriptionType.fromString(featureAttributes.subscriptionType));
|
||||
|
||||
|
||||
assertTrue("License should be valid for shield", esLicenseManager.hasLicenseForFeature(featureType));
|
||||
assertTrue("License should be valid for " + featureType.string(), esLicenseManager.hasLicenseForFeature(featureType));
|
||||
assertTrue("License should be valid for maxNodes = " + (featureAttributes.maxNodes - 1), esLicenseManager.hasLicenseForNodes(featureType, featureAttributes.maxNodes - 1));
|
||||
assertTrue("License should be valid for maxNodes = " + (featureAttributes.maxNodes), esLicenseManager.hasLicenseForNodes(featureType, featureAttributes.maxNodes));
|
||||
assertFalse("License should not be valid for maxNodes = " + (featureAttributes.maxNodes + 1), esLicenseManager.hasLicenseForNodes(featureType, featureAttributes.maxNodes + 1));
|
||||
|
|
|
@ -6,41 +6,32 @@
|
|||
package org.elasticsearch.license.plugin;
|
||||
|
||||
import org.elasticsearch.action.ActionFuture;
|
||||
import org.elasticsearch.action.ActionModule;
|
||||
import org.elasticsearch.client.transport.TransportClient;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.common.collect.ImmutableSet;
|
||||
import org.elasticsearch.common.component.LifecycleComponent;
|
||||
import org.elasticsearch.common.inject.Injector;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.license.TestUtils;
|
||||
import org.elasticsearch.license.core.ESLicenses;
|
||||
import org.elasticsearch.license.core.LicenseBuilders;
|
||||
import org.elasticsearch.license.core.LicenseUtils;
|
||||
import org.elasticsearch.license.licensor.tools.KeyPairGeneratorTool;
|
||||
import org.elasticsearch.license.plugin.action.get.GetLicenseAction;
|
||||
import org.elasticsearch.license.plugin.action.delete.DeleteLicenseAction;
|
||||
import org.elasticsearch.license.plugin.action.delete.DeleteLicenseRequest;
|
||||
import org.elasticsearch.license.plugin.action.delete.DeleteLicenseResponse;
|
||||
import org.elasticsearch.license.plugin.action.delete.TransportDeleteLicenseAction;
|
||||
import org.elasticsearch.license.plugin.action.get.GetLicenseRequest;
|
||||
import org.elasticsearch.license.plugin.action.get.GetLicenseResponse;
|
||||
import org.elasticsearch.license.plugin.action.get.TransportGetLicenseAction;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseAction;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseRequest;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseResponse;
|
||||
import org.elasticsearch.license.plugin.action.put.TransportPutLicenseAction;
|
||||
import org.elasticsearch.license.plugin.core.LicensesMetaData;
|
||||
import org.elasticsearch.license.plugin.rest.RestGetLicenseAction;
|
||||
import org.elasticsearch.license.plugin.rest.RestPutLicenseAction;
|
||||
import org.elasticsearch.license.plugin.core.LicensesService;
|
||||
import org.elasticsearch.plugins.AbstractPlugin;
|
||||
import org.elasticsearch.rest.RestModule;
|
||||
import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
||||
import org.elasticsearch.test.InternalTestCluster;
|
||||
import org.junit.After;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Paths;
|
||||
import java.text.ParseException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
@ -55,7 +46,6 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
|||
@ClusterScope(scope = SUITE, numDataNodes = 10)
|
||||
public class LicenseTransportTests extends ElasticsearchIntegrationTest {
|
||||
|
||||
|
||||
private static String pubKeyPath = null;
|
||||
private static String priKeyPath = null;
|
||||
|
||||
|
@ -68,33 +58,29 @@ public class LicenseTransportTests extends ElasticsearchIntegrationTest {
|
|||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void setup() throws IOException {
|
||||
|
||||
// Generate temp KeyPair spec
|
||||
File privateKeyFile = File.createTempFile("privateKey", ".key");
|
||||
File publicKeyFile = File.createTempFile("publicKey", ".key");
|
||||
LicenseTransportTests.pubKeyPath = publicKeyFile.getAbsolutePath();
|
||||
LicenseTransportTests.priKeyPath = privateKeyFile.getAbsolutePath();
|
||||
assert privateKeyFile.delete();
|
||||
assert publicKeyFile.delete();
|
||||
|
||||
// Generate keyPair
|
||||
String[] args = new String[4];
|
||||
args[0] = "--publicKeyPath";
|
||||
args[1] = LicenseTransportTests.pubKeyPath;
|
||||
args[2] = "--privateKeyPath";
|
||||
args[3] = LicenseTransportTests.priKeyPath;
|
||||
KeyPairGeneratorTool.main(args);
|
||||
public static void setup() throws IOException, URISyntaxException {
|
||||
priKeyPath = Paths.get(LicenseTransportTests.class.getResource("/org.elasticsearch.license.plugin/test_pri.key").toURI()).toAbsolutePath().toString();
|
||||
pubKeyPath = Paths.get(LicenseTransportTests.class.getResource("/org.elasticsearch.license.plugin/test_pub.key").toURI()).toAbsolutePath().toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* - add more delete tests
|
||||
* - add put invalid licenses tests
|
||||
* - add multiple licenses of the same feature tests
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testEmptyGetLicense() throws Exception {
|
||||
final ActionFuture<DeleteLicenseResponse> deleteFuture = licenseDeleteAction().execute(new DeleteLicenseRequest("marvel", "shield"));
|
||||
final DeleteLicenseResponse deleteLicenseResponse = deleteFuture.get();
|
||||
assertTrue(deleteLicenseResponse.isAcknowledged());
|
||||
|
||||
final ActionFuture<GetLicenseResponse> getLicenseFuture = licenseGetAction().execute(new GetLicenseRequest());
|
||||
|
||||
final GetLicenseResponse getLicenseResponse = getLicenseFuture.get();
|
||||
|
||||
//TODO
|
||||
//assertThat(getLicenseResponse.licenses(), nullValue());
|
||||
assertThat("expected 0 licenses; but got: " + getLicenseResponse.licenses(), getLicenseResponse.licenses().licenses().size(), equalTo(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -104,25 +90,14 @@ public class LicenseTransportTests extends ElasticsearchIntegrationTest {
|
|||
TestUtils.FeatureAttributes featureAttributes =
|
||||
new TestUtils.FeatureAttributes("shield", "subscription", "platinum", "foo bar Inc.", "elasticsearch", 2, "2014-12-13", "2015-12-13");
|
||||
map.put(ESLicenses.FeatureType.SHIELD, featureAttributes);
|
||||
|
||||
String licenseString = TestUtils.generateESLicenses(map);
|
||||
|
||||
|
||||
String[] args = new String[6];
|
||||
args[0] = "--license";
|
||||
args[1] = licenseString;
|
||||
args[2] = "--publicKeyPath";
|
||||
args[3] = pubKeyPath;
|
||||
args[4] = "--privateKeyPath";
|
||||
args[5] = priKeyPath;
|
||||
|
||||
String licenseOutput = TestUtils.runLicenseGenerationTool(args);
|
||||
String licenseOutput = TestUtils.runLicenseGenerationTool(licenseString, pubKeyPath, priKeyPath);
|
||||
|
||||
PutLicenseRequest putLicenseRequest = new PutLicenseRequest();
|
||||
//putLicenseRequest.license(licenseString);
|
||||
final ESLicenses putLicenses = LicenseUtils.readLicensesFromString(licenseOutput);
|
||||
putLicenseRequest.license(putLicenses);
|
||||
LicenseUtils.printLicense(putLicenses);
|
||||
//LicenseUtils.printLicense(putLicenses);
|
||||
ensureGreen();
|
||||
|
||||
final ActionFuture<PutLicenseResponse> putLicenseFuture = licensePutAction().execute(putLicenseRequest);
|
||||
|
@ -131,13 +106,22 @@ public class LicenseTransportTests extends ElasticsearchIntegrationTest {
|
|||
|
||||
assertThat(putLicenseResponse.isAcknowledged(), equalTo(true));
|
||||
|
||||
final ActionFuture<GetLicenseResponse> getLicenseFuture = licenseGetAction().execute(new GetLicenseRequest());
|
||||
ActionFuture<GetLicenseResponse> getLicenseFuture = licenseGetAction().execute(new GetLicenseRequest());
|
||||
|
||||
final GetLicenseResponse getLicenseResponse = getLicenseFuture.get();
|
||||
GetLicenseResponse getLicenseResponse = getLicenseFuture.get();
|
||||
|
||||
assertThat(getLicenseResponse.licenses(), notNullValue());
|
||||
|
||||
LicenseUtils.printLicense(getLicenseResponse.licenses());
|
||||
//LicenseUtils.printLicense(getLicenseResponse.licenses());
|
||||
assertTrue(isSame(putLicenses, getLicenseResponse.licenses()));
|
||||
|
||||
|
||||
final ActionFuture<DeleteLicenseResponse> deleteFuture = licenseDeleteAction().execute(new DeleteLicenseRequest("marvel", "shield"));
|
||||
final DeleteLicenseResponse deleteLicenseResponse = deleteFuture.get();
|
||||
assertTrue(deleteLicenseResponse.isAcknowledged());
|
||||
|
||||
getLicenseResponse = licenseGetAction().execute(new GetLicenseRequest()).get();
|
||||
assertTrue(isSame(getLicenseResponse.licenses(), LicenseBuilders.licensesBuilder().build()));
|
||||
}
|
||||
|
||||
public TransportGetLicenseAction licenseGetAction() {
|
||||
|
@ -149,4 +133,42 @@ public class LicenseTransportTests extends ElasticsearchIntegrationTest {
|
|||
final InternalTestCluster clients = internalCluster();
|
||||
return clients.getInstance(TransportPutLicenseAction.class);
|
||||
}
|
||||
|
||||
public TransportDeleteLicenseAction licenseDeleteAction() {
|
||||
final InternalTestCluster clients = internalCluster();
|
||||
return clients.getInstance(TransportDeleteLicenseAction.class);
|
||||
}
|
||||
|
||||
|
||||
//TODO: convert to asserts
|
||||
public static boolean isSame(ESLicenses firstLicenses, ESLicenses secondLicenses) {
|
||||
|
||||
// we do the build to make sure we weed out any expired licenses
|
||||
final ESLicenses licenses1 = LicenseBuilders.licensesBuilder().licenses(firstLicenses).build();
|
||||
final ESLicenses licenses2 = LicenseBuilders.licensesBuilder().licenses(secondLicenses).build();
|
||||
|
||||
// check if the effective licenses have the same feature set
|
||||
if (!licenses1.features().equals(licenses2.features())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// for every feature license, check if all the attributes are the same
|
||||
for (ESLicenses.FeatureType featureType : licenses1.features()) {
|
||||
ESLicenses.ESLicense license1 = licenses1.get(featureType);
|
||||
ESLicenses.ESLicense license2 = licenses2.get(featureType);
|
||||
|
||||
if (!license1.uid().equals(license2.uid())
|
||||
|| !license1.feature().string().equals(license2.feature().string())
|
||||
|| !license1.subscriptionType().string().equals(license2.subscriptionType().string())
|
||||
|| !license1.type().string().equals(license2.type().string())
|
||||
|| !license1.issuedTo().equals(license2.issuedTo())
|
||||
|| !license1.signature().equals(license2.signature())
|
||||
|| license1.expiryDate() != license2.expiryDate()
|
||||
|| license1.issueDate() != license2.issueDate()
|
||||
|| license1.maxNodes() != license2.maxNodes()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue