Search code examples
linuxdockerasp.net-corecertificatecertificate-revocation

Is there a way to check and clean Certificate Revocation List cache for ASP.NET Core application that is dockerized and run under the Linux?


We need to implement checks of client certificate validity in our ASP.NET Core 2.X application that is dockerized and run under Linux. In particular, we are interested in revocation status of certificates. Such validation was implemented by using X509Chain and it works as expected.

var chain = new X509Chain();
var chainPolicy = new X509ChainPolicy
{
    RevocationMode = X509RevocationMode.Online,
    RevocationFlag = X509RevocationFlag.EntireChain
};
chain.ChainPolicy = chainPolicy;
...

Dockerfile

FROM mcr.microsoft.com/dotnet/core/aspnet:2.2-stretch-slim AS base
WORKDIR /app
EXPOSE 80

FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch AS build
....

However, we have requirements regarding the expiration time of CRL cache for our application. It looks like Linux (I assume it is debian for mcr.microsoft.com/dotnet/core/aspnet:2.2-stretch-slim image) caches CRLs by default - first request last for ~150ms and the following requests are handled almost in no time (unfortunately I cannot find available information to confirm this observation).

What is default time for CRL cache in Linux (debian)? Is it possible to change it? Is there a way to check list of the cached CRL?

Is possible to clean CRL cache like in Windows?

certutil -urlcache * delete

Linux certificate util dirmngr seems to be is not a part of the mcr.microsoft.com/dotnet/core/aspnet:2.2-stretch-slim base image for ASP.NET Core 2.2 applications.


Solution

  • As it is .net Core, which is open source, have you looked up the sources at github. There you'lkl find a call to the CrlCache which shows where data is stored:

    namespace Internal.Cryptography.Pal
    {
        internal static class CrlCache
        {
            private static readonly string s_crlDir =
                PersistedFiles.GetUserFeatureDirectory(
                    X509Persistence.CryptographyFeatureName,
    X509Persistence.CrlsSubFeatureName);
    
    
        internal static class X509Persistence
        {
            internal const string CryptographyFeatureName = "cryptography";
            internal const string X509StoresSubFeatureName = "x509stores";
            internal const string CrlsSubFeatureName = "crls";
            internal const string OcspSubFeatureName = "ocsp";
        }
    ...
            internal const string TopLevelDirectory = "dotnet";
            internal const string TopLevelHiddenDirectory = "." + TopLevelDirectory;
            internal const string SecondLevelDirectory = "corefx";
    ...
            internal static string GetUserFeatureDirectory(params string[] featurePathParts)
            {
                Debug.Assert(featurePathParts != null);
                Debug.Assert(featurePathParts.Length > 0);
    
                if (s_userProductDirectory == null)
                {
                    EnsureUserDirectories();
                }
    
                return Path.Combine(s_userProductDirectory, Path.Combine(featurePathParts));
            }
    
            private static void EnsureUserDirectories()
            {
                string userHomeDirectory = GetHomeDirectory();
    
                if (string.IsNullOrEmpty(userHomeDirectory))
                {
                    throw new InvalidOperationException(SR.PersistedFiles_NoHomeDirectory);
                }
    
                s_userProductDirectory = Path.Combine(
                    userHomeDirectory,
                    TopLevelHiddenDirectory,
                    SecondLevelDirectory);
    }
    
            internal static string GetHomeDirectory()
            {
                // First try to get the user's home directory from the HOME environment variable.
                // This should work in most cases.
    string userHomeDirectory = Environment.GetEnvironmentVariable("HOME");
    

    So the path should be $HOME/.dotnet/corefx/cryptography/crls