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

mTLS with ClientCert Password #1014

Merged
merged 19 commits into from
Jun 18, 2021
Merged
Show file tree
Hide file tree
Changes from 10 commits
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 @@ -36,24 +36,24 @@ public void Credentials()
ILogger logger = new TestLogger();

WebClientDownloader downloader;
downloader = new WebClientDownloader(null, null, null, logger);
downloader = new WebClientDownloader(null, null, null, null, logger);
downloader.GetHeader(HttpRequestHeader.Authorization).Should().BeNull();

downloader = new WebClientDownloader("da39a3ee5e6b4b0d3255bfef95601890afd80709", null, null, logger);
downloader = new WebClientDownloader("da39a3ee5e6b4b0d3255bfef95601890afd80709", null, null, null, logger);
downloader.GetHeader(HttpRequestHeader.Authorization).Should().Be("Basic ZGEzOWEzZWU1ZTZiNGIwZDMyNTViZmVmOTU2MDE4OTBhZmQ4MDcwOTo=");

downloader = new WebClientDownloader(null, "password", null, logger);
downloader = new WebClientDownloader(null, "password", null, null, logger);
downloader.GetHeader(HttpRequestHeader.Authorization).Should().BeNull();

downloader = new WebClientDownloader("admin", "password", null, logger);
downloader = new WebClientDownloader("admin", "password", null, null, logger);
downloader.GetHeader(HttpRequestHeader.Authorization).Should().Be("Basic YWRtaW46cGFzc3dvcmQ=");
}

[TestMethod]
public void UserAgent()
{
// Arrange
var downloader = new WebClientDownloader(null, null, null, new TestLogger());
var downloader = new WebClientDownloader(null, null, null, null, new TestLogger());

// Act
var userAgent = downloader.GetHeader(HttpRequestHeader.UserAgent);
Expand All @@ -69,7 +69,7 @@ public void UserAgent_OnSubsequentCalls()
// Arrange
var expectedUserAgent = string.Format("ScannerMSBuild/{0}",
typeof(WebClientDownloaderTest).Assembly.GetName().Version.ToDisplayString());
var downloader = new WebClientDownloader(null, null, null, new TestLogger());
var downloader = new WebClientDownloader(null, null, null, null, new TestLogger());

// Act & Assert
var userAgent = downloader.GetHeader(HttpRequestHeader.UserAgent);
Expand All @@ -92,27 +92,27 @@ public void UserAgent_OnSubsequentCalls()
[TestMethod]
public void SemicolonInUsername()
{
Action act = () => new WebClientDownloader("user:name", "", null, new TestLogger());
Action act = () => new WebClientDownloader("user:name", "", null, null, new TestLogger());
act.Should().ThrowExactly<ArgumentException>().WithMessage("username cannot contain the ':' character due to basic authentication limitations");
}

[TestMethod]
public void AccentsInUsername()
{
Action act = () => new WebClientDownloader("héhé", "password", null, new TestLogger());
Action act = () => new WebClientDownloader("héhé", "password", null, null, new TestLogger());
act.Should().ThrowExactly<ArgumentException>().WithMessage("username and password should contain only ASCII characters due to basic authentication limitations");
}

[TestMethod]
public void AccentsInPassword()
{
Action act = () => new WebClientDownloader("username", "héhé", null, new TestLogger());
Action act = () => new WebClientDownloader("username", "héhé", null, null, new TestLogger());
act.Should().ThrowExactly<ArgumentException>().WithMessage("username and password should contain only ASCII characters due to basic authentication limitations");
}
[TestMethod]
public void UsingClientCert()
{
Action act = () => new WebClientDownloader(null, null, "certtestsonar.pem", new TestLogger());
Action act = () => new WebClientDownloader(null, null, "certtestsonar.pem", "dummypw", new TestLogger());
act.Should().NotThrow();
}
}
Expand Down
1 change: 1 addition & 0 deletions src/SonarScanner.MSBuild.Common/SonarProperties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,6 @@ public static class SonarProperties
public const string VsTestReportsPaths = "sonar.cs.vstest.reportsPaths";

public const string ClientCertPath = "sonar.clientcert.path";
public const string ClientCertPassword = "sonar.clientcert.password";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,10 @@ public ISonarQubeServer CreateSonarQubeServer(ProcessedArgs args)
var username = args.GetSetting(SonarProperties.SonarUserName, null);
var password = args.GetSetting(SonarProperties.SonarPassword, null);
var clientCertPath = args.GetSetting(SonarProperties.ClientCertPath, null);
var clientCertPassword = args.GetSetting(SonarProperties.ClientCertPassword, null);
var hostUrl = args.SonarQubeUrl;

this.server = new SonarWebService(new WebClientDownloader(username, password, clientCertPath, this.logger), hostUrl, this.logger);
this.server = new SonarWebService(new WebClientDownloader(username, password, clientCertPath, clientCertPassword, this.logger), hostUrl, this.logger);
return this.server;
}

Expand Down
6 changes: 3 additions & 3 deletions src/SonarScanner.MSBuild.PreProcessor/WebClientDownloader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public class WebClientDownloader : IDownloader
private readonly ILogger logger;
private readonly HttpClient client;

public WebClientDownloader(string userName, string password, string clientCertPath, ILogger logger)
public WebClientDownloader(string userName, string password, string clientCertPath, string clientCertPassword, ILogger logger)
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;

Expand All @@ -48,11 +48,11 @@ public WebClientDownloader(string userName, string password, string clientCertPa

if (this.client == null)
{
if (clientCertPath != null)
if (clientCertPath != null || clientCertPassword != null) // password mandatory, as to use client cert in .jar it cannot be with empty password
{
var clientHandler = new HttpClientHandler();
clientHandler.ClientCertificateOptions = ClientCertificateOption.Manual;
clientHandler.ClientCertificates.Add(new X509Certificate2(clientCertPath));
clientHandler.ClientCertificates.Add(new X509Certificate2(clientCertPath, clientCertPassword));

this.client = new HttpClient(clientHandler);
}
Expand Down