From be5e4eb724549ef654d161fcee933dd79ec53b02 Mon Sep 17 00:00:00 2001 From: =?utf8?q?S=C3=A9bastien=20Lesaint?= Date: Tue, 5 Apr 2016 14:15:32 +0200 Subject: [PATCH] SONAR-7411 drop support for HTTPs Tomcat connector --- .../src/test/java/it/Category5Suite.java | 2 - .../test/java/it/serverSystem/HttpsTest.java | 202 ------------------ .../process/ProcessTest/sonar.properties | 55 ----- .../process/ProcessTest/sonar.properties | 55 ----- .../sonar/server/app/TomcatConnectors.java | 60 ++---- .../sonar/server/app/TomcatStartupLogs.java | 16 -- .../org/sonar/server/app/StartupLogsTest.java | 28 --- .../server/app/TomcatConnectorsTest.java | 82 +------ .../src/main/assembly/conf/sonar.properties | 84 +------- 9 files changed, 23 insertions(+), 561 deletions(-) delete mode 100644 it/it-tests/src/test/java/it/serverSystem/HttpsTest.java diff --git a/it/it-tests/src/test/java/it/Category5Suite.java b/it/it-tests/src/test/java/it/Category5Suite.java index ea1fbc31c8e..4f87a8880bc 100644 --- a/it/it-tests/src/test/java/it/Category5Suite.java +++ b/it/it-tests/src/test/java/it/Category5Suite.java @@ -19,7 +19,6 @@ */ package it; -import it.serverSystem.HttpsTest; import it.serverSystem.RestartTest; import it.serverSystem.ServerSystemRestartingOrchestrator; import it.settings.SettingsTestRestartingOrchestrator; @@ -37,7 +36,6 @@ import org.junit.runners.Suite; @Suite.SuiteClasses({ ServerSystemRestartingOrchestrator.class, RestartTest.class, - HttpsTest.class, SettingsTestRestartingOrchestrator.class, // update center UpdateCenterTest.class, diff --git a/it/it-tests/src/test/java/it/serverSystem/HttpsTest.java b/it/it-tests/src/test/java/it/serverSystem/HttpsTest.java deleted file mode 100644 index 6a39cffac43..00000000000 --- a/it/it-tests/src/test/java/it/serverSystem/HttpsTest.java +++ /dev/null @@ -1,202 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package it.serverSystem; - -import com.sonar.orchestrator.Orchestrator; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.security.cert.X509Certificate; -import java.util.List; -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLHandshakeException; -import javax.net.ssl.SSLSession; -import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.experimental.categories.Category; -import org.junit.rules.ExpectedException; -import util.NetworkUtils; -import util.QaOnly; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.fail; - -/** - * This class start a new orchestrator on each test case - */ -@Category(QaOnly.class) -public class HttpsTest { - - public static final String HTTPS_PROTOCOLS = "https.protocols"; - - Orchestrator orchestrator; - - int httpsPort = NetworkUtils.getNextAvailablePort(); - - @Rule - public ExpectedException thrown = ExpectedException.none(); - - String initialHttpsProtocols = null; - - @Before - public void setUp() throws Exception { - // SSLv3 is not supported since SQ 4.5.2. Only TLS v1, v1.1 and v1.2 are - // enabled by Tomcat. - // The problem is that java 1.6 supports only TLSv1 but not v1.1 nor 1.2, - // so version to be used must be explicitly set on JVM. - initialHttpsProtocols = StringUtils.defaultString(System.getProperty(HTTPS_PROTOCOLS), ""); - System.setProperty(HTTPS_PROTOCOLS, "TLSv1"); - } - - @After - public void tearDown() { - if (orchestrator != null) { - orchestrator.stop(); - } - System.setProperty(HTTPS_PROTOCOLS, initialHttpsProtocols); - } - - @Test - public void fail_to_start_if_bad_keystore_credentials() throws Exception { - try { - URL jksKeystore = getClass().getResource("/serverSystem/HttpsTest/keystore.jks"); - orchestrator = Orchestrator.builderEnv() - .setServerProperty("sonar.web.https.port", String.valueOf(httpsPort)) - .setServerProperty("sonar.web.https.keyAlias", "tests") - .setServerProperty("sonar.web.https.keyPass", "__wrong__") - .setServerProperty("sonar.web.https.keystoreFile", new File(jksKeystore.toURI()).getAbsolutePath()) - .setServerProperty("sonar.web.https.keystorePass", "__wrong__") - .build(); - orchestrator.start(); - fail(); - } catch (Exception e) { - File logFile = orchestrator.getServer().getLogs(); - assertThat(FileUtils.readFileToString(logFile)).contains("Password verification failed"); - } - } - - @Test - public void enable_https_port() throws Exception { - // start server - URL jksKeystore = getClass().getResource("/serverSystem/HttpsTest/keystore.jks"); - orchestrator = Orchestrator.builderEnv() - .setServerProperty("sonar.web.https.port", String.valueOf(httpsPort)) - .setServerProperty("sonar.web.https.keyAlias", "tests") - .setServerProperty("sonar.web.https.keyPass", "thetests") - .setServerProperty("sonar.web.https.keystoreFile", new File(jksKeystore.toURI()).getAbsolutePath()) - .setServerProperty("sonar.web.https.keystorePass", "thepassword") - .build(); - orchestrator.start(); - - // check logs - File logFile = orchestrator.getServer().getLogs(); - assertThat(FileUtils.readFileToString(logFile)).contains("HTTPS connector enabled on port " + httpsPort); - - // connect from clients - connectTrusted(); - connectUntrusted(); - } - - private void connectTrusted() throws IOException { - URL url = new URL("https://localhost:" + httpsPort); - HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); - try { - connection.getInputStream(); - fail(); - } catch (SSLHandshakeException e) { - // ok, the certificate is not trusted - } - } - - private void connectUntrusted() throws Exception { - // Create a trust manager that does not validate certificate chains - TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() { - public X509Certificate[] getAcceptedIssuers() { - return null; - } - - public void checkClientTrusted(X509Certificate[] certs, String authType) { - } - - public void checkServerTrusted(X509Certificate[] certs, String authType) { - } - } - }; - - // Install the all-trusting trust manager - // SSLv3 is disabled since SQ 4.5.2 : https://jira.codehaus.org/browse/SONAR-5860 - SSLContext sc = SSLContext.getInstance("TLS"); - sc.init(null, trustAllCerts, new java.security.SecureRandom()); - - SSLSocketFactory untrustedSocketFactory = sc.getSocketFactory(); - - - // Create all-trusting host name verifier - HostnameVerifier allHostsValid = new HostnameVerifier() { - public boolean verify(String hostname, SSLSession session) { - return true; - } - }; - URL url = new URL("https://localhost:" + httpsPort + "/sessions/login"); - HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); - connection.setRequestMethod("POST"); - connection.setAllowUserInteraction(true); - connection.setSSLSocketFactory(untrustedSocketFactory); - connection.setHostnameVerifier(allHostsValid); - - InputStream input = connection.getInputStream(); - checkCookieFlags(connection); - try { - String html = IOUtils.toString(input); - assertThat(html).contains(" cookies = connection.getHeaderFields().get("Set-Cookie"); - boolean foundSessionCookie = false; - for (String cookie : cookies) { - if (StringUtils.containsIgnoreCase(cookie, "JSESSIONID")) { - foundSessionCookie = true; - assertThat(cookie).containsIgnoringCase("Secure").containsIgnoringCase("HttpOnly"); - } - } - if (!foundSessionCookie) { - fail("Session cookie not found"); - } - } -} diff --git a/server/sonar-process-monitor/src/test/resources/org/sonar/process/ProcessTest/sonar.properties b/server/sonar-process-monitor/src/test/resources/org/sonar/process/ProcessTest/sonar.properties index 4c4ddb2f130..583c4c45f1f 100644 --- a/server/sonar-process-monitor/src/test/resources/org/sonar/process/ProcessTest/sonar.properties +++ b/server/sonar-process-monitor/src/test/resources/org/sonar/process/ProcessTest/sonar.properties @@ -87,76 +87,21 @@ sonar.jdbc.timeBetweenEvictionRunsMillis=30000 # TCP port for incoming HTTP connections. Disabled when value is -1. #sonar.web.port=9000 -# TCP port for incoming HTTPS connections. Disabled when value is -1 (default). -#sonar.web.https.port=-1 - -# HTTPS - the alias used to for the server certificate in the keystore. -# If not specified the first key read in the keystore is used. -#sonar.web.https.keyAlias= - -# HTTPS - the password used to access the server certificate from the -# specified keystore file. The default value is "changeit". -#sonar.web.https.keyPass=changeit - -# HTTPS - the pathname of the keystore file where is stored the server certificate. -# By default, the pathname is the file ".keystore" in the user home. -# If keystoreType doesn't need a file use empty value. -#sonar.web.https.keystoreFile= - -# HTTPS - the password used to access the specified keystore file. The default -# value is the value of sonar.web.https.keyPass. -#sonar.web.https.keystorePass= - -# HTTPS - the type of keystore file to be used for the server certificate. -# The default value is JKS (Java KeyStore). -#sonar.web.https.keystoreType=JKS - -# HTTPS - the name of the keystore provider to be used for the server certificate. -# If not specified, the list of registered providers is traversed in preference order -# and the first provider that supports the keystore type is used (see sonar.web.https.keystoreType). -#sonar.web.https.keystoreProvider= - -# HTTPS - the pathname of the truststore file which contains trusted certificate authorities. -# By default, this would be the cacerts file in your JRE. -# If truststoreFile doesn't need a file use empty value. -#sonar.web.https.truststoreFile= - -# HTTPS - the password used to access the specified truststore file. -#sonar.web.https.truststorePass= - -# HTTPS - the type of truststore file to be used. -# The default value is JKS (Java KeyStore). -#sonar.web.https.truststoreType=JKS - -# HTTPS - the name of the truststore provider to be used for the server certificate. -# If not specified, the list of registered providers is traversed in preference order -# and the first provider that supports the truststore type is used (see sonar.web.https.truststoreType). -#sonar.web.https.truststoreProvider= - -# HTTPS - whether to enable client certificate authentication. -# The default is false (client certificates disabled). -# Other possible values are 'want' (certificates will be requested, but not required), -# and 'true' (certificates are required). -#sonar.web.https.clientAuth=false - # The maximum number of connections that the server will accept and process at any given time. # When this number has been reached, the server will not accept any more connections until # the number of connections falls below this value. The operating system may still accept connections # based on the sonar.web.connections.acceptCount property. The default value is 50 for each # enabled connector. #sonar.web.http.maxThreads=50 -#sonar.web.https.maxThreads=50 # The minimum number of threads always kept running. The default value is 5 for each # enabled connector. #sonar.web.http.minThreads=5 -#sonar.web.https.minThreads=5 # The maximum queue length for incoming connection requests when all possible request processing # threads are in use. Any requests received when the queue is full will be refused. # The default value is 25 for each enabled connector. #sonar.web.http.acceptCount=25 -#sonar.web.https.acceptCount=25 # Access logs are generated in the file logs/access.log. This file is rolled over when it's 5Mb. # An archive of 3 files is kept in the same directory. diff --git a/server/sonar-process/src/test/resources/org/sonar/process/ProcessTest/sonar.properties b/server/sonar-process/src/test/resources/org/sonar/process/ProcessTest/sonar.properties index 4c4ddb2f130..583c4c45f1f 100644 --- a/server/sonar-process/src/test/resources/org/sonar/process/ProcessTest/sonar.properties +++ b/server/sonar-process/src/test/resources/org/sonar/process/ProcessTest/sonar.properties @@ -87,76 +87,21 @@ sonar.jdbc.timeBetweenEvictionRunsMillis=30000 # TCP port for incoming HTTP connections. Disabled when value is -1. #sonar.web.port=9000 -# TCP port for incoming HTTPS connections. Disabled when value is -1 (default). -#sonar.web.https.port=-1 - -# HTTPS - the alias used to for the server certificate in the keystore. -# If not specified the first key read in the keystore is used. -#sonar.web.https.keyAlias= - -# HTTPS - the password used to access the server certificate from the -# specified keystore file. The default value is "changeit". -#sonar.web.https.keyPass=changeit - -# HTTPS - the pathname of the keystore file where is stored the server certificate. -# By default, the pathname is the file ".keystore" in the user home. -# If keystoreType doesn't need a file use empty value. -#sonar.web.https.keystoreFile= - -# HTTPS - the password used to access the specified keystore file. The default -# value is the value of sonar.web.https.keyPass. -#sonar.web.https.keystorePass= - -# HTTPS - the type of keystore file to be used for the server certificate. -# The default value is JKS (Java KeyStore). -#sonar.web.https.keystoreType=JKS - -# HTTPS - the name of the keystore provider to be used for the server certificate. -# If not specified, the list of registered providers is traversed in preference order -# and the first provider that supports the keystore type is used (see sonar.web.https.keystoreType). -#sonar.web.https.keystoreProvider= - -# HTTPS - the pathname of the truststore file which contains trusted certificate authorities. -# By default, this would be the cacerts file in your JRE. -# If truststoreFile doesn't need a file use empty value. -#sonar.web.https.truststoreFile= - -# HTTPS - the password used to access the specified truststore file. -#sonar.web.https.truststorePass= - -# HTTPS - the type of truststore file to be used. -# The default value is JKS (Java KeyStore). -#sonar.web.https.truststoreType=JKS - -# HTTPS - the name of the truststore provider to be used for the server certificate. -# If not specified, the list of registered providers is traversed in preference order -# and the first provider that supports the truststore type is used (see sonar.web.https.truststoreType). -#sonar.web.https.truststoreProvider= - -# HTTPS - whether to enable client certificate authentication. -# The default is false (client certificates disabled). -# Other possible values are 'want' (certificates will be requested, but not required), -# and 'true' (certificates are required). -#sonar.web.https.clientAuth=false - # The maximum number of connections that the server will accept and process at any given time. # When this number has been reached, the server will not accept any more connections until # the number of connections falls below this value. The operating system may still accept connections # based on the sonar.web.connections.acceptCount property. The default value is 50 for each # enabled connector. #sonar.web.http.maxThreads=50 -#sonar.web.https.maxThreads=50 # The minimum number of threads always kept running. The default value is 5 for each # enabled connector. #sonar.web.http.minThreads=5 -#sonar.web.https.minThreads=5 # The maximum queue length for incoming connection requests when all possible request processing # threads are in use. Any requests received when the queue is full will be refused. # The default value is 25 for each enabled connector. #sonar.web.http.acceptCount=25 -#sonar.web.https.acceptCount=25 # Access logs are generated in the file logs/access.log. This file is rolled over when it's 5Mb. # An archive of 3 files is kept in the same directory. diff --git a/server/sonar-server/src/main/java/org/sonar/server/app/TomcatConnectors.java b/server/sonar-server/src/main/java/org/sonar/server/app/TomcatConnectors.java index ba1a67a7e57..bcf14fed9ec 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/app/TomcatConnectors.java +++ b/server/sonar-server/src/main/java/org/sonar/server/app/TomcatConnectors.java @@ -19,24 +19,24 @@ */ package org.sonar.server.app; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; +import com.google.common.base.Predicates; import java.util.HashSet; import java.util.List; import java.util.Set; +import javax.annotation.CheckForNull; import javax.annotation.Nullable; import org.apache.catalina.connector.Connector; import org.apache.catalina.startup.Tomcat; import org.sonar.process.Props; +import static com.google.common.collect.FluentIterable.from; +import static java.util.Arrays.asList; + /** * Configuration of Tomcat connectors */ class TomcatConnectors { - public static final String PROP_HTTPS_CIPHERS = "sonar.web.https.ciphers"; - public static final int DISABLED_PORT = -1; public static final String HTTP_PROTOCOL = "HTTP/1.1"; public static final String AJP_PROTOCOL = "AJP/1.3"; @@ -47,9 +47,9 @@ class TomcatConnectors { } static void configure(Tomcat tomcat, Props props) { - List connectors = new ArrayList<>(); - connectors.addAll(Arrays.asList(newHttpConnector(props), newAjpConnector(props), newHttpsConnector(props))); - connectors.removeAll(Collections.singleton(null)); + List connectors = from(asList(newHttpConnector(props), newAjpConnector(props))) + .filter(Predicates.notNull()) + .toList(); verify(connectors); @@ -67,13 +67,13 @@ class TomcatConnectors { for (Connector connector : connectors) { int port = connector.getPort(); if (ports.contains(port)) { - throw new IllegalStateException(String.format("HTTP, AJP and HTTPS must not use the same port %d", port)); + throw new IllegalStateException(String.format("HTTP and AJP must not use the same port %d", port)); } ports.add(port); } } - @Nullable + @CheckForNull private static Connector newHttpConnector(Props props) { Connector connector = null; // Not named "sonar.web.http.port" to keep backward-compatibility @@ -86,47 +86,15 @@ class TomcatConnectors { return connector; } - @Nullable + @CheckForNull private static Connector newAjpConnector(Props props) { - Connector connector = null; int port = props.valueAsInt("sonar.ajp.port", DISABLED_PORT); if (port > DISABLED_PORT) { - connector = newConnector(props, AJP_PROTOCOL, "http"); - connector.setPort(port); - } - return connector; - } - - @Nullable - private static Connector newHttpsConnector(Props props) { - Connector connector = null; - int port = props.valueAsInt("sonar.web.https.port", DISABLED_PORT); - if (port > DISABLED_PORT) { - connector = newConnector(props, HTTP_PROTOCOL, "https"); + Connector connector = newConnector(props, AJP_PROTOCOL, "http"); connector.setPort(port); - connector.setSecure(true); - connector.setScheme("https"); - configureMaxHttpHeaderSize(connector); - setConnectorAttribute(connector, "keyAlias", props.value("sonar.web.https.keyAlias")); - String keyPassword = props.value("sonar.web.https.keyPass", "changeit"); - setConnectorAttribute(connector, "keyPass", keyPassword); - setConnectorAttribute(connector, "keystorePass", props.value("sonar.web.https.keystorePass", keyPassword)); - setConnectorAttribute(connector, "keystoreFile", props.value("sonar.web.https.keystoreFile")); - setConnectorAttribute(connector, "keystoreType", props.value("sonar.web.https.keystoreType", "JKS")); - setConnectorAttribute(connector, "keystoreProvider", props.value("sonar.web.https.keystoreProvider")); - setConnectorAttribute(connector, "truststorePass", props.value("sonar.web.https.truststorePass", "changeit")); - setConnectorAttribute(connector, "truststoreFile", props.value("sonar.web.https.truststoreFile")); - setConnectorAttribute(connector, "truststoreType", props.value("sonar.web.https.truststoreType", "JKS")); - setConnectorAttribute(connector, "truststoreProvider", props.value("sonar.web.https.truststoreProvider")); - setConnectorAttribute(connector, "clientAuth", props.value("sonar.web.https.clientAuth", "false")); - setConnectorAttribute(connector, "ciphers", props.value(PROP_HTTPS_CIPHERS)); - // SSLv3 must not be enable because of Poodle vulnerability - // See https://jira.sonarsource.com/browse/SONAR-5860 - setConnectorAttribute(connector, "sslEnabledProtocols", "TLSv1,TLSv1.1,TLSv1.2"); - setConnectorAttribute(connector, "sslProtocol", "TLS"); - setConnectorAttribute(connector, "SSLEnabled", true); + return connector; } - return connector; + return null; } /** diff --git a/server/sonar-server/src/main/java/org/sonar/server/app/TomcatStartupLogs.java b/server/sonar-server/src/main/java/org/sonar/server/app/TomcatStartupLogs.java index 5f107784be9..cba0409fc00 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/app/TomcatStartupLogs.java +++ b/server/sonar-server/src/main/java/org/sonar/server/app/TomcatStartupLogs.java @@ -22,7 +22,6 @@ package org.sonar.server.app; import org.apache.catalina.connector.Connector; import org.apache.catalina.startup.Tomcat; import org.apache.commons.lang.StringUtils; -import org.apache.coyote.http11.AbstractHttp11JsseProtocol; import org.sonar.api.utils.log.Logger; import org.sonar.process.Props; @@ -41,8 +40,6 @@ class TomcatStartupLogs { for (Connector connector : connectors) { if (StringUtils.containsIgnoreCase(connector.getProtocol(), "AJP")) { logAjp(connector); - } else if (StringUtils.equalsIgnoreCase(connector.getScheme(), "https")) { - logHttps(connector); } else if (StringUtils.equalsIgnoreCase(connector.getScheme(), "http")) { logHttp(connector); } else { @@ -59,17 +56,4 @@ class TomcatStartupLogs { log.info(String.format("HTTP connector enabled on port %d", connector.getPort())); } - private void logHttps(Connector connector) { - StringBuilder sb = new StringBuilder(); - sb.append("HTTPS connector enabled on port ").append(connector.getPort()); - - AbstractHttp11JsseProtocol protocol = (AbstractHttp11JsseProtocol) connector.getProtocolHandler(); - sb.append(" | ciphers="); - if (props.contains(TomcatConnectors.PROP_HTTPS_CIPHERS)) { - sb.append(StringUtils.join(protocol.getCiphersUsed(), ",")); - } else { - sb.append("JVM defaults"); - } - log.info(sb.toString()); - } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/app/StartupLogsTest.java b/server/sonar-server/src/test/java/org/sonar/server/app/StartupLogsTest.java index 9322829aa21..bb856924dda 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/app/StartupLogsTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/app/StartupLogsTest.java @@ -22,7 +22,6 @@ package org.sonar.server.app; import java.util.Properties; import org.apache.catalina.connector.Connector; import org.apache.catalina.startup.Tomcat; -import org.apache.coyote.http11.AbstractHttp11JsseProtocol; import org.junit.Test; import org.mockito.Mockito; import org.sonar.api.utils.log.Logger; @@ -63,33 +62,6 @@ public class StartupLogsTest { verifyNoMoreInteractions(logger); } - @Test - public void logHttps_default_ciphers() { - Connector connector = newConnector("HTTP/1.1", "https"); - when(tomcat.getService().findConnectors()).thenReturn(new Connector[] {connector}); - - underTest.log(tomcat); - - verify(logger).info("HTTPS connector enabled on port 1234 | ciphers=JVM defaults"); - verifyNoMoreInteractions(logger); - } - - @Test - public void logHttps_overridden_ciphers() { - Connector connector = mock(Connector.class); - when(connector.getScheme()).thenReturn("https"); - when(connector.getPort()).thenReturn(1234); - AbstractHttp11JsseProtocol protocol = mock(AbstractHttp11JsseProtocol.class); - when(protocol.getCiphersUsed()).thenReturn(new String[] {"SSL_RSA", "TLS_RSA_WITH_RC4"}); - when(connector.getProtocolHandler()).thenReturn(protocol); - when(tomcat.getService().findConnectors()).thenReturn(new Connector[] {connector}); - props.set(TomcatConnectors.PROP_HTTPS_CIPHERS, "SSL_RSA,TLS_RSA_WITH_RC4"); - underTest.log(tomcat); - - verify(logger).info("HTTPS connector enabled on port 1234 | ciphers=SSL_RSA,TLS_RSA_WITH_RC4"); - verifyNoMoreInteractions(logger); - } - @Test public void unsupported_connector() { Connector connector = mock(Connector.class, Mockito.RETURNS_DEEP_STUBS); diff --git a/server/sonar-server/src/test/java/org/sonar/server/app/TomcatConnectorsTest.java b/server/sonar-server/src/test/java/org/sonar/server/app/TomcatConnectorsTest.java index bc3861ae37b..ee7bd281f38 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/app/TomcatConnectorsTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/app/TomcatConnectorsTest.java @@ -90,8 +90,6 @@ public class TomcatConnectorsTest { Properties p = new Properties(); p.setProperty("sonar.web.port", "9000"); p.setProperty("sonar.web.http.minThreads", "2"); - p.setProperty("sonar.web.https.port", "9443"); - p.setProperty("sonar.web.https.minThreads", "5"); Props props = new Props(p); TomcatConnectors.configure(tomcat, props); @@ -103,20 +101,12 @@ public class TomcatConnectorsTest { return c.getPort() == 9000 && c.getProperty("minSpareThreads").equals(2); } })); - verify(tomcat.getService()).addConnector(argThat(new ArgumentMatcher() { - @Override - public boolean matches(Object o) { - Connector c = (Connector) o; - return c.getPort() == 9443 && c.getProperty("minSpareThreads").equals(5); - } - })); } @Test public void fail_if_http_connectors_are_disabled() { Properties p = new Properties(); p.setProperty("sonar.web.port", "-1"); - p.setProperty("sonar.web.https.port", "-1"); Props props = new Props(p); try { @@ -127,24 +117,11 @@ public class TomcatConnectorsTest { } } - @Test - public void only_https_is_enabled() { - Properties p = new Properties(); - p.setProperty("sonar.web.port", "-1"); - p.setProperty("sonar.web.https.port", "9443"); - Props props = new Props(p); - - TomcatConnectors.configure(tomcat, props); - - verifyConnectorProperty(tomcat, "https", "clientAuth", "false"); - } - @Test public void all_connectors_are_enabled() { Properties p = new Properties(); p.setProperty("sonar.web.port", "9000"); p.setProperty("sonar.ajp.port", "9009"); - p.setProperty("sonar.web.https.port", "9443"); Props props = new Props(p); TomcatConnectors.configure(tomcat, props); @@ -163,27 +140,19 @@ public class TomcatConnectorsTest { return c.getScheme().equals("http") && c.getPort() == 9009 && c.getProtocol().equals(TomcatConnectors.AJP_PROTOCOL); } })); - verify(tomcat.getService()).addConnector(argThat(new ArgumentMatcher() { - @Override - public boolean matches(Object o) { - Connector c = (Connector) o; - return c.getScheme().equals("https") && c.getPort() == 9443 && c.getProtocol().equals(TomcatConnectors.HTTP_PROTOCOL); - } - })); } @Test - public void http_and_ajp_and_https_ports_should_be_different() { + public void http_and_ajp_ports_should_be_different() { Properties p = new Properties(); p.setProperty("sonar.web.port", "9000"); p.setProperty("sonar.ajp.port", "9000"); - p.setProperty("sonar.web.https.port", "9000"); try { TomcatConnectors.configure(tomcat, new Props(p)); fail(); } catch (IllegalStateException e) { - assertThat(e).hasMessage("HTTP, AJP and HTTPS must not use the same port 9000"); + assertThat(e).hasMessage("HTTP and AJP must not use the same port 9000"); } } @@ -192,7 +161,6 @@ public class TomcatConnectorsTest { Properties p = new Properties(); p.setProperty("sonar.web.port", "9000"); p.setProperty("sonar.ajp.port", "9009"); - p.setProperty("sonar.web.https.port", "9443"); TomcatConnectors.configure(tomcat, new Props(p)); @@ -210,20 +178,12 @@ public class TomcatConnectorsTest { return c.getScheme().equals("http") && c.getPort() == 9009 && ((InetAddress) c.getProperty("address")).getHostAddress().equals("0.0.0.0"); } })); - verify(tomcat.getService()).addConnector(argThat(new ArgumentMatcher() { - @Override - public boolean matches(Object o) { - Connector c = (Connector) o; - return c.getScheme().equals("https") && c.getPort() == 9443 && ((InetAddress) c.getProperty("address")).getHostAddress().equals("0.0.0.0"); - } - })); } @Test public void bind_to_specific_address() { Properties p = new Properties(); p.setProperty("sonar.web.port", "9000"); - p.setProperty("sonar.web.https.port", "9443"); p.setProperty("sonar.web.host", "1.2.3.4"); TomcatConnectors.configure(tomcat, new Props(p)); @@ -235,51 +195,15 @@ public class TomcatConnectorsTest { return c.getScheme().equals("http") && c.getPort() == 9000 && ((InetAddress) c.getProperty("address")).getHostAddress().equals("1.2.3.4"); } })); - verify(tomcat.getService()).addConnector(argThat(new ArgumentMatcher() { - @Override - public boolean matches(Object o) { - Connector c = (Connector) o; - return c.getScheme().equals("https") && c.getPort() == 9443 && ((InetAddress) c.getProperty("address")).getHostAddress().equals("1.2.3.4"); - } - })); - } - - @Test - public void enable_client_auth() { - Properties p = new Properties(); - p.setProperty("sonar.web.port", "-1"); - p.setProperty("sonar.web.https.port", "9443"); - p.setProperty("sonar.web.https.clientAuth", "want"); - Props props = new Props(p); - - TomcatConnectors.configure(tomcat, props); - - verifyConnectorProperty(tomcat, "https", "clientAuth", "want"); } @Test - public void require_client_auth() { - Properties p = new Properties(); - p.setProperty("sonar.web.port", "-1"); - p.setProperty("sonar.web.https.port", "9443"); - p.setProperty("sonar.web.https.clientAuth", "true"); - Props props = new Props(p); - - TomcatConnectors.configure(tomcat, props); - - verifyConnectorProperty(tomcat, "https", "clientAuth", "true"); - } - - @Test - public void test_max_http_header_size_for_http_and_https_connections() { + public void test_max_http_header_size_for_http_connection() { Properties properties = new Properties(); - properties.setProperty("sonar.web.https.port", "9443"); - Props props = new Props(properties); TomcatConnectors.configure(tomcat, props); verifyConnectorProperty(tomcat, "http", "maxHttpHeaderSize", TomcatConnectors.MAX_HTTP_HEADER_SIZE_BYTES); - verifyConnectorProperty(tomcat, "https", "maxHttpHeaderSize", TomcatConnectors.MAX_HTTP_HEADER_SIZE_BYTES); } private static void verifyConnectorProperty(Tomcat tomcat, final String connectorScheme, diff --git a/sonar-application/src/main/assembly/conf/sonar.properties b/sonar-application/src/main/assembly/conf/sonar.properties index 00f8bde74c6..1d700de0695 100644 --- a/sonar-application/src/main/assembly/conf/sonar.properties +++ b/sonar-application/src/main/assembly/conf/sonar.properties @@ -57,9 +57,9 @@ #----- Connection pool settings # The maximum number of active connections that can be allocated # at the same time, or negative for no limit. -# The recommended value is 1.2 * max sizes of HTTP/HTTPS pools. For example if both HTTP and -# HTTPS ports are enabled with default sizes (50, see properties sonar.web.http.maxThreads -# and sonar.web.https.maxThreads) then sonar.jdbc.maxActive should be 1.2 * (50 + 50) = 120. +# The recommended value is 1.2 * max sizes of HTTP pools. For example if HTTP ports are +# enabled with default sizes (50, see property sonar.web.http.maxThreads) +# then sonar.jdbc.maxActive should be 1.2 * (50) = 120. #sonar.jdbc.maxActive=60 # The maximum number of connections that can remain idle in the @@ -108,91 +108,19 @@ #sonar.web.port=9000 -# Recommendation for HTTPS -# SonarQube natively supports HTTPS. However using a reverse proxy -# infrastructure is the recommended way to set up your SonarQube installation -# on production environments which need to be highly secured. -# This allows to fully master all the security parameters that you want. - -# TCP port for incoming HTTPS connections. Disabled when value is -1 (default). -#sonar.web.https.port=-1 - -# HTTPS - the alias used to for the server certificate in the keystore. -# If not specified the first key read in the keystore is used. -#sonar.web.https.keyAlias= - -# HTTPS - the password used to access the server certificate from the -# specified keystore file. The default value is "changeit". -#sonar.web.https.keyPass=changeit - -# HTTPS - the pathname of the keystore file where is stored the server certificate. -# By default, the pathname is the file ".keystore" in the user home. -# If keystoreType doesn't need a file use empty value. -#sonar.web.https.keystoreFile= - -# HTTPS - the password used to access the specified keystore file. The default -# value is the value of sonar.web.https.keyPass. -#sonar.web.https.keystorePass= - -# HTTPS - the type of keystore file to be used for the server certificate. -# The default value is JKS (Java KeyStore). -#sonar.web.https.keystoreType=JKS - -# HTTPS - the name of the keystore provider to be used for the server certificate. -# If not specified, the list of registered providers is traversed in preference order -# and the first provider that supports the keystore type is used (see sonar.web.https.keystoreType). -#sonar.web.https.keystoreProvider= - -# HTTPS - the pathname of the truststore file which contains trusted certificate authorities. -# By default, this would be the cacerts file in your JRE. -# If truststoreFile doesn't need a file use empty value. -#sonar.web.https.truststoreFile= - -# HTTPS - the password used to access the specified truststore file. -#sonar.web.https.truststorePass= - -# HTTPS - the type of truststore file to be used. -# The default value is JKS (Java KeyStore). -#sonar.web.https.truststoreType=JKS - -# HTTPS - the name of the truststore provider to be used for the server certificate. -# If not specified, the list of registered providers is traversed in preference order -# and the first provider that supports the truststore type is used (see sonar.web.https.truststoreType). -#sonar.web.https.truststoreProvider= - -# HTTPS - whether to enable client certificate authentication. -# The default is false (client certificates disabled). -# Other possible values are 'want' (certificates will be requested, but not required), -# and 'true' (certificates are required). -#sonar.web.https.clientAuth=false - -# HTTPS - comma separated list of encryption ciphers to support for HTTPS connections. -# If specified, only the ciphers that are listed and supported by the SSL implementation will be used. -# By default, the default ciphers for the JVM will be used. Note that this usually means that the weak -# export grade ciphers, for instance RC4, will be included in the list of available ciphers. -# The ciphers are specified using the JSSE cipher naming convention (see -# https://www.openssl.org/docs/apps/ciphers.html) -# Example: sonar.web.https.ciphers=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 -#sonar.web.https.ciphers= - # The maximum number of connections that the server will accept and process at any given time. # When this number has been reached, the server will not accept any more connections until # the number of connections falls below this value. The operating system may still accept connections -# based on the sonar.web.connections.acceptCount property. The default value is 50 for each -# enabled connector. +# based on the sonar.web.connections.acceptCount property. The default value is 50. #sonar.web.http.maxThreads=50 -#sonar.web.https.maxThreads=50 -# The minimum number of threads always kept running. The default value is 5 for each -# enabled connector. +# The minimum number of threads always kept running. The default value is 5. #sonar.web.http.minThreads=5 -#sonar.web.https.minThreads=5 # The maximum queue length for incoming connection requests when all possible request processing # threads are in use. Any requests received when the queue is full will be refused. -# The default value is 25 for each enabled connector. +# The default value is 25. #sonar.web.http.acceptCount=25 -#sonar.web.https.acceptCount=25 # TCP port for incoming AJP connections. Disabled if value is -1. Disabled by default. #sonar.ajp.port=-1 -- 2.39.5