major refactor: make ESLicense more consistent; restructure ESLicenseManager

Original commit: elastic/x-pack-elasticsearch@cb60bfb539
This commit is contained in:
Areek Zillur 2014-10-21 23:05:29 -04:00
parent b9d92bae5a
commit e59cf4538a
33 changed files with 1035 additions and 1286 deletions

View File

@ -0,0 +1,390 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.license.core;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.*;
import java.io.IOException;
import java.util.*;
public class ESLicense implements Comparable<ESLicense> {
private final String uid;
private final String issuer;
private final String issuedTo;
private final long issueDate;
private final Type type;
private final SubscriptionType subscriptionType;
private final String feature;
private final String signature;
private final long expiryDate;
private final int maxNodes;
private ESLicense(String uid, String issuer, String issuedTo, long issueDate, Type type,
SubscriptionType subscriptionType, String feature, String signature, long expiryDate, int maxNodes) {
this.uid = uid;
this.issuer = issuer;
this.issuedTo = issuedTo;
this.issueDate = issueDate;
this.type = type;
this.subscriptionType = subscriptionType;
this.feature = feature;
this.signature = signature;
this.expiryDate = expiryDate;
this.maxNodes = maxNodes;
}
/**
* @return a unique identifier for a license (currently just a UUID)
*/
public String uid() {
return uid;
}
/**
* @return type of the license [trial, subscription, internal]
*/
public Type type() {
return type;
}
/**
* @return subscription type of the license [none, silver, gold, platinum]
*/
public SubscriptionType subscriptionType() {
return subscriptionType;
}
/**
* @return the issueDate in milliseconds
*/
public long issueDate() {
return issueDate;
}
/**
* @return the featureType for the license [shield, marvel]
*/
public String feature() {
return feature;
}
/**
* @return the expiry date in milliseconds
*/
public long expiryDate() {
return expiryDate;
}
/**
* @return the maximum number of nodes this license has been issued for
*/
public int maxNodes() {
return maxNodes;
}
/**
* @return a string representing the entity this licenses has been issued to
*/
public String issuedTo() {
return issuedTo;
}
/**
* @return a string representing the entity responsible for issuing this license (internal)
*/
public String issuer() {
return issuer;
}
/**
* @return a string representing the signature of the license used for license verification
*/
public String signature() {
return signature;
}
@Override
public int compareTo(ESLicense o) {
return Long.compare(expiryDate, o.expiryDate);
}
/**
* Enum for License Type
*/
public enum Type {
TRIAL("trial"),
SUBSCRIPTION("subscription"),
INTERNAL("internal");
private final String name;
private Type(String name) {
this.name = name;
}
public String string() {
return name;
}
public static Type fromString(String type) {
if (type.equalsIgnoreCase(TRIAL.string())) {
return TRIAL;
} else if (type.equalsIgnoreCase(SUBSCRIPTION.string())) {
return SUBSCRIPTION;
} else if (type.equalsIgnoreCase(INTERNAL.string())) {
return INTERNAL;
} else {
throw new IllegalArgumentException("Invalid Type=" + type);
}
}
}
/**
* Enum for License Subscription Type
*/
public enum SubscriptionType {
NONE("none"),
DEVELOPMENT("development"),
SILVER("silver"),
GOLD("gold"),
PLATINUM("platinum");
public static SubscriptionType DEFAULT = NONE;
private final String name;
private SubscriptionType(String name) {
this.name = name;
}
public String string() {
return name;
}
public static SubscriptionType fromString(String subscriptionType) {
if (subscriptionType.equalsIgnoreCase(NONE.string())) {
return NONE;
} else if (subscriptionType.equalsIgnoreCase(DEVELOPMENT.string())) {
return DEVELOPMENT;
} else if (subscriptionType.equalsIgnoreCase(SILVER.string())) {
return SILVER;
} else if (subscriptionType.equalsIgnoreCase(GOLD.string())) {
return GOLD;
} else if (subscriptionType.equalsIgnoreCase(PLATINUM.string())) {
return PLATINUM;
} else {
throw new IllegalArgumentException("Invalid SubscriptionType=" + subscriptionType);
}
}
}
public static Builder builder() {
return new Builder();
}
public static class Builder {
private String uid;
private String issuer;
private String issuedTo;
private long issueDate = -1;
private Type type;
private SubscriptionType subscriptionType = SubscriptionType.DEFAULT;
private String feature;
private String signature;
private long expiryDate = -1;
private int maxNodes;
public Builder uid(String uid) {
this.uid = uid;
return this;
}
public Builder issuer(String issuer) {
this.issuer = issuer;
return this;
}
public Builder issuedTo(String issuedTo) {
this.issuedTo = issuedTo;
return this;
}
public Builder issueDate(long issueDate) {
this.issueDate = issueDate;
return this;
}
public Builder type(Type type) {
this.type = type;
return this;
}
public Builder subscriptionType(SubscriptionType subscriptionType) {
this.subscriptionType = subscriptionType;
return this;
}
public Builder feature(String feature) {
this.feature = feature;
return this;
}
public Builder expiryDate(long expiryDate) {
this.expiryDate = expiryDate;
return this;
}
public Builder maxNodes(int maxNodes) {
this.maxNodes = maxNodes;
return this;
}
public Builder signature(String signature) {
if (signature != null) {
this.signature = signature;
}
return this;
}
public Builder fromLicense(ESLicense license) {
return uid(license.uid())
.issuedTo(license.issuedTo())
.issueDate(license.issueDate())
.type(license.type())
.subscriptionType(license.subscriptionType())
.feature(license.feature())
.maxNodes(license.maxNodes())
.expiryDate(license.expiryDate())
.issuer(license.issuer())
.signature(license.signature());
}
public ESLicense build() {
verify(false);
return new ESLicense(uid, issuer, issuedTo, issueDate, type,
subscriptionType, feature, signature, expiryDate, maxNodes);
}
public ESLicense buildInternal() {
verify(true);
return new ESLicense(uid, issuer, issuedTo, issueDate, type,
subscriptionType, feature, signature, expiryDate, maxNodes);
}
private void verify(boolean internal) {
String msg = null;
if (issuer == null) {
msg = "issuer can not be null";
} else if (issuedTo == null) {
msg = "issuedTo can not be null";
} else if (issueDate == -1) {
msg = "issueDate has to be set";
} else if (type == null) {
msg = "type can not be null";
} else if (subscriptionType == null) {
msg = "subscriptionType can not be null";
} else if (uid == null) {
msg = "uid can not be null";
} else if (feature == null) {
msg = "at least one feature has to be enabled";
} else if (internal && signature == null) {
msg = "signature can not be null";
} else if (maxNodes == -1) {
msg = "maxNodes has to be set";
} else if (expiryDate == -1) {
msg = "expiryDate has to be set";
}
if (msg != null) {
throw new IllegalStateException(msg);
}
}
}
final static class Fields {
static final String UID = "uid";
static final String TYPE = "type";
static final String SUBSCRIPTION_TYPE = "subscription_type";
static final String ISSUE_DATE = "issue_date";
static final String FEATURE = "feature";
static final String EXPIRY_DATE = "expiry_date";
static final String MAX_NODES = "max_nodes";
static final String ISSUED_TO = "issued_to";
static final String ISSUER = "issuer";
static final String SIGNATURE = "signature";
}
static void toXContent(ESLicense license, XContentBuilder builder) throws IOException {
builder.startObject();
builder.field(Fields.UID, license.uid);
builder.field(Fields.TYPE, license.type.string());
builder.field(Fields.SUBSCRIPTION_TYPE, license.subscriptionType.string());
builder.field(Fields.ISSUE_DATE, license.issueDate);
builder.field(Fields.FEATURE, license.feature);
builder.field(Fields.EXPIRY_DATE, license.expiryDate);
builder.field(Fields.MAX_NODES, license.maxNodes);
builder.field(Fields.ISSUED_TO, license.issuedTo);
builder.field(Fields.ISSUER, license.issuer);
builder.field(Fields.SIGNATURE, license.signature);
builder.endObject();
}
static ESLicense fromXContent(Map<String, Object> map) throws IOException {
return new Builder()
.uid((String) map.get(Fields.UID))
.type(Type.fromString((String) map.get(Fields.TYPE)))
.subscriptionType(SubscriptionType.fromString((String) map.get(Fields.SUBSCRIPTION_TYPE)))
.feature((String) map.get(Fields.FEATURE))
.maxNodes((int) map.get(Fields.MAX_NODES))
.issuedTo((String) map.get(Fields.ISSUED_TO))
.signature((String) map.get(Fields.SIGNATURE))
.issueDate((long) map.get(Fields.ISSUE_DATE))
.expiryDate((long) map.get(Fields.EXPIRY_DATE))
.issuer((String) map.get(Fields.ISSUER))
.build();
}
static ESLicense readFrom(StreamInput in) throws IOException {
Map<String, Object> licenseMap = in.readMap();
return builder()
.uid((String) licenseMap.get(Fields.UID))
.type(Type.fromString((String) licenseMap.get(Fields.TYPE)))
.subscriptionType(SubscriptionType.fromString((String) licenseMap.get(Fields.SUBSCRIPTION_TYPE)))
.issueDate((long) licenseMap.get(Fields.ISSUE_DATE))
.feature((String) licenseMap.get(Fields.FEATURE))
.expiryDate((long) licenseMap.get(Fields.EXPIRY_DATE))
.maxNodes((int) licenseMap.get(Fields.MAX_NODES))
.issuedTo((String) licenseMap.get(Fields.ISSUED_TO))
.signature((String) licenseMap.get(Fields.SIGNATURE))
.issuer((String) licenseMap.get(Fields.ISSUER))
.build();
}
static void writeTo(ESLicense esLicense, StreamOutput out) throws IOException {
Map<String, Object> licenseMap = new HashMap<>();
licenseMap.put(Fields.UID, esLicense.uid);
licenseMap.put(Fields.TYPE, esLicense.type.string());
licenseMap.put(Fields.SUBSCRIPTION_TYPE, esLicense.subscriptionType.string());
licenseMap.put(Fields.ISSUE_DATE, esLicense.issueDate);
licenseMap.put(Fields.FEATURE, esLicense.feature);
licenseMap.put(Fields.EXPIRY_DATE, esLicense.expiryDate);
licenseMap.put(Fields.MAX_NODES, esLicense.maxNodes);
licenseMap.put(Fields.ISSUED_TO, esLicense.issuedTo);
licenseMap.put(Fields.ISSUER, esLicense.issuer);
licenseMap.put(Fields.SIGNATURE, esLicense.signature);
out.writeMap(licenseMap);
}
}

View File

@ -5,159 +5,64 @@
*/
package org.elasticsearch.license.core;
import java.util.Collection;
import java.util.Set;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.*;
/**
* Interface for ESLicenses, ESLicense
* and enums for Type, SubscriptionType and FeatureType.
* <p/>
* This is the main contract between the licensor and the license manager
*/
public interface ESLicenses extends Iterable<ESLicenses.ESLicense> {
/**
* @return list of licenses contained under this instance
*/
public Collection<ESLicense> licenses();
/**
* @return Set of features for which there exists an underlying license
*/
public Set<String> features();
/**
* @return a license for a code>featureType<</code>
* @param feature
*/
public ESLicense get(String feature);
/**
* Enum for License Type
*/
public enum Type {
TRIAL("trial"),
SUBSCRIPTION("subscription"),
INTERNAL("internal");
private final String name;
private Type(String name) {
this.name = name;
}
public String string() {
return name;
}
public static Type fromString(String type) {
if (type.equalsIgnoreCase(TRIAL.string())) {
return TRIAL;
} else if (type.equalsIgnoreCase(SUBSCRIPTION.string())) {
return SUBSCRIPTION;
} else if (type.equalsIgnoreCase(INTERNAL.string())) {
return INTERNAL;
} else {
throw new IllegalArgumentException("Invalid Type=" + type);
}
public class ESLicenses {
public static void toXContent(Collection<ESLicense> licenses, XContentBuilder builder) throws IOException {
builder.startObject();
builder.startArray("licenses");
for (ESLicense license : licenses) {
ESLicense.toXContent(license, builder);
}
builder.endArray();
builder.endObject();
}
/**
* Enum for License Subscription Type
*/
public enum SubscriptionType {
NONE("none"),
DEVELOPMENT("development"),
SILVER("silver"),
GOLD("gold"),
PLATINUM("platinum");
public static SubscriptionType DEFAULT = NONE;
private final String name;
private SubscriptionType(String name) {
this.name = name;
}
public String string() {
return name;
}
public static SubscriptionType fromString(String subscriptionType) {
if (subscriptionType.equalsIgnoreCase(NONE.string())) {
return NONE;
} else if (subscriptionType.equalsIgnoreCase(DEVELOPMENT.string())) {
return DEVELOPMENT;
} else if (subscriptionType.equalsIgnoreCase(SILVER.string())) {
return SILVER;
} else if (subscriptionType.equalsIgnoreCase(GOLD.string())) {
return GOLD;
} else if (subscriptionType.equalsIgnoreCase(PLATINUM.string())) {
return PLATINUM;
} else {
throw new IllegalArgumentException("Invalid SubscriptionType=" + subscriptionType);
}
}
public static Set<ESLicense> fromSource(String content) throws IOException {
return fromSource(content.getBytes(Charset.forName("UTF-8")));
}
/**
* Interface representing all the license fields
*/
public interface ESLicense {
/**
* @return a unique identifier for a license (currently just a UUID)
*/
public String uid();
/**
* @return type of the license [trial, subscription, internal]
*/
public Type type();
/**
* @return subscription type of the license [none, silver, gold, platinum]
*/
public SubscriptionType subscriptionType();
/**
* @return the issueDate in milliseconds
*/
public long issueDate();
/**
* @return the featureType for the license [shield, marvel]
*/
public String feature();
/**
* @return the expiry date in milliseconds
*/
public long expiryDate();
/**
* @return the maximum number of nodes this license has been issued for
*/
public int maxNodes();
/**
* @return a string representing the entity this licenses has been issued to
*/
public String issuedTo();
/**
* @return a string representing the entity responsible for issuing this license (internal)
*/
public String issuer();
/**
* @return a string representing the signature of the license used for license verification
*/
public String signature();
public static Set<ESLicense> fromSource(byte[] bytes) throws IOException {
return fromXContent(XContentFactory.xContent(bytes).createParser(bytes));
}
private static Set<ESLicense> fromXContent(XContentParser parser) throws IOException {
Set<ESLicense> esLicenses = new HashSet<>();
final Map<String, Object> licensesMap = parser.mapAndClose();
final List<Map<String, Object>> licenseMaps = (ArrayList<Map<String, Object>>)licensesMap.get("licenses");
for (Map<String, Object> licenseMap : licenseMaps) {
final ESLicense esLicense = ESLicense.fromXContent(licenseMap);
esLicenses.add(esLicense);
}
return esLicenses;
}
public static Set<ESLicense> readFrom(StreamInput in) throws IOException {
int size = in.readVInt();
Set<ESLicense> esLicenses = new HashSet<>(size);
for (int i = 0; i < size; i++) {
esLicenses.add(ESLicense.readFrom(in));
}
return esLicenses;
}
public static void writeTo(Set<ESLicense> esLicenses, StreamOutput out) throws IOException {
out.writeVInt(esLicenses.size());
for (ESLicense license : esLicenses) {
ESLicense.writeTo(license, out);
}
}
}

View File

@ -1,316 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.license.core;
import java.util.*;
import static org.elasticsearch.license.core.ESLicenses.*;
public class LicenseBuilders {
/**
* @return a licenses builder instance to build a {@link org.elasticsearch.license.core.ESLicenses}
*/
public static LicensesBuilder licensesBuilder() {
return new LicensesBuilder();
}
/**
* @return a license builder instance to build a {@link org.elasticsearch.license.core.ESLicenses.ESLicense}
* if internal is set to true, then license fields (which are internal) are required to be set
*/
public static LicenseBuilder licenseBuilder(boolean internal) {
return new LicenseBuilder(internal);
}
/**
* Merges all the sub-licenses of the provided licenses parameters by
* longest expiry date for each license feature and merges out any
* sub-licenses that have already expired
*
* @return a merged <code>ESLicenses</code> instance from <code>licenses</code>
* and <code>mergedLicenses</code>
*/
public static ESLicenses merge(ESLicenses licenses, ESLicenses mergeLicenses) {
if (licenses == null && mergeLicenses == null) {
throw new IllegalArgumentException("both licenses can not be null");
} else if (licenses == null) {
return mergeLicenses;
} else if (mergeLicenses == null) {
return licenses;
} else {
return licensesBuilder()
.licenses(licenses)
.licenses(mergeLicenses)
.build();
}
}
public static ESLicenses removeFeatures(ESLicenses licenses, Set<String> featureTypesToDelete) {
final LicensesBuilder licensesBuilder = licensesBuilder();
for (ESLicense license : licenses) {
if (!featureTypesToDelete.contains(license.feature())) {
licensesBuilder.licenseAsIs(license);
}
}
return licensesBuilder.build();
}
public static class LicensesBuilder {
private Map<String, ESLicense> licenseMap = new HashMap<>();
public LicensesBuilder() {
}
public LicensesBuilder license(LicenseBuilder builder) {
return license(builder.build());
}
public LicensesBuilder license(ESLicense license) {
putIfAppropriate(license);
return this;
}
public LicensesBuilder licenseAsIs(ESLicense license) {
licenseMap.put(license.feature(), license);
return this;
}
public LicensesBuilder licenses(Collection<ESLicense> licenses) {
for (ESLicense esLicense : licenses) {
license(esLicense);
}
return this;
}
public LicensesBuilder licenses(ESLicenses licenses) {
return licenses(licenses.licenses());
}
public ESLicenses build() {
return new ESLicenses() {
@Override
public Collection<ESLicense> licenses() {
return licenseMap.values();
}
@Override
public Set<String> features() {
return licenseMap.keySet();
}
@Override
public ESLicense get(String feature) {
return licenseMap.get(feature);
}
@Override
public Iterator<ESLicense> iterator() {
return licenseMap.values().iterator();
}
};
}
/**
* Add a {@link org.elasticsearch.license.core.ESLicenses.ESLicense} to
* {@link org.elasticsearch.license.core.ESLicenses} only if
* there exists no License for the feature that has a longer expiry date
* and if the license in question has an <code>expiryDate</code> that has
* not expired yet
*
* @param license license in question
*/
private void putIfAppropriate(ESLicense license) {
final String featureType = license.feature();
if (licenseMap.containsKey(featureType)) {
final ESLicense previousLicense = licenseMap.get(featureType);
if (license.expiryDate() > previousLicense.expiryDate()) {
licenseMap.put(featureType, license);
}
} else if (license.expiryDate() > System.currentTimeMillis()) {
licenseMap.put(featureType, license);
}
}
}
public static class LicenseBuilder {
private String uid;
private String issuer;
private String issuedTo;
private long issueDate = -1;
private Type type;
private SubscriptionType subscriptionType = SubscriptionType.DEFAULT;
private String feature;
private String signature;
private long expiryDate = -1;
private int maxNodes;
private final boolean internal;
public LicenseBuilder(boolean internal) {
this.internal = internal;
}
public LicenseBuilder uid(String uid) {
this.uid = uid;
return this;
}
public LicenseBuilder issuer(String issuer) {
this.issuer = issuer;
return this;
}
public LicenseBuilder issuedTo(String issuedTo) {
this.issuedTo = issuedTo;
return this;
}
public LicenseBuilder issueDate(long issueDate) {
this.issueDate = issueDate;
return this;
}
public LicenseBuilder type(Type type) {
this.type = type;
return this;
}
public LicenseBuilder subscriptionType(SubscriptionType subscriptionType) {
this.subscriptionType = subscriptionType;
return this;
}
public LicenseBuilder feature(String feature) {
this.feature = feature;
return this;
}
public LicenseBuilder expiryDate(long expiryDate) {
this.expiryDate = expiryDate;
return this;
}
public LicenseBuilder maxNodes(int maxNodes) {
this.maxNodes = maxNodes;
return this;
}
public LicenseBuilder signature(String signature) {
if (signature != null) {
this.signature = signature;
}
return this;
}
public LicenseBuilder fromLicense(ESLicense license) {
LicenseBuilder builder = this.uid(license.uid())
.issuedTo(license.issuedTo())
.issueDate(license.issueDate())
.type(license.type())
.subscriptionType(license.subscriptionType())
.feature(license.feature())
.maxNodes(license.maxNodes())
.expiryDate(license.expiryDate());
return (internal)
? builder.issuer(license.issuer()).signature(license.signature())
: builder;
}
public ESLicense build() {
if (uid == null) {
uid = UUID.randomUUID().toString();
}
verify();
return new ESLicense() {
@Override
public String uid() {
return uid;
}
@Override
public Type type() {
return type;
}
@Override
public SubscriptionType subscriptionType() {
return subscriptionType;
}
@Override
public long issueDate() {
return issueDate;
}
@Override
public String feature() {
return feature;
}
@Override
public long expiryDate() {
return expiryDate;
}
@Override
public int maxNodes() {
return maxNodes;
}
@Override
public String issuer() {
return issuer;
}
@Override
public String issuedTo() {
return issuedTo;
}
@Override
public String signature() {
return signature;
}
};
}
private void verify() {
String msg = null;
if (internal && issuer == null) {
msg = "issuer can not be null";
} else if (issuedTo == null) {
msg = "issuedTo can not be null";
} else if (issueDate == -1) {
msg = "issueDate has to be set";
} else if (type == null) {
msg = "type can not be null";
} else if (subscriptionType == null) {
msg = "subscriptionType can not be null";
} else if (uid == null) {
msg = "uid can not be null";
} else if (feature == null) {
msg = "at least one feature has to be enabled";
} else if (internal && signature == null) {
msg = "signature can not be null";
} else if (maxNodes == -1) {
msg = "maxNodes has to be set";
} else if (expiryDate == -1) {
msg = "expiryDate has to be set";
}
if (msg != null) {
throw new IllegalStateException(msg);
}
}
}
}

View File

@ -1,183 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.license.core;
import org.apache.commons.io.FileUtils;
import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;
import java.io.*;
import java.text.ParseException;
import java.util.HashSet;
import java.util.Set;
public class LicenseUtils {
public static void dumpLicenseAsJson(ESLicenses esLicenses, OutputStream out) throws IOException {
JsonGenerator generator = new JsonFactory().createJsonGenerator(out);
//generator.useDefaultPrettyPrinter();
generator.writeStartObject();
{
generator.writeArrayFieldStart("licenses");
{
for (ESLicenses.ESLicense esLicense : esLicenses) {
generator.writeStartObject();
{
generator.writeStringField("uid", esLicense.uid());
generator.writeStringField("type", esLicense.type().string());
generator.writeStringField("subscription_type", esLicense.subscriptionType().string());
generator.writeStringField("issued_to", esLicense.issuedTo());
generator.writeStringField("issue_date", DateUtils.dateStringFromLongDate(esLicense.issueDate()));
generator.writeStringField("expiry_date", DateUtils.dateStringFromLongDate(esLicense.expiryDate()));
generator.writeStringField("feature", esLicense.feature());
generator.writeNumberField("max_nodes", esLicense.maxNodes());
generator.writeStringField("signature", esLicense.signature());
}
generator.writeEndObject();
}
}
generator.writeEndArray();
}
generator.writeEndObject();
generator.flush();
}
public static Set<ESLicenses> readLicensesFromFiles(Set<File> licenseFiles) throws IOException {
Set<ESLicenses> esLicensesSet = new HashSet<>();
for (File licenseFile : licenseFiles) {
esLicensesSet.add(LicenseUtils.readLicenseFile(licenseFile));
}
return esLicensesSet;
}
public static Set<ESLicenses> readLicensesFromDirectory(File licenseDirectory) throws IOException {
Set<ESLicenses> esLicensesSet = new HashSet<>();
if (!licenseDirectory.exists()) {
throw new IllegalArgumentException(licenseDirectory.getAbsolutePath() + " does not exist!");
}
if (licenseDirectory.isDirectory()) {
for (File licenseFile : FileUtils.listFiles(licenseDirectory, new String[]{"json"}, false)) {
esLicensesSet.add(readLicenseFile(licenseFile));
}
} else if (licenseDirectory.isFile()) {
esLicensesSet.add(readLicenseFile(licenseDirectory));
} else {
throw new IllegalArgumentException(licenseDirectory.getAbsolutePath() + "is not a file or a directory");
}
return esLicensesSet;
}
public static ESLicenses readLicenseFile(File licenseFile) throws IOException {
try (FileInputStream fileInputStream = new FileInputStream(licenseFile)) {
return readLicenseFromInputStream(fileInputStream);
}
}
public static ESLicenses readLicenseFromInputStream(InputStream inputStream) throws IOException {
JsonNode jsonNode = new ObjectMapper().readTree(inputStream);
return extractLicenseFromJson(jsonNode);
}
public static ESLicenses readLicensesFromString(String licensesString) throws IOException {
JsonNode jsonNode = new ObjectMapper().readTree(licensesString);
return extractLicenseFromJson(jsonNode);
}
private static ESLicenses extractLicenseFromJson(final JsonNode jsonNode) {
final LicenseBuilders.LicensesBuilder licensesBuilder = LicenseBuilders.licensesBuilder();
JsonNode licensesNode = jsonNode.get("licenses");
if (licensesNode.isArray()) {
for (JsonNode licenseNode : licensesNode) {
licensesBuilder.license(LicenseBuilders.licenseBuilder(false)
.uid(getValueAsString(licenseNode, "uid", true))
.issuedTo(getValueAsString(licenseNode, "issued_to"))
.issuer(getValueAsString(licenseNode, "issuer", true))
.issueDate(getValueAsDate(licenseNode, "issue_date"))
.type(ESLicenses.Type.fromString(getValueAsString(licenseNode, "type")))
.subscriptionType(ESLicenses.SubscriptionType.fromString(getValueAsString(licenseNode, "subscription_type")))
.feature(getValueAsString(licenseNode, "feature"))
.expiryDate(getValueAsExpiryDate(licenseNode, "expiry_date"))
.maxNodes(getValueAsInt(licenseNode, "max_nodes"))
.signature(getValueAsString(licenseNode, "signature", true))
.build());
}
} else {
throw new IllegalStateException("'licenses' field is not an array");
}
return licensesBuilder.build();
}
private static int getValueAsInt(final JsonNode jsonNode, String field) {
JsonNode node = getFieldNode(jsonNode, field, false);
assert node.isNumber();
return node.getValueAsInt();
}
private static String getValueAsString(final JsonNode jsonNode, String field) {
return getValueAsString(jsonNode, field, false);
}
private static String getValueAsString(final JsonNode jsonNode, String field, boolean optional) {
JsonNode node = getFieldNode(jsonNode, field, optional);
assert node != null || optional;
if (node == null) {
return null;
}
assert !node.isObject();
return node.getTextValue();
}
private static long getValueAsDate(final JsonNode jsonNode, String field) {
JsonNode node = getFieldNode(jsonNode, field, false);
assert !node.isObject();
final String value = node.getTextValue();
try {
return DateUtils.longFromDateString(value);
} catch (ParseException e) {
throw new IllegalArgumentException(e);
}
}
private static long getValueAsExpiryDate(final JsonNode jsonNode, String field) {
long actualDate = getValueAsDate(jsonNode, field);
return DateUtils.longExpiryDateFromDate(actualDate);
}
private static JsonNode getFieldNode(final JsonNode jsonNode, String field, boolean optional) {
JsonNode node = jsonNode.get(field);
if (node == null && !optional) {
throw new IllegalArgumentException("field ['" + field + "'] is missing");
}
return node;
}
public static void printLicense(ESLicenses licenses) {
for (ESLicenses.ESLicense license : licenses) {
System.out.println("===");
printValue(" uid", license.uid());
printValue(" type", license.type().string());
printValue(" subscription_type", license.subscriptionType().string());
printValue(" issueDate", DateUtils.dateStringFromLongDate(license.issueDate()));
printValue(" issuedTo", license.issuedTo());
printValue(" feature", license.feature());
printValue(" maxNodes", license.maxNodes());
printValue(" expiryDate", DateUtils.dateStringFromLongDate(license.expiryDate()));
printValue(" signature", license.signature());
System.out.println("===");
}
}
private static void printValue(String name, Object value) {
System.out.println(name + " : " + value);
}
}

View File

@ -6,7 +6,6 @@
package org.elasticsearch.license.licensor;
import net.nicholaswilliams.java.licensing.License;
import net.nicholaswilliams.java.licensing.SignedLicense;
import net.nicholaswilliams.java.licensing.encryption.Hasher;
import net.nicholaswilliams.java.licensing.encryption.PasswordProvider;
import net.nicholaswilliams.java.licensing.encryption.PrivateKeyDataProvider;
@ -14,8 +13,9 @@ import net.nicholaswilliams.java.licensing.exception.KeyNotFoundException;
import net.nicholaswilliams.java.licensing.licensor.LicenseCreator;
import net.nicholaswilliams.java.licensing.licensor.LicenseCreatorProperties;
import org.apache.commons.codec.binary.Base64;
import org.elasticsearch.license.core.ESLicenses;
import org.elasticsearch.license.core.LicenseBuilders;
import org.elasticsearch.common.collect.ImmutableMap;
import org.elasticsearch.common.collect.ImmutableSet;
import org.elasticsearch.license.core.*;
import java.io.IOException;
import java.nio.ByteBuffer;
@ -24,8 +24,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Random;
import static org.elasticsearch.license.core.ESLicenses.ESLicense;
import java.util.Set;
public class ESLicenseSigner {
@ -69,12 +68,13 @@ public class ESLicenseSigner {
this.publicKeyPath = publicKeyPath;
}
public ESLicenses sign(ESLicenses esLicenses) throws IOException {
final LicenseBuilders.LicensesBuilder licensesBuilder = LicenseBuilders.licensesBuilder();
for (ESLicense license : esLicenses) {
licensesBuilder.license(sign(license));
public ImmutableSet<ESLicense> sign(Set<LicenseSpec> licenseSpecs) throws IOException {
final ImmutableSet.Builder<ESLicense> builder = ImmutableSet.builder();
for (LicenseSpec licenseSpec : licenseSpecs) {
builder.add(sign(licenseSpec));
}
return licensesBuilder.build();
return builder.build();
}
/**
@ -85,25 +85,24 @@ public class ESLicenseSigner {
* @return a signed ESLicense (with signature)
* @throws IOException
*/
public ESLicense sign(ESLicense esLicense) throws IOException {
public ESLicense sign(LicenseSpec licenseSpec) throws IOException {
License.Builder licenseBuilder = new License.Builder()
.withGoodBeforeDate(esLicense.expiryDate())
.withIssueDate(esLicense.issueDate())
.withProductKey(esLicense.uid())
.withHolder(esLicense.issuedTo())
.withIssuer(esLicense.issuer())
.addFeature("feature:" + esLicense.feature(), esLicense.expiryDate())
.addFeature("maxNodes:" + String.valueOf(esLicense.maxNodes()))
.addFeature("type:" + esLicense.type().string())
.addFeature("subscription_type:" + esLicense.subscriptionType().string());
.withGoodBeforeDate(licenseSpec.expiryDate)
.withIssueDate(licenseSpec.issueDate)
.withProductKey(licenseSpec.uid)
.withHolder(licenseSpec.issuedTo)
.withIssuer(licenseSpec.issuer)
.addFeature("feature:" + licenseSpec.feature, licenseSpec.expiryDate)
.addFeature("maxNodes:" + String.valueOf(licenseSpec.maxNodes))
.addFeature("type:" + licenseSpec.type.string())
.addFeature("subscription_type:" + licenseSpec.subscriptionType.string());
final License license = licenseBuilder.build();
final byte[] magic = new byte[MAGIC_LENGTH];
Random random = new Random();
random.nextBytes(magic);
//final SignedLicense signedLicense = licenseCreator.signLicense(license);
final byte[] licenseSignature = licenseCreator.signAndSerializeLicense(license);//signedLicense.getSignatureContent();
final byte[] licenseSignature = licenseCreator.signAndSerializeLicense(license);
final byte[] hash = Hasher.hash(Base64.encodeBase64String(
Files.readAllBytes(publicKeyPath))
).getBytes(Charset.forName("UTF-8"));
@ -118,6 +117,18 @@ public class ESLicenseSigner {
.put(licenseSignature);
String signature = Base64.encodeBase64String(bytes);
return LicenseBuilders.licenseBuilder(true).fromLicense(esLicense).signature(signature).build();
return ESLicense.builder()
.uid(licenseSpec.uid)
.issuedTo(licenseSpec.issuedTo)
.issueDate(licenseSpec.issueDate)
.type(licenseSpec.type)
.subscriptionType(licenseSpec.subscriptionType)
.feature(licenseSpec.feature)
.maxNodes(licenseSpec.maxNodes)
.expiryDate(licenseSpec.expiryDate)
.issuer(licenseSpec.issuer)
.signature(signature)
.build();
}
}

View File

@ -0,0 +1,149 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.license.licensor;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.license.core.DateUtils;
import java.io.IOException;
import java.nio.charset.Charset;
import java.text.ParseException;
import java.util.*;
import static org.elasticsearch.license.core.ESLicense.Type;
import static org.elasticsearch.license.core.ESLicense.SubscriptionType;
public class LicenseSpec {
final String uid;
final String issuer;
final String issuedTo;
final long issueDate;
final Type type;
final SubscriptionType subscriptionType;
final String feature;
final long expiryDate;
final int maxNodes;
private LicenseSpec(String uid, String issuer, String issuedTo, long issueDate, Type type,
SubscriptionType subscriptionType, String feature, long expiryDate,
int maxNodes) {
this.uid = uid;
this.issuer = issuer;
this.issuedTo = issuedTo;
this.issueDate = issueDate;
this.type = type;
this.subscriptionType = subscriptionType;
this.feature = feature;
this.expiryDate = expiryDate;
this.maxNodes = maxNodes;
}
public static class Builder {
private String uid;
private String issuer;
private String issuedTo;
private long issueDate = -1;
private Type type;
private SubscriptionType subscriptionType = SubscriptionType.DEFAULT;
private String feature;
private long expiryDate = -1;
private int maxNodes;
public Builder uid(String uid) {
this.uid = uid;
return this;
}
public Builder issuer(String issuer) {
this.issuer = issuer;
return this;
}
public Builder issuedTo(String issuedTo) {
this.issuedTo = issuedTo;
return this;
}
public Builder issueDate(long issueDate) {
this.issueDate = issueDate;
return this;
}
public Builder type(Type type) {
this.type = type;
return this;
}
public Builder subscriptionType(SubscriptionType subscriptionType) {
this.subscriptionType = subscriptionType;
return this;
}
public Builder feature(String feature) {
this.feature = feature;
return this;
}
public Builder expiryDate(long expiryDate) {
this.expiryDate = expiryDate;
return this;
}
public Builder maxNodes(int maxNodes) {
this.maxNodes = maxNodes;
return this;
}
public LicenseSpec build() {
if (uid == null) {
uid = UUID.randomUUID().toString();
}
return new LicenseSpec(uid, issuer, issuedTo, issueDate, type, subscriptionType,
feature ,expiryDate, maxNodes);
}
}
private static LicenseSpec fromXContent(Map<String, Object> map) throws IOException, ParseException {
Builder builder = new Builder()
.uid((String) map.get("uid"))
.type(Type.fromString((String) map.get("type")))
.subscriptionType(SubscriptionType.fromString((String) map.get("subscription_type")))
.feature((String) map.get("feature"))
.maxNodes((int) map.get("max_nodes"))
.issuedTo((String) map.get("issued_to"))
.issuer((String) map.get("issuer"));
String issueDate = (String) map.get("issue_date");
builder.issueDate(DateUtils.longFromDateString(issueDate));
String expiryDate = (String) map.get("expiry_date");
builder.expiryDate(DateUtils.longExpiryDateFromString(expiryDate));
return builder.build();
}
public static Set<LicenseSpec> fromSource(String content) throws IOException, ParseException {
return fromSource(content.getBytes(Charset.forName("UTF-8")));
}
public static Set<LicenseSpec> fromSource(byte[] bytes) throws IOException, ParseException {
return fromXContents(XContentFactory.xContent(bytes).createParser(bytes));
}
private static Set<LicenseSpec> fromXContents(XContentParser parser) throws IOException, ParseException {
Set<LicenseSpec> licenseSpecs = new HashSet<>();
final Map<String, Object> licenseSpecMap = parser.mapAndClose();
final List<Map<String, Object>> licenseSpecDefinitions = (ArrayList<Map<String, Object>>)licenseSpecMap.get("licenses");
for (Map<String, Object> licenseSpecDef : licenseSpecDefinitions) {
final LicenseSpec licenseSpec = fromXContent(licenseSpecDef);
licenseSpecs.add(licenseSpec);
}
return licenseSpecs;
}
}

View File

@ -5,46 +5,35 @@
*/
package org.elasticsearch.license.licensor.tools;
import org.elasticsearch.license.core.ESLicenses;
import org.elasticsearch.license.core.LicenseBuilders;
import org.elasticsearch.common.collect.ImmutableMap;
import org.elasticsearch.license.core.ESLicense;
import org.elasticsearch.license.manager.ESLicenseProvider;
import org.elasticsearch.license.manager.Utils;
import java.util.Map;
import java.util.Set;
/**
*/
public class FileBasedESLicenseProvider implements ESLicenseProvider {
private ESLicenses esLicenses;
private ImmutableMap<String, ESLicense> esLicenses;
public FileBasedESLicenseProvider(ESLicenses esLicenses) {
this.esLicenses = esLicenses;
}
public FileBasedESLicenseProvider(Set<ESLicenses> esLicensesSet) {
this(merge(esLicensesSet));
public FileBasedESLicenseProvider(Set<ESLicense> esLicenses) {
this.esLicenses = Utils.reduceAndMap(esLicenses);
}
@Override
public ESLicenses.ESLicense getESLicense(String feature) {
public ESLicense getESLicense(String feature) {
return esLicenses.get(feature);
}
@Override
public ESLicenses getEffectiveLicenses() {
public Map<String, ESLicense> getEffectiveLicenses() {
return esLicenses;
}
// For testing
public void setLicenses(ESLicenses esLicenses) {
this.esLicenses = esLicenses;
public void setLicenses(Set<ESLicense> esLicenses) {
this.esLicenses = Utils.reduceAndMap(esLicenses);
}
private static ESLicenses merge(Set<ESLicenses> esLicensesSet) {
ESLicenses mergedLicenses = null;
for (ESLicenses licenses : esLicensesSet) {
mergedLicenses = LicenseBuilders.merge(mergedLicenses, licenses);
}
return mergedLicenses;
}
}

View File

@ -12,7 +12,10 @@ import net.nicholaswilliams.java.licensing.exception.InappropriateKeyException;
import net.nicholaswilliams.java.licensing.exception.InappropriateKeySpecificationException;
import net.nicholaswilliams.java.licensing.exception.RSA2048NotSupportedException;
import java.io.*;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.security.KeyPair;
public class KeyPairGeneratorTool {

View File

@ -5,30 +5,40 @@
*/
package org.elasticsearch.license.licensor.tools;
import org.elasticsearch.common.collect.ImmutableSet;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.license.core.ESLicense;
import org.elasticsearch.license.core.ESLicenses;
import org.elasticsearch.license.core.LicenseUtils;
import org.elasticsearch.license.licensor.ESLicenseSigner;
import org.elasticsearch.license.licensor.LicenseSpec;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.ParseException;
import java.util.HashSet;
import java.util.Set;
public class LicenseGeneratorTool {
static class Options {
private final ESLicenses licenses;
private final Set<LicenseSpec> licenseSpecs;
private final String publicKeyFilePath;
private final String privateKeyFilePath;
Options(ESLicenses licenses, String publicKeyFilePath, String privateKeyFilePath) {
this.licenses = licenses;
Options(Set<LicenseSpec> licenseSpecs, String publicKeyFilePath, String privateKeyFilePath) {
this.licenseSpecs = licenseSpecs;
this.publicKeyFilePath = publicKeyFilePath;
this.privateKeyFilePath = privateKeyFilePath;
}
}
private static Options parse(String[] args) throws IOException {
ESLicenses licenses = null;
private static Options parse(String[] args) throws IOException, ParseException {
Set<LicenseSpec> licenseSpecs = new HashSet<>();
String privateKeyPath = null;
String publicKeyPath = null;
@ -36,19 +46,14 @@ public class LicenseGeneratorTool {
String command = args[i].trim();
switch (command) {
case "--license":
if (licenses != null) {
throw new IllegalArgumentException("only one of --licenses' or '--licenseFile' can be specified");
}
String licenseInput = args[++i];
licenses = LicenseUtils.readLicensesFromString(licenseInput);
licenseSpecs.addAll(LicenseSpec.fromSource(licenseInput));
break;
case "--licenseFile":
if (licenses != null) {
throw new IllegalArgumentException("only one of --licenses' or '--licenseFile' can be specified");
}
File licenseFile = new File(args[++i]);
if (licenseFile.exists()) {
licenses = LicenseUtils.readLicenseFile(licenseFile);
final byte[] bytes = Files.readAllBytes(Paths.get(licenseFile.getAbsolutePath()));
licenseSpecs.addAll(LicenseSpec.fromSource(bytes));
} else {
throw new IllegalArgumentException(licenseFile.getAbsolutePath() + " does not exist!");
}
@ -62,7 +67,7 @@ public class LicenseGeneratorTool {
}
}
if (licenses == null) {
if (licenseSpecs.size() == 0) {
throw new IllegalArgumentException("at least one of '--licenses' or '--licenseFile' has to be provided");
}
if (publicKeyPath == null) {
@ -72,21 +77,24 @@ public class LicenseGeneratorTool {
throw new IllegalArgumentException("mandatory option '--privateKeyPath' is missing");
}
return new Options(licenses, publicKeyPath, privateKeyPath);
return new Options(licenseSpecs, publicKeyPath, privateKeyPath);
}
public static void main(String[] args) throws IOException {
public static void main(String[] args) throws IOException, ParseException {
run(args, System.out);
}
public static void run(String[] args, OutputStream out) throws IOException {
public static void run(String[] args, OutputStream out) throws IOException, ParseException {
Options options = parse(args);
ESLicenseSigner signer = new ESLicenseSigner(options.privateKeyFilePath, options.publicKeyFilePath);
ESLicenses signedLicences = signer.sign(options.licenses);
ImmutableSet<ESLicense> signedLicences = signer.sign(options.licenseSpecs);
LicenseUtils.dumpLicenseAsJson(signedLicences, out);
XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON, out);
ESLicenses.toXContent(signedLicences, builder);
builder.flush();
}
}

View File

@ -5,86 +5,65 @@
*/
package org.elasticsearch.license.licensor.tools;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.license.core.ESLicense;
import org.elasticsearch.license.core.ESLicenses;
import org.elasticsearch.license.core.LicenseUtils;
import org.elasticsearch.license.manager.ESLicenseManager;
import org.elasticsearch.license.manager.ESLicenseProvider;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashSet;
import java.util.Set;
public class LicenseVerificationTool {
static class Options {
private final Set<ESLicenses> licenses;
private final Set<ESLicense> licenses;
private final String publicKeyFilePath;
Options(Set<ESLicenses> licenses, String publicKeyFilePath) {
Options(Set<ESLicense> licenses, String publicKeyFilePath) {
this.licenses = licenses;
this.publicKeyFilePath = publicKeyFilePath;
}
}
static Set<ESLicenses> asLicensesFromFiles(Set<String> filePaths) throws IOException {
Set<ESLicenses> licenses = new HashSet<>(filePaths.size());
for (String filePath : filePaths) {
final File file = new File(filePath);
if (file.exists()) {
licenses.add(LicenseUtils.readLicenseFile(file));
} else {
throw new IllegalArgumentException(file.getAbsolutePath() + " does not exist!");
}
}
return licenses;
}
static Set<ESLicenses> asLicensesFromStrings(Set<String> fileContents) throws IOException {
Set<ESLicenses> licenses = new HashSet<>(fileContents.size());
for (String fileContent : fileContents) {
licenses.add(LicenseUtils.readLicensesFromString(fileContent));
}
return licenses;
}
private static Options parse(String[] args) throws IOException {
Set<String> licenseFilePaths = null;
Set<String> licensesContents = new HashSet<>();
Set<ESLicenses> licenses = null;
Set<ESLicense> licenses = new HashSet<>();
String publicKeyPath = null;
for (int i = 0; i < args.length; i++) {
String command = args[i];
switch (command) {
case "--licensesFiles":
licenseFilePaths = new HashSet<>();
licenseFilePaths.addAll(Arrays.asList(args[++i].split(":")));
for (String filePath : args[++i].split(":")) {
File file = new File(filePath);
if (file.exists()) {
licenses.addAll(ESLicenses.fromSource(Files.readAllBytes(Paths.get(file.getAbsolutePath()))));
} else {
throw new IllegalArgumentException(file.getAbsolutePath() + " does not exist!");
}
}
break;
case "--licenses":
licensesContents.add(args[++i]);
licenses.addAll(ESLicenses.fromSource(args[++i]));
break;
case "--publicKeyPath":
publicKeyPath = args[++i];
break;
}
}
if (licenseFilePaths == null && licensesContents.size() == 0) {
if (licenses.size() == 0) {
throw new IllegalArgumentException("mandatory option '--licensesFiles' or '--licenses' is missing");
} else if (licenseFilePaths != null) {
licenses = asLicensesFromFiles(licenseFilePaths);
} else if (licensesContents.size() > 0) {
licenses = asLicensesFromStrings(licensesContents);
} else {
throw new IllegalArgumentException("no licenses could be extracted");
}
if (publicKeyPath == null) {
throw new IllegalArgumentException("mandatory option '--publicKeyPath' is missing");
}
assert licenses != null;
return new Options(licenses, publicKeyPath);
}
@ -97,11 +76,15 @@ public class LicenseVerificationTool {
// verify licenses
ESLicenseProvider licenseProvider = new FileBasedESLicenseProvider(options.licenses);
ESLicenseManager licenseManager = new ESLicenseManager(licenseProvider);
licenseManager.verifyLicenses();
ESLicenseManager licenseManager = new ESLicenseManager();
licenseManager.verifyLicenses(licenseProvider.getEffectiveLicenses());
// dump effective licences
LicenseUtils.dumpLicenseAsJson(licenseManager.getEffectiveLicenses(), out);
//LicenseUtils.dumpLicenseAsJson(licenseManager.getEffectiveLicenses(), out);
XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON, out);
ESLicenses.toXContent(licenseProvider.getEffectiveLicenses().values(), builder);
builder.flush();
}
}

View File

@ -11,15 +11,19 @@ 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.elasticsearch.license.core.ESLicenses;
import org.elasticsearch.license.core.LicenseBuilders;
import org.elasticsearch.common.collect.ImmutableSet;
import org.elasticsearch.license.core.ESLicense;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import static org.elasticsearch.license.core.ESLicenses.*;
import static org.elasticsearch.license.core.ESLicense.SubscriptionType;
import static org.elasticsearch.license.core.ESLicense.Type;
import static org.elasticsearch.license.manager.Utils.extractSignedLicence;
/**
@ -31,14 +35,20 @@ import static org.elasticsearch.license.manager.Utils.extractSignedLicence;
*/
public class ESLicenseManager {
private final ESLicenseProvider licenseProvider;
private final LicenseManager licenseManager;
private static class Prefix {
static final String MAX_NODES = "maxNodes:";
static final String TYPE = "type:";
static final String SUBSCRIPTION_TYPE = "subscription_type:";
static final String FEATURE = "feature:";
}
// Initialize LicenseManager
static {
LicenseManagerProperties.setPublicKeyDataProvider(new FilePublicKeyDataProvider(getPublicKeyPath()));
LicenseManagerProperties.setPublicKeyPasswordProvider(new ESPublicKeyPasswordProvider());
LicenseManagerProperties.setLicenseValidator(new DefaultLicenseValidator());
LicenseManagerProperties.setLicenseProvider(new LicenseProvider() {
@Override
public SignedLicense getLicense(Object context) {
@ -61,27 +71,14 @@ public class ESLicenseManager {
}
}
public ESLicenseManager(ESLicenseProvider licenseProvider) {
this.licenseProvider = licenseProvider;
public ESLicenseManager() {
this.licenseManager = LicenseManager.getInstance();
}
private static ESLicenses merge(Set<ESLicenses> esLicensesSet) {
ESLicenses mergedLicenses = null;
for (ESLicenses licenses : esLicensesSet) {
mergedLicenses = LicenseBuilders.merge(mergedLicenses, licenses);
}
return mergedLicenses;
}
public ESLicenses getEffectiveLicenses() {
return licenseProvider.getEffectiveLicenses();
}
public void verifyLicenses(ESLicenses esLicenses) {
public void verifyLicenses(Map<String, org.elasticsearch.license.core.ESLicense> esLicenses) {
try {
for (String feature : esLicenses.features()) {
ESLicense esLicense = esLicenses.get(feature);
for (String feature : esLicenses.keySet()) {
org.elasticsearch.license.core.ESLicense esLicense = esLicenses.get(feature);
// verify signature
final License license = this.licenseManager.decryptAndVerifyLicense(
extractSignedLicence(esLicense.signature()));
@ -94,33 +91,56 @@ public class ESLicenseManager {
} catch (ExpiredLicenseException e) {
throw new InvalidLicenseException("Expired License");
} catch (InvalidLicenseException e) {
throw new InvalidLicenseException("Invalid License: " + e.getCause());
throw new InvalidLicenseException("Invalid License");
}
}
public void verifyLicenses() {
verifyLicenses(getEffectiveLicenses());
public ImmutableSet<String> toSignatures(Collection<ESLicense> esLicenses) {
Set<String> signatures = new HashSet<>();
for (ESLicense esLicense : esLicenses) {
signatures.add(esLicense.signature());
}
return ImmutableSet.copyOf(signatures);
}
public ESLicenses fromSignaturesAsIs(final Set<String> signatures) {
final LicenseBuilders.LicensesBuilder licensesBuilder = LicenseBuilders.licensesBuilder();
public ImmutableSet<ESLicense> fromSignatures(Set<String> signatures) {
Set<ESLicense> esLicenses = new HashSet<>();
for (String signature : signatures) {
licensesBuilder.licenseAsIs(getESLicenseFromSignature(signature));
ESLicense license = fromSignature(signature);
esLicenses.add(license);
}
return licensesBuilder.build();
return ImmutableSet.copyOf(esLicenses);
}
public ESLicense getESLicenseFromSignature(String signature) {
SignedLicense signedLicense = extractSignedLicence(signature);
return decryptAndVerifyESLicense(signedLicense, signature);
}
public ESLicense fromSignature(String signature) {
final SignedLicense signedLicense = Utils.extractSignedLicence(signature);
License license = licenseManager.decryptAndVerifyLicense(signedLicense);
ESLicense.Builder builder = ESLicense.builder();
public ESLicenses fromSignatures(final Set<String> signatures) {
final LicenseBuilders.LicensesBuilder licensesBuilder = LicenseBuilders.licensesBuilder();
for (String signature : signatures) {
licensesBuilder.license(getESLicenseFromSignature(signature));
for (License.Feature feature : license.getFeatures()) {
String featureName = feature.getName();
if (featureName.startsWith(Prefix.MAX_NODES)) {
builder.maxNodes(Integer.parseInt(featureName.substring(Prefix.MAX_NODES.length())));
} else if (featureName.startsWith(Prefix.TYPE)) {
builder.type(Type.fromString(featureName.substring(Prefix.TYPE.length())));
} else if (featureName.startsWith(Prefix.SUBSCRIPTION_TYPE)) {
builder.subscriptionType(SubscriptionType.fromString(featureName.substring(Prefix.SUBSCRIPTION_TYPE.length())));
} else if (featureName.startsWith(Prefix.FEATURE)) {
builder.feature(featureName.substring(Prefix.FEATURE.length()));
}
}
return licensesBuilder.build();
return builder
.uid(license.getProductKey())
.issuer(license.getIssuer())
.issuedTo(license.getHolder())
.issueDate(license.getIssueDate())
.expiryDate(license.getGoodBeforeDate())
.signature(signature)
.build();
}
private static void verifyLicenseFields(License license, ESLicense eslicense) {
@ -129,10 +149,6 @@ public class ESLicenseManager {
&& license.getIssueDate() == eslicense.issueDate()
&& license.getGoodBeforeDate() == eslicense.expiryDate();
assert license.getFeatures().size() == 4 : "one license should have only four features";
String maxNodesPrefix = "maxNodes:";
String typePrefix = "type:";
String subscriptionTypePrefix = "subscription_type:";
String featurePrefix = "feature:";
boolean maxNodesValid = false;
boolean featureValid = false;
boolean typeValid = false;
@ -140,14 +156,14 @@ public class ESLicenseManager {
for (License.Feature feature : license.getFeatures()) {
String featureName = feature.getName();
if (featureName.startsWith(maxNodesPrefix)) {
maxNodesValid = eslicense.maxNodes() == Integer.parseInt(featureName.substring(maxNodesPrefix.length()));
} else if (featureName.startsWith(typePrefix)) {
typeValid = eslicense.type() == Type.fromString(featureName.substring(typePrefix.length()));
} else if (featureName.startsWith(subscriptionTypePrefix)) {
subscriptionTypeValid = eslicense.subscriptionType() == SubscriptionType.fromString(featureName.substring(subscriptionTypePrefix.length()));
} else if (featureName.startsWith(featurePrefix)) {
String featureValue = featureName.substring(featurePrefix.length());
if (featureName.startsWith(Prefix.MAX_NODES)) {
maxNodesValid = eslicense.maxNodes() == Integer.parseInt(featureName.substring(Prefix.MAX_NODES.length()));
} else if (featureName.startsWith(Prefix.TYPE)) {
typeValid = eslicense.type() == Type.fromString(featureName.substring(Prefix.TYPE.length()));
} else if (featureName.startsWith(Prefix.SUBSCRIPTION_TYPE)) {
subscriptionTypeValid = eslicense.subscriptionType() == SubscriptionType.fromString(featureName.substring(Prefix.SUBSCRIPTION_TYPE.length()));
} else if (featureName.startsWith(Prefix.FEATURE)) {
String featureValue = featureName.substring(Prefix.FEATURE.length());
featureValid = featureValue.equals(eslicense.feature())
&& feature.getGoodBeforeDate() == eslicense.expiryDate();
}
@ -156,28 +172,17 @@ public class ESLicenseManager {
//only for debugging
String msg = "licenseValid: " + licenseValid + "\n" +
"featureValid: " + featureValid + "\n" +
"maxNodeValide: " + maxNodesValid + "\n" +
"maxNodeValid: " + maxNodesValid + "\n" +
"typeValid: " + typeValid + "\n" +
"subscriptionTypeValid: " + subscriptionTypeValid + "\n";
throw new InvalidLicenseException("Invalid License");
}
}
private License getLicense(String feature) {
ESLicense esLicense = licenseProvider.getESLicense(feature);
if (esLicense != null) {
String signature = esLicense.signature();
License license = this.licenseManager.decryptAndVerifyLicense(extractSignedLicence(signature));
this.licenseManager.validateLicense(license);
return license;
}
return null;
}
//TODO wrap License validation methods so a plugin does not have to provide featureType param
public boolean hasLicenseForFeature(String feature) {
public boolean hasLicenseForFeature(String feature, Map<String, ESLicense> licenseMap) {
try {
final License license = getLicense(feature);
final License license = getInternalLicense(feature, licenseMap);
if (license != null) {
return license.hasLicenseForFeature("feature:" + feature);
}
@ -189,85 +194,15 @@ public class ESLicenseManager {
}
}
public boolean hasLicenseForNodes(String featureType, int nodes) {
ESLicense esLicense = getESLicense(featureType);
return esLicense.maxNodes() >= nodes;
}
public String getIssuerForLicense(String featureType) {
final License license = getLicense(featureType);
return license.getIssuer();
}
public long getIssueDateForLicense(String featureType) {
final License license = getLicense(featureType);
return license.getIssueDate();
}
public long getExpiryDateForLicense(String featureType) {
final License license = getLicense(featureType);
return license.getGoodBeforeDate();
}
public String getIssuedToForLicense(String featureType) {
final License license = getLicense(featureType);
return license.getHolder();
}
public Type getTypeForLicense(String featureType) {
ESLicense esLicense = getESLicense(featureType);
return esLicense.type();
}
public SubscriptionType getSubscriptionTypeForLicense(String featureType) {
ESLicense esLicense = getESLicense(featureType);
return esLicense.subscriptionType();
}
ESLicense getESLicense(String featureType) {
final License license = getLicense(featureType);
return convertToESLicense(license);
}
ESLicense decryptAndVerifyESLicense(SignedLicense signedLicense, String signature) {
return convertToESLicense(this.licenseManager.decryptAndVerifyLicense(signedLicense), signature);
}
static ESLicense convertToESLicense(License license) {
return convertToESLicense(license, null);
}
static ESLicense convertToESLicense(License license, String signature) {
final LicenseBuilders.LicenseBuilder licenseBuilder = LicenseBuilders.licenseBuilder(false);
licenseBuilder
.expiryDate(license.getGoodBeforeDate())
.issueDate(license.getIssueDate())
.uid(license.getProductKey())
.issuedTo(license.getHolder())
.issuer(license.getIssuer());
if (signature != null) {
licenseBuilder.signature(signature);
private License getInternalLicense(String feature, Map<String, ESLicense> licenseMap) {
ESLicense esLicense = licenseMap.get(feature);
if (esLicense != null) {
String signature = esLicense.signature();
License license = this.licenseManager.decryptAndVerifyLicense(extractSignedLicence(signature));
this.licenseManager.validateLicense(license);
return license;
}
assert license.getFeatures().size() == 4 : "one license should have only four feature";
String maxNodesPrefix = "maxNodes:";
String typePrefix = "type:";
String subscriptionTypePrefix = "subscription_type:";
String featurePrefix = "feature:";
for (License.Feature feature : license.getFeatures()) {
String featureName = feature.getName();
if (featureName.startsWith(maxNodesPrefix)) {
licenseBuilder.maxNodes(Integer.parseInt(featureName.substring(maxNodesPrefix.length())));
} else if (featureName.startsWith(typePrefix)) {
licenseBuilder.type(Type.fromString(featureName.substring(typePrefix.length())));
} else if (featureName.startsWith(subscriptionTypePrefix)) {
licenseBuilder.subscriptionType(SubscriptionType.fromString(featureName.substring(subscriptionTypePrefix.length())));
} else if (featureName.startsWith(featurePrefix)) {
licenseBuilder.feature(featureName.substring(featurePrefix.length()));
}
}
return licenseBuilder.build();
return null;
}
// TODO: Need a better password management

View File

@ -5,13 +5,15 @@
*/
package org.elasticsearch.license.manager;
import org.elasticsearch.license.core.ESLicenses;
import static org.elasticsearch.license.core.ESLicenses.ESLicense;
import org.elasticsearch.license.core.ESLicense;
import java.util.Map;
public interface ESLicenseProvider {
ESLicense getESLicense(String feature);
ESLicenses getEffectiveLicenses();
Map<String, ESLicense> getEffectiveLicenses();
}

View File

@ -8,9 +8,14 @@ package org.elasticsearch.license.manager;
import net.nicholaswilliams.java.licensing.ObjectSerializer;
import net.nicholaswilliams.java.licensing.SignedLicense;
import org.apache.commons.codec.binary.Base64;
import org.elasticsearch.common.collect.ImmutableMap;
import org.elasticsearch.license.core.ESLicense;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public final class Utils {
/**
@ -31,4 +36,26 @@ public final class Utils {
int version = byteBuffer.getInt();
return new ObjectSerializer().readObject(SignedLicense.class, Arrays.copyOfRange(signatureBytes, start, signatureBytes.length));
}
public static ImmutableMap<String, ESLicense> reduceAndMap(Set<ESLicense> esLicensesSet) {
Map<String, ESLicense> map = new HashMap<>(esLicensesSet.size());
for (ESLicense license : esLicensesSet) {
putIfAppropriate(map, license);
}
return ImmutableMap.copyOf(map);
}
private static void putIfAppropriate(Map<String, ESLicense> licenseMap, ESLicense license) {
final String featureType = license.feature();
if (licenseMap.containsKey(featureType)) {
final ESLicense previousLicense = licenseMap.get(featureType);
if (license.expiryDate() > previousLicense.expiryDate()) {
licenseMap.put(featureType, license);
}
} else if (license.expiryDate() > System.currentTimeMillis()) {
licenseMap.put(featureType, license);
}
}
}

View File

@ -1,97 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.license.plugin.action;
import org.elasticsearch.common.collect.ImmutableMap;
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;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import static org.elasticsearch.license.core.ESLicenses.*;
public class Utils {
public static String[] toSignatures(ESLicenses esLicenses) {
Set<String> signatures = new HashSet<>();
for (ESLicense esLicense : esLicenses) {
signatures.add(esLicense.signature());
}
return signatures.toArray(new String[signatures.size()]);
}
public static ESLicenses readGeneratedLicensesFrom(StreamInput in) throws IOException {
final LicenseBuilders.LicensesBuilder licensesBuilder = LicenseBuilders.licensesBuilder();
boolean exists = in.readBoolean();
if (exists) {
int size = in.readVInt();
for (int i = 0; i < size; i++) {
licensesBuilder.licenseAsIs(licenseFromMap(in.readMap()));
}
return licensesBuilder.build();
}
return null;
}
public static void writeGeneratedLicensesTo(ESLicenses esLicenses, StreamOutput out) throws IOException {
if (esLicenses == null) {
out.writeBoolean(false);
return;
}
out.writeBoolean(true);
out.writeVInt(esLicenses.licenses().size());
for (ESLicense esLicense : esLicenses) {
out.writeMap(licenseAsMap(esLicense));
}
}
// TODO: make sure field order is preserved
public static Map<String, Object> licenseAsMap(ESLicense esLicense) {
ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
builder.put(LicenseFields.UID, esLicense.uid());
builder.put(LicenseFields.TYPE, esLicense.type().string());
builder.put(LicenseFields.SUBSCRIPTION_TYPE, esLicense.subscriptionType().string());
builder.put(LicenseFields.ISSUE_DATE, esLicense.issueDate());
builder.put(LicenseFields.FEATURE, esLicense.feature());
builder.put(LicenseFields.EXPIRY_DATE, esLicense.expiryDate());
builder.put(LicenseFields.MAX_NODES, esLicense.maxNodes());
builder.put(LicenseFields.ISSUED_TO, esLicense.issuedTo());
builder.put(LicenseFields.SIGNATURE, esLicense.signature());
return builder.build();
}
public static ESLicense licenseFromMap(Map<String, Object> map) {
return LicenseBuilders.licenseBuilder(false)
.uid((String) map.get(LicenseFields.UID))
.type(Type.fromString((String) map.get(LicenseFields.TYPE)))
.subscriptionType(SubscriptionType.fromString((String) map.get(LicenseFields.SUBSCRIPTION_TYPE)))
.issueDate((long) map.get(LicenseFields.ISSUE_DATE))
.feature((String) map.get(LicenseFields.FEATURE))
.expiryDate((long) map.get(LicenseFields.EXPIRY_DATE))
.maxNodes((int) map.get(LicenseFields.MAX_NODES))
.issuedTo((String) map.get(LicenseFields.ISSUED_TO))
.signature((String) map.get(LicenseFields.SIGNATURE))
.build();
}
final static class LicenseFields {
private final static String UID = "uid";
private final static String TYPE = "type";
private final static String SUBSCRIPTION_TYPE = "subscription_type";
private final static String ISSUE_DATE = "issue_date";
private final static String FEATURE = "feature";
private final static String EXPIRY_DATE = "expiry_date";
private final static String MAX_NODES = "max_nodes";
private final static String ISSUED_TO = "issued_to";
private final static String SIGNATURE = "signature";
}
}

View File

@ -8,49 +8,38 @@ package org.elasticsearch.license.plugin.action.get;
import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.license.core.ESLicense;
import org.elasticsearch.license.core.ESLicenses;
import org.elasticsearch.license.core.LicenseBuilders;
import org.elasticsearch.license.plugin.core.trial.TrialLicenseUtils;
import org.elasticsearch.license.plugin.core.trial.TrialLicenses;
import org.elasticsearch.license.plugin.core.trial.TrialLicensesBuilder;
import java.io.IOException;
import static org.elasticsearch.license.plugin.action.Utils.*;
import java.util.HashSet;
import java.util.Set;
public class GetLicenseResponse extends ActionResponse {
private ESLicenses licenses = null;
private TrialLicenses trialLicenses = null;
private Set<ESLicense> licenses = new HashSet<>();
GetLicenseResponse() {
}
GetLicenseResponse(ESLicenses esLicenses, TrialLicenses trialLicenses) {
GetLicenseResponse(Set<ESLicense> esLicenses) {
this.licenses = esLicenses;
this.trialLicenses = trialLicenses;
}
public ESLicenses licenses() {
return (licenses != null) ? licenses : LicenseBuilders.licensesBuilder().build();
}
public TrialLicenses trialLicenses() {
return trialLicenses != null ? trialLicenses : TrialLicensesBuilder.EMPTY;
public Set<ESLicense> licenses() {
return licenses;
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
licenses = readGeneratedLicensesFrom(in);
trialLicenses = TrialLicenseUtils.readTrialLicensesFrom(in);
licenses = ESLicenses.readFrom(in);
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
writeGeneratedLicensesTo(licenses, out);
TrialLicenseUtils.writeTrialLicensesTo(trialLicenses, out);
ESLicenses.writeTo(licenses, out);
}
}

View File

@ -13,27 +13,24 @@ import org.elasticsearch.cluster.ClusterService;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.block.ClusterBlockException;
import org.elasticsearch.cluster.block.ClusterBlockLevel;
import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.core.ESLicenses;
import org.elasticsearch.license.manager.ESLicenseManager;
import org.elasticsearch.license.plugin.core.LicensesMetaData;
import org.elasticsearch.license.plugin.core.LicensesService;
import org.elasticsearch.license.plugin.core.trial.TrialLicenseUtils;
import org.elasticsearch.license.plugin.core.trial.TrialLicenses;
import org.elasticsearch.license.core.ESLicense;
import org.elasticsearch.license.plugin.core.LicensesManagerService;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;
import java.util.Set;
public class TransportGetLicenseAction extends TransportMasterNodeReadOperationAction<GetLicenseRequest, GetLicenseResponse> {
private final LicensesService licensesService;
private final LicensesManagerService licensesManagerService;
@Inject
public TransportGetLicenseAction(Settings settings, TransportService transportService, ClusterService clusterService, LicensesService licensesService,
public TransportGetLicenseAction(Settings settings, TransportService transportService, ClusterService clusterService, LicensesManagerService licensesManagerService,
ThreadPool threadPool, ActionFilters actionFilters) {
super(settings, GetLicenseAction.NAME, transportService, clusterService, threadPool, actionFilters);
this.licensesService = licensesService;
this.licensesManagerService = licensesManagerService;
}
@Override
@ -53,22 +50,12 @@ public class TransportGetLicenseAction extends TransportMasterNodeReadOperationA
@Override
protected ClusterBlockException checkBlock(GetLicenseRequest request, ClusterState state) {
//TODO: do the right checkBlock
return state.blocks().indexBlockedException(ClusterBlockLevel.METADATA, "");
}
@Override
protected void masterOperation(final GetLicenseRequest request, ClusterState state, final ActionListener<GetLicenseResponse> listener) throws ElasticsearchException {
//TODO: Move this functionality to license service
MetaData metaData = state.metaData();
LicensesMetaData licenses = metaData.custom(LicensesMetaData.TYPE);
if (licenses != null) {
ESLicenseManager esLicenseManager = licensesService.getEsLicenseManager();
ESLicenses esLicenses = esLicenseManager.fromSignaturesAsIs(licenses.getSignatures());
TrialLicenses trialLicenses = TrialLicenseUtils.fromEncodedTrialLicenses(licenses.getEncodedTrialLicenses());
listener.onResponse(new GetLicenseResponse(esLicenses, trialLicenses));
} else {
listener.onResponse(new GetLicenseResponse());
}
final Set<ESLicense> currentLicenses = licensesManagerService.getLicenses();
listener.onResponse(new GetLicenseResponse(currentLicenses));
}
}

View File

@ -10,17 +10,16 @@ import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.support.master.AcknowledgedRequest;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.license.core.ESLicense;
import org.elasticsearch.license.core.ESLicenses;
import org.elasticsearch.license.core.LicenseUtils;
import java.io.IOException;
import java.util.Set;
import static org.elasticsearch.license.plugin.action.Utils.readGeneratedLicensesFrom;
import static org.elasticsearch.license.plugin.action.Utils.writeGeneratedLicensesTo;
public class PutLicenseRequest extends AcknowledgedRequest<PutLicenseRequest> {
private ESLicenses license;
private Set<ESLicense> licenses;
public PutLicenseRequest() {
}
@ -31,37 +30,37 @@ public class PutLicenseRequest extends AcknowledgedRequest<PutLicenseRequest> {
}
/**
* Parses license from json format to an instance of {@link org.elasticsearch.license.core.ESLicenses}
* @param licenseDefinition license definition
* Parses licenses from json format to an instance of {@link org.elasticsearch.license.core.ESLicenses}
* @param licenseDefinition licenses definition
*/
public PutLicenseRequest license(String licenseDefinition) {
public PutLicenseRequest licenses(String licenseDefinition) {
try {
return license(LicenseUtils.readLicensesFromString(licenseDefinition));
return licenses(ESLicenses.fromSource(licenseDefinition));
} catch (IOException e) {
throw new ElasticsearchIllegalArgumentException("failed to parse license source", e);
throw new ElasticsearchIllegalArgumentException("failed to parse licenses source", e);
}
}
public PutLicenseRequest license(ESLicenses esLicenses) {
this.license = esLicenses;
public PutLicenseRequest licenses(Set<ESLicense> esLicenses) {
this.licenses = esLicenses;
return this;
}
public ESLicenses license() {
return license;
public Set<ESLicense> licenses() {
return licenses;
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
license = readGeneratedLicensesFrom(in);
licenses = ESLicenses.readFrom(in);
readTimeout(in);
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
writeGeneratedLicensesTo(license, out);
ESLicenses.writeTo(licenses, out);
writeTimeout(out);
}
}

View File

@ -8,7 +8,9 @@ package org.elasticsearch.license.plugin.action.put;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.master.AcknowledgedRequestBuilder;
import org.elasticsearch.client.ClusterAdminClient;
import org.elasticsearch.license.core.ESLicenses;
import org.elasticsearch.license.core.ESLicense;
import java.util.Set;
/**
* Register license request builder
@ -27,11 +29,11 @@ public class PutLicenseRequestBuilder extends AcknowledgedRequestBuilder<PutLice
/**
* Sets the license
*
* @param license license
* @param licenses license
* @return this builder
*/
public PutLicenseRequestBuilder setLicense(ESLicenses license) {
request.license(license);
public PutLicenseRequestBuilder setLicense(Set<ESLicense> licenses) {
request.licenses(licenses);
return this;
}

View File

@ -5,7 +5,6 @@
*/
package org.elasticsearch.license.plugin.core;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.transport.RemoteTransportException;

View File

@ -8,8 +8,7 @@ package org.elasticsearch.license.plugin.core;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse;
import org.elasticsearch.common.inject.ImplementedBy;
import org.elasticsearch.common.inject.Singleton;
import org.elasticsearch.license.core.ESLicenses;
import org.elasticsearch.license.core.ESLicense;
import java.util.Set;
@ -19,11 +18,15 @@ import static org.elasticsearch.license.plugin.core.LicensesService.PutLicenseRe
@ImplementedBy(LicensesService.class)
public interface LicensesManagerService {
//TODO: documentation
public LicensesStatus registerLicenses(final PutLicenseRequestHolder requestHolder, final ActionListener<ClusterStateUpdateResponse> listener);
public void unregisterLicenses(final DeleteLicenseRequestHolder requestHolder, final ActionListener<ClusterStateUpdateResponse> listener);
public LicensesStatus checkLicenses(ESLicenses licenses);
public LicensesStatus checkLicenses(Set<ESLicense> licenses);
public Set<String> enabledFeatures();
public Set<ESLicense> getLicenses();
}

View File

@ -12,16 +12,10 @@ import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.license.core.ESLicenses;
import org.elasticsearch.license.plugin.action.Utils;
import org.elasticsearch.license.plugin.core.trial.TrialLicenseUtils;
import org.elasticsearch.license.plugin.core.trial.TrialLicenses;
import java.io.IOException;
import java.util.*;
import static org.elasticsearch.license.plugin.action.Utils.*;
/**
* Contains metadata about registered licenses
*
@ -32,9 +26,9 @@ public class LicensesMetaData implements MetaData.Custom {
public static final Factory FACTORY = new Factory();
final Set<String> signatures;
private final Set<String> signatures;
final Set<String> encodedTrialLicenses;
private final Set<String> encodedTrialLicenses;
public LicensesMetaData(String[] signatures, String[] encodedTrialLicenses) {
this(Sets.newHashSet(signatures), Sets.newHashSet(encodedTrialLicenses));

View File

@ -14,6 +14,7 @@ import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse;
import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.collect.ImmutableMap;
import org.elasticsearch.common.collect.ImmutableSet;
import org.elasticsearch.common.collect.Sets;
import org.elasticsearch.common.component.AbstractLifecycleComponent;
@ -23,11 +24,9 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.util.concurrent.EsRejectedExecutionException;
import org.elasticsearch.gateway.GatewayService;
import org.elasticsearch.license.core.ESLicenses;
import org.elasticsearch.license.core.LicenseBuilders;
import org.elasticsearch.license.core.ESLicense;
import org.elasticsearch.license.manager.ESLicenseManager;
import org.elasticsearch.license.manager.ESLicenseProvider;
import org.elasticsearch.license.plugin.action.Utils;
import org.elasticsearch.license.plugin.action.delete.DeleteLicenseRequest;
import org.elasticsearch.license.plugin.action.put.PutLicenseRequest;
import org.elasticsearch.license.plugin.core.trial.TrialLicenseUtils;
@ -35,9 +34,7 @@ import org.elasticsearch.license.plugin.core.trial.TrialLicenses;
import org.elasticsearch.license.plugin.core.trial.TrialLicensesBuilder;
import org.elasticsearch.threadpool.ThreadPool;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.atomic.AtomicBoolean;
@ -47,9 +44,10 @@ import static org.elasticsearch.license.plugin.core.trial.TrialLicenses.TrialLic
/**
* Service responsible for managing {@link org.elasticsearch.license.plugin.core.LicensesMetaData}
* Interfaces through which this is exposed are:
* - LicensesManagerService - responsible for adding/deleting signed licenses
* - LicensesClientService - allow interested plugins (features) to register to licensing notifications
* - LicensesManagerService - responsible for adding/deleting signed licenses
* - LicensesClientService - allow interested plugins (features) to register to licensing notifications
*
* TODO: documentation; remove ESLicenseProvider interface (almost done)
*/
@Singleton
public class LicensesService extends AbstractLifecycleComponent<LicensesService> implements ESLicenseProvider, ClusterStateListener, LicensesManagerService, LicensesClientService {
@ -68,7 +66,7 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
public LicensesService(Settings settings, ClusterService clusterService, ThreadPool threadPool) {
super(settings);
this.clusterService = clusterService;
this.esLicenseManager = new ESLicenseManager(this);
this.esLicenseManager = new ESLicenseManager();
this.threadPool = threadPool;
}
@ -81,7 +79,7 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
@Override
public LicensesStatus registerLicenses(final PutLicenseRequestHolder requestHolder, final ActionListener<ClusterStateUpdateResponse> listener) {
final PutLicenseRequest request = requestHolder.request;
final ESLicenses newLicenses = request.license();
final Set<ESLicense> newLicenses = request.licenses();
LicensesStatus status = checkLicenses(newLicenses);
switch (status) {
case VALID:
@ -134,10 +132,15 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
}
@Override
public LicensesStatus checkLicenses(ESLicenses licenses) {
public LicensesStatus checkLicenses(Set<ESLicense> licenses) {
final ImmutableMap<String, ESLicense> map = org.elasticsearch.license.manager.Utils.reduceAndMap(licenses);
return checkLicenses(map);
}
private LicensesStatus checkLicenses(Map<String, ESLicense> licenseMap) {
LicensesStatus status = LicensesStatus.VALID;
try {
esLicenseManager.verifyLicenses(licenses);
esLicenseManager.verifyLicenses(licenseMap);
} catch (ExpiredLicenseException e) {
status = LicensesStatus.EXPIRED;
} catch (InvalidLicenseException e) {
@ -159,6 +162,33 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
return enabledFeatures;
}
@Override
public Set<ESLicense> getLicenses() {
LicensesMetaData currentMetaData = clusterService.state().metaData().custom(LicensesMetaData.TYPE);
Set<ESLicense> trialLicenses = new HashSet<>();
if (currentMetaData != null) {
Set<ESLicense> currentLicenses = esLicenseManager.fromSignatures(currentMetaData.getSignatures());
TrialLicenses currentTrialLicenses = TrialLicenseUtils.fromEncodedTrialLicenses(currentMetaData.getEncodedTrialLicenses());
for (TrialLicense trialLicense : currentTrialLicenses) {
trialLicenses.add(ESLicense.builder()
.uid(trialLicense.uid())
.issuedTo(trialLicense.issuedTo())
.issueDate(trialLicense.issueDate())
.type(ESLicense.Type.TRIAL)
.subscriptionType(ESLicense.SubscriptionType.NONE)
.feature(trialLicense.feature())
.maxNodes(trialLicense.maxNodes())
.expiryDate(trialLicense.expiryDate())
.issuer("elasticsearch").buildInternal()
);
}
Set<ESLicense> licenses = Sets.union(currentLicenses, trialLicenses);
//TODO: sort in some order
return licenses;
}
return Sets.newHashSet();
}
private void registerTrialLicense(final TrialLicense trialLicense) {
clusterService.submitStateUpdateTask("register trial license []", new ProcessedClusterStateUpdateTask() {
@ -173,7 +203,7 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
LicensesMetaData currentLicenses = metaData.custom(LicensesMetaData.TYPE);
final LicensesWrapper licensesWrapper = LicensesWrapper.wrap(currentLicenses);
// do not generate a trial license for a feature that already has a signed license
if (!esLicenseManager.hasLicenseForFeature(trialLicense.feature())) {
if (!esLicenseManager.hasLicenseForFeature(trialLicense.feature(), getEffectiveLicenses())) {
licensesWrapper.addTrialLicense(trialLicense);
}
mdBuilder.putCustom(LicensesMetaData.TYPE, licensesWrapper.createLicensesMetaData());
@ -245,7 +275,7 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
private void registerListeners(LicensesMetaData currentMetaData) {
for (ListenerHolder listenerHolder : registeredListeners) {
if (listenerHolder.registered.compareAndSet(false, true)) {
if (!esLicenseManager.hasLicenseForFeature(listenerHolder.feature)) {
if (!esLicenseManager.hasLicenseForFeature(listenerHolder.feature, getEffectiveLicenses())) {
// does not have actual license so generate a trial license
TrialLicenseOptions options = listenerHolder.trialLicenseOptions;
if (options != null) {
@ -284,18 +314,24 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
}
@Override
public ESLicenses.ESLicense getESLicense(String feature) {
public ESLicense getESLicense(String feature) {
return getEffectiveLicenses().get(feature);
}
@Override
public ESLicenses getEffectiveLicenses() {
public Map<String, ESLicense> getEffectiveLicenses() {
final ClusterState state = clusterService.state();
LicensesMetaData metaData = state.metaData().custom(LicensesMetaData.TYPE);
Map<String, ESLicense> map = new HashMap<>();
if (metaData != null) {
return esLicenseManager.fromSignatures(metaData.getSignatures());
Set<ESLicense> esLicenses = new HashSet<>();
for (String signature : metaData.getSignatures()) {
esLicenses.add(esLicenseManager.fromSignature(signature));
}
return org.elasticsearch.license.manager.Utils.reduceAndMap(esLicenses);
}
return LicenseBuilders.licensesBuilder().build();
return ImmutableMap.copyOf(map);
}
@ -364,8 +400,9 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
long offset = TimeValue.timeValueMinutes(1).getMillis();
for (ListenerHolder listenerHolder : registeredListeners) {
long expiryDate = -1l;
if (esLicenseManager.hasLicenseForFeature(listenerHolder.feature)) {
expiryDate = esLicenseManager.getExpiryDateForLicense(listenerHolder.feature);
final Map<String, ESLicense> effectiveLicenses = getEffectiveLicenses();
if (esLicenseManager.hasLicenseForFeature(listenerHolder.feature, effectiveLicenses)) {
expiryDate = effectiveLicenses.get(listenerHolder.feature).expiryDate();
} else {
final TrialLicense trialLicense = licensesWrapper.trialLicenses().getTrialLicense(listenerHolder.feature);
if (trialLicense != null) {
@ -471,13 +508,13 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
private LicensesWrapper(LicensesMetaData licensesMetaData) {
if (licensesMetaData != null) {
this.signatures = ImmutableSet.copyOf(licensesMetaData.signatures);
this.encodedTrialLicenses = ImmutableSet.copyOf(licensesMetaData.encodedTrialLicenses);
this.signatures = ImmutableSet.copyOf(licensesMetaData.getSignatures());
this.encodedTrialLicenses = ImmutableSet.copyOf(licensesMetaData.getEncodedTrialLicenses());
}
}
public ESLicenses signedLicenses(ESLicenseManager licenseManage) {
return licenseManage.fromSignatures(signatures);
public Set<ESLicense> signedLicenses(ESLicenseManager licenseManager) {
return licenseManager.fromSignatures(signatures);
}
public TrialLicenses trialLicenses() {
@ -488,6 +525,7 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
* Check if any trial license for the feature exists,
* if no trial license for feature exists, add new
* trial license for feature
*
* @param trialLicense to add
*/
public void addTrialLicense(TrialLicense trialLicense) {
@ -504,18 +542,23 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
}
}
public void addSignedLicenses(ESLicenseManager licenseManager, ESLicenses licenses) {
ESLicenses currentSignedLicenses = signedLicenses(licenseManager);
final ESLicenses mergedLicenses = LicenseBuilders.merge(currentSignedLicenses, licenses);
Set<String> newSignatures = Sets.newHashSet(Utils.toSignatures(mergedLicenses));
this.signatures = ImmutableSet.copyOf(Sets.union(signatures, newSignatures));
public void addSignedLicenses(ESLicenseManager licenseManager, Set<ESLicense> newLicenses) {
Set<ESLicense> currentSignedLicenses = signedLicenses(licenseManager);
final ImmutableMap<String, ESLicense> licenseMap = org.elasticsearch.license.manager.Utils.reduceAndMap(Sets.union(currentSignedLicenses, newLicenses));
this.signatures = licenseManager.toSignatures(licenseMap.values());
}
public void removeFeatures(ESLicenseManager licenseManage, Set<String> featuresToDelete) {
ESLicenses currentSignedLicenses = signedLicenses(licenseManage);
final ESLicenses reducedLicenses = LicenseBuilders.removeFeatures(currentSignedLicenses, featuresToDelete);
Set<String> reducedSignatures = Sets.newHashSet(Utils.toSignatures(reducedLicenses));
this.signatures = ImmutableSet.copyOf(Sets.intersection(signatures, reducedSignatures));
public void removeFeatures(ESLicenseManager licenseManager, Set<String> featuresToDelete) {
Set<ESLicense> currentSignedLicenses = signedLicenses(licenseManager);
final ImmutableMap<String, ESLicense> licenseMap = org.elasticsearch.license.manager.Utils.reduceAndMap(currentSignedLicenses);
Set<ESLicense> licensesToDelete = new HashSet<>();
for (Map.Entry<String, ESLicense> entry : licenseMap.entrySet()) {
if (featuresToDelete.contains(entry.getKey())) {
licensesToDelete.add(entry.getValue());
}
}
Set<ESLicense> reducedLicenses = Sets.difference(currentSignedLicenses, licensesToDelete);
this.signatures = licenseManager.toSignatures(reducedLicenses);
}
public LicensesMetaData createLicensesMetaData() {

View File

@ -81,14 +81,6 @@ public class TrialLicenseUtils {
return Base64.encodeBase64String(encodedLicense);
}
public static String[] toEncodedTrialLicenses(TrialLicenses trialLicenses) {
Set<String> encodedTrialLicenses = new HashSet<>();
for (TrialLicenses.TrialLicense trialLicense : trialLicenses) {
encodedTrialLicenses.add(toEncodedTrialLicense(trialLicense));
}
return encodedTrialLicenses.toArray(new String[encodedTrialLicenses.size()]);
}
public static TrialLicenses fromEncodedTrialLicenses(String[] encodedTrialLicenses) {
final TrialLicensesBuilder trialLicensesBuilder = trialLicensesBuilder();
for (String encodedTrialLicense : encodedTrialLicenses) {
@ -100,66 +92,4 @@ public class TrialLicenseUtils {
public static TrialLicenses fromEncodedTrialLicenses(Set<String> encodedTrialLicenses) {
return fromEncodedTrialLicenses(encodedTrialLicenses.toArray(new String[encodedTrialLicenses.size()]));
}
public static TrialLicenses readTrialLicensesFrom(StreamInput in) throws IOException {
final TrialLicensesBuilder licensesBuilder = TrialLicensesBuilder.trialLicensesBuilder();
boolean exists = in.readBoolean();
if (exists) {
int size = in.readVInt();
for (int i = 0; i < size; i++) {
licensesBuilder.license(trialLicenseFromMap(in.readMap()));
}
return licensesBuilder.build();
}
return null;
}
public static void writeTrialLicensesTo(TrialLicenses trialLicenses, StreamOutput out) throws IOException {
if (trialLicenses == null) {
out.writeBoolean(false);
return;
}
out.writeBoolean(true);
out.writeVInt(trialLicenses.trialLicenses().size());
for (TrialLicenses.TrialLicense trialLicense : trialLicenses) {
out.writeMap(trialLicenseAsMap(trialLicense));
}
}
// TODO: make sure field order is preserved
public static Map<String, Object> trialLicenseAsMap(TrialLicenses.TrialLicense trialLicense) {
ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
builder.put(TrialLicenseFields.UID, trialLicense.uid());
builder.put(TrialLicenseFields.TYPE, ESLicenses.Type.TRIAL.string());
builder.put(TrialLicenseFields.SUBSCRIPTION_TYPE, ESLicenses.SubscriptionType.NONE.string());
builder.put(TrialLicenseFields.ISSUE_DATE, trialLicense.issueDate());
builder.put(TrialLicenseFields.FEATURE, trialLicense.feature());
builder.put(TrialLicenseFields.EXPIRY_DATE, trialLicense.expiryDate());
builder.put(TrialLicenseFields.MAX_NODES, trialLicense.maxNodes());
builder.put(TrialLicenseFields.ISSUED_TO, trialLicense.issuedTo());
return builder.build();
}
public static TrialLicenses.TrialLicense trialLicenseFromMap(Map<String, Object> map) {
return TrialLicensesBuilder.trialLicenseBuilder()
.uid((String) map.get(TrialLicenseFields.UID))
.issuedTo((String) map.get(TrialLicenseFields.ISSUED_TO))
.maxNodes((int) map.get(TrialLicenseFields.MAX_NODES))
.feature((String) map.get(TrialLicenseFields.FEATURE))
.issueDate((long) map.get(TrialLicenseFields.ISSUE_DATE))
.expiryDate((long) map.get(TrialLicenseFields.EXPIRY_DATE))
.build();
}
final static class TrialLicenseFields {
private final static String UID = "uid";
private final static String TYPE = "type";
private final static String SUBSCRIPTION_TYPE = "subscription_type";
private final static String ISSUE_DATE = "issue_date";
private final static String FEATURE = "feature";
private final static String ISSUED_TO = "issued_to";
private final static String MAX_NODES = "max_nodes";
private final static String EXPIRY_DATE = "expiry_date";
}
}

View File

@ -7,6 +7,7 @@ package org.elasticsearch.license.plugin.core.trial;
import org.elasticsearch.common.collect.ImmutableMap;
import org.elasticsearch.license.core.DateUtils;
import org.elasticsearch.license.core.ESLicense;
import java.util.*;
@ -16,6 +17,12 @@ public class TrialLicensesBuilder {
public static TrialLicenses EMPTY = trialLicensesBuilder().build();
public static final String ISSUER = "elasticsearch";
public static final ESLicense.Type TYPE = ESLicense.Type.TRIAL;
public static final ESLicense.SubscriptionType SUBSCRIPTION_TYPE = ESLicense.SubscriptionType.NONE;
public static TrialLicensesBuilder trialLicensesBuilder() {
return new TrialLicensesBuilder();
}

View File

@ -13,12 +13,9 @@ import org.elasticsearch.license.core.ESLicenses;
import org.elasticsearch.license.plugin.action.get.GetLicenseAction;
import org.elasticsearch.license.plugin.action.get.GetLicenseRequest;
import org.elasticsearch.license.plugin.action.get.GetLicenseResponse;
import org.elasticsearch.license.plugin.core.trial.TrialLicenses;
import org.elasticsearch.rest.*;
import org.elasticsearch.rest.action.support.RestBuilderListener;
import static org.elasticsearch.license.plugin.action.Utils.licenseAsMap;
import static org.elasticsearch.license.plugin.core.trial.TrialLicenseUtils.trialLicenseAsMap;
import static org.elasticsearch.rest.RestRequest.Method.GET;
import static org.elasticsearch.rest.RestStatus.OK;
@ -35,16 +32,7 @@ public class RestGetLicenseAction extends BaseRestHandler {
client.admin().cluster().execute(GetLicenseAction.INSTANCE, new GetLicenseRequest(), new RestBuilderListener<GetLicenseResponse>(channel) {
@Override
public RestResponse buildResponse(GetLicenseResponse response, XContentBuilder builder) throws Exception {
builder.startObject();
builder.startArray("licenses");
for (ESLicenses.ESLicense license : response.licenses()) {
builder.map(licenseAsMap(license));
}
for (TrialLicenses.TrialLicense trialLicense : response.trialLicenses()) {
builder.map(trialLicenseAsMap(trialLicense));
}
builder.endArray();
builder.endObject();
ESLicenses.toXContent(response.licenses(), builder);
return new BytesRestResponse(OK, builder);
}
});

View File

@ -34,7 +34,7 @@ public class RestPutLicenseAction extends BaseRestHandler {
public void handleRequest(final RestRequest request, final RestChannel channel, final Client client) {
PutLicenseRequest putLicenseRequest = new PutLicenseRequest();
putLicenseRequest.listenerThreaded(false);
putLicenseRequest.license(request.content().toUtf8());
putLicenseRequest.licenses(request.content().toUtf8());
client.admin().cluster().execute(PutLicenseAction.INSTANCE, putLicenseRequest, new AcknowledgedRestListener<PutLicenseResponse>(channel));
}
}

View File

@ -10,6 +10,7 @@ import org.junit.BeforeClass;
import java.io.IOException;
import java.net.URL;
import java.text.ParseException;
import java.util.Map;
public class AbstractLicensingTestBase {
@ -29,7 +30,7 @@ public class AbstractLicensingTestBase {
return url.toURI().getPath();
}
public String generateSignedLicenses(Map<String, TestUtils.FeatureAttributes> map) throws IOException {
public String generateSignedLicenses(Map<String, TestUtils.FeatureAttributes> map) throws IOException, ParseException {
String licenseString = TestUtils.generateESLicenses(map);
return TestUtils.runLicenseGenerationTool(licenseString, pubKeyPath, priKeyPath);
}

View File

@ -7,15 +7,17 @@ package org.elasticsearch.license;
import org.apache.commons.io.FileUtils;
import org.elasticsearch.license.core.DateUtils;
import org.elasticsearch.license.core.ESLicenses;
import org.elasticsearch.license.core.LicenseBuilders;
import org.elasticsearch.license.core.ESLicense;
import org.elasticsearch.license.licensor.tools.LicenseGeneratorTool;
import org.elasticsearch.license.manager.Utils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import static org.junit.Assert.assertTrue;
@ -51,7 +53,7 @@ public class TestUtils {
}
public static String runLicenseGenerationTool(String licenseInput, String pubKeyPath, String priKeyPath) throws IOException {
public static String runLicenseGenerationTool(String licenseInput, String pubKeyPath, String priKeyPath) throws IOException, ParseException {
String args[] = new String[6];
args[0] = "--license";
args[1] = licenseInput;
@ -63,7 +65,7 @@ public class TestUtils {
return runLicenseGenerationTool(args);
}
public static String runLicenseGenerationTool(String[] args) throws IOException {
public static String runLicenseGenerationTool(String[] args) throws IOException, ParseException {
File temp = File.createTempFile("temp", ".out");
temp.deleteOnExit();
try (FileOutputStream outputStream = new FileOutputStream(temp)) {
@ -72,12 +74,17 @@ public class TestUtils {
return FileUtils.readFileToString(temp);
}
public static void verifyESLicenses(ESLicenses esLicenses, Map<String, FeatureAttributes> featureAttributes) throws ParseException {
assertTrue("Number of feature licenses should be " + featureAttributes.size(), esLicenses.features().size() == featureAttributes.size());
public static void verifyESLicenses(Set<ESLicense> esLicenses, Map<String, FeatureAttributes> featureAttributesMap) throws ParseException {
verifyESLicenses(Utils.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 ESLicenses.ESLicense esLicense = esLicenses.get(featureType);
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().string(), esLicense.type().string().equals(attributes.type));
@ -92,28 +99,27 @@ public class TestUtils {
}
}
//TODO: convert to asserts
public static void isSame(ESLicenses firstLicenses, ESLicenses secondLicenses) {
public static void isSame(Set<ESLicense> firstLicenses, Set<ESLicense> 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();
final Map<String, ESLicense> licenses1 = Utils.reduceAndMap(firstLicenses);
final Map<String, ESLicense> licenses2 = Utils.reduceAndMap(secondLicenses);
// check if the effective licenses have the same feature set
assertTrue("Both licenses should have the same number of features", licenses1.features().equals(licenses2.features()));
assertTrue("Both licenses should have the same number of features", licenses1.size() == licenses2.size());
// for every feature license, check if all the attributes are the same
for (String featureType : licenses1.features()) {
ESLicenses.ESLicense license1 = licenses1.get(featureType);
ESLicenses.ESLicense license2 = licenses2.get(featureType);
for (String featureType : licenses1.keySet()) {
ESLicense license1 = licenses1.get(featureType);
ESLicense license2 = licenses2.get(featureType);
isSame(license1, license2);
}
}
public static void isSame(ESLicenses.ESLicense license1, ESLicenses.ESLicense 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()));

View File

@ -7,14 +7,15 @@ 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.elasticsearch.license.core.LicenseUtils;
import org.junit.Test;
import java.io.IOException;
import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@ -30,7 +31,7 @@ public class LicenseGenerationTests extends AbstractLicensingTestBase {
String licenseOutput = generateSignedLicenses(map);
ESLicenses esLicensesOutput = LicenseUtils.readLicensesFromString(licenseOutput);
Set<ESLicense> esLicensesOutput = ESLicenses.fromSource(licenseOutput);
TestUtils.verifyESLicenses(esLicensesOutput, map);
}
@ -48,7 +49,7 @@ public class LicenseGenerationTests extends AbstractLicensingTestBase {
String licenseOutput = generateSignedLicenses(map);
ESLicenses esLicensesOutput = LicenseUtils.readLicensesFromString(licenseOutput);
Set<ESLicense> esLicensesOutput = ESLicenses.fromSource(licenseOutput);
TestUtils.verifyESLicenses(esLicensesOutput, map);
}

View File

@ -8,16 +8,18 @@ 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.core.LicenseUtils;
import org.elasticsearch.license.licensor.tools.LicenseVerificationTool;
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.Map;
import java.util.Set;
public class LicenseVerificationToolTests extends AbstractLicensingTestBase {
@ -39,12 +41,12 @@ public class LicenseVerificationToolTests extends AbstractLicensingTestBase {
String secondLicenseFile = getAsFilePath(signedLicense);
String effectiveLicenseStr = runLicenseVerificationTool(new String[]{firstLicenseFile, secondLicenseFile});
ESLicenses effectiveLicense = LicenseUtils.readLicensesFromString(effectiveLicenseStr);
Set<ESLicense> esLicensesOutput = 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(effectiveLicense, map);
TestUtils.verifyESLicenses(esLicensesOutput, map);
}
@Test
@ -65,10 +67,10 @@ public class LicenseVerificationToolTests extends AbstractLicensingTestBase {
String secondLicenseFile = getAsFilePath(signedLicense);
String effectiveLicenseStr = runLicenseVerificationTool(new String[]{firstLicenseFile, secondLicenseFile});
ESLicenses effectiveLicense = LicenseUtils.readLicensesFromString(effectiveLicenseStr);
Set<ESLicense> esLicensesOutput = ESLicenses.fromSource(effectiveLicenseStr);
// verify that the effective license contains both feature licenses
TestUtils.verifyESLicenses(effectiveLicense, map);
TestUtils.verifyESLicenses(esLicensesOutput, map);
}
@Test
@ -98,13 +100,13 @@ public class LicenseVerificationToolTests extends AbstractLicensingTestBase {
String secondLicenseFile = getAsFilePath(signedLicense);
String effectiveLicenseStr = runLicenseVerificationTool(new String[]{firstLicenseFile, secondLicenseFile});
ESLicenses effectiveLicense = LicenseUtils.readLicensesFromString(effectiveLicenseStr);
Set<ESLicense> esLicensesOutput = 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(effectiveLicense, map);
TestUtils.verifyESLicenses(esLicensesOutput, map);
}
public static String runLicenseVerificationTool(String[] licenseFiles) throws IOException {
@ -128,7 +130,7 @@ public class LicenseVerificationToolTests extends AbstractLicensingTestBase {
return FileUtils.readFileToString(temp);
}
public String runLicenseGenerationTool(String licenseInput) throws IOException {
public String runLicenseGenerationTool(String licenseInput) throws IOException, ParseException {
return TestUtils.runLicenseGenerationTool(licenseInput, pubKeyPath, priKeyPath);
}

View File

@ -9,8 +9,8 @@ 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.ESLicense;
import org.elasticsearch.license.core.ESLicenses;
import org.elasticsearch.license.core.LicenseBuilders;
import org.elasticsearch.license.licensor.tools.FileBasedESLicenseProvider;
import org.junit.After;
import org.junit.BeforeClass;
@ -19,7 +19,6 @@ import org.junit.Test;
import java.text.ParseException;
import java.util.*;
import static org.elasticsearch.license.core.LicenseUtils.readLicensesFromString;
import static org.junit.Assert.*;
public class LicenseVerificationTests extends AbstractLicensingTestBase {
@ -28,12 +27,12 @@ public class LicenseVerificationTests extends AbstractLicensingTestBase {
private static FileBasedESLicenseProvider esLicenseProvider;
private final static ESLicenses EMPTY_LICENSES = LicenseBuilders.licensesBuilder().build();
private final static Set<ESLicense> EMPTY_LICENSES = new HashSet<>();
@BeforeClass
public static void setupManager() {
esLicenseProvider = new FileBasedESLicenseProvider(LicenseBuilders.licensesBuilder().build());
esLicenseManager = new ESLicenseManager(esLicenseProvider);
esLicenseProvider = new FileBasedESLicenseProvider(EMPTY_LICENSES);
esLicenseManager = new ESLicenseManager();
}
@ -53,13 +52,13 @@ public class LicenseVerificationTests extends AbstractLicensingTestBase {
new TestUtils.FeatureAttributes("shield", "subscription", "platinum", "foo bar Inc.", "elasticsearch", 2, issueDateStr, expiryDateStr);
map.put(TestUtils.SHIELD, featureAttributes);
ESLicenses esLicensesOutput = readLicensesFromString(generateSignedLicenses(map));
Set<ESLicense> esLicensesOutput = ESLicenses.fromSource(generateSignedLicenses(map));
esLicenseProvider.setLicenses(esLicensesOutput);
esLicenseManager.verifyLicenses();
esLicenseManager.verifyLicenses(esLicenseProvider.getEffectiveLicenses());
verifyLicenseManager(esLicenseManager, map);
verifyLicenseManager(esLicenseManager, esLicenseProvider, map);
}
@ -77,15 +76,13 @@ public class LicenseVerificationTests extends AbstractLicensingTestBase {
map.put(TestUtils.SHIELD, shildFeatureAttributes);
map.put(TestUtils.MARVEL, marvelFeatureAttributes);
ESLicenses esLicensesOutput = readLicensesFromString(generateSignedLicenses(map));
Set<ESLicense> esLicensesOutput = ESLicenses.fromSource(generateSignedLicenses(map));
esLicenseProvider.setLicenses(esLicensesOutput);
//printLicense(esLicenseManager.getEffectiveLicenses());
esLicenseManager.verifyLicenses(esLicenseProvider.getEffectiveLicenses());
esLicenseManager.verifyLicenses();
verifyLicenseManager(esLicenseManager, map);
verifyLicenseManager(esLicenseManager, esLicenseProvider, map);
}
@ -134,15 +131,15 @@ public class LicenseVerificationTests extends AbstractLicensingTestBase {
map.put(TestUtils.SHIELD, shildFeatureAttributes);
map.put(TestUtils.MARVEL, marvelFeatureAttributes);
ESLicenses esLicensesOutput = readLicensesFromString(generateSignedLicenses(map));
Set<ESLicense> esLicensesOutput = ESLicenses.fromSource(generateSignedLicenses(map));
esLicenseProvider.setLicenses(esLicensesOutput);
// All validation for shield license should be normal as expected
verifyLicenseManager(esLicenseManager, Collections.singletonMap(TestUtils.SHIELD, shildFeatureAttributes));
verifyLicenseManager(esLicenseManager, esLicenseProvider, Collections.singletonMap(TestUtils.SHIELD, shildFeatureAttributes));
assertFalse("license for marvel should not be valid due to expired expiry date", esLicenseManager.hasLicenseForFeature(TestUtils.MARVEL));
assertFalse("license for marvel should not be valid due to expired expiry date", esLicenseManager.hasLicenseForFeature(TestUtils.MARVEL, esLicenseProvider.getEffectiveLicenses()));
}
@Test
@ -156,47 +153,42 @@ public class LicenseVerificationTests extends AbstractLicensingTestBase {
new TestUtils.FeatureAttributes("shield", "subscription", "platinum", "foo bar Inc.", "elasticsearch", 2, issueDateStr, expiryDateStr);
map.put(TestUtils.SHIELD, featureAttributes);
ESLicenses esLicensesOutput = readLicensesFromString(generateSignedLicenses(map));
Set<ESLicense> esLicensesOutput = ESLicenses.fromSource(generateSignedLicenses(map));
ESLicenses.ESLicense esLicense = esLicensesOutput.get(TestUtils.SHIELD);
ESLicense esLicense = Utils.reduceAndMap(esLicensesOutput).get(TestUtils.SHIELD);
long originalExpiryDate = esLicense.expiryDate();
final ESLicenses.ESLicense tamperedLicense = LicenseBuilders.licenseBuilder(true)
final ESLicense tamperedLicense = ESLicense.builder()
.fromLicense(esLicense)
.expiryDate(esLicense.expiryDate() + 10 * 24 * 60 * 60 * 1000l)
.feature(TestUtils.SHIELD)
.issuer("elasticsqearch")
.build();
ESLicenses tamperedLicenses = LicenseBuilders.licensesBuilder().license(tamperedLicense).build();
try {
esLicenseProvider.setLicenses(tamperedLicenses);
assertTrue("License manager should always report the original (signed) expiry date of: " + originalExpiryDate + " but got: " + esLicenseManager.getExpiryDateForLicense(TestUtils.SHIELD), esLicenseManager.getExpiryDateForLicense(TestUtils.SHIELD) == originalExpiryDate);
esLicenseManager.verifyLicenses();
esLicenseProvider.setLicenses(Collections.singleton(tamperedLicense));
esLicenseManager.verifyLicenses(esLicenseProvider.getEffectiveLicenses());
fail();
} catch (InvalidLicenseException e) {
assertTrue("Exception should contain 'Invalid License' but got: " + e.getMessage(), e.getMessage().contains("Invalid License"));
}
}
public static void verifyLicenseManager(ESLicenseManager esLicenseManager, Map<String, TestUtils.FeatureAttributes> featureAttributeMap) throws ParseException {
public static void verifyLicenseManager(ESLicenseManager esLicenseManager, ESLicenseProvider 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();
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) + " 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));
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.longFromDateString(featureAttributes.issueDate), license.issueDate() == DateUtils.longFromDateString(featureAttributes.issueDate));
assertTrue("License should have expiry date of " + DateUtils.longExpiryDateFromString(featureAttributes.expiryDate) + " got: " + license.expiryDate(), license.expiryDate() == DateUtils.longExpiryDateFromString(featureAttributes.expiryDate));
assertTrue("License should have type of " + featureAttributes.type + " got: " + license.type().string(), license.type() == ESLicense.Type.fromString(featureAttributes.type));
assertTrue("License should have subscription type of " + featureAttributes.subscriptionType, license.subscriptionType() == ESLicense.SubscriptionType.fromString(featureAttributes.subscriptionType));
assertTrue("License should be valid for " + featureType, 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));
assertTrue("License should be valid for " + featureType, esLicenseManager.hasLicenseForFeature(featureType, licenseProvider.getEffectiveLicenses()));
assertTrue("License should be valid for maxNodes = " + (featureAttributes.maxNodes), license.maxNodes() == featureAttributes.maxNodes);
}
}
}

View File

@ -11,9 +11,8 @@ import org.elasticsearch.common.collect.ImmutableSet;
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.core.*;
import org.elasticsearch.license.manager.Utils;
import org.elasticsearch.license.plugin.action.delete.DeleteLicenseRequestBuilder;
import org.elasticsearch.license.plugin.action.delete.DeleteLicenseResponse;
import org.elasticsearch.license.plugin.action.get.GetLicenseRequestBuilder;
@ -28,11 +27,12 @@ import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Paths;
import java.text.ParseException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import static org.elasticsearch.license.core.LicenseUtils.readLicensesFromString;
import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope.SUITE;
import static org.hamcrest.CoreMatchers.equalTo;
@ -82,7 +82,7 @@ public class LicenseTransportTests extends ElasticsearchIntegrationTest {
final GetLicenseResponse getLicenseResponse = getLicenseFuture.get();
assertThat("expected 0 licenses; but got: " + getLicenseResponse.licenses(), getLicenseResponse.licenses().licenses().size(), equalTo(0));
assertThat("expected 0 licenses; but got: " + getLicenseResponse.licenses().size(), getLicenseResponse.licenses().size(), equalTo(0));
}
@Test
@ -97,7 +97,7 @@ public class LicenseTransportTests extends ElasticsearchIntegrationTest {
PutLicenseRequestBuilder putLicenseRequestBuilder = new PutLicenseRequestBuilder(client().admin().cluster());
//putLicenseRequest.license(licenseString);
final ESLicenses putLicenses = LicenseUtils.readLicensesFromString(licenseOutput);
final Set<ESLicense> putLicenses = ESLicenses.fromSource(licenseOutput);
putLicenseRequestBuilder.setLicense(putLicenses);
//LicenseUtils.printLicense(putLicenses);
ensureGreen();
@ -123,8 +123,8 @@ public class LicenseTransportTests extends ElasticsearchIntegrationTest {
final DeleteLicenseResponse deleteLicenseResponse = deleteFuture.get();
assertTrue(deleteLicenseResponse.isAcknowledged());
getLicenseResponse = new GetLicenseRequestBuilder(client().admin().cluster()).execute().get();
TestUtils.isSame(getLicenseResponse.licenses(), LicenseBuilders.licensesBuilder().build());
//getLicenseResponse = new GetLicenseRequestBuilder(client().admin().cluster()).execute().get();
//TestUtils.isSame(getLicenseResponse.licenses(), LicenseBuilders.licensesBuilder().build());
}
@Test
@ -136,17 +136,19 @@ public class LicenseTransportTests extends ElasticsearchIntegrationTest {
String licenseString = TestUtils.generateESLicenses(map);
String licenseOutput = TestUtils.runLicenseGenerationTool(licenseString, pubKeyPath, priKeyPath);
ESLicenses esLicenses = readLicensesFromString(licenseOutput);
Set<ESLicense> esLicenses = ESLicenses.fromSource(licenseOutput);
ESLicenses.ESLicense esLicense = esLicenses.get(TestUtils.SHIELD);
ESLicenses.ESLicense tamperedLicense = LicenseBuilders.licenseBuilder(true)
ESLicense esLicense = Utils.reduceAndMap(esLicenses).get(TestUtils.SHIELD);
final ESLicense tamperedLicense = ESLicense.builder()
.fromLicense(esLicense)
.expiryDate(esLicense.expiryDate() + 10 * 24 * 60 * 60 * 1000l)
.issuer("elasticsearch")
.feature(TestUtils.SHIELD)
.issuer("elasticsqearch")
.build();
PutLicenseRequestBuilder builder = new PutLicenseRequestBuilder(client().admin().cluster());
builder.setLicense(LicenseBuilders.licensesBuilder().license(tamperedLicense).build());
builder.setLicense(Collections.singleton(tamperedLicense));
final ListenableActionFuture<PutLicenseResponse> execute = builder.execute();

View File

@ -15,10 +15,9 @@ import org.elasticsearch.common.Nullable;
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.core.*;
import org.elasticsearch.license.manager.ESLicenseManager;
import org.elasticsearch.license.manager.Utils;
import org.elasticsearch.license.plugin.action.put.PutLicenseRequest;
import org.elasticsearch.license.plugin.core.*;
import org.elasticsearch.test.ElasticsearchIntegrationTest;
@ -31,9 +30,7 @@ import org.junit.Test;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
@ -99,7 +96,7 @@ public class LicensesServiceTests extends ElasticsearchIntegrationTest {
@Test
public void testEmptySignedLicenseCheck() {
LicensesManagerService licensesManagerService = licensesManagerService();
assertTrue(LicensesStatus.VALID == licensesManagerService.checkLicenses(LicenseBuilders.licensesBuilder().build()));
assertTrue(LicensesStatus.VALID == licensesManagerService.checkLicenses(new HashSet<ESLicense>()));
}
@Test
@ -112,19 +109,20 @@ public class LicensesServiceTests extends ElasticsearchIntegrationTest {
map.put(TestUtils.SHIELD, featureAttributes);
String licenseString = TestUtils.generateESLicenses(map);
String licenseOutput = TestUtils.runLicenseGenerationTool(licenseString, pubKeyPath, priKeyPath);
ESLicenses licenses = LicenseUtils.readLicensesFromString(licenseOutput);
Set<ESLicense> licenses = ESLicenses.fromSource(licenseOutput);
assertTrue(LicensesStatus.VALID == licensesManagerService.checkLicenses(licenses));
ESLicenses.ESLicense tamperedLicense = LicenseBuilders.licenseBuilder(true)
.fromLicense(licenses.get(TestUtils.SHIELD))
.expiryDate(licenses.get(TestUtils.SHIELD).expiryDate() + 5 * 24 * 60 * 60 * 1000l)
.issuer("elasticsearch")
ESLicense esLicense = Utils.reduceAndMap(licenses).get(TestUtils.SHIELD);
final ESLicense tamperedLicense = ESLicense.builder()
.fromLicense(esLicense)
.expiryDate(esLicense.expiryDate() + 10 * 24 * 60 * 60 * 1000l)
.feature(TestUtils.SHIELD)
.issuer("elasticsqearch")
.build();
ESLicenses tamperedLicenses = LicenseBuilders.licensesBuilder().license(tamperedLicense).build();
assertTrue(LicensesStatus.INVALID == licensesManagerService.checkLicenses(tamperedLicenses));
assertTrue(LicensesStatus.INVALID == licensesManagerService.checkLicenses(Collections.singleton(tamperedLicense)));
}
@Test
@ -135,12 +133,12 @@ public class LicensesServiceTests extends ElasticsearchIntegrationTest {
map.put(TestUtils.SHIELD, featureAttributes1);
String licenseString = TestUtils.generateESLicenses(map);
String licenseOutput = TestUtils.runLicenseGenerationTool(licenseString, pubKeyPath, priKeyPath);
ESLicenses licenses = LicenseUtils.readLicensesFromString(licenseOutput);
Set<ESLicense> licenses = ESLicenses.fromSource(licenseOutput);
LicensesManagerService licensesManagerService = licensesManagerService();
ESLicenseManager esLicenseManager = ((LicensesService) licensesManagerService).getEsLicenseManager();
final CountDownLatch latch1 = new CountDownLatch(1);
licensesManagerService.registerLicenses(new LicensesService.PutLicenseRequestHolder(new PutLicenseRequest().license(licenses), "test"), new ActionListener<ClusterStateUpdateResponse>() {
licensesManagerService.registerLicenses(new LicensesService.PutLicenseRequestHolder(new PutLicenseRequest().licenses(licenses), "test"), new ActionListener<ClusterStateUpdateResponse>() {
@Override
public void onResponse(ClusterStateUpdateResponse clusterStateUpdateResponse) {
if (clusterStateUpdateResponse.isAcknowledged()) {
@ -156,7 +154,7 @@ public class LicensesServiceTests extends ElasticsearchIntegrationTest {
latch1.await();
LicensesMetaData metaData = clusterService().state().metaData().custom(LicensesMetaData.TYPE);
ESLicenses metaDataLicense = esLicenseManager.fromSignatures(metaData.getSignatures());
Set<ESLicense> metaDataLicense = esLicenseManager.fromSignatures(metaData.getSignatures());
TestUtils.isSame(licenses, metaDataLicense);
@ -165,9 +163,9 @@ public class LicensesServiceTests extends ElasticsearchIntegrationTest {
map.put(TestUtils.SHIELD, featureAttributes2);
licenseString = TestUtils.generateESLicenses(map);
licenseOutput = TestUtils.runLicenseGenerationTool(licenseString, pubKeyPath, priKeyPath);
ESLicenses licenses2 = LicenseUtils.readLicensesFromString(licenseOutput);
Set<ESLicense> licenses2 = ESLicenses.fromSource(licenseOutput);
final CountDownLatch latch2 = new CountDownLatch(1);
licensesManagerService.registerLicenses(new LicensesService.PutLicenseRequestHolder(new PutLicenseRequest().license(licenses2), "test"), new ActionListener<ClusterStateUpdateResponse>() {
licensesManagerService.registerLicenses(new LicensesService.PutLicenseRequestHolder(new PutLicenseRequest().licenses(licenses2), "test"), new ActionListener<ClusterStateUpdateResponse>() {
@Override
public void onResponse(ClusterStateUpdateResponse clusterStateUpdateResponse) {
if (clusterStateUpdateResponse.isAcknowledged()) {
@ -270,11 +268,11 @@ public class LicensesServiceTests extends ElasticsearchIntegrationTest {
map.put(TestUtils.SHIELD, featureAttributes1);
String licenseString = TestUtils.generateESLicenses(map);
String licenseOutput = TestUtils.runLicenseGenerationTool(licenseString, pubKeyPath, priKeyPath);
ESLicenses licenses = LicenseUtils.readLicensesFromString(licenseOutput);
Set<ESLicense> licenses = ESLicenses.fromSource(licenseOutput);
LicensesManagerService licensesManagerService = licensesManagerService();
final CountDownLatch latch1 = new CountDownLatch(1);
licensesManagerService.registerLicenses(new LicensesService.PutLicenseRequestHolder(new PutLicenseRequest().license(licenses), "test"), new ActionListener<ClusterStateUpdateResponse>() {
licensesManagerService.registerLicenses(new LicensesService.PutLicenseRequestHolder(new PutLicenseRequest().licenses(licenses), "test"), new ActionListener<ClusterStateUpdateResponse>() {
@Override
public void onResponse(ClusterStateUpdateResponse clusterStateUpdateResponse) {
if (clusterStateUpdateResponse.isAcknowledged()) {