审计触发器中的当前事务ID

时间:2009-08-12 10:27:39

标签: sql-server tsql

我正在考虑从审计触发器中存储某种形式的事务ID。解决方案似乎是使用sys.dm_tran_current_transaction,如本文SQL Server Triggers - grouping by transactions中所述。

但是,我不能使用它,因为运行sql语句的用户帐户不具有“VIEW SERVER STATE”权限并导致错误:

Msg 297, Level 16, State 1, Line 3
The user does not have permission to perform this action.

是否有人知道此视图的替代方法将提供类似的事务ID或在触发器上使用“WITH EXECUTE AS”以允许从此视图中进行选择。

从我对“WITH EXECUTE AS”的尝试看来,服务器级别的权限似乎没有被转移,这是因为模拟数据库用户所以这是真的。

5 个答案:

答案 0 :(得分:13)

您可以使用代码签名解决几乎所有安全问题。大多数细粒度和精细调整的访问控制,只是有点难以理解。

在触发器上使用EXECUTE AS OWNER,创建证书,签署触发器,删除私钥(以便其他任何人都无法使用它再次签署任何内容),导出证书(仅限公钥),导入master中的证书,创建从证书派生的登录,授予对此登录的身份验证(以extend the database execute as impersonation为目的地),然后将查看服务器状态授予此登录。这是防弹,完全控制的特权控制。如果需要更改触发器,则必须再次执行签名过程(包括证书派生登录和授权)。从安全的角度来看,这是期望的(您正在签署触发器的特定变体),从操作的角度来看,它是一个皮塔饼,但是可以管理。

create table t (i int);
create table audit (transaction_id int);
go

create trigger t_audit_trigger
on t
with execute as owner
after insert, update, delete
as
begin
    set nocount on;
    insert into audit (transaction_id) 
    select transaction_id from sys.dm_tran_current_transaction;
    if (@@ROWCOUNT != 1)
        raiserror(N'Failed to audit transaction', 16, 1);
end
go

create certificate t_audit_view_server
    encryption by password = 'Password#123'
    with subject = N't_audit_view_server'
    , start_date = '08/10/2009';
go

add signature to t_audit_trigger
    by certificate t_audit_view_server
    with password = 'Password#123';
go

alter certificate t_audit_view_server
    remove private key;

backup certificate t_audit_view_server
    to file = 'c:\temp\t_audit_view_server.cer';
go

use master;
go

create certificate t_audit_view_server
    from file = 'c:\temp\t_audit_view_server.cer';
go  

create login t_audit_view_server_login
    from certificate t_audit_view_server;
go

grant authenticate server to t_audit_view_server_login;
grant view server state to t_audit_view_server_login;
go

答案 1 :(得分:3)

从SQL Server 2008开始,Microsoft引入了sys.dm_exec_requests,即弃用sys.sysprocesses。此视图返回transaction_id,可以在不授予VIEW SERVER STATE的情况下调用。与sys.sysprocesses一样,如果未授予VIEW SERVER STATE,则返回当前进程的详细信息,如果是,则返回所有进程。

答案 2 :(得分:2)

虽然不是直接回答您的问题,而是使用自定义构建的审核框架,但在SQL Server 2008中您可以使用更改数据捕获技术。

请参阅联机丛书中的以下参考资料:http://msdn.microsoft.com/en-us/library/bb522489.aspx

编辑(解决方案,已添加):以下是如何创建存储过程以访问系统视图,使用execute as子句和使用模拟的演练。

USE MASTER;

select * from sys.dm_tran_current_transaction

--Create a login with view server state permissions
CREATE LOGIN ViewServerStateLogin
WITH password = 'Hello123';
CREATE user ViewServerStateLogin;

--Create a login to test the permissions assignment
CREATE LOGIN TestViewServerState
WITH password = 'Hello123';
CREATE user TestViewServerState;

--Test with Login
EXECUTE AS LOGIN = 'TestViewServerState';
    --This obviously does not work.
    select * from sys.dm_tran_current_transaction
revert;

--Grant view server state permission to the ViewServerStateLogin
GRANT VIEW SERVER state TO ViewServerStateLogin;

--Create a procedure to wrap the call to the system view
CREATE PROCEDURE proc_TestViewServerState

AS
    SET NOCOUNT ON;

    EXECUTE AS LOGIN='ViewServerStateLogin'

        select * from sys.dm_tran_current_transaction

    revert;

RETURN(0);

--Assign execute permission to the test accounts
GRANT EXECUTE ON proc_TestViewServerState TO TestViewServerState

--Grant impersonation rights to the test login
GRANT IMPERSONATE ON LOGIN::ViewServerStateLogin TO TestViewServerState

--Test with Procedure
EXECUTE AS LOGIN = 'TestViewServerState';
    EXEC proc_TestViewServerState
revert;

答案 3 :(得分:1)

从SQL Server 2016开始,您可以使用CURRENT_TRANSACTION_ID。根据文件:

  

任何用户都可以返回当前会话的交易ID。

答案 4 :(得分:-1)

加密存储过程,不要共享ViewServerStateLogin的pw。然后你会得到一个足够密度的黑匣子来满足审核员的要求。