自 2017 年年中以来 Azure 应用服务(Azure 网站)上的 X509Certificate2?

X509Certificate2 on Azure App Services (Azure Websites) since mid-2017?

我有一个 .NET Framework 4.7 应用程序,它允许用户上传 PFX 或 PKCS#12 格式的 X.509 证书(认为:"SSL certificates" 包含私钥),然后将证书加载到一个 System.Security.Cryptography.X509Certificates.X509Certificate2 个实例。由于我的应用程序代码还需要重新导出证书,因此我指定了 X509KeyStorageFlags.Exportable 选项。

当 运行 在我的生产 Web 服务器上的 IIS 下时,未加载 Windows 身份的 Windows 用户配置文件 w3wp.exe 在其下运行,因此我没有指定UserKeySet 标志。

String filePassword = ...
Byte[] userProvidedCertificateFile = ...

using( X509Certificate2 cert = new X509Certificate2( rawData: userProvidedCertificateFile, password: filePassword, keyStorageFlags: X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet )
{
    ...
}

2017 年初,我将此代码部署到 Azure 应用服务(又名 Azure 网站)实例并且它工作正常 - 在最初失败后因为我确实设置了 UserKeySet 标志(因为 Azure 应用服务没有加载用户配置文件证书存储。

但是,自 2017 年年中(可能在 5 月或 6 月左右)以来,我的应用程序已停止工作 - 我假设 Azure App Service 已移至更新的系统(尽管 Kudu 报告我的应用程序 运行 Windows 服务器 2012 (NT 6.2.9200.0).

它目前失败并显示两条错误消息,具体取决于输入:

我写了一个广泛的测试用例,尝试 X509Certificate2 构造函数参数的不同组合,以及使用和不使用 WEBSITE_LOAD_CERTIFICATES Azure 应用程序设置。

以下是我在处理包含私钥且没有密码保护的上传 PFX/PKCS#12 证书文件时的发现:

因此 WEBSITE_LOAD_CERTIFICATES 似乎有效 - 但前提是加载到 X509Certificate2 实例的证书具有与 WEBSITE_LOAD_CERTIFICATES 中指定的指纹相同的指纹。

有什么解决办法吗?

我更多地考虑了 WEBSITE_LOAD_CERTIFICATES 似乎如何产生影响 - 但我对此有一种有趣的感觉 实际上 仅使用指定的证书指纹。

所以我将 WEBSITE_LOAD_CERTIFICATES 值更改为虚拟指纹 - 任意 40 个字符的 Base16 字符串,并重新 运行 我的测试 - 它有效,即使指纹没有关系我正在使用的证书。

似乎只需定义 WEBSITE_LOAD_CERTIFICATES 即可使 Azure 网站能够使用 X509CertificateX509Certificate2 - 即使加载的证书从未安装到甚至检索不到来自任何系统范围或用户配置文件证书存储(如 MMC.exe 的证书管理单元中所示)。

这种行为似乎没有在任何地方记录,所以我在这里提到它。

我已就此联系 Azure 支持。

关于我在年中注意到的行为变化 - 很可能我最初为我们使用的测试证书设置了 WEBSITE_LOAD_CERTIFICATES。当我在今年晚些时候 6 月左右进行新部署时,我必须重置 应用程序设置 ,它删除了 WEBSITE_LOAD_CERTIFICATES,因此破坏了 X509Certificate2 个实例。

长话短说:

  1. portal.azure.com
  2. 中打开您的 Azure 应用服务(Azure 网站)边栏选项卡
  3. 转到应用程序设置页面
  4. 滚动到应用程序设置
  5. 添加一个新的条目键:WEBSITE_LOAD_CERTIFICATES,并为其提供一个虚拟的(假的,虚构的,运行domly-generated)值。
  6. X509Certificate2( Byte[], String, X509KeyStorageFlags ) 构造函数现在可以工作,但请注意:
    • keyStorageFlags: X509KeyStorageFlags.MachineKeySet 将失败 "Access denied"
    • 所有其他 keyStorageFlags 值,包括 MachineKeySet | UserKeySet 都会成功(即 MachineKeySet 本身会失败,但 MachineKeySet 与其他位集一起使用会起作用) .