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

Fix openid certificates on Azure App Services #3255

Merged
merged 2 commits into from
Mar 5, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -488,20 +488,8 @@ private static X509Certificate2 GetCertificate(StoreLocation location, StoreName
{
try
{
// Extract the certificate password from the separate .pwd file.
var password = await GetPasswordAsync(Path.ChangeExtension(file.FullName, ".pwd"));

var flags =
#if SUPPORTS_EPHEMERAL_KEY_SETS
RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ?
X509KeyStorageFlags.EphemeralKeySet :
X509KeyStorageFlags.MachineKeySet;
#else
X509KeyStorageFlags.MachineKeySet;
#endif

// Only add the certificate if it's still valid.
var certificate = new X509Certificate2(file.FullName, password, flags);
var certificate = await GetCertificateAsync(file.FullName);
if (certificate.NotBefore <= DateTime.Now && certificate.NotAfter > DateTime.Now)
{
certificates.Add((file.FullName, certificate));
Expand All @@ -525,6 +513,43 @@ async Task<string> GetPasswordAsync(string path)
return _dataProtector.Unprotect(await reader.ReadToEndAsync());
}
}

async Task<X509Certificate2> GetCertificateAsync(string path)
{
// Extract the certificate password from the separate .pwd file.
var password = await GetPasswordAsync(Path.ChangeExtension(path, ".pwd"));

try
{
// Note: ephemeral key sets are not supported on non-Windows platforms.
var flags =
#if SUPPORTS_EPHEMERAL_KEY_SETS
RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ?
X509KeyStorageFlags.EphemeralKeySet :
X509KeyStorageFlags.MachineKeySet;
#else
X509KeyStorageFlags.MachineKeySet;
#endif

return new X509Certificate2(path, password, flags);
}
// Some cloud platforms (e.g Azure App Service/Antares) are known to fail to import .pfx files if the
// private key is not persisted or marked as exportable. To ensure X.509 certificates can be correctly
// read on these platforms, a second pass is made by specifying the PersistKeySet and Exportable flags.
// For more information, visit https://github.com/OrchardCMS/OrchardCore/issues/3222.
catch (CryptographicException exception)
{
_logger.LogDebug(exception, "A first-chance exception occurred while trying to extract " +
"a X.509 certificate with the default key storage options.");

return new X509Certificate2(path, password,
X509KeyStorageFlags.MachineKeySet |
X509KeyStorageFlags.PersistKeySet |
X509KeyStorageFlags.Exportable);
}
// Don't swallow exceptions thrown from the catch handler to ensure unrecoverable exceptions
// (e.g caused by malformed X.509 certificates or invalid password) are correctly logged.
}
}
}
}