Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Where does .net core search for certificates on linux platform #27658

Closed
terrajobst opened this issue Oct 17, 2018 · 18 comments
Closed

Where does .net core search for certificates on linux platform #27658

terrajobst opened this issue Oct 17, 2018 · 18 comments
Labels
area-System.Security question Answer questions and provide assistance, not an issue with source code or documentation.
Milestone

Comments

@terrajobst
Copy link
Member

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.

@terrajobst
Copy link
Member Author

@bartonjs Can you answer this?

@bartonjs
Copy link
Member

@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.

@ramsubbaraoc
Copy link

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
Copy link
Member

  • LocalMachine\Root is an interpreted view of the SSL_CERT_DIR and SSL_CERT_FILE values from OpenSSL.
  • LocalMachine\CA (intermediates) is populated by members of the previous interpretation which are not self-issued.
  • No other LocalMachine stores are supported
  • CurrentUser\Disallowed is not supported
  • All (other) CurrentUser stores are (currently) stored under ~/.dotnet/corefx/x509stores/. Directly interacting with this directory or its child directories and files can put .NET in an invalid state, and is not supported. The structure of this directory is considered an internal implementation detail and subject to change.

@mattzink
Copy link

@bartonjs Is this mapping documented outside this issue? It is pretty important information for many Linux devs.

@bartonjs
Copy link
Member

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".

@svick
Copy link
Contributor

svick commented Oct 18, 2018

@bartonjs If this is something that's important to users of the class, should it be documented on Microsoft Docs?

@mattzink
Copy link

@bartonjs Perfect. Thanks for the pointer. My google-fu didn't find that doc.

@tmds
Copy link
Member

tmds commented Oct 19, 2018

LocalMachine\Root 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).

@pauliusnorkus
Copy link

Is there example how to load (format files) PEM containing private key and certificate to LocalMachine store?

@nikoudel
Copy link
Contributor

nikoudel commented Jan 15, 2019

I'm using this kind of code to load a certificate by a thumbprint in a .NET Core 2.2 application:

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.

@bartonjs
Copy link
Member

@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.

@nikoudel
Copy link
Contributor

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.

@bartonjs
Copy link
Member

Closing, since the original question was answered a while ago 😄.

@yohanb
Copy link

yohanb commented May 27, 2019

Made a little tool for this if ever it could help someone:
https://github.com/sharegate/dotnet-certificate-tool

@mathavanmani
Copy link

mathavanmani commented Aug 8, 2019

@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.

@yohanb
Copy link

yohanb commented Aug 12, 2019

@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.

@msftgits msftgits transferred this issue from dotnet/corefx Jan 31, 2020
@msftgits msftgits added this to the 3.0 milestone Jan 31, 2020
@jcmcken
Copy link

jcmcken commented Apr 21, 2020

LocalMachine\Root 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?

@ghost ghost locked as resolved and limited conversation to collaborators Dec 15, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Security question Answer questions and provide assistance, not an issue with source code or documentation.
Projects
None yet
Development

No branches or pull requests