[YARP Ingress Controller] TLS handshake missing private key: `The server mode SSL must use a certificate with the associated private key`
Describe the bug
Hi there,
I implemented a HTTPS termination for YARP Ingress Controller this week. During my test, I found that TLS handshake would fail and error was The server mode SSL must use a certificate with the associated private key.
I checked the documentation. In summary, a C# X509Certificate2 instance by default has an ephemeral private key in memory linked by a memory pointer. ASP.NET Kestrel relies on OpenSSL on Linux for TLS handshake. However, the OpenSSL under the hood of Linux doesn't know how to get its private key by pointer so OpenSSL thinks the private key is missing.
I would like to make a PR fix for you to review and get your feedback if you regard it as a real bug.
My fix
We need to export the private key so that the PFX file itself includes the private key. The code has done it for Windows.
The following code would eliminate the TLS handshake error and my HTTPS termination would work:
if (OperatingSystem.IsLinux())
{
var pfx = certificate.Export(X509ContentType.Pkcs12);
certificate = X509CertificateLoader.LoadPkcs12(pfx, null); // a class in .NET9
}I would say the current code would also work with slight modification based on .NET 8, even if I haven't tested:
if (OperatingSystem.IsWindows() || OperatingSystem.IsLinux())
{
// Cert needs converting. Read https://github.com/dotnet/runtime/issues/23749#issuecomment-388231655
using var convertedCertificate = X509Certificate2.CreateFromPem(certString, privateString);
return new X509Certificate2(convertedCertificate.Export(X509ContentType.Pkcs12));
}To Reproduce
Reproduce
Use a certificate type secret in Kubernetes and use the generated certificate for TLS handshake by public X509Certificate2 ConvertCertificate(NamespacedName namespacedName, V1Secret secret).
Exceptions
[2026-09-03 16:05:36 DBG] [Microsoft.AspNetCore.Server.Kestrel.Https.Internal.HttpsConnectionMiddleware] Failed to authenticate HTTPS connection.
System.Security.Authentication.AuthenticationException: The server mode SSL must use a certificate with the associated private key.
at System.Net.Security.SslStream.AcquireServerCredentials(Byte[]& thumbPrint)
at System.Net.Security.SslStream.GenerateToken(ReadOnlySpan`1 inputBuffer, Int32& consumed)
at System.Net.Security.SslStream.NextMessage(ReadOnlySpan`1 incomingBuffer, Int32& consumed)
at System.Net.Security.SslStream.ProcessTlsFrame(Int32 frameSize)
at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](Boolean receiveFirst, Byte[] reAuthenticationData, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Https.Internal.HttpsConnectionMiddleware.OnConnectionAsync(ConnectionContext context)Further technical details
Packages
<PackageReference Include="Yarp.Kubernetes.Controller" Version="3.0.0-preview.1.26370.1"/>
<PackageReference Include="Yarp.ReverseProxy" Version="3.0.0-preview.1.26370.1"/>Platform
Docker image mcr.microsoft.com/dotnet/sdk:10.0-noble on Ubuntu host machine
Source: dotnet/yarp