From 169c326a17d0b7db6ef1dce07bd290d56d23307c Mon Sep 17 00:00:00 2001 From: Lyudmila Fokina <35386883+BigPandaToo@users.noreply.github.com> Date: Fri, 4 Dec 2020 17:41:10 +0100 Subject: [PATCH] Adding a warning header when a license is about to expire (#64948) * This change adds a warning header when a license is about to expire Resolves #60562 * This change adds realm name of the realm used to perform authentication to the responses of _security/oidc/authenticate and _security/oidc/authenticate APIs Resolves #53161 * Adding doc for the new API introduced by #64517 - /_security/saml/metadata/{realm} Related to #49018 * Adding a warning header when a license is about to expire Resolves #60562 * Addressing the PR feedback * Switching back to adding the header during featureCheck to allow warnings when authentication is disabled as well. Adding filterHeader implementation to SecurityRestFilter exception handling to remove all the warnings if authentication fails. * Changing the wording for "expired" message to be consistent with the log messages; changing "today" calculation; adding a test case for failing authN to make sure we remove the warning header * Small changes in the way we verify header in tests * Nit changes Co-authored-by: Elastic Machine --- .../http/DefaultRestChannel.java | 2 +- .../org/elasticsearch/rest/RestResponse.java | 4 + .../elasticsearch/license/LicenseService.java | 11 +- .../license/LicenseStateListener.java | 2 +- .../license/XPackLicenseState.java | 40 ++++++- .../org/elasticsearch/license/TestUtils.java | 10 +- .../license/XPackLicenseStateTests.java | 56 +++++----- .../test/SecuritySettingsSourceField.java | 1 + .../rest/action/IdpBaseRestHandlerTests.java | 2 +- .../license/MachineLearningLicensingIT.java | 4 +- .../elasticsearch/license/LicensingTests.java | 105 +++++++++++++++++- .../security/rest/SecurityRestFilter.java | 10 ++ .../xpack/security/SecurityTests.java | 8 +- .../support/SecondaryAuthenticatorTests.java | 2 +- .../authz/store/CompositeRolesStoreTests.java | 9 +- .../action/saml/SamlBaseRestHandlerTests.java | 2 +- .../spatial/LocalStateSpatialPlugin.java | 2 +- .../xpack/spatial/SpatialPluginTests.java | 2 +- 18 files changed, 216 insertions(+), 56 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/http/DefaultRestChannel.java b/server/src/main/java/org/elasticsearch/http/DefaultRestChannel.java index b2e7ad9e8baf2..b72777d0c4bad 100644 --- a/server/src/main/java/org/elasticsearch/http/DefaultRestChannel.java +++ b/server/src/main/java/org/elasticsearch/http/DefaultRestChannel.java @@ -123,7 +123,7 @@ public void sendResponse(RestResponse restResponse) { // Add all custom headers addCustomHeaders(httpResponse, restResponse.getHeaders()); - addCustomHeaders(httpResponse, threadContext.getResponseHeaders()); + addCustomHeaders(httpResponse, restResponse.filterHeaders(threadContext.getResponseHeaders())); // If our response doesn't specify a content-type header, set one setHeaderField(httpResponse, CONTENT_TYPE, restResponse.contentType(), false); diff --git a/server/src/main/java/org/elasticsearch/rest/RestResponse.java b/server/src/main/java/org/elasticsearch/rest/RestResponse.java index d0d6fa752d68e..60a6dc4895676 100644 --- a/server/src/main/java/org/elasticsearch/rest/RestResponse.java +++ b/server/src/main/java/org/elasticsearch/rest/RestResponse.java @@ -89,4 +89,8 @@ public Map> getHeaders() { return customHeaders; } } + + public Map> filterHeaders(Map> headers) { + return headers; + } } diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/LicenseService.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/LicenseService.java index ea7294c179b14..1dc07cf76dd0e 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/LicenseService.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/LicenseService.java @@ -82,6 +82,11 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste */ static final TimeValue GRACE_PERIOD_DURATION = days(7); + /** + * Period before the license expires when warning starts being added to the response header + */ + static final TimeValue LICENSE_EXPIRATION_WARNING_PERIOD = days(7); + public static final long BASIC_SELF_GENERATED_LICENSE_EXPIRATION_MILLIS = XPackInfoResponse.BASIC_SELF_GENERATED_LICENSE_EXPIRATION_MILLIS; @@ -125,7 +130,7 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste public static final String LICENSE_JOB = "licenseJob"; - private static final DateFormatter DATE_FORMATTER = DateFormatter.forPattern("EEEE, MMMM dd, yyyy"); + public static final DateFormatter DATE_FORMATTER = DateFormatter.forPattern("EEEE, MMMM dd, yyyy"); private static final String ACKNOWLEDGEMENT_HEADER = "This license update requires acknowledgement. To acknowledge the license, " + "please read the following messages and update the license again, this time with the \"acknowledge=true\" parameter:"; @@ -476,7 +481,7 @@ private void updateLicenseState(LicensesMetadata licensesMetadata) { 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, mostRecentTrialVersion); + licenseState.update(License.OperationMode.MISSING, false, license.expiryDate(), mostRecentTrialVersion); return; } if (license != null) { @@ -489,7 +494,7 @@ protected void updateLicenseState(final License license, Version mostRecentTrial // date that is near Long.MAX_VALUE active = time >= license.issueDate() && time - GRACE_PERIOD_DURATION.getMillis() < license.expiryDate(); } - licenseState.update(license.operationMode(), active, mostRecentTrialVersion); + licenseState.update(license.operationMode(), active, license.expiryDate(), mostRecentTrialVersion); if (active) { if (time < license.expiryDate()) { diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/LicenseStateListener.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/LicenseStateListener.java index ef3302613c333..fb909138741b8 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/LicenseStateListener.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/LicenseStateListener.java @@ -15,7 +15,7 @@ public interface LicenseStateListener { /** - * Callback when the license state changes. See {@link XPackLicenseState#update(License.OperationMode, boolean, Version)}. + * Callback when the license state changes. See {@link XPackLicenseState#update(License.OperationMode, boolean, long, Version)}. */ void licenseStateChanged(); diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/XPackLicenseState.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/XPackLicenseState.java index bed17458cb953..e91ed5cf5c3e5 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/XPackLicenseState.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/XPackLicenseState.java @@ -8,6 +8,8 @@ import org.elasticsearch.Version; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.Strings; +import org.elasticsearch.common.SuppressForbidden; +import org.elasticsearch.common.logging.HeaderWarning; import org.elasticsearch.common.logging.LoggerMessageFormat; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.license.License.OperationMode; @@ -19,10 +21,12 @@ import java.util.EnumMap; import java.util.LinkedHashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.LongAccumulator; import java.util.function.BiFunction; import java.util.function.Function; @@ -30,6 +34,8 @@ import java.util.function.Predicate; import java.util.stream.Collectors; +import static org.elasticsearch.license.LicenseService.LICENSE_EXPIRATION_WARNING_PERIOD; + /** * A holder for the current state of the license for all xpack features. */ @@ -399,7 +405,7 @@ private static boolean isBasic(OperationMode mode) { return mode == OperationMode.BASIC; } - /** A wrapper for the license mode and state, to allow atomically swapping. */ + /** A wrapper for the license mode, state, and expiration date, to allow atomically swapping. */ private static class Status { /** The current "mode" of the license (ie license type). */ @@ -408,9 +414,13 @@ private static class Status { /** True if the license is active, or false if it is expired. */ final boolean active; - Status(OperationMode mode, boolean active) { + /** The current expiration date of the license; Long.MAX_VALUE if not available yet. */ + final long licenseExpiryDate; + + Status(OperationMode mode, boolean active, long licenseExpiryDate) { this.mode = mode; this.active = active; + this.licenseExpiryDate = licenseExpiryDate; } } @@ -424,7 +434,7 @@ private static class Status { // XPackLicenseState. However, if status is read multiple times in a method, it can change in between // reads. Methods should use `executeAgainstStatus` and `checkAgainstStatus` to ensure that the status // is only read once. - private volatile Status status = new Status(OperationMode.TRIAL, true); + private volatile Status status = new Status(OperationMode.TRIAL, true, Long.MAX_VALUE); public XPackLicenseState(Settings settings, LongSupplier epochMillisProvider) { this.listeners = new CopyOnWriteArrayList<>(); @@ -472,12 +482,13 @@ private boolean checkAgainstStatus(Predicate statusPredicate) { * * @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 expirationDate Expiration date of the current license. * @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); + void update(OperationMode mode, boolean active, long expirationDate, @Nullable Version mostRecentTrialVersion) { + status = new Status(mode, active, expirationDate); listeners.forEach(LicenseStateListener::licenseStateChanged); } @@ -513,12 +524,26 @@ boolean isActive() { /** * Checks whether the given feature is allowed, tracking the last usage time. */ + @SuppressForbidden(reason = "Argument to Math.abs() is definitely not Long.MIN_VALUE") public boolean checkFeature(Feature feature) { boolean allowed = isAllowed(feature); LongAccumulator maxEpochAccumulator = lastUsed.get(feature); + final long licenseExpiryDate = getLicenseExpiryDate(); + final long diff = licenseExpiryDate - System.currentTimeMillis(); if (maxEpochAccumulator != null) { maxEpochAccumulator.accumulate(epochMillisProvider.getAsLong()); } + + if (feature.minimumOperationMode.compareTo(OperationMode.BASIC) > 0 && + LICENSE_EXPIRATION_WARNING_PERIOD.getMillis() > diff) { + final long days = TimeUnit.MILLISECONDS.toDays(diff); + final String expiryMessage = (days == 0 && diff > 0)? "expires today": + (diff > 0? String.format(Locale.ROOT, "will expire in [%d] days", days): + String.format(Locale.ROOT, "expired on [%s]", LicenseService.DATE_FORMATTER.formatMillis(licenseExpiryDate))); + HeaderWarning.addWarning("Your license {}. " + + "Contact your administrator or update your license for continued use of features", expiryMessage); + } + return allowed; } @@ -635,6 +660,11 @@ public boolean isAllowedByLicense(OperationMode minimumMode, boolean needActive) }); } + /** Return the current license expiration date. */ + public long getLicenseExpiryDate() { + return executeAgainstStatus(status -> status.licenseExpiryDate); + } + /** * A convenient method to test whether a feature is by license status. * @see #isAllowedByLicense(OperationMode, boolean) diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/license/TestUtils.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/license/TestUtils.java index 27222105f3e39..6a0d0f34c7f34 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/license/TestUtils.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/license/TestUtils.java @@ -360,21 +360,23 @@ public static class AssertingLicenseState extends XPackLicenseState { public final List modeUpdates = new ArrayList<>(); public final List activeUpdates = new ArrayList<>(); public final List trialVersionUpdates = new ArrayList<>(); + public final List expirationDateUpdates = new ArrayList<>(); public AssertingLicenseState() { super(Settings.EMPTY, () -> 0); } @Override - void update(License.OperationMode mode, boolean active, Version mostRecentTrialVersion) { + void update(License.OperationMode mode, boolean active, long expirationDate, Version mostRecentTrialVersion) { modeUpdates.add(mode); activeUpdates.add(active); + expirationDateUpdates.add(expirationDate); trialVersionUpdates.add(mostRecentTrialVersion); } } /** - * A license state that makes the {@link #update(License.OperationMode, boolean, Version)} + * A license state that makes the {@link #update(License.OperationMode, boolean, long, Version)} * method public for use in tests. */ public static class UpdatableLicenseState extends XPackLicenseState { @@ -387,8 +389,8 @@ public UpdatableLicenseState(Settings settings) { } @Override - public void update(License.OperationMode mode, boolean active, Version mostRecentTrialVersion) { - super.update(mode, active, mostRecentTrialVersion); + public void update(License.OperationMode mode, boolean active, long expirationDate, Version mostRecentTrialVersion) { + super.update(mode, active, expirationDate, mostRecentTrialVersion); } } diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/license/XPackLicenseStateTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/license/XPackLicenseStateTests.java index 4aa2ebbb1e9d6..ca3a70011f3ad 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/license/XPackLicenseStateTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/license/XPackLicenseStateTests.java @@ -38,7 +38,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 predicate, boolean expected) { XPackLicenseState licenseState = TestUtils.newTestLicenseState(); - licenseState.update(mode, active, null); + licenseState.update(mode, active, Long.MAX_VALUE, null); assertEquals(expected, predicate.test(licenseState)); } @@ -102,7 +102,7 @@ public void testTransportSslDoesNotAutomaticallyEnableSecurityOnTrialLicense() { public void testSecurityBasicWithoutExplicitSecurityEnabled() { XPackLicenseState licenseState = TestUtils.newTestLicenseState(); - licenseState.update(BASIC, true, null); + licenseState.update(BASIC, true, Long.MAX_VALUE, null); assertThat(licenseState.isSecurityEnabled(), is(false)); assertThat(licenseState.checkFeature(Feature.SECURITY_IP_FILTERING), is(false)); @@ -120,7 +120,7 @@ public void testSecurityBasicWithoutExplicitSecurityEnabled() { public void testSecurityBasicWithExplicitSecurityEnabled() { final Settings settings = Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build(); XPackLicenseState licenseState = new XPackLicenseState(settings, () -> 0); - licenseState.update(BASIC, true, null); + licenseState.update(BASIC, true, Long.MAX_VALUE, null); assertThat(licenseState.isSecurityEnabled(), is(true)); assertThat(licenseState.checkFeature(Feature.SECURITY_IP_FILTERING), is(false)); @@ -137,7 +137,7 @@ public void testSecurityBasicWithExplicitSecurityEnabled() { public void testSecurityDefaultBasicExpired() { XPackLicenseState licenseState = TestUtils.newTestLicenseState(); - licenseState.update(BASIC, false, null); + licenseState.update(BASIC, false, Long.MAX_VALUE, null); assertThat(licenseState.isSecurityEnabled(), is(false)); assertThat(licenseState.checkFeature(Feature.SECURITY_IP_FILTERING), is(false)); @@ -152,7 +152,7 @@ public void testSecurityDefaultBasicExpired() { public void testSecurityEnabledBasicExpired() { Settings settings = Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build(); XPackLicenseState licenseState = new XPackLicenseState(settings, () -> 0); - licenseState.update(BASIC, false, null); + licenseState.update(BASIC, false, Long.MAX_VALUE, null); assertThat(licenseState.isSecurityEnabled(), is(true)); assertThat(licenseState.checkFeature(Feature.SECURITY_IP_FILTERING), is(false)); @@ -168,7 +168,7 @@ public void testSecurityStandard() { Settings settings = randomFrom(Settings.EMPTY, Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build()); XPackLicenseState licenseState = new XPackLicenseState(settings, () -> 0); - licenseState.update(STANDARD, true, null); + licenseState.update(STANDARD, true, Long.MAX_VALUE, null); assertThat(licenseState.isSecurityEnabled(), is(true)); assertThat(licenseState.checkFeature(Feature.SECURITY_IP_FILTERING), is(false)); @@ -182,7 +182,7 @@ public void testSecurityStandardExpired() { Settings settings = randomFrom(Settings.EMPTY, Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build()); XPackLicenseState licenseState = new XPackLicenseState(settings, () -> 0); - licenseState.update(STANDARD, false, null); + licenseState.update(STANDARD, false, Long.MAX_VALUE, null); assertThat(licenseState.isSecurityEnabled(), is(true)); assertThat(licenseState.checkFeature(Feature.SECURITY_IP_FILTERING), is(false)); @@ -196,7 +196,7 @@ public void testSecurityGold() { Settings settings = randomFrom(Settings.EMPTY, Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build()); XPackLicenseState licenseState = new XPackLicenseState(settings, () -> 0); - licenseState.update(GOLD, true, null); + licenseState.update(GOLD, true, Long.MAX_VALUE, null); assertThat(licenseState.isSecurityEnabled(), is(true)); assertThat(licenseState.checkFeature(Feature.SECURITY_IP_FILTERING), is(true)); @@ -213,7 +213,7 @@ public void testSecurityGoldExpired() { Settings settings = randomFrom(Settings.EMPTY, Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build()); XPackLicenseState licenseState = new XPackLicenseState(settings, () -> 0); - licenseState.update(GOLD, false, null); + licenseState.update(GOLD, false, Long.MAX_VALUE, null); assertThat(licenseState.isSecurityEnabled(), is(true)); assertThat(licenseState.checkFeature(Feature.SECURITY_IP_FILTERING), is(true)); @@ -230,7 +230,7 @@ public void testSecurityPlatinum() { Settings settings = randomFrom(Settings.EMPTY, Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build()); XPackLicenseState licenseState = new XPackLicenseState(settings, () -> 0); - licenseState.update(PLATINUM, true, null); + licenseState.update(PLATINUM, true, Long.MAX_VALUE, null); assertThat(licenseState.isSecurityEnabled(), is(true)); assertThat(licenseState.checkFeature(Feature.SECURITY_IP_FILTERING), is(true)); @@ -247,7 +247,7 @@ public void testSecurityPlatinumExpired() { Settings settings = randomFrom(Settings.EMPTY, Settings.builder().put(XPackSettings.SECURITY_ENABLED.getKey(), true).build()); XPackLicenseState licenseState = new XPackLicenseState(settings, () -> 0); - licenseState.update(PLATINUM, false, null); + licenseState.update(PLATINUM, false, Long.MAX_VALUE, null); assertThat(licenseState.isSecurityEnabled(), is(true)); assertThat(licenseState.checkFeature(Feature.SECURITY_IP_FILTERING), is(true)); @@ -262,7 +262,7 @@ public void testSecurityPlatinumExpired() { public void testNewTrialDefaultsSecurityOff() { XPackLicenseState licenseState = TestUtils.newTestLicenseState(); - licenseState.update(TRIAL, true, VersionUtils.randomVersionBetween(random(), Version.V_6_3_0, Version.CURRENT)); + licenseState.update(TRIAL, true, Long.MAX_VALUE, VersionUtils.randomVersionBetween(random(), Version.V_6_3_0, Version.CURRENT)); assertThat(licenseState.isSecurityEnabled(), is(false)); assertSecurityNotAllowed(licenseState); @@ -419,7 +419,7 @@ public void testSqlDefaults() { public void testSqlBasic() { XPackLicenseState licenseState = TestUtils.newTestLicenseState(); - licenseState.update(BASIC, true, null); + licenseState.update(BASIC, true, Long.MAX_VALUE, null); assertThat(licenseState.checkFeature(XPackLicenseState.Feature.SQL), is(true)); assertThat(licenseState.checkFeature(XPackLicenseState.Feature.JDBC), is(false)); @@ -427,7 +427,7 @@ public void testSqlBasic() { public void testSqlBasicExpired() { XPackLicenseState licenseState = TestUtils.newTestLicenseState(); - licenseState.update(BASIC, false, null); + licenseState.update(BASIC, false, Long.MAX_VALUE, null); assertThat(licenseState.checkFeature(XPackLicenseState.Feature.SQL), is(false)); assertThat(licenseState.checkFeature(XPackLicenseState.Feature.JDBC), is(false)); @@ -435,7 +435,7 @@ public void testSqlBasicExpired() { public void testSqlStandard() { XPackLicenseState licenseState = TestUtils.newTestLicenseState(); - licenseState.update(STANDARD, true, null); + licenseState.update(STANDARD, true, Long.MAX_VALUE, null); assertThat(licenseState.checkFeature(XPackLicenseState.Feature.SQL), is(true)); assertThat(licenseState.checkFeature(XPackLicenseState.Feature.JDBC), is(false)); @@ -443,7 +443,7 @@ public void testSqlStandard() { public void testSqlStandardExpired() { XPackLicenseState licenseState = TestUtils.newTestLicenseState(); - licenseState.update(STANDARD, false, null); + licenseState.update(STANDARD, false, Long.MAX_VALUE, null); assertThat(licenseState.checkFeature(XPackLicenseState.Feature.SQL), is(false)); assertThat(licenseState.checkFeature(XPackLicenseState.Feature.JDBC), is(false)); @@ -451,7 +451,7 @@ public void testSqlStandardExpired() { public void testSqlGold() { XPackLicenseState licenseState = TestUtils.newTestLicenseState(); - licenseState.update(GOLD, true, null); + licenseState.update(GOLD, true, Long.MAX_VALUE, null); assertThat(licenseState.checkFeature(XPackLicenseState.Feature.SQL), is(true)); assertThat(licenseState.checkFeature(XPackLicenseState.Feature.JDBC), is(false)); @@ -459,7 +459,7 @@ public void testSqlGold() { public void testSqlGoldExpired() { XPackLicenseState licenseState = TestUtils.newTestLicenseState(); - licenseState.update(GOLD, false, null); + licenseState.update(GOLD, false, Long.MAX_VALUE, null); assertThat(licenseState.checkFeature(XPackLicenseState.Feature.SQL), is(false)); assertThat(licenseState.checkFeature(XPackLicenseState.Feature.JDBC), is(false)); @@ -467,7 +467,7 @@ public void testSqlGoldExpired() { public void testSqlPlatinum() { XPackLicenseState licenseState = TestUtils.newTestLicenseState(); - licenseState.update(PLATINUM, true, null); + licenseState.update(PLATINUM, true, Long.MAX_VALUE, null); assertThat(licenseState.checkFeature(XPackLicenseState.Feature.SQL), is(true)); assertThat(licenseState.checkFeature(XPackLicenseState.Feature.JDBC), is(true)); @@ -475,7 +475,7 @@ public void testSqlPlatinum() { public void testSqlPlatinumExpired() { XPackLicenseState licenseState = TestUtils.newTestLicenseState(); - licenseState.update(PLATINUM, false, null); + licenseState.update(PLATINUM, false, Long.MAX_VALUE, null); assertThat(licenseState.checkFeature(XPackLicenseState.Feature.SQL), is(false)); assertThat(licenseState.checkFeature(XPackLicenseState.Feature.JDBC), is(false)); @@ -496,56 +496,56 @@ public void testCcrDefaults() { public void testCcrBasic() { final XPackLicenseState state = TestUtils.newTestLicenseState(); - state.update(BASIC, true, null); + state.update(BASIC, true, Long.MAX_VALUE, null); assertThat(state.checkFeature(XPackLicenseState.Feature.CCR), is(false)); } public void testCcrBasicExpired() { final XPackLicenseState state = TestUtils.newTestLicenseState(); - state.update(BASIC, false, null); + state.update(BASIC, false, Long.MAX_VALUE, null); assertThat(state.checkFeature(XPackLicenseState.Feature.CCR), is(false)); } public void testCcrStandard() { final XPackLicenseState state = TestUtils.newTestLicenseState(); - state.update(STANDARD, true, null); + state.update(STANDARD, true, Long.MAX_VALUE, null); assertThat(state.checkFeature(XPackLicenseState.Feature.CCR), is(false)); } public void testCcrStandardExpired() { final XPackLicenseState state = TestUtils.newTestLicenseState(); - state.update(STANDARD, false, null); + state.update(STANDARD, false, Long.MAX_VALUE, null); assertThat(state.checkFeature(XPackLicenseState.Feature.CCR), is(false)); } public void testCcrGold() { final XPackLicenseState state = TestUtils.newTestLicenseState(); - state.update(GOLD, true, null); + state.update(GOLD, true, Long.MAX_VALUE, null); assertThat(state.checkFeature(XPackLicenseState.Feature.CCR), is(false)); } public void testCcrGoldExpired() { final XPackLicenseState state = TestUtils.newTestLicenseState(); - state.update(GOLD, false, null); + state.update(GOLD, false, Long.MAX_VALUE, null); assertThat(state.checkFeature(XPackLicenseState.Feature.CCR), is(false)); } public void testCcrPlatinum() { final XPackLicenseState state = TestUtils.newTestLicenseState(); - state.update(PLATINUM, true, null); + state.update(PLATINUM, true, Long.MAX_VALUE, null); assertTrue(state.checkFeature(XPackLicenseState.Feature.CCR)); } public void testCcrPlatinumExpired() { final XPackLicenseState state = TestUtils.newTestLicenseState(); - state.update(PLATINUM, false, null); + state.update(PLATINUM, false, Long.MAX_VALUE, null); assertFalse(state.checkFeature(XPackLicenseState.Feature.CCR)); } diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/test/SecuritySettingsSourceField.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/test/SecuritySettingsSourceField.java index 12082b770436d..eb0c450bc2107 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/test/SecuritySettingsSourceField.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/test/SecuritySettingsSourceField.java @@ -10,6 +10,7 @@ public final class SecuritySettingsSourceField { public static final SecureString TEST_PASSWORD_SECURE_STRING = new SecureString("x-pack-test-password".toCharArray()); public static final String TEST_PASSWORD = "x-pack-test-password"; + public static final String TEST_INVALID_PASSWORD = "invalid-test-password"; private SecuritySettingsSourceField() {} } diff --git a/x-pack/plugin/identity-provider/src/test/java/org/elasticsearch/xpack/idp/saml/rest/action/IdpBaseRestHandlerTests.java b/x-pack/plugin/identity-provider/src/test/java/org/elasticsearch/xpack/idp/saml/rest/action/IdpBaseRestHandlerTests.java index 2593c362b582f..6eb4206a00ad9 100644 --- a/x-pack/plugin/identity-provider/src/test/java/org/elasticsearch/xpack/idp/saml/rest/action/IdpBaseRestHandlerTests.java +++ b/x-pack/plugin/identity-provider/src/test/java/org/elasticsearch/xpack/idp/saml/rest/action/IdpBaseRestHandlerTests.java @@ -38,7 +38,7 @@ private IdpBaseRestHandler buildHandler(License.OperationMode licenseMode) { .put("xpack.idp.enabled", true) .build(); final TestUtils.UpdatableLicenseState licenseState = new TestUtils.UpdatableLicenseState(settings); - licenseState.update(licenseMode, true, null); + licenseState.update(licenseMode, true, Long.MAX_VALUE, null); return new IdpBaseRestHandler(licenseState) { @Override protected RestChannelConsumer innerPrepareRequest(RestRequest request, NodeClient client) throws IOException { diff --git a/x-pack/plugin/ml/src/internalClusterTest/java/org/elasticsearch/license/MachineLearningLicensingIT.java b/x-pack/plugin/ml/src/internalClusterTest/java/org/elasticsearch/license/MachineLearningLicensingIT.java index 05f564c13348e..3678d669bae92 100644 --- a/x-pack/plugin/ml/src/internalClusterTest/java/org/elasticsearch/license/MachineLearningLicensingIT.java +++ b/x-pack/plugin/ml/src/internalClusterTest/java/org/elasticsearch/license/MachineLearningLicensingIT.java @@ -852,7 +852,7 @@ public static void disableLicensing() { public static void disableLicensing(License.OperationMode operationMode) { for (XPackLicenseState licenseState : internalCluster().getInstances(XPackLicenseState.class)) { - licenseState.update(operationMode, false, null); + licenseState.update(operationMode, false, Long.MAX_VALUE, null); } } @@ -862,7 +862,7 @@ public static void enableLicensing() { public static void enableLicensing(License.OperationMode operationMode) { for (XPackLicenseState licenseState : internalCluster().getInstances(XPackLicenseState.class)) { - licenseState.update(operationMode, true, null); + licenseState.update(operationMode, true, Long.MAX_VALUE, null); } } } diff --git a/x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/license/LicensingTests.java b/x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/license/LicensingTests.java index ded11e8444cab..6b2ff9d6ba3ce 100644 --- a/x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/license/LicensingTests.java +++ b/x-pack/plugin/security/src/internalClusterTest/java/org/elasticsearch/license/LicensingTests.java @@ -5,6 +5,7 @@ */ package org.elasticsearch.license; +import org.apache.http.Header; import org.elasticsearch.ElasticsearchSecurityException; import org.elasticsearch.action.DocWriteResponse; import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; @@ -15,6 +16,11 @@ import org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse; import org.elasticsearch.action.index.IndexResponse; import org.elasticsearch.client.Client; +import org.elasticsearch.client.Request; +import org.elasticsearch.client.RequestOptions; +import org.elasticsearch.client.Response; +import org.elasticsearch.client.ResponseException; +import org.elasticsearch.common.settings.SecureString; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.CollectionUtils; import org.elasticsearch.discovery.DiscoveryModule; @@ -26,24 +32,30 @@ import org.elasticsearch.test.MockHttpTransport; import org.elasticsearch.test.SecurityIntegTestCase; import org.elasticsearch.test.SecuritySettingsSource; +import org.elasticsearch.test.SecuritySettingsSourceField; import org.elasticsearch.transport.Netty4Plugin; import org.elasticsearch.transport.TransportInfo; import org.elasticsearch.xpack.core.XPackField; import org.elasticsearch.xpack.security.LocalStateSecurity; +import org.hamcrest.Matchers; import org.junit.After; import org.junit.Before; import java.nio.file.Files; import java.nio.file.Path; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; +import java.util.Locale; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; import static org.elasticsearch.discovery.SettingsBasedSeedHostsProvider.DISCOVERY_SEED_HOSTS_SETTING; +import static org.elasticsearch.license.LicenseService.LICENSE_EXPIRATION_WARNING_PERIOD; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures; +import static org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue; import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.is; @@ -190,6 +202,69 @@ public void testNodeJoinWithoutSecurityExplicitlyEnabled() throws Exception { } } + public void testWarningHeader() throws Exception { + Request request = new Request("GET", "/_security/user"); + RequestOptions.Builder options = request.getOptions().toBuilder(); + options.addHeader("Authorization", basicAuthHeaderValue(SecuritySettingsSource.TEST_USER_NAME, + new SecureString(SecuritySettingsSourceField.TEST_PASSWORD.toCharArray()))); + request.setOptions(options); + Response response = getRestClient().performRequest(request); + List beforeWarningHeaders = getWarningHeaders(response.getHeaders()); + assertTrue(beforeWarningHeaders.isEmpty()); + License.OperationMode mode = randomFrom(License.OperationMode.GOLD, License.OperationMode.PLATINUM, + License.OperationMode.ENTERPRISE, License.OperationMode.STANDARD); + long now = System.currentTimeMillis(); + + long newExpirationDate = now + LICENSE_EXPIRATION_WARNING_PERIOD.getMillis() - 1; + setLicensingExpirationDate(mode, newExpirationDate); + response = getRestClient().performRequest(request); + List afterWarningHeaders= getWarningHeaders(response.getHeaders()); + assertThat(afterWarningHeaders, Matchers.hasSize(1)); + assertThat(afterWarningHeaders.get(0), Matchers.containsString("Your license will expire in [6] days. " + + "Contact your administrator or update your license for continued use of features")); + + newExpirationDate = now + 300000; + setLicensingExpirationDate(mode, newExpirationDate); + response = getRestClient().performRequest(request); + afterWarningHeaders= getWarningHeaders(response.getHeaders()); + assertThat(afterWarningHeaders, Matchers.hasSize(1)); + assertThat(afterWarningHeaders.get(0), Matchers.containsString("Your license expires today. " + + "Contact your administrator or update your license for continued use of features")); + + newExpirationDate = now - 300000; + setLicensingExpirationDate(mode, newExpirationDate); + response = getRestClient().performRequest(request); + afterWarningHeaders= getWarningHeaders(response.getHeaders()); + assertThat(afterWarningHeaders, Matchers.hasSize(1)); + long finalNewExpirationDate = newExpirationDate; + String expiredMessage = String.format(Locale.ROOT, "Your license expired on [%s]. ", + LicenseService.DATE_FORMATTER.formatMillis(finalNewExpirationDate)); + assertThat(afterWarningHeaders.get(0), Matchers.containsString(expiredMessage + + "Contact your administrator or update your license for continued use of features")); + } + + public void testNoWarningHeaderWhenAuthenticationFailed() throws Exception { + Request request = new Request("GET", "/_security/user"); + RequestOptions.Builder options = request.getOptions().toBuilder(); + options.addHeader("Authorization", basicAuthHeaderValue(SecuritySettingsSource.TEST_USER_NAME, + new SecureString(SecuritySettingsSourceField.TEST_INVALID_PASSWORD.toCharArray()))); + request.setOptions(options); + License.OperationMode mode = randomFrom(License.OperationMode.GOLD, License.OperationMode.PLATINUM, + License.OperationMode.ENTERPRISE, License.OperationMode.STANDARD); + long now = System.currentTimeMillis(); + long newExpirationDate = now + LICENSE_EXPIRATION_WARNING_PERIOD.getMillis() - 1; + setLicensingExpirationDate(mode, newExpirationDate); + Header[] headers = null; + try { + getRestClient().performRequest(request); + } catch (ResponseException e) { + headers = e.getResponse().getHeaders(); + List afterWarningHeaders= getWarningHeaders(e.getResponse().getHeaders()); + assertThat(afterWarningHeaders, Matchers.hasSize(0)); + } + assertThat(headers != null && headers.length == 3, is(true)); + } + private static void assertElasticsearchSecurityException(ThrowingRunnable runnable) { ElasticsearchSecurityException ee = expectThrows(ElasticsearchSecurityException.class, runnable); assertThat(ee.getMetadata(LicenseUtils.EXPIRED_FEATURE_METADATA), hasItem(XPackField.SECURITY)); @@ -211,7 +286,7 @@ private void disableLicensing() throws Exception { // apply the disabling of the license once the cluster is stable for (XPackLicenseState licenseState : internalCluster().getInstances(XPackLicenseState.class)) { - licenseState.update(OperationMode.BASIC, false, null); + licenseState.update(OperationMode.BASIC, false, Long.MAX_VALUE, null); } }, 30L, TimeUnit.SECONDS); } @@ -223,7 +298,7 @@ private void enableLicensing(License.OperationMode operationMode) throws Excepti assertBusy(() -> { // first update the license so we can execute monitoring actions for (XPackLicenseState licenseState : internalCluster().getInstances(XPackLicenseState.class)) { - licenseState.update(operationMode, true, null); + licenseState.update(operationMode, true, Long.MAX_VALUE, null); } ensureGreen(); @@ -233,8 +308,32 @@ private void enableLicensing(License.OperationMode operationMode) throws Excepti // re-apply the update in case any node received an updated cluster state that triggered the license state // to change for (XPackLicenseState licenseState : internalCluster().getInstances(XPackLicenseState.class)) { - licenseState.update(operationMode, true, null); + licenseState.update(operationMode, true, Long.MAX_VALUE, null); } }, 30L, TimeUnit.SECONDS); } + + private void setLicensingExpirationDate(License.OperationMode operationMode, long expirationDate) throws Exception { + assertBusy(() -> { + for (XPackLicenseState licenseState : internalCluster().getInstances(XPackLicenseState.class)) { + licenseState.update(operationMode, true, expirationDate, null); + } + + ensureGreen(); + ensureClusterSizeConsistency(); + ensureClusterStateConsistency(); + }, 30L, TimeUnit.SECONDS); + } + + private List getWarningHeaders(Header[] headers) { + List warnings = new ArrayList<>(); + + for (Header header : headers) { + if (header.getName().equals("Warning")) { + warnings.add(header.getValue()); + } + } + + return warnings; + } } diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/rest/SecurityRestFilter.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/rest/SecurityRestFilter.java index 69c444aa9bf4d..b6a9844dbcc7a 100644 --- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/rest/SecurityRestFilter.java +++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/rest/SecurityRestFilter.java @@ -12,6 +12,7 @@ import org.elasticsearch.ExceptionsHelper; import org.elasticsearch.action.ActionListener; import org.elasticsearch.client.node.NodeClient; +import org.elasticsearch.common.util.Maps; import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.http.HttpChannel; import org.elasticsearch.license.XPackLicenseState; @@ -30,6 +31,7 @@ import java.io.IOException; import java.util.List; +import java.util.Map; public class SecurityRestFilter implements RestHandler { @@ -98,6 +100,14 @@ private void handleException(String actionType, RestRequest request, RestChannel @Override protected boolean skipStackTrace() { return restStatus == RestStatus.UNAUTHORIZED; } + @Override + public Map> filterHeaders(Map> headers) { + if (headers.containsKey("Warning")) { + return Maps.copyMapWithRemovedEntry(headers, "Warning"); + } + return headers; + } + }); } catch (Exception inner) { inner.addSuppressed(e); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/SecurityTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/SecurityTests.java index adfff5b6950bb..3e6478ed64417 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/SecurityTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/SecurityTests.java @@ -7,6 +7,7 @@ import org.elasticsearch.ElasticsearchSecurityException; import org.elasticsearch.Version; +import org.elasticsearch.action.ActionListener; import org.elasticsearch.client.Client; import org.elasticsearch.cluster.ClusterName; import org.elasticsearch.cluster.ClusterState; @@ -29,9 +30,11 @@ import org.elasticsearch.license.TestUtils; import org.elasticsearch.license.XPackLicenseState; import org.elasticsearch.plugins.MapperPlugin; +import org.elasticsearch.rest.RestRequest; import org.elasticsearch.script.ScriptService; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.VersionUtils; +import org.elasticsearch.test.rest.FakeRestRequest; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.watcher.ResourceWatcherService; import org.elasticsearch.xpack.core.XPackField; @@ -50,6 +53,7 @@ import org.elasticsearch.xpack.core.ssl.SSLService; import org.elasticsearch.xpack.security.audit.AuditTrailService; import org.elasticsearch.xpack.security.audit.logfile.LoggingAuditTrail; +import org.elasticsearch.xpack.security.authc.AuthenticationService; import org.elasticsearch.xpack.security.authc.Realms; import org.hamcrest.Matchers; import org.junit.After; @@ -62,6 +66,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.BiConsumer; import java.util.function.Function; import java.util.function.Predicate; @@ -421,7 +426,8 @@ public void testGetFieldFilterSecurityEnabledLicenseNoFLS() throws Exception { Function> fieldFilter = security.getFieldFilter(); assertNotSame(MapperPlugin.NOOP_FIELD_FILTER, fieldFilter); licenseState.update( - randomFrom(License.OperationMode.BASIC, License.OperationMode.STANDARD, License.OperationMode.GOLD), true, null); + randomFrom(License.OperationMode.BASIC, License.OperationMode.STANDARD, License.OperationMode.GOLD), + true, Long.MAX_VALUE, null); assertNotSame(MapperPlugin.NOOP_FIELD_FILTER, fieldFilter); assertSame(MapperPlugin.NOOP_FIELD_PREDICATE, fieldFilter.apply(randomAlphaOfLengthBetween(3, 6))); } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/support/SecondaryAuthenticatorTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/support/SecondaryAuthenticatorTests.java index b662326056779..5ee13eec8b996 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/support/SecondaryAuthenticatorTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/support/SecondaryAuthenticatorTests.java @@ -109,7 +109,7 @@ public void setupMocks() throws Exception { when(client.threadPool()).thenReturn(threadPool); final TestUtils.UpdatableLicenseState licenseState = new TestUtils.UpdatableLicenseState(); - licenseState.update(License.OperationMode.PLATINUM, true, null); + licenseState.update(License.OperationMode.PLATINUM, true, Long.MAX_VALUE, null); final Clock clock = Clock.systemUTC(); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStoreTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStoreTests.java index 03a243e867dc6..05dfaa4587304 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStoreTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStoreTests.java @@ -752,7 +752,8 @@ public void testCustomRolesProvidersLicensing() { UpdatableLicenseState xPackLicenseState = new UpdatableLicenseState(SECURITY_ENABLED_SETTINGS); // these licenses don't allow custom role providers - xPackLicenseState.update(randomFrom(OperationMode.BASIC, OperationMode.GOLD, OperationMode.STANDARD), true, null); + xPackLicenseState.update(randomFrom(OperationMode.BASIC, OperationMode.GOLD, OperationMode.STANDARD), true, + Long.MAX_VALUE, null); final AtomicReference> effectiveRoleDescriptors = new AtomicReference>(); final DocumentSubsetBitsetCache documentSubsetBitsetCache = buildBitsetCache(); CompositeRolesStore compositeRolesStore = new CompositeRolesStore( @@ -775,7 +776,8 @@ Settings.EMPTY, fileRolesStore, nativeRolesStore, reservedRolesStore, mock(Nativ Arrays.asList(inMemoryProvider), new ThreadContext(Settings.EMPTY), xPackLicenseState, cache, mock(ApiKeyService.class), documentSubsetBitsetCache, rds -> effectiveRoleDescriptors.set(rds)); // these licenses allow custom role providers - xPackLicenseState.update(randomFrom(OperationMode.PLATINUM, OperationMode.ENTERPRISE, OperationMode.TRIAL), true, null); + xPackLicenseState.update(randomFrom(OperationMode.PLATINUM, OperationMode.ENTERPRISE, OperationMode.TRIAL), true, + Long.MAX_VALUE, null); roleNames = Sets.newHashSet("roleA"); future = new PlainActionFuture<>(); compositeRolesStore.roles(roleNames, future); @@ -791,7 +793,8 @@ Settings.EMPTY, fileRolesStore, nativeRolesStore, reservedRolesStore, mock(Nativ Settings.EMPTY, fileRolesStore, nativeRolesStore, reservedRolesStore, mock(NativePrivilegeStore.class), Arrays.asList(inMemoryProvider), new ThreadContext(Settings.EMPTY), xPackLicenseState, cache, mock(ApiKeyService.class), documentSubsetBitsetCache, rds -> effectiveRoleDescriptors.set(rds)); - xPackLicenseState.update(randomFrom(OperationMode.PLATINUM, OperationMode.ENTERPRISE, OperationMode.TRIAL), false, null); + xPackLicenseState.update(randomFrom(OperationMode.PLATINUM, OperationMode.ENTERPRISE, OperationMode.TRIAL), false, + Long.MAX_VALUE, null); roleNames = Sets.newHashSet("roleA"); future = new PlainActionFuture<>(); compositeRolesStore.roles(roleNames, future); diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/rest/action/saml/SamlBaseRestHandlerTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/rest/action/saml/SamlBaseRestHandlerTests.java index b7ab884ce42b8..f79763f3e5cca 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/rest/action/saml/SamlBaseRestHandlerTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/rest/action/saml/SamlBaseRestHandlerTests.java @@ -45,7 +45,7 @@ private SamlBaseRestHandler buildHandler(License.OperationMode licenseMode) { .put(XPackSettings.SECURITY_ENABLED.getKey(), true) .build(); final TestUtils.UpdatableLicenseState licenseState = new TestUtils.UpdatableLicenseState(settings); - licenseState.update(licenseMode, true, null); + licenseState.update(licenseMode, true, Long.MAX_VALUE, null); return new SamlBaseRestHandler(settings, licenseState) { diff --git a/x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/LocalStateSpatialPlugin.java b/x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/LocalStateSpatialPlugin.java index 42c0769c3bd6b..02dd11e8b9be9 100644 --- a/x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/LocalStateSpatialPlugin.java +++ b/x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/LocalStateSpatialPlugin.java @@ -22,7 +22,7 @@ public class LocalStateSpatialPlugin extends SpatialPlugin { protected XPackLicenseState getLicenseState() { TestUtils.UpdatableLicenseState licenseState = new TestUtils.UpdatableLicenseState(); License.OperationMode operationMode = License.OperationMode.TRIAL; - licenseState.update(operationMode, true, VersionUtils.randomVersion(LuceneTestCase.random())); + licenseState.update(operationMode, true, Long.MAX_VALUE, VersionUtils.randomVersion(LuceneTestCase.random())); return licenseState; } } diff --git a/x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/SpatialPluginTests.java b/x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/SpatialPluginTests.java index a9337a2c65265..9646630206cbd 100644 --- a/x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/SpatialPluginTests.java +++ b/x-pack/plugin/spatial/src/test/java/org/elasticsearch/xpack/spatial/SpatialPluginTests.java @@ -82,7 +82,7 @@ private SpatialPlugin getPluginWithOperationMode(License.OperationMode operation return new SpatialPlugin() { protected XPackLicenseState getLicenseState() { TestUtils.UpdatableLicenseState licenseState = new TestUtils.UpdatableLicenseState(); - licenseState.update(operationMode, true, VersionUtils.randomVersion(random())); + licenseState.update(operationMode, true, Long.MAX_VALUE, VersionUtils.randomVersion(random())); return licenseState; } };