Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Auditoria y Triggers
Auditoria y Triggers
Despues de pasar muchas horas pensando, debuggiando y buscandole la vuelta a una solucion que
consistia en hacerle una auditoria a una base de datos SQL 2005, pudimos desarrollar una
herramienta llamada SQLTableHistory esta herramienta nos da la facilidad de que podemos
seleccionar las tablas que queremos auditar.
Pero navegando me encontre con una excelente solucion hecha por Jon Galloway, en la cual consiste
en crear un solo script y que este se encarge de crear los triggers necesarios para cada tabla de la
base de datos seleccionada, la diferencia con SQLTableHistory es que con nuestra herramienta
podemos seleccionar las tablas que queremos que se le haga su respectiva auditoria y con la solucion
presentada en este blog.
Aqui un ejemplo de como se verian los datos con la solucion de Jon Galloway
Con esta informacion podemos hacer reportes de una manera sencilla tales como:
Con estas herramientas es posible volver al estado anterior de la tabla y volver en un punto
especifico, claro esta ya depende de las nuevas extensiones que ustedes le hagan.
Aqui os dejo el script completo que crea la tabla de auditoria y corre el script para crear los triggers a
todas las tablas de la base de datos.
GO
IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME= 'Audit
')
CREATE TABLE Audit
AuditID [int]IDENTITY(1,1) NOT NULL,
Type char(1),
TableName varchar(128),
PrimaryKeyField varchar(1000),
PrimaryKeyValue varchar(1000),
FieldName varchar(128),
OldValue varchar(1000),
NewValue varchar(1000),
UpdateDate datetime DEFAULT (GetDate()),
UserNamevarchar(128)
GO
DECLARE @sql varchar(8000), @TABLE_NAMEsysname
SET NOCOUNT ON
SELECT @TABLE_NAME= MIN(TABLE_NAME)
FROM INFORMATION_SCHEMA.Tables
WHERE
TABLE_TYPE= 'BASE TABLE'
AND TABLE_NAME!= 'sysdiagrams'
AND TABLE_NAME!= 'Audit'
WHILE @TABLE_NAMEIS NOT NULL
BEGIN
SELECT @sql =
'
@field int ,
@maxfield int ,
@char int ,
@fieldname varchar(128) ,
@TableName varchar(128) ,
@PKCols varchar(1000) ,
@sql varchar(2000),
@UpdateDate varchar(21) ,
@UserName varchar(128) ,
@Type char(1) ,
@PKFieldSelect varchar(1000),
@PKValueSelect varchar(1000)
-- Action
else
select @Type = ''I''
else
fromINFORMATION_SCHEMA.TABLE_CONSTRAINTS pk ,
INFORMATION_SCHEMA.KEY_COLUMN_USAGE c
andc.TABLE_NAME = pk.TABLE_NAME
andc.CONSTRAINT_NAME = pk.CONSTRAINT_NAME
fromINFORMATION_SCHEMA.TABLE_CONSTRAINTS pk ,
INFORMATION_SCHEMA.KEY_COLUMN_USAGE c
andc.TABLE_NAME = pk.TABLE_NAME
andc.CONSTRAINT_NAME = pk.CONSTRAINT_NAME
select @PKValueSelect = coalesce(@PKValueSelect+''+'','''') +
''convert(varchar(100), coalesce(i.'' + COLUMN_NAME + '',d.'' + COLUMN_NAME +
''))''
INFORMATION_SCHEMA.KEY_COLUMN_USAGE c
if @PKCols is null
begin
return
end
begin
begin
select @sql = @sql + '' from #ins i full outer join #del d''
select @sql = @sql + '' where i.'' + @fieldname + '' <> d.'' + @fieldname
select @sql = @sql + '' or (i.'' + @fieldname + '' is null and d.'' +
@fieldname + '' is not null)''
select @sql = @sql + '' or (i.'' + @fieldname + '' is not null and d.'' +
@fieldname + '' is null)''
exec (@sql)
end
end
'
SELECT @sql
EXEC(@sql)
SELECT @TABLE_NAME= MIN(TABLE_NAME) FROM INFORMATION_SCHEMA.Tables
WHERE TABLE_NAME> @TABLE_NAME
AND TABLE_TYPE= 'BASE TABLE'
AND TABLE_NAME!= 'sysdiagrams'
AND TABLE_NAME!= 'Audit'
END
Para mas informacion:
Construcción de un sistema de auditoría con triggers en
Microsoft SQL Server
Introducción
La auditoria de sistemas es un punto importante a considerar en sistemas cliente / servidor en los cuales
existe una multitud de usuarios trabajando sobre una misma fuente de datos. Cuando dichos sistemas son
de pequeño porte y poseen pocos usuarios el problema podría parecer trivial, pero a medida que la
envergadura del sistema crece y (sobre todo) la cantidad y variedad de usuarios es mayor, la auditoria se
convierte en un punto difícil de manejar. En este artículo se intenta presentar dos soluciones posibles al
problema y desarrollar una de ellas en la cual solo se utiliza transact-SQL, por último se darán las bases
para automatizar la instalación de la solución presentada y algunas consideraciones y optimizaciones
posibles.
Sobre auditoría
Antes que nada habría que aclarar a que nos referimos cuando hablamos de "auditoria". En este ámbito, con
auditoria nos referimos al seguimiento de las operaciones realizadas por cada usuario, básicamente llevar un
control de "que se hace", "quien lo hace (el Usuario)", "en donde se hace", y "cuando se hace".
El concepto no es nuevo, en los entornos mainframe suele ser llamado "el login del sistema", aquel lector
que esté relacionado con la jerga entenderá que nos referimos a lo mismo, solo diferimos en la forma de
implementarlo.
También podría hallarse una cierta analogía con los eventos visualizados en la sección de Seguridad del
Visor de Eventos de Windows NT/2000.
Con esto nos referimos a que dentro del código encargado de hacer modificaciones a los datos, se realicen
las inserciones a la tabla AUDIT, de este modo, cualquier operación generará un registro de auditoria. La
ubicación del código (responsable de las inserciones) dependerá de la arquitectura que utilice el
desarrollador, ya sea en una arquitectura de dos o tres capas, en donde se concentre la lógica de negocio de
la aplicación, allí estará el código encargado de realizar las inserciones de auditoria.
De este modo, cada tabla (que se desee auditar) tendrá un disparador (o trigger) que, cada vez que detecte
una modificación en la tabla, inserte un registro en la tabla de auditoria. Si el lector desconoce el concepto
de disparador, en las secciones siguientes describiremos en detalle de que se trata, por ahora veámoslo
como "algo" que está "latente" en la base de datos que, al detectar una modificación en los datos de una
determinada tabla, ejecuta una serie de sentencias Transact - SQL previamente configuradas.
La opción que se va a desarrollar es la segunda, la decisión no es arbitraria, obedece a una serie de ventajas
que se detallan a continuación:
Primero que nada, el hecho de descargar lógica del lado del cliente suele ser PELIGROSO, en este caso las
aplicaciones se hacen mas complejas de programar y mantener. Si se usan disparadores como solución se
esta reutilizando código implícitamente, cualquier nueva aplicación que acceda a una tabla existente, será
"automáticamente" auditada sin necesidad de escribir una sola línea de código de más.
Además, hay que tener en cuenta que si el sistema es accedido a través de Webforms (ASP.Net) no será
bueno cargar al cliente de trabajo que se debería concentrar del lado del servidor.
Por último, como hemos dicho antes, es posible que existan "múltiples usuarios" accediendo de "múltiples
maneras" al gestor. Muchas de estas "maneras" pueden no ser aplicaciones propietarias, un usuario por
ejemplo podría acceder a través del Query Analyzer y ejecutar una sentencia delete a una tabla cualquiera,
si la auditoria se encuentra en el cliente que hemos programado, nunca sabremos quien fue. El lector debe
tener en cuenta que NO existe manera de modificar datos en una base de datos SQL Server y evitar que se
ejecuten los disparadores que estén asociados a estos datos.
Conceptos teóricos y construcciones utilizadas
Para poder comprender correctamente las secciones siguientes, es necesario tener claros algunos conceptos
de teoría de bases de datos y la sintaxis de algunas sentencias:
Desencadenador (trigger)
Podría definirse como un tipo especial de procedimiento almacenado que se ejecuta automáticamente
cuando un usuario intenta modificar datos sobre una tabla determinada. Los disparadores se almacenan en
la base de datos en forma similar a los procedimientos almacenados, sin embargo NUNCA son ejecutados
explícitamente por los usuarios, sólo se disparan cuando el gestor detecta una modificación.
La sintaxis que utilizaremos durante este desarrollo para la creación de disparadores es la siguiente:
Desarrollo
Con lo que se ha explicado hasta el momento, poco nos resta para implementar el sistema de auditoria,
simplemente hay que crear un disparador por cada tabla que se quiera auditar, el disparador tiene que
ejecutar un insert a la tabla AUDIT, veámoslo con un ejemplo. Supongamos una tabla CLIENTES, que
presenta la siguiente estructura (muy simplificada, solo para fines demostrativos):
Lo que se presenta a continuación es un procedimiento almacenado que encapsula la creación de los tres
disparadores para una tabla determinada que es pasada como parámetro de entrada:
A continuación desarrollamos un ejemplo práctico para el disparador que controla la eliminación, en donde
utilizamos la tabla "deleted", ésta es una tabla temporal a la cual se puede tener acceso dentro de un
disparador, de este modo podemos recuperar los datos que están siendo eliminados y que han disparado la
ejecución del disparador (nótese que también se podría utilizar la tabla temporal inserted accesible desde
los disparadores para inserción).
Lo que vamos a hacer es recuperar el nombre del cliente que se está eliminando y lo vamos a guardar en el
campo descripción de la tabla AUDIT.
De este modo reformulamos la creación del disparador de la siguiente manera: