DENY 覆盖 SQL Server 中的 GRANT?

Joh*_*ith 7 sql-server

我正在学习 70-462 考试,我正在练习一些我在网上找到的练习。在站点“Microsoft 问答”中,一个我不明白的解决方案

解决方案的最后一步是“拒绝员工角色对 SalaryDetails 表的 SELECT 访问”。但是,所有公司员工都被添加到此角色中,并且因为“HR 管理员也是公司员工”,因此 HR 管理员最终应该没有对 SalaryDetails 表的任何访问权限,这不是所要求的。

解决方案是错误的,还是我遗漏了什么?

在此先感谢您的帮助!

小智 4

它与权限层次结构以及使用角色成员资格而不是直接向每个登录授予权限有关。这篇 SQLMag 文章很好地展示了 SQL Server 中的层次结构。[如果这篇文章消失了,我复制了下面的图片。] 在此输入图像描述

您正在授予DENY该角色Employees,因此人力资源管理员作为更高级别角色的成员应该意味着他们不会直接继承DENY. 至少我是这么理解的。

引用的文章的特定部分涉及DENY

第三个权限语句是DENY。DENY 语句也会撤销权限,但这样做的方式使得主体无法通过角色成员身份继承权限。当您拒绝许可时,该委托人就没有该许可,就这样。拒绝权限可以让您获得非常精细的权限。一个常见的示例是通过角色的成员身份向部门中的每个人授予一组权限。但是,您可以通过拒绝某些用户或仅用户子集所属的另一个角色的权限来微调该方案,利用用户属于多个角色的能力。

我纠正了

首先让我声明,我为没有首先测试我所说的话而道歉,因为我最终证明自己是错的。我应该更清楚。

要学习的第一课:测试一切。

第二个教训:并非所有 Microsoft 考试问题都是完美的。我建议坚持使用 Microsoft 支持的测试引擎(例如MeasureUp.com

先回答再详细

我将首先向您介绍我的发现,然后向您展示我如何测试它。所以我的发现是,如果您使用而不是,基本上选项 D可能是正确的。这是基于 Bob Beauchemin 关于 SQL Server 2005 安全最佳实践的白皮书中的声明:REVOKEDENY

在 SQL Server 中,授权是通过数据访问语言 (DAL) 而不是 DDL 或 DML 完成的。除了 ISO-ANSI 标准规定的两个 DAL 动词 GRANT 和 REVOKE 之外,SQL Server 还包含一个 DENY DAL 动词。当用户是多个数据库主体的成员时,DENY 与 REVOKE 不同。如果用户 Fred 是三个数据库角色 A、B 和 C 的成员,并且角色 A 和 B 被授予了对安全对象的权限,则如果从角色 C 撤消该权限,Fred 仍然可以访问该安全对象。如果安全对象被角色 C 拒绝,则 Fred 无法访问该安全对象。这使得管理 SQL Server 与管理 Windows 系列操作系统的其他部分类似。

因此,基本上REVOKE删除了权限,并且基本上不会对表本身应用任何权限。您没有明确拒绝任何人访问该表。因此,如果您确实想拒绝权限,则必须从员工角色中删除 HRAdmins 组才能使其正常工作。

我无权访问 Azure SQL,因此只能在本地 SQL Server 2014 实例上进行测试。下面的脚本是我经历过的,包括我的评论。

USE [master];
GO
--Create a database to work with
CREATE DATABASE [Database_WorkingWithPermissions];
GO

--Create the logins (I can't create Windows Groups but should work the same way)
CREATE LOGIN HRAdmin1 WITH PASSWORD = N'Apple123';

CREATE LOGIN Employee1 WITH PASSWORD = N'Apple123';

--Create the users in the database
USE [Database_WorkingWithPermissions];
GO

CREATE USER Employee1 FROM LOGIN Employee1;
CREATE USER HRAdmin1 FROM LOGIN HRAdmin1;
GO

--Create the role
CREATE ROLE Employees

--Create the tables noted in the question
CREATE TABLE [Employees] (employeeID int IDENTITY(1,1), employeeName varchar(15));
CREATE TABLE [SalaryDetails] (employeeID int, salaryAmount decimal(12,3));
CREATE TABLE [OtherTable] (column1 int);

--Grant permissions to the roles according to requirements
GRANT SELECT ON [dbo].[Employees] TO [Employees];
GO
GRANT SELECT ON [dbo].[OtherTable] TO [Employees];
GO
DENY SELECT ON [dbo].[SalaryDetails] TO [Employees];
GO

--Assign membership to the role based on requirements
ALTER ROLE [Employees] ADD MEMBER [Employee1];
GO
ALTER ROLE [Employees] ADD MEMBER [HRAdmin1]
GO
ALTER ROLE [db_datareader] ADD MEMBER [HRAdmin1];
GO

--Go through and see what permissions
EXECUTE AS USER = 'HRAdmin1'
SELECT * FROM [dbo].[Employees];
SELECT * FROM [dbo].[SalaryDetails];
REVERT;

EXECUTE AS USER = 'Employee1'
SELECT * FROM [dbo].[Employees];
SELECT * FROM [dbo].[SalaryDetails];
REVERT;

--So HRAdmin1 does not have permissions as it should
-- So they need to be removed from the Employee role
ALTER ROLE [Employees] DROP MEMBER [HRAdmin1]
GO

--Run the test again
--Go through and see what permissions
EXECUTE AS USER = 'HRAdmin1'
SELECT * FROM [dbo].[Employees];
SELECT * FROM [dbo].[SalaryDetails];
REVERT;

EXECUTE AS USER = 'Employee1'
SELECT * FROM [dbo].[Employees];
SELECT * FROM [dbo].[SalaryDetails];
REVERT;

--According to a SQL Server 2005 whitepaper Bob Beauchemin wrote on Security Best Practices
-- Revoke should be used
ALTER ROLE [Employees] ADD MEMBER [HRAdmin1]
GO
REVOKE SELECT ON [dbo].[SalaryDetails] TO [Employees];
GO

--Run the test again
--Go through and see what permissions
EXECUTE AS USER = 'HRAdmin1'
SELECT * FROM [dbo].[Employees];
SELECT * FROM [dbo].[SalaryDetails];
REVERT;

EXECUTE AS USER = 'Employee1'
SELECT * FROM [dbo].[Employees];
SELECT * FROM [dbo].[SalaryDetails];
REVERT;
Run Code Online (Sandbox Code Playgroud)