diff --git a/.github/workflows/ee.yml b/.github/workflows/ee.yml
new file mode 100644
index 000000000..d9ed7bb59
--- /dev/null
+++ b/.github/workflows/ee.yml
@@ -0,0 +1,65 @@
+name: Test EE
+
+on:
+ pull_request:
+ push:
+ branches:
+ - master
+ tags:
+ - v*
+
+env:
+ ES_VERSION: 24.2.0-jammy
+ ES_DOCKER_REGISTRY: docker.eventstore.com/eventstore-ee/eventstoredb-commercial
+
+jobs:
+ test:
+ timeout-minutes: 20
+ strategy:
+ fail-fast: false
+ matrix:
+ framework: [ net6.0, net7.0, net8.0 ]
+ os: [ ubuntu-latest ]
+ build: [ Streams, PersistentSubscriptions, Operations, UserManagement, ProjectionManagement ]
+ test: [ Plugins ]
+ configuration: [ release ]
+ runs-on: ${{ matrix.os }}
+ name: EventStore.Client.${{ matrix.test }}/${{ matrix.os }}/${{ matrix.framework }}/${{ env.ES_VERSION }}
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+ - shell: bash
+ run: |
+ git fetch --prune --unshallow
+ - name: Login to Cloudsmith
+ uses: docker/login-action@v3
+ with:
+ registry: docker.eventstore.com
+ username: ${{ secrets.CLOUDSMITH_CICD_USER }}
+ password: ${{ secrets.CLOUDSMITH_CICD_TOKEN }}
+ - name: Pull EventStore Image
+ shell: bash
+ run: |
+ docker pull ${{ env.ES_DOCKER_REGISTRY }}:${{ env.ES_VERSION }}
+ - name: Install dotnet SDKs
+ uses: actions/setup-dotnet@v3
+ with:
+ dotnet-version: |
+ 6.0.x
+ 7.0.x
+ 8.0.x
+ - name: Compile
+ shell: bash
+ run: |
+ dotnet build --configuration ${{ matrix.configuration }} --framework ${{ matrix.framework }} src/EventStore.Client.${{ matrix.build }}
+ - name: Run Tests
+ shell: bash
+ env:
+ ES_DOCKER_TAG: ${{ env.ES_VERSION }}
+ ES_DOCKER_REGISTRY: ${{ env.ES_DOCKER_REGISTRY }}
+ run: |
+ sudo ./gencert.sh
+ dotnet test --configuration ${{ matrix.configuration }} --blame \
+ --logger:"GitHubActions;report-warnings=false" --logger:"console;verbosity=normal" \
+ --framework ${{ matrix.framework }} \
+ test/EventStore.Client.${{ matrix.test }}.Tests
diff --git a/EventStore.Client.sln b/EventStore.Client.sln
index 51229f72c..03ecf4045 100644
--- a/EventStore.Client.sln
+++ b/EventStore.Client.sln
@@ -33,6 +33,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.Client.UserManag
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.Client.Tests.Common", "test\EventStore.Client.Tests.Common\EventStore.Client.Tests.Common.csproj", "{E326832D-DE52-4DE4-9E54-C800908B75F3}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventStore.Client.Plugins.Tests", "test\EventStore.Client.Plugins.Tests\EventStore.Client.Plugins.Tests.csproj", "{7D929D45-F1D9-462B-BE49-84BEC11D5039}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -94,6 +96,10 @@ Global
{E326832D-DE52-4DE4-9E54-C800908B75F3}.Debug|x64.Build.0 = Debug|Any CPU
{E326832D-DE52-4DE4-9E54-C800908B75F3}.Release|x64.ActiveCfg = Release|Any CPU
{E326832D-DE52-4DE4-9E54-C800908B75F3}.Release|x64.Build.0 = Release|Any CPU
+ {7D929D45-F1D9-462B-BE49-84BEC11D5039}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {7D929D45-F1D9-462B-BE49-84BEC11D5039}.Debug|x64.Build.0 = Debug|Any CPU
+ {7D929D45-F1D9-462B-BE49-84BEC11D5039}.Release|x64.ActiveCfg = Release|Any CPU
+ {7D929D45-F1D9-462B-BE49-84BEC11D5039}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{D3744A86-DD35-4104-AAEE-84B79062C4A2} = {EA59C1CB-16DA-4F68-AF8A-642A969B4CF8}
@@ -109,5 +115,6 @@ Global
{6CEB731F-72E1-461F-A6B3-54DBF3FD786C} = {C51F2C69-45A9-4D0D-A708-4FC319D5D340}
{22634CEE-4F7B-4679-A48D-38A2A8580ECA} = {C51F2C69-45A9-4D0D-A708-4FC319D5D340}
{E326832D-DE52-4DE4-9E54-C800908B75F3} = {C51F2C69-45A9-4D0D-A708-4FC319D5D340}
+ {7D929D45-F1D9-462B-BE49-84BEC11D5039} = {C51F2C69-45A9-4D0D-A708-4FC319D5D340}
EndGlobalSection
EndGlobal
diff --git a/gencert.ps1 b/gencert.ps1
index 3908f57e8..1101cc13d 100644
--- a/gencert.ps1
+++ b/gencert.ps1
@@ -4,18 +4,22 @@ Write-Host ">> Generating certificate..."
New-Item -ItemType Directory -Path .\certs -Force
# Set permissions for the directory
-icacls .\certs /grant:r "$($env:UserName):(OI)(CI)RX"
+icacls .\certs /grant:r "$($env:UserName):(OI)(CI)F"
# Pull the Docker image
-docker pull eventstore/es-gencert-cli:1.0.2
+docker pull ghcr.io/eventstore/es-gencert-cli:1.3
-# Create CA certificate
-docker run --rm --volume ${PWD}\certs:/tmp --user (Get-Process -Id $PID).SessionId eventstore/es-gencert-cli:1.0.2 create-ca -out /tmp/ca
+docker run --rm --volume ${PWD}\certs:/tmp ghcr.io/eventstore/es-gencert-cli create-ca -out /tmp/ca
-# Create node certificate
-docker run --rm --volume ${PWD}\certs:/tmp --user (Get-Process -Id $PID).SessionId eventstore/es-gencert-cli:1.0.2 create-node -ca-certificate /tmp/ca/ca.crt -ca-key /tmp/ca/ca.key -out /tmp/node -ip-addresses 127.0.0.1 -dns-names localhost
+docker run --rm --volume ${PWD}\certs:/tmp ghcr.io/eventstore/es-gencert-cli create-node -ca-certificate /tmp/ca/ca.crt -ca-key /tmp/ca/ca.key -out /tmp/node -ip-addresses 127.0.0.1 -dns-names localhost
+
+# Create admin user
+docker run --rm --volume ${PWD}\certs:/tmp ghcr.io/eventstore/es-gencert-cli create-user -username admin -ca-certificate /tmp/ca/ca.crt -ca-key /tmp/ca/ca.key -out /tmp/user-admin
+
+# Create an invalid user
+docker run --rm --volume ${PWD}\certs:/tmp ghcr.io/eventstore/es-gencert-cli create-user -username invalid -ca-certificate /tmp/ca/ca.crt -ca-key /tmp/ca/ca.key -out /tmp/user-invalid
# Set permissions recursively for the directory
-icacls .\certs /grant:r "$($env:UserName):(OI)(CI)RX"
+icacls .\certs /grant:r "$($env:UserName):(OI)(CI)F"
Import-Certificate -FilePath ".\certs\ca\ca.crt" -CertStoreLocation Cert:\CurrentUser\Root
diff --git a/gencert.sh b/gencert.sh
index fa640f624..7cd69b56a 100755
--- a/gencert.sh
+++ b/gencert.sh
@@ -13,11 +13,15 @@ mkdir -p certs
chmod 0755 ./certs
-docker pull eventstore/es-gencert-cli:1.0.2
+docker pull ghcr.io/eventstore/es-gencert-cli:1.3
-docker run --rm --volume $PWD/certs:/tmp --user $(id -u):$(id -g) eventstore/es-gencert-cli:1.0.2 create-ca -out /tmp/ca
+docker run --rm --volume $PWD/certs:/tmp --user $(id -u):$(id -g) ghcr.io/eventstore/es-gencert-cli create-ca -out /tmp/ca
-docker run --rm --volume $PWD/certs:/tmp --user $(id -u):$(id -g) eventstore/es-gencert-cli:1.0.2 create-node -ca-certificate /tmp/ca/ca.crt -ca-key /tmp/ca/ca.key -out /tmp/node -ip-addresses 127.0.0.1 -dns-names localhost
+docker run --rm --volume $PWD/certs:/tmp --user $(id -u):$(id -g) ghcr.io/eventstore/es-gencert-cli create-node -ca-certificate /tmp/ca/ca.crt -ca-key /tmp/ca/ca.key -out /tmp/node -ip-addresses 127.0.0.1 -dns-names localhost
+
+docker run --rm --volume $PWD/certs:/tmp --user $(id -u):$(id -g) ghcr.io/eventstore/es-gencert-cli create-user -username admin -ca-certificate /tmp/ca/ca.crt -ca-key /tmp/ca/ca.key -out /tmp/user-admin
+
+docker run --rm --volume $PWD/certs:/tmp --user $(id -u):$(id -g) ghcr.io/eventstore/es-gencert-cli create-user -username invalid -ca-certificate /tmp/ca/ca.crt -ca-key /tmp/ca/ca.key -out /tmp/user-invalid
chmod -R 0755 ./certs
diff --git a/src/EventStore.Client/ChannelFactory.cs b/src/EventStore.Client/ChannelFactory.cs
index d6ed7c3bf..3f6be47f7 100644
--- a/src/EventStore.Client/ChannelFactory.cs
+++ b/src/EventStore.Client/ChannelFactory.cs
@@ -39,10 +39,10 @@ HttpMessageHandler CreateHandler() {
return settings.CreateHttpMessageHandler.Invoke();
}
- var configureClientCert = settings.ConnectivitySettings is { TlsCaFile: not null, Insecure: false };
-
var certificate = settings.ConnectivitySettings.ClientCertificate ??
settings.ConnectivitySettings.TlsCaFile;
+
+ var configureClientCert = settings.ConnectivitySettings is { Insecure: false } && certificate != null;
#if NET
var handler = new SocketsHttpHandler {
KeepAlivePingDelay = settings.ConnectivitySettings.KeepAliveInterval,
@@ -57,8 +57,7 @@ HttpMessageHandler CreateHandler() {
EnableMultipleHttp2Connections = true
};
#endif
- if (!settings.ConnectivitySettings.Insecure) return handler;
-
+ if (settings.ConnectivitySettings.Insecure) return handler;
#if NET
if (configureClientCert) {
handler.SslOptions.ClientCertificates = new X509CertificateCollection { certificate! };
diff --git a/src/EventStore.Client/EventStoreClientConnectivitySettings.cs b/src/EventStore.Client/EventStoreClientConnectivitySettings.cs
index ec734ff21..92890d2f2 100644
--- a/src/EventStore.Client/EventStoreClientConnectivitySettings.cs
+++ b/src/EventStore.Client/EventStoreClientConnectivitySettings.cs
@@ -110,7 +110,7 @@ public bool Insecure {
///
/// Client certificate used for user authentication.
///
- public X509Certificate2? ClientCertificate { get; set; } = null;
+ public X509Certificate2? ClientCertificate { get; set; }
///
/// The default .
diff --git a/src/EventStore.Client/EventStoreClientSettings.ConnectionString.cs b/src/EventStore.Client/EventStoreClientSettings.ConnectionString.cs
index 56309140f..253532aab 100644
--- a/src/EventStore.Client/EventStoreClientSettings.ConnectionString.cs
+++ b/src/EventStore.Client/EventStoreClientSettings.ConnectionString.cs
@@ -249,11 +249,11 @@ private static EventStoreClientSettings CreateSettings(
return settings;
HttpMessageHandler CreateDefaultHandler() {
- var configureClientCert = settings.ConnectivitySettings is { TlsCaFile: not null, Insecure: false };
-
var certificate = settings.ConnectivitySettings.ClientCertificate ??
settings.ConnectivitySettings.TlsCaFile;
+ var configureClientCert = settings.ConnectivitySettings is { Insecure: false } && certificate != null;
+
#if NET
var handler = new SocketsHttpHandler {
KeepAlivePingDelay = settings.ConnectivitySettings.KeepAliveInterval,
@@ -268,7 +268,7 @@ HttpMessageHandler CreateDefaultHandler() {
EnableMultipleHttp2Connections = true
};
#endif
-
+ if (settings.ConnectivitySettings.Insecure) return handler;
#if NET
if (configureClientCert) {
handler.SslOptions.ClientCertificates = [certificate!];
diff --git a/test/EventStore.Client.Plugins.Tests/EventStore.Client.Plugins.Tests.csproj b/test/EventStore.Client.Plugins.Tests/EventStore.Client.Plugins.Tests.csproj
new file mode 100644
index 000000000..ee7d48512
--- /dev/null
+++ b/test/EventStore.Client.Plugins.Tests/EventStore.Client.Plugins.Tests.csproj
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/test/EventStore.Client.Plugins.Tests/client_certificate.cs b/test/EventStore.Client.Plugins.Tests/client_certificate.cs
new file mode 100644
index 000000000..b1d220c0e
--- /dev/null
+++ b/test/EventStore.Client.Plugins.Tests/client_certificate.cs
@@ -0,0 +1,88 @@
+namespace EventStore.Client.Plugins.Tests;
+
+[Trait("Category", "Target:Plugins")]
+[Trait("Category", "Type:UserCertificate")]
+public class client_certificate(ITestOutputHelper output, EventStoreFixture fixture)
+ : EventStoreTests(output, fixture) {
+ public static IEnumerable