FROM microsoft/dotnet:2.1-aspnetcore-runtime-nanoserver-1803 AS base
ENV var ASPNETCORE_ENVIRONMENT=Development
ENV ASPNETCORE_URLS=http://:80/;https://.443
WORKDIR /app
EXPOSE 80 443
FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY WebMeshApp/WebMeshApp.csproj WebMeshApp/
RUN dotnet restore WebMeshApp/WebMeshApp.csproj
COPY . .
WORKDIR /src/WebMeshApp
RUN dotnet build WebMeshApp.csproj -c Release -o /app
FROM build AS publish
RUN dotnet publish WebMeshApp.csproj -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
COPY *.pfx .
ENTRYPOINT ["dotnet", "WebMeshApp.dll"]
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseKestrel(options =>
options.Listen(new System.Net.IPEndPoint(System.Net.IPAddress.Any, 443), listenOptions =>
{
var httpsConnectionAdapterOptions = new HttpsConnectionAdapterOptions()
{
ClientCertificateMode = ClientCertificateMode.NoCertificate,
SslProtocols = SslProtocols.Tls,
ServerCertificate = LoadCertificate()
};
listenOptions.UseHttps(httpsConnectionAdapterOptions);
}))
.UseApplicationInsights()
.UseStartup<Startup>();
private static X509Certificate2 LoadCertificate()
{
//just to ensure that we are picking the right file! little bit of ugly code:
var files = Directory.GetFiles(Directory.GetCurrentDirectory());
var certificateFile = files.First(name => name.Contains("pfx"));
return new X509Certificate2(/*"certfordocker.pfx*/certificateFile, "password");
}
}
The application should start flawlessly to be able to see its execution result on a browser.
The code produces the following exception:
Internal.Cryptography.CryptoThrowHelper.WindowsCryptographicException
HResult=0x80090011
Message=Object was not found
Source=<Cannot evaluate the exception source>
StackTrace:
<Cannot evaluate the exception stack trace>
The issue happens consistently.
@Arash-Sabet - It looks like you are coping in all pfx files and using the first one. Are there more than one pfx files in your scenario? Have you verified you are using the expected cert? You might have better luck getting a good answer on StackOverflow where the audience is much larger. This issue seems more general and not specific to the .NET Core docker images themselves.
@MichaelSimons
Please re-open the issue. There was only one pfx file to choose and load. The issue is that we had to add the following line to the docker file to have the code work properly:
USER ContainerAdministrator
Normally, I suspect that we should not be adding that line to the docker file just for the sake of pfx file.
@Arash-Sabet - I'm suspecting you may be hitting a simple file permissions issue. Does Authenticated User have Full control permissions to the cert on the host? I took your code and ran a simple console app and was unable to load the cert without it when running as the default ContainerUser. It worked without it if I ran as ContainerAdministrator.
public static void Main(string[] args)
{
var files = Directory.GetFiles(Directory.GetCurrentDirectory());
var certificateFile = files.First(name => name.Contains("pfx"));
try {
X509Certificate2 cert = new X509Certificate2(certificateFile, "crypticpassword");
Console.WriteLine($"cert loaded: '{cert.ToString()}'");
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
If that isn't viable, an alternative would be to change the permissions within your dockerfile after the cert is copied.
COPY your.pfx .
USER ContainerAdministrator
RUN icacls your.pfx /grant ContainerUser:(F) # something like this (not tested)
USER ContainerUser
Yes, the authenticated user has full control. At this moment not sure what else to say but maybe putting the topic that we discussed in a kind of document for developers to be mindful of this case. They may end up spending hours and hours to understand what's going on while there are no explicit error messages to tell what possibly went wrong.
Just to make sure we are on the same page can you share the output of running icacls *pfx on your host machine where the cert resides that is getting copied into the image and share the output?
I have not tried it and I think I am afraid that I won't be able to make it for the next while due to the timeline.
Hey @MichaelSimons, can you provide me the example that you ran, please?
I'm using dotnet:2.2-aspnetcore-runtime-nanoserver-1709 , I already tried using USER ContainerAdministrator but is still not working.
Thanks in advance.
@MichaelSimons @vany0114 - I was able to get it working for me by setting the 3rd parameter on X509Certificate2 to use the X509KeyStorageFlags.EphemeralKeySet.
I tried doing the icacls route, but that didn't work out at all. I even set the USER to be ContainerAdministrator but it didn't change anything. The storage flags were the winner for me.
@snickler I am getting below error
"Unable to configure HTTPS endpoint. No server certificate was specified, and the default developer certificate could not be found or is out of date."
when I am running my application under Docker Compose project
after spending many hours on internet I found your post and tried it.
after passing 3rd parameter "X509KeyStorageFlags.EphemeralKeySet" to "X509Certificate2"
resolved my issue, and this will save my life.
return new X509Certificate2(ReadStream(stream), "idsrv3test", X509KeyStorageFlags.EphemeralKeySet);
@snickler I am getting below error
"Unable to configure HTTPS endpoint. No server certificate was specified, and the default developer certificate could not be found or is out of date."
when I am running my application under Docker Compose project
after spending many hours on internet I found your post and tried it.
after passing 3rd parameter "X509KeyStorageFlags.EphemeralKeySet" to "X509Certificate2"
resolved my issue, and this will save my life.
return new X509Certificate2(ReadStream(stream), "idsrv3test", X509KeyStorageFlags.EphemeralKeySet);
Glad I could help!
Most helpful comment
@MichaelSimons @vany0114 - I was able to get it working for me by setting the 3rd parameter on
X509Certificate2to use theX509KeyStorageFlags.EphemeralKeySet.I tried doing the icacls route, but that didn't work out at all. I even set the USER to be ContainerAdministrator but it didn't change anything. The storage flags were the winner for me.