4545import org .sonarsource .scanner .lib .internal .http .ssl .CertificateStore ;
4646import org .sonarsource .scanner .lib .internal .util .VersionUtils ;
4747
48+ import static java .util .Optional .ofNullable ;
4849import static org .sonarsource .scanner .lib .ScannerProperties .SCANNER_ARCH ;
4950import static org .sonarsource .scanner .lib .ScannerProperties .SCANNER_OS ;
51+ import static org .sonarsource .scanner .lib .ScannerProperties .SONAR_SCANNER_KEYSTORE_PASSWORD ;
52+ import static org .sonarsource .scanner .lib .ScannerProperties .SONAR_SCANNER_KEYSTORE_PATH ;
53+ import static org .sonarsource .scanner .lib .ScannerProperties .SONAR_SCANNER_TRUSTSTORE_PASSWORD ;
54+ import static org .sonarsource .scanner .lib .ScannerProperties .SONAR_SCANNER_TRUSTSTORE_PATH ;
5055
5156/**
5257 * Entry point to run a Sonar analysis programmatically.
@@ -58,6 +63,10 @@ public class ScannerEngineBootstrapper {
5863 private static final String SONARCLOUD_HOST = "https://sonarcloud.io" ;
5964 private static final String SONARCLOUD_REST_API = "https://api.sonarcloud.io" ;
6065 static final String SQ_VERSION_NEW_BOOTSTRAPPING = "10.6" ;
66+ private static final String JAVAX_NET_SSL_TRUST_STORE = "javax.net.ssl.trustStore" ;
67+ private static final String JAVAX_NET_SSL_TRUST_STORE_PASSWORD = "javax.net.ssl.trustStorePassword" ;
68+ private static final String JAVAX_NET_SSL_KEY_STORE = "javax.net.ssl.keyStore" ;
69+ private static final String JAVAX_NET_SSL_KEY_STORE_PASSWORD = "javax.net.ssl.keyStorePassword" ;
6170
6271 private final IsolatedLauncherFactory launcherFactory ;
6372 private final ScannerEngineLauncherFactory scannerEngineLauncherFactory ;
@@ -106,48 +115,31 @@ public ScannerEngineFacade bootstrap() {
106115 LOG .debug ("Scanner max available memory: {}" , FileUtils .byteCountToDisplaySize (Runtime .getRuntime ().maxMemory ()));
107116 }
108117 initBootstrapDefaultValues ();
109- var properties = Map .copyOf (bootstrapProperties );
110- var isSonarCloud = isSonarCloud (properties );
111- var isSimulation = properties .containsKey (InternalProperties .SCANNER_DUMP_TO_FILE );
112- var sonarUserHome = resolveSonarUserHome (properties );
118+ adaptJvmSslPropertiesToScannerProperties (bootstrapProperties , system );
119+ var immutableProperties = Map .copyOf (bootstrapProperties );
120+ var isSonarCloud = isSonarCloud (immutableProperties );
121+ var isSimulation = immutableProperties .containsKey (InternalProperties .SCANNER_DUMP_TO_FILE );
122+ var sonarUserHome = resolveSonarUserHome (immutableProperties );
113123 var fileCache = FileCache .create (sonarUserHome );
114- var httpConfig = new HttpConfig (bootstrapProperties , sonarUserHome );
124+ var httpConfig = new HttpConfig (immutableProperties , sonarUserHome );
115125 scannerHttpClient .init (httpConfig );
116126 String serverVersion = null ;
117127 if (!isSonarCloud ) {
118- serverVersion = getServerVersion (scannerHttpClient , isSimulation , properties );
128+ serverVersion = getServerVersion (scannerHttpClient , isSimulation , immutableProperties );
119129 }
120130
121131 if (isSimulation ) {
122- return new SimulationScannerEngineFacade (properties , isSonarCloud , serverVersion );
132+ return new SimulationScannerEngineFacade (immutableProperties , isSonarCloud , serverVersion );
123133 } else if (isSonarCloud || VersionUtils .isAtLeastIgnoringQualifier (serverVersion , SQ_VERSION_NEW_BOOTSTRAPPING )) {
124- var launcher = scannerEngineLauncherFactory .createLauncher (scannerHttpClient , fileCache , properties );
125- var adaptedProperties = adaptDeprecatedPropertiesForForkedBootstrapping (properties , httpConfig );
126- return new NewScannerEngineFacade (adaptedProperties , launcher , isSonarCloud , serverVersion );
134+ var launcher = scannerEngineLauncherFactory .createLauncher (scannerHttpClient , fileCache , immutableProperties );
135+ return new NewScannerEngineFacade (immutableProperties , launcher , isSonarCloud , serverVersion );
127136 } else {
128137 var launcher = launcherFactory .createLauncher (scannerHttpClient , fileCache );
129- var adaptedProperties = adaptDeprecatedPropertiesForInProcessBootstrapping (properties , httpConfig );
138+ var adaptedProperties = adaptDeprecatedPropertiesForInProcessBootstrapping (immutableProperties , httpConfig );
130139 return new InProcessScannerEngineFacade (adaptedProperties , launcher , false , serverVersion );
131140 }
132141 }
133142
134- /**
135- * New versions of SonarQube/SonarCloud will run on a separate VM. For people who used to rely on configuring SSL
136- * by inserting the trusted certificate in the Scanner JVM truststore,
137- * we need to adapt the properties to read from the truststore of the scanner JVM.
138- */
139- Map <String , String > adaptDeprecatedPropertiesForForkedBootstrapping (Map <String , String > properties , HttpConfig httpConfig ) {
140- var adaptedProperties = new HashMap <>(properties );
141- if (system .getProperty ("javax.net.ssl.trustStore" ) == null && httpConfig .getSslConfig ().getTrustStore () == null ) {
142- var defaultJvmTrustStoreLocation = Paths .get (System .getProperty ("java.home" ), "lib" , "security" , "cacerts" );
143- if (Files .isRegularFile (defaultJvmTrustStoreLocation )) {
144- LOG .debug ("Mapping default scanner JVM truststore location '{}' to new properties" , defaultJvmTrustStoreLocation );
145- adaptedProperties .put ("sonar.scanner.truststorePath" , defaultJvmTrustStoreLocation .toString ());
146- adaptedProperties .put ("sonar.scanner.truststorePassword" , System .getProperty ("javax.net.ssl.trustStorePassword" , "changeit" ));
147- }
148- }
149- return Map .copyOf (adaptedProperties );
150- }
151143
152144 /**
153145 * Older SonarQube versions used to rely on some different properties, or even {@link System} properties.
@@ -170,13 +162,13 @@ Map<String, String> adaptDeprecatedPropertiesForInProcessBootstrapping(Map<Strin
170162
171163 var keyStore = httpConfig .getSslConfig ().getKeyStore ();
172164 if (keyStore != null ) {
173- setSystemPropertyIfNotAlreadySet ("javax.net.ssl.keyStore" , keyStore .getPath ().toString ());
174- setSystemPropertyIfNotAlreadySet ("javax.net.ssl.keyStorePassword" , keyStore .getKeyStorePassword ().orElse (CertificateStore .DEFAULT_PASSWORD ));
165+ setSystemPropertyIfNotAlreadySet (JAVAX_NET_SSL_KEY_STORE , keyStore .getPath ().toString ());
166+ setSystemPropertyIfNotAlreadySet (JAVAX_NET_SSL_KEY_STORE_PASSWORD , keyStore .getKeyStorePassword ().orElse (CertificateStore .DEFAULT_PASSWORD ));
175167 }
176168 var trustStore = httpConfig .getSslConfig ().getTrustStore ();
177169 if (trustStore != null ) {
178- setSystemPropertyIfNotAlreadySet ("javax.net.ssl.trustStore" , trustStore .getPath ().toString ());
179- setSystemPropertyIfNotAlreadySet ("javax.net.ssl.trustStorePassword" , trustStore .getKeyStorePassword ().orElse (CertificateStore .DEFAULT_PASSWORD ));
170+ setSystemPropertyIfNotAlreadySet (JAVAX_NET_SSL_TRUST_STORE , trustStore .getPath ().toString ());
171+ setSystemPropertyIfNotAlreadySet (JAVAX_NET_SSL_TRUST_STORE_PASSWORD , trustStore .getKeyStorePassword ().orElse (CertificateStore .DEFAULT_PASSWORD ));
180172 }
181173
182174 return Map .copyOf (adaptedProperties );
@@ -229,6 +221,37 @@ private void initBootstrapDefaultValues() {
229221 }
230222 }
231223
224+ /**
225+ * New versions of SonarQube/SonarCloud will run on a separate VM. For people who used to rely on configuring SSL
226+ * by inserting the trusted certificate in the Scanner JVM truststore, or passing JVM SSL properties
227+ * we need to adapt the properties, at least temporarily, until we have helped most users to migrate.
228+ */
229+ static void adaptJvmSslPropertiesToScannerProperties (Map <String , String > bootstrapProperties , System2 system ) {
230+ if (!bootstrapProperties .containsKey (SONAR_SCANNER_TRUSTSTORE_PATH )) {
231+ var jvmTrustStoreProp = system .getProperty (JAVAX_NET_SSL_TRUST_STORE );
232+ if (StringUtils .isBlank (jvmTrustStoreProp )) {
233+ var defaultJvmTrustStoreLocation = Paths .get (System .getProperty ("java.home" ), "lib" , "security" , "cacerts" );
234+ if (Files .isRegularFile (defaultJvmTrustStoreLocation )) {
235+ LOG .debug ("Mapping default scanner JVM truststore location '{}' to new properties" , defaultJvmTrustStoreLocation );
236+ bootstrapProperties .put (SONAR_SCANNER_TRUSTSTORE_PATH , defaultJvmTrustStoreLocation .toString ());
237+ bootstrapProperties .putIfAbsent (SONAR_SCANNER_TRUSTSTORE_PASSWORD , System .getProperty (JAVAX_NET_SSL_TRUST_STORE_PASSWORD , "changeit" ));
238+ }
239+ } else {
240+ bootstrapProperties .putIfAbsent (SONAR_SCANNER_TRUSTSTORE_PATH , jvmTrustStoreProp );
241+ ofNullable (system .getProperty (JAVAX_NET_SSL_TRUST_STORE_PASSWORD ))
242+ .ifPresent (password -> bootstrapProperties .putIfAbsent (SONAR_SCANNER_TRUSTSTORE_PASSWORD , password ));
243+ }
244+ }
245+ if (!bootstrapProperties .containsKey (SONAR_SCANNER_KEYSTORE_PATH )) {
246+ var keystoreProp = system .getProperty (JAVAX_NET_SSL_KEY_STORE );
247+ if (!StringUtils .isBlank (keystoreProp )) {
248+ bootstrapProperties .put (SONAR_SCANNER_KEYSTORE_PATH , keystoreProp );
249+ ofNullable (system .getProperty (JAVAX_NET_SSL_KEY_STORE_PASSWORD ))
250+ .ifPresent (password -> bootstrapProperties .putIfAbsent (SONAR_SCANNER_KEYSTORE_PASSWORD , password ));
251+ }
252+ }
253+ }
254+
232255 private String getSonarCloudUrl () {
233256 return bootstrapProperties .getOrDefault (ScannerProperties .SONARCLOUD_URL , SONARCLOUD_HOST );
234257 }
0 commit comments