From 9e1fded16c1dc80f886af1db4413cbe78a245d7f Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Fri, 27 Sep 2024 16:27:04 +0200 Subject: SONAR-23013 Improve coverage --- .../scanner/http/ScannerWsClientProvider.java | 28 ++++++++++++++++------ .../scanner/http/ScannerWsClientProviderTest.java | 14 +++++++++++ 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/http/ScannerWsClientProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/http/ScannerWsClientProvider.java index 09265c58ce7..67e224f8845 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/http/ScannerWsClientProvider.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/http/ScannerWsClientProvider.java @@ -19,6 +19,7 @@ */ package org.sonar.scanner.http; +import java.io.IOException; import java.io.InputStream; import java.net.InetSocketAddress; import java.net.Proxy; @@ -26,11 +27,16 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; import java.time.Duration; import java.time.format.DateTimeParseException; import nl.altindag.ssl.SSLFactory; import nl.altindag.ssl.exception.GenericKeyStoreException; import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.sonar.api.CoreProperties; import org.sonar.api.notifications.AnalysisWarnings; import org.sonar.api.utils.System2; @@ -52,6 +58,9 @@ import static org.sonar.core.config.ProxyProperties.HTTP_PROXY_PASSWORD; import static org.sonar.core.config.ProxyProperties.HTTP_PROXY_USER; public class ScannerWsClientProvider { + + private static final Logger LOG = LoggerFactory.getLogger(ScannerWsClientProvider.class); + static final int DEFAULT_CONNECT_TIMEOUT = 5; static final int DEFAULT_RESPONSE_TIMEOUT = 0; static final String READ_TIMEOUT_SEC_PROPERTY = "sonar.ws.timeout"; @@ -149,22 +158,27 @@ public class ScannerWsClientProvider { } var trustStoreConfig = sslConfig.getTrustStore(); if (trustStoreConfig != null && Files.exists(trustStoreConfig.getPath())) { - KeyStore trustStore = loadKeyStore( - trustStoreConfig.getPath(), - trustStoreConfig.getKeyStorePassword().toCharArray(), - trustStoreConfig.getKeyStoreType()); + KeyStore trustStore; + try { + trustStore = loadKeyStoreWithBouncyCastle( + trustStoreConfig.getPath(), + trustStoreConfig.getKeyStorePassword().toCharArray(), + trustStoreConfig.getKeyStoreType()); + LOG.debug("Loaded truststore from '{}' containing {} certificates", trustStoreConfig.getPath(), trustStore.size()); + } catch (KeyStoreException | IOException | CertificateException | NoSuchAlgorithmException e) { + throw new GenericKeyStoreException("Unable to read truststore from '" + trustStoreConfig.getPath() + "'", e); + } sslFactoryBuilder.withTrustMaterial(trustStore); } return sslFactoryBuilder.build(); } - public static KeyStore loadKeyStore(Path keystorePath, char[] keystorePassword, String keystoreType) { + static KeyStore loadKeyStoreWithBouncyCastle(Path keystorePath, char[] keystorePassword, String keystoreType) throws IOException, + KeyStoreException, CertificateException, NoSuchAlgorithmException { try (InputStream keystoreInputStream = Files.newInputStream(keystorePath, StandardOpenOption.READ)) { KeyStore keystore = KeyStore.getInstance(keystoreType, new BouncyCastleProvider()); keystore.load(keystoreInputStream, keystorePassword); return keystore; - } catch (Exception e) { - throw new GenericKeyStoreException(e); } } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/http/ScannerWsClientProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/http/ScannerWsClientProviderTest.java index e605999ddd3..3aea5460db9 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/http/ScannerWsClientProviderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/http/ScannerWsClientProviderTest.java @@ -30,6 +30,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Properties; +import nl.altindag.ssl.exception.GenericKeyStoreException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Tag; @@ -319,6 +320,19 @@ class ScannerWsClientProviderTest { assertThat(r.content()).isEqualTo("Success"); } } + + @Test + void it_should_fail_if_invalid_truststore_password() { + scannerProps.put("sonar.host.url", sonarqubeMock.baseUrl()); + scannerProps.put("sonar.scanner.truststorePath", toPath(requireNonNull(ScannerWsClientProviderTest.class.getResource("/ssl/client-truststore.p12"))).toString()); + scannerProps.put("sonar.scanner.truststorePassword", "wrong_password"); + + var scannerPropsObj = new ScannerProperties(scannerProps); + var thrown = assertThrows(GenericKeyStoreException.class, + () -> underTest.provide(scannerPropsObj, env, GLOBAL_ANALYSIS_MODE, system2, ANALYSIS_WARNINGS, sonarUserHome)); + + assertThat(thrown).hasStackTraceContaining("Unable to read truststore"); + } } @Nested -- cgit v1.2.3