本文介绍了自2017年中以来是否在Azure应用服务(Azure网站)上提供X509Certificate2?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

 字符串filePassword = ...Byte [] userProvidedCertificateFile = ...using(X509Certificate2 cert = new X509Certificate2(rawData:userProvidedCertificateFile,password:filePassword,keyStorageFlags:X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet){...} 

2017年初,我将此代码部署到了Azure App Service(又名Azure网站)实例,并且工作正常-最初失败后,因为我确实设置了 UserKeySet 标志(就像Azure App Services一样)无法加载用户配置文件证书存储.

但是,自2017年中以来(可能在5月或6月左右),我的应用程序已停止运行-我假定Azure应用服务已移至更新的系统(尽管Kudu报告我的应用程序在Windows Server 2012上运行(:访问被拒绝.".

  • 因此,诸如 UserKeySet UserKeySet之类的值|MachineKeySet Exportable 将起作用.
  • 导出证书需要 X509KeyStorageFlags.Exportable -与所有其他环境相同.
  • 因此,看来 WEBSITE_LOAD_CERTIFICATES 似乎可行-但仅当加载到 X509Certificate2 实例中的证书具有与 WEBSITE_LOAD_CERTIFICATES

    中指定的相同的指纹时,代码>.

    有什么办法解决这个问题吗?

    解决方案

    我想了更多关于 WEBSITE_LOAD_CERTIFICATES 似乎有何改变的想法-但我对此真的感到很有趣 仅适用于指定的证书指纹.

    因此,我将 WEBSITE_LOAD_CERTIFICATES 值更改为虚拟指纹-任意40个字符的Base16字符串,然后重新运行了测试-并且即使指纹与证书无关,它仍然有效我当时在工作.

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

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

    我已与Azure支持人员联系.

    关于我在年中发现的行为变化-很可能我确实为我们正在使用的测试证书设置了 WEBSITE_LOAD_CERTIFICATES .当我在今年6月下旬进行新部署时,我必须重置应用程序设置,该设置删除了 WEBSITE_LOAD_CERTIFICATES 并因此破坏了 X509Certificate2 实例.

    TL; DR:

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

    I have a .NET Framework 4.7 application that allows users to upload X.509 certificates in PFX or PKCS#12 format (think: "SSL certificates" with the private key included), it then loads the certificate into a System.Security.Cryptography.X509Certificates.X509Certificate2 instance. As my application code also needs to re-export the certificate I specify the X509KeyStorageFlags.Exportable option.

    When running under IIS on my production web-server, the Windows user-profile for the identity that w3wp.exe runs under is not loaded, so I do not specify the UserKeySet flag.

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

    In early 2017 I deployed this code to an Azure App Service (aka Azure Website) instance and it worked okay - after initially failing because I did have the UserKeySet flag set (as Azure App Services do not load a user-profile certificate store.

    However, since mid-2017 (possibly around May or June) my application has stopped working - I assume the Azure App Service was moved to an updated system (though Kudu reports my application is running on Windows Server 2012 (NT 6.2.9200.0).

    It currently fails with two error messages that varied depending on input:

    • CryptographicException "The system cannot find the file specified."
    • CryptographicException "Access denied."

    I wrote an extensive test-case that tries different combinations of X509Certificate2 constructor arguments, as well as with and without the WEBSITE_LOAD_CERTIFICATES Azure application setting.

    Here are my findings when working with an uploaded PFX/PKCS#12 certificate file that contains a private key and does not have password-protection:

    • Running under IIS Express on my development box:
      • Loading the certificate file always succeeds, regardless of X509KeyStorageFlags value.
      • Exporting the certificate file requires at least X509KeyStorageFlags.Exportable.
    • Running under IIS on a production server (not an Azure App Service) where the w3wp.exe user-profile is not loaded:
      • Loading the certificate file requires that X509KeyStorageFlags.UserKeySet is not set, but otherwise always succeeds.
      • Exporting the certificate file requires at least X509KeyStorageFlags.Exportable, but otherwise always succeeds, otherwise it fails with "Key not valid for use in specified state."
    • Running under Azure App Service, without WEBSITE_LOAD_CERTIFICATES defined:
      • Loading the certificate with MachineKeySet set and UserKeySet is not set fails with a CryptographicException: "Access denied."
      • Loading the certificate with any other keyStorageFlags value, including values like UserKeySet | MachineKeySet | Exportable or just DefaultKeySet fails with a CryptographicException: "The system cannot find the file specified."
      • As I was not able to load the certificate at all I could not test exporting certificates.
    • Running under Azure App Service, with WEBSITE_LOAD_CERTIFICATES defined as the thumbprint of the certificate that was uploaded:
      • Loading the certificate with MachineKeySet and UserKeySet is not set, fails with CryptographicException: "Access denied." .
        • So values like UserKeySet and UserKeySet | MachineKeySet and Exportable will work.
      • Exporting certificates requires X509KeyStorageFlags.Exportable - same as all other environments.

    So it seems that WEBSITE_LOAD_CERTIFICATES seems to work - but only if the certificate being loaded into an X509Certificate2 instance has the same thumbprint as specified in WEBSITE_LOAD_CERTIFICATES.

    Is there any way around this?

    解决方案

    I thought more about how WEBSITE_LOAD_CERTIFICATES seems to make a difference - but I had a funny feeling about it really only working with the certificate thumbprint that's specified.

    So I changed the WEBSITE_LOAD_CERTIFICATES value to a dummy thumbprint - an arbitrary 40-character Base16 string, and re-ran my test - and it worked, even though the thumbprint had no relation to the certificate I was working with.

    It seems that simply having WEBSITE_LOAD_CERTIFICATES defined will enable the the Azure website's ability to use X509Certificate and X509Certificate2 - even if the loaded certificate is never installed into, or even retrieved from, any systemwide or user-profile certificate store (as seen in the Certificates snap-in for MMC.exe).

    This behaviour does not seem to be documented anywhere, so I'm mentioning it here.

    I've contacted Azure support about this.

    Regarding the behavioural change I noticed at mid-year - it's very likely that I did have WEBSITE_LOAD_CERTIFICATES originally set for a testing certificate we were using. When I made a new deployment later in the year around June I must have reset the Application settings which removed the WEBSITE_LOAD_CERTIFICATES and so broke X509Certificate2 instances.

    TL;DR:

    1. Open your Azure App Service (Azure Website) blade in portal.azure.com
    2. Go to the Application settings page
    3. Scroll to App settings
    4. Add a new entry key: WEBSITE_LOAD_CERTIFICATES, and provide a dummy (fake, made-up, randomly-generated) value for it.
    5. The X509Certificate2( Byte[], String, X509KeyStorageFlags ) constructor will now work, but note:
      • keyStorageFlags: X509KeyStorageFlags.MachineKeySet will fail with "Access denied"
      • All other keyStorageFlags values, including MachineKeySet | UserKeySet will succeed (i.e. MachineKeySet by itself will fail, but MachineKeySet used in conjunction with other bits set will work).

    这篇关于自2017年中以来是否在Azure应用服务(Azure网站)上提供X509Certificate2?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

    10-25 01:10