GNU/Linux >> Linux Esercitazione >  >> Linux

Impossibile leggere il certificato durante l'esecuzione nel contenitore Linux Docker:funziona su Windows

Quindi, sembra che il problema principale sia duplice:

  1. Il "nome descrittivo" per "Nome alternativo oggetto" varia a seconda del sistema operativo.
  2. La stringa formattata varia a seconda del sistema operativo.

Finestre:

Friendly name: "Subject Alternative Name"
Formatted data:
    DNS Name=*.stackexchange.com
    DNS Name=stackexchange.com
    DNS Name=stackoverflow.com
    DNS Name=*.stackoverflow.com
    DNS Name=stackauth.com
    DNS Name=sstatic.net
    DNS Name=*.sstatic.net
    DNS Name=serverfault.com
    DNS Name=*.serverfault.com
    DNS Name=superuser.com
    DNS Name=*.superuser.com
    DNS Name=stackapps.com
    DNS Name=openid.stackauth.com
    DNS Name=*.meta.stackexchange.com
    DNS Name=meta.stackexchange.com
    DNS Name=mathoverflow.net
    DNS Name=*.mathoverflow.net
    DNS Name=askubuntu.com
    DNS Name=*.askubuntu.com
    DNS Name=stacksnippets.net
    DNS Name=*.blogoverflow.com
    DNS Name=blogoverflow.com
    DNS Name=*.meta.stackoverflow.com
    DNS Name=*.stackoverflow.email
    DNS Name=stackoverflow.email
    DNS Name=stackoverflow.blog

Linux in Docker (e Mac, a quanto pare):

Friendly name: "X509v3 Subject Alternative Name"
Formatted data:
    DNS:*.stackexchange.com, DNS:stackexchange.com, DNS:stackoverflow.com, DNS:*.stackoverflow.com, DNS:stackauth.com, DNS:sstatic.net, DNS:*.sstatic.net, DNS:serverfault.com, DNS:*.serverfault.com, DNS:superuser.com, DNS:*.superuser.com, DNS:stackapps.com, DNS:openid.stackauth.com, DNS:*.meta.stackexchange.com, DNS:meta.stackexchange.com, DNS:mathoverflow.net, DNS:*.mathoverflow.net, DNS:askubuntu.com, DNS:*.askubuntu.com, DNS:stacksnippets.net, DNS:*.blogoverflow.com, DNS:blogoverflow.com, DNS:*.meta.stackoverflow.com, DNS:*.stackoverflow.email, DNS:stackoverflow.email, DNS:stackoverflow.blog

Per risolvere il problema n. 1, ho iniziato a utilizzare il valore piuttosto che il nome descrittivo:2.5.29.17

Per risolvere il problema n. 2, ho dovuto aggiornare leggermente la mia espressione regolare. Mentre funzionava bene per i dati su più righe (Windows), non funzionava bene per i dati separati da virgole Linux/Mac.

La nuova espressione è ora:((DNS:|DNS Name=|CN=)(?<domain>.*?),?(?=\s|$))+

Mettendo tutto insieme, otteniamo:

const string ALT_NAME_VALUE = "2.5.29.17";
string certificateData = "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlJUERDQ0J5U2dBd0lCQWdJUUIyWEdUblRsa2RhQU9jb3FoSFZqOERBTkJna3Foa2lHOXcwQkFRc0ZBREJ3DQpNUXN3Q1FZRFZRUUdFd0pWVXpFVk1CTUdBMVVFQ2hNTVJHbG5hVU5sY25RZ1NXNWpNUmt3RndZRFZRUUxFeEIzDQpkM2N1WkdsbmFXTmxjblF1WTI5dE1TOHdMUVlEVlFRREV5WkVhV2RwUTJWeWRDQlRTRUV5SUVocFoyZ2dRWE56DQpkWEpoYm1ObElGTmxjblpsY2lCRFFUQWVGdzB4T0RFd01EVXdNREF3TURCYUZ3MHhPVEE0TVRReE1qQXdNREJhDQpNR294Q3pBSkJnTlZCQVlUQWxWVE1Rc3dDUVlEVlFRSUV3Sk9XVEVSTUE4R0ExVUVCeE1JVG1WM0lGbHZjbXN4DQpIVEFiQmdOVkJBb1RGRk4wWVdOcklFVjRZMmhoYm1kbExDQkpibU11TVJ3d0dnWURWUVFEREJNcUxuTjBZV05yDQpaWGhqYUdGdVoyVXVZMjl0TUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUE5S2s2DQpOWFVQMW9jWHQ4OW1UMWNJeGFkQmh6Q0wwWVRxUDAxL0RTb3RVSFJ6VjcwcU9DVDdBZE1UMEsxSmk2ckZ5YXB6DQpSaXFVSWhBa2hFc2VYUnAwTU5yMjFmU1V3NFZvQ2IrSW1PNmduSWx6b2xraHJwSzZJeTM0S3lVM3p5dDhYWUQrDQptWTNpOEdqUFpPeXNSSk5MeTNvdVFCbXp1T21VLzJGb21ubWlFR0YwMm1WZ2IzZXY4UHJjbnQ3ZENpRjdsaUJJDQpzZDN6a1BlWHZUVlljVmNiL01CckZFemM0RnVJdXBoVGlKYm9Oejh3SHY5K1BYQVhVVUg4VEVTclVmRlBDS0pIDQp3ZDlFQW9OWDhqUFUxVEl4aUNvZTZYTjVFMW1QeUdneXZFbmFjSC9IZXJLL2VMYzQ2TDdZV1ZHUnlqSFdhYVRLDQowckpoS2draDU5cXNXQmRuNXdJREFRQUJvNElFMWpDQ0JOSXdId1lEVlIwakJCZ3dGb0FVVVdqL2tLOENCM1U4DQp6TmxsWkdLaUVyaFpjanN3SFFZRFZSME9CQllFRkpxS3dXN0I4azM2MlhzQzFJK3pBNnhxUGNaWU1JSUIvQVlEDQpWUjBSQklJQjh6Q0NBZStDRXlvdWMzUmhZMnRsZUdOb1lXNW5aUzVqYjIyQ0VYTjBZV05yWlhoamFHRnVaMlV1DQpZMjl0Z2hGemRHRmphMjkyWlhKbWJHOTNMbU52YllJVEtpNXpkR0ZqYTI5MlpYSm1iRzkzTG1OdmJZSU5jM1JoDQpZMnRoZFhSb0xtTnZiWUlMYzNOMFlYUnBZeTV1WlhTQ0RTb3VjM04wWVhScFl5NXVaWFNDRDNObGNuWmxjbVpoDQpkV3gwTG1OdmJZSVJLaTV6WlhKMlpYSm1ZWFZzZEM1amIyMkNEWE4xY0dWeWRYTmxjaTVqYjIyQ0R5b3VjM1Z3DQpaWEoxYzJWeUxtTnZiWUlOYzNSaFkydGhjSEJ6TG1OdmJZSVViM0JsYm1sa0xuTjBZV05yWVhWMGFDNWpiMjJDDQpHQ291YldWMFlTNXpkR0ZqYTJWNFkyaGhibWRsTG1OdmJZSVdiV1YwWVM1emRHRmphMlY0WTJoaGJtZGxMbU52DQpiWUlRYldGMGFHOTJaWEptYkc5M0xtNWxkSUlTS2k1dFlYUm9iM1psY21ac2IzY3VibVYwZ2cxaGMydDFZblZ1DQpkSFV1WTI5dGdnOHFMbUZ6YTNWaWRXNTBkUzVqYjIyQ0VYTjBZV05yYzI1cGNIQmxkSE11Ym1WMGdoSXFMbUpzDQpiMmR2ZG1WeVpteHZkeTVqYjIyQ0VHSnNiMmR2ZG1WeVpteHZkeTVqYjIyQ0dDb3ViV1YwWVM1emRHRmphMjkyDQpaWEptYkc5M0xtTnZiWUlWS2k1emRHRmphMjkyWlhKbWJHOTNMbVZ0WVdsc2doTnpkR0ZqYTI5MlpYSm1iRzkzDQpMbVZ0WVdsc2doSnpkR0ZqYTI5MlpYSm1iRzkzTG1Kc2IyY3dEZ1lEVlIwUEFRSC9CQVFEQWdXZ01CMEdBMVVkDQpKUVFXTUJRR0NDc0dBUVVGQndNQkJnZ3JCZ0VGQlFjREFqQjFCZ05WSFI4RWJqQnNNRFNnTXFBd2hpNW9kSFJ3DQpPaTh2WTNKc015NWthV2RwWTJWeWRDNWpiMjB2YzJoaE1pMW9ZUzF6WlhKMlpYSXRaell1WTNKc01EU2dNcUF3DQpoaTVvZEhSd09pOHZZM0pzTkM1a2FXZHBZMlZ5ZEM1amIyMHZjMmhoTWkxb1lTMXpaWEoyWlhJdFp6WXVZM0pzDQpNRXdHQTFVZElBUkZNRU13TndZSllJWklBWWI5YkFFQk1Db3dLQVlJS3dZQkJRVUhBZ0VXSEdoMGRIQnpPaTh2DQpkM2QzTG1ScFoybGpaWEowTG1OdmJTOURVRk13Q0FZR1o0RU1BUUlDTUlHREJnZ3JCZ0VGQlFjQkFRUjNNSFV3DQpKQVlJS3dZQkJRVUhNQUdHR0doMGRIQTZMeTl2WTNOd0xtUnBaMmxqWlhKMExtTnZiVEJOQmdnckJnRUZCUWN3DQpBb1pCYUhSMGNEb3ZMMk5oWTJWeWRITXVaR2xuYVdObGNuUXVZMjl0TDBScFoybERaWEowVTBoQk1raHBaMmhCDQpjM04xY21GdVkyVlRaWEoyWlhKRFFTNWpjblF3REFZRFZSMFRBUUgvQkFJd0FEQ0NBUVlHQ2lzR0FRUUIxbmtDDQpCQUlFZ2ZjRWdmUUE4Z0IzQUtTNUNaQzBHRmdVaDdzVG9zeG5jQW84TlpnRStSdmZ1T04zelE3SURkd1FBQUFCDQpaa0lKK1NNQUFBUURBRWd3UmdJaEFQQ2FkeHY0N2NCNFFPT3ZOOXMvUjIzRWVwRWJTSTQvTXVBZGY1dktlVTc5DQpBaUVBMmdaM084bnp1VVZhblJXOWZnNm1nZnNMMDhObi9aR203M08vRjNJR1gyVUFkd0NIZGIvbldYejRqRU9aDQpYNzN6YnY5V2pVZFdOdjlLdFdEQnRPci9YcUNERHdBQUFXWkNDZm9HQUFBRUF3QklNRVlDSVFEUWpmbVZCcSsvDQp5MmdCSy9lRTl4Nmp6OWhUWjV0SWZoa1N0Uzg1Zk1BeGVnSWhBTUF1Tmt5dU80dDA2RWlFZ01XaWFsSlp1QW5rDQpRdzI5R2NlSUJHOHIxQXAzTUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFBQWs4NzMvKzJRc3dLZkpTUW4raVplDQpaYzh1aUdnOTlwbWQwMDhFMmNtR0VycU56UGNsSzlJTmJQand4bDl6SWdUY1hwRi9VdEJWVlMxWjdYbzgzcWZzDQpHTVBkTXpZdDNGK2hRcFFZTGhsR0YrNUpmMng2WmIxempUL2FNM0dNZEdpKzZPUFYrWUhsL3dnVWU0NU42a1J1DQpEWm5WTDE2NytXM2wybkQrbVNoTy83eHF3SGladXowR0h5QkhScDVpNDNibEgwdmc2N3NKOGd1TjgxcGFwdXBZDQoydjc4RmN2UjhqMEVMZmd5ZWh0V3BqRjN2ektTcS9yWTJzTVhUWXpTUHFNZWtzc2VITmhTTVlVNld3OWg5cHlNDQphVm53OXZhaHFmN25LSEhjQzJWUlRVZ2tRZm45eURtbUJPbzBuUThYZ2ZwZDY1L1BheFZmQm51S2ZFa1hCZnBNDQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tDQo=";
var secretData = Convert.FromBase64String(certificateData);
string[] urls = null;

var tmp = new X509Certificate2Collection();
tmp.Import(secretData);
var cert = tmp.OfType<X509Certificate2>().FirstOrDefault();
urls = cert.Extensions
    .OfType<X509Extension>()
    .Where(e => e.Oid.Value == ALT_NAME_VALUE)
    // I removed the part appending the original subject because I realise the same
    // information is available in the SAN object, so it was just duplicating data
    // this also allowed me to combine Format with creating the AsnEncodedData object
    .Select(e => new AsnEncodedData(e.Oid, e.RawData).Format(true))
    .SelectMany(d => Regex.Matches(d, "((DNS:|DNS Name=|CN=)(?<domain>.*?),?(?=\\s|$))+").OfType<Match>().Where(m => m.Success).Select(m => m.Groups["domain"].Value))
    .Distinct()
    .ToArray();

Console.WriteLine("S");
foreach (var r in urls)
{
    Console.WriteLine(r);
}
Console.WriteLine("E");

E ora l'output su Windows e Linux è lo stesso:

S
*.stackexchange.com
stackexchange.com
stackoverflow.com
*.stackoverflow.com
stackauth.com
sstatic.net
*.sstatic.net
serverfault.com
*.serverfault.com
superuser.com
*.superuser.com
stackapps.com
openid.stackauth.com
*.meta.stackexchange.com
meta.stackexchange.com
mathoverflow.net
*.mathoverflow.net
askubuntu.com
*.askubuntu.com
stacksnippets.net
*.blogoverflow.com
blogoverflow.com
*.meta.stackoverflow.com
*.stackoverflow.email
stackoverflow.email
stackoverflow.blog
E

Grazie a Nkosi che mi ha indicato questa risposta, sono stato in grado di utilizzare PeNet per estrarre gli URL del certificato:

var node = Asn1Node.ReadNode(cert.RawData);
urls =
    FlattenNodes(node)
    .Where(n => n.Nodes.Count > 0 && n.Nodes[0] is Asn1ObjectIdentifier && ((Asn1ObjectIdentifier)n.Nodes[0]).FriendlyName == "subjectAltName")
    .SelectMany(n => n.Nodes).OfType<Asn1OctetString>()
    .SelectMany(o => Asn1Sequence.ReadNode(o.Data).Nodes).OfType<Asn1CustomNode>()
    .Select(o => System.Text.Encoding.UTF8.GetString(o.Data))
    .ToArray();

Dove FlattenNodes sembra

private IEnumerable<Asn1Node> FlattenNodes(Asn1Node parentNode)
{
    yield return parentNode;
    foreach (var childNode in parentNode.Nodes)
    {
        foreach (var grandChildNode in FlattenNodes(childNode))
        {
            yield return grandChildNode;
        }
    }
}

So che l'appiattimento di tutti i nodi probabilmente non è di gran lunga il modo più efficiente per farlo, ma nel mio caso le prestazioni non sono molto importanti. Sta semplicemente controllando una manciata di certificati in un cluster Kubernetes come un cron job giornaliero.

Sarei interessato a sapere se è possibile senza una libreria di terze parti, soprattutto perché è su Windows.


Linux
  1. 7 divertenti contenitori Linux/caratteristiche di trasporto di immagini

  2. Automatizzare l'esecuzione del comando su Linux da Windows utilizzando PuTTY

  3. Riduzione delle prestazioni CUDA durante l'esecuzione in Windows

  4. Come posso ottenere informazioni sul contenitore Docker Linux dall'interno del contenitore stesso?

  5. La compilazione di .NET Core nel contenitore linux docker non riesce a causa dell'autenticazione SSL a Nuget

Ottieni podman attivo e funzionante su Windows usando Linux

Come posso profilare il codice C++ in esecuzione su Linux?

Installazione di netstat sul contenitore linux docker

I contenitori Windows possono essere ospitati su Linux?

Esecuzione di Linux all'interno di Windows XP, ovvero nessun dual boot

Come registro il server Linux con il server DNS di Windows