当更改安全的所有权时,我需要执行一些审计,例如
ALTER AUTHORIZATION ON SCHEMA::[SchemaName] TO [PrincipalName];发生在数据库中。
数据库范围DDL-触发器似乎是实现此目的的合适机制。在文档 (具有服务器或数据库作用域的DDL语句节)中,我看到应该有ALTER_AUTHORIZATION事件。
但是,当我试图创建适当的DDL触发器时
CREATE TRIGGER [OnAlterAuthorization] ON DATABASE
FOR ALTER_AUTHORIZATION
AS
BEGIN
PRINT 'Perform audit';
END我得到了错误Msg 1084
Msg 1084、级别15、状态1、过程OnAlterAuthorization、第2行批处理起始线%0 'ALTER_AUTHORIZATION‘是无效的事件类型。
在sys.event_notification_event_types中
SELECT type_name
FROM sys.event_notification_event_types
WHERE type_name LIKE 'ALTER_AUTHOR%';没有ALTER_AUTHORIZATION事件,只是
type_name
-----------------------------
ALTER_AUTHORIZATION_SERVER
ALTER_AUTHORIZATION_DATABASE其中ALTER_AUTHORIZATION_SERVER显然不适合,而ALTER_AUTHORIZATION_DATABASE则根据文档
当指定ON数据库时,应用于ALTER授权语句
所以问题是。ALTER_AUTHORIZATION在文档中的承诺在哪里?如何捕捉数据库中安全所有权的更改?
发布于 2017-03-28 09:55:19
我发现,尽管发生了这种情况,但根据文档,ALTER_AUTHORIZATION_DATABASE被声明为
当指定ON数据库时,应用于ALTER授权语句
它不仅在数据库所有者更改时触发,而且在数据库中安全更改的所有者时也会触发。
换句话说,DDL-触发器
CREATE TRIGGER [OnAlterAuthorization] ON DATABASE
FOR ALTER_AUTHORIZATION_DATABASE
AS
BEGIN
PRINT 'Check ownership';
END不仅是为了
ALTER AUTHORIZATION ON DATABASE::[DbName] TO [PrincipalName];但是,例如
ALTER AUTHORIZATION ON SCHEMA::[SchemaName] TO [PrincipalName];或
ALTER AUTHORIZATION ON ROLE::[RoleName] TO [PrincipalName];也是。
发布于 2017-03-24 20:04:51
我遇到了和你一样的问题。接下来,我会发现事件通知可以用来处理AUDIT_CHANGE_DATABASE_OWNER事件。(请注意,此事件不能与DDL触发器一起使用。)我写了一篇事件通知博客文章,恰好以AUDIT_CHANGE_DATABASE_OWNER事件为例:服务器事件处理:事件通知
下面是一个脚本,可以让您开始。
USE SomeDatabase
GO
--Create a queue just for change db owner events.
CREATE QUEUE queChangeDBOwnerNotification
--Create a service just for change db owner events.
CREATE SERVICE svcChangeDBOwnerNotification
ON QUEUE queChangeDBOwnerNotification ([http://schemas.microsoft.com/SQL/Notifications/PostEventNotification])
-- Create the event notification for change db owner events on the service.
CREATE EVENT NOTIFICATION enChangeDBOwner
ON SERVER
WITH FAN_IN
FOR AUDIT_CHANGE_DATABASE_OWNER
TO SERVICE 'svcChangeDBOwnerNotification', 'current database';
GO
CREATE PROCEDURE dbo.ReceiveChangeDBOwner
AS
BEGIN
SET NOCOUNT ON
DECLARE @MsgBody XML
WHILE (1 = 1)
BEGIN
BEGIN TRANSACTION
-- Receive the next available message FROM the queue
WAITFOR (
RECEIVE TOP(1) -- just handle one message at a time
@MsgBody = CAST(message_body AS XML)
FROM queChangeDBOwnerNotification
), TIMEOUT 1000 -- if the queue is empty for one second, give UPDATE and go away
-- If we didn't get anything, bail out
IF (@@ROWCOUNT = 0)
BEGIN
ROLLBACK TRANSACTION
BREAK
END
ELSE
BEGIN
--Interrogate the event data for relevant properties/values.
DECLARE @Cmd VARCHAR(1024)
DECLARE @MailBody NVARCHAR(MAX)
DECLARE @Subject NVARCHAR(255)
SET @Cmd = @MsgBody.value('(/EVENT_INSTANCE/TextData)[1]', 'VARCHAR(1024)')
SET @Subject = @@SERVERNAME + ' -- ' + @MsgBody.value('(/EVENT_INSTANCE/EventType)[1]', 'VARCHAR(128)' )
--Build an html table for use with an html-formatted email message.
SET @MailBody =
'<table border="1">' +
'<tr><td>Server Name</td><td>' + @MsgBody.value('(/EVENT_INSTANCE/ServerName)[1]', 'VARCHAR(128)' ) + '</td></tr>' +
'<tr><td>Start Time</td><td>' + @MsgBody.value('(/EVENT_INSTANCE/StartTime)[1]', 'VARCHAR(128)' ) + '</td></tr>' +
'<tr><td>Session Login Name</td><td>' + @MsgBody.value('(/EVENT_INSTANCE/SessionLoginName)[1]', 'VARCHAR(128)' ) + '</td></tr>' +
'<tr><td>Login Name</td><td>' + @MsgBody.value('(/EVENT_INSTANCE/LoginName)[1]', 'VARCHAR(128)') + '</td></tr>' +
'<tr><td>Windows Domain\User Name</td><td>' + @MsgBody.value('(/EVENT_INSTANCE/NTDomainName)[1]', 'VARCHAR(256)') + '\' +
@MsgBody.value('(/EVENT_INSTANCE/NTUserName)[1]', 'VARCHAR(256)') + '</td></tr>' +
'<tr><td>DB User Name</td><td>' + @MsgBody.value('(/EVENT_INSTANCE/DBUserName)[1]', 'VARCHAR(128)' ) + '</td></tr>' +
'<tr><td>Host Name</td><td>' + @MsgBody.value('(/EVENT_INSTANCE/HostName)[1]', 'VARCHAR(128)' ) + '</td></tr>' +
'<tr><td>Application Name</td><td>' + @MsgBody.value('(/EVENT_INSTANCE/ApplicationName)[1]', 'VARCHAR(128)' ) + '</td></tr>' +
'<tr><td>Command Succeeded</td><td>' + @MsgBody.value('(/EVENT_INSTANCE/Success)[1]', 'VARCHAR(8)' ) + '</td></tr>' +
'</table><br/>' +
'<p><b>Text Data:</b><br/>' + REPLACE(@Cmd, CHAR(13) + CHAR(10), '<br/>') +'</p><br/>'
--PRINT @Subject
--PRINT @MailBody
--Note: you may need to set [msdb] to trustworthy for this to work.
--Another option is to sign a stored proc with a certificate.
--See: https://learn.microsoft.com/en-us/sql/relational-databases/tutorial-signing-stored-procedures-with-a-certificate
EXEC msdb.dbo.sp_send_dbmail
@recipients = 'You@YourDomain.com',
@subject = @Subject,
@body = @MailBody,
@body_format = 'HTML',
@exclude_query_output = 1
/*
Commit the transaction. At any point before this, we
could roll back -- the received message would be back
on the queue AND the response wouldn't be sent.
*/
COMMIT TRANSACTION
END
END
END
GO
ALTER QUEUE dbo.queChangeDBOwnerNotification
WITH
STATUS = ON,
ACTIVATION (
PROCEDURE_NAME = dbo.ReceiveChangeDBOwner,
STATUS = ON,
MAX_QUEUE_READERS = 1,
EXECUTE AS OWNER)
GOhttps://dba.stackexchange.com/questions/168102
复制相似问题