L’auditing dei dati rappresenta l’insieme delle attività mirate ad accertare la validità e l’affidabilità di un’informazione.
I meccanismi di auditing vengono utilizzati per tenere traccia di tutti gli eventi che riguardano la sicurezza del sistema database. SQL Server Profiler è un tool che permette di monitorare gli eventi del database engine, si basa sull’impostazione di tracce (o filtri di traccia). Una traccia (o filtro di traccia) è un set di eventi memorizzati di cui occorre creare un profilo.
SQL Server adotta un’architettura di sicurezza basata su tre differenti livelli di protezione:
– Autenticazione: l’utilizzo delle risorse di un database deve essere subordinato alla preventiva autenticazione degli utenti che avviene attraverso la fornitura di una password
– Autorizzazione: i permessi assegnati agli utenti regolano il diritto di accedere (o meno) ai vari oggetti del database (tabelle, viste, stored procedure, ecc…)
– Auditing: la fase di auditing è caratterizzata dalla scelta dei mezzi più idonei per:
o Identificare e riconoscere possibili abusi
o Assicurare l’integrità delle informazioni
o Mantenere (comunque) alto il livello delle prestazioni
Scenario
Lavorate come database administrator per la vostra organizzazione. Gli utenti dell’ufficio commerciale vi segnalano periodicamente delle situazioni anomale su alcuni dati memorizzati nel sistema informativo. In particolare lamentano prezzi di listino errati per i prodotti commerciali di largo consumo e la cancellazione di alcuni articoli obsoleti non movimentati nell’ultimo esercizio fiscale. Dopo aver aggiornato i prezzi errati, l’anomalia di ripresenta nuovamente ad una distanza di tempo ravvicinata. Il responsabile commerciale non si spiega il motivo di tali variazioni non autorizzate.
Sospettate un bug nella procedura di aggiornamento prezzi oppure un accesso non autorizzato alla tabella prodotti con conseguente aggiornamento abusivo del prezzo di listino e la cancellazione di alcuni articoli.
Il responsabile commerciale desidera conoscere la natura di tali aggiornamenti errati o abusivi con il dettaglio del tipo di evento che ha avuto luogo, le informazioni di connessione ed il testo del comando SQL eseguito. Desidera inoltre essere informato tempestivamente, con un messaggio di posta elettronica, al verificarsi un aggiornamento del prezzo di listino.
Soluzione
Con SQL Server 2008 il supporto all’auditing è nativo grazie al comando "CREATE AUDIT", con SQL Server 2000 o 2005 dobbiamo invece farci una soluzione custom. Una possibile soluzione è rappresentata dall’implementazione di tracce SQL per monitorare l’utilizzo delle autorizzazioni (UPDATE, DELETE, ecc…) sull’anagrafica prodotti, oltre alla realizzazione di un trigger per il monitoraggio degli aggiornamenti eseguiti sul prezzo di listino.
L’utilizzo delle traccie è necessario perchè non sono intrusive come i trigger ed inoltre rappresentano l’unico modo per poter effettuare l’audit anche del comando "TRUNCATE TABLE" che altrimenti non potrebbe mai essere intercettato in quanto non scatena nessun trigger.
La soluzione è stata implementata sul database AdventureWorks ipotizzando che fosse il database del sistema informativo utilizzato nella nostra organizzazione. L’anagrafica prodotti è rappresentata dalla tabella Production.Product.
Oggetti implementati per la soluzione di auditing
Tabelle
– AUDITINGVALUE
– AUDITING
– AUDITINGMAIL
Stored Procedure
– USP_TRACE_AUDIT_CREATE
– USP_TRACE_GETTABLE_IMPORT_FILE
– USP_AUDIT_MAIL
– USP_AUDIT_INS_DATA
Trigger
– TRIU_PRODUCTION_PRODUCT_AUDIT
Iniziamo con la creazione delle tabelle di auditing sul database AdventureWorks.
USE AdventureWorks
GO
/*
AUDITING
Setup tabelle:
– AUDITINGVALUE
– AUDITING
– AUDITINGMAIL
*/
— Drop table dbo.AUDITINGVALUE
IF (ISNULL(OBJECT_ID(‘AUDITINGVALUE’), 0) > 0)
DROP TABLE [dbo].[AUDITINGVALUE]
GO
— Create table dbo.AUDITINGVALUE
CREATE TABLE [dbo].[AUDITINGVALUE]
(ID INT IDENTITY(1, 1) NOT NULL,
RowID INT NOT NULL,
SPID INT NOT NULL,
fOldValue NVARCHAR(128),
fNewValue NVARCHAR(128)
PRIMARY KEY(ID)
) ON [PRIMARY]
— Drop table dbo.AUDITING
IF (ISNULL(OBJECT_ID(‘AUDITING’), 0) > 0)
DROP TABLE [dbo].[AUDITING]
GO
— Create table dbo.AUDITING
CREATE TABLE [dbo].[AUDITING]
(ID int IDENTITY (1, 1) NOT NULL,
RowID int NULL,
EventClass int NULL,
TextData nvarchar(2000) NULL,
DatabaseID int NULL,
NTUserName nvarchar(128) NULL,
NTDomainName nvarchar(128) NULL,
HostName nvarchar(128) NULL,
ClientProcessID int NULL,
ApplicationName nvarchar(128) NULL,
LoginName nvarchar(128) NULL,
SPID int NULL,
Duration bigint NULL,
StartTime datetime NULL,
ObjectID int NULL,
ObjectName nvarchar(128) NULL,
DatabaseName nvarchar(128) NULL,
DBUserName nvarchar(128) NULL,
Login_Time datetime NULL,
OldValue nvarchar(128) NULL,
NewValue nvarchar(128) NULL,
FieldName nvarchar(128) NULL
)
ON [PRIMARY]
GO
— Creazione indice cluster sul campo dbo.AUDITING.StartTime
CREATE CLUSTERED INDEX [IDX__AUDITING_StartTime] ON [DBO].[AUDITING]
([StartTime] DESC) ON [PRIMARY]
GO
— Creazione indice non-cluster sul campo dbo.AUDITING.ID
CREATE NONCLUSTERED INDEX [IDX__AUDITING_ID] ON [DBO].[AUDITING]
([ID] ASC) ON [PRIMARY]
GO
— Creazione della chiave primaria tabella dbo.AUDITING
ALTER TABLE [dbo].[AUDITING] ADD CONSTRAINT PK__AUDITING_ID PRIMARY KEY(ID)
— Drop table dbo.AUDITINGMAIL
IF (ISNULL(OBJECT_ID(‘AUDITINGMAIL’), 0) > 0)
DROP TABLE [dbo].[AUDITINGMAIL]
GO
— Create table dbo.AUDITINGMAIL
CREATE TABLE [dbo].[AUDITINGMAIL]
(ID INT IDENTITY (1, 1) NOT NULL,
MailRecipients NVARCHAR(512),
MailMessage NVARCHAR(1024),
MailCopy_Recipients NVARCHAR(512),
MailSubject NVARCHAR(80),
MailError INT DEFAULT 0 NOT NULL
PRIMARY KEY (ID)
) ON [PRIMARY]
Procediamo con la creazione delle stored procedure sul database AdventureWorks.
USE AdventureWorks
GO
/*
AUDITING
Setup Stored Procedure:
– USP_TRACE_AUDIT_CREATE
– USP_TRACE_GETTABLE_IMPORT_FILE
– USP_AUDIT_MAIL
– USP_AUDIT_INS_DATA
*/
— Drop procedure dbo.USP_TRACE_AUDIT_CREATE
IF (OBJECT_ID(‘USP_TRACE_AUDIT_CREATE’) IS NOT NULL)
DROP PROCEDURE [dbo].[USP_TRACE_AUDIT_CREATE]
GO
END
GO
— Drop procedure dbo.USP_TRACE_GETTABLE_IMPORT_FILE
IF (OBJECT_ID(‘USP_TRACE_GETTABLE_IMPORT_FILE’) IS NOT NULL)
DROP PROCEDURE [DBO].[USP_TRACE_GETTABLE_IMPORT_FILE]
GO
— Create procedure dbo.USP_TRACE_GETTABLE_IMPORT_FILE
CREATE PROCEDURE dbo.USP_TRACE_GETTABLE_IMPORT_FILE(@sTraceFile varchar(4000))
AS
BEGIN
/*
Descrizione:
Implementa la logica d’importazione dei file di traccia (.trc)
nella tabella dbo.AUDITING
Parametri:
@sTraceFile = Nome del file di traccia iniziale
*/
DECLARE
@nTraceFiles int,
@sSQL varchar(8000),
@bIsRunning smallint,
@sPath varchar(255),
@sFirstFile varchar(255),
@sLastFile varchar(255),
@sFileName varchar(255)
IF (RIGHT(@sTraceFile, 1) <> ‘\’)
SET @sTraceFile = @sTraceFile + ‘\’
— Determinazione dei files da importare ordinati
— per data + nome file senza informazioni di dettaglio
EXEC master..xp_sprintf @sSQL OUTPUT, ‘DIR "%s*.trc" /ODN /B’, @sTraceFile
— Debug
–PRINT @sSQL
— Impostazione directory di path
SELECT @sPath = SUBSTRING(@sTraceFile, 1, DATALENGTH(@sTraceFile) – CHARINDEX(‘\’,REVERSE(@sTraceFile))) + ‘\’
— Debug
–PRINT @sPath
SELECT @sFileName = RIGHT(@sTraceFile,CHARINDEX(‘\’,REVERSE(@sTraceFile))-1)
— Debug
–PRINT @sFileName
IF EXISTS(SELECT * FROM tempdb..sysobjects
WHERE ID = OBJECT_ID(‘tempdb..#tmpFiles’))
DROP TABLE #tmpFiles
CREATE TABLE #tmpFiles(f_id int IDENTITY,
[filename] varchar(255))
INSERT #tmpFiles
EXEC master..xp_cmdshell @sSQL
— Determino il numero totale dei files
SELECT @nTraceFiles = COUNT(*)
FROM #tmpFiles
WHERE [filename] LIKE @sFileName + ‘%’
— Debug
–PRINT @nTraceFiles
— Determino il primo file
SELECT @sFirstFile = @sPath +
(SELECT [filename]
FROM #tmpFiles
INNER JOIN (SELECT MIN(f_id) AS f_id
FROM #tmpFiles
WHERE [filename] LIKE @sFileName + ‘%’) [first] ON #tmpFiles.f_id = [first].f_id)
— Debug
–PRINT @sFirstFile
— Determino l’ultimo file
SELECT @sLastFile = @sPath +
(SELECT [filename]
FROM #tmpFiles
INNER JOIN (SELECT MAX(f_id) AS f_id
FROM #tmpFiles
WHERE [filename] LIKE @sFileName + ‘%’) [first] ON #tmpFiles.f_id = [first].f_id)
— Debug
–PRINT @sLastFile
— La traccia è in esecuzione ?
— Se è in esecuzione non importo l’ultimo file
IF EXISTS(SELECT * FROM ::fn_trace_getinfo(default)
WHERE property = 2
AND ((value = @sLastFile) OR
(CAST(value AS varchar(4000)) = @sTraceFile))
)
SELECT @bIsRunning = 1
ELSE
SELECT @bIsRunning = 0
— Importazione
SELECT @nTraceFiles = @nTraceFiles – @bIsRunning — Sottraggo 1 se la traccia è in esecuzione
IF (@nTraceFiles > 0)
BEGIN
INSERT INTO [dbo].[AUDITING]
(EventClass,
TextData,
DatabaseID,
NTUserName,
NTDomainName,
HostName,
ClientProcessID,
ApplicationName,
LoginName,
SPID,
Duration,
StartTime,
ObjectID,
ObjectName,
DatabaseName,
DBUserName)
SELECT
T.EventClass,
REPLACE(CAST(T.TextData AS NVARCHAR(2000)), CHAR(13) + CHAR(10), ”),
T.DatabaseID,
T.NTUserName,
T.NTDomainName,
T.HostName,
T.ClientProcessID,
T.ApplicationName,
T.LoginName,
T.SPID,
T.Duration,
T.StartTime,
T.ObjectID,
T.ObjectName,
T.DatabaseName,
T.DBUserName
FROM ::fn_trace_gettable(@sFirstFile, @nTraceFiles) AS T
IF (@@ERROR = 0)
BEGIN
— Cancellazione files importati
DECLARE curFiles CURSOR READ_ONLY FOR
SELECT [filename]
FROM #tmpFiles
WHERE ([filename] LIKE @sFileName + ‘%’)
AND (f_id <= @nTraceFiles)
OPEN curFiles
FETCH NEXT FROM curFiles INTO @sFileName
WHILE (@@fetch_status <> –1)
BEGIN
IF (@@fetch_status <> –2)
BEGIN
— EXEC master..xp_fileexist
EXEC master..xp_sprintf @sSQL OUTPUT, ‘DEL /Q "%s%s"’, @sPath, @sFileName
EXEC master..xp_cmdshell @sSQL
END
FETCH NEXT FROM curFiles INTO @sFileName
END
CLOSE curFiles
DEALLOCATE curFiles
END
END
DROP TABLE #tmpFiles
END
— Drop procedure dbo.USP_AUDIT_MAIL
IF (OBJECT_ID(‘USP_AUDIT_MAIL’) IS NOT NULL)
DROP PROCEDURE dbo.USP_AUDIT_MAIL
GO
— Drop procedure dbo.USP_AUDIT_MAIL
CREATE PROCEDURE dbo.USP_AUDIT_MAIL
AS BEGIN
/*
Descrizione:
Implementa la logica di invio delle email di notifica
*/
DECLARE @RowNumber INT,
@MailRecipients NVARCHAR(512),
@MailMessage NVARCHAR(1024),
@MailCopy_Recipients NVARCHAR(512),
@MailSubject NVARCHAR(80)
EXEC master..xp_startmail
IF (@@ERROR = 0)
BEGIN
WHILE (SELECT ISNULL(MIN(ID), 0) FROM AUDITINGMAIL) > 0
BEGIN
SELECT @MailRecipients = MailRecipients,
@MailMessage = MailMessage,
@MailCopy_Recipients = MailCopy_Recipients,
@MailSubject = MailSubject,
@RowNumber = ID
FROM AUDITINGMAIL
WHERE (ID = (SELECT MIN(ID) FROM AUDITINGMAIL))
— Send email
EXEC master..xp_sendmail @Recipients = @MailRecipients,
@Message = @MailMessage,
@Copy_Recipients = @MailCopy_Recipients,
@Subject = @MailSubject
IF (@@ERROR = 0)
BEGIN
DELETE FROM AUDITINGMAIL WHERE (ID = @RowNumber)
END
ELSE BEGIN
UPDATE AUDITINGMAIL SET MailError = –1 WHERE (ID = @RowNumber)
END
END
END
EXEC master..xp_stopmail
END
GO
— Drop procedure dbo.USP_AUDIT_INS_DATA
IF (OBJECT_ID(‘USP_AUDIT_INS_DATA’) IS NOT NULL)
DROP PROCEDURE dbo.USP_AUDIT_INS_DATA
GO
— Create procedure dbo.USP_AUDIT_INS_DATA
CREATE PROCEDURE dbo.USP_AUDIT_INS_DATA
(@TextData NVARCHAR(2000),
@ObjectName NVARCHAR(128),
@FieldName NVARCHAR(128),
@SPID INT,
@SendMail INT,
@MailRecipients NVARCHAR(512),
@MailMessage NVARCHAR(1024),
@MailCopy_Recipients NVARCHAR(512),
@MailSubject NVARCHAR(80)
)
AS BEGIN
/*
Descrizione:
Implementa la logica d’inserimento dei dati di
auditing nella tabella AUDITING. La stored procedure
viene richiamata dai trigger
Parametri:
@TextData: Query text – Testo del comando SQL
@ObjectName: Object name – Nome oggetto/tabella
@FieldName: Field name – Nome del campo che ha subito l’aggiornamento
@SPID: Server process identifier (ID)
@SendMail: Enable or disable send mail
services for this alarm – Flag invio email
@MailRecipients: Is the semicolon-separated list
of the recipients of the mail – Destinarati email
@MailMessage: Is the message to be sent – Corpo del messaggio email
@MailCopy_Recipients: Is the semicolon-separated list
identifying the recipients of a copy of the mail (cc:’ing) –
Destinatari in copia/conoscenza
@MailSubject: Is an optional parameter specifying the subject of the mail.
If subject is not specified, SQL Server Message is the default –
Oggetto messaggio email
*/
SET NOCOUNT ON
DECLARE @EventClass INT,
@DatabaseID INT,
@NTUserName NVARCHAR(128),
@NTDomainName NVARCHAR(128),
@HostName NVARCHAR(128),
@ClientProcessID INT,
@ApplicationName NVARCHAR(128),
@LoginName NVARCHAR(128),
@Duration BIGINT,
@StartTime DATETIME,
@ObjectID INT,
@DatabaseName NVARCHAR(128),
@DBUserName NVARCHAR(128),
@Login_Time DATETIME
SET @EventClass = 0
SET @DatabaseID = (SELECT dbid FROM master.dbo.sysprocesses WHERE spid=@SPID)
SET @NTUserName = (SELECT CASE WHEN (LTRIM(RTRIM(nt_username))=”) THEN NULL ELSE nt_username END FROM master.dbo.sysprocesses WHERE spid=@SPID)
SET @NTDomainName = (SELECT CASE WHEN (LTRIM(RTRIM(nt_domain))=”) THEN NULL ELSE nt_domain END FROM master.dbo.sysprocesses WHERE spid=@SPID)
SET @HostName = (SELECT CASE WHEN (LTRIM(RTRIM(hostname))=”) THEN NULL ELSE hostname END FROM master.dbo.sysprocesses WHERE spid=@SPID)
SET @ClientProcessID = 0
SET @ApplicationName = (SELECT CASE WHEN (LTRIM(RTRIM(program_name))=”) THEN NULL ELSE program_name END FROM master.dbo.sysprocesses WHERE spid=@SPID)
SET @LoginName = (SELECT CASE WHEN (LTRIM(RTRIM(loginame))=”) THEN NULL ELSE loginame END FROM master.dbo.sysprocesses WHERE spid=@SPID)
SET @Duration = 0
SET @StartTime = GETDATE()
SET @ObjectID = OBJECT_ID(@ObjectName)
SET @DatabaseName = LTRIM(RTRIM(DB_NAME(@DatabaseID)))
SET @DBUserName = NULL
SET @Login_Time = (SELECT login_time FROM master.dbo.sysprocesses WHERE spid=@SPID)
INSERT INTO [dbo].[AUDITING]
(EventClass,
TextData,
DatabaseID,
NTUserName,
NTDomainName,
HostName,
ClientProcessID,
ApplicationName,
LoginName,
SPID,
Duration,
StartTime,
ObjectID,
ObjectName,
DatabaseName,
DBUserName,
Login_Time,
FieldName,
OldValue,
NewValue,
RowID)
SELECT
@EventClass,
LTRIM(RTRIM(@TextData)),
@DatabaseID,
LTRIM(RTRIM(@NTUserName)),
LTRIM(RTRIM(@NTDomainName)),
LTRIM(RTRIM(@HostName)),
@ClientProcessID,
LTRIM(RTRIM(@ApplicationName)),
LTRIM(RTRIM(@LoginName)),
@SPID,
@Duration,
@StartTime,
@ObjectID,
LTRIM(RTRIM(@ObjectName)),
LTRIM(RTRIM(@DatabaseName)),
LTRIM(RTRIM(@DBUserName)),
LTRIM(RTRIM(@Login_Time)),
LTRIM(RTRIM(@FieldName)),
LTRIM(RTRIM(ATV.fOldValue)),
LTRIM(RTRIM(ATV.fNewValue)),
ATV.RowID
FROM [dbo].[AUDITINGVALUE] ATV
WHERE (ATV.SPID = @SPID)
IF (@SendMail = –1)
BEGIN
INSERT INTO [dbo].[AUDITINGMAIL]
(MailRecipients,
MailMessage,
MailCopy_Recipients,
MailSubject,
MailError)
SELECT
@MailRecipients,
(@MailMessage +
‘ UserName: ‘ + RTRIM(LTRIM(ISNULL(@NTUserName, ”))) +
‘, HostName: ‘ + RTRIM(LTRIM(ISNULL(@HostName, ”))) +
‘, RowID: ‘ + RTRIM(LTRIM(STR(ISNULL(ATV.RowID, 0)))) +
‘, ObjectID: ‘ + LTRIM(RTRIM(ISNULL(@ObjectID, 0))) +
‘, ObjectName: ‘ + LTRIM(RTRIM(ISNULL(@ObjectName, ”))) +
‘, FieldName: ‘ + LTRIM(RTRIM(ISNULL(@FieldName, ”))) +
‘, StartTime: ‘ + ISNULL(CONVERT(VarChar, @StartTime, 113), ”) +
‘, OldValue: ‘ + LTRIM(RTRIM(ISNULL(ATV.fOldValue, ”))) +
‘, NewValue: ‘ + LTRIM(RTRIM(ISNULL(ATV.fNewValue, ”)))
),
@MailCopy_Recipients,
@MailSubject,
0
FROM [dbo].[AUDITINGVALUE] ATV
WHERE (ATV.SPID = @SPID)
END
SET NOCOUNT OFF
END
Procediamo con la creazione del trigger Production.TRIU_PRODUCTION_PRODUCT_AUDIT sulla tabella Production.Product. Il trigger implementa un meccanismo di auditing sul campo ListPrice. Ogni aggiornamento del campo ListPrice viene registrato sulla tabella AUDITING attraverso la stored procedure USP_AUDIT_INS_DATA.
USE AdventureWorks
GO
— Drop trigger Production.TRIU_PRODUCTION_PRODUCT_AUDIT
IF (OBJECT_ID(‘Production.TRIU_PRODUCTION_PRODUCT_AUDIT’) IS NOT NULL)
DROP TRIGGER Production.TRIU_PRODUCTION_PRODUCT_AUDIT
GO
— Create trigger Production.TRIU_PRODUCTION_PRODUCT_AUDIT
CREATE TRIGGER TRIU_PRODUCTION_PRODUCT_AUDIT ON Production.Product
FOR UPDATE AS
BEGIN
DECLARE
@TextData NVARCHAR(2000),
@ParentObj INT,
@ObjectName NVARCHAR(128)
— ListPrice
IF UPDATE(ListPrice)
BEGIN
— Comando SQL
CREATE TABLE #TraceInfo
(EventType NVARCHAR(30),
Parameters INTEGER,
EventInfo NVARCHAR(2000))
INSERT INTO #TraceInfo EXEC(‘DBCC INPUTBUFFER(@@SPID) WITH NO_INFOMSGS’)
SET @TextData = (SELECT Eventinfo FROM #TraceInfo)
— Inserimento valori modificati fOldValue, FNewValue
INSERT INTO [dbo].[AUDITINGVALUE]
(RowID, SPID, fOldValue, fNewValue)
SELECT
d.ProductID,
@@SPID,
LTRIM(RTRIM(CAST(ISNULL(d.ListPrice, ”) AS NVARCHAR(128)))),
LTRIM(RTRIM(CAST(ISNULL(i.ListPrice, ”) AS NVARCHAR(128))))
FROM Inserted i
INNER JOIN Deleted d On d.ProductID=i.ProductID
WHERE (ISNULL(d.ListPrice, 0) <> ISNULL(i.ListPrice, 0))
SELECT @ParentObj = Parent_Obj FROM dbo.sysobjects WHERE (ID = @@PROCID)
SELECT @ObjectName = OBJECT_NAME(@ParentObj)
EXEC dbo.USP_AUDIT_INS_DATA
@TextData,
@ObjectName,
‘ListPrice’,
@@SPID,
— @SendMail
–1,
— @MailRecipients
‘manager@sales.it’,
— @MailMessage
‘Il campo ListPrice della tabella Production.Product è stato modificato.’,
— @MailCopy_Recipients
‘manager@sales.it’,
— @MailSubject
‘SQL Server Message: Notifica di aggiornamento campo’
IF (@@ERROR = 0)
DELETE FROM [dbo].[AUDITINGVALUE] WHERE SPID = @@SPID
END
END
Per tracciare gli accessi alla tabella prodotti si è scelto di monitorare l’evento 114 Audit Schema Object Access Event generato quando si utilizza un’autorizzazione per gli oggetti (ad esempio SELECT) con esito sia positivo che negativo. Abbiamo applicato i filtri per database e per entità: tabella Product del database AdventureWorks.
Il file di traccia audit_trace_file.trc verrà generato nella directory C:\audit_trace\ ed avrà una dimensione massima di 10 MB, raggiunta la quale SQL Server provvederà alla generazione di un nuovo file di traccia con come audit_trace_file_1.trc nella directory C:\audit_trace\ (opzione TRACE_FILE_ROLLOVER). Non è stata impostata una data/ora di arresto per l’esecuzione della traccia SQL Server.
Per creare ed avviare la traccia SQL utilizziamo la stored procedure USP_TRACE_AUDIT_CREATE:
DECLARE
@DataBaseID INT,
@FilePath NVARCHAR(128),
@StopTime DATETIME,
@maxfilesize BIGINT
SELECT @DataBaseID = dbid
FROM master..sysdatabases
WHERE (NAME = ‘AdventureWorks’)
SET @FilePath = ‘C:\audit_trace\audit_trace_file’
SET @StopTime = NULL
SET @maxfilesize = 10
EXEC USP_TRACE_AUDIT_CREATE @DataBaseID, @FilePath, @StopTime, @maxfilesize, ‘Product’
Per controllare l’effettiva generazione della traccia SQL e del relativo file con estensione TRC si potrà utilizzare la funzione ::fn_trace_getinfo(default) con il seguente comando di SELECT:
TraceID = 2 rappresenta l’ID della traccia SQL appena creata.
Il meccanismo di auditing è da questo momento attivo, eseguiamo ora alcuni comandi DML sull’anagrafica prodotti: eliminiamo il prodotto con ProductID = 1006 e modifichiamo il prezzo di listino del prodotto con ProductID = 2.
DELETE FROM Production.Product WHERE ProductId=1006
UPDATE Production.Product SET ListPrice = 14 where ProductId=2
Interrompiamo (close) la traccia SQL con TraceID = 2
— Close trace (status = 2)
DECLARE @RC int, @TraceID int
SET @TraceID = 2
EXEC @RC = sp_trace_setstatus @TraceID, 2
Terminiamo (stop) la traccia SQL con TraceID = 2
— Stop trace (status = 0)
DECLARE @RC int, @TraceID int
SET @TraceID = 2
EXEC @RC = sp_trace_setstatus @TraceID, 0
Importiamo, nella tabella AUDITING, gli eventi memorizzati nei file di traccia (non in esecuzione) contenuti nella cartella C:\Audit_Trace. Per questa attività utilizziamo la stored procedure USP_TRACE_GETTABLE_IMPORT_FILE:
Interrogando la tabella AUDITING possiamo determinare le informazioni richieste dal responsabile commerciale: la natura degli aggiornamenti eseguiti sull’anagrafica prodotti ed in particolare sul prezzo di listino, l’utente che ha eseguito tali aggiornamenti, l’applicazione utilizzata, la data e l’ora in cui è avvenuto l’aggiornamento, il prezzo di listino che aveva l’articolo prima dell’aggiornamento ed il prezzo di listino dopo l’aggiornamento. E’ stato possibile rilevare anche la cancellazione anagrafica di un prodotto.
La tabella AUDITINGMAIL contiene una riga per ogni notifica da inviare via posta elettronica ai destinatari indicati nei campi MailRecipients e MailCopy_Recipients. Per l’invio dei messaggi email è necessario configurare il servizio SQL Mail, successivamente si potrà utilizzare la stored procedure USP_AUDIT_MAIL.
Vediamo il contenuto della tabella AUDITINGMAIL:
Per l’invio delle email, dopo aver configurato SQL Mail sarà sufficiente eseguire
EXEC dbo.USP_AUDIT_MAIL
Questa soluzione si presta anche per eventuali altri scopi: modificando gli eventi monitorati dalla stored procedure USP_TRACE_AUDIT_CREATE sarà possibile ottenere informazioni dettagliate su:
– Eventi cursore
– Crescita o riduzione delle dimensioni del database
– Messaggi di errore e di avviso
– Blocchi acquisiti o rilasciati su oggetti SQL Server
– Eventi di accesso, come connessioni, disconnessioni e tentativi di accesso terminati con esito negativo
– Stato batch delle RPC
– Parallelismo di esecuzioni SQL
– Avvio e termine di una stored procedure
– Avvio e termine di un’istruzione SQL all’interno di una stored procedure
– Avvio e termine di un batch SQL
– Scansione di tabelle
– Istruzioni T-SQL (Select, Update, Insert ecc…)