访问私钥的致命错误导致SQL Server无法启动

和证书相关的SQL Server无法启动问题可能会有很多原因。今天介绍其中一种情况。这种情况相对少见,而且根本原因也隐藏的比较深。

                                  

SQL Server无法启动的症状


当SQL Server无法启动的时候,一般都要检查SQL error log和Windows event log来对问题进行判断。有时候你在SQL error log里看到如下错误。

2010-06-28 17:40:47.72 server Encryption requested but no valid certificate was found. SQL Server terminating. 2010-06-28 17:40:47.72 server Error: 17826, Severity: 18, State: 1 2010-06-28 17:40:47.72 server Could not set up Net-Library 'SSNETLIB'.. 2010-06-28 17:40:47.72 server Unable to load any netlibs. 2010-06-28 17:40:47.72 server SQL Server could not spawn FRunCM thread.

 

更加关键的是,你在Windows Security log中会看到如下错误。

A fatal error occurred when attempting to access the SSL server credential private key. The error code returned from the cryptographic module is 0x80090022.

 

这类问题一般都是由于证书不合法,或者SQL Server无法访问指定的证书做成的。

问题的原因


看到上述错误信息,我们可以清楚的看到问题的直接原因是SQL Server在启动时检测到证书但是无法访问该证书的私钥。因此我们的第一反应是去检查私钥是否存在于证书之内,以及SQL Server的启动账户是否有访问证书的完全权限。这样的检查对大多数私钥访问问题是有效果的。不过可惜是它不能解决我们今天讨论的这个问题。

这个问题的关键是那个错误代码0x80090022。0x80090022的意思是“Provider could not perform the action since the context was acquired as silent”。怎么理解呢?你可以认为是SQL Server无法访问证书的私钥因为在静默模式下无法提供私钥的密码。

于是问题就好理解了。SQL Server在访问证书的时候是在数据库引擎内部访问的,没有界面供用户输入东西,这就是所谓的静默模式。因此一旦在秘钥访问时弹出一个对话框要求输入任何密码的话,由于我们在静默模式下看不到这个框,也就不能做输入,最后导致SQL Server访问秘钥失败而无法启动。对话框的样子如下所示:

 

 

 

正常情况下当你访问证书的秘钥时是不会有弹出的对话框让你输入私钥密码的。但是如果你在导入证书时,选择了”Enable strong private key protection”选项(如下图所示),那么在访问私钥的时候就会被要求输入密码。

问题的症结清楚了。

                             

解决问题的办法


清楚了根本,那么解决问题就容易了。我们只需要把证书从certificate store里删除掉,然后重新导入一次。重新导入的时候确保”Enable strong private protection”选项没有被选上,这样就行了。

另外大家可能要留意一个本地组策略的安全选项”System cryptography: Force strong key protection for user keys stored on the computer”。这个选项会编辑一个注册表键值: HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Cryptography\ForceKeyProtection。

此键值的默认值是0。一旦这个键值被设置为非0(对应的就是在本地组策略中将”System cryptography: Force strong key protection for user keys stored on the computer”设置为非”User input is not required when new keys are stored and used”项时),则在导入证书时,”Enable strong private protection”选项就会被默认选中。因此在导入证书的时候就会无意识选中”Enable strong private protection”选项。