【发布时间】:2021-08-03 16:52:40
【问题描述】:
过去我使用数据库触发器来记录所有架构更改。这是光荣的。但是,它要求任何需要修改架构的人都必须具有某些权限。我相信需要的是查看服务器状态。记不清了,但这篇文章需要哪些人并不重要。
问题是,如果有用户可以更改架构但不应该拥有该权限怎么办?这完全破坏了我的工具,因为触发器只会导致他们收到此错误。我可以将它包装在一个 try catch 中,但是如果它不记录更改,那显然会破坏整个目的。
有没有办法让这个触发器为每个人运行,即使我不能给每个人所有必需的权限?我猜答案是否定的,因为我不知道如何在某种模拟下触发触发器,而且我想不出任何其他解决方案。但我希望你们知道一些我不知道的事情!
这里是触发器:
CREATE TRIGGER [LogSchemaEvent]
ON DATABASE
FOR CREATE_TABLE, ALTER_TABLE, DROP_TABLE,
CREATE_VIEW, ALTER_VIEW, DROP_VIEW,
CREATE_PROCEDURE, ALTER_PROCEDURE, DROP_PROCEDURE,
CREATE_FUNCTION, ALTER_FUNCTION, DROP_FUNCTION,
CREATE_TRIGGER, ALTER_TRIGGER, DROP_TRIGGER,
CREATE_SCHEMA, ALTER_SCHEMA, DROP_SCHEMA,
CREATE_INDEX, ALTER_INDEX, DROP_INDEX,
CREATE_TYPE, DROP_TYPE
AS
BEGIN
SET NOCOUNT ON
DECLARE @EventData XML = EVENTDATA()
DECLARE @ip VARCHAR(32) = (
SELECT client_net_address
FROM sys.dm_exec_connections
WHERE session_id = @@SPID)
INSERT SchemaEvents (
EventType,
EventDDL,
EventXML,
DatabaseName,
SchemaName,
ObjectName,
HostName,
IPAddress,
ProgramName,
LoginName)
SELECT
@EventData.value('(/EVENT_INSTANCE/EventType)[1]', 'NVARCHAR(100)'),
@EventData.value('(/EVENT_INSTANCE/TSQLCommand)[1]', 'NVARCHAR(MAX)'),
@EventData,
DB_NAME(),
@EventData.value('(/EVENT_INSTANCE/SchemaName)[1]', 'NVARCHAR(255)'),
@EventData.value('(/EVENT_INSTANCE/ObjectName)[1]', 'NVARCHAR(255)'),
HOST_NAME(),
@ip,
PROGRAM_NAME(),
SUSER_SNAME();
END
【问题讨论】:
-
您可以使用基于具有所需权限的证书用户的证书对触发器进行签名。如果您将触发器 DDL 添加到您的问题,我将使用脚本添加答案。
-
抱歉,直到现在我才意识到模块签名只能使用 DML 触发器完成,而不能使用 DDL 触发器。如果我能找到解决方法,我会跟进。
-
仅供参考,我找到了部分解决方法(将实现移动到模式范围的 proc 并对其进行签名),但它要求数据库是可信的。如果 MS 提供了一种对数据库和服务器触发器进行签名的方法,这将变得容易得多。
-
@DanGuzman 你的意思是模式范围的触发器吗?或者你是在暗示触发器会调用一个签名的过程?
-
我的意思是 DDL 触发器调用签名的 proc。即使进行了签名,我也会收到错误消息“正在执行的模块不受信任。模块数据库的所有者需要被授予身份验证权限,或者模块需要进行数字签名。”除非数据库是可信的。
标签: triggers permissions sql-server-2017