On Mac, I generated an SSL certificate using Keychain access and exported it as a .cer file which worked well locally. However, when ran on docker, I received this: Unhandled exception. System.NotSupportedException: The server mode SSL must use a certificate with the associated private key.
So I exported a .p12 file for the same cert and extracted the .key from it using this command
Nabils-MBP:certs nabilhaffar$ openssl pkcs12 -legacy -nocerts -in mycert.p12 -out mykey.key
Then used the original .cer file with mykey.key to create a .pfx using:
openssl pkcs12 -export -out mycert.pfx -inkey mykey.key -in mycert.cer
So now I have this error:
Unhandled exception. System.Security.Cryptography.CryptographicException: The certificate data cannot be read with the provided password, the password may be incorrect.
I've been stuck here for a couple days. I need this certificate to work on docker locally, and the AWS EC2 instance it's running on. Any help would be appreciated.
.NET 7 certificate loading in program.cs :
var certFilePath = builder.Configuration["Kestrel:Endpoints:Https:Certificate:Path"];
var certPassword = builder.Configuration["Cert:Password"];
Console.WriteLine($"Certificate Path: {certFilePath}");
Console.WriteLine($"Certificate Password: {certPassword}");
if (string.IsNullOrEmpty(certFilePath) || string.IsNullOrEmpty(certPassword))
{
throw new Exception("Certificate file path or password not configured.");
}
try
{
var certificate = new X509Certificate2(certFilePath, certPassword, X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.MachineKeySet);
builder.WebHost.ConfigureKestrel((context, options) =>
{
options.ConfigureHttpsDefaults(httpsOptions =>
{
httpsOptions.ServerCertificate = certificate;
});
options.Listen(IPAddress.Any, 80); // HTTP port
options.Listen(IPAddress.Any, 5001, listenOptions =>
{
listenOptions.UseHttps(); // HTTPS port with a certificate
});
});
// Use certificate (e.g., add to services for HTTPS)
builder.Services.AddSingleton(certificate);
}
catch (CryptographicException ex)
{
Console.WriteLine($"CryptographicException: {ex.Message}");
throw;
}
DockerFile:
# Use the official .NET 7 SDK image for building the app
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /app
# Copy and restore dependencies
COPY *.sln ./
COPY AssetTracker/*.csproj ./AssetTracker/
RUN dotnet restore AssetTracker/AssetTracker.csproj
# Copy everything else and build the application
COPY AssetTracker/. ./AssetTracker/
WORKDIR /app/AssetTracker
RUN dotnet publish -c Release -o /app/publish
# Use the .NET runtime image to run the app
FROM mcr.microsoft.com/dotnet/aspnet:7.0
WORKDIR /app
COPY --from=build /app/publish .
EXPOSE 80
EXPOSE 443
EXPOSE 5001
CMD ["dotnet", "AssetTracker.dll"]
RUN apt update && apt install -y curl
docker-compose.dev.yml
services:
assettracker:
image: assettracker
build: .
ports:
- "8080:80"
- "5001:443"
environment:
- ASPNETCORE_ENVIRONMENT=Development
- Redis__Host=redis
- Redis__Port=6379
volumes:
- /Users/nabilhaffar/.microsoft/usersecrets:/root/.microsoft/usersecrets:ro
- /Users/nabilhaffar/.aspnet/DataProtection-Keys:/root/.aspnet/DataProtection-Keys
- ./Assettracker/certs:/root/certs # Mount certs to /root/certs inside container
env_file:
- .env
depends_on:
- redis
redis:
image: redis:latest
ports:
- "6379:6379"
volumes:
- redis-data:/data
volumes:
redis-data:
driver: local
appsettings.Development.json
{
"Kestrel": {
"Endpoints": {
"Https": {
"Url": "https://0.0.0.0:443",
"Certificate": {
"Path": "/root/certs/mycert.pfx"
//"Path": "certs/mycert.cer" // Use the relative path locally
},
"CertificateKey": {
//"Path": "/root/certs/mykey.key",
//"Path": "certs/mykey-pkcs8.key" // Use the relative path locally
}
}
}
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"Redis": {
"Host": "127.0.0.1",
"Port": "6379"
}
}
The issue I was having was due to having the Kestrel configuration in appsettings.json as well as program.cs. For some reason, it was adding another Kestrel (instance?) to the one already configured in the program.cs code. The Kestrel config and https cert loaded in program.cs had already been working with the same Dockerfile and compose.yml. I only noticed it when the same error got triggered at App.run in program.cs while previously it triggered at the certificate loading code also in program.cs