自 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
).
它目前失败并显示两条错误消息,具体取决于输入:
CryptographicException
"The system cannot find the file specified."
CryptographicException
"Access denied."
我写了一个广泛的测试用例,尝试 X509Certificate2
构造函数参数的不同组合,以及使用和不使用 WEBSITE_LOAD_CERTIFICATES
Azure 应用程序设置。
以下是我在处理包含私钥且没有密码保护的上传 PFX/PKCS#12 证书文件时的发现:
- 运行 在我的开发盒上的 IIS Express 下:
- 无论
X509KeyStorageFlags
值如何,加载证书文件总是成功。
- 导出证书文件至少需要
X509KeyStorageFlags.Exportable
.
- 运行 在未加载
w3wp.exe
用户配置文件的生产服务器(不是 Azure 应用服务)上的 IIS 下:
- 加载证书文件需要
X509KeyStorageFlags.UserKeySet
未设置 ,否则总是成功。
- 导出证书文件至少需要
X509KeyStorageFlags.Exportable
,否则总是成功,否则失败"Key not valid for use in specified state."
- 运行 在 Azure App Service 下,没有定义
WEBSITE_LOAD_CERTIFICATES
:
- 加载设置了
MachineKeySet
且 UserKeySet
设置为 而非 的证书失败并显示 CryptographicException
:"Access denied."
- 使用任何其他
keyStorageFlags
值(包括 UserKeySet | MachineKeySet | Exportable
或 DefaultKeySet
之类的值加载证书失败并显示 CryptographicException
:"The system cannot find the file specified."
- 因为我根本无法加载证书,所以我无法测试导出证书。
- 运行 在 Azure App Service 下,
WEBSITE_LOAD_CERTIFICATES
定义为已上传证书的指纹:
- 加载带有
MachineKeySet
和 UserKeySet
的证书是 not 集,失败 CryptographicException
:"Access denied."。
- 所以像
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
个实例。
长话短说:
- 在
portal.azure.com
中打开您的 Azure 应用服务(Azure 网站)边栏选项卡
- 转到应用程序设置页面
- 滚动到应用程序设置
- 添加一个新的条目键:
WEBSITE_LOAD_CERTIFICATES
,并为其提供一个虚拟的(假的,虚构的,运行domly-generated)值。
X509Certificate2( Byte[], String, X509KeyStorageFlags )
构造函数现在可以工作,但请注意:
keyStorageFlags: X509KeyStorageFlags.MachineKeySet
将失败 "Access denied"
- 所有其他
keyStorageFlags
值,包括 MachineKeySet | UserKeySet
都会成功(即 MachineKeySet
本身会失败,但 MachineKeySet
与其他位集一起使用会起作用) .
我有一个 .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
).
它目前失败并显示两条错误消息,具体取决于输入:
CryptographicException
"The system cannot find the file specified."CryptographicException
"Access denied."
我写了一个广泛的测试用例,尝试 X509Certificate2
构造函数参数的不同组合,以及使用和不使用 WEBSITE_LOAD_CERTIFICATES
Azure 应用程序设置。
以下是我在处理包含私钥且没有密码保护的上传 PFX/PKCS#12 证书文件时的发现:
- 运行 在我的开发盒上的 IIS Express 下:
- 无论
X509KeyStorageFlags
值如何,加载证书文件总是成功。 - 导出证书文件至少需要
X509KeyStorageFlags.Exportable
.
- 无论
- 运行 在未加载
w3wp.exe
用户配置文件的生产服务器(不是 Azure 应用服务)上的 IIS 下:- 加载证书文件需要
X509KeyStorageFlags.UserKeySet
未设置 ,否则总是成功。 - 导出证书文件至少需要
X509KeyStorageFlags.Exportable
,否则总是成功,否则失败"Key not valid for use in specified state."
- 加载证书文件需要
- 运行 在 Azure App Service 下,没有定义
WEBSITE_LOAD_CERTIFICATES
:- 加载设置了
MachineKeySet
且UserKeySet
设置为 而非 的证书失败并显示CryptographicException
:"Access denied." - 使用任何其他
keyStorageFlags
值(包括UserKeySet | MachineKeySet | Exportable
或DefaultKeySet
之类的值加载证书失败并显示CryptographicException
:"The system cannot find the file specified." - 因为我根本无法加载证书,所以我无法测试导出证书。
- 加载设置了
- 运行 在 Azure App Service 下,
WEBSITE_LOAD_CERTIFICATES
定义为已上传证书的指纹:- 加载带有
MachineKeySet
和UserKeySet
的证书是 not 集,失败CryptographicException
:"Access denied."。- 所以像
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
个实例。
长话短说:
- 在
portal.azure.com
中打开您的 Azure 应用服务(Azure 网站)边栏选项卡
- 转到应用程序设置页面
- 滚动到应用程序设置
- 添加一个新的条目键:
WEBSITE_LOAD_CERTIFICATES
,并为其提供一个虚拟的(假的,虚构的,运行domly-generated)值。 X509Certificate2( Byte[], String, X509KeyStorageFlags )
构造函数现在可以工作,但请注意:keyStorageFlags: X509KeyStorageFlags.MachineKeySet
将失败 "Access denied"- 所有其他
keyStorageFlags
值,包括MachineKeySet | UserKeySet
都会成功(即MachineKeySet
本身会失败,但MachineKeySet
与其他位集一起使用会起作用) .