自2017年中期以来,Azure App Services(Azure网站)上的X509Certificate2?

Dai*_*Dai 4 azure x509certificate azure-web-sites

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

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

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

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

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

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

它目前失败,有两个错误消息根据输入而变化:

  • CryptographicException "该系统找不到指定的文件."
  • CryptographicException "拒绝访问."

我编写了一个广泛的测试用例,它尝试不同的X509Certificate2构造函数参数组合,以及有和没有WEBSITE_LOAD_CERTIFICATESAzure应用程序设置.

以下是我使用上传的PFX/PKCS#12证书文件时的调查结果,该文件包含私钥但没有密码保护:

  • 在我的开发箱上运行IIS Express:
    • 无论X509KeyStorageFlags值如何,加载证书文件总是成功的.
    • 导出证书文件至少需要X509KeyStorageFlags.Exportable.
  • w3wp.exe未加载用户配置文件的生产服务器(不是Azure应用服务)上的IIS下运行:
    • 加载证书文件要求X509KeyStorageFlags.UserKeySet设置,但在其他方面总是成功.
    • 导出证书文件至少需要X509KeyStorageFlags.Exportable,但总是成功,否则失败,"密钥无法在指定状态下使用".
  • 在Azure App Service下运行,WEBSITE_LOAD_CERTIFICATES未定义:
    • 加载与证书MachineKeySet集,并UserKeySet设置失败,出现CryptographicException"拒绝访问".
    • 使用任何其他keyStorageFlags值加载证书,包括类似UserKeySet | MachineKeySet | Exportable或仅DefaultKeySet失败的值CryptographicException:"系统找不到指定的文件."
    • 由于我根本无法加载证书,因此无法测试导出证书.
  • 在Azure App Service下运行,并WEBSITE_LOAD_CERTIFICATES定义为已上载证书的指纹:
    • 加载与证书MachineKeySet ,并 UserKeySet设置,失败CryptographicException:"访问被拒绝"..
      • 所以价值观UserKeySetUserKeySet | MachineKeySetExportable将会奏效.
    • 导出证书需要X509KeyStorageFlags.Exportable- 与所有其他环境相同.

所以似乎WEBSITE_LOAD_CERTIFICATES似乎工作 - 但只有当加载到X509Certificate2实例中的证书具有与指定的相同的指纹时WEBSITE_LOAD_CERTIFICATES.

有没有办法解决?

Dai*_*Dai 12

我想更多关于如何WEBSITE_LOAD_CERTIFICATES有所作为 - 但我有一种有趣的感觉,它真的只使用指定的证书指纹.

因此,我将WEBSITE_LOAD_CERTIFICATES值更改为虚拟指纹 - 任意40个字符的Base16字符串,并重新运行我的测试 - 它工作正常,即使指纹与我正在使用的证书无关.

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

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

我已经联系过Azure支持.

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

TL; DR:

  1. 打开您的Azure应用服务(Azure网站)刀片 portal.azure.com
  2. 转到" 应用程序设置"页面
  3. 滚动到应用程序设置
  4. 添加一个新的输入键:WEBSITE_LOAD_CERTIFICATES,并为其提供虚拟(伪造,伪造,随机生成)值.
  5. X509Certificate2( Byte[], String, X509KeyStorageFlags )构造函数将现在的工作,但要注意:
    • keyStorageFlags: X509KeyStorageFlags.MachineKeySet "拒绝访问"将失败
    • 所有其他keyStorageFlags值,包括MachineKeySet | UserKeySet将成功(即MachineKeySet,本身将失败,但MachineKeySet与其他位集合使用将起作用).

  • [`WEBSITE_LOAD_USER_PROFILE` 也会解决这个问题](https://github.com/projectkudu/kudu/wiki/Configurable-settings#add-user-profile-support-for-a-site) (3认同)
  • 这对我有用,谢谢!ps 以下构造函数也将起作用: X509Certificate2("fileName.pfx", "password") (2认同)