自2017年中以来是否在Azure应用服务(Azure网站)上提供X509Certificate2? [英] X509Certificate2 on Azure App Services (Azure Websites) since mid-2017?
问题描述
我有一个.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上运行(<代码>NT 6.2.9200.0 ).
当前失败,并显示两条错误消息,具体取决于输入:
-
CryptographicException
系统找不到指定的文件." -
CryptographicException
访问被拒绝."
我编写了一个广泛的测试用例,它尝试使用 X509Certificate2
构造函数参数的不同组合,以及使用和不使用 WEBSITE_LOAD_CERTIFICATES
Azure应用程序设置的情况.
在使用包含私有密钥但没有密码保护的上载PFX/PKCS#12证书文件时,这是我的发现:
- 在我的开发盒上的IIS Express下运行:
- 无论
X509KeyStorageFlags
值如何,加载证书文件总是成功. - 导出证书文件至少需要
X509KeyStorageFlags.Exportable
.
- 无论
- 在未加载
w3wp.exe
用户配置文件的生产服务器(不是Azure App Service)上的IIS下运行:- 加载证书文件要求未设置 X509KeyStorageFlags.UserKeySet ,否则始终成功.
- 导出证书文件至少需要
X509KeyStorageFlags.Exportable
,但是否则始终会成功,否则会失败,并显示密钥在指定状态下无效".
- 在未定义
WEBSITE_LOAD_CERTIFICATES
的Azure应用服务下运行:- 使用
MachineKeySet
设置且UserKeySet
设置为 not 设置的证书加载失败,并显示CryptographicException
:拒绝访问." - 使用其他任何
keyStorageFlags
值加载证书,包括UserKeySet |MachineKeySet |可导出
或仅DefaultKeySet
失败,并出现CryptographicException
:系统找不到指定的文件." - 由于我完全无法加载证书,因此无法测试导出证书.
- 使用
- 在Azure App Service下运行,将
WEBSITE_LOAD_CERTIFICATES
定义为上载的证书的指纹:- 未设置未设置
MachineKeySet
和UserKeySet
的证书,失败并出现CryptographicException 代码>:访问被拒绝.".
- 因此,诸如
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:
- 在
portal.azure.com
中打开您的Azure应用服务(Azure网站)刀片 - 转到应用程序设置页面
- 滚动到应用设置
- 添加一个新的输入键:
WEBSITE_LOAD_CERTIFICATES
,并为其提供一个虚拟(伪造,伪造,随机生成的)值. -
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
.
- Loading the certificate file always succeeds, regardless of
- 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."
- Loading the certificate file requires that
- Running under Azure App Service, without
WEBSITE_LOAD_CERTIFICATES
defined:- Loading the certificate with
MachineKeySet
set andUserKeySet
is not set fails with aCryptographicException
: "Access denied." - Loading the certificate with any other
keyStorageFlags
value, including values likeUserKeySet | MachineKeySet | Exportable
or justDefaultKeySet
fails with aCryptographicException
: "The system cannot find the file specified." - As I was not able to load the certificate at all I could not test exporting certificates.
- Loading the certificate with
- Running under Azure App Service, with
WEBSITE_LOAD_CERTIFICATES
defined as the thumbprint of the certificate that was uploaded:- Loading the certificate with
MachineKeySet
andUserKeySet
is not set, fails withCryptographicException
: "Access denied." .- So values like
UserKeySet
andUserKeySet | MachineKeySet
andExportable
will work.
- So values like
- Exporting certificates requires
X509KeyStorageFlags.Exportable
- same as all other environments.
- Loading the certificate with
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:
- Open your Azure App Service (Azure Website) blade in
portal.azure.com
- Go to the Application settings page
- Scroll to App settings
- Add a new entry key:
WEBSITE_LOAD_CERTIFICATES
, and provide a dummy (fake, made-up, randomly-generated) value for it. - The
X509Certificate2( Byte[], String, X509KeyStorageFlags )
constructor will now work, but note:keyStorageFlags: X509KeyStorageFlags.MachineKeySet
will fail with "Access denied"- All other
keyStorageFlags
values, includingMachineKeySet | UserKeySet
will succeed (i.e.MachineKeySet
by itself will fail, butMachineKeySet
used in conjunction with other bits set will work).
这篇关于自2017年中以来是否在Azure应用服务(Azure网站)上提供X509Certificate2?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!