From bd22041edd9715212bc1c5a92eed393af80de95f Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Wed, 4 Feb 2015 11:05:39 +0100 Subject: [PATCH] SONAR-6140 use JVM ciphers by default --- .../java/org/sonar/server/app/Connectors.java | 9 +------ .../org/sonar/server/app/EmbeddedTomcat.java | 2 +- .../org/sonar/server/app/StartupLogs.java | 16 ++++++++---- .../org/sonar/server/app/StartupLogsTest.java | 26 ++++++++++++++----- .../src/main/assembly/conf/sonar.properties | 12 ++++++--- 5 files changed, 42 insertions(+), 23 deletions(-) diff --git a/server/sonar-server/src/main/java/org/sonar/server/app/Connectors.java b/server/sonar-server/src/main/java/org/sonar/server/app/Connectors.java index 83554f58773..1518117eafe 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/app/Connectors.java +++ b/server/sonar-server/src/main/java/org/sonar/server/app/Connectors.java @@ -39,13 +39,6 @@ class Connectors { public static final String PROP_HTTPS_CIPHERS = "sonar.web.https.ciphers"; - /** - * Removes the weak ciphers that are provided by default in JVM - * We follow the recommendations from Mozilla (Intermediate Compatibility) - * https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28default.29 - */ - public static final String DEFVAL_HTTPS_CIPHERS = "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA"; - 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"; @@ -125,7 +118,7 @@ class Connectors { 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, DEFVAL_HTTPS_CIPHERS)); + setConnectorAttribute(connector, "ciphers", props.value(PROP_HTTPS_CIPHERS)); // SSLv3 must not be enable because of Poodle vulnerability // See https://jira.codehaus.org/browse/SONAR-5860 setConnectorAttribute(connector, "sslEnabledProtocols", "TLSv1,TLSv1.1,TLSv1.2"); diff --git a/server/sonar-server/src/main/java/org/sonar/server/app/EmbeddedTomcat.java b/server/sonar-server/src/main/java/org/sonar/server/app/EmbeddedTomcat.java index 7d33ad00f11..ea651f54e01 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/app/EmbeddedTomcat.java +++ b/server/sonar-server/src/main/java/org/sonar/server/app/EmbeddedTomcat.java @@ -60,7 +60,7 @@ class EmbeddedTomcat { webappContext = Webapp.configure(tomcat, props); try { tomcat.start(); - new StartupLogs(LoggerFactory.getLogger(getClass())).log(tomcat); + new StartupLogs(props, LoggerFactory.getLogger(getClass())).log(tomcat); } catch (LifecycleException e) { Throwables.propagate(e); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/app/StartupLogs.java b/server/sonar-server/src/main/java/org/sonar/server/app/StartupLogs.java index cec1a2ea69a..d2e7f4e736a 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/app/StartupLogs.java +++ b/server/sonar-server/src/main/java/org/sonar/server/app/StartupLogs.java @@ -22,15 +22,17 @@ 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.ProtocolHandler; import org.apache.coyote.http11.AbstractHttp11JsseProtocol; import org.slf4j.Logger; +import org.sonar.process.Props; class StartupLogs { private final Logger log; + private final Props props; - StartupLogs(Logger log) { + StartupLogs(Props props, Logger log) { + this.props = props; this.log = log; } @@ -61,9 +63,13 @@ class StartupLogs { StringBuilder sb = new StringBuilder(); sb.append("HTTPS connector enabled on port ").append(connector.getPort()); - ProtocolHandler protocol = connector.getProtocolHandler(); - String[] ciphers = ((AbstractHttp11JsseProtocol) protocol).getCiphersUsed(); - sb.append(" | ciphers=").append(StringUtils.join(ciphers, ",")); + AbstractHttp11JsseProtocol protocol = (AbstractHttp11JsseProtocol) connector.getProtocolHandler(); + sb.append(" | ciphers="); + if (props.contains(Connectors.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 0fed81db6b5..ea80502c785 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 @@ -25,6 +25,9 @@ import org.apache.coyote.http11.AbstractHttp11JsseProtocol; import org.junit.Test; import org.mockito.Mockito; import org.slf4j.Logger; +import org.sonar.process.Props; + +import java.util.Properties; import static org.junit.Assert.fail; import static org.mockito.Mockito.*; @@ -33,7 +36,8 @@ public class StartupLogsTest { Tomcat tomcat = mock(Tomcat.class, Mockito.RETURNS_DEEP_STUBS); Logger logger = mock(Logger.class); - StartupLogs sut = new StartupLogs(logger); + Props props = new Props(new Properties()); + StartupLogs sut = new StartupLogs(props, logger); @Test public void logAjp() throws Exception { @@ -58,16 +62,26 @@ public class StartupLogsTest { } @Test - public void logHttps() throws Exception { - Connector connector = mock(Connector.class, Mockito.RETURNS_DEEP_STUBS); + public void logHttps_default_ciphers() throws Exception { + Connector connector = newConnector("HTTP/1.1", "https"); when(tomcat.getService().findConnectors()).thenReturn(new Connector[] {connector}); + + sut.log(tomcat); + + verify(logger).info("HTTPS connector enabled on port 1234 | ciphers=JVM defaults"); + verifyNoMoreInteractions(logger); + } + + @Test + public void logHttps_overridden_ciphers() throws Exception { + Connector connector = mock(Connector.class); when(connector.getScheme()).thenReturn("https"); - when(connector.getProtocol()).thenReturn("HTTP/1.1"); when(connector.getPort()).thenReturn(1234); AbstractHttp11JsseProtocol protocol = mock(AbstractHttp11JsseProtocol.class); - when(connector.getProtocolHandler()).thenReturn(protocol); 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(Connectors.PROP_HTTPS_CIPHERS, "SSL_RSA,TLS_RSA_WITH_RC4"); sut.log(tomcat); verify(logger).info("HTTPS connector enabled on port 1234 | ciphers=SSL_RSA,TLS_RSA_WITH_RC4"); diff --git a/sonar-application/src/main/assembly/conf/sonar.properties b/sonar-application/src/main/assembly/conf/sonar.properties index abc68188936..53fb2cfb207 100644 --- a/sonar-application/src/main/assembly/conf/sonar.properties +++ b/sonar-application/src/main/assembly/conf/sonar.properties @@ -102,6 +102,13 @@ # TCP port for incoming HTTP connections. Disabled when value is -1. #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 @@ -156,11 +163,10 @@ # 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) -# By default, the Mozilla recommendations are followed (Intermediate Compatibility). See -# https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28default.29 -# # 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= -- 2.39.5