Skip to content

Commit

Permalink
Verify certificate format and add more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
w1am committed Feb 6, 2024
1 parent 620f0cf commit 7f3a7f2
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 14 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/base.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
env:
ES_DOCKER_TAG: ${{ inputs.docker-tag }}
run: |
./gencert.sh
sudo ./gencert.sh
dotnet test --configuration ${{ matrix.configuration }} --blame \
--logger:"GitHubActions;report-warnings=false" --logger:"console;verbosity=normal" \
--framework ${{ matrix.framework }} \
Expand Down
14 changes: 10 additions & 4 deletions src/EventStore.Client/EventStoreClientSettings.ConnectionString.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Net.Http;
using System.Net.Security;
using System.Security.Authentication;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using Timeout_ = System.Threading.Timeout;

Expand Down Expand Up @@ -220,12 +221,17 @@ private static EventStoreClientSettings CreateSettings(
}

if (typedOptions.TryGetValue(TlsCaFile, out var tlsCaFile)) {
var tlsCaFilePath = (string)tlsCaFile;
var tlsCaFilePath = Path.GetFullPath((string)tlsCaFile);
if (!string.IsNullOrEmpty(tlsCaFilePath) && !File.Exists(tlsCaFilePath)) {
throw new FileNotFoundException($"Failed to load certificate. File was not found");
throw new FileNotFoundException($"Failed to load certificate. File was not found.");
}

settings.ConnectivitySettings.TlsCaFile = (string)tlsCaFile;
try {
using var x509Certificate2 = new X509Certificate2(tlsCaFilePath);
settings.ConnectivitySettings.TlsCaFile = tlsCaFilePath;
} catch (CryptographicException) {
throw new Exception("Failed to load certificate. Invalid file format.");
}
}

settings.CreateHttpMessageHandler = CreateDefaultHandler;
Expand Down Expand Up @@ -351,4 +357,4 @@ private static (string, string) ParseKeyValuePair(string s) {
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,36 @@ namespace EventStore.Client.Streams.Tests.Append;

[Trait("Category", "Target:Stream")]
[Trait("Category", "Operation:Append")]
public class append_to_stream_with_tls_ca_file(ITestOutputHelper output, EventStoreFixture fixture) : EventStoreTests<EventStoreFixture>(output, fixture) {
[Fact]
public async Task tls_ca_file_exists_and_append_succeeds() {
var certificateFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "certs", "ca", "ca.crt");

public class append_to_stream_with_tls_ca_file(ITestOutputHelper output, EventStoreFixture fixture)
: EventStoreTests<EventStoreFixture>(output, fixture) {
public static IEnumerable<object[]> CertPaths =>
new List<object[]> {
new object[] { Path.Combine("certs", "ca", "ca.crt") },
new object[] { Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "certs", "ca", "ca.crt") },
};

[Theory]
[MemberData(nameof(CertPaths))]
private async Task TestAppendWithCaFile(string certificateFilePath) {
Fixture.Log.Information($"Using certificate: {certificateFilePath}");

Assert.True(File.Exists(certificateFilePath), $"Certificate file not found at: {certificateFilePath}");
Assert.True(File.Exists(certificateFilePath));

var connectionString = $"esdb://admin:changeit@localhost:2113/?tls=true&tlsVerifyCert=true&tlsCAFile={certificateFilePath}";
var connectionString =
$"esdb://admin:changeit@localhost:2113/?tls=true&tlsVerifyCert=true&tlsCAFile={certificateFilePath}";

var settings = EventStoreClientSettings.Create(connectionString);

var client = new EventStoreClient(settings);

var appendResult = await client.AppendToStreamAsync("some-stream", StreamState.Any, new[] { new EventData(Uuid.NewUuid(), "some-event", default) });
var appendResult = await client.AppendToStreamAsync(
"some-stream",
StreamState.Any,
new[] { new EventData(Uuid.NewUuid(), "some-event", default) }
);

appendResult.ShouldNotBeNull();

await client.DisposeAsync();
}
}
}
21 changes: 21 additions & 0 deletions test/EventStore.Client.Tests/ConnectionStringTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,27 @@ public void should_throw_error_when_tls_ca_file_does_not_exists() {
);

Assert.NotNull(exception);
Assert.Equal("Failed to load certificate. File was not found.", exception.Result.Message);
}

[Fact]
public void should_throw_exception_when_wrong_format_is_used_for_certificate_file_in_connection_string() {
var certificateFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "unknownCertificate");

// Create a file with invalid certificate format
using var stream = File.Create(certificateFilePath);
var connectionString =
$"esdb://admin:changeit@localhost:2113/?tls=true&tlsVerifyCert=true&tlsCAFile={certificateFilePath}";

var exception = Assert.ThrowsAsync<Exception>(
() => {
EventStoreClientSettings.Create(connectionString);

Check failure on line 175 in test/EventStore.Client.Tests/ConnectionStringTests.cs

View workflow job for this annotation

GitHub Actions / test/EventStore.Client/ubuntu-latest/net7.0

EventStore.Client.Tests.ConnectionStringTests.should_throw_exception_when_wrong_format_is_used_for_certificate_file_in_connection_string

System.AggregateException : One or more errors occurred. (Assert.Throws() Failure: Exception type was not an exact match Expected: typeof(System.Exception) Actual: typeof(System.IO.IOException)) ---- Assert.Throws() Failure: Exception type was not an exact match Expected: typeof(System.Exception) Actual: typeof(System.IO.IOException) -------- System.IO.IOException : The process cannot access the file '/home/runner/work/EventStore-Client-Dotnet/EventStore-Client-Dotnet/test/EventStore.Client.Tests/bin/release/net7.0/unknownCertificate' because it is being used by another process.

Check failure on line 175 in test/EventStore.Client.Tests/ConnectionStringTests.cs

View workflow job for this annotation

GitHub Actions / test/EventStore.Client/ubuntu-latest/net8.0

EventStore.Client.Tests.ConnectionStringTests.should_throw_exception_when_wrong_format_is_used_for_certificate_file_in_connection_string

System.AggregateException : One or more errors occurred. (Assert.Throws() Failure: Exception type was not an exact match Expected: typeof(System.Exception) Actual: typeof(System.IO.IOException)) ---- Assert.Throws() Failure: Exception type was not an exact match Expected: typeof(System.Exception) Actual: typeof(System.IO.IOException) -------- System.IO.IOException : The process cannot access the file '/home/runner/work/EventStore-Client-Dotnet/EventStore-Client-Dotnet/test/EventStore.Client.Tests/bin/release/net8.0/unknownCertificate' because it is being used by another process.

Check failure on line 175 in test/EventStore.Client.Tests/ConnectionStringTests.cs

View workflow job for this annotation

GitHub Actions / test/EventStore.Client/ubuntu-latest/net6.0

EventStore.Client.Tests.ConnectionStringTests.should_throw_exception_when_wrong_format_is_used_for_certificate_file_in_connection_string

System.AggregateException : One or more errors occurred. (Assert.Throws() Failure: Exception type was not an exact match Expected: typeof(System.Exception) Actual: typeof(System.IO.IOException)) ---- Assert.Throws() Failure: Exception type was not an exact match Expected: typeof(System.Exception) Actual: typeof(System.IO.IOException) -------- System.IO.IOException : The process cannot access the file '/home/runner/work/EventStore-Client-Dotnet/EventStore-Client-Dotnet/test/EventStore.Client.Tests/bin/release/net6.0/unknownCertificate' because it is being used by another process.
return Task.CompletedTask;
}
);

Assert.NotNull(exception);
Assert.Equal("Failed to load certificate. Invalid file format.", exception.Result.Message);
}

[Fact]
Expand Down

0 comments on commit 7f3a7f2

Please sign in to comment.