Link to home
Start Free TrialLog in
Avatar of dbaSQL
dbaSQLFlag for United States of America

asked on

query the SQL SERVER Audit output

v2008R2, I recently implemented a SQL Server Audit, designed to monitor object changes, as well as server/database level setting changes.  It's been in place for about a week, and I like what I am seeing -- but, I am having a few problems reading the data.

The audit dumps the sqlaudit file to disk, and I upload it once daily to a table.  I then have a little reporting procedure which looks for the new audit events, and sends a summary email to me, briefly noting the changes.  All of the audit events are being captured correctly in the files, but my reporting procedure isn't returning them all to me.  Also, some of the events in the file are being loaded to the table in chunks, rather than in a single records.  For example, one record will have the first part of an alter or create statement, and the next record holds the rest of it.  (maybe my datalength is insufficient?)

The sql server audit is still fairly new to me, and I was hoping for some EE advice for how to properly reference the audit events - server and database separately -- and how to better filter, or manage the data, once i've loaded the sqlaudit file to my table, and am trying to report on the events.  Below I have pasted the piece that writes the file to a table, and the piece that I am using to read from it.


THIS IS THE PIECE THAT COLLECTS THE sqlaudit FILE AND LOADS TO TABLE
NOTE: My WHERE clauses are trying to separate server from database audit events.  I was also getting duplicates in my result-set, so they are geared to elimiate dupes.  Possibly not correct. You can see my case statement, this is to get the bulk out of the larger events, and just quickly reference the action and the object, rather than putting the whole create or alter statement in there.  It seems correct.
-----------------------------------------------------------------------------------------------------------
INSERT dbo.myTable (EventTime,AuditType,ActionID,ServerName,DatabaseName,SchemaName,ObjectName,ActionPerformed,UserName,AuditFile)
SELECT EventTime,AuditType,ActionID,ServerName,DatabaseName,SchemaName,ObjectName,ActionPerformed,UserName,AuditFile
FROM
(      
      -- Database Audit
      SELECT af.event_time [EventTime],aa.class_desc [AuditType],af.action_id [ActionID],af.server_instance_name [ServerName],af.database_name [DatabaseName],af.[schema_name] [SchemaName],af.[object_name] [ObjectName],af.[statement] [ActionPerformed],af.server_principal_name [UserName],af.[FILE_NAME] [AuditFile]
      FROM sys.fn_get_audit_file ('C:\Audit\SQLServer*.sqlaudit',NULL,NULL) af INNER JOIN sys.dm_audit_actions aa
        ON af.action_id = aa.action_id INNER JOIN sys.dm_audit_class_type_map ctm
            ON aa.class_desc = ctm.securable_class_desc
      WHERE af.[statement] <> ''
      AND aa.class_desc <> 'SERVER'
      AND af.database_name <> 'master'
      AND ctm.class_type_desc = 'DATABASE'
      AND af.action_id IN('AL','DR')
      AND af.[OBJECT_NAME] NOT IN ('dbo','')
      GROUP BY af.event_time,aa.class_desc,af.action_id,af.server_instance_name,af.database_name,af.[schema_name],af.[object_name],af.[statement],af.server_principal_name,af.[file_name]
            
UNION

      -- Server Audit
      SELECT af.event_time [EventTime],aa.class_desc [AuditType],af.action_id [ActionID],af.server_instance_name [ServerName],af.database_name [DatabaseName],af.[schema_name] [SchemaName],af.[object_name] [ObjectName],af.[statement] [ActionPerformed],af.server_principal_name [UserName],af.[FILE_NAME] [AuditFile]
      FROM sys.fn_get_audit_file ('C:\Audit\SQLServer*.sqlaudit',NULL,NULL) af INNER JOIN sys.dm_audit_actions aa
        ON af.action_id = aa.action_id INNER JOIN sys.dm_audit_class_type_map ctm
            ON aa.class_desc = ctm.securable_class_desc
      WHERE af.[statement] <> ''
      AND aa.class_desc <> 'DATABASE'
      AND ctm.class_type_desc = 'SERVER AUDIT'
      AND af.database_name = 'master'
      AND af.[OBJECT_NAME] NOT IN ('dbo','')
      GROUP BY af.event_time,aa.class_desc,af.action_id,af.server_instance_name,af.database_name,af.[schema_name],af.[object_name],af.[statement],af.server_principal_name,af.[file_name]
) x
WHERE
      x.EventTime > @MaxEventTime


THIS IS WHAT I USE TO CAPTURE NEW EVENTS AND EMAIL THEM
--------------------------------------------------------------------------------------------
DECLARE @dt DATETIME = CONVERT(VARCHAR(10),GETDATE(),101)
DECLARE @QueryOut NVARCHAR(MAX),
      @Header VARCHAR(1000),
      @List VARCHAR(1000),
      @Subject NVARCHAR(155) = (SELECT @@SERVERNAME + '  ' + '  Server Audit'),
                        @tableHTML NVARCHAR(MAX)

SELECT @QueryOut = CAST(
            (
            SELECT
            td = CONVERT(VARCHAR(16),DATEADD(minute, DATEDIFF(minute,GETUTCDATE(),GETDATE()),EventTime)),'',
                                    td = AuditType,'',
                                    td = ServerName,'',
                                    td = DatabaseName,'',
                                    td = SchemaName,'',
                                    td = ObjectName,'',
                                    td = CASE WHEN ActionPerformed LIKE 'CREATE TABLE%' THEN SUBSTRING(ActionPerformed,1,31)  
                                                  WHEN ActionPerformed LIKE '%CREATE PROCEDURE%' THEN SUBSTRING(ActionPerformed,1,50)
                                                  WHEN ActionPerformed LIKE 'CREATE LOGIN%' THEN SUBSTRING(ActionPerformed,1,27)
                                                  ELSE ActionPerformed END,'',
                                    td = UserName
                              FROM
                                    dbo.MyTable sa
                              WHERE
                                    sa.Time >= @dt            
                              FOR XML PATH('tr'), TYPE)
                              AS NVARCHAR(MAX))

                  SET @tableHTML =
                        N'<STYLE TYPE="text/css">' +
                        N'TD{font-family: Verdana; font-size: 8pt; color:Black;}' +
                        N'table {border-width:4px; border-style:outset; text-align:left; color:Black;}' +
                        N'th {border-width:1px; border-style:inset; font-size:16px; font-weight:bold; padding:5px 20px 5px 20px;color:Black;}' +
                        N'td {border-width:1px; border-style:inset; font-size:12px; white-space:nowrap; padding:3px 20px 3px 20px;color:DarkBlue;}' +
                        N'H3 {font-size:16px; white-space:nowrap; color:Black;}' +
                        N'</STYLE>' +
                        N'<table border="1">' +
                        N'<tr>' +
                        N'<th>EventTime</th>' +
                        N'<th>AuditType</th>' +
                        N'<th>Server</th>' +                  
                        N'<th>Database</th>' +
                        N'<th>Schema</th>' +
                        N'<th>Object</th>' +
                        N'<th>Action</th>' +
                        N'<th>ByWhom</th>' +
                        @QueryOut +
                        + N'</table>';

                        IF(@tableHTML IS NULL)
                        BEGIN
                              RETURN;
                        END
                        ELSE
                        BEGIN
                              EXEC msdb.dbo.sp_send_dbmail
                                @profile_name = 'Profile',
                                @recipients = 'email',
                                @subject = @Subject,
                                @body = @tableHTML,
                                @body_format = 'HTML' ;
                        END
Avatar of dbaSQL
dbaSQL
Flag of United States of America image

ASKER

Are there any SQL Server Audit Experts out there?
Avatar of dbaSQL

ASKER

Also, Is anybody familiar with Disabling/Enablilng the alerts?  Mine timeout when I attempt to do so.  They are fairly small -- only a few events being captured at the server level, and within each of the targeted databases.  I wanted to change the max_rollover_files, I attempted to alter, it never completed.  I attempted to disable, it timed out.

Any ideas?
Avatar of Aneesh
>Also, some of the events in the file are being loaded to the table in chunks, rather than in a single records.  For example, one record will have the first part of an alter or create statement, and the next record holds the rest of it.  (maybe my data length is insufficient?)

Can you paste a sample here
Avatar of dbaSQL

ASKER

well, i would have to genericize it.  i'm looking at one right now -- it is three records.  The statement captured in the 1st record begins with 'ALTER PROCEDURE' and ends with this:

       */    IF(@Venue IS NOT NULL AND @ProductCode IS NULL

The statement captured in the 2nd record begins with this, which is end of the statement above:

     )    OR(@Venue IS NOT NULL AND @FutMonth IS NULL)

And it ends with this:    

     END         /* Update acti

The 3rd statement value begins with this, which is the end of the above statment:    

     e price to deactive, if exists. */






i just figured it out, aneesh.  
select len(actionperformed) from myTable where auditid in(4310,4311,4312)

those 3 id's are the identifiers for the three records I was describing just now.  LEN of the first one is 4000, the 2nd one is 4000 and the third one is 907.

My datalength is insufficient.

Do you have any ideas on the actual filters I am using, or the way I am targeting the server audit, vs the database audit?
Avatar of dbaSQL

ASKER

Or the timeouts when attempting to stop/disable the audit(s).  that is troubling me.
Avatar of dbaSQL

ASKER

odd.  now they disable just fine.  i haven't been able to do it for a couple of days without a timeout.  hmmm...
ASKER CERTIFIED SOLUTION
Avatar of Aneesh
Aneesh
Flag of Canada image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of dbaSQL

ASKER

well, thank you for looking this way, aneesh.  hopefully somebody else will take a look, too.
Avatar of dbaSQL

ASKER

I will close this now, Aneesh. Please excuse the delay, and thank you for looking.