Skip to content

Commit

Permalink
SCANJLIB-241 Add property to skip loading of OS-level SSL certificates
Browse files Browse the repository at this point in the history
  • Loading branch information
henryju committed Dec 2, 2024
1 parent 723eb33 commit fe8416a
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ private ScannerProperties() {
public static final String SONAR_SCANNER_KEYSTORE_PASSWORD = "sonar.scanner.keystorePassword";
public static final String SONAR_SCANNER_TRUSTSTORE_PATH = "sonar.scanner.truststorePath";
public static final String SONAR_SCANNER_TRUSTSTORE_PASSWORD = "sonar.scanner.truststorePassword";

public static final String SONAR_SCANNER_SKIP_SYSTEM_TRUSTSTORE = "sonar.scanner.skipSystemTruststore";
/**
* Skip analysis.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import static java.lang.Integer.parseInt;
import static java.lang.String.format;
import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
import static org.sonarsource.scanner.lib.ScannerProperties.SONAR_SCANNER_SKIP_SYSTEM_TRUSTSTORE;
import static org.sonarsource.scanner.lib.ScannerProperties.SONAR_SCANNER_CONNECT_TIMEOUT;
import static org.sonarsource.scanner.lib.ScannerProperties.SONAR_SCANNER_KEYSTORE_PASSWORD;
import static org.sonarsource.scanner.lib.ScannerProperties.SONAR_SCANNER_KEYSTORE_PATH;
Expand Down Expand Up @@ -79,6 +80,7 @@ public class HttpConfig {
private final String proxyUser;
private final String proxyPassword;
private final String userAgent;
private final boolean skipSystemTrustMaterial;

public HttpConfig(Map<String, String> bootstrapProperties, Path sonarUserHome) {
this.webApiBaseUrl = StringUtils.removeEnd(bootstrapProperties.get(ScannerProperties.HOST_URL), "/");
Expand All @@ -94,6 +96,7 @@ public HttpConfig(Map<String, String> bootstrapProperties, Path sonarUserHome) {
this.proxy = loadProxy(bootstrapProperties);
this.proxyUser = loadProxyUser(bootstrapProperties);
this.proxyPassword = loadProxyPassword(bootstrapProperties);
this.skipSystemTrustMaterial = Boolean.parseBoolean(defaultIfBlank(bootstrapProperties.get(SONAR_SCANNER_SKIP_SYSTEM_TRUSTSTORE), "false"));
}

private static String loadProxyPassword(Map<String, String> bootstrapProperties) {
Expand Down Expand Up @@ -249,4 +252,8 @@ public String getProxyUser() {
public String getProxyPassword() {
return proxyPassword;
}

public boolean skipSystemTruststore() {
return skipSystemTrustMaterial;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Arrays.asList;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.sonarsource.scanner.lib.ScannerProperties.SONAR_SCANNER_SKIP_SYSTEM_TRUSTSTORE;

public class OkHttpClientFactory {

Expand All @@ -72,7 +73,7 @@ private OkHttpClientFactory() {

static OkHttpClient create(HttpConfig httpConfig) {

var sslContext = configureSsl(httpConfig.getSslConfig());
var sslContext = configureSsl(httpConfig.getSslConfig(), httpConfig.skipSystemTruststore());

OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder()
.connectTimeout(httpConfig.getConnectTimeout().toMillis(), TimeUnit.MILLISECONDS)
Expand Down Expand Up @@ -112,10 +113,14 @@ static OkHttpClient create(HttpConfig httpConfig) {
return okHttpClientBuilder.build();
}

private static SSLFactory configureSsl(SslConfig sslConfig) {
private static SSLFactory configureSsl(SslConfig sslConfig, boolean skipSystemTrustMaterial) {
var sslFactoryBuilder = SSLFactory.builder()
.withDefaultTrustMaterial()
.withSystemTrustMaterial();
.withDefaultTrustMaterial();
if (!skipSystemTrustMaterial) {
LOG.debug("Loading OS trusted SSL certificates...");
LOG.debug("This operation might be slow or even get stuck. You can skip it by passing the scanner property '{}=true'", SONAR_SCANNER_SKIP_SYSTEM_TRUSTSTORE);
sslFactoryBuilder.withSystemTrustMaterial();
}
if (System.getProperties().containsKey("javax.net.ssl.keyStore")) {
sslFactoryBuilder.withSystemPropertyDerivedIdentityMaterial();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.junitpioneer.jupiter.RestoreSystemProperties;
import org.slf4j.event.Level;
import testutils.LogTester;

import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl;
Expand All @@ -68,6 +70,9 @@ class OkHttpClientFactoryTest {

private final Map<String, String> bootstrapProperties = new HashMap<>();

@RegisterExtension
private LogTester logTester = new LogTester();

@TempDir
private Path sonarUserHomeDir;
private Path sonarUserHome;
Expand Down Expand Up @@ -131,6 +136,25 @@ void it_should_fail_if_invalid_keystore_password(String keystore, @Nullable Stri
}
}

@Test
void should_load_os_certificates_by_default() {
logTester.setLevel(Level.DEBUG);

OkHttpClientFactory.create(new HttpConfig(bootstrapProperties, sonarUserHome));

assertThat(logTester.logs(Level.DEBUG)).contains("Loading OS trusted SSL certificates...");
}

@Test
void should_skip_load_of_os_certificates_if_props_set() {
logTester.setLevel(Level.DEBUG);
bootstrapProperties.put("sonar.scanner.skipSystemTruststore", "true");

OkHttpClientFactory.create(new HttpConfig(bootstrapProperties, sonarUserHome));

assertThat(logTester.logs(Level.DEBUG)).doesNotContain("Loading OS trusted SSL certificates...");
}

@Nested
// Workaround until we move to Java 17+ and can make Wiremock extension static
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
Expand Down

0 comments on commit fe8416a

Please sign in to comment.