dotnet / SqlClient

Microsoft.Data.SqlClient provides database connectivity to SQL Server for .NET applications.
MIT License
849 stars 284 forks source link

ef core7 , RemoteCertificateValidationCallback error was throwd in docker container #1856

Open sajjadsaharkhan opened 1 year ago

sajjadsaharkhan commented 1 year ago

I try to run an asp.net core api with dotnet7 SDK in a docker container.

I have this connection string: server=xxx.xxx.xxx.xxx,SqlServerPort;database=DbName;user id=sa;password=DbPassword123;TrustServerCertificate=True;

it works fine on my local pc. but when I run this project in a docker container throws this error:

Microsoft.Data.SqlClient.SqlException (0x80131904): A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: TCP Provider, error: 35 - An internal exception was caught) System.Security.Authentication.AuthenticationException: The remote certificate was rejected by the provided RemoteCertificateValidationCallback.

I use this Dockerfile:

FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /src
COPY ["Project.Api/Project.Api.csproj", "Project.Api/"]
COPY ["Project.Module.Admin/Project.Module.Admin.csproj", "Project.Module.Admin/"]
COPY ["Project.Module.Shared/Project.Module.Shared.csproj", "Project.Module.Shared/"]
COPY ["Project.Data/Project.Data.csproj", "Project.Data/"]
COPY ["Project.Infrastructure/Project.Infrastructure.csproj", "Project.Infrastructure/"]
COPY ["Project.Identity/Project.Identity.csproj", "Project.Identity/"]
COPY ["Project.Job/Project.Job.csproj", "Project.Job/"]
COPY ["Project.Module.Driver/Project.Module.Driver.csproj", "Project.Module.Driver/"]
COPY ["Project.Module.User/Project.Module.User.csproj", "Project.Module.User/"]
RUN dotnet restore "Project.Api/Project.Api.csproj"
COPY . .
WORKDIR "/src/Project.Api"
RUN dotnet build "Project.Api.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "Project.Api.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Project.Api.dll"]

and use this docker-compose file:

version: "3.4"
services:
  db-production:
    image: "mcr.microsoft.com/mssql/server:2022-latest"
    container_name: db-production
    restart: always
    environment:
      ACCEPT_EULA: "Y"
      MSSQL_SA_PASSWORD: "DbPassword123"
    volumes:
      - /home/volumes/mssql/data/production:/var/opt/mssql/data
    ports:
      - "1432:1433"
  backend-production:
    image: "backend_production:${TAG}"
    container_name: backend-production
    environment:
      - "ASPNETCORE_ENVIRONMENT=Production"
    build:
      context: .
      dockerfile: Project.Api/Dockerfile
    ports:
      - "${EXPOSED_PORT_PRODUCTION}:80"
    restart: unless-stopped
    depends_on:
      - db-production

I add my dbContext and SQL server ef core provider:

builder.Services.AddDbContextPool<AppDbContext>(options =>
{
    options.UseSqlServer(builder.Configuration.GetConnectionString("ConnectionStringName"), ss =>
    {
        ss.EnableRetryOnFailure(3);
    });
});

if I downgrade EF Core package version to 6.0.1 its works fine on docker!

EF Core version: 7.0.0 Database provider: (e.g. Microsoft.EntityFrameworkCore.SqlServer) Target framework: (e.g. .NET 7.0) Operating system: Windows, Linux IDE: (e.g. Jetbrains Rider 2022.3 EAP 9)

roji commented 1 year ago

Moving to do the SqlClient repo as this isn't related to EF Core.

sajjadsaharkhan commented 1 year ago

@roji Thanks Shay :)

modarreszadeh commented 1 year ago

I have the same problem after migrating to dotnet 7

JRahnama commented 1 year ago

I think the issue comes from the breaking change in M.D.SqlClient by changing the default value of Connection string Encrypt from false to true. For testing purposes, you can add Encrypt=False to your connection string or

Encrypt = SqlConnectionEncryptOption.Optional

in your connection string builder and see if that solves the issue.

sajjadsaharkhan commented 1 year ago

@JRahnama

thanks, Javad. but I change my connection string from: server=xxx.xxx.xxx.xxx,SqlServerPort;database=DbName;user id=sa;password=DbPassword123;TrustServerCertificate=True; to: server=xxx.xxx.xxx.xxx,SqlServerPort;database=DbName;user id=sa;password=DbPassword123;TrustServerCertificate=True;Encrypt=False;

and it didn't make a difference . I also tried to remove TrustServerCertificate=True to be sure and it's not working.

sajjadsaharkhan commented 1 year ago

Is there any sample project or GitHub repo for asp.net core with dotnet 7 SDK and EF Core 7 that runs fine on docker?

JRahnama commented 1 year ago

Is there any sample project or GitHub repo for asp.net core with dotnet 7 SDK and EF Core 7 that runs fine on docker?

Not that I am aware of. EFCore team may know that better. Have you tried a new simple application with EFCore to see if that works? One other option I can think of is HostNameInCertificate connection string property that was recently added. Seems like you are using IP instead of server name which could cause some issues with this new property. Can you use server FQDN instead of IP address and see what happens?

Just keep in mind that we are in the middle of a GA release and cannot dedicate so much time on the issues at the moment, but we can investigate it later after the GA release.

velocitysystems commented 1 year ago

Same issue here with EF Core 7 + .NET 7 inside a Lambda docker container. Setting TrustServerCertificate and Encrypt have no effect in the SQL connection string.

sajjadsaharkhan commented 1 year ago

Is there any sample project or GitHub repo for asp.net core with dotnet 7 SDK and EF Core 7 that runs fine on docker?

Not that I am aware of. EFCore team may know that better. Have you tried a new simple application with EFCore to see if that works? One other option I can think of is HostNameInCertificate connection string property that was recently added. Seems like you are using IP instead of server name which could cause some issues with this new property. Can you use server FQDN instead of IP address and see what happens?

Just keep in mind that we are in the middle of a GA release and cannot dedicate so much time on the issues at the moment, but we can investigate it later after the GA release.

Unfortunately I can't use FQDN in my cloud PaaS provider. There is no way to use an IP address?

gjvdree commented 1 year ago

I currently have the same Issue, tried every possibility of the parameters
Persist Security Info=True; Encrypt=False; TrustServerCertificate=True;

nickmallinson commented 1 year ago

New application, new Databases.... tried everything similar to @gjvdree - but still no luck. :-(

velocitysystems commented 1 year ago

This really needs to be resolved as its a significant breaking change/regression.

teharris1 commented 1 year ago

@JRahnama why is this in waiting for customer? It looks like sufficient information has been given and the issue is certainly repeatable. What is the team waiting on from any customer?

ricardomomm commented 1 year ago

Bump, this is causing several issues here in our dev environment.

blanks88 commented 1 year ago

Hey, I got the same error:

System.Security.Authentication.AuthenticationException
The remote certificate was rejected by the provided RemoteCertificateValidationCallback.
   at System.Net.Security.SslStream.SendAuthResetSignal(ProtocolToken message, ExceptionDispatchInfo exception)
   at System.Net.Security.SslStream.CompleteHandshake(SslAuthenticationOptions sslAuthenticationOptions)
   at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](Boolean receiveFirst, Byte[] reAuthenticationData, CancellationToken cancellationToken)
   at System.Net.Security.SslStream.AuthenticateAsClient(SslClientAuthenticationOptions sslClientAuthenticationOptions)
   at Microsoft.Data.SqlClient.SNI.SNITCPHandle.EnableSsl(UInt32 options)

also tried TrustServerCertificate=True; but still fails.

ComperioAG commented 1 year ago

We have the same problem which prevents us from upgrading to EF Core 7 yet, as it would break our development pipeline.

taylorwaddell commented 1 year ago

Also having the same issue. Have tried everything above including changing from localhost to the actual IP and port number.

gpltaylor commented 1 year ago

We just experienced this issue and adding "Trust Server Certificate=True" fix the issue.

Within UAT we use managed instances. When connecting to the SQL Browser Agent, the connection simply dies with the same error. We are not happy with the solution but this was fixed by setting the connect to use TCP and set the Instance port directly

Server=tcp:persistneo,1439;Database=<removed>;User Id=<removed>;Password=<removed>;Trust Server Certificate=True
akrpic77 commented 1 year ago

mssql-scripter doesn't work on Linux due to same bug.

rakeshkumargupta commented 1 year ago

Please check the code DB context object is added as singleton and the object must be injected from constructor only. The connectionString must be set or re-set (re-load from Configuration appsettings.json) if the object of dbcontext is created separately anywhere in code.

elepner commented 1 year ago

Any progress on this? We are stuck on EF6 due to this bug because we cannot run our integration tests.

PaulIvanov commented 9 months ago

Any updates regarding this? We are also blocked from migrating to .net 7 until this is fixed

JRahnama commented 9 months ago

Is anyone able to provide a sample repo without EFCore that reproduces the issue?

elepner commented 9 months ago

@JRahnama here it is: https://github.com/elepner/EfCore7BugReproduce

saddamhossain commented 8 months ago

The following repository seamlessly integrates with ASP.NET Core, .NET 8, and Microsoft SQL Server, demonstrating a smooth and efficient Docker deployment process. https://github.com/saddamhossain/DockerDemo

Raffaele-Doti commented 7 months ago

I updated to EF core version 8.0.1 and simply adding "Encrypt=False" to my connection string solved the callback certificate exception. Below the connection string I used to register the data context into my IOC container. Server=mySqlServerInstance,1433; Database=MyDatabase; User=sa; Password=MyStrongPassword; MultipleActiveResultSets=true;TrustServerCertificate=true;Encrypt=False;

sajjadsaharkhan commented 7 months ago

I updated to EF core version 8.0.1 and simply adding "Encrypt=False" to my connection string solved the callback certificate exception. Below the connection string, I used to register the data context into my IOC container. Server=mySqlServerInstance,1433; Database=MyDatabase; User=sa; Password=MyStrongPassword; MultipleActiveResultSets=true;TrustServerCertificate=true;Encrypt=False;

It's also works for me in .NET 8.

AfrozChowki commented 7 months ago

I am also facing the same issue, even with .Net 8 (tried 8.0.1 & 8.0.3), adding Encrypt=False & TrustServerCertificate has no effect, it still expects server certificate validation.

More context: Running integration tests with EF Core in docker container & facing the same issue. It blocking to upgrade EF Core to > 6.0.0

Getting below additional stack trace in my case --AuthenticationException at System.Net.Security.SslStream.SendAuthResetSignal(ReadOnlySpan1 alert, ExceptionDispatchInfo exception) at System.Net.Security.SslStream.CompleteHandshake(SslAuthenticationOptions sslAuthenticationOptions) at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](Boolean receiveFirst, Byte[] reAuthenticationData, CancellationToken cancellationToken) at System.Net.Security.SslStream.AuthenticateAsClient(SslClientAuthenticationOptions sslClientAuthenticationOptions) at Microsoft.Data.SqlClient.SNI.SNITCPHandle.EnableSsl(UInt32 options)

----> System.Security.Authentication.AuthenticationException : The remote certificate was rejected by the provided RemoteCertificateValidationCallback.

elepner commented 5 months ago

After changing connection string format from Server=sql-db,1433;Database=CloudDb;User Id=sa;Password=YourStrong@Passw0rd;MultipleActiveResultSets=true to Data Source=sql-db; Initial Catalog=CloudDb; User ID=sa; Password=YourStrong@Passw0rd;trusted_connection=false;Persist Security Info=False;Encrypt=False; everything started working. Thanks, @saddamhossain, for providing a working example.