summaryrefslogtreecommitdiffstats
path: root/it/it-tests/src/test/java/administation/HttpsTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'it/it-tests/src/test/java/administation/HttpsTest.java')
-rw-r--r--it/it-tests/src/test/java/administation/HttpsTest.java182
1 files changed, 182 insertions, 0 deletions
diff --git a/it/it-tests/src/test/java/administation/HttpsTest.java b/it/it-tests/src/test/java/administation/HttpsTest.java
new file mode 100644
index 00000000000..1f77039e869
--- /dev/null
+++ b/it/it-tests/src/test/java/administation/HttpsTest.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2009-2014 SonarSource SA
+ * All rights reserved
+ * mailto:contact AT sonarsource DOT com
+ */
+package administation;
+
+import com.sonar.orchestrator.Orchestrator;
+import com.sonar.orchestrator.util.NetworkUtils;
+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.rules.ExpectedException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+
+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("/administration/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("/administration/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 + "/sonar");
+ 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 + "/sonar/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("<body");
+ } finally {
+ IOUtils.closeQuietly(input);
+ }
+ }
+
+ /**
+ * SSF-13 HttpOnly flag
+ * SSF-16 Secure flag
+ */
+ private void checkCookieFlags(HttpsURLConnection connection) {
+ List<String> 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");
+ }
+ }
+}