diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/License.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/License.java
index 5686d6f7a2c0e..ac0b70e6dcfb7 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/License.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/License.java
@@ -772,22 +772,4 @@ public Builder validate() {
}
}
- /**
- * Returns true
iff the license is a production licnese
- */
- public boolean isProductionLicense() {
- switch (operationMode()) {
- case MISSING:
- case TRIAL:
- case BASIC:
- return false;
- case STANDARD:
- case GOLD:
- case PLATINUM:
- return true;
- default:
- throw new AssertionError("unknown operation mode: " + operationMode());
-
- }
- }
}
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 68e094511a3e8..7316876470772 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
@@ -214,10 +214,13 @@ public void registerLicense(final PutLicenseRequest request, final ActionListene
}
}
+ // This check would be incorrect if "basic" licenses were allowed here
+ // because the defaults there mean that security can be "off", even if the setting is "on"
+ // BUT basic licenses are explicitly excluded earlier in this method, so we don't need to worry
if (XPackSettings.SECURITY_ENABLED.get(settings)) {
// TODO we should really validate that all nodes have xpack installed and are consistently configured but this
// should happen on a different level and not in this code
- if (newLicense.isProductionLicense()
+ if (XPackLicenseState.isTransportTlsRequired(newLicense, settings)
&& XPackSettings.TRANSPORT_SSL_ENABLED.get(settings) == false
&& isProductionMode(settings, clusterService.localNode())) {
// security is on but TLS is not configured we gonna fail the entire request and throw an exception
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 d650a4a9fbb30..1bb2c532eff4b 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
@@ -276,8 +276,8 @@ private static class Status {
}
}
- private final Logger logger;
- private final DeprecationLogger deprecationLogger;
+ private static final Logger logger = LogManager.getLogger(XPackLicenseState.class);
+ private static final DeprecationLogger deprecationLogger = new DeprecationLogger(logger);
private final List listeners;
private final boolean isSecurityEnabled;
@@ -287,8 +287,6 @@ private static class Status {
private boolean isSecurityEnabledByTrialVersion;
public XPackLicenseState(Settings settings) {
- this.logger = LogManager.getLogger(getClass());
- this.deprecationLogger = new DeprecationLogger(logger);
this.listeners = new CopyOnWriteArrayList<>();
this.isSecurityEnabled = XPackSettings.SECURITY_ENABLED.get(settings);
this.isSecurityExplicitlyEnabled = checkSecurityExplicitlyEnabled(settings);
@@ -301,8 +299,8 @@ public XPackLicenseState(Settings settings) {
* setting is not explicitly set.
* This behaviour is deprecated, and will be removed in 7.0
*/
- private boolean checkSecurityExplicitlyEnabled(Settings settings) {
- if (isSecurityEnabled) {
+ private static boolean checkSecurityExplicitlyEnabled(Settings settings) {
+ if (XPackSettings.SECURITY_ENABLED.get(settings)) {
if (settings.hasValue(XPackSettings.SECURITY_ENABLED.getKey())) {
return true;
}
@@ -324,8 +322,6 @@ private XPackLicenseState(XPackLicenseState xPackLicenseState) {
this.isSecurityExplicitlyEnabled = xPackLicenseState.isSecurityExplicitlyEnabled;
this.status = xPackLicenseState.status;
this.isSecurityEnabledByTrialVersion = xPackLicenseState.isSecurityEnabledByTrialVersion;
- this.logger = xPackLicenseState.logger;
- this.deprecationLogger = xPackLicenseState.deprecationLogger;
}
/**
@@ -770,6 +766,25 @@ public synchronized boolean isSecurityDisabledByLicenseDefaults() {
return false;
}
+ public static boolean isTransportTlsRequired(License license, Settings settings) {
+ if (license == null) {
+ return false;
+ }
+ switch (license.operationMode()) {
+ case STANDARD:
+ case GOLD:
+ case PLATINUM:
+ return XPackSettings.SECURITY_ENABLED.get(settings);
+ case BASIC:
+ return XPackSettings.SECURITY_ENABLED.get(settings) && checkSecurityExplicitlyEnabled(settings);
+ case MISSING:
+ case TRIAL:
+ return false;
+ default:
+ throw new AssertionError("unknown operation mode [" + license.operationMode() + "]");
+ }
+ }
+
private static boolean isSecurityEnabled(final OperationMode mode, final boolean isSecurityExplicitlyEnabled,
final boolean isSecurityEnabledByTrialVersion, final boolean isSecurityEnabled) {
switch (mode) {
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/TLSLicenseBootstrapCheck.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/TLSLicenseBootstrapCheck.java
index 6f6592bbdfca2..a042aeb4a2359 100644
--- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/TLSLicenseBootstrapCheck.java
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/TLSLicenseBootstrapCheck.java
@@ -9,6 +9,7 @@
import org.elasticsearch.bootstrap.BootstrapContext;
import org.elasticsearch.license.License;
import org.elasticsearch.license.LicenseService;
+import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.xpack.core.XPackSettings;
/**
@@ -19,10 +20,11 @@ public final class TLSLicenseBootstrapCheck implements BootstrapCheck {
public BootstrapCheckResult check(BootstrapContext context) {
if (XPackSettings.TRANSPORT_SSL_ENABLED.get(context.settings()) == false) {
License license = LicenseService.getLicense(context.metaData());
- if (license != null && license.isProductionLicense()) {
- return BootstrapCheckResult.failure("Transport SSL must be enabled for setups with production licenses. Please set " +
- "[xpack.security.transport.ssl.enabled] to [true] or disable security by setting [xpack.security.enabled] " +
- "to [false]");
+ if (XPackLicenseState.isTransportTlsRequired(license, context.settings())) {
+ return BootstrapCheckResult.failure("Transport SSL must be enabled if security is enabled on a [" +
+ license.operationMode().description() + "] license. " +
+ "Please set [xpack.security.transport.ssl.enabled] to [true] or disable security by setting " +
+ "[xpack.security.enabled] to [false]");
}
}
return BootstrapCheckResult.success();
diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/TLSLicenseBootstrapCheckTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/TLSLicenseBootstrapCheckTests.java
index ac73418800c77..3cb14180930d3 100644
--- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/TLSLicenseBootstrapCheckTests.java
+++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/TLSLicenseBootstrapCheckTests.java
@@ -5,40 +5,115 @@
*/
package org.elasticsearch.xpack.core.ssl;
+import org.elasticsearch.bootstrap.BootstrapCheck;
+import org.elasticsearch.bootstrap.BootstrapContext;
import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.license.License;
+import org.elasticsearch.license.License.OperationMode;
import org.elasticsearch.license.TestUtils;
import org.elasticsearch.test.AbstractBootstrapCheckTestCase;
-import java.util.EnumSet;
-
public class TLSLicenseBootstrapCheckTests extends AbstractBootstrapCheckTestCase {
- public void testBootstrapCheck() throws Exception {
+ public void testBootstrapCheckOnEmptyMetadata() {
assertTrue(new TLSLicenseBootstrapCheck().check(emptyContext).isSuccess());
assertTrue(new TLSLicenseBootstrapCheck().check(createTestContext(Settings.builder().put("xpack.security.transport.ssl.enabled"
- , randomBoolean()).build(), MetaData.EMPTY_META_DATA)).isSuccess());
- int numIters = randomIntBetween(1,10);
- for (int i = 0; i < numIters; i++) {
- License license = TestUtils.generateSignedLicense(TimeValue.timeValueHours(24));
- EnumSet productionModes = EnumSet.of(License.OperationMode.GOLD, License.OperationMode.PLATINUM,
- License.OperationMode.STANDARD);
- MetaData.Builder builder = MetaData.builder();
- TestUtils.putLicense(builder, license);
- MetaData build = builder.build();
- if (productionModes.contains(license.operationMode()) == false) {
- assertTrue(new TLSLicenseBootstrapCheck().check(createTestContext(
- Settings.builder().put("xpack.security.transport.ssl.enabled", true).build(), build)).isSuccess());
- } else {
- assertTrue(new TLSLicenseBootstrapCheck().check(createTestContext(
- Settings.builder().put("xpack.security.transport.ssl.enabled", false).build(), build)).isFailure());
- assertEquals("Transport SSL must be enabled for setups with production licenses. Please set " +
- "[xpack.security.transport.ssl.enabled] to [true] or disable security by setting " +
- "[xpack.security.enabled] to [false]",
- new TLSLicenseBootstrapCheck().check(createTestContext(
- Settings.builder().put("xpack.security.transport.ssl.enabled", false).build(), build)).getMessage());
- }
+ , randomBoolean()).build(), MetaData.EMPTY_META_DATA)).isSuccess());
+ }
+
+ public void testBootstrapCheckFailureOnPremiumLicense() throws Exception {
+ final OperationMode mode = randomFrom(OperationMode.PLATINUM, OperationMode.GOLD, OperationMode.STANDARD);
+ final Settings.Builder settings = Settings.builder();
+ if (randomBoolean()) {
+ // randomise between default-false & explicit-false
+ settings.put("xpack.security.transport.ssl.enabled", false);
+ }
+ if (randomBoolean()) {
+ // randomise between default-true & explicit-true
+ settings.put("xpack.security.enabled", true);
+ }
+
+ final BootstrapCheck.BootstrapCheckResult result = runBootstrapCheck(mode, settings);
+ assertTrue("Expected bootstrap failure", result.isFailure());
+ assertEquals("Transport SSL must be enabled if security is enabled on a [" + mode.description() + "] license. Please set " +
+ "[xpack.security.transport.ssl.enabled] to [true] or disable security by setting " +
+ "[xpack.security.enabled] to [false]",
+ result.getMessage());
+ }
+
+ public void testBootstrapCheckSucceedsWithTlsEnabledOnPremiumLicense() throws Exception {
+ final OperationMode mode = randomFrom(OperationMode.PLATINUM, OperationMode.GOLD, OperationMode.STANDARD);
+ final Settings.Builder settings = Settings.builder().put("xpack.security.transport.ssl.enabled", true);
+ final BootstrapCheck.BootstrapCheckResult result = runBootstrapCheck(mode, settings);
+ assertSuccess(result);
+ }
+
+ public void testBootstrapCheckFailureOnBasicLicense() throws Exception {
+ final Settings.Builder settings = Settings.builder().put("xpack.security.enabled", true);
+ if (randomBoolean()) {
+ // randomise between default-false & explicit-false
+ settings.put("xpack.security.transport.ssl.enabled", false);
+ }
+ final BootstrapCheck.BootstrapCheckResult result = runBootstrapCheck(OperationMode.BASIC, settings);
+ assertTrue("Expected bootstrap failure", result.isFailure());
+ assertEquals("Transport SSL must be enabled if security is enabled on a [basic] license. Please set " +
+ "[xpack.security.transport.ssl.enabled] to [true] or disable security by setting " +
+ "[xpack.security.enabled] to [false]",
+ result.getMessage());
+ }
+
+ public void testBootstrapSucceedsIfSecurityIsNotEnabledOnBasicLicense() throws Exception {
+ final Settings.Builder settings = Settings.builder();
+ if (randomBoolean()) {
+ // randomise between default-false & explicit-false
+ settings.put("xpack.security.enabled", false);
+ }
+ if (randomBoolean()) {
+ // it does not matter whether or not this is set, as security is not enabled.
+ settings.put("xpack.security.transport.ssl.enabled", randomBoolean());
}
+ final BootstrapCheck.BootstrapCheckResult result = runBootstrapCheck(OperationMode.BASIC, settings);
+ assertSuccess(result);
}
+
+ public void testBootstrapSucceedsIfTlsIsEnabledOnBasicLicense() throws Exception {
+ final Settings.Builder settings = Settings.builder().put("xpack.security.transport.ssl.enabled", true);
+ if (randomBoolean()) {
+ // it does not matter whether or not this is set, as TLS is enabled.
+ settings.put("xpack.security.enabled", randomBoolean());
+ }
+ final BootstrapCheck.BootstrapCheckResult result = runBootstrapCheck(OperationMode.BASIC, settings);
+ assertSuccess(result);
+ }
+
+ public void testBootstrapCheckAlwaysSucceedsOnTrialLicense() throws Exception {
+ final Settings.Builder settings = Settings.builder();
+ if (randomBoolean()) {
+ // it does not matter whether this is set, or to which value.
+ settings.put("xpack.security.enabled", randomBoolean());
+ }
+ if (randomBoolean()) {
+ // it does not matter whether this is set, or to which value.
+ settings.put("xpack.security.transport.ssl.enabled", randomBoolean());
+ }
+ final BootstrapCheck.BootstrapCheckResult result = runBootstrapCheck(OperationMode.TRIAL, settings);
+ assertSuccess(result);
+ }
+
+ public BootstrapCheck.BootstrapCheckResult runBootstrapCheck(OperationMode mode, Settings.Builder settings) throws Exception {
+ final License license = TestUtils.generateSignedLicense(mode.description(), TimeValue.timeValueHours(24));
+ MetaData.Builder builder = MetaData.builder();
+ TestUtils.putLicense(builder, license);
+ MetaData metaData = builder.build();
+ final BootstrapContext context = createTestContext(settings.build(), metaData);
+ return new TLSLicenseBootstrapCheck().check(context);
+ }
+
+ public void assertSuccess(BootstrapCheck.BootstrapCheckResult result) {
+ if (result.isFailure()) {
+ fail("Bootstrap check failed unexpectedly: " + result.getMessage());
+ }
+ }
+
}
diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java
index f6e256017e727..859c2693556b1 100644
--- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java
+++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java
@@ -1180,7 +1180,7 @@ public Function> getFieldFilter() {
public BiConsumer getJoinValidator() {
if (enabled) {
return new ValidateTLSOnJoin(XPackSettings.TRANSPORT_SSL_ENABLED.get(settings),
- DiscoveryModule.DISCOVERY_TYPE_SETTING.get(settings))
+ DiscoveryModule.DISCOVERY_TYPE_SETTING.get(settings), settings)
.andThen(new ValidateUpgradedSecurityIndex())
.andThen(new ValidateLicenseCanBeDeserialized())
.andThen(new ValidateLicenseForFIPS(XPackSettings.FIPS_MODE_ENABLED.get(settings)));
@@ -1191,18 +1191,21 @@ public BiConsumer getJoinValidator() {
static final class ValidateTLSOnJoin implements BiConsumer {
private final boolean isTLSEnabled;
private final String discoveryType;
+ private final Settings settings;
- ValidateTLSOnJoin(boolean isTLSEnabled, String discoveryType) {
+ ValidateTLSOnJoin(boolean isTLSEnabled, String discoveryType, Settings settings) {
this.isTLSEnabled = isTLSEnabled;
this.discoveryType = discoveryType;
+ this.settings = settings;
}
@Override
public void accept(DiscoveryNode node, ClusterState state) {
License license = LicenseService.getLicense(state.metaData());
- if (license != null && license.isProductionLicense() &&
- isTLSEnabled == false && "single-node".equals(discoveryType) == false) {
- throw new IllegalStateException("TLS setup is required for license type [" + license.operationMode().name() + "]");
+ if (isTLSEnabled == false && "single-node".equals(discoveryType) == false
+ && XPackLicenseState.isTransportTlsRequired(license, settings)) {
+ throw new IllegalStateException("Transport TLS ([" + XPackSettings.TRANSPORT_SSL_ENABLED.getKey() +
+ "]) is required for license type [" + license.operationMode().description() + "] when security is enabled");
}
}
}
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 95e1e5b3cc955..8108af7b931ce 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
@@ -57,7 +57,6 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
-import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -276,17 +275,45 @@ public void testTLSJoinValidator() throws Exception {
int numIters = randomIntBetween(1,10);
for (int i = 0; i < numIters; i++) {
boolean tlsOn = randomBoolean();
+ boolean securityExplicitlyEnabled = randomBoolean();
String discoveryType = randomFrom("single-node", "zen", randomAlphaOfLength(4));
- Security.ValidateTLSOnJoin validator = new Security.ValidateTLSOnJoin(tlsOn, discoveryType);
+
+ final Settings settings;
+ if (securityExplicitlyEnabled) {
+ settings = Settings.builder().put("xpack.security.enabled", true).build();
+ } else {
+ settings = Settings.EMPTY;
+ }
+ Security.ValidateTLSOnJoin validator = new Security.ValidateTLSOnJoin(tlsOn, discoveryType, settings);
MetaData.Builder builder = MetaData.builder();
- License license = TestUtils.generateSignedLicense(TimeValue.timeValueHours(24));
+ License.OperationMode licenseMode = randomFrom(License.OperationMode.values());
+ License license = TestUtils.generateSignedLicense(licenseMode.description(), TimeValue.timeValueHours(24));
TestUtils.putLicense(builder, license);
ClusterState state = ClusterState.builder(ClusterName.DEFAULT).metaData(builder.build()).build();
- EnumSet productionModes = EnumSet.of(License.OperationMode.GOLD, License.OperationMode.PLATINUM,
- License.OperationMode.STANDARD);
- if (productionModes.contains(license.operationMode()) && tlsOn == false && "single-node".equals(discoveryType) == false) {
+
+ final boolean expectFailure;
+ switch (licenseMode) {
+ case PLATINUM:
+ case GOLD:
+ case STANDARD:
+ expectFailure = tlsOn == false && "single-node".equals(discoveryType) == false;
+ break;
+ case BASIC:
+ expectFailure = tlsOn == false && "single-node".equals(discoveryType) == false && securityExplicitlyEnabled;
+ break;
+ case MISSING:
+ case TRIAL:
+ expectFailure = false;
+ break;
+ default:
+ throw new AssertionError("unknown operation mode [" + license.operationMode() + "]");
+ }
+ logger.info("Test TLS join; Lic:{} TLS:{} Disco:{} Settings:{} ; Expect Failure: {}",
+ licenseMode, tlsOn, discoveryType, settings.toDelimitedString(','), expectFailure);
+ if (expectFailure) {
IllegalStateException ise = expectThrows(IllegalStateException.class, () -> validator.accept(node, state));
- assertEquals("TLS setup is required for license type [" + license.operationMode().name() + "]", ise.getMessage());
+ assertEquals("Transport TLS ([xpack.security.transport.ssl.enabled]) is required for license type ["
+ + license.operationMode().description() + "] when security is enabled", ise.getMessage());
} else {
validator.accept(node, state);
}