Serveurs liés et délégation Kerberos

David BARBARIN

La délégation Kerberos dans le cadre des serveurs liés permet aux utilisateurs d'interroger des serveurs SQL distants en utilisant les informations de leur compte Windows et ceci sans avoir à les entrer sur chaque serveur interrogé. Ce processus est également appelé saut (ou hop en anglais). La mise en place d'un tel processus nécessite d'appréhender le protocole d'authentification sur lequel il repose et une certaine maîtrise de certains outils d'aide aux diagnostics est un plus pour pouvoir résoudre les problèmes que l'on peut rencontrer. ---- Commentez ♪

- Titre : Serveurs liés et délégation Kerberos

- Auteur : David BARBARIN

- Parution : 4 janvier 2011

- Licence : Copyright ® 2011 David BARBARIN. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Introduction

- II. Problématique

- III. Fonctionnement de Kerberos

- III-A. Infrastructure Kerberos

- III-B. Processus d'authentification

- III-C. Cache d'autorisation

- III-D. Service principal Name

- III-E. Prérequis de fonctionnement

- IV. Délégation Kerberos

- IV-A. Type de délégation

- V. Cas d'étude

- V-A. Exemple 1 : authentification simple d'un compte utilisateur

- V-B. Exemple 2 : Délégation Kerberos avec un serveur lié

- V-B-1. SPN absent

- V-B-2. SPN ou délégation mal configurée

- V-B-3. SPN dupliqué

- VI. Conclusion

- VII. Webographie

- VIII. Bibliographie

I - Introduction

La mise en place de serveurs liés est une opération devenue courante de nos jours. En effet, il n'est pas rare d'avoir à manipuler plusieurs sources de données et plusieurs serveurs SQL pour scinder l'information par exemple. De plus, les règles de sécurité étant devenues beaucoup plus draconiennes, les entreprises préfèrent se tourner vers des méthodes d'authentification fiables comme Kerberos et abandonnent peu à peu l'utilisation de compte utilisateur générique de type SQL. Cependant l'utilisation du protocole Kerberos avec les serveurs liés nécessite très souvent la mise en place de la délégation Kerberos lorsqu'il s'agit d'interroger des données dans le contexte de l'utilisateur Windows. Lorsqu'on aborde la délégation avec les administrateurs de base de données ceux-ci n'ont en général qu'une connaissance partielle en la matière et ont du mal à résoudre les problèmes liés à Kerberos. Certains diront que le problème relève de l'administrateur système, mais il n'est pas rare que celui-ci ne puisse pas aider le DBA, car lui-même ne possède pas la connaissance nécessaire ou tout simplement parce que ce rôle n'existe pas au sein de l'entreprise.

II - Problématique

Dans de nombreux environnements, l'authentification est réalisée à l'aide d'un compte de connexion (ou login) et d'un mot de passe. Ce mot de passe est à chaque fois transmis sur le réseau. Ceci pose deux problèmes majeurs : l'évolutivité et la sécurité.

En effet l'authentification entre un client et un serveur unique (ou service) requiert un secret partagé (sous la forme d'un mot de passe) entre les deux protagonistes. Dans ce premier cas, il est simple pour une personne de retenir ce secret (implémenté sous la forme d'un mot de passe), même si celui-ci est complexe. Cependant dans la plupart des entreprises il est nécessaire de se connecter à plusieurs serveurs pour accéder aux différents services d'une entreprise (messagerie, serveur de fichiers, serveurs de bases de données, serveur intranet, etc.). Dans ce deuxième cas, il paraît inconcevable pour cette même personne de retenir un mot passe pour chaque serveur ou service avec lequel il doit communiquer. Dans un réseau de N comptes le nombre potentiel de mots de passe peut se calculer de la façon suivante :

N x (N-1)/ 2

À titre d'exemple, pour une petite PME de 50 personnes cela représente 1225 clés à gérer et pour une entreprise de plus grande envergure de 1000 personnes 49500 clés. Autant dire que la gestion des mots de passe peut très vite devenir chaotique dans ce cas. De la même manière, l'envoi d'un mot de passe sur le réseau est une faille de sécurité certaine si celui-ci est transmis en clair. Bien qu'il existe des techniques de chiffrement comme SSL ou TLS qui permettent de chiffrer les communications sur le réseau, il incombe à chaque service de l'implémenter, ce qui en complexifie l'administration. Nous verrons que Kerberos permet de pallier ces deux problèmes majeurs par la suite.

III - Fonctionnement de Kerberos

Commençons par le début : Kerberos c'est quoi exactement ? C'est un protocole d'authentification réseau sécurisé qui repose sur un mécanisme de clés secrètes et de tickets. Ce protocole a été créé au MIT (Massachussets Institute of Technology). La version 5 est la dernière à être normalisée par l'IETF dans les RFC 1510 et RFC 1964. Lorsque l'on commence l'apprentissage de Kerberos on s'aperçoit rapidement que l'on aborde en réalité différents thèmes que sont la sécurité, le chiffrement, l'utilisation de ticket de service, les protocoles réseau et bien d'autres encore. Cet apprentissage, je le reconnais, n'est pas simple. De plus Kerberos est dépendant d'autres composants qui peuvent être système ou réseau, ce qui rend son apprentissage encore plus complexe. Dans cette section nous verrons les notions essentielles qu'un DBA doit à mon sens posséder pour pouvoir résoudre la plupart des problèmes qu'il peut rencontrer avec ce protocole d'authentification.

III-A - Infrastructure Kerberos

Kerberos peut être décrit de la façon suivante.

- Un centre de distribution de clés (KDC) : c'est un sous-système qui se situe sur le contrôleur de domaine dans une architecture Windows. Il héberge deux services importants qui sont le service d'autorisation (AS = Autorisation Service) et le service qui délivre les tickets de service (TGS = Ticket-Granting Service).

- Le service d'autorisation (AS : Autorisation Service) : ce service génère un ticket spécial appelé TGT (Ticket-Granting Ticket). Ce ticket permet de sécuriser les échanges entre un client et le KDC d'une part et permet à un client de s'authentifier une seule fois pendant la durée d'une session d'autre part. Imaginez que vous ayez à rentrer votre mot de passe à chaque fois qu'une demande est initiée sur un serveur de bases de données !!!

- Le service de tickets (TGS : Ticket-Granting service) : ce service génère le ticket de service demandé par l'utilisateur pour se connecter au service demandé (ticket appelé TGS).

La figure ci-dessous illustre de manière simplifiée l'architecture du centre de distribution des clés :

III-B - Processus d'authentification

Pour pouvoir dialoguer avec un service sur le réseau, un client doit d'abord s'authentifier auprès de lui en demandant un ticket d'authentification auprès du KDC. La figure ci-dessous décrit un protocole d'échange entre un client, le KDC et le service avec lequel il doit dialoguer.

Première phase de l'authentification (messages KRB_AS_REQ et KRB_AS_REP)

Le service AS génère une clé de session qu'il chiffre avec le mot de passe de l'utilisateur. Le TGT est également généré et est chiffré avec une clé propre au KDC en utilisant un compte utilisateur krbtgt. Ce compte est désactivé et est réservé exclusivement pour les besoins du centre de distribution des clés. Par conséquent le TGT ne peut être lu que par le KDC.

Deuxième phase de l'authentification (messages KRB_TGS_REQ et KRB_TGS_REP)

Un second dialogue est initié depuis le client pour demander le ticket d'authentification au service cible (délivré par le service de tickets). Celui-ci est chiffré avec le mot de passe du service concerné ce qui signifie qu'il est le seul à pouvoir déchiffrer ce second ticket qui n'est donc pas à destination du client. Ce dernier ne peut donc pas être lu par le client. Le TGS contient notamment une copie de la clé de session générée par le service d'autorisation ainsi que le nom de l'utilisateur désirant se connecter au service. Ce nom est appelé principal dans une architecture Kerberos.

Troisième phase de l'authentification (KRB_AP_REQ et KRB_AP_REP)

Le client déchiffre à l'aide de son mot de passe la première partie du message qui contient la clé de session. Il se sert de cette clé pour chiffrer une valeur d'horodatage. Le tout est appelé authentifiant (ou authenticator en anglais). Cet authentifiant garantit que l'expéditeur soit bien celui-ci qui est prévu.

Note : j'ai souvent entendu dire que la synchronisation du temps entre les ordinateurs dans un domaine Windows était importante sans vraiment savoir pourquoi. Nous avons ici l'explication: si l'horodatage n'est pas suffisamment précis, le ticket en provenance du client sera comparé à l'horodatage du serveur cible et sera finalement rejeté, car ce dernier l'interprétera comme une tentative d'usurpation d'identité.

III-C - Cache d'autorisation

Nous parlons rapidement du cache d'autorisation (credential cache en anglais). Celui-ci se situe sur le client. Si l'on revient un instant sur la première phase du processus d'authentification, on se souvient que le KDC envoie un TGT au client. Sans ce TGT, à chaque fois que le client se connecte à un service l'utilisateur serait invité à entrer son mot de passe. Autant dire que cela risquerait d'être contre-productif ! Pour pallier ce problème, le client se sert du TGT qu'il a mis en cache pour demander un nouveau ticket au KDC. Il n'y a donc plus besoin d'entrer le mot de passe de l'utilisateur. Cela résout par la même occasion le problème de sécurité dû à la transmission du mot de passe à travers le réseau.

Le fonctionnement de Kerberos peut être comparé avec l'achat d'une entrée dans un parc d'attractions. On achète la première fois son ticket (mot de passe utilisateur). Le guichet nous délivre alors un ticket d'entrée (TGS) et nous tamponne également la main (TGT). Il est possible de sortir du parc et d'y rentrer à nouveau en présentant le tampon. (Le TGT nous donne droit à nouveau à un TGS). Bien entendu on ne peut ne pas faire cela indéfiniment. En général ceci est valable pour une journée. C'est la même chose pour le TGT. Celui-ci possède une durée de vie paramétrable par l'administrateur système. Il existe des outils pour visualiser le contenu de ce cache et les tickets qui y sont présents. Nous verrons l'utilisation de ces outils dans la partie « Cas d'étude » de l'article.

III-D - Service principal Name

Enfin nous parlerons des SPN (ou Service Principal Name) qui sont des éléments très importants dans une infrastructure Kerberos. Chaque service est associé à un SPN unique dans un domaine qui permet de le référencer. Ceci est très important surtout lorsque nous aborderons la délégation Kerberos. Nous verrons que la majorité des problèmes concernant la délégation viennent d'un SPN absent ou mal configuré.

Un SPN est composé des éléments suivants :

- le type de service ;

- le compte de service associé ;

- l'ordinateur qui héberge le service ;

- le port utilisé par le service. Ce dernier paramètre est optionnel si le port est celui utilisé par défaut.

La syntaxe du SPN est donc la suivante : [service]/[hostname]:[port]

Nous avons vu lors du processus d'authentification que le KDC utilisait le mot de passe du service concerné pour chiffrer le ticket de service (TGS). Pour cela il recherche le SPN associé au service. Celui-ci va indiquer quel type de compte il utilise et permettra au service d'authentification de savoir quel mot de passe il doit utiliser pour chiffre le TGS. En effet, dans un domaine Windows les objets d'ordinateur et d'utilisateur possèdent tous deux un mot de passe. Selon le cas, un service peut être associé à l'un des deux mots de passe. Dans ce cas comment le service d'autorisation sait quel mot de passe choisir ? Cela dépend du type de compte associé au service. Si un compte prédéfini (BUILTIN) est utilisé alors le mot de passe associé à l'objet d'ordinateur sera utilisé. En revanche si un compte de domaine est utilisé alors c'est le mot de passe associé à l'utilisateur de domaine qui sera utilisé.

III-E - Prérequis de fonctionnement

La mise en place de Kerberos nécessite que certains composants système ou réseau dont il dépend soient opérationnels pour garantir son fonctionnement propre. Ces composants sont :

- TCP/IP : cette couche de communication doit être impérativement actif entre le client, le contrôleur de domaine et le service cible ;

- Domaine Active Directory : dans une architecture Windows Kerberos ne peut fonctionner qu'avec un domaine AD actif. Par conséquent les utilisateurs locaux ou NT4 ne sont pas compatibles avec ce protocole d'authentification ;

- Système de résolution de nom : Kerberos se base sur la résolution de nom pour fonctionner, de la même manière qu'un domaine Active Directory. Ce composant est donc très important dans ce type d'architecture ;

- Service de temps : comme nous avons pu voir précédemment, la synchronisation du temps entre le client, le contrôleur de domaine et le serveur cible est très importante pour réussir l'authentification. Dans la grande majorité des cas, le contrôleur de domaine est la source de synchronisation du temps pour tous les serveurs du domaine concernés ;

- Système d'exploitation : Kerberos ne peut fonctionner qu'avec une version du système d'exploitation qui le supporte (Windows 2000, Windows XP ou plus).

IV - Délégation Kerberos

Nous arrivons maintenant à la délégation Kerberos avec SQL Server, mais il m'apparaissait nécessaire de voir (ou revoir) les principes fondamentaux de Kerberos dans un premier temps pour mieux comprendre le fonctionnement de délégation à proprement parler. La délégation est une fonctionnalité de Kerberos qui permet à un serveur d'obtenir et de transmettre le ticket d'un client pour l'authentifier vers un autre serveur et ceci sans avoir besoin du mot de passe de ce premier. On retrouve souvent ce type de scénario (appelé souvent « double hop ») avec SQL Server et les serveurs liés lorsqu'on désire mettre en place une authentification via le contexte de sécurité du client (contexte de sécurité Windows) et que l'on souhaite interroger les données sur un serveur distant par l'intermédiaire du serveur lié dans le contexte de sécurité de l'utilisateur Windows. La figure ci-dessous illustre les différentes phases de la délégation Kerberos.

Phase 1 : elle concerne la demande de ticket du client au KDC pour pouvoir s'authentifier sur le serveur SQL1. Nous avons vu ce processus dans la section précédente.

Phase 2 : le client qui est connecté à l'instance SQL1 veut initier une requête vers l'instance SQL2 à l'aide d'un serveur lié (par exemple SELECT col1, col2 FROM linked_server.bdd.dbo.table). Pour cela il doit d'abord s'authentifier sur le serveur SQL2. C'est à ce moment que le serveur SQL1 va demander un ticket d'authentification au KDC en empruntant les informations (credential) du client.

Phase 3 : le KDC répond en envoyant le ticket d'authentification (TGS) pour le client au serveur SQL1 si et seulement si ce serveur est autorisé pour la délégation.

Phase 4 : le serveur SQL1 ouvre une connexion sur le serveur SQL2 en utilisation le ticket d'autorisation. Ce dernier vérifie que le client a les droits de connexion et exécute la requête du client.

Phase 5 : le serveur SQL1 affiche le résultat de la requête ou un message d'erreur provenant de SQL2.

IV-A - Type de délégation

Depuis la version 2003 de Windows, il existe deux types de délégation :

- la délégation non contrainte : elle existe depuis Windows 2000 et permet au serveur d'obtenir un ticket pour n'importe quel service ;

- la délégation contrainte : ce nouveau type de délégation introduit avec Windows 2003 permet de restreindre la liste des services pour lesquels un serveur peut demander un ticket ce qui réduit considérablement la fenêtre des risques potentiels de sécurité.

Attention cependant à la délégation contrainte. Bien qu'elle soit plus intéressante pour des raisons de sécurité, celle-ci est plus contraignante à mettre en place. En effet, si plusieurs serveurs sont concernés par la délégation (plusieurs sauts) et si le premier est paramétré pour ce type de délégation les suivants doivent également être paramétrés de la même manière.

V - Cas d'étude

Après avoir vu les principes généraux de fonctionnement d'une architecture Kerberos et celles qui concernent la délégation, nous étudierons ici deux exemples qui nous permettront d'observer les messages échangés entre un client, un contrôleur de domaine et un service. Nous procéderons ensuite au paramétrage de la délégation Kerberos dans un contexte d'utilisation avec les serveurs liés et nous tenterons d'analyser les problèmes les plus fréquemment rencontrés dans ce type de scénario. Ceux-ci peuvent être nombreux et dépendent beaucoup du contexte client. Cet article n'a pas la prétention de tous les répertorier. Enfin, nous verrons également certains outils qu'il est possible d'utiliser pour tenter de résoudre les erreurs rencontrées lors d'une authentification Kerberos.

V-A - Exemple 1 : authentification simple d'un compte utilisateur

Dans ce premier exemple nous utiliserons deux serveurs SQL nommés KERBSQL et KERBSSAS qui sont installés avec Windows Server 2008 R2 et SQL Server 2008 R2. De plus un serveur lié KERBSSAS est installé sur l'instance SQL Server KERBSQL et ciblera l'instance SQL Server KERBSSAS. Nous utiliserons lors de l'authentification le contexte de sécurité du client (contexte de sécurité Windows) pour se connecter au serveur lié KEBERSSAS. Le compte utilisateur de domaine qui sera utilisé pour les tests est kerbuser dans le domaine testllab.pragmantic. Celui-ci se connectera au serveur KERBSQL depuis le serveur KERBSSAS qui fera office de client. Pour le moment chaque instance SQL Server utilisera le compte de service prédéfini LocalSystem. La figure suivante montre l'architecture que nous venons de décrire :

Dans ce premier exemple, nous visualiserons les messages Kerberos échangés lors de l'ouverture de session sur le serveur KERBSSAS (le client) avec l'utilisateur Windows kerbuser et la connexion à l'instance SQL KERBSQL avec ce même utilisateur en exécutant la commande suivante :

sqlcmd -E -S KERBSQL

Nous utiliserons en parallèle un analyseur de trames appelé WireShark sur KERBSQL pour récupérer les messages Kerberos avec un filtre prédéfini Kerberos pour ne visualiser que les trames qui nous intéressent. Voici le résultat que nous obtenons avec cet utilitaire après avoir effectué une ouverture de session dans un premier temps et une connexion à l'instance SQL Server dans un second temps :

L'adresse IP 192.168.92.41 correspond au serveur KERBSQL, 192.168.92.42 au serveur KERBSSAS et 192.168.92.10 au contrôleur de domaine. Nous observons ici les trames appartenant au dialogue entre le KDC et le client avec la demande d'une clé de session suivie du TGT (AS_REQ, AS_REP) d'une part et du ticket de service (TGS) pour le service concerné (TGS_REQ_TGS_REP) d'autre part. Une seconde demande de ticket est ensuite initiée depuis le client (KERBSSAS) pour se connecter au service SQL Server sur KERBSQL.

On peut observer dans la première partie du message l'erreur KRB5KDC ERR_PREAUTH_REQUIRED. Il faut préciser qu'une authentification Kerberos dans un domaine Windows s'effectue toujours sans préauthentification alors que celle-ci est obligatoire. C'est naturellement que le KDC répond par un message d'erreur en stipulant dans la réponse le type de préauthentification à employer. Le client réitère ensuite sa demande en ajoutant l'information nécessaire. C'est ce que nous observons ici. Cette erreur n'est donc pas à prendre en compte pour le débogage dans notre cas.

Demande AS-REQ : [Source : KERBSSAS] - [Destination : KDC]

La demande de la clé de session et du TGT s'effectue bien avec le principal kerbuser vers le service Kerberos krbtgt/testllab. On peut également remarquer le port de communication utilisé par le KDC = 88. Le port utilisé par le client est quant à lui dynamique (ici 49405).

Demande AS-REP : [Source : KDC] - [Destination : KERBSSAS]

Le KDC répond en renvoyant le ticket de session et le TGT.

Réponse TGS-REQ : [Source : KERBSSAS] - [Destination : KDC]

Après la demande de clé de session et du TGT, le client demande ensuite le ticket de service (TGS) qui lui permettra de se connecter au service demandé. Il s'agit dans notre cas de se connecter au serveur KERBSSAS. D'ailleurs on peut le voir ici avec le nom du service cible nommé host/kerbssas.testllab.pragmantic. Est-ce que cette chaîne de caractères cela ne vous rappelle rien ? Cela ressemble en effet à un SPN. Comme nous l'avons dit plus haut, son rôle principal est d'identifier le service demandé. Il y a plusieurs façons de visualiser le SPN associé à un objet d'ordinateur ou à un objet utilisateur.

1- Par l'intermédiaire du snap-in adsi.msc, en choisissant l'objet concerné et en visualisant l'attribut servicePrincipalName :

2- Par l'utilitaire en ligne de commande setspn.exe avec le commutateur -L et le nom de l'objet concerné :

Demande TGS-REP : [Source : KDC] - [Destination : KERBSSAS]

La réponse du KDC est composée du ticket de service qui permettra à l'utilisateur kerbuser de se connecter au serveur KERBSSAS (service host/kerbssas.testllab.pragmantic).

Demande TGS-REQ [Source : KERBSSAS] - [Destination : KDC]

La deuxième demande de ticket de service concerne cette fois-ci la connexion au serveur SQL KERBSQL (commande sqlcmd). Comme on peut le remarquer, le service cible a changé. Celui-ci est maintenant nommé MSSQLSvc/kerbsql.testllab.pragmantic. Il n'y a pas eu de demande de type AS, car le client utilise maintenant le TGT présent dans son cache. Si l'on reprend l'analogie concernant le parc d'attractions, vous pouvez utiliser votre tampon pour accéder à n'importe quelle activité pendant la journée sans avoir à repayer une autre entrée. Ici le TGT permet de se connecter à n'importe quel service pendant sa durée de validité sans avoir à demander le mot de passe du compte utilisateur.

Réponse TGS-REP : [Source : KDC] - [Destination : KERBSSAS]

La réponse du KDC est la même que précédemment à quelques différences près. Le ticket de service est valable uniquement pour le service MSSQLSvc/kerbsql.testllab.pragmantic. On peut vérifier que le protocole utilisé pour l'authentification est bien celui attendu directement avec SQL Server. Pour cela on peut utiliser la DMV sys.dm_exec_connections de la façon suivante :

SELECT
session_id,
client_net_address
net_transport,
protocol_type,
auth_scheme
FROM sys.dm_exec_connections
WHERE client_net_address = '192.168.92.42' - KERBSSAS

… qui donne le résultat suivant :

V-B - Exemple 2 : Délégation Kerberos avec un serveur lié

Dans l'exemple 1 nous avons vu les messages échangés lorsqu'un compte utilisateur (kerbuser) s'authentifie à un client (KERBSSAS) et désire se connecter ensuite à un service (instance SQL Server KERBSQL). Dans ce deuxième exemple, nous verrons la mise en place de la délégation Kerberos avec l'utilisation des serveurs liés qui utilisent avec le contexte de sécurité Windows d'un utilisateur. Pour cela nous devons introduire un troisième serveur nommé KERBSSRS dans notre architecture et qui fera office de client pour se connecter à l'instance SQL Server KERBSQL. Un serveur lié est installé sur ce serveur nommé KERBSSAS et qui ciblera l'instance SQL Server KERBSSAS. L'utilisateur kerbuser aura accès en lecture et en écriture respectivement sur les bases DB_KERBSQL et DB_KERBSSAS des instances KERBSQL et KERBSSAS. Pour que tout ce petit monde puisse dialoguer, il va falloir configurer la délégation Kerberos afin que l'authentification de l'utilisateur Windows kerbuser puisse s'effectuer depuis le client KERBSSRS vers le serveur final KERBSSAS en passant par le serveur KERBSQL (cas du double saut). Le schéma suivant illustre cette nouvelle architecture :

Pour que la délégation Kerberos puisse fonctionner, les étapes de paramétrage suivantes sont nécessaires :

- configurer les comptes de service des serveurs SQL avec des comptes de domaine (non obligatoire) ;

- configurer les SPN des services SQL concernés ;

- autoriser le compte utilisateur de domaine utilisé par l'instance KERBSQL pour la délégation.

Nous verrons après les problèmes que l'on peut rencontrer si l'une des étapes de paramétrage a été omise.

V-B-1 - SPN absent

Le fait d'avoir un compte de domaine pour que la délégation fonctionne n'est pas obligatoire, mais si l'on veut réduire les problèmes de sécurité dus à des privilèges trop élevés, il est recommandé d'utiliser un compte d'utilisateur de domaine classique sans aucun droit particulier. Nous allons configurer les comptes de services des serveurs SQL KERBSQL et KERBSSAS de la manière suivante :

Serveur

Compte de service

KERBSQL

testllab\kerbsqlaccount

KERBSSAS

testllab\kerbssasaccount

Si l'on jette un coup d'œil aux SPN inscrits pour chaque serveur concerné par la délégation avec l'utilitaire setspn.exe, on s'aperçoit rapidement que ceux associés aux services SQL Server ont disparu.

En effet, pour des services comme SQL Server, l'utilisation d'un compte utilisateur de domaine n'inscrit pas automatiquement de SPN associé contrairement à un compte prédéfini (BUILTIN). Celui-ci doit être entré manuellement, mais pour le moment nous laisserons la situation en l'état.

Connectons-nous ensuite avec le compte de connexion kerbuser sur le serveur KERBSQL avec SQL Server Management Studio :

Jusque là pas de souci. L'utilisateur kerbuser a accès, comme prévu, à la base DB_KERBSQL et la table dbo.test. On peut maintenant exécuter une requête en quatre parties depuis l'instance SQL Server KERBSQL qui interrogera le serveur lié KERBSSAS. Cette requête ciblera la base de données DB_KERBSSAS et la table dbo.test comme défini ci-dessous :

On constate cette fois que la requête ne fonctionne pas et nous obtenons le message d'erreur suivant :

Msg 18456, Level 14, State 1, Line 1 Login failed for user 'NT AUTHORITY\ANONYMOUS LOGON'

Le message d'erreur nous parle d'un utilisateur nommé ANONYMOUS LOGON alors que nous essayons de nous identifier avec l'utilisateur kerbuser… Quel est le problème ici ? Pour le savoir, nous allons utiliser une WireShark pour récupérer les messages Kerberos. On peut remarquer l'existante d'une erreur lors de la demande du ticket de service par le serveur KERBSQL (ip : 192.168.92.41)

Si l'on se réfère à la RFC 1510, ce message d'erreur correspond à :

KDC_ERR_S_PRINCIPAL_UNKNOWN 7 Server not found in Kerberos database

On peut traduire cette erreur par une absence de SPN associé au service demandé, ce qui est le cas ici puisque nous avons vu précédemment que le fait de changer le compte de service pour SQL Server supprime également le SPN correspondant au service qui lui est associé. Une autre manière de visualiser les erreurs Kerberos est d'activer les événements d'audit Kerberos sur le ou les serveurs concernés par la délégation. Attention cependant à n'utiliser cette méthode qu'à des fins de débogage. Il faut donc penser à désactiver ces audits après avoir résolu votre problème. Pour activer les événements d'audit Kerberos il suffit d'ajouter la clé de registre suivante avec la valeur décimale 1.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Parameters\LogLevel

Voici les messages que l'on peut trouver dans le journal d'événements :

On peut récupérer ici le code d'erreur et sa valeur hexadécimale 0x1b qui correspond à « KDC_ERR_MUST_USE_USER2USER: Server principal valid for user2user only ». Ce message d'erreur indique également qu'un SPN a été mal paramétré. On peut retrouver la signification de ce message d'erreur dans la RFC 1510 ou avec l'utilitaire Err.exe. Nous verrons comment l'utiliser un peu plus loin. Si l'on regarde maintenant le protocole utilisé pour l'authentification sur SQL Server voici ce que l'on peut remarquer :

Le protocole utilisé n'est plus Kerberos. Celui a été rétrogradé à l'utilisation de NTLM !!! Il est évident que la délégation Kerberos ne peut pas fonctionner dans ce cas.

Maintenant que nous avons identifié le problème il faut donc commencer par paramétrer un SPN pour les comptes de service utilisés par les instances SQL Server KERBSQL et KERBSSAS avec l'utilitaire setspn.exe :

setspn -A MSSQLSvc/KERBSQL :1433 TESTLLAB\kerbsqlaccount
setspn -A MSSQLSvc/KERBSQL.testllab.pragmantic :1433 TESTLLAB\kerbsqlaccount

setspn -A MSSQLSvc/KERBSSAS :1433 TESTLLAB\kerbssasaccount
setspn -A MSSQLSvc/KERBSSAS.testllab.pragmantic :1433 TESTLLAB\kerbssasaccount

Cette action permet au KDC de retrouver le service MSSQLSvc du serveur KERBSQL dans l'annuaire et de connaître le mot de passe à utiliser pour chiffrer le ticket de service (TGS).

Pour effectuer à nouveau les tests de bon fonctionnement, il faut au préalable s'assurer que le client ne contient pas dans son cache des tickets de session ayant des informations erronées. Pour purger le cache, il est possible d'utiliser l'utilitaire KList.exe. Cet utilitaire permet également de visualiser les tickets Kerberos et leurs propriétés présents dans le cache.

Klist.exe purge

V-B-2 - SPN ou délégation mal configurée

Si nous relançons à nouveau notre requête en quatre parties, nous obtenons encore le même message d'erreur que précédemment. Un coup d'œil sur les trames Kerberos via WireShark donne ceci :

…

Le KDC renvoie un message d'erreur différent cette foi-cis : KRB5KDC_ERR_BADOPTION avec un code NT Status : STATUS_NOT_SUPPORTED. La RFC 1510 indique que le code d'erreur KRB5KDC_ERR_BADOPTION signifie que le KDC ne peut pas traiter la demande de ticket, car quelque chose pose problème. Nous avons également comme précision STATUS_NOT_SUPPORTED.

On retrouve la même chose dans le journal d'événement :

Nous avons parlé de l'utilitaire Err.exe qui permet de retrouver la signification des messages d'erreurs associés à leur valeur hexadécimale. Cet utilitaire est proposé gratuitement en téléchargement par Microsoft. Celui-ci propose la description suivante pour le code d'erreur 0xc00000bb :

On peut maintenant se demander pourquoi nous avons ce message d'erreur. Nous avons paramétré correctement les SPN associés au compte de service des instances SQL Server KERBSQL et KERBSSAS, mais nous avons oublié une chose importante. Lorsque nous avons parlé du fonctionnement de la délégation, nous avons dit qu'il fallait que le serveur ou le service qui joue le rôle de délégateur soit autorisé à le faire, sans quoi le KDC n'accepterait pas la requête. C'est exactement ce qui se passe ici. Nous devons donc autoriser le compte de service kerbsqlaccount pour la délégation, car c'est ce service qui jouera ce rôle dans notre cas. Nous utiliserons le type de délégation la délégation contrainte dans notre second exemple (pour rappel, ce type de délégation n'est possible qu'à partir d'un niveau fonctionnel 2003 au niveau AD).

Je me permets d'attirer l'attention sur certains sites qui proposent des tutoriels sur la délégation Kerberos avec SQL Server. Beaucoup d'entre eux montrent comment autoriser la délégation au niveau du compte utilisateur et du serveur qui héberge l'instance SQL Server. Malheureusement certains sites Web que j'ai pu voir induisent en erreur le lecteur sur la configuration de la délégation et je retrouve souvent ce genre d'erreur soit chez les clients soit sur les forums. Nous allons profiter de notre deuxième exemple pour voir et comprendre quel est le problème. Si l'on suit ces tutoriels, on doit, pour autoriser le « double saut », configurer le compte utilisateur associé au compte de service SQL Server pour autoriser la délégation en utilisant la méthode suivante.

- Aller dans console d'administration des utilisateurs « utilisateurs et ordinateurs Active Directory ». On peut accéder directement à cette console en lançant dsa.msc dans une invite de commande.

- Sélectionner le compte utilisateur qui dans notre cas est kerbsqlaccount et sélectionner le menu « propriétés »

- Choisir l'onglet « délégation ». Cet onglet n'apparaît que si le niveau fonctionnel du domaine est au moins égal à 2003 et si le compte utilisateur concerné possède un SPN.

- Sélectionner l'option « N'approuver cet utilisateur que pour la délégation aux services spécifiés » et choisir la sous-option « Utiliser uniquement Kerberos ».

- Ajouter le type de service concerné pour la délégation. Ici l'on choisira le compte kerbsqlaccount avec le service MSSQLSvc.

Nous venons ci de permettre au compte de service kerbsqlaccount de présenter les informations d'identification du compte utilisateur au serveur KERBSQL.testllab.pragmantic. Si l'on exécute à nouveau la requête en quatre parties sur le serveur lié KERBSSAS on retrouve de nouveau le message d'erreur :

Msg 18456, Level 14, State 1, Line 1 Login failed for user 'NT AUTHORITY\ANONYMOUS LOGON'

Avec WireShark nous obtenons les messages suivants :

La demande du ticket de service (TGS-REQ) est la suivante :

Le serveur KERBSQL (192.168.92.41) fait une demande de ticket au KDC (TGS-REQ) pour pouvoir se connecter au service MSSQLSvc du serveur KERBSSAS. Cette demande fait bien partie d'un processus de délégation. L'option KDC Constrained Delegation permet de l'affirmer.

La réponse du KDC est :

Le KDC répond par le message d'erreur : KRB5KDC_ERR_BADOPTION - NT Status : STATUS_NO_MATCH. La signification du message à partir de la RC 1510 permet d'affirmer que le KDC ne peut pas délivrer de ticket de service à cause d'un mauvais paramétrage (BADOPTION). L'information supplémentaire de statut (NT Status) précise qu'il existe un problème de concordance dans les informations présentes dans la demande initiée par le serveur KERBSQL.

Le journal des événements indique le message suivant :

Avec l'utilitaire Err.exe nous pouvons voir à quoi correspond le code d'erreur 0xc0000272 :

Si l'on réfléchit un peu, nous avons, en principe, paramétré correctement les SPN pour chaque compte de service (kerbsqlaccount et kerbssasaccount). Nous avons également autorisé le compte de service kerbsqlaccount pour la délégation, donc on ne devrait pas avoir d'erreur. Cependant on peut remarquer que le processus de demande de ticket échoue lorsque le serveur KERBSQL demande le TGS, car le KDC détecte une erreur dans cette demande. On peut alors se demander si le serveur KERBSQL envoie les bonnes informations au KDC ou si celui-ci est autorisé. Maintenant si l'on regarde le détail de la demande, on voit que le service demandé est MSSQLSvc/kerbssas.testllab.pragmantic et c'est sur celui que la délégation doit s'opérer. Or nous n'avons pas paramétré ce service dans la console de gestion des utilisateurs tout à l'heure. À la place nous avons mis le service MSSQLSvc/kerbsql.testllab.pragmantic. C'est la raison pour laquelle le KDC détecte une erreur dans la demande. La présentation des informations de délégation est autorisée sur un service qui ne correspond pas à la demande du TGS.

Pour résoudre ce problème, il suffit donc de changer le service cible pour le compte utilisateur kerbsqlaccount. Il faut choisir le compte utilisateur kerbssasaccount et sélectionner le service MSSQLSvc associé comme le montre la figure ci-dessous.

L'exécution de la requête en quatre parties sur le serveur lié KERBSSAS fonctionne correctement.

La demande du TGS depuis le serveur KERBSQL est la suivante :

LA réponse du KDC est :

On remarque que le credential de l'utilisateur kerbuser est bien utilisé. Le ticket de service est bien destiné au serveur KERBSSAS. La délégation fonctionne parfaitement maintenant !!!

V-B-3 - SPN dupliqué

Un problème courant rencontré en entreprise est la duplication des SPN. En effet, il n'est pas rare d'avoir un changement de compte utilisateur pour un service donné et il n'est pas rare non plus d'avoir des problèmes liés à ce changement. En effet, pour que la délégation fonctionne, il faut associer le SPN du service SQL Server au nouveau compte utilisateur qui sera utilisé. Dans notre exemple, on créera le compte de domaine utilisateur kerbsqlaccount2. On lui associera le SPN associé au service SQL de l'instance KERBSQL.

setspn -A MSSQLSvc/KERBSQL :1433 TESTLLAB\kerbsqlaccount2
setspn -A MSSQLSvc/KERBSQL.testllab.pragmantic :1433 TESTLLAB\kerbsqlaccount2

Ensuite pour que SQL Server puisse utiliser ce nouveau compte utilisateur, il faut se rendre dans la console de gestion des configurations (configuration manager) et changer le compte utilisé par le service SQL Server sur le serveur KERBSQL :

Si l'on interroge à nouveau le serveur lié KERBSSAS nous obtenons à nouveau le message d'erreur suivant :

Si l'on récupère les trames Kerberos avec WireShark nous obtenons un message d'erreur lors de la réponse du KDC vers le serveur KERBSQL :

…

Nous retrouvons le même message d'erreur que lorsqu'il n'existait pas de SPN configuré pour le compte utilisateur utilisé par SQL Server. Ce message d'erreur signifiait que le KDC ne trouvait pas d'enregistrement associé au service demandé. Or ici le SPN existe, mais le KDC trouve plusieurs SPN associés au service MSSQLSvc/KERBSQL:1433. Dans ce cas il lui est impossible de savoir quel mot de passe il doit utiliser pour chiffrer la partie du ticket qui concerne l'authentification du client vers le service cible.

On peut également le voir dans le journal d'événement l'erreur suivante :

En utilisant l'utilitaire Err.exe on peut voir la description de l'erreur associée à la valeur hexadécimale 0xc0000035 :

STATUS_OBJECT _NAME_COLLISION signifie qu'il existe plusieurs SPN pour un service donné et qu'un conflit existe.

Depuis Windows Server 2008, il est possible de retrouver facilement les SPN en doublon grâce à l'utilitaire setspn.exe suivi du commutateur -X.

Avec des versions antérieures, il est possible d'utiliser l'utilitaire ldifde.exe pour récupérer tous les SPN associés au service MSSQLSvc pour un serveur donné. Par exemple il est possible de voir s'il existe un SPN dupliqué pour MSSQLSvc/KERBSQL ou MSSQLSvc/KERBSQL.testllab.pragmantic.

ldifde -t 3268 -d "dc=testllab,dc=pragmantic" -l serviceprincipalname -r "(serviceprincipalname=MSSQLSvc/KERBSSAS*)" -p subtree -f c:\spn_duplicate.txt

Il suffit ensuite d'ouvrir le fichier pour voir qu'il existe deux entrées pour le SPN qui nous intéresse :

dn: CN=kerbsqlaccount,CN=Users,DC=testllab,DC=pragmantic
changetype: add
servicePrincipalName: MSSQLSvc/KERBSQL.testllab.pragmantic:1433
servicePrincipalName: MSSQLSvc/KERBSQL:1433
servicePrincipalName: MSSQLSvc/KERBSSAS:1433
servicePrincipalName: MSSQLSvc/KERBSSAS.testllab.pragmantic:1433

dn: CN=kerbsqlaccount2,CN=Users,DC=testllab,DC=pragmantic
changetype: add
servicePrincipalName: MSSQLSvc/KERBSQL.testllab.pragmantic:1433
servicePrincipalName: MSSQLSvc/KERBSQL:1433

Dans le cas où l'on associe le SPN associé au service SQL de l'instance KERSSAS (qui concerne le serveur lié) au compte utilisateur kerbsqaccount2 via les commandes suivantes :

setspn -A MSSQLSvc/KERBSSAS :1433 TESTLLAB\kerbsqlaccount2
setspn -A MSSQLSvc/KERBSSASL.testllab.pragmantic :1433 TESTLLAB\kerbsqlaccount2

On peut trouver dans le journal d'événements du contrôleur de domaine le message suivant :

L'erreur est explicite. Il existe des doublons pour le SPN qui concerne le service SQL Server du serveur KERBSSAS. Comme précédemment, la solution est de détecter les doublons et de les supprimer.

VI - Conclusion

La délégation n'est pas une opération complexe en soi, comme nous avons pu le voir. Résoudre les problèmes qui lui sont associés est une tout autre affaire, car celle demande quelques connaissances sur le fonctionnement de la délégation et du protocole d'authentification Kerberos. Nous avons vu qu'il existait un panel d'outils qui peuvent nous aider dans cette tâche. Je finirai cet article pour une anecdote : un collègue m'a demandé récemment si la délégation Kerberos était difficile à mettre en place et après avoir réfléchi quelques instants voici ce que je lui ai dit : « Je pense que l'on peut comparer la délégation Kerberos avec son premier rendez-vous avec sa petite amie. Le premier rendez-vous est quelque chose de très important, car il faut que tout soit parfait, nous n’avons pas le droit à l'erreur. La moindre maladresse, la moindre faute d'inattention peuvent être fatales. La délégation c'est la même chose, si tout est correctement paramétré alors c'est gagné, mais s'il existe le moindre problème alors cela peut très vite devenir un enfer !!! »

VII - Webographie

- Kerberos Wikiperdia

- Kerberos - technet

- Kerberos - KB217098

- Kerberos - KB326985

- Troubleshooting Kerberos problems

- RFC 1510

- Kerberos V5 - RFC 1510

- WireShark Tool

- ldifde Tool

VIII - Bibliographie

- Troubleshooting Kerberos errors by Microsoft (March 2004)

- SQL Server MVP Deep Dives