Auditoria y triggers

14
AGREGAR UN SIMPLE TRIGGER PARA AUDITAR TU BASE DE DATOS SQL SERVER 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: Cuales tablas han sufridos cambios recientemente. Cuales tablas no sufrieron cambios el pasado año. Cuales tablas jamaz han sufrido cambios. Mostrar todos los cambios a las tablas por un usuario y periodo especifico. Mostrar las tablas mas activas en un determinado periodo. 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. USE MYDATABASE--Ponerle el nombre de la base de datos que va hacer auditada GO IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME= 'Audit ') CREATE TABLE Audit

Transcript of Auditoria y triggers

Page 1: Auditoria y triggers

AGREGAR UN SIMPLE TRIGGER PARA AUDITAR TU BASE DE DATOS SQL SERVER

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:

Cuales tablas han sufridos cambios recientemente. Cuales tablas no sufrieron cambios el pasado año. Cuales tablas jamaz han sufrido cambios. Mostrar todos los cambios a las tablas por un usuario y periodo especifico. Mostrar las tablas mas activas en un determinado periodo.

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.

USE MYDATABASE--Ponerle el nombre de la base de datos que va hacer auditada

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),

Page 2: Auditoria y triggers

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

EXEC('IF OBJECT_ID (''' + @TABLE_NAME+ '_ChangeTracking'', ''TR'') IS NOT NULL DROP TRIGGER ' + @TABLE_NAME+'_ChangeTracking')

SELECT @sql =

'

create trigger ' + @TABLE_NAME+ '_ChangeTracking on ' + @TABLE_NAME+ ' for insert, update, delete

as

Page 3: Auditoria y triggers

 

declare @bit int ,

@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)

 

select @TableName = ''' + @TABLE_NAME+ '''

 

-- date and user

select @UserName = system_user ,

@UpdateDate = convert(varchar(8), getdate(), 112) + '' '' + convert(varchar(12), getdate(), 114)

 

-- Action

if exists (select * from inserted)

if exists (select * from deleted)

select @Type = ''U''

else

select @Type = ''I''

Page 4: Auditoria y triggers

else

select @Type = ''D''

 

-- get list of columns

select * into #ins from inserted

select * into #del from deleted

 

-- Get primary key columns for full outer join

select@PKCols = coalesce(@PKCols + '' and'', '' on'') + '' i.'' + c.COLUMN_NAME + '' = d.'' + c.COLUMN_NAME

fromINFORMATION_SCHEMA.TABLE_CONSTRAINTS pk ,

INFORMATION_SCHEMA.KEY_COLUMN_USAGE c

where pk.TABLE_NAME = @TableName

andCONSTRAINT_TYPE = ''PRIMARY KEY''

andc.TABLE_NAME = pk.TABLE_NAME

andc.CONSTRAINT_NAME = pk.CONSTRAINT_NAME

 

-- Get primary key fields select for insert

select @PKFieldSelect = coalesce(@PKFieldSelect+''+'','''') + '''''''' + COLUMN_NAME + ''''''''

fromINFORMATION_SCHEMA.TABLE_CONSTRAINTS pk ,

INFORMATION_SCHEMA.KEY_COLUMN_USAGE c

where pk.TABLE_NAME = @TableName

andCONSTRAINT_TYPE = ''PRIMARY KEY''

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 + ''))''

Page 5: Auditoria y triggers

from INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk ,   

INFORMATION_SCHEMA.KEY_COLUMN_USAGE c  

where  pk.TABLE_NAME = @TableName  

and CONSTRAINT_TYPE = ''PRIMARY KEY''  

and c.TABLE_NAME = pk.TABLE_NAME  

and c.CONSTRAINT_NAME = pk.CONSTRAINT_NAME

 

if @PKCols is null

begin

raiserror(''no PK on table %s'', 16, -1, @TableName)

return

end

 

select @field = 0, @maxfield = max(ORDINAL_POSITION) from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = @TableName

while @field < @maxfield

begin

select @field = min(ORDINAL_POSITION) from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = @TableName and ORDINAL_POSITION > @field

select @bit = (@field - 1 )% 8 + 1

select @bit = power(2,@bit - 1)

select @char = ((@field - 1) / 8) + 1

if substring(COLUMNS_UPDATED(),@char, 1) & @bit > 0 or @Type in (''I'',''D'')

begin

select @fieldname = COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = @TableName and ORDINAL_POSITION = @field

select @sql = ''insert Audit (Type, TableName, PrimaryKeyField, PrimaryKeyValue, FieldName, OldValue, NewValue, UpdateDate, UserName)''

select @sql = @sql + '' select '''''' + @Type + ''''''''

select @sql = @sql + '','''''' + @TableName + ''''''''

Page 6: Auditoria y triggers

select @sql = @sql + '','' + @PKFieldSelect

select @sql = @sql + '','' + @PKValueSelect

select @sql = @sql + '','''''' + @fieldname + ''''''''

select @sql = @sql + '',convert(varchar(1000),d.'' + @fieldname + '')''

select @sql = @sql + '',convert(varchar(1000),i.'' + @fieldname + '')''

select @sql = @sql + '','''''' + @UpdateDate + ''''''''

select @sql = @sql + '','''''' + @UserName + ''''''''

select @sql = @sql + '' from #ins i full outer join #del d''

select @sql = @sql + @PKCols

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:

Page 7: Auditoria y triggers
Page 8: Auditoria y triggers

Construcción de un sistema de auditoría con triggers en Microsoft SQL Server

Por Mariano Minoli.

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.

Diferentes enfoques para un mismo problema

Primero buscaremos donde almacenar la información, mas allá de cómo hacerlo. Puede que el lector esté

pensando en una tabla en la cual se almacenen datos que contesten a las preguntas hechas en el párrafo

anterior, no vamos a contradecirlo: las dos soluciones propuestas incluyen una tabla almacenada en la base

de datos. El formato de la tabla puede variar dependiendo de las necesidades específicas del entorno,

nosotros proponemos la siguiente, a los efectos del desarrollo:

Page 9: Auditoria y triggers

El script para la creación de la tabla es:

CREATE TABLE [dbo].[AUDIT] (

[id_evento] [int] IDENTITY (1, 1) NOT NULL ,

[tipo_evento] [char] (10) NOT NULL ,

[fecha] [datetime] NOT NULL ,

[descripcion] [char] (50) NULL ,

[usuario] [char] (30) NULL ,

[terminal] [char] (30) NULL ,

[aplicacion] [char] (30) NULL) ON [PRIMARY]GOALTER TABLE [dbo].[AUDIT] WITH NOCHECK ADD

CONSTRAINT [PK_AUDIT] PRIMARY KEY NONCLUSTERED ( [id_evento] ) ON [PRIMARY]

GO

Ahora que sabemos donde vamos a almacenar la información, necesitamos determinar como vamos a

hacerlo. Presentamos dos opciones:

1. Delegar la responsabilidad en la lógica de negocio de la aplicación.

2. Crear disparadores en cada tabla que se desee auditar.

1er opción: Delegar la responsabilidad en la lógica de negocio de la aplicación.

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.

2da opción: Crear disparadores en cada tabla que se desee auditar.

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:

Page 10: Auditoria y triggers

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.

Existen tres tipos de disparadores, uno para cada tipo de actualización:

Eliminación

Inserción

Modificación

La sintaxis que utilizaremos durante este desarrollo para la creación de disparadores es la siguiente:

CREATE TRIGGER nombre_trigger ON tabla

[WITH ENCRYPTION]

{ {FOR { [DELETE] [,] [INSERT] [,] [UPDATE] }

AS sentencia_sql [...n]}

Cabe aclarar que existen otras opciones adicionales que no son utilizadas durante este desarrollo.

Sentencia insert utilizada con un select

Debido a que no es la sintaxis más popular de un insert, nos pareció interesante explicarle que se va a

utilizar la cláusula de la siguiente manera:

Insert into TABLA _ DESTINO

Select * from TABLA _ ORIGEN

Esta sentencia inserta todos los registros obtenidos como el resultado de la consulta a la TABLA_ORIGEN en

la TABLA_DESTINO

Execute

Page 11: Auditoria y triggers

Puede ser utilizado para ejecutar un procedimiento almacenado o (como en nuestro caso) para ejecutar un

conjunto de sentencias Transact-SQL que es pasada como un string, esto nos permite "armar" la sentencia

concatenando partes fijas con variables que van tomando distintos valores.

Las funciones getdate(), host_name(), SYSTEM_USER, APP_NAME

Usamos estas funciones para "capturar" valores que nos interesa almacenar en la tabla AUDIT. Sus

significados son:

Getdate(): Fecha-hora actual del sistema.

SYSTEM_USER: Nombre del usuario que envía una sentencia al servidor.

host_name(): Nombre de la maquina cliente desde donde se envía la sentencia.

APP_NAME: Nombre de la aplicación cliente a través de la cual se envía la sentencia.

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):

La sentencia de creación de esta tabla es:

CREATE TABLE [dbo].[CLIENTES] (

[id_cliente] [int] NOT NULL ,

[Nombre] [char] (50) NOT NULL)

ON [PRIMARY]

GO

Para esta tabla las sentencias de creación de los disparadores son las siguientes:

CREATE TRIGGER AUDITdel ON CLIENTES

FOR DELETE

AS

Insert into AUDIT select "Delete", getdate(), "Eliminacion de un registro", SYSTEM_USER,

host_name(),APP_NAME()

CREATE TRIGGER AUDITins ON CLIENTES

FOR INSERT

AS

insert into AUDITselect "Insert", getdate(), "Insercion de un registro", SYSTEM_USER,

host_name(),APP_NAME()

CREATE TRIGGER AUDITdel ON CLIENTES

FOR UPDATE

AS

insert into AUDITselect "Update", getdate(), "Modificacion de un registro", SYSTEM_USER,

host_name(),APP_NAME()

Cabe aclarar que lo mismo se podría hacer de una manera más "amigable" desde el Administrador

Corporativo (Enterprise Manager).

Page 12: Auditoria y triggers

Habiendo creado los tres disparadores sobre la tabla clientes, intente hacer cualquier operación que

modifique los datos de la misma, por ejemplo podría ejecutar las tres sentencias siguientes:

Insert into CLIENTES values (2356, "Juan Perez")

Go

Update CLIENTES set Nombre = "Ricardo Perez"

where id_cliente = 2356

Go

Delete CLIENTES where id_cliente = 2356

Si analiza la tabla AUDIT verá que las sentencias ejecutadas accionaron los disparadores que se habían

creado. Éstos insertaron un registro por cada modificación efectuada a la tabla. Verifique con la siguiente

consulta:

select * from AUDIT

Optimización 1: Creación de un Procedimiento Almacenado que automatice la instalación del

sistema

Con lo visto hasta el momento, ya esta en condiciones de crear sus propios disparadores sobre cada tabla

que desee auditar, ahora suponga que quiere auditar con este método la base de datos corporativa, en la

cual se alojan datos referentes a todos los subsistemas de la organización. Suponga que las tablas a auditar

son 300.

¿No le interesa la idea de automatizar la instalación de los disparadores?

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:

CREATE PROCEDURE sp_instalarTrigger

@tabla as char(128)

as

-- Aseguramos que el parametro de entrada esté libre de espacios

set @tabla = ltrim(rtrim(@tabla))

-- Creacion del trigger para ELIMINACION

EXECUTE ('CREATE TRIGGER AUDITdel_' + @tabla +' ON ' + @tabla +' FOR DELETE AS Insert into

AUDITselect "Delete", getdate(), "Eliminacion de un registro", SYSTEM_USER,

host_name(),APP_NAME()')

-- Creacion del trigger para INSERCIONEXECUTE ('CREATE TRIGGER AUDITins_' + @tabla +' ON '

+ @tabla +' FOR INSERT AS Insert into AUDITselect "Insert", getdate(), "Insercion de un

registro", SYSTEM_USER, host_name(),APP_NAME()')

-- Creacion del trigger para MODIFICACIONEXECUTE ('CREATE TRIGGER AUDITupd_' + @tabla +' ON

' + @tabla +' FOR UPDATE AS Insert into AUDITselect "Update", getdate(), "Modificacion de

un registro", SYSTEM_USER, host_name(),APP_NAME()')

Por ejemplo, para nuestra tabla sería:

Exec sp_instalarTrigger "CLIENTES"

Un segundo paso para lograr una instalación totalmente automática podría ser crear otro procedimiento

almacenado que:

Page 13: Auditoria y triggers

Cargue un cursor con todas las tablas de usuario a través de un select de la tabla sysobjects (con la

condición de que el campo xtype sea "U").

Luego ejecute el procedimiento almacenado antes creado por cada registro dentro del cursor.

Sin embargo debe ser cuidadoso con este enfoque de "instalación masiva" porque la sobrecarga de

procesamiento que existirá en el servidor a partir de la instalación de los disparadores podría no ser

aceptable (o deseable) en todas la tablas, mas adelante hablaremos de ello.

Optimización 2: Personalización del mensaje grabado (tablas inserted y deleted)Si analiza la tabla AUDIT que

se ha propuesto verá que uno de los campos es "descripción". Hasta el momento hemos estado insertando

una cadena fija que presenta una suerte de descripción acerca del evento que dispara el disparador, en

realidad ese campo está pensado para guardar una descripción detallada del evento ocurrido, ¿cuán

detallada?, todo lo detallada que el usuario considere necesario y esté dispuesto a programar.

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:

-- Primero eliminamos el trigger que se habia creado anteriormente

if exists (select * from sysobjects where id =object_id(N'[dbo].[AUDITdel_CLIENTES]') and

OBJECTPROPERTY(id, N'IsTrigger') = 1)

drop trigger [dbo].[AUDITdel_CLIENTES]

GO

-- Luego creamos el trigger para ELIMINACION con el mensaje personalizado

CREATE TRIGGER AUDITdel_CLIENTES ON CLIENTES FOR DELETE

AS

Insert into AUDIT select "Delete",getdate(), (select "Nombre eliminado: " + convert(char(15),Nombre) from

deleted) ,SYSTEM_USER, host_name(),APP_NAME()

Con este enfoque se podrían almacenar todos los datos antes de una eliminación para poder reconstruir un

registro si es necesario, aunque si su aplicación hace eliminaciones masivas (es decir de mas de dos

registros), debería replantear la inserción a la tabla AUDIT recorriendo, por ejemplo, un cursor armado con

una consulta a la tabla deleted.Aquí cabe una aclaración: el código Transact-SQL que se encuentra dentro

del trigger puede estar compuesto por bucles, condicionales, casi cualquier construcción Transact-SQL

válida, sin embargo deberá tener en cuenta que toda la demora que introduzca este código impactará

directamente en cada una de las operaciones que los usuarios hagan sobre los datos.

Encriptación de los disparadores

Una consideración que podría ser importante es la de encriptar el código de los disparadores creados, de

este modo evitará que se conozca cómo y donde se está almacenando la información de auditoria, mas allá

de que luego restrinja el acceso a la tabla AUDIT. El código debe ser encriptado al momento de la creación

del disparador a través de la cláusula "WITH ENCRYPTION", para nuestro disparador de eliminación sería:

Page 14: Auditoria y triggers

-- Primero eliminamos el trigger que se había creado anteriormente

if exists (select * from sysobjects where id =object_id(N'[dbo].[AUDITdel_CLIENTES]') and

OBJECTPROPERTY(id, N'IsTrigger') = 1)drop trigger [dbo].[AUDITdel_CLIENTES]

GO

-- Luego creamos el trigger para ELIMINACION con el mensaje personalizado y ENCRIPTADO

CREATE TRIGGER AUDITdel_CLIENTES WITH ENCRYPTION ON CLIENTES FOR DELETE

AS

Insert into AUDIT select "Delete",Getdate(), (select "Nombre eliminado: " +

convert(char(15),Nombre) from deleted) ,SYSTEM_USER, host_name(),APP_NAME()

Conclusiones

Hemos visto como, a partir de unas simples sentencias de Transact-SQL , se puede crear todo un sistema

que realice un seguimiento muy detallado de las operaciones de los usuarios sobre los datos. Además vimos

que su diseño es flexible y puede ser personalizado para necesidades específicas.

Si desea, puede completar el desarrollo creando una interfaz gráfica que acceda a la tabla AUDIT y permita

hacer consultas con filtros configurables por el usuario, emitir reportes, etc.