Skip to content

Detect old trial licenses and mimic behaviour #32209

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jul 20, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ public LicenseService(Settings settings, ClusterService clusterService, Clock cl
this.scheduler = new SchedulerEngine(clock);
this.licenseState = licenseState;
this.operationModeFileWatcher = new OperationModeFileWatcher(resourceWatcherService,
XPackPlugin.resolveConfigFile(env, "license_mode"), logger, () -> updateLicenseState(getLicense()));
XPackPlugin.resolveConfigFile(env, "license_mode"), logger,
() -> updateLicenseState(getLicensesMetaData()));
this.scheduler.register(this);
populateExpirationCallbacks();
}
Expand Down Expand Up @@ -265,11 +266,11 @@ private static TimeValue days(int days) {

@Override
public void triggered(SchedulerEngine.Event event) {
final LicensesMetaData licensesMetaData = clusterService.state().metaData().custom(LicensesMetaData.TYPE);
final LicensesMetaData licensesMetaData = getLicensesMetaData();
if (licensesMetaData != null) {
final License license = licensesMetaData.getLicense();
if (event.getJobName().equals(LICENSE_JOB)) {
updateLicenseState(license);
updateLicenseState(license, licensesMetaData.getMostRecentTrialVersion());
} else if (event.getJobName().startsWith(ExpirationCallback.EXPIRATION_JOB_PREFIX)) {
expirationCallbacks.stream()
.filter(expirationCallback -> expirationCallback.getId().equals(event.getJobName()))
Expand Down Expand Up @@ -311,6 +312,10 @@ public License getLicense() {
return license == LicensesMetaData.LICENSE_TOMBSTONE ? null : license;
}

private LicensesMetaData getLicensesMetaData() {
return this.clusterService.state().metaData().custom(LicensesMetaData.TYPE);
}

void startTrialLicense(PostStartTrialRequest request, final ActionListener<PostStartTrialResponse> listener) {
if (VALID_TRIAL_TYPES.contains(request.getType()) == false) {
throw new IllegalArgumentException("Cannot start trial of type [" + request.getType() + "]. Valid trial types are "
Expand Down Expand Up @@ -422,10 +427,16 @@ public void clusterChanged(ClusterChangedEvent event) {
}
}

protected void updateLicenseState(final License license) {
private void updateLicenseState(LicensesMetaData licensesMetaData) {
if (licensesMetaData != null) {
updateLicenseState(getLicense(licensesMetaData), licensesMetaData.getMostRecentTrialVersion());
}
}

protected void updateLicenseState(final License license, Version mostRecentTrialVersion) {
if (license == LicensesMetaData.LICENSE_TOMBSTONE) {
// implies license has been explicitly deleted
licenseState.update(License.OperationMode.MISSING, false);
licenseState.update(License.OperationMode.MISSING, false, mostRecentTrialVersion);
return;
}
if (license != null) {
Expand All @@ -438,7 +449,7 @@ protected void updateLicenseState(final License license) {
// date that is near Long.MAX_VALUE
active = time >= license.issueDate() && time - GRACE_PERIOD_DURATION.getMillis() < license.expiryDate();
}
licenseState.update(license.operationMode(), active);
licenseState.update(license.operationMode(), active, mostRecentTrialVersion);

if (active) {
if (time < license.expiryDate()) {
Expand Down Expand Up @@ -480,7 +491,7 @@ private void onUpdate(final LicensesMetaData currentLicensesMetaData) {
logger.info("license [{}] mode [{}] - valid", license.uid(),
license.operationMode().name().toLowerCase(Locale.ROOT));
}
updateLicenseState(license);
updateLicenseState(license, currentLicensesMetaData.getMostRecentTrialVersion());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
*/
package org.elasticsearch.license;

import org.elasticsearch.Version;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.logging.LoggerMessageFormat;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.License.OperationMode;
import org.elasticsearch.xpack.core.XPackField;
Expand Down Expand Up @@ -266,6 +269,7 @@ private static class Status {
private final List<Runnable> listeners = new CopyOnWriteArrayList<>();
private final boolean isSecurityEnabled;
private final boolean isSecurityExplicitlyEnabled;
private volatile boolean isSecurityEnabledByTrialVersion;

public XPackLicenseState(Settings settings) {
this.isSecurityEnabled = XPackSettings.SECURITY_ENABLED.get(settings);
Expand All @@ -274,11 +278,30 @@ public XPackLicenseState(Settings settings) {
// setting is not explicitly set
this.isSecurityExplicitlyEnabled = isSecurityEnabled &&
(settings.hasValue(XPackSettings.SECURITY_ENABLED.getKey()) || XPackSettings.TRANSPORT_SSL_ENABLED.get(settings));
this.isSecurityEnabledByTrialVersion = false;
}

/** Updates the current state of the license, which will change what features are available. */
void update(OperationMode mode, boolean active) {
/**
* Updates the current state of the license, which will change what features are available.
*
* @param mode The mode (type) of the current license.
* @param active True if the current license exists and is within its allowed usage period; false if it is expired or missing.
* @param mostRecentTrialVersion If this cluster has, at some point commenced a trial, the most recent version on which they did that.
* May be {@code null} if they have never generated a trial license on this cluster, or the most recent
* trial was prior to this metadata being tracked (6.1)
*/
void update(OperationMode mode, boolean active, @Nullable Version mostRecentTrialVersion) {
status = new Status(mode, active);
if (isSecurityEnabled == true && isSecurityExplicitlyEnabled == false && mode == OperationMode.TRIAL
&& isSecurityEnabledByTrialVersion == false) {
// Before 6.3, Trial licenses would default having security enabled.
// If this license was generated before that version, then treat it as if security is explicitly enabled
if (mostRecentTrialVersion == null || mostRecentTrialVersion.before(Version.V_6_3_0)) {
Loggers.getLogger(getClass()).info("Automatically enabling security for older trial license ({})",
mostRecentTrialVersion == null ? "[pre 6.1.0]" : mostRecentTrialVersion.toString());
isSecurityEnabledByTrialVersion = true;
}
}
listeners.forEach(Runnable::run);
}

Expand Down Expand Up @@ -587,6 +610,6 @@ public boolean isSecurityAvailable() {

public boolean isSecurityEnabled() {
final OperationMode mode = status.mode;
return mode == OperationMode.TRIAL ? isSecurityExplicitlyEnabled : isSecurityEnabled;
return mode == OperationMode.TRIAL ? (isSecurityExplicitlyEnabled || isSecurityEnabledByTrialVersion) : isSecurityEnabled;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
package org.elasticsearch.license;

import com.carrotsearch.randomizedtesting.RandomizedTest;
import org.elasticsearch.Version;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.common.Strings;
Expand Down Expand Up @@ -353,20 +354,22 @@ public void onFailure(Exception e) {
public static class AssertingLicenseState extends XPackLicenseState {
public final List<License.OperationMode> modeUpdates = new ArrayList<>();
public final List<Boolean> activeUpdates = new ArrayList<>();
public final List<Version> trialVersionUpdates = new ArrayList<>();

public AssertingLicenseState() {
super(Settings.EMPTY);
}

@Override
void update(License.OperationMode mode, boolean active) {
void update(License.OperationMode mode, boolean active, Version mostRecentTrialVersion) {
modeUpdates.add(mode);
activeUpdates.add(active);
trialVersionUpdates.add(mostRecentTrialVersion);
}
}

/**
* A license state that makes the {@link #update(License.OperationMode, boolean)}
* A license state that makes the {@link #update(License.OperationMode, boolean, Version)}
* method public for use in tests.
*/
public static class UpdatableLicenseState extends XPackLicenseState {
Expand All @@ -379,8 +382,8 @@ public UpdatableLicenseState(Settings settings) {
}

@Override
public void update(License.OperationMode mode, boolean active) {
super.update(mode, active);
public void update(License.OperationMode mode, boolean active, Version mostRecentTrialVersion) {
super.update(mode, active, mostRecentTrialVersion);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
*/
package org.elasticsearch.license;

import org.elasticsearch.Version;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.license.License.OperationMode;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.VersionUtils;
import org.elasticsearch.xpack.core.XPackField;
import org.elasticsearch.xpack.core.XPackSettings;

Expand All @@ -31,7 +33,7 @@ public class XPackLicenseStateTests extends ESTestCase {
/** Creates a license state with the given license type and active state, and checks the given method returns expected. */
void assertAllowed(OperationMode mode, boolean active, Predicate<XPackLicenseState> predicate, boolean expected) {
XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY);
licenseState.update(mode, active);
licenseState.update(mode, active, null);
assertEquals(expected, predicate.test(licenseState));
}

Expand Down Expand Up @@ -102,7 +104,7 @@ public void testSecurityDefaults() {
public void testSecurityBasic() {
XPackLicenseState licenseState = new XPackLicenseState(randomFrom(Settings.EMPTY,
Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build()));
licenseState.update(BASIC, true);
licenseState.update(BASIC, true, null);

assertThat(licenseState.isAuthAllowed(), is(false));
assertThat(licenseState.isIpFilteringAllowed(), is(false));
Expand All @@ -116,7 +118,7 @@ public void testSecurityBasic() {
public void testSecurityBasicExpired() {
XPackLicenseState licenseState = new XPackLicenseState(randomFrom(Settings.EMPTY,
Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build()));
licenseState.update(BASIC, false);
licenseState.update(BASIC, false, null);

assertThat(licenseState.isAuthAllowed(), is(false));
assertThat(licenseState.isIpFilteringAllowed(), is(false));
Expand All @@ -130,7 +132,7 @@ public void testSecurityBasicExpired() {
public void testSecurityStandard() {
XPackLicenseState licenseState = new XPackLicenseState(randomFrom(Settings.EMPTY,
Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build()));
licenseState.update(STANDARD, true);
licenseState.update(STANDARD, true, null);

assertThat(licenseState.isAuthAllowed(), is(true));
assertThat(licenseState.isIpFilteringAllowed(), is(false));
Expand All @@ -144,7 +146,7 @@ public void testSecurityStandard() {
public void testSecurityStandardExpired() {
XPackLicenseState licenseState = new XPackLicenseState(randomFrom(Settings.EMPTY,
Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build()));
licenseState.update(STANDARD, false);
licenseState.update(STANDARD, false, null);

assertThat(licenseState.isAuthAllowed(), is(true));
assertThat(licenseState.isIpFilteringAllowed(), is(false));
Expand All @@ -158,7 +160,7 @@ public void testSecurityStandardExpired() {
public void testSecurityGold() {
XPackLicenseState licenseState = new XPackLicenseState(randomFrom(Settings.EMPTY,
Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build()));
licenseState.update(GOLD, true);
licenseState.update(GOLD, true, null);

assertThat(licenseState.isAuthAllowed(), is(true));
assertThat(licenseState.isIpFilteringAllowed(), is(true));
Expand All @@ -172,7 +174,7 @@ public void testSecurityGold() {
public void testSecurityGoldExpired() {
XPackLicenseState licenseState = new XPackLicenseState(randomFrom(Settings.EMPTY,
Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build()));
licenseState.update(GOLD, false);
licenseState.update(GOLD, false, null);

assertThat(licenseState.isAuthAllowed(), is(true));
assertThat(licenseState.isIpFilteringAllowed(), is(true));
Expand All @@ -186,7 +188,7 @@ public void testSecurityGoldExpired() {
public void testSecurityPlatinum() {
XPackLicenseState licenseState = new XPackLicenseState(randomFrom(Settings.EMPTY,
Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build()));
licenseState.update(PLATINUM, true);
licenseState.update(PLATINUM, true, null);

assertThat(licenseState.isAuthAllowed(), is(true));
assertThat(licenseState.isIpFilteringAllowed(), is(true));
Expand All @@ -200,7 +202,7 @@ public void testSecurityPlatinum() {
public void testSecurityPlatinumExpired() {
XPackLicenseState licenseState = new XPackLicenseState(randomFrom(Settings.EMPTY,
Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build()));
licenseState.update(PLATINUM, false);
licenseState.update(PLATINUM, false, null);

assertThat(licenseState.isAuthAllowed(), is(true));
assertThat(licenseState.isIpFilteringAllowed(), is(true));
Expand All @@ -211,6 +213,34 @@ public void testSecurityPlatinumExpired() {
assertThat(licenseState.isCustomRoleProvidersAllowed(), is(false));
}

public void testNewTrialDefaultsSecurityOff() {
XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY);
licenseState.update(TRIAL, true, VersionUtils.randomVersionBetween(random(), Version.V_6_3_0, Version.CURRENT));

assertThat(licenseState.isSecurityEnabled(), is(false));
assertThat(licenseState.isAuthAllowed(), is(true));
assertThat(licenseState.isIpFilteringAllowed(), is(true));
assertThat(licenseState.isAuditingAllowed(), is(true));
assertThat(licenseState.isStatsAndHealthAllowed(), is(true));
assertThat(licenseState.isDocumentAndFieldLevelSecurityAllowed(), is(true));
assertThat(licenseState.allowedRealmType(), is(XPackLicenseState.AllowedRealmType.ALL));
assertThat(licenseState.isCustomRoleProvidersAllowed(), is(true));
}

public void testOldTrialDefaultsSecurityOn() {
XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY);
licenseState.update(TRIAL, true, rarely() ? null : VersionUtils.randomVersionBetween(random(), Version.V_5_6_0, Version.V_6_2_4));

assertThat(licenseState.isSecurityEnabled(), is(true));
assertThat(licenseState.isAuthAllowed(), is(true));
assertThat(licenseState.isIpFilteringAllowed(), is(true));
assertThat(licenseState.isAuditingAllowed(), is(true));
assertThat(licenseState.isStatsAndHealthAllowed(), is(true));
assertThat(licenseState.isDocumentAndFieldLevelSecurityAllowed(), is(true));
assertThat(licenseState.allowedRealmType(), is(XPackLicenseState.AllowedRealmType.ALL));
assertThat(licenseState.isCustomRoleProvidersAllowed(), is(true));
}

public void testSecurityAckBasicToNotGoldOrStandard() {
OperationMode toMode = randomFrom(OperationMode.values(), mode -> mode != GOLD && mode != STANDARD);
assertAckMesssages(XPackField.SECURITY, BASIC, toMode, 0);
Expand Down Expand Up @@ -354,63 +384,63 @@ public void testSqlDefaults() {

public void testSqlBasic() {
XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY);
licenseState.update(BASIC, true);
licenseState.update(BASIC, true, null);

assertThat(licenseState.isSqlAllowed(), is(true));
assertThat(licenseState.isJdbcAllowed(), is(false));
}

public void testSqlBasicExpired() {
XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY);
licenseState.update(BASIC, false);
licenseState.update(BASIC, false, null);

assertThat(licenseState.isSqlAllowed(), is(false));
assertThat(licenseState.isJdbcAllowed(), is(false));
}

public void testSqlStandard() {
XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY);
licenseState.update(STANDARD, true);
licenseState.update(STANDARD, true, null);

assertThat(licenseState.isSqlAllowed(), is(true));
assertThat(licenseState.isJdbcAllowed(), is(false));
}

public void testSqlStandardExpired() {
XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY);
licenseState.update(STANDARD, false);
licenseState.update(STANDARD, false, null);

assertThat(licenseState.isSqlAllowed(), is(false));
assertThat(licenseState.isJdbcAllowed(), is(false));
}

public void testSqlGold() {
XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY);
licenseState.update(GOLD, true);
licenseState.update(GOLD, true, null);

assertThat(licenseState.isSqlAllowed(), is(true));
assertThat(licenseState.isJdbcAllowed(), is(false));
}

public void testSqlGoldExpired() {
XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY);
licenseState.update(GOLD, false);
licenseState.update(GOLD, false, null);

assertThat(licenseState.isSqlAllowed(), is(false));
assertThat(licenseState.isJdbcAllowed(), is(false));
}

public void testSqlPlatinum() {
XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY);
licenseState.update(PLATINUM, true);
licenseState.update(PLATINUM, true, null);

assertThat(licenseState.isSqlAllowed(), is(true));
assertThat(licenseState.isJdbcAllowed(), is(true));
}

public void testSqlPlatinumExpired() {
XPackLicenseState licenseState = new XPackLicenseState(Settings.EMPTY);
licenseState.update(PLATINUM, false);
licenseState.update(PLATINUM, false, null);

assertThat(licenseState.isSqlAllowed(), is(false));
assertThat(licenseState.isJdbcAllowed(), is(false));
Expand Down
Loading