我发现关于如何准确格式化 SPN(服务主体名称)以获得正确的 Kerberos 连接以及每个 SQL 实例需要多少个相互矛盾的信息。
此 2017 MS 文档包含以下内容:
从 SQL Server 2008 开始,为了支持 TCP/IP、命名管道和共享内存上的 Kerberos 身份验证,更改了 SPN 格式。命名实例和默认实例支持的 SPN 格式如下。
- 命名实例:
MSSQLSvc/FQDN:[port|instancename]
- 默认实例:
MSSQLSvc/FQDN:port|MSSQLSvc/FQDN
新的 SPN 格式不需要端口号。这意味着多端口服务器或不使用端口号的协议可以使用 Kerberos 身份验证。
我认为最后一段的意思是我只需要一个条目,以下之一:
- 命名实例:
MSSQLSvc/sqlbox1.mydomain.org/instance2
- 默认实例:
MSSQLSvc/sqlbox1.mydomain.org
这似乎与这个较旧的 (2011) MS 文档相矛盾,不仅与端口号有关,还与使用什么名称有关:
要创建 SPN,您可以使用 SQL Server 的 NetBIOS 名称或完全限定域名 (FQDN)。但是,您必须为 NetBIOS 名称和 FQDN 创建一个 SPN。
当我查看环境中已经存在的 SPN 时,我看到了各种各样的组合,有些服务器最多有 4 个条目:
MSSQLSvc/sqlbox1
MSSQLSvc/sqlbox1:1433
MSSQLSvc/sqlbox1.mydomain.org
MSSQLSvc/sqlbox1.mydomain.org:1433
甚至MS 自己的 Kerberos 配置管理器似乎也想生成最后两个版本(带有适当的混淆):
同样,对于现有的命名实例,我看到了一个奇怪的组合,其中一些几乎可以肯定是无效的:
MSSQLSvc/sqlbox1:1522
MSSQLSvc/sqlbox1:instance2
MSSQLSvc/sqlbox1.mydomain.org:1522
MSSQLSvc/sqlbox1.mydomain.org:instance2
MSSQLSvc/sqlbox1.mydomain.org/instance2
MSSQLSvc/sqlbox1.mydomain.org:1522:instance2
那么,如果我只在我的环境中使用 TCP,那么对于默认实例和命名实例,我的 DSN 应该是什么样子呢?
我应该包括端口,还是不包括?还是包括一个带端口和一个不带?
仅使用 FQDN,还是只需要带有 Netbios 名称的条目?或者只有当我们使用命名管道(我们不是)时才会这样?
(对于上下文,我们运行 SQL 2005 到 2014,一些集群,另一些独立。连接仅通过 TCP,在配置管理器中禁用命名管道。我们将手动修复/创建这些,而不是允许 SQL 服务帐户创建它们服务器启动。)
如果您只使用 TCP/IP 连接到您的实例,则只需要指定的端口。通过命名管道协议连接到 SQL 实例时使用实例名称。遗憾的是,MS 文章没有直接说明哪种协议需要哪种格式,但它源自(我的环境中的许多测试)和以下MS 文章语句:
关于 FQDN 与 NETBIOS 名称,我会推荐 FQDN,因为如果您遇到随机 DNS 服务器问题,它们不会那么容易出现问题。
从我关于此事的博客文章中提取,格式应如下所示:
可以在此处找到 MS 的源参考。
现在让您的网络管理员日(例如,允许自注册 SPN 的 OU 配置)
您的网络管理员可以在包含所有 SQL Server 服务帐户的域上创建一个 OU,这些服务帐户可以配置为服务帐户可以为自己和自己单独创建 SPN。该方法主要遵循Ryan Reis 的博客,但有一些细微的调整,因此不会执行过度授权。
此过程描述了在域中创建 OU,以允许其中的帐户自行注册自己的 SPN:
完成上述步骤后,现在配置有问题的 OU 容器,以便添加到其中的任何帐户都能够为自己和自己单独注册和删除 SPN。这正是正确数量的权限,因为这些帐户将无法践踏其他帐户注册的 SPN。
在步骤 16 中重新启动 SQL Server 的目的是确保按预期注册 SPN。SQL 将尝试在关闭时删除任何已注册的 SPN,并在启动时添加它们,因此仅当所述 SQL Server 服务当前不存在 SPN 时才真正需要重新启动。
关于此方法的最后一点说明是,如果您在传统的故障转移群集实例 (FCI) 配置中运行 SQL Server,则不建议将此实例的服务帐户添加到此 OU,根据KB 2443457。
我真的需要发布我的 Kerberos 系列的第 2 部分......
当 SQL Server 服务创建 SPN 时,它会为每个实例创建两个。这是它使用的格式。
默认实例:
命名实例:
对于您的命名实例,如果手动创建 SPN,您将需要一个静态端口而不是默认的动态端口。