我有一个tSQLt测试,我期望它会失败,但是可以成功运行。当我在过程外运行代码时,它按预期失败,但是使用Run执行测试时,不会发生错误。
我已经阅读了问题tSQLt Testing SQL Server security permissions,但是接受的答案不能解决我的问题。
我的测试如下:
CREATE PROCEDURE TestSecurity.[test AFDK_Reader cannot read from AWS schema]
AS
BEGIN
--EXEC tSQLt.ExpectException
EXECUTE AS USER = 'AFDK_Reader'
select *
from sys.user_token
SELECT * FROM fn_my_permissions('AWS', 'SCHEMA')
ORDER BY subentity_name, permission_name ;
SELECT *
FROM [AWS].[ADRESSEPUNKT_HISTORIK]
REVERT
END
该角色仅授予对AFDK模式的选择权限,这是SQL用户具有的唯一数据库角色成员身份。
AFDK_Reader没有读取AWS模式的权限。
有人可以告诉我如何进行调试吗?预先感谢。
答案 0 :(得分:0)
EXECUTE AS... REVERT
命令在存储过程中的行为与您期望的不同。这是SQL Server中存储过程安全性的常规功能。存储过程的一种常见用法是抽象权限。 MS文档页面Customizing Permissions with Impersonation in SQL Server说:
如果已存储,SQL Server不会检查调用方的权限 过程和表具有相同的所有者。
这实际上就是这里发生的事情。即使EXECUTE AS
更改了安全上下文,也不会在存储过程中检查该安全上下文。
文档页面还显示:
但是,如果对象具有不同的所有权链接将不起作用 所有者,或者使用动态SQL。
获得预期行为的一种方法是从动态SQL语句内部运行SELECT
语句,这意味着将针对表权限对活动的安全上下文进行测试:
CREATE PROCEDURE TestSecurity.[test AFDK_Reader cannot read from AWS schema]
AS
BEGIN
EXEC tSQLt.ExpectException
EXECUTE AS USER = 'AFDK_Reader'
EXEC ('SELECT * FROM [AWS].[ADRESSEPUNKT_HISTORIK]')
REVERT
END
另一种(更好的)解决方案可能是使用内置的权限功能来通过元数据测试权限设置。这是仍然使用EXECUTE AS... REVERT
和sys.fn_my_permission
的一种方法:
CREATE PROCEDURE TestSecurity.[test AFDK_Reader cannot read from AWS schema]
AS
BEGIN
EXECUTE AS USER = 'AFDK_Reader'
DECLARE @permissionCount int = (SELECT COUNT(*) FROM sys.fn_my_permissions('[AWS].[ADRESSEPUNKT_HISTORIK]', 'OBJECT') WHERE permission_name = 'SELECT' AND subentity_name = '')
REVERT
EXEC tSQLt.AssertEquals 0, @permissionCount
END