major refactor: make ESLicense more consistent; restructure ESLicenseManager
Original commit: elastic/x-pack-elasticsearch@cb60bfb539
This commit is contained in:
parent
b9d92bae5a
commit
e59cf4538a
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
*/
|
||||
package org.elasticsearch.license.plugin.core;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.transport.RemoteTransportException;
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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()));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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()) {
|
||||
|
|
Loading…
Reference in New Issue