首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用于ALTER_AUTHORIZATION的DDL触发器

用于ALTER_AUTHORIZATION的DDL触发器
EN

Database Administration用户
提问于 2017-03-24 15:28:49
回答 2查看 567关注 0票数 1

当更改安全的所有权时,我需要执行一些审计,例如

代码语言:javascript
复制
ALTER AUTHORIZATION ON SCHEMA::[SchemaName] TO [PrincipalName];

发生在数据库中。

数据库范围DDL-触发器似乎是实现此目的的合适机制。在文档 (具有服务器或数据库作用域的DDL语句节)中,我看到应该有ALTER_AUTHORIZATION事件。

但是,当我试图创建适当的DDL触发器时

代码语言:javascript
复制
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

代码语言:javascript
复制
SELECT type_name
FROM sys.event_notification_event_types
WHERE type_name LIKE 'ALTER_AUTHOR%';

没有ALTER_AUTHORIZATION事件,只是

代码语言:javascript
复制
type_name
-----------------------------
ALTER_AUTHORIZATION_SERVER
ALTER_AUTHORIZATION_DATABASE

其中ALTER_AUTHORIZATION_SERVER显然不适合,而ALTER_AUTHORIZATION_DATABASE则根据文档

当指定ON数据库时,应用于ALTER授权语句

所以问题是。ALTER_AUTHORIZATION在文档中的承诺在哪里?如何捕捉数据库中安全所有权的更改?

EN

回答 2

Database Administration用户

回答已采纳

发布于 2017-03-28 09:55:19

我发现,尽管发生了这种情况,但根据文档,ALTER_AUTHORIZATION_DATABASE被声明为

当指定ON数据库时,应用于ALTER授权语句

它不仅在数据库所有者更改时触发,而且在数据库中安全更改的所有者时也会触发。

换句话说,DDL-触发器

代码语言:javascript
复制
CREATE TRIGGER [OnAlterAuthorization] ON DATABASE
FOR ALTER_AUTHORIZATION_DATABASE
AS
BEGIN
    PRINT 'Check ownership';
END

不仅是为了

代码语言:javascript
复制
ALTER AUTHORIZATION ON DATABASE::[DbName] TO [PrincipalName];

但是,例如

代码语言:javascript
复制
ALTER AUTHORIZATION ON SCHEMA::[SchemaName] TO [PrincipalName];

代码语言:javascript
复制
ALTER AUTHORIZATION ON ROLE::[RoleName] TO [PrincipalName];

也是。

票数 0
EN

Database Administration用户

发布于 2017-03-24 20:04:51

我遇到了和你一样的问题。接下来,我会发现事件通知可以用来处理AUDIT_CHANGE_DATABASE_OWNER事件。(请注意,此事件不能与DDL触发器一起使用。)我写了一篇事件通知博客文章,恰好以AUDIT_CHANGE_DATABASE_OWNER事件为例:服务器事件处理:事件通知

下面是一个脚本,可以让您开始。

代码语言:javascript
复制
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) 
GO
票数 1
EN
页面原文内容由Database Administration提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://dba.stackexchange.com/questions/168102

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档