Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SCAN4NET-227 Use system trusted certificate or JVM certificate store #2330

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace SonarScanner.MSBuild.PreProcessor.Test.AnalysisConfigProcessing.Processors;

[TestClass]
public class PropertyAsScannerOptsMappingProcessorTests
public class TruststorePropertiesProcessorTests
{
[TestMethod]
public void Update_TrustStorePropertiesNullValue_Mapped()
Expand Down Expand Up @@ -34,15 +34,16 @@ public void Update_TrustStorePropertiesValue_Mapped()
{
// Arrange
var cmdLineArgs = new ListPropertiesProvider();
cmdLineArgs.AddProperty("sonar.scanner.truststorePath", @"C:\path\to\truststore.pfx");
cmdLineArgs.AddProperty("sonar.scanner.truststorePassword", "itchange");
cmdLineArgs.AddProperty(SonarProperties.TruststorePath, @"C:\path\to\truststore.pfx");
cmdLineArgs.AddProperty(SonarProperties.TruststorePassword, "itchange");
cmdLineArgs.AddProperty(SonarProperties.HostUrl, "https://localhost:9000");
var processor = CreateProcessor(CreateProcessedArgs(cmdLineArgs), isUnix: false);
var config = new AnalysisConfig
{
LocalSettings =
[
new Property("sonar.scanner.truststorePath", @"C:\path\to\truststore.pfx"),
new Property("sonar.scanner.truststorePassword", "itchange")
new Property(SonarProperties.TruststorePath, @"C:\path\to\truststore.pfx"),
new Property(SonarProperties.TruststorePassword, "itchange")
]
};

Expand All @@ -62,16 +63,17 @@ public void Update_DefaultPropertyValues()
var sonarUserHome = Path.Combine("~", ".sonar");
var defaultTruststorePath = Path.Combine(sonarUserHome, SonarPropertiesDefault.TruststorePath);
var cmdLineArgs = new ListPropertiesProvider();
cmdLineArgs.AddProperty("sonar.userHome", sonarUserHome);
cmdLineArgs.AddProperty(SonarProperties.UserHome, sonarUserHome);
cmdLineArgs.AddProperty(SonarProperties.HostUrl, "https://localhost:9000");
var fileWrapper = Substitute.For<IFileWrapper>();
fileWrapper.Exists(defaultTruststorePath).Returns(true);
var processor = CreateProcessor(CreateProcessedArgs(cmdLineArgs, fileWrapper), isUnix: false);
var config = new AnalysisConfig { LocalSettings = [new Property("sonar.userHome", sonarUserHome)] };
var config = new AnalysisConfig { LocalSettings = [new Property(SonarProperties.UserHome, sonarUserHome)] };

// Act
processor.Update(config);

config.LocalSettings.Should().ContainSingle(x => x.Id == "sonar.userHome" && x.Value == sonarUserHome);
config.LocalSettings.Should().ContainSingle(x => x.Id == SonarProperties.UserHome && x.Value == sonarUserHome);
config.ScannerOptsSettings.Should().HaveCount(2)
.And.Contain(x => x.Id == "javax.net.ssl.trustStore" && x.Value == $"\"{defaultTruststorePath.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)}\"")
.And.Contain(x => x.Id == "javax.net.ssl.trustStorePassword" && x.Value == $"\"{SonarPropertiesDefault.TruststorePassword}\"");
Expand All @@ -81,7 +83,6 @@ public void Update_DefaultPropertyValues()
[DataRow(SonarProperties.Verbose, "true")]
[DataRow(SonarProperties.Organization, "org")]
[DataRow(SonarProperties.HostUrl, "http://localhost:9000")]
[DataRow(SonarProperties.HostUrl, @"http://localhost:9000\")]
public void Update_UnmappedProperties(string id, string value)
{
// Arrange
Expand All @@ -103,9 +104,10 @@ public void Update_MapsTruststorePathToScannerOpts_Windows(string input, string
{
// Arrange
var cmdLineArgs = new ListPropertiesProvider();
cmdLineArgs.AddProperty("sonar.scanner.truststorePath", input);
cmdLineArgs.AddProperty(SonarProperties.HostUrl, "https://localhost:9000");
cmdLineArgs.AddProperty(SonarProperties.TruststorePath, input);
var processor = CreateProcessor(CreateProcessedArgs(cmdLineArgs), isUnix: false);
var config = new AnalysisConfig { LocalSettings = [new Property("sonar.scanner.truststorePath", input)] };
var config = new AnalysisConfig { LocalSettings = [new Property(SonarProperties.TruststorePath, input)] };

// Act
processor.Update(config);
Expand All @@ -115,7 +117,7 @@ public void Update_MapsTruststorePathToScannerOpts_Windows(string input, string
config.ScannerOptsSettings.Should().HaveCount(2);
AssertExpectedScannerOptsSettings("javax.net.ssl.trustStore", expected, config);
AssertExpectedScannerOptsSettings("javax.net.ssl.trustStorePassword", $"\"{SonarPropertiesDefault.TruststorePassword}\"", config);
Property.TryGetProperty("sonar.scanner.truststorePath", config.LocalSettings, out _).Should().BeFalse();
Property.TryGetProperty(SonarProperties.TruststorePath, config.LocalSettings, out _).Should().BeFalse();
}

[DataTestMethod]
Expand All @@ -126,16 +128,26 @@ public void Update_MapsTruststorePasswordToScannerOpts_Windows(string input, str
{
// Arrange
var cmdLineArgs = new ListPropertiesProvider();
cmdLineArgs.AddProperty("sonar.scanner.truststorePassword", input);
cmdLineArgs.AddProperty(SonarProperties.TruststorePath, "some/path");
cmdLineArgs.AddProperty(SonarProperties.TruststorePassword, input);
cmdLineArgs.AddProperty(SonarProperties.HostUrl, "https://localhost:9000");
var processor = CreateProcessor(CreateProcessedArgs(cmdLineArgs), isUnix: false);
var config = new AnalysisConfig { LocalSettings = [new Property("sonar.scanner.truststorePassword", input)] };
var config = new AnalysisConfig
{
LocalSettings =
[
new Property(SonarProperties.TruststorePath, "some/path"),
new Property(SonarProperties.TruststorePassword, input)
]
};

// Act
processor.Update(config);

// Assert
config.LocalSettings.Should().ContainSingle(x => x.Id == SonarProperties.TruststorePassword && x.Value == input);
config.ScannerOptsSettings.Should().ContainSingle();
config.ScannerOptsSettings.Should().HaveCount(2);
AssertExpectedScannerOptsSettings("javax.net.ssl.trustStore", @"""some/path""", config);
AssertExpectedScannerOptsSettings("javax.net.ssl.trustStorePassword", expected, config);
}

Expand All @@ -146,9 +158,10 @@ public void Update_MapsTruststorePathToScannerOpts_Linux(string input, string ex
{
// Arrange
var cmdLineArgs = new ListPropertiesProvider();
cmdLineArgs.AddProperty("sonar.scanner.truststorePath", input);
cmdLineArgs.AddProperty(SonarProperties.HostUrl, "https://localhost:9000");
cmdLineArgs.AddProperty(SonarProperties.TruststorePath, input);
var processor = CreateProcessor(CreateProcessedArgs(cmdLineArgs), isUnix: true);
var config = new AnalysisConfig { LocalSettings = [new Property("sonar.scanner.truststorePath", input)] };
var config = new AnalysisConfig { LocalSettings = [new Property(SonarProperties.TruststorePath, input)] };

// Act
processor.Update(config);
Expand All @@ -158,7 +171,7 @@ public void Update_MapsTruststorePathToScannerOpts_Linux(string input, string ex
config.ScannerOptsSettings.Should().HaveCount(2);
AssertExpectedScannerOptsSettings("javax.net.ssl.trustStore", expected, config);
AssertExpectedScannerOptsSettings("javax.net.ssl.trustStorePassword", SonarPropertiesDefault.TruststorePassword, config);
Property.TryGetProperty("sonar.scanner.truststorePath", config.LocalSettings, out _).Should().BeFalse();
Property.TryGetProperty(SonarProperties.TruststorePath, config.LocalSettings, out _).Should().BeFalse();
}

[DataTestMethod]
Expand All @@ -168,31 +181,107 @@ public void Update_MapsTruststorePasswordToScannerOpts_Linux(string input, strin
{
// Arrange
var cmdLineArgs = new ListPropertiesProvider();
cmdLineArgs.AddProperty("sonar.scanner.truststorePassword", input);
var processor = CreateProcessor(CreateProcessedArgs(cmdLineArgs), isUnix: true);
var config = new AnalysisConfig { LocalSettings = [new Property("sonar.scanner.truststorePassword", input)] };
cmdLineArgs.AddProperty(SonarProperties.HostUrl, "https://localhost:9000");
cmdLineArgs.AddProperty(SonarProperties.TruststorePassword, input);
var javaHome = Path.Combine("/home", "user", "java");
var javaHomeCacerts = Path.Combine(javaHome, "lib", "security", "cacerts");
var fileWrapper = Substitute.For<IFileWrapper>();
fileWrapper.Exists(javaHomeCacerts).Returns(true);
var processor = CreateProcessor(CreateProcessedArgs(cmdLineArgs), fileWrapper, isUnix: true);
var config = new AnalysisConfig { LocalSettings = [new Property(SonarProperties.TruststorePassword, input)] };
using var envScope = new EnvironmentVariableScope();
envScope.SetVariable("JAVA_HOME", javaHome);

// Act
processor.Update(config);

// Assert
config.LocalSettings.Should().ContainSingle(x => x.Id == SonarProperties.TruststorePassword && x.Value == input);
config.ScannerOptsSettings.Should().ContainSingle();
config.ScannerOptsSettings.Should().HaveCount(2);
AssertExpectedScannerOptsSettings("javax.net.ssl.trustStore", javaHomeCacerts.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar), config);
AssertExpectedScannerOptsSettings("javax.net.ssl.trustStorePassword", expected, config);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could additionally assert that fileWrapper.Exists(javaHomeCacerts) was called once.

}

[TestMethod]
public void Update_TrustedByTheSystem_Windows()
{
// Arrange
var cmdLineArgs = new ListPropertiesProvider();
cmdLineArgs.AddProperty(SonarProperties.HostUrl, "https://localhost:9000");
var processor = CreateProcessor(CreateProcessedArgs(cmdLineArgs), isUnix: false);
var config = new AnalysisConfig { LocalSettings = [] };

// Act
processor.Update(config);

// Assert
config.LocalSettings.Should().BeEmpty();
config.ScannerOptsSettings.Should().ContainSingle();
AssertExpectedScannerOptsSettings("javax.net.ssl.trustStoreType", "Windows-ROOT", config);
}

[TestMethod]
public void Update_TrustedByTheSystem_Linux()
{
// Arrange
var javaHome = Path.Combine("/home", "user", "java");
var javaHomeCacerts = Path.Combine(javaHome, "lib", "security", "cacerts");
var fileWrapper = Substitute.For<IFileWrapper>();
fileWrapper.Exists(javaHomeCacerts).Returns(true);
var cmdLineArgs = new ListPropertiesProvider();
cmdLineArgs.AddProperty(SonarProperties.HostUrl, "https://localhost:9000");
var processor = CreateProcessor(CreateProcessedArgs(cmdLineArgs), fileWrapper, isUnix: true);
var config = new AnalysisConfig { LocalSettings = [] };
using var envScope = new EnvironmentVariableScope();
envScope.SetVariable("JAVA_HOME", javaHome);

// Act
processor.Update(config);

// Assert
config.LocalSettings.Should().BeEmpty();
config.ScannerOptsSettings.Should().HaveCount(1);
AssertExpectedScannerOptsSettings("javax.net.ssl.trustStore", javaHomeCacerts.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar), config);
}

[TestMethod]
public void Update_TrustedByTheSystemPasswordProvided_Linux()
{
// Arrange
var javaHome = Path.Combine("/home", "user", "java");
var javaHomeCacerts = Path.Combine(javaHome, "lib", "security", "cacerts");
var fileWrapper = Substitute.For<IFileWrapper>();
fileWrapper.Exists(javaHomeCacerts).Returns(true);
var cmdLineArgs = new ListPropertiesProvider();
cmdLineArgs.AddProperty(SonarProperties.HostUrl, "https://localhost:9000");
var processor = CreateProcessor(CreateProcessedArgs(cmdLineArgs), fileWrapper, isUnix: true);
var config = new AnalysisConfig { LocalSettings = [] };
using var envScope = new EnvironmentVariableScope();
envScope.SetVariable("JAVA_HOME", javaHome);
envScope.SetVariable("SONAR_SCANNER_OPTS", "-Djavax.net.ssl.trustStorePassword=itchange");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if we also set another property here, e.g. -Xmx2048m?


// Act
processor.Update(config);

// Assert
config.LocalSettings.Should().HaveCount(1);
config.ScannerOptsSettings.Should().HaveCount(2);
AssertExpectedScannerOptsSettings("javax.net.ssl.trustStore", javaHomeCacerts.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar), config);
AssertExpectedScannerOptsSettings("javax.net.ssl.trustStorePassword", "itchange", config);
}

private static void AssertExpectedScannerOptsSettings(string key, string expectedValue, AnalysisConfig actualConfig)
{
var found = Property.TryGetProperty(key, actualConfig.ScannerOptsSettings, out var property);
found.Should().BeTrue("Expected local property was not found. Key: {0}", key);
property.Value.Should().Be(expectedValue, "Unexpected local value. Key: {0}", key);
}

private static PropertyAsScannerOptsMappingProcessor CreateProcessor(ProcessedArgs args, bool isUnix = false)
private static TruststorePropertiesProcessor CreateProcessor(ProcessedArgs args, IFileWrapper fileWrapper = null, bool isUnix = false)
{
var operatingSystemProvider = Substitute.For<IOperatingSystemProvider>();
operatingSystemProvider.IsUnix().Returns(isUnix);
return new PropertyAsScannerOptsMappingProcessor(args, null, operatingSystemProvider);
return new TruststorePropertiesProcessor(args, null, fileWrapper ?? Substitute.For<IFileWrapper>(), operatingSystemProvider);
}

private static ProcessedArgs CreateProcessedArgs(IAnalysisPropertyProvider cmdLineProvider = null, IFileWrapper fileWrapper = null) =>
Expand All @@ -201,7 +290,7 @@ private static ProcessedArgs CreateProcessedArgs(IAnalysisPropertyProvider cmdLi
"1.0",
"organization",
false,
cmdLineProvider ?? Substitute.For<IAnalysisPropertyProvider>(),
cmdLineProvider ?? EmptyPropertyProvider.Instance,
Substitute.For<IAnalysisPropertyProvider>(),
EmptyPropertyProvider.Instance,
fileWrapper ?? Substitute.For<IFileWrapper>(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,6 @@ private static IEnumerable<IAnalysisConfigProcessor> CreateProcessors(BuildSetti
new InitializationProcessor(buildSettings, localSettings, additionalSettings, serverProperties), // this must be first
new CoverageExclusionsProcessor(localSettings, serverProperties),
new AnalysisScopeProcessor(localSettings, serverProperties),
new PropertyAsScannerOptsMappingProcessor(localSettings, serverProperties, new OperatingSystemProvider(FileWrapper.Instance, logger)),
new TruststorePropertiesProcessor(localSettings, serverProperties, FileWrapper.Instance, new OperatingSystemProvider(FileWrapper.Instance, logger)),
];
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

using System.Collections.Generic;
using System.Linq;
using SonarScanner.MSBuild.Common;

namespace SonarScanner.MSBuild.PreProcessor.AnalysisConfigProcessing.Processors;

// See https://sonarsource.atlassian.net/browse/SCAN4NET-29
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

using SonarScanner.MSBuild.Common;

namespace SonarScanner.MSBuild.PreProcessor.AnalysisConfigProcessing.Processors;

public interface IAnalysisConfigProcessor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,75 @@ namespace SonarScanner.MSBuild.PreProcessor.AnalysisConfigProcessing.Processors;
/// Map property name to another property name and/or value to pass them through the SONAR_SCANNER_OPTS
/// environment variable to Scanner CLI 5.
/// </summary>
public class PropertyAsScannerOptsMappingProcessor(
public class TruststorePropertiesProcessor(
ProcessedArgs localSettings,
IDictionary<string, string> serverProperties,
IFileWrapper fileWrapper,
IOperatingSystemProvider operatingSystemProvider)
: AnalysisConfigProcessorBase(localSettings, serverProperties)
{
const string JAVAX_NET_SSL_TRUST_STORE = "javax.net.ssl.trustStore";
const string JAVAX_NET_SSL_TRUST_STORE_TYPE = "javax.net.ssl.trustStoreType";
const string JAVAX_NET_SSL_TRUST_STORE_PASSWORD = "javax.net.ssl.trustStorePassword";

public override void Update(AnalysisConfig config)
{
MapProperty(config, "javax.net.ssl.trustStore", PropertyValueOrDefault(SonarProperties.TruststorePath, LocalSettings.TruststorePath), ConvertToJavaPath, EnsureSurroundedByQuotes);
var password = PropertyValueOrDefault(SonarProperties.TruststorePassword, LocalSettings.TruststorePassword);
MapProperty(config, "javax.net.ssl.trustStorePassword", password, EnsureSurroundedByQuotes);
if (new Uri(LocalSettings.ServerInfo.ServerUrl).Scheme != "https"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (new Uri(LocalSettings.ServerInfo.ServerUrl).Scheme != "https"
if (new Uri(LocalSettings.ServerInfo.ServerUrl).Scheme != Uri.UriSchemeHttps

|| LocalSettings.ServerInfo.ServerUrl is SonarPropertiesDefault.SonarcloudUrl)
{
return;
}

var truststorePath = PropertyValueOrDefault(SonarProperties.TruststorePath, LocalSettings.TruststorePath);
var truststorePassword = PropertyValueOrDefault(SonarProperties.TruststorePassword, LocalSettings.TruststorePassword);

if (truststorePath is null)
{
if (operatingSystemProvider.IsUnix())
{
truststorePath = FindJavaTruststorePath();
truststorePassword ??= TruststorePasswordFromEnvironment();
}
else
{
MapProperty(config, JAVAX_NET_SSL_TRUST_STORE_TYPE, "Windows-ROOT");
}
}

MapProperty(config, JAVAX_NET_SSL_TRUST_STORE, truststorePath, ConvertToJavaPath, EnsureSurroundedByQuotes);
config.LocalSettings.RemoveAll(x => x.Id is SonarProperties.TruststorePath or SonarProperties.TruststorePassword);
config.LocalSettings.Add(new Property(SonarProperties.TruststorePassword, password));

if (truststorePassword is not null)
{
MapProperty(config, JAVAX_NET_SSL_TRUST_STORE_PASSWORD, truststorePassword, EnsureSurroundedByQuotes);
config.LocalSettings.Add(new Property(SonarProperties.TruststorePassword, truststorePassword));
}
}

private static string TruststorePasswordFromEnvironment()
{
var sonarScannerOpts = Environment.GetEnvironmentVariable("SONAR_SCANNER_OPTS");
if (sonarScannerOpts is null)
{
return null;
}

return sonarScannerOpts.Split(' ').FirstOrDefault(x => x.StartsWith($"-D{JAVAX_NET_SSL_TRUST_STORE_PASSWORD}=")) is { } truststorePassword

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is safe to specify StringComparison.OrdinalIgnoreCase:

Suggested change
return sonarScannerOpts.Split(' ').FirstOrDefault(x => x.StartsWith($"-D{JAVAX_NET_SSL_TRUST_STORE_PASSWORD}=")) is { } truststorePassword
return sonarScannerOpts.Split(' ').FirstOrDefault(x => x.StartsWith($"-D{JAVAX_NET_SSL_TRUST_STORE_PASSWORD}=", StringComparison.OrdinalIgnoreCase)) is { } truststorePassword

Copy link
Contributor Author

@sebastien-marichal sebastien-marichal Feb 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure, I think the properties are case sensitive.
During my test I made several times the mistake of writing down the javax properties like truststore instead of trustStore.

? truststorePassword.Substring($"-D{JAVAX_NET_SSL_TRUST_STORE_PASSWORD}=".Length)
: null;
}

private string FindJavaTruststorePath()
{
var javaHome = Environment.GetEnvironmentVariable("JAVA_HOME");
if (javaHome is null)
{
// TODO: propagate the error?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so. A debug log should be enough.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will not fail before the end step then.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the JRE provisioning is enabled, JAVA_HOME does not have to be set. There might be cases where the provisioned JRE trusts the server anyhow. The JRE comes with a default set of CA roots. If we fail it here, it would break https servers with a proper purchased certificate or one from https://letsencrypt.org/
Or am I miss something here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is from letsencrypt, it should be trusted without giving a store.
My understanding of purchased certificates is that you don't need to provide a truststore as they should be valid from some public CA.

I would be for failing the execution to follow the fail fast principle but I am not 100% sure that in this case there is no scenario where it would work.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The scenario is:

  • JRE provisioning is enabled and executed
  • JAVA_HOME is not set
  • The server is providing a certificate from a CA root trusted by the provisioned JRE (e.g. Let's Encrypt, Digi Cert, etc.)
  • The user doesn't specify anything (truststorePath is null)
  • We are on Linux
  • FindJavaTruststorePath is called

-> We would fail the begin step, even though everything would just work.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we safely assume that the cacerts of JAVA_HOME would be the same the one from the provisioned JRE?

If we take the same scenario with JAVA_HOME set, we will tell the provisioned JRE to use the local cacerts rather that the one download. I wonder if there is a possibility for the scenario to succeed with one and not the other where in theory it should succeed with both.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The root ca certs change on a regular basis (see e.g. here https://learn.microsoft.com/en-us/security/trusted-root/release-notes). It is likely that we will have different CA roots in both locations.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: I think this is a problem the scanner-cli may have as well.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also: As a user, you can install custom root CAs in your JAVA_HOME, but you can not install root CAs in the provisioned JRE. Therefore, we should prefer JAVA_HOME over the provisioned JRE.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good to me, I will only do a log.

return null;
}

var javaTruststorePath = Path.Combine(javaHome, "lib", "security", "cacerts");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a link to some kind of documentation or ticket about the source of these path.

return fileWrapper.Exists(javaTruststorePath) ? javaTruststorePath : null;
}

private string PropertyValueOrDefault(string propertyName, string defaultValue) =>
Expand Down
Loading
Loading