Skip to content

Commit

Permalink
(sdk-dotnet): fix ca cert server validation in dotnet client (#1056)
Browse files Browse the repository at this point in the history
Create validation method to trust CA server certificate in dotnet client
  • Loading branch information
KarlaCarvajal authored Oct 8, 2024
1 parent 8380256 commit 06aacf7
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 76 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ lhctl/lhctl
# Others
local-dev/certs/
build/
.config

# Python
__pycache__
Expand Down
2 changes: 1 addition & 1 deletion sdk-dotnet/Examples/BasicExample/BasicExample.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
Expand Down
3 changes: 1 addition & 2 deletions sdk-dotnet/LittleHorse.Sdk.Tests/LHInputVariablesTest.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using Xunit;

namespace LittleHorse.Sdk.Tests.Internal
Expand Down Expand Up @@ -169,7 +168,7 @@ public void LHConfigVariables_WithSomeLHOptionsCommentedInFile_ShouldReturnSetOp
Assert.Equal(int.Parse(keyValueLHConfigs["LHC_API_PORT"]), inputVariables.LHC_API_PORT);
Assert.Equal(DefaultLHConfigVariables.LHC_API_PROTOCOL, inputVariables.LHC_API_PROTOCOL);
Assert.Null(inputVariables.LHC_CA_CERT);
Assert.Equal(string.Empty, inputVariables.LHW_TASK_WORKER_VERSION);
Assert.Equal(DefaultLHConfigVariables.LHW_TASK_WORKER_VERSION, inputVariables.LHW_TASK_WORKER_VERSION);
}

[Fact]
Expand Down
40 changes: 0 additions & 40 deletions sdk-dotnet/LittleHorse.Sdk.Tests/Utils/CertificatesHandlerTest.cs

This file was deleted.

26 changes: 20 additions & 6 deletions sdk-dotnet/LittleHorse.Sdk/LHConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
using LittleHorse.Sdk.Internal;
using LittleHorse.Sdk.Utils;
using Microsoft.Extensions.Logging;
using System.Net.Http;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
using static LittleHorse.Common.Proto.LittleHorse;

namespace LittleHorse.Sdk {
Expand Down Expand Up @@ -136,11 +139,7 @@ private GrpcChannel CreateChannel(string host, int port)
{
var httpHandler = new HttpClientHandler();
var address = $"{BootstrapProtocol}://{host}:{port}";

if (_inputVariables.LHC_CA_CERT != null)
{
httpHandler = CertificatesHandler.GetHttpHandlerFrom(_inputVariables.LHC_CA_CERT);
}
httpHandler.ServerCertificateCustomValidationCallback = ServerCertificateCustomValidation;

if (_inputVariables.LHC_CLIENT_CERT != null && _inputVariables.LHC_CLIENT_KEY != null)
{
Expand All @@ -150,7 +149,7 @@ private GrpcChannel CreateChannel(string host, int port)

httpHandler.ClientCertificates.Add(cert);
}

if (IsOAuth)
{
return CreateGrpcChannelWithOauthCredentials(address, httpHandler);
Expand All @@ -162,6 +161,21 @@ private GrpcChannel CreateChannel(string host, int port)
});
}

private bool ServerCertificateCustomValidation(HttpRequestMessage requestMessage, X509Certificate2? certificate, X509Chain? certChain, SslPolicyErrors sslErrors)
{
var pathCaCert = _inputVariables.LHC_CA_CERT;
if (pathCaCert != null)
{
var caCert = new X509Certificate2(File.ReadAllBytes(pathCaCert));

certChain!.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust;
certChain.ChainPolicy.CustomTrustStore.Add(caCert);
}

var certChainBuilder = certificate != null && certChain != null && certChain.Build(certificate);
return certChainBuilder;
}

private GrpcChannel CreateGrpcChannelWithOauthCredentials(string address, HttpClientHandler httpHandler)
{
InitializeOAuth();
Expand Down
31 changes: 4 additions & 27 deletions sdk-dotnet/LittleHorse.Sdk/Utils/CertificatesHandler.cs
Original file line number Diff line number Diff line change
@@ -1,39 +1,16 @@
using System.Net.Security;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using LittleHorse.Sdk.Internal;
using Microsoft.Extensions.Logging;

[assembly: InternalsVisibleTo("LittleHorse.Sdk.Tests")]

namespace LittleHorse.Sdk.Utils {
internal class CertificatesHandler
{
internal static HttpClientHandler GetHttpHandlerFrom(string pathCaCert)
{
try
{
var caCert = new X509Certificate2(File.ReadAllBytes(pathCaCert));
var handler = new HttpClientHandler();

handler.ServerCertificateCustomValidationCallback =
(httpRequestMessage, cert, certChain, sslPolicyErrors) =>
{
return certChain!.ChainElements.Any(element =>
element.Certificate.Thumbprint == caCert.Thumbprint);
};

return handler;
}
catch (System.Security.Cryptography.CryptographicException)
{
throw new Exception($"Certificate file {pathCaCert} has corrupted data.");
}
catch (Exception ex)
{
throw new FileNotFoundException($"Certificate file {pathCaCert} does not exist.",
ex.Message);
}
}

internal static X509Certificate2 GetX509CertificateFrom(string pathPrivateCert, string pathRequestedCert)
{
string certificatePem = File.ReadAllText(pathRequestedCert);
Expand Down

0 comments on commit 06aacf7

Please sign in to comment.