From standard created by ramsubbaraoc : dotnet/standard#849
On Windows, for .NET Framework classes we can specify sslkeyrepository as SYSTEM/USER.On linux where does the .NET Core classes search for the certificates by default and what could be the values for sslkeyrepository.
@bartonjs Can you answer this?
@ramsubbaraoc I'm not sure what your question is. (I'm not sure what "sslkeyrepository" is)
The X509Store class functions on Linux, but not the My store for the LocalMachine context. Directly editing the store is not supported, to add a certificate you need to add it via the X509Store.Add method.
I meant storelocation if it is LocalMachine or User. Now on linux what would be the location for LocalMachine/User. For Windows the API's search in the windows certmgr
@bartonjs Is this mapping documented outside this issue? It is pretty important information for many Linux devs.
https://github.com/dotnet/corefx/blob/master/Documentation/architecture/cross-platform-cryptography.md documents the supportedness of the stores.
The physical location on disk is not documented anywhere specific, because interacting with that directory "voids the warranty".
@bartonjs If this is something that's important to users of the class, should it be documented on Microsoft Docs?
@bartonjs Perfect. Thanks for the pointer. My google-fu didn't find that doc.
LocalMachineRoot is an interpreted view of the SSL_CERT_DIR and SSL_CERT_FILE values from OpenSSL.
OpenSSL has defaults for the dir and file. You can overwrite these defaults by specifying envvars (SSL_CERT_DIR/SSL_CERT_FILE). For example, you create a certificate bundle file and set SSL_CERT_FILE to it. Then you launch your dotnet
app, and it will use the bundle certificates (+ the default dir certificates).
Is there example how to load (format files) PEM containing private key and certificate to LocalMachine store?
I'm using this kind of code to load a certificate by a thumbprint in a .NET Core 2.2 application:
``` C#
using System;
using System.Security.Cryptography.X509Certificates;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
var crt = GetCertificate(args[0]);
Console.WriteLine("OK:" + crt.Thumbprint);
Console.ReadKey();
}
public static X509Certificate2 GetCertificate(string thumbprint)
{
if (string.IsNullOrEmpty(thumbprint))
{
throw new ArgumentException("Certificate thumbprint must not be empty");
}
using (var certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser))
{
certStore.Open(OpenFlags.ReadOnly);
var certCollection = certStore.Certificates.Find(
findType: X509FindType.FindByThumbprint,
findValue: thumbprint,
validOnly: false);
if (certCollection.Count > 0)
{
return certCollection[0];
}
}
throw new ArgumentException(
$"Current user's personal certificate store" +
$" does not contain certificate '{thumbprint}'.");
}
}
}
``
I am using the
microsoft/dotnet:2.2-runtime` docker image.
Where should I put my .crt and .key files so the app can find the certificate?
I tried to put them in /etc/ssl/certs
and /etc/ssl/private
but that didn't work.
@nikoudel .NET Core 2.2 can't read bare private keys. You have to merge it together into a PFX. To add it to a cert store, you have to do
C#
using (X509Store store = new x50Store(StoreName.My, StoreLocation.CurrentUser, OpenFlags.ReadWrite))
{
store.Add(new X509Certificate2(pathToPfx, pfxPassword, X509StorageFlags.PersistKeySet));
}
as an initialization task. Or, just don't load it from the store/thumbprint, and just load the PFX directly.
Thanks for your comment @bartonjs! It explains the problem I'm having. I didn't realize I can/should use the same API to store the certificate too.
Closing, since the original question was answered a while ago :smile:.
Made a little tool for this if ever it could help someone:
https://github.com/sharegate/dotnet-certificate-tool
@nikoudel .NET Core 2.2 can't read bare private keys. You have to merge it together into a PFX. To add it to a cert store, you have to do
using (X509Store store = new x50Store(StoreName.My, StoreLocation.CurrentUser, OpenFlags.ReadWrite)) { store.Add(new X509Certificate2(pathToPfx, pfxPassword, X509StorageFlags.PersistKeySet)); }
as an initialization task. Or, just don't load it from the store/thumbprint, and just load the PFX directly.
HI @bartonjs , If we got multiple .net core application as Doker containers, Do we need to add certificate in all the containers. Can't we just mount the certificate?
Thanks.
@mathavanmani I've been through this scenario before and found that the best way is to pass the certificate as a runtime argument (pfx or base64 string) and install it with an entrypoint script.
I doubt that mounting it directly in the .dotnet/corefx/cryptography/x509stores/...
folder will work and if ever the runtime changes the path, you'll fall into unsupported territory.
Don't forget not to bake the certificate inside the docker image since that's a potential security threat.
LocalMachineRoot is an interpreted view of the SSL_CERT_DIR and SSL_CERT_FILE values from OpenSSL.
OpenSSL has defaults for the dir and file. You can overwrite these defaults by specifying envvars (SSL_CERT_DIR/SSL_CERT_FILE). For example, you create a certificate bundle file and set SSL_CERT_FILE to it. Then you launch your
dotnet
app, and it will use the bundle certificates (+ the default dir certificates).
Are the semantics of this documented? I tried adding a PEM cert for our private repo using the above settings and neither worked. I tried adding our CA chain as well, doesn't work. Is it supposed to be PKCS12? PEM?
Most helpful comment
Made a little tool for this if ever it could help someone:
https://github.com/sharegate/dotnet-certificate-tool