I am trying to use the .Net Core Clean Architecture App Template and get it running in containers and deployed through an azure CI/CD pipeline
I have the containerized version of the template running locally in linux container with port 5001 and everything works perfectly.
I have the azure pipeline build process working properly and it creats image in my container registry.
The problem is once I deploy/release to a Web App for Containers, the app fails and throws the following error:
Application startup exception System.InvalidOperationException: Couldn't find a valid certificate with subject 'CN=localhost' on the 'CurrentUser\My' at Microsoft.AspNetCore.ApiAuthorization.IdentityServer.SigningKeysLoader.LoadFromStoreCert(String subject, String storeName, StoreLocation storeLocation, DateTimeOffset currentTime)
What I have done:
Following these docs from MS I have created a local dev cert:
dotnet dev-certs https -ep %USERPROFILE%\.aspnet\https\aspnetapp.pfx -p { password here }dotnet dev-certs https --trustI then imported this into the Web App as a private .pfx cert.
I added an application setting WEBSITE_LOAD_CERTIFICATES with the "thumb" value of the cert
I used the "hostname" of the imported cert in the Identity Server appSettings.json section (hostname=localhost in my case)
When the Web app loads, it shows :( Application error and the docker logs give me the error I quoted above.
I am pretty sure this is related to the Identity server set up and the appSettings.json values here:
"IdentityServer": {
"Key": {
"Type": "Store",
"StoreName": "My",
"StoreLocation": "CurrentUser",
"Name": "CN=localhost"
}
}
Can someone help me figure out how to resolve this error?
EDIT 1 - Manually specify file for IdentityServer Key
This is related to identity server for sure. I tried to manually set the Cert as a file in the appSettings.json like this:
"IdentityServer": {
"Key": {
"Type": "File",
"FilePath": "aspnetapp.pfx",
"Password": "Your_password123"
}
}
Now I get this error:
Loading certificate file at '/app/aspnetapp.pfx' with storage flags ''. Application startup exception System.InvalidOperationException: There was an error loading the certificate. The file '/app/aspnetapp.pfx' was not found. Microsoft.AspNetCore.ApiAuthorization.IdentityServer.SigningKeysLoader.LoadFromFile
I added this to the dockerfile:
WORKDIR /app
COPY ["/aspnetapp.pfx", "/app"]
RUN find /app
And as you can see from the image below, the files are showing in the build directory for the app:
I also made sure that the aspnetapp.pfx is not getting ignored by the .gitignore or .dockerignore files.
I cannot figure out why it won't load this file. It appears like it exists right where it is supposed to.
EDIT 2 using cert thumb and updated path
So I used tnc1977 suggestion and had this as my setting for the identity key
"IdentityServer": {
"Key": {
"Type": "File",
"FilePath": "/var/ssl/private/<thumb_value>.p12",
"Password": "Your_password123"
}
}
However, this gave another error:
There was an error loading the certificate. Either the password is incorrect or the process does not have permisions to store the key in the Keyset 'EphemeralKeySet' Interop+Crypto+OpenSslCryptographicException: error:23076071:PKCS12 routines:PKCS12_parse:mac verify failure
EDIT 3: Valid Azure App Certificate
I purchased an Azure App Certificate and added a custom domain with TSL set up and the same errors appear
EDIT 4: Load Cert in code startup.cs - new error:
I now know that I caanot use the cert store CurrentUser/My because that is for windows. Linux containers have to manually load the cert in code.
I am using the thumbprint of aa application certificate that has been added to the azure web app. It is a private azure app cert and it has been verified against a custom domain.
I added this code to my statup.cs configureservices (I know hardcoding these values is not best practice but I want to just see if it could load the cert, I will wsitch to env variables and key vault):
// linux file path for private keys
var cryptBytes = File.ReadAllBytes("/var/ssl/private/<thumbprint>.p12");
var cert = new X509Certificate2(cryptBytes, "");
services.AddIdentityServer().AddSigningCredential(cert);
I enter a blank password because I think that is what you are supposed to do. I am now getting the following error in my docker logs which leads me to believe the cert loaded and now the error is related to me using both services.AddIdentityServer().AddSigningCredential(cert); in startup.cs configureservices and app.UseIdentityServer() in startup.cs configure:
Unhandled exception. System.InvalidOperationException: Decorator already registered for type: IAuthenticationService.
I am not sure how to add the cert to the app.UseIdentityServer(); line.
EDIT 5
after a lot more digging, unfortunately @tnc1997 answer will not work. IN asp.net core 3 calls to app.UseIdentityServer in my satrtup.cs internally reverence a method that will look for the identity server Key,File,Pass etc in the appsetting(environment).json file.
As a result, even if I loaded the cert in code like tnc1997 shows, the application still looks in the settings file. So the settings file has to contain the corect details for the IS4 key.
Also, azure does not place the cert in the typical trusted location in the linux container. From what I have read, it appears that the only way to do this is to mount a volume (in this case an azure storage file share) and use the cert uploaded to that file share.
I can confirm that this works locally, but now I am still having issues running the container, the front end loads and it appears that the web api project does not start. I am going to post another question to address that issue.
