4. 服务器角色与固定角色
在 SQL Server 的权限体系中,登录名(Login)解决的是“能不能连上实例”,而服务器角色(Server Role)解决的是“连上之后能在实例级别做什么”。固定服务器角色是 SQL Server 预置的一组权限容器,它们把一组服务器级权限打包在一起,管理员只需把登录名加入角色,就完成了授权。理解每个固定角色的权限边界,是实施最小权限原则的前提。
固定服务器角色的权限边界
SQL Server 提供九个固定服务器角色,它们的权限范围从“几乎无所不能”到“仅能查看部分元数据”,差异极大。下面这张图展示了主要固定服务器角色的权限层级与关键能力边界。
需要特别注意的是 securityadmin 角色。它本身不直接拥有数据访问权限,但可以管理登录名和服务器角色成员。这意味着一个 securityadmin 成员可以给自己或他人授予 sysadmin 角色,从而实现间接提权。因此在实际治理中,securityadmin 的成员应当与 sysadmin 同等严格地管控。
public 角色是一个特殊存在:每个登录名都自动属于它,且无法被移除。它的权限就是所有登录名共享的“权限基线”。如果误将高权限授予 public,等于授予了所有能连上实例的登录名。例如执行 GRANT VIEW SERVER STATE TO public 后,任何登录名都能查看服务器运行状态,这通常不是期望的结果。
最小权限原则的落地方法
最小权限原则要求:只授予完成工作所必需的最小权限,且只在必要的时间内授予。在服务器角色层面,落地方法可以归纳为三条。
- 能用固定角色就不自建角色。固定角色的权限边界由 SQL Server 定义和维护,行为可预期;自建服务器角色虽然灵活,但容易因权限叠加而失控。
- 能用窄角色就不用宽角色。例如需要创建数据库的账号,加入 dbcreator 即可,不要加入 sysadmin;需要管理登录名的账号,加入 securityadmin 即可,同样不要加入 sysadmin。
- 定期审计角色成员。人员岗位变动后,旧角色成员往往被遗忘。应定期查询角色成员清单,清理不再需要的成员。
下面是一段可直接执行的审计脚本,用于列出所有固定服务器角色及其成员,帮助发现权限过宽或长期未清理的账号。
-- 查询固定服务器角色成员清单
SELECT
r.name AS 角色名,
r.type_desc AS 角色类型,
m.name AS 成员登录名,
m.type_desc AS 成员类型,
m.create_date AS 登录名创建时间
FROM sys.server_role_members srm
JOIN sys.server_principals r
ON srm.role_principal_id = r.principal_id
JOIN sys.server_principals m
ON srm.member_principal_id = m.principal_id
WHERE r.is_fixed_role = 1
ORDER BY r.name, m.name;
-- 单独检查 sysadmin 成员(重点关注)
SELECT p.name AS sysadmin成员, p.type_desc, p.create_date
FROM sys.server_role_members srm
JOIN sys.server_principals p
ON srm.member_principal_id = p.principal_id
JOIN sys.server_principals r
ON srm.role_principal_id = r.principal_id
WHERE r.name = 'sysadmin';
执行结果中,如果 sysadmin 成员列表里出现了应用程序账号、普通运维账号或已离职人员的登录名,就说明权限治理存在缺口。合理的做法是:sysadmin 只保留极少数管理员账号,且这些账号不用于日常业务连接。
角色成员管理操作
角色成员管理使用 ALTER SERVER ROLE 语句,语法简洁但需要谨慎执行。以下示例展示添加成员、移除成员以及创建自定义服务器角色的完整过程。
-- 将登录名加入固定服务器角色
ALTER SERVER ROLE securityadmin ADD MEMBER [DOMAIN\zhangsan];
-- 从固定服务器角色移除成员
ALTER SERVER ROLE securityadmin DROP MEMBER [DOMAIN\zhangsan];
-- 创建自定义服务器角色并授予有限权限
CREATE SERVER ROLE role_ops_readonly;
GRANT VIEW SERVER STATE TO role_ops_readonly;
GRANT VIEW ANY DEFINITION TO role_ops_readonly;
-- 将登录名加入自定义角色
ALTER SERVER ROLE role_ops_readonly ADD MEMBER [DOMAIN\lisi];
执行 ALTER SERVER ROLE ... ADD MEMBER 需要当前用户拥有 ALTER ANY SERVER ROLE 权限,或者本身是 sysadmin 成员。移除成员时,如果该成员是角色中最后一个拥有某权限的账号,需要确认移除后不会影响正常运维。
常见误区与判断依据
在实际治理中,有几个高频误区值得警惕。第一,把 dbcreator 当成“普通开发权限”随意授予。dbcreator 成员创建的数据库会自动成为其 dbo,如果该成员在数据库中创建了恶意对象或修改了安全配置,影响范围会超出预期。第二,认为 public 角色“没有权限所以不用管”。public 的权限是所有登录名的公共基线,任何对 public 的授权都会放大到全体登录名。第三,忽略 securityadmin 的提权能力,把它当作“只读安全查看角色”授予审计人员。
判断一个账号的服务器角色配置是否合理,可以问三个问题:这个账号是否真的需要实例级权限?它加入的角色是否是满足需求的最窄角色?它的成员资格是否有明确的到期或复核时间?如果三个问题都能给出肯定且具体的答案,配置基本是合理的;如果任何一个问题答不上来,就应当重新评估。
ALTER SERVER ROLE sysadmin ADD MEMBER 将自己或他人提升为 sysadmin。因此,securityadmin 的成员名单应当与 sysadmin 一样受到严格审批和定期审计,不能因为“它不直接访问数据”就放松管控。
总结来说,固定服务器角色的治理核心是“边界清晰、按需授予、定期复核”。sysadmin 和 securityadmin 属于高敏感角色,成员应少而精;serveradmin 和 dbcreator 属于功能性角色,应按岗位职责授予;public 是所有登录名的公共基线,任何授权都需评估影响面。把这三层关系理清,服务器级权限治理就有了稳固的基础。