A propos de l’erreur 33203 : SQL Server audit could not write to the security log

Mis en avant

Lors de la mise en place des audits de sécurité je me suis heurté à cette fameuse erreur 33203 sur une instance nommée qui indique explicitement que SQL Server ne peut pas écrire dan le journal de sécurité Windows.  Ma configuration est la suivante : SQL Server 2012 SP1  et Windows 2012 Server.

Je précise avant de commencer que les prérequis de fonctionnement des audits avec le journal de sécurité Windows sont respectés. La conséquence directe de l’erreur 33203 est qu’au évènement n’est enregistré dans le journal de sécurité Windows, ce qui est plutôt gênant pour des audits. De plus les journaux des erreurs Windows et SQL Server ne sont pas spécialement bavards quant à la cause de cette erreur.

 

image

 

Dans ce cas comment savoir ce qui empêche SQL Server d’écrire dans le journal ? Je dois dire que les outils sysinternals sont bien utiles dans ces moments et en particulier procmon.

Une capture procmon me donne ceci lorsque j’active un objet d’audit depuis SQL Server :

 

image

On peut remarquer ici que SQL Server tente un accès à la clé de registre HKLM\System\CurrentControlSet\Services\EventLog\Security et que cet accès lui est visiblement refusé. Un message est également inscrit dans le journal des erreurs SQL. Pas de souci, nous allons configurer les permissions adéquates sur cette clé de registre.

 

image

 

Le paramétrage des permissions a visiblement permis à l’instance SQL Server de créer une nouvelle clé de registre dans HKLM\System\CurrentControlSet\Services\EventLog\Security :

image

 

image

 

Me croyant sauvé, j’active mes audits mais je me heurte à une nouvelle erreur. Une nouvelle trace procmon me révèle le problème suivant :

 

image

 

SQL Server tente de lire le fichier C:\Windows\System32\LogFiles\Sum\Api.log mais encore un fois ce dernier se voit refuser l’accès. Le paramétrage en lecture seule du fichier Api.log me permet enfin d’activer mes audits et de valider que les évènements soient bien enregistrés dans le journal de sécurité Windows. Ce deuxième problème visiblement a été remonté chez Microsoft et est toujours d’actualité. A noter que je n’ai eu ce souci que pour mon instance nommé dans mon cas.

 

Quelques remarques supplémentaires :

  • Le fait d’enlever le compte de service SQL des permissions de la clé de registre HKLM\System\CurrentControlSet\Services\EventLog\Security ne semble plus être gênant à partir du moment où la nouvelle clé a été créé.
  • Il n’est pas possible cependant d’enlever les permissions sur le fichier C:\Windows\System32\LogFiles\Sum\Api.log sous peine d’avoir dans le journal des évènements Windows le type d’erreur suivant et plus d’évènement d’audit enregistré. A voir si le problème sera résolu plus tard par Microsoft (dans un CU4 peut être ?) avec Windows Server 2012. L’ensemble des problèmes répertoriés concerneraient Windows Server 2012.
  • Je ne pense pas que le problème soit lié à la version de SQL Server. Si j’ai le temps je testerai sur une version SQL Server 2008 R2 et mettrait à jour mon blog.

 

image

 

Bonne activation d’audit !! Sourire

 

David BARBARIN (Mikedavem)
MVP SQL Server

Problème d’utilisation de l’option WITH EXECUTE AS dans une procédure stockée avec les serveurs liés

Mis en avant

L’emprunt d’identité peut s’avérer nécessaire lorsque l’on commence à vouloir faire de la sécurité à un niveau granulaire relativement bas. Par exemple la politique de sécurité en vigueur peut nous contraindre à restreindre l’accès aux données via des procédures stockées. Cependant si ces données sont distantes et implique l’implémentation d’un serveur lié pour y avoir accès, cela peut donner matière à plus de réflexion. En effet, dans ce cas il va falloir donner les droits adéquates aux utilisateurs concernés sur le serveur distant pour accéder aux données, ce qui risque pour le coup d’augmenter la surface d’exposition. Un utilisateur A devra pouvoir exécuter une procédure stockée et sélectionner les données sur le serveur distant. L’utilisateur A peut par conséquent passer outre la procédure stockée et se connecter directement au serveur distant pour accéder aux données. Pour éviter cela on peut tout à fait utiliser le mécanisme d’emprunt d’identité dans une procédure stockée à l’aide de WITH EXECUTE AS et associer l’utilisateur dédié à cette tâche à un utilisateur sur le serveur distant. On bénéficie ainsi d’un contrôle d’accès beaucoup fort et maitrisé.

 

Le schéma ci-dessous illustre bien notre problématique :

 

icon_arrow Dans le 1er cas un mapping est nécessaire pour chaque utilisateur qui va vouloir accéder aux données du serveur distant Instance 2, ce qui signifie qu’il devra exister les mêmes logins sur le serveur distant Instance 2. Comme je l’ai évoqué au début cela implique également que les utilisateurs concernés pourront directement accéder aux données du serveur distant avec leurs informations de connexion.

 

image

 

icon_arrow Dans le 2ème cas nous mettons en place un mécanisme d’emprunt d’identité via l’option WITH EXECUTE AS USER dans la procédure stockée. L’idée ici est de n’autoriser que cet utilisateur à avoir accès aux données distantes.

 

image

 

La mise en place d’un tel mécanisme dans le contexte des serveurs liés nécessitent un certain paramétrage :

  • L’activation obligatoire de l’option de bases de données trustworthy. Malheureusement seule cette option est viable lorsqu’il s’agit d’accès inter instances. L’utilisation des certificats dans ce cas ne fonctionne pas.
  • Différer l’exécution de la procédure stockée concernée. Je n’ai pas trouvé d’article Microsoft sur le sujet mais simplement un item connect. C’est ce point que je vais détailler ici.

 

Si l’on utilise directement l’option WITH EXECUTE AS dans une procédure stockée de la manière suivante :

 

CREATE PROCEDURE dbo.GetRemoteData
WITH EXECUTE AS 'USER1'
AS

SELECT col1, col2
FROM [linked_server].[DATABASE].[schema].[TABLE]
GO

 

… avec l’appel suivant …

 

EXEC dbo.GetRemoteData

 

… il y a de grandes chances que cela ne fonctionne pas surtout si l’on a définit le contexte d’authentification de serveur lié suivant :

 

image

 

Dans ce cas seul le mapping défini pour l’utilisateur USER1 fonctionnera et aucun autre login ou aucun autre type d’authentification ne fonctionnera.

 

Si maintenant j’exécute ou je crée la procédure stockée dbo.GetRemoteData dans le contexte d’un utilisateur différent de l’utilisateur USER1 ayant les droits de création et d’exécution je peux me retrouver avec le message suivant :

 

image

 

Pourtant me direz-vous que nous avons bien défini l’emprunt d’identité dans la procédure stockée et qu’ici visiblement SQL Server n’est pas capable de trouver le mapping défini dans les options de sécurité du serveur lié. En réalité il faut bien comprendre ce qui se passe lorsqu’une procédure stockée est compilée et lorsque celle-ci est exécutée (run-time context). SQL Server compile une procédure stockée avec les credentials de l’appelant de la procédure et non ceux de l’utilisateur associée à l’emprunt d’identité. C’est pendant l’exécution de la procédure que le mécanisme d’emprunt d’identité jouera tout son rôle. Lorsqu’on accède aux données aux travers d’un serveur lié la compilation va générer l’erreur 7416 si l’appelant de la procédure n’a pas un mapping inter-instances configuré (SQL Server va vérifier lors de la compilation l’accès aux différents objets du serveur distant).

Pour contourner ce problème on peut user de 2 mécanismes qui permettent de différer l’exécution de la procédure stockée et de laisser le mécanisme d’emprunt d’identité opérer en premier lieu :

  • Créer une nouvelle procédure stockée qui va scinder l’exécution de notre procédure stockée initiale en 2 étapes
  • Encapsuler le code à exécuter de la procédure stockée avec EXEC( »), ce qui permettra au final de faire la même que dans la 1ère solution.

 

Par exemple :

CREATE PROCEDURE dbo.GetRemoteDataWithImpersonate
WITH EXECUTE AS 'USER1'  
AS

EXEC dbo.GetRemoteData
GO

ou encore :

CREATE PROCEDURE dbo.GetRemoteData    
WITH EXECUTE AS 'USER1'    
AS

EXEC('SELECT col1, col2 FROM [linked_server].[database].[schema].[table]')    
GO

 

Le choix de la méthode dépendra bien du contexte.

 

Bonne programmation !

David BARBARIN (Mikedavem)
MVP SQL Server

Prochain évènement GUSS le 24 avril – 19h00 : Webcast sur SQL Server 2012 AlwaysOn pour les fermes Sharepoint 2013

Mis en avant

J’aurai le plaisir d’animer le prochain évènement du GUSS sous un nouveau format. Le principe est simple : où que vous soyez, vous pouvez rejoindre le webcast en ligne avec le son, la vidéo et un chat pour poser des questions.

 

Ce webcast sera composé de 2 sujets de 30 minutes :

 

icon_arrow  Always-On : rappel des bases
La première session rappellera le fonctionnement et les bases de la Haute-Disponibilité avec AlwaysOn (avantages, architecture, groupes de disponibilités, type de réplications de données, etc.).

 

icon_arrow AlwaysOn dans les fermes sharepoint 2013
Mise en pratique avec une implémentation d’AlwaysOn avec SharePoint, produit très consommateur de SQL Server et avec des topologies souvent complexes. L’idée ici est d’avoir une vision beaucoup plus orientée base de données et analyser les avantages mais aussi les impacts à utiliser AlwaysOn avec Sharepoint (création / supression d’applications, authentification, utilisation des connexions readonly, maintenance des bases de données, monitoring …)

 

Les informations de connexion vous seront communiqués la veille sur le site du GUSS. En espérant vous voir nombreux !

 

David BARBARIN (Mikedavem)
MVP SQL Server

MVP SQL Server : Quatrième chapitre pour l’année 2013

Mis en avant

Pas de poisson d’avril et une vraie bonne nouvelle de la part de Microsoft aujourd’hui : le renouvèlement de mon titre de MVP SQL Server pour la 4ème fois.

J’en profite pour remercier Martine Tiphaine et Microsoft une nouvelle fois !

 

mvp

 

David BARBARIN (Mikedavem)
MVP SQL Server