Skip to content

SkipServerCertificateValidation doesn't seem to work when passing a DbConnection or DbDataSource to UseClickHouse #50

Description

@danielharbrueger

Description

I'm trying to connect to a ClickHouse instance with an untrusted/self-signed cert, and skip validation using ClickHouseClientSettings.SkipServerCertificateValidation. Since that setting doesn't exist as a connection string key, I'm building a ClickHouseClientSettings object in code and passing it into either a ClickHouseConnection or ClickHouseDataSource, then handing that to UseClickHouse from EntityFrameworkCore.

Both the DbConnection overload and the DbDataSource overload fail with an untrusted root / SSL error, exactly as if the setting were never set.

To rule out the driver itself, I tested the same settings object directly with ClickHouseClient (no EF Core at all) and it works fine, connects and runs a query with no cert error. So the setting itself works, it just doesn't seem to carry through when going through either of these two UseClickHouse overloads.

My guess is that somewhere internally it's pulling the connection string back out of the connection/data source and building a new one from that, which would explain why a setting that only exists in code (not in the connection string) gets lost.

Repro

Works fine, no EF Core:

var settings = new ClickHouseClientSettings("Host=;Protocol=https;Port=8443;Username=;Password=")
{
    SkipServerCertificateValidation = true
};

using var client = new ClickHouseClient(settings);
await client.ExecuteScalarAsync("SELECT 1"); // succeeds

Fails with DbDataSource:

var dataSource = new ClickHouseDataSource(settings);

var options = new DbContextOptionsBuilder()
    .UseClickHouse(dataSource)
    .Options;

await using var ctx = new MyContext(options);
await ctx.Database.CanConnectAsync(); // untrusted root error

Fails with DbConnection too:

var connection = new ClickHouseConnection(settings);

var options = new DbContextOptionsBuilder()
    .UseClickHouse(connection, contextOwnsConnection: true)
    .Options;

await using var ctx = new MyContext(options);
await ctx.Database.CanConnectAsync(); // same error

Exception

System.Security.Authentication.AuthenticationException: The remote certificate is invalid because of errors in the certificate chain: UntrustedRoot at System.Net.Security.SslStream.CompleteHandshake...

Environment

  • ClickHouse.EntityFrameworkCore: 0.2.0
  • ClickHouse.Driver: 1.1.0
  • .NET: 10.0

Question

Is UseClickHouse(DbConnection) / UseClickHouse(DbDataSource) expected to preserve the actual instance you pass in, including settings that don't have a connection string equivalent? Right now it looks like it's only picking up whatever survives a round trip through the connection string, which silently drops anything like SkipServerCertificateValidation that's code-only.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions