Comment filtrer l'utilisation de la fonction définie par l'utilisateur scalaire des données d'audit SQL Server?


12

Nous avons une base de données SQL Server qui a une spécification d'audit de base de données qui vérifie toutes les actions d'exécution sur la base de données.

CREATE DATABASE AUDIT SPECIFICATION [dbAudit]
FOR SERVER AUDIT [servAudit]
ADD (EXECUTE ON DATABASE::[DatabaseName] BY [public])

Nous avons constaté que certaines requêtes écriront dans le journal d'audit l'utilisation d'une fonction scalaire pour chaque ligne d'un jeu de résultats. Lorsque cela se produit, le journal se remplit avant que nous puissions l'ETL dans son lieu de repos final et nous avons une lacune dans notre journalisation.

Malheureusement, pour des raisons de conformité, nous ne pouvons pas simplement arrêter l'audit de chaque EXECUTEdéclaration.

Notre première pensée pour l'approche de ce problème est d'utiliser la WHEREclause sur l' audit du serveur pour filtrer l'activité. Le code ressemblait à ceci:

WHERE [object_id] not in (Select object_id from sys.objects where type = 'FN' )

Malheureusement, SQL Server n'autorise pas l'opérateur relationnel IN (probablement parce qu'il ne veut pas interroger chaque fois qu'il doit écrire dans le journal d'audit).

Nous aimerions éviter d'écrire un proc stocké qui code en dur object_idla WHEREclause, mais c'est notre réflexion actuelle sur la meilleure façon d'aborder ce problème. Y a-t-il une autre approche que nous devrions envisager?

Nous avons remarqué que lorsque la fonction scalaire est utilisée dans un CTE récursif, elle entraîne l'écriture de la requête dans le journal d'audit pour chaque ligne du jeu de résultats.

Certaines fonctions à valeur scalaire sont fournies par un fournisseur que nous ne pouvons pas supprimer ou déplacer vers une autre base de données.


6
We've found that some queries will write to the audit log the use of a scalar function for every row in a result set.- C'est l'un des effets secondaires les plus magnifiques des FDU scalaires que j'ai jamais entendu, et j'en ai beaucoup entendu.
Erik Darling

3
Existe-t-il une option pour créer des UDF que vous ne souhaitez pas auditer dans une base de données distincte (qui n'est pas auditée) et les invoquer via un nom en 3 parties?
Scott Hodgin

@ScottHodgin, j'aime la solution de contournement, mais dans nos circonstances, certaines fonctions à valeur scalaire sont fournies par un fournisseur que nous ne pouvons pas supprimer ou déplacer vers une autre base de données.
Mark Iannucci

Ceux qui suivent peuvent se demander dans quel cas la requête doit être écrite dans le journal d'audit pour chaque ligne d'un jeu de résultats; nous l'avons remarqué lorsque la fonction scalaire est utilisée dans un CTE récursif.
Mark Iannucci

Réponses:


6

Il y a quelques options que j'ai pu trouver. Toutes les options traitent des variations des prédicats de filtre. REMARQUE: vous devez désactiver la vérification du serveur afin d'apporter des modifications, puis re permettre lui.

Premièrement, l'approche la plus générique consiste à filtrer tous les FDU scalaires. Vous pouvez le faire en utilisant le class_typechamp d'audit. La documentation indique que ce champ l'est VARCHAR(2), mais elle ne permet pas de spécifier une chaîne. Cependant, j'ai réussi à faire fonctionner les éléments suivants:

ALTER SERVER AUDIT [servAudit]
WHERE ([class_type] <> 20038); -- EXECUTE Scalar UDF

(plus d'informations sur cette enquête ici: Server Audit Mystery: le filtrage class_type obtient le message d'erreur 25713 )

L'approche suivante la plus générique n'est pas une option car il a été déclaré qu'il s'agit d'une base de données fournie par le fournisseur et donc aucune modification ne peut être apportée. Je vais donc couvrir ce dernier.

L'approche la moins générique (mais qui fonctionne définitivement) consiste à filtrer le nom de fonction spécifique:

ALTER SERVER AUDIT [servAudit]
WHERE ([object_name]<>'function_name');

Ou, si plusieurs noms:

ALTER SERVER AUDIT [servAudit]
WHERE ([object_name]<>'function_name1' AND [object_name]<>'function_name2');

Bien qu'elle ne soit pas très générique, cette approche devrait être correcte car le nombre de fonctions à filtrer devrait être assez petit, et il ne sera pas très fréquent que de nouvelles fonctions soient introduites.

Enfin, pour les autres personnes confrontées à cette situation et qui ne sont pas limitées à apporter des modifications: vous pouvez placer des fonctions dans leur propre schéma, puis filtrer uniquement ce schéma. C'est plus générique que de filtrer les fonctions individuellement. En supposant que vous créez un schéma nommé fnet que vous y placez la ou les fonctions:

ALTER SERVER AUDIT [servAudit]
WHERE ([schema_name]<>'fn');

ÉGALEMENT, concernant les deux commentaires suivants dans la question:

Malheureusement, SQL Server n'autorise pas l'opérateur relationnel IN (probablement parce qu'il ne veut pas interroger chaque fois qu'il doit écrire dans le journal d'audit).

et:

Nous aimerions éviter d'écrire un proc stocké qui code en dur l'id_objet dans la clause WHERE

L' INopérateur n'est pas le problème. Certes, ce n'est pas pris en charge, mais c'est juste un raccourci pour une liste de ORconditions. Le vrai problème est l'utilisation de T-SQL. Seuls les littéraux - chaînes ou nombres - sont autorisés. Vous n'auriez donc pas pu exécuter une procédure stockée de toute façon. Vous ne pouvez pas non plus utiliser les fonctions intégrées.


merci pour cette réponse. Nous sommes en train de mettre en œuvre ce changement, et j'accepterai cette réponse lorsque nous confirmerons que cela fonctionne dans notre environnement.
Mark Iannucci

1
@MarkIannucci Merci! De plus, je viens de corriger un bug mineur dans ma suggestion idéale. J'avais copié et collé des tests où je filtrais les fonctions FOR au lieu de N'IMPORTE QUELLE fonction MAIS. J'ai changé le =pour être <>dans ma réponse. Je viens aussi de le tester et cela fonctionne comme annoncé :-)
Solomon Rutzky
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.