Browse Source

Reject misconfigured/ambiguous SSL server config (#45892)

This commit makes it an error to start a node where either of the
server contexts (xpack.security.transport.ssl and
xpack.security.http.ssl) meet either of these conditions:

1. The server lacks a certificate/key pair (i.e. neither
   ssl.keystore.path not ssl.certificate are configured)
2. The server has some ssl configuration, but ssl.enabled is not
   specified. This new validation does not care whether ssl.enabled is
   true or false (though other validation might), it simply makes it
   an error to configure server SSL without being explicit about
   whether to enable that configuration.
Tim Vernum 6 years ago
parent
commit
eb3c57b8eb
18 changed files with 301 additions and 69 deletions
  1. 2 0
      client/rest-high-level/build.gradle
  2. 70 0
      docs/reference/migration/migrate_8_0/security.asciidoc
  3. 31 1
      x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/SSLService.java
  4. 20 2
      x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/transport/ProfileConfigurationsTests.java
  5. 26 6
      x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLConfigurationReloaderTests.java
  6. 42 13
      x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLServiceTests.java
  7. 1 0
      x-pack/plugin/security/src/test/java/org/elasticsearch/test/SettingsFilterTests.java
  8. 23 0
      x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/PkiRealmBootstrapCheckTests.java
  9. 15 9
      x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/tool/CommandLineHttpClientTests.java
  10. 1 0
      x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapUserSearchSessionFactoryTests.java
  11. 1 0
      x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlRealmTests.java
  12. 2 15
      x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/SecurityNetty4HttpServerTransportTests.java
  13. 2 22
      x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/nio/SecurityNioHttpServerTransportTests.java
  14. 1 1
      x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ssl/SslIntegrationTests.java
  15. 58 0
      x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLErrorMessageTests.java
  16. 1 0
      x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLReloadIntegTests.java
  17. 1 0
      x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLTrustRestrictionsTests.java
  18. 4 0
      x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/HttpClientTests.java

+ 2 - 0
client/rest-high-level/build.gradle

@@ -126,6 +126,8 @@ testClusters.all {
   setting 'xpack.security.enabled', 'true'
   setting 'xpack.security.authc.token.enabled', 'true'
   setting 'xpack.security.authc.api_key.enabled', 'true'
+  setting 'xpack.security.http.ssl.enabled', 'false'
+  setting 'xpack.security.transport.ssl.enabled', 'false'
   // Truststore settings are not used since TLS is not enabled. Included for testing the get certificates API
   setting 'xpack.security.http.ssl.certificate_authorities', 'testnode.crt'
   setting 'xpack.security.transport.ssl.truststore.path', 'testnode.jks'

+ 70 - 0
docs/reference/migration/migrate_8_0/security.asciidoc

@@ -41,3 +41,73 @@ realm directly.
 The `transport.profiles.*.xpack.security.type` setting has been removed since
 the Transport Client has been removed and therefore all client traffic now uses
 the HTTP transport. Transport profiles using this setting should be removed.
+
+[float]
+[[ssl-validation-changes]]
+==== SSL/TLS configuration validation
+
+[float]
+===== The `xpack.security.transport.ssl.enabled` setting may be required
+
+It is now an error to configure any SSL settings for
+`xpack.security.transport.ssl` without also configuring
+`xpack.security.transport.ssl.enabled`.
+
+For example, the following configuration is invalid:
+[source,yaml]
+--------------------------------------------------
+xpack.security.transport.ssl.keystore.path: elastic-certificates.p12
+xpack.security.transport.ssl.truststore.path: elastic-certificates.p12
+--------------------------------------------------
+
+And must be configured as:
+[source,yaml]
+--------------------------------------------------
+xpack.security.transport.ssl.enabled: true <1>
+xpack.security.transport.ssl.keystore.path: elastic-certificates.p12
+xpack.security.transport.ssl.truststore.path: elastic-certificates.p12
+--------------------------------------------------
+<1> or `false`.
+
+[float]
+===== The `xpack.security.http.ssl.enabled` setting may be required
+
+It is now an error to configure any SSL settings for
+`xpack.security.http.ssl` without also configuring
+`xpack.security.http.ssl.enabled`.
+
+For example, the following configuration is invalid:
+[source,yaml]
+--------------------------------------------------
+xpack.security.http.ssl.certificate: elasticsearch.crt 
+xpack.security.http.ssl.key: elasticsearch.key 
+xpack.security.http.ssl.certificate_authorities: [ "corporate-ca.crt" ]
+--------------------------------------------------
+
+And must be configured as either:
+[source,yaml]
+--------------------------------------------------
+xpack.security.http.ssl.enabled: true <1>
+xpack.security.http.ssl.certificate: elasticsearch.crt 
+xpack.security.http.ssl.key: elasticsearch.key 
+xpack.security.http.ssl.certificate_authorities: [ "corporate-ca.crt" ]
+--------------------------------------------------
+<1> or `false`.
+
+[float]
+===== The `xpack.security.transport.ssl` Certificate and Key may be required
+
+It is now an error to enable SSL for the transport interface without also configuring
+a certificate and key through use of the `xpack.security.transport.ssl.keystore.path`
+setting or the `xpack.security.transport.ssl.certificate` and
+`xpack.security.transport.ssl.key` settings.
+
+[float]
+===== The `xpack.security.http.ssl` Certificate and Key may be required
+
+It is now an error to enable SSL for the HTTP (Rest) server without also configuring
+a certificate and key through use of the `xpack.security.http.ssl.keystore.path`
+setting or the `xpack.security.http.ssl.certificate` and
+`xpack.security.http.ssl.key` settings.
+
+

+ 31 - 1
x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/SSLService.java

@@ -33,7 +33,6 @@ import javax.net.ssl.SSLSocketFactory;
 import javax.net.ssl.TrustManagerFactory;
 import javax.net.ssl.X509ExtendedKeyManager;
 import javax.net.ssl.X509ExtendedTrustManager;
-
 import java.io.IOException;
 import java.net.InetAddress;
 import java.net.Socket;
@@ -428,6 +427,10 @@ public class SSLService {
         Map<String, Settings> profileSettings = getTransportProfileSSLSettings(settings);
         profileSettings.forEach((key, profileSetting) -> loadConfiguration(key, profileSetting, sslContextHolders));
 
+        for (String context : List.of("xpack.security.transport.ssl", "xpack.security.http.ssl")) {
+            validateServerConfiguration(context);
+        }
+
         return Collections.unmodifiableMap(sslContextHolders);
     }
 
@@ -446,6 +449,33 @@ public class SSLService {
         }
     }
 
+    private void validateServerConfiguration(String prefix) {
+        assert prefix.endsWith(".ssl");
+        SSLConfiguration configuration = getSSLConfiguration(prefix);
+        final String enabledSetting = prefix + ".enabled";
+        if (settings.getAsBoolean(enabledSetting, false) == true) {
+            // Client Authentication _should_ be required, but if someone turns it off, then this check is no longer relevant
+            final SSLConfigurationSettings configurationSettings = SSLConfigurationSettings.withPrefix(prefix + ".");
+            if (isConfigurationValidForServerUsage(configuration) == false) {
+                throw new ElasticsearchSecurityException("invalid SSL configuration for " + prefix +
+                    " - server ssl configuration requires a key and certificate, but these have not been configured; you must set either " +
+                    "[" + configurationSettings.x509KeyPair.keystorePath.getKey() + "], or both [" +
+                    configurationSettings.x509KeyPair.keyPath.getKey() + "] and [" +
+                    configurationSettings.x509KeyPair.certificatePath.getKey() + "]");
+            }
+        } else if (settings.hasValue(enabledSetting) == false) {
+            final List<String> sslSettingNames = settings.keySet().stream()
+                .filter(s -> s.startsWith(prefix))
+                .sorted()
+                .collect(Collectors.toUnmodifiableList());
+            if (sslSettingNames.isEmpty() == false) {
+                throw new ElasticsearchSecurityException("invalid configuration for " + prefix + " - [" + enabledSetting +
+                    "] is not set, but the following settings have been configured in elasticsearch.yml : [" +
+                    Strings.collectionToCommaDelimitedString(sslSettingNames) + "]");
+            }
+        }
+    }
+
     private void storeSslConfiguration(String key, SSLConfiguration configuration) {
         if (key.endsWith(".")) {
             key = key.substring(0, key.length() - 1);

+ 20 - 2
x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/transport/ProfileConfigurationsTests.java

@@ -6,6 +6,7 @@
 
 package org.elasticsearch.xpack.core.security.transport;
 
+import org.elasticsearch.common.settings.MockSecureSettings;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.env.Environment;
 import org.elasticsearch.env.TestEnvironment;
@@ -15,14 +16,16 @@ import org.elasticsearch.xpack.core.ssl.SSLService;
 import org.elasticsearch.xpack.core.ssl.VerificationMode;
 import org.hamcrest.Matchers;
 
+import java.nio.file.Path;
 import java.util.Map;
 
 public class ProfileConfigurationsTests extends ESTestCase {
 
     public void testGetSecureTransportProfileConfigurations() {
-        final Settings settings = Settings.builder()
+        final Settings settings = getBaseSettings()
             .put("path.home", createTempDir())
             .put("xpack.security.transport.ssl.verification_mode", VerificationMode.CERTIFICATE.name())
+            .put("xpack.security.transport.ssl.verification_mode", VerificationMode.CERTIFICATE.name())
             .put("transport.profiles.full.xpack.security.ssl.verification_mode", VerificationMode.FULL.name())
             .put("transport.profiles.cert.xpack.security.ssl.verification_mode", VerificationMode.CERTIFICATE.name())
             .build();
@@ -39,7 +42,7 @@ public class ProfileConfigurationsTests extends ESTestCase {
 
     public void testGetInsecureTransportProfileConfigurations() {
         assumeFalse("Can't run in a FIPS JVM with verification mode None", inFipsJvm());
-        final Settings settings = Settings.builder()
+        final Settings settings = getBaseSettings()
             .put("path.home", createTempDir())
             .put("xpack.security.transport.ssl.verification_mode", VerificationMode.CERTIFICATE.name())
             .put("transport.profiles.none.xpack.security.ssl.verification_mode", VerificationMode.NONE.name())
@@ -53,4 +56,19 @@ public class ProfileConfigurationsTests extends ESTestCase {
         assertThat(profileConfigurations.get("none").verificationMode(), Matchers.equalTo(VerificationMode.NONE));
         assertThat(profileConfigurations.get("default"), Matchers.sameInstance(defaultConfig));
     }
+
+    private Settings.Builder getBaseSettings() {
+        final Path keystore = randomBoolean()
+            ? getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks")
+            : getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.p12");
+
+        MockSecureSettings secureSettings = new MockSecureSettings();
+        secureSettings.setString("xpack.security.transport.ssl.keystore.secure_password", "testnode");
+
+        return Settings.builder()
+            .setSecureSettings(secureSettings)
+            .put("xpack.security.transport.ssl.enabled", true)
+            .put("xpack.security.transport.ssl.keystore.path", keystore.toString());
+    }
+
 }

+ 26 - 6
x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLConfigurationReloaderTests.java

@@ -110,6 +110,7 @@ public class SSLConfigurationReloaderTests extends ESTestCase {
         secureSettings.setString("xpack.security.transport.ssl.keystore.secure_password", "testnode");
         final Settings settings = Settings.builder()
             .put("path.home", createTempDir())
+            .put("xpack.security.transport.ssl.enabled", true)
             .put("xpack.security.transport.ssl.keystore.path", keystorePath)
             .setSecureSettings(secureSettings)
             .build();
@@ -166,6 +167,7 @@ public class SSLConfigurationReloaderTests extends ESTestCase {
         secureSettings.setString("xpack.security.transport.ssl.secure_key_passphrase", "testnode");
         final Settings settings = Settings.builder()
             .put("path.home", createTempDir())
+            .put("xpack.security.transport.ssl.enabled", true)
             .put("xpack.security.transport.ssl.key", keyPath)
             .put("xpack.security.transport.ssl.certificate", certPath)
             .putList("xpack.security.transport.ssl.certificate_authorities", certPath.toString())
@@ -222,10 +224,10 @@ public class SSLConfigurationReloaderTests extends ESTestCase {
             updatedTruststorePath);
         MockSecureSettings secureSettings = new MockSecureSettings();
         secureSettings.setString("xpack.security.transport.ssl.truststore.secure_password", "testnode");
-        Settings settings = Settings.builder()
+        final Settings settings = baseKeystoreSettings(tempDir, secureSettings)
+            .put("xpack.security.transport.ssl.enabled", true)
             .put("xpack.security.transport.ssl.truststore.path", trustStorePath)
             .put("path.home", createTempDir())
-            .setSecureSettings(secureSettings)
             .build();
         Environment env = TestEnvironment.newEnvironment(settings);
         // Create the MockWebServer once for both pre and post checks
@@ -273,7 +275,8 @@ public class SSLConfigurationReloaderTests extends ESTestCase {
         Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt"), serverCertPath);
         Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.pem"), serverKeyPath);
         Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode_updated.crt"), updatedCert);
-        Settings settings = Settings.builder()
+        Settings settings = baseKeystoreSettings(tempDir, null)
+            .put("xpack.security.transport.ssl.enabled", true)
             .putList("xpack.security.transport.ssl.certificate_authorities", serverCertPath.toString())
             .put("path.home", createTempDir())
             .build();
@@ -322,6 +325,7 @@ public class SSLConfigurationReloaderTests extends ESTestCase {
         MockSecureSettings secureSettings = new MockSecureSettings();
         secureSettings.setString("xpack.security.transport.ssl.keystore.secure_password", "testnode");
         Settings settings = Settings.builder()
+            .put("xpack.security.transport.ssl.enabled", true)
             .put("xpack.security.transport.ssl.keystore.path", keystorePath)
             .setSecureSettings(secureSettings)
             .put("path.home", createTempDir())
@@ -372,6 +376,7 @@ public class SSLConfigurationReloaderTests extends ESTestCase {
         MockSecureSettings secureSettings = new MockSecureSettings();
         secureSettings.setString("xpack.security.transport.ssl.secure_key_passphrase", "testnode");
         Settings settings = Settings.builder()
+            .put("xpack.security.transport.ssl.enabled", true)
             .put("xpack.security.transport.ssl.key", keyPath)
             .put("xpack.security.transport.ssl.certificate", certPath)
             .putList("xpack.security.transport.ssl.certificate_authorities", certPath.toString(), clientCertPath.toString())
@@ -419,10 +424,10 @@ public class SSLConfigurationReloaderTests extends ESTestCase {
         Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks"), trustStorePath);
         MockSecureSettings secureSettings = new MockSecureSettings();
         secureSettings.setString("xpack.security.transport.ssl.truststore.secure_password", "testnode");
-        Settings settings = Settings.builder()
+        Settings settings = baseKeystoreSettings(tempDir, secureSettings)
+            .put("xpack.security.transport.ssl.enabled", true)
             .put("xpack.security.transport.ssl.truststore.path", trustStorePath)
             .put("path.home", createTempDir())
-            .setSecureSettings(secureSettings)
             .build();
         Environment env = TestEnvironment.newEnvironment(settings);
         final SSLService sslService = new SSLService(settings, env);
@@ -463,7 +468,8 @@ public class SSLConfigurationReloaderTests extends ESTestCase {
         Path tempDir = createTempDir();
         Path clientCertPath = tempDir.resolve("testclient.crt");
         Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testclient.crt"), clientCertPath);
-        Settings settings = Settings.builder()
+        Settings settings = baseKeystoreSettings(tempDir, null)
+            .put("xpack.security.transport.ssl.enabled", true)
             .putList("xpack.security.transport.ssl.certificate_authorities", clientCertPath.toString())
             .put("path.home", createTempDir())
             .build();
@@ -501,6 +507,20 @@ public class SSLConfigurationReloaderTests extends ESTestCase {
         assertThat(sslService.sslContextHolder(config).sslContext(), sameInstance(context));
     }
 
+    private Settings.Builder baseKeystoreSettings(Path tempDir, MockSecureSettings secureSettings) throws IOException {
+        final Path keystorePath = tempDir.resolve("testclient.jks");
+        Files.copy(getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks"), keystorePath);
+
+        if (secureSettings == null) {
+            secureSettings = new MockSecureSettings();
+        }
+        secureSettings.setString("xpack.security.transport.ssl.keystore.secure_password", "testnode");
+
+        return Settings.builder()
+            .put("xpack.security.transport.ssl.keystore.path", keystorePath.toString())
+            .setSecureSettings(secureSettings);
+    }
+
     private void validateSSLConfigurationIsReloaded(Settings settings, Environment env, Consumer<SSLContext> preChecks,
                                                     Runnable modificationFunction, Consumer<SSLContext> postChecks) throws Exception {
         final CountDownLatch reloadLatch = new CountDownLatch(1);

+ 42 - 13
x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ssl/SSLServiceTests.java

@@ -111,8 +111,11 @@ public class SSLServiceTests extends ESTestCase {
         Path testClientStore = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testclient.jks");
         MockSecureSettings secureSettings = new MockSecureSettings();
         secureSettings.setString("xpack.security.transport.ssl.truststore.secure_password", "testnode");
+        secureSettings.setString("xpack.security.transport.ssl.keystore.secure_password", "testnode");
         secureSettings.setString("transport.profiles.foo.xpack.security.ssl.truststore.secure_password", "testclient");
         Settings settings = Settings.builder()
+                .put("xpack.security.transport.ssl.enabled", true)
+                .put("xpack.security.transport.ssl.keystore.path", testnodeStore)
                 .put("xpack.security.transport.ssl.truststore.path", testnodeStore)
                 .put("xpack.security.transport.ssl.truststore.type", testnodeStoreType)
                 .setSecureSettings(secureSettings)
@@ -145,6 +148,7 @@ public class SSLServiceTests extends ESTestCase {
         MockSecureSettings secureSettings = new MockSecureSettings();
         secureSettings.setString("xpack.security.transport.ssl.secure_key_passphrase", "testnode");
         Settings settings = Settings.builder()
+                .put("xpack.security.transport.ssl.enabled", true)
                 .put("xpack.security.transport.ssl.certificate", testnodeCert)
                 .put("xpack.security.transport.ssl.key", testnodeKey)
                 .setSecureSettings(secureSettings)
@@ -170,6 +174,7 @@ public class SSLServiceTests extends ESTestCase {
         secureSettings.setString("xpack.security.transport.ssl.keystore.secure_password", "testnode");
         secureSettings.setString("xpack.security.transport.ssl.keystore.secure_key_password", "testnode1");
         Settings settings = Settings.builder()
+            .put("xpack.security.transport.ssl.enabled", true)
             .put("xpack.security.transport.ssl.keystore.path", differentPasswordsStore)
             .setSecureSettings(secureSettings)
             .build();
@@ -204,6 +209,7 @@ public class SSLServiceTests extends ESTestCase {
         MockSecureSettings secureSettings = new MockSecureSettings();
         secureSettings.setString("xpack.security.transport.ssl.secure_key_passphrase", "testnode");
         Settings settings = Settings.builder()
+            .put("xpack.security.transport.ssl.enabled", true)
             .put("xpack.security.transport.ssl.certificate", testnodeCert)
             .put("xpack.security.transport.ssl.key", testnodeKey)
             .setSecureSettings(secureSettings)
@@ -223,13 +229,14 @@ public class SSLServiceTests extends ESTestCase {
 
     public void testThatCreateSSLEngineWithOnlyTruststoreWorks() throws Exception {
         MockSecureSettings secureSettings = new MockSecureSettings();
-        secureSettings.setString("xpack.security.transport.ssl.truststore.secure_password", "testclient");
+        secureSettings.setString("xpack.http.ssl.truststore.secure_password", "testclient");
         Settings settings = Settings.builder()
-            .put("xpack.security.transport.ssl.truststore.path", testclientStore)
+            .put("xpack.http.ssl.enabled", true)
+            .put("xpack.http.ssl.truststore.path", testclientStore)
             .setSecureSettings(secureSettings)
             .build();
         SSLService sslService = new SSLService(settings, env);
-        SSLConfiguration configuration = sslService.getSSLConfiguration("xpack.security.transport.ssl");
+        SSLConfiguration configuration = sslService.getSSLConfiguration("xpack.security.http.ssl");
         SSLEngine sslEngine = sslService.createSSLEngine(configuration, null, -1);
         assertThat(sslEngine, notNullValue());
     }
@@ -240,6 +247,7 @@ public class SSLServiceTests extends ESTestCase {
         MockSecureSettings secureSettings = new MockSecureSettings();
         secureSettings.setString("xpack.security.transport.ssl.keystore.secure_password", "testnode");
         Settings settings = Settings.builder()
+            .put("xpack.security.transport.ssl.enabled", true)
             .put("xpack.security.transport.ssl.keystore.path", testnodeStore)
             .put("xpack.security.transport.ssl.keystore.type", testnodeStoreType)
             .setSecureSettings(secureSettings)
@@ -252,25 +260,27 @@ public class SSLServiceTests extends ESTestCase {
     public void testValidForServer() throws Exception {
         assumeFalse("Can't run in a FIPS JVM, JKS keystores can't be used", inFipsJvm());
         MockSecureSettings secureSettings = new MockSecureSettings();
-        secureSettings.setString("xpack.security.transport.ssl.truststore.secure_password", "testnode");
+        secureSettings.setString("xpack.http.ssl.truststore.secure_password", "testnode");
         Settings settings = Settings.builder()
-            .put("xpack.security.transport.ssl.truststore.path", testnodeStore)
-            .put("xpack.security.transport.ssl.truststore.type", testnodeStoreType)
+            .put("xpack.http.ssl.truststore.path", testnodeStore)
+            .put("xpack.http.ssl.truststore.type", testnodeStoreType)
             .setSecureSettings(secureSettings)
             .build();
         SSLService sslService = new SSLService(settings, env);
-        assertFalse(sslService.isConfigurationValidForServerUsage(sslService.getSSLConfiguration("xpack.security.transport.ssl")));
+        // Technically, we don't care whether xpack.http.ssl is valid for server - it's a client context, but we validate both of the
+        // server contexts (http & transport) during construction, so this is the only way to make a non-server-valid context.
+        assertFalse(sslService.isConfigurationValidForServerUsage(sslService.getSSLConfiguration("xpack.http.ssl")));
 
-        secureSettings.setString("xpack.security.transport.ssl.keystore.secure_password", "testnode");
+        secureSettings.setString("xpack.http.ssl.keystore.secure_password", "testnode");
         settings = Settings.builder()
-            .put("xpack.security.transport.ssl.truststore.path", testnodeStore)
-            .put("xpack.security.transport.ssl.truststore.type", testnodeStoreType)
+            .put("xpack.http.ssl.truststore.path", testnodeStore)
+            .put("xpack.http.ssl.truststore.type", testnodeStoreType)
             .setSecureSettings(secureSettings)
-            .put("xpack.security.transport.ssl.keystore.path", testnodeStore)
-            .put("xpack.security.transport.ssl.keystore.type", testnodeStoreType)
+            .put("xpack.http.ssl.keystore.path", testnodeStore)
+            .put("xpack.http.ssl.keystore.type", testnodeStoreType)
             .build();
         sslService = new SSLService(settings, env);
-        assertTrue(sslService.isConfigurationValidForServerUsage(sslService.getSSLConfiguration("xpack.security.transport.ssl")));
+        assertTrue(sslService.isConfigurationValidForServerUsage(sslService.getSSLConfiguration("xpack.http.ssl")));
     }
 
     public void testGetVerificationMode() throws Exception {
@@ -280,6 +290,7 @@ public class SSLServiceTests extends ESTestCase {
             is(XPackSettings.VERIFICATION_MODE_DEFAULT));
 
         Settings settings = Settings.builder()
+            .put("xpack.security.transport.ssl.enabled", false)
             .put("xpack.security.transport.ssl.verification_mode", "certificate")
             .put("transport.profiles.foo.xpack.security.ssl.verification_mode", "full")
             .build();
@@ -294,6 +305,7 @@ public class SSLServiceTests extends ESTestCase {
         assertTrue(sslService.getSSLConfiguration("xpack.security.transport.ssl").sslClientAuth().enabled());
 
         Settings settings = Settings.builder()
+            .put("xpack.security.transport.ssl.enabled", false)
             .put("xpack.security.transport.ssl.client_authentication", "optional")
             .put("transport.profiles.foo.port", "9400-9410")
             .build();
@@ -303,9 +315,18 @@ public class SSLServiceTests extends ESTestCase {
     }
 
     public void testThatHttpClientAuthDefaultsToNone() throws Exception {
+        MockSecureSettings secureSettings = new MockSecureSettings();
+        secureSettings.setString("xpack.security.transport.ssl.keystore.secure_password", "testnode");
+        secureSettings.setString("xpack.security.http.ssl.keystore.secure_password", "testnode");
         final Settings globalSettings = Settings.builder()
             .put("xpack.security.http.ssl.enabled", true)
+            .put("xpack.security.http.ssl.keystore.path", testnodeStore)
+            .put("xpack.security.http.ssl.keystore.type", testnodeStoreType)
+            .put("xpack.security.transport.ssl.enabled", true)
             .put("xpack.security.transport.ssl.client_authentication", SSLClientAuth.OPTIONAL.name())
+            .put("xpack.security.transport.ssl.keystore.path", testnodeStore)
+            .put("xpack.security.transport.ssl.keystore.type", testnodeStoreType)
+            .setSecureSettings(secureSettings)
             .build();
         final SSLService sslService = new SSLService(globalSettings, env);
 
@@ -350,6 +371,7 @@ public class SSLServiceTests extends ESTestCase {
         MockSecureSettings secureSettings = new MockSecureSettings();
         secureSettings.setString("xpack.security.transport.ssl.secure_key_passphrase", "testnode");
         Settings settings = Settings.builder()
+            .put("xpack.security.transport.ssl.enabled", true)
             .put("xpack.security.transport.ssl.certificate", testnodeCert)
             .put("xpack.security.transport.ssl.key", testnodeKey)
             .setSecureSettings(secureSettings)
@@ -383,6 +405,7 @@ public class SSLServiceTests extends ESTestCase {
         MockSecureSettings secureSettings = new MockSecureSettings();
         secureSettings.setString("xpack.security.transport.ssl.secure_key_passphrase", "testnode");
         Settings settings = Settings.builder()
+            .put("xpack.security.transport.ssl.enabled", true)
             .put("xpack.security.transport.ssl.certificate", testnodeCert)
             .put("xpack.security.transport.ssl.key", testnodeKey)
             .setSecureSettings(secureSettings)
@@ -398,6 +421,7 @@ public class SSLServiceTests extends ESTestCase {
         MockSecureSettings secureSettings = new MockSecureSettings();
         secureSettings.setString("xpack.security.transport.ssl.secure_key_passphrase", "testnode");
         Settings settings = Settings.builder()
+            .put("xpack.security.transport.ssl.enabled", true)
             .put("xpack.security.transport.ssl.certificate", testnodeCert)
             .put("xpack.security.transport.ssl.key", testnodeKey)
             .setSecureSettings(secureSettings)
@@ -423,6 +447,7 @@ public class SSLServiceTests extends ESTestCase {
         MockSecureSettings secureSettings = new MockSecureSettings();
         secureSettings.setString("xpack.security.transport.ssl.secure_key_passphrase", "testnode");
         Settings settings = Settings.builder()
+            .put("xpack.security.transport.ssl.enabled", true)
             .put("xpack.security.transport.ssl.certificate", testnodeCert)
             .put("xpack.security.transport.ssl.key", testnodeKey)
             .setSecureSettings(secureSettings)
@@ -514,6 +539,9 @@ public class SSLServiceTests extends ESTestCase {
         final MockSecureSettings secureSettings = new MockSecureSettings();
         final Settings.Builder builder = Settings.builder();
         for (String prefix : contextNames) {
+            if (prefix.startsWith("xpack.security.transport") || prefix.startsWith("xpack.security.http")) {
+                builder.put(prefix + ".enabled", true);
+            }
             secureSettings.setString(prefix + ".keystore.secure_password", "testnode");
             builder.put(prefix + ".keystore.path", testnodeStore)
                 .putList(prefix + ".cipher_suites", cipher.next());
@@ -548,6 +576,7 @@ public class SSLServiceTests extends ESTestCase {
         secureSettings.setString("xpack.http.ssl.keystore.secure_password", "testnode");
 
         final Settings settings = Settings.builder()
+                .put("xpack.security.transport.ssl.enabled", randomBoolean())
                 .put("xpack.security.transport.ssl.keystore.path", jksPath)
                 .put("xpack.security.transport.ssl.truststore.path", jksPath)
                 .put("xpack.http.ssl.keystore.path", p12Path)

+ 1 - 0
x-pack/plugin/security/src/test/java/org/elasticsearch/test/SettingsFilterTests.java

@@ -71,6 +71,7 @@ public class SettingsFilterTests extends ESTestCase {
         configureFilteredSetting("xpack.security.authc.realms.pki.pki1.truststore.algorithm", "SunX509");
 
 
+        configureUnfilteredSetting("xpack.security.transport.ssl.enabled", "true");
         configureFilteredSetting("xpack.security.transport.ssl.cipher_suites",
                 Strings.arrayToCommaDelimitedString(XPackSettings.DEFAULT_CIPHERS.toArray()));
         configureFilteredSetting("xpack.security.transport.ssl.supported_protocols", randomFrom("TLSv1", "TLSv1.1", "TLSv1.2"));

+ 23 - 0
x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/PkiRealmBootstrapCheckTests.java

@@ -14,6 +14,8 @@ import org.elasticsearch.test.AbstractBootstrapCheckTestCase;
 import org.elasticsearch.xpack.core.ssl.SSLService;
 import org.hamcrest.Matchers;
 
+import java.nio.file.Path;
+
 public class PkiRealmBootstrapCheckTests extends AbstractBootstrapCheckTestCase {
 
     public void testPkiRealmBootstrapDefault() throws Exception {
@@ -23,23 +25,34 @@ public class PkiRealmBootstrapCheckTests extends AbstractBootstrapCheckTestCase
     }
 
     public void testBootstrapCheckWithPkiRealm() throws Exception {
+        final Path certPath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt");
+        final Path keyPath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.pem");
+
+        MockSecureSettings secureSettings = new MockSecureSettings();
         Settings settings = Settings.builder()
                 .put("xpack.security.authc.realms.pki.test_pki.order", 0)
                 .put("path.home", createTempDir())
+                .setSecureSettings(secureSettings)
                 .build();
         Environment env = TestEnvironment.newEnvironment(settings);
         assertTrue(runCheck(settings, env).isFailure());
 
         // enable transport tls
+        secureSettings.setString("xpack.security.transport.ssl.secure_key_passphrase", "testnode");
         settings = Settings.builder().put(settings)
                 .put("xpack.security.transport.ssl.enabled", true)
+                .put("xpack.security.transport.ssl.certificate", certPath)
+                .put("xpack.security.transport.ssl.key", keyPath)
                 .build();
         assertFalse(runCheck(settings, env).isFailure());
 
         // enable ssl for http
+        secureSettings.setString("xpack.security.http.ssl.secure_key_passphrase", "testnode");
         settings = Settings.builder().put(settings)
                 .put("xpack.security.transport.ssl.enabled", false)
                 .put("xpack.security.http.ssl.enabled", true)
+                .put("xpack.security.http.ssl.certificate", certPath)
+                .put("xpack.security.http.ssl.key", keyPath)
                 .build();
         env = TestEnvironment.newEnvironment(settings);
         assertTrue(runCheck(settings, env).isFailure());
@@ -82,6 +95,7 @@ public class PkiRealmBootstrapCheckTests extends AbstractBootstrapCheckTestCase
     public void testBootstrapCheckWithDisabledRealm() throws Exception {
         Settings settings = Settings.builder()
                 .put("xpack.security.authc.realms.pki.test_pki.enabled", false)
+                .put("xpack.security.transport.ssl.enabled", false)
                 .put("xpack.security.transport.ssl.client_authentication", "none")
                 .put("path.home", createTempDir())
                 .build();
@@ -90,11 +104,20 @@ public class PkiRealmBootstrapCheckTests extends AbstractBootstrapCheckTestCase
     }
 
     public void testBootstrapCheckWithDelegationEnabled() throws Exception {
+        final Path certPath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt");
+        final Path keyPath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.pem");
+        MockSecureSettings secureSettings = new MockSecureSettings();
+        // enable transport tls
+        secureSettings.setString("xpack.security.transport.ssl.secure_key_passphrase", "testnode");
         Settings settings = Settings.builder()
                 .put("xpack.security.authc.realms.pki.test_pki.enabled", true)
                 .put("xpack.security.authc.realms.pki.test_pki.delegation.enabled", true)
+                .put("xpack.security.transport.ssl.enabled", randomBoolean())
                 .put("xpack.security.transport.ssl.client_authentication", "none")
+                .put("xpack.security.transport.ssl.certificate", certPath.toString())
+                .put("xpack.security.transport.ssl.key", keyPath.toString())
                 .put("path.home", createTempDir())
+                .setSecureSettings(secureSettings)
                 .build();
         Environment env = TestEnvironment.newEnvironment(settings);
         assertFalse(runCheck(settings, env).isFailure());

+ 15 - 9
x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/esnative/tool/CommandLineHttpClientTests.java

@@ -37,9 +37,14 @@ public class CommandLineHttpClientTests extends ESTestCase {
 
     private MockWebServer webServer;
     private Environment environment = TestEnvironment.newEnvironment(Settings.builder().put("path.home", createTempDir()).build());
+    private Path certPath;
+    private Path keyPath;
 
     @Before
     public void setup() throws Exception {
+        certPath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt");
+        keyPath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.pem");
+
         webServer = createMockWebServer();
         webServer.enqueue(new MockResponse().setResponseCode(200).setBody("{\"test\": \"complete\"}"));
         webServer.start();
@@ -51,8 +56,7 @@ public class CommandLineHttpClientTests extends ESTestCase {
     }
 
     public void testCommandLineHttpClientCanExecuteAndReturnCorrectResultUsingSSLSettings() throws Exception {
-        Path certPath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt");
-        Settings settings = Settings.builder()
+        Settings settings = getHttpSslSettings()
             .put("xpack.security.http.ssl.certificate_authorities", certPath.toString())
             .put("xpack.security.http.ssl.verification_mode", VerificationMode.CERTIFICATE)
             .build();
@@ -75,17 +79,19 @@ public class CommandLineHttpClientTests extends ESTestCase {
     }
 
     private MockWebServer createMockWebServer() {
-        Path certPath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt");
-        Path keyPath = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.pem");
+        Settings settings = getHttpSslSettings().build();
+        TestsSSLService sslService = new TestsSSLService(settings, environment);
+        return new MockWebServer(sslService.sslContext("xpack.security.http.ssl."), false);
+    }
+
+    private Settings.Builder getHttpSslSettings() {
         MockSecureSettings secureSettings = new MockSecureSettings();
         secureSettings.setString("xpack.security.http.ssl.secure_key_passphrase", "testnode");
-        Settings settings = Settings.builder()
+        return Settings.builder()
+            .put("xpack.security.http.ssl.enabled", true)
             .put("xpack.security.http.ssl.key", keyPath.toString())
             .put("xpack.security.http.ssl.certificate", certPath.toString())
-            .setSecureSettings(secureSettings)
-            .build();
-        TestsSSLService sslService = new TestsSSLService(settings, environment);
-        return new MockWebServer(sslService.sslContext("xpack.security.http.ssl."), false);
+            .setSecureSettings(secureSettings);
     }
 
     private HttpResponseBuilder responseBuilder(final InputStream is) throws IOException {

+ 1 - 0
x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapUserSearchSessionFactoryTests.java

@@ -65,6 +65,7 @@ public class LdapUserSearchSessionFactoryTests extends LdapTestCase {
 
         globalSettings = Settings.builder()
             .put("path.home", createTempDir())
+            .put("xpack.security.transport.ssl.enabled", false)
             .put("xpack.security.transport.ssl.certificate_authorities", certPath)
             .build();
         sslService = new SSLService(globalSettings, env);

+ 1 - 0
x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/saml/SamlRealmTests.java

@@ -130,6 +130,7 @@ public class SamlRealmTests extends SamlTestCase {
         final MockSecureSettings mockSecureSettings = new MockSecureSettings();
         mockSecureSettings.setString("xpack.security.http.ssl.secure_key_passphrase", "testnode");
         final Settings settings = Settings.builder()
+            .put("xpack.security.http.ssl.enabled", true)
             .put("xpack.security.http.ssl.key",
                 getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.pem"))
             .put("xpack.security.http.ssl.certificate",

+ 2 - 15
x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/netty4/SecurityNetty4HttpServerTransportTests.java

@@ -29,7 +29,6 @@ import java.util.Collections;
 import java.util.Locale;
 
 import static org.hamcrest.Matchers.arrayContaining;
-import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.is;
 import static org.hamcrest.Matchers.not;
@@ -49,6 +48,7 @@ public class SecurityNetty4HttpServerTransportTests extends ESTestCase {
         MockSecureSettings secureSettings = new MockSecureSettings();
         secureSettings.setString("xpack.security.http.ssl.secure_key_passphrase", "testnode");
         Settings settings = Settings.builder()
+            .put("xpack.security.http.ssl.enabled", true)
             .put("xpack.security.http.ssl.key", testnodeKey)
             .put("xpack.security.http.ssl.certificate", testnodeCert)
             .put("path.home", createTempDir())
@@ -147,24 +147,11 @@ public class SecurityNetty4HttpServerTransportTests extends ESTestCase {
         assertThat(customEngine.getEnabledProtocols(), not(equalTo(defaultEngine.getEnabledProtocols())));
     }
 
-    public void testThatExceptionIsThrownWhenConfiguredWithoutSslKey() throws Exception {
-        Settings settings = Settings.builder()
-            .put("xpack.security.http.ssl.certificate_authorities", testnodeCert)
-            .put(XPackSettings.HTTP_SSL_ENABLED.getKey(), true)
-            .put("path.home", createTempDir())
-            .build();
-        env = TestEnvironment.newEnvironment(settings);
-        sslService = new SSLService(settings, env);
-        IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
-                () -> new SecurityNetty4HttpServerTransport(settings, new NetworkService(Collections.emptyList()), mock(BigArrays.class),
-                        mock(IPFilter.class), sslService, mock(ThreadPool.class), xContentRegistry(), new NullDispatcher()));
-        assertThat(e.getMessage(), containsString("key must be provided"));
-    }
-
     public void testNoExceptionWhenConfiguredWithoutSslKeySSLDisabled() throws Exception {
         MockSecureSettings secureSettings = new MockSecureSettings();
         secureSettings.setString("xpack.security.http.ssl.secure_key_passphrase", "testnode");
         Settings settings = Settings.builder()
+            .put("xpack.security.http.ssl.enabled", false)
             .put("xpack.security.http.ssl.key", testnodeKey)
             .put("xpack.security.http.ssl.certificate", testnodeCert)
             .setSecureSettings(secureSettings)

+ 2 - 22
x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/nio/SecurityNioHttpServerTransportTests.java

@@ -36,7 +36,6 @@ import java.util.Collections;
 import java.util.Locale;
 
 import static org.hamcrest.Matchers.arrayContaining;
-import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.is;
 import static org.hamcrest.Matchers.not;
@@ -57,6 +56,7 @@ public class SecurityNioHttpServerTransportTests extends ESTestCase {
         MockSecureSettings secureSettings = new MockSecureSettings();
         secureSettings.setString("xpack.security.http.ssl.secure_key_passphrase", "testnode");
         Settings settings = Settings.builder()
+            .put("xpack.security.http.ssl.enabled", true)
             .put("xpack.security.http.ssl.key", testNodeKey)
             .put("xpack.security.http.ssl.certificate", testNodeCert)
             .put("path.home", createTempDir())
@@ -180,31 +180,11 @@ public class SecurityNioHttpServerTransportTests extends ESTestCase {
         assertThat(customEngine.getEnabledProtocols(), not(equalTo(defaultEngine.getEnabledProtocols())));
     }
 
-    public void testThatExceptionIsThrownWhenConfiguredWithoutSslKey() {
-        MockSecureSettings secureSettings = new MockSecureSettings();
-        secureSettings.setString("xpack.security.http.ssl.truststore.secure_password", "testnode");
-        Settings settings = Settings.builder()
-            .put("xpack.security.http.ssl.truststore.path",
-                getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks"))
-            .setSecureSettings(secureSettings)
-            .put(XPackSettings.HTTP_SSL_ENABLED.getKey(), true)
-            .put("path.home", createTempDir())
-            .build();
-        env = TestEnvironment.newEnvironment(settings);
-        sslService = new SSLService(settings, env);
-        nioGroupFactory = new NioGroupFactory(settings, logger);
-
-        IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
-            () -> new SecurityNioHttpServerTransport(settings,
-                new NetworkService(Collections.emptyList()), mock(BigArrays.class), mock(PageCacheRecycler.class), mock(ThreadPool.class),
-                xContentRegistry(), new NullDispatcher(), mock(IPFilter.class), sslService, nioGroupFactory));
-        assertThat(e.getMessage(), containsString("key must be provided"));
-    }
-
     public void testNoExceptionWhenConfiguredWithoutSslKeySSLDisabled() {
         MockSecureSettings secureSettings = new MockSecureSettings();
         secureSettings.setString("xpack.security.http.ssl.truststore.secure_password", "testnode");
         Settings settings = Settings.builder()
+            .put("xpack.security.http.ssl.enabled", false)
             .put("xpack.security.http.ssl.truststore.path",
                 getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks"))
             .setSecureSettings(secureSettings)

+ 1 - 1
x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/ssl/SslIntegrationTests.java

@@ -61,7 +61,7 @@ public class SslIntegrationTests extends SecurityIntegTestCase {
     }
 
     public void testThatConnectionToHTTPWorks() throws Exception {
-        Settings.Builder builder = Settings.builder();
+        Settings.Builder builder = Settings.builder().put("xpack.security.http.ssl.enabled", true);
         addSSLSettingsForPEMFiles(
             builder, "/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testclient.pem",
             "testclient",

+ 58 - 0
x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLErrorMessageTests.java

@@ -127,6 +127,51 @@ public class SSLErrorMessageTests extends ESTestCase {
         checkBlockedTrustManagerResource("certificate_authorities", "certificate_authorities");
     }
 
+    public void testMessageForTransportSslEnabledWithoutKeys() throws Exception {
+        final String prefix = "xpack.security.transport.ssl";
+        final Settings.Builder settings = Settings.builder();
+        settings.put(prefix + ".enabled", true);
+        configureWorkingTruststore(prefix, settings);
+
+        Throwable exception = expectFailure(settings);
+        assertThat(exception, throwableWithMessage("invalid SSL configuration for " + prefix +
+            " - server ssl configuration requires a key and certificate, but these have not been configured;" +
+            " you must set either [" + prefix + ".keystore.path], or both [" + prefix + ".key] and [" + prefix + ".certificate]"));
+        assertThat(exception, instanceOf(ElasticsearchException.class));
+    }
+
+    public void testNoErrorIfTransportSslDisabledWithoutKeys() throws Exception {
+        final String prefix = "xpack.security.transport.ssl";
+        final Settings.Builder settings = Settings.builder();
+        settings.put(prefix + ".enabled", false);
+        configureWorkingTruststore(prefix, settings);
+        expectSuccess(settings);
+    }
+
+    public void testMessageForTransportNotEnabledButKeystoreConfigured() throws Exception {
+        final String prefix = "xpack.security.transport.ssl";
+        checkUnusedConfiguration(prefix, prefix + ".keystore.path," + prefix + ".keystore.secure_password",
+            this::configureWorkingKeystore);
+    }
+
+    public void testMessageForTransportNotEnabledButTruststoreConfigured() throws Exception {
+        final String prefix = "xpack.security.transport.ssl";
+        checkUnusedConfiguration(prefix, prefix + ".truststore.path," + prefix + ".truststore.secure_password",
+            this::configureWorkingTruststore);
+    }
+
+    public void testMessageForHttpsNotEnabledButKeystoreConfigured() throws Exception {
+        final String prefix = "xpack.security.http.ssl";
+        checkUnusedConfiguration(prefix, prefix + ".keystore.path," + prefix + ".keystore.secure_password",
+            this::configureWorkingKeystore);
+    }
+
+    public void testMessageForHttpsNotEnabledButTruststoreConfigured() throws Exception {
+        final String prefix = "xpack.security.http.ssl";
+        checkUnusedConfiguration(prefix, prefix + ".truststore.path," + prefix + ".truststore.secure_password",
+            this::configureWorkingTruststore);
+    }
+
     private void checkMissingKeyManagerResource(String fileType, String configKey, @Nullable Settings.Builder additionalSettings) {
         checkMissingResource("KeyManager", fileType, configKey,
             (prefix, builder) -> buildKeyConfigSettings(additionalSettings, prefix, builder));
@@ -235,6 +280,16 @@ public class SSLErrorMessageTests extends ESTestCase {
         assertThat(exception, throwableWithMessage(containsString(fileName)));
     }
 
+    private void checkUnusedConfiguration(String prefix, String settingsConfigured, BiConsumer<String, Settings.Builder> configure) {
+        final Settings.Builder settings = Settings.builder();
+        configure.accept(prefix, settings);
+
+        Throwable exception = expectFailure(settings);
+        assertThat(exception, throwableWithMessage("invalid configuration for " + prefix + " - [" + prefix + ".enabled] is not set," +
+            " but the following settings have been configured in elasticsearch.yml : [" + settingsConfigured + "]"));
+        assertThat(exception, instanceOf(ElasticsearchException.class));
+    }
+
     private String missingFile() {
         return resource("cert1a.p12").replace("cert1a.p12", "file.dne");
     }
@@ -292,6 +347,9 @@ public class SSLErrorMessageTests extends ESTestCase {
     private ElasticsearchException expectFailure(Settings.Builder settings) {
         return expectThrows(ElasticsearchException.class, () -> new SSLService(settings.build(), env));
     }
+    private SSLService expectSuccess(Settings.Builder settings) {
+        return new SSLService(settings.build(), env);
+    }
 
     private String resource(String fileName) {
         final Path path = this.paths.get(fileName);

+ 1 - 0
x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLReloadIntegTests.java

@@ -99,6 +99,7 @@ public class SSLReloadIntegTests extends SecurityIntegTestCase {
         secureSettings.setString("xpack.security.transport.ssl.secure_key_passphrase", "testnode");
         Settings settings = Settings.builder()
             .put("path.home", createTempDir())
+            .put("xpack.security.transport.ssl.enabled", true)
             .put("xpack.security.transport.ssl.key", keyPath)
             .put("xpack.security.transport.ssl.certificate", certPath)
             .putList("xpack.security.transport.ssl.certificate_authorities",

+ 1 - 0
x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/ssl/SSLTrustRestrictionsTests.java

@@ -213,6 +213,7 @@ public class SSLTrustRestrictionsTests extends SecurityIntegTestCase {
     private void tryConnect(CertificateInfo certificate, boolean shouldFail) throws Exception {
         Settings settings = Settings.builder()
                 .put("path.home", createTempDir())
+                .put("xpack.security.transport.ssl.enabled", true)
                 .put("xpack.security.transport.ssl.key", certificate.getKeyPath())
                 .put("xpack.security.transport.ssl.certificate", certificate.getCertPath())
                 .putList("xpack.security.transport.ssl.certificate_authorities", ca.getCertPath().toString())

+ 4 - 0
x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/HttpClientTests.java

@@ -197,6 +197,7 @@ public class HttpClientTests extends ESTestCase {
             // We can't use the client created above for the server since it is only a truststore
             secureSettings.setString("xpack.security.http.ssl.secure_key_passphrase", "testnode");
             Settings settings2 = Settings.builder()
+                .put("xpack.security.http.ssl.enabled", true)
                 .put("xpack.security.http.ssl.key", keyPath)
                 .put("xpack.security.http.ssl.certificate", certPath)
                 .putList("xpack.security.http.ssl.supported_protocols", getProtocols())
@@ -226,6 +227,7 @@ public class HttpClientTests extends ESTestCase {
             // We can't use the client created above for the server since it only defines a truststore
             secureSettings.setString("xpack.security.http.ssl.secure_key_passphrase", "testnode-no-subjaltname");
             Settings settings2 = Settings.builder()
+                .put("xpack.security.http.ssl.enabled", true)
                 .put("xpack.security.http.ssl.key", keyPath)
                 .put("xpack.security.http.ssl.certificate", certPath)
                 .putList("xpack.security.http.ssl.supported_protocols", getProtocols())
@@ -382,6 +384,7 @@ public class HttpClientTests extends ESTestCase {
         Settings serverSettings = Settings.builder()
             .put("xpack.http.ssl.key", keyPath)
             .put("xpack.http.ssl.certificate", certPath)
+            .put("xpack.security.http.ssl.enabled", false)
             .putList("xpack.security.http.ssl.supported_protocols", getProtocols())
             .setSecureSettings(serverSecureSettings)
             .build();
@@ -397,6 +400,7 @@ public class HttpClientTests extends ESTestCase {
                 .put(HttpSettings.PROXY_SCHEME.getKey(), "https")
                 .put("xpack.http.ssl.certificate_authorities", trustedCertPath)
                 .putList("xpack.security.http.ssl.supported_protocols", getProtocols())
+                .put("xpack.security.http.ssl.enabled", false)
                 .build();
 
             HttpRequest.Builder requestBuilder = HttpRequest.builder("localhost", webServer.getPort())