Quelques commandes à connaître pour diagnostiquer les problèmes avec Kerberos

Il n’est pas toujours possible d’accéder à la console d’administration d’Active Directory pour consulter les SPNs configurés pour un compte ou pour connaître la liste des services permis pour la délégation.

Voici donc une liste d’outils “Command Line” qui peuvent vous aider à effectuer des diagnostics lorsque votre ami des TI est absent.

KList (C:\Windows\System32)

  1. klist: liste les “tickets” actifs pour le compte courant
  2. klist purge: vide la liste des “tickets” pour le compte courant

SetSpn (C:\Windows\System32)

  1. setspn –l nomcompte: liste les SPNs configurés pour un compte donné
  2. setspn –s nomservice nomcompte: ajoute un SPN au compte spécifié après avoir vérifié qu’il n’y a aucun doublon
  3. setspn –d nomservice nomcompte: supprime un SPN au compte spécifié
  4. setspn –X: Vérifie qu’il n’y a pas de doublons, c’est à dire un SPN enregistré sur plus d’un compte. La présence de doublons peut empêcher Kerberos de fonctionner.

Script PowerShell (Maison)

Il manquait une manière d’obtenir la liste des services autorisés pour la délégation pour un compte donné. Ce script PowerShell vous permet de le faire (en obtenant la liste des SPNs configurés du même coup):

.\ListKerberos.ps1 nomcompte

Merci à mon collègue Georges Turpin pour la trouvaille et l’adaptation.

Voici le contenu du script:

param (
[string]$UserID = $(throw « -UserID required. »)
)

$strUserName = $UserID
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$strFilter = « (&(objectCategory=User)(samAccountName= » + $strUserName + « )) »
$objSearcher.SearchRoot = $objDomain
$objSearcher.PageSize = 1000
$objSearcher.Filter = $strFilter
$objSearcher.SearchScope = « Subtree »
$colResults = $objSearcher.FindAll()

foreach ($objResult in $colResults)
{
$objUser = $objResult.GetDirectoryEntry()
$objUser.RefreshCache(@(« canonicalName »))

Write-host  »  servicePrincipalNames » -ForegroundColor Green

$i=1

foreach($SPN in $objUser.servicePrincipalName)
{
Write-host  »    SPN( » $i « )   =    » $SPN
$i+=1
}

Write-host «  »

    « – – – – – »

$objHash = @{}
$objHash.Add(« ADS_UF_SCRIPT », »&h0001″)
$objHash.Add(« ADS_UF_ACCOUNTDISABLE », »&h0002″)
$objHash.Add(« ADS_UF_HOMEDIR_REQUIRED », »&h0008″)
$objHash.Add(« ADS_UF_LOCKOUT », »&h0010″)
$objHash.Add(« ADS_UF_PASSWD_NOTREQD », »&h0020″)
$objHash.Add(« ADS_UF_PASSWD_CANT_CHANGE », »&h0040″)
$objHash.Add(« ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED », »&h0080″)
$objHash.Add(« ADS_UF_TEMP_DUPLICATE_ACCOUNT », »&h0100″)
$objHash.Add(« ADS_UF_NORMAL_ACCOUNT », »&h0200″)
$objHash.Add(« ADS_UF_INTERDOMAIN_TRUST_ACCOUNT », »&h0800″)
$objHash.Add(« ADS_UF_WORKSTATION_TRUST_ACCOUNT », »&h1000″)
$objHash.Add(« ADS_UF_SERVER_TRUST_ACCOUNT », »&h2000″)
$objHash.Add(« ADS_UF_DONT_EXPIRE_PASSWD », »&h10000″)
$objHash.Add(« ADS_UF_MNS_LOGON_ACCOUNT », »&h20000″)
$objHash.Add(« ADS_UF_SMARTCARD_REQUIRED », »&h40000″)
$objHash.Add(« ADS_UF_TRUSTED_FOR_DELEGATION », »&h80000″)
$objHash.Add(« ADS_UF_NOT_DELEGATED », »&h100000″)
$objHash.Add(« ADS_UF_USE_DES_KEY_ONLY », »&h200000″)
$objHash.Add(« ADS_UF_DONT_REQUIRE_PREAUTH », »&h400000″)
$objHash.Add(« ADS_UF_PASSWORD_EXPIRED », »&h800000″)
$objHash.Add(« ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION », »&h1000000″)

[string]$intUAC = $objUser.userAccountControl.Value

Foreach ($objKey in $objHash.Keys)
{
[string]$intKey = $objHash.Item($objKey)

If (($intUAC -bAnd $intKey) -ne 0)
{
switch ($objKey)
{
« ADS_UF_SCRIPT »{« The logon script is executed. »}
« ADS_UF_ACCOUNTDISABLE »{« The user account is disabled. »}
« ADS_UF_HOMEDIR_REQUIRED »{« The home directory is required. »}
« ADS_UF_LOCKOUT »{« The account is currently locked out. »}
« ADS_UF_PASSWD_NOTREQD »{« No password is required. »}
« ADS_UF_PASSWD_CANT_CHANGE »{« The user cannot change the password. « }
« ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED »{« The user can send an encrypted password. »}
« ADS_UF_TEMP_DUPLICATE_ACCOUNT »{« This is an account for users whose primary account is in another domain. »}
« ADS_UF_NORMAL_ACCOUNT »{« This is a default account type that represents a typical user. »}
« ADS_UF_INTERDOMAIN_TRUST_ACCOUNT »{« This is a permit to trust account for a system domain that trusts other domains. »}
« ADS_UF_WORKSTATION_TRUST_ACCOUNT »{« This is a computer account for a computer that is a member of this domain. »}
« ADS_UF_SERVER_TRUST_ACCOUNT »{« This is a computer account for a system backup domain controller that is a member of this domain. »}
« ADS_UF_DONT_EXPIRE_PASSWD »{« The password for this account will never expire. »}
« ADS_UF_MNS_LOGON_ACCOUNT »{« This is an MNS logon account. »}
« ADS_UF_SMARTCARD_REQUIRED »{« The user must log on using a smart card. »}
« ADS_UF_TRUSTED_FOR_DELEGATION » { « DELEGATION – Trust this user for delegation to any service (Kerberos only). » }
« ADS_UF_NOT_DELEGATED »
{
« DELEGATION – Trust this user for delegation to specified services only (use any protocol): »
$objUser.properties[« msDS-AllowedToDelegateTo »]
}
« ADS_UF_USE_DES_KEY_ONLY »{« Restrict this principal to use only Data Encryption Standard (DES) encryption types for keys. »}
« ADS_UF_DONT_REQUIRE_PREAUTH »{« This account does not require Kerberos pre-authentication for logon. »}
« ADS_UF_PASSWORD_EXPIRED »{« The user password has expired. »}
« ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION »
{
« DELEGATION – The account is enabled for delegation: »
$objUser.properties[« msDS-AllowedToDelegateTo »]
}
default {« Could not find the UAC »}
}
}
}
}

Est-ce que cette information vous a été utile? Utilisez-vous d’autres outils? N’hésitez pas à commenter …

Publicités

Oui vous pouvez utiliser C2WTS sur un serveur unique (Single Server Install) avec SharePoint 2013

Problématique

Un article de TechNet crée de la confusion au niveau de la configuration de SharePoint 2013 lorsque tout est sur le même serveur.

Le paragraphe suivant est le coupable:

Note: Some of the configuration steps may change, or may not work in certain farm topologies. For instance, a single server install does not support the Windows Identity Foundation C2WTS services so claims to windows token delegation scenarios are not possible with this farm configuration.

Ou en français:

Remarque : certaines étapes de configuration peuvent changer, ou peuvent ne pas fonctionner dans certaines topologies de batteries de serveurs.  Par exemple, une installation de serveur unique ne prend pas en charge les services C2WTS Windows Identity Foundation, c’est pourquoi les scénarios de délégation de jetons Windows ne sont pas possibles avec cette configuration de batterie de serveurs.

Cela laisse sous-entendre que la sécurité de données (SSAS) ne peut être utilisée avec SharePoint 2013, SSRS et SSAS. Il faudrait donc configurer les sources de données pour utiliser un compte en particulier ce qui empêcherait de retourner des données différentes selon l’utilisateur du rapport.

Plusieurs forums discutent de cette affirmation donc celui-ci. Une hypothèse est que Single Server Install a probablement été inversé pour “Standalone” qui signifie que Windows Internal Database est utilisée plutôt qu’une vrai version de SQL Server.

Solution

Peu importe, nous l’avons testé et cela fonctionne parfaitement!

Dans mon article Reporting Services 2012 et la configuration Kerberos: désolé vous devrez utiliser la constrained delegation avec C2WTS je disais que dès que C2WTS est utilisé, la constrained Kerberos delegation doit être utilisée. Je maintiens mon affirmation avec l’exception suivante: pas si tout est sur le même serveur.

Quand tout est sur le même serveur, utilisez vos comptes de services réguliers qui délèguent vers “Any Services”:

Service Compte
SQL Server (engin relationnel) cs-sql
Analysis Services cs-ssas
Reporting Services cs-ssrs ou cs-web
SharePoint (Web Apps) cs-web
C2WTS Local System

La clé pour que cela fonctionne sur un seul serveur est d’utiliser “Local System” comme compte de service pour C2WTS.

Si vous utilisez un compte de domaine pour C2WTS ça ne fonctionnera pas. Vous n’avez même pas besoin de configurer la délégation Kerberos pour le serveur (i.e. servername$).

Cela vous permettra d’avoir le scénario suivant:

  1. Frédérick demande l’affichage d’un rapport SSRS 2012 stocké dans SharePoint 2013.
  2. IIS l’authentifie via Windows Authentication et la plomberie Microsoft .NET convertira le jeton Windows en Claim.
  3. SharePoint et SSRS fonctionnent en claims.
  4. Puis lorsqu’il est temps d’interoger la source de données (SSAS) il faut obtenir une identité Windows car SSAS n’est pas Claim-Aware. C’est là qu’intervient C2WTS et celui-ci génère un jeton pour Frédérick qu’il envoie à SSAS.
  5. SSAS peut donc retourner les données propres à Frédérick (sécurité de données).

image

Le déploiement sur un seul serveur est pratique pour réaliser des tests ou pour des solutions de moindres envergures.

J’espère donc que cet article contribura à réduire la confusion sur ce sujet.

Et vous, utilisez-vous les déploiement sur un seul serveur avec de la sécurité de données?

Références

Claims to Windows Token Service (C2WTS)
http://technet.microsoft.com/en-us/library/hh231678.aspx

Claims to Windows Token Service (c2WTS) Overview
http://msdn.microsoft.com/en-us/library/ee517278.aspx

Does C2WTS work on a single server install??
http://social.technet.microsoft.com/Forums/sharepoint/en-US/85bd9bf4-ce25-4faf-85ea-6e3bbf081f24/does-c2wts-work-on-a-single-server-install?forum=sharepointadminprevious

Comment impersonifier temporairement l’identité du AppPool en ASP.Net

Il est fréquent d’impersonifier l’identité du l’utilisateur dans une application ASP.Net MVC. L’application est personnalisée ou sécuritée par utilisateur ce qui nous empêche d’impersonifier un compte de service précis.

Normalement, avec une connaissance de Kerberos, il est facile de faire en sorte que l’identité de l’utilisateur voyage jusqu’aux différents serveurs de données (SQL Server, Analysis Services etc.).

Mais dans certains cas, la délégation Kerberos n’est pas envisageable. C’est en autre le cas pour l’API qui se trouve dans System.DirectoryServices. Cet API permet d’interroger Active Directory afin d’obtenir les groupes dont un utilisateur fait partie ou d’aller chercher des propriétés etc.

Même si cet API est en .NET, ça semble utiliser des fonctonnalités COM et il semblerait que la délégation Kerberos n’est pas supportée dans ce scénario. En effet, lors d’un Double Hop, l’erreur suivante est obtenue lors de l’utilisation des classes de System.DirectoryServices:

[COMException (0x80072020): An operations error occurred. ]

Le KB329986propose des solutions mais aucune ne nous semblait acceptable pour notre besoin (ex. utiliser l’authentification basique).

Heureusement, nos applications ASP.Net MVC s’exécutent sous un AppPool ayant une identité d’un compte de domaine (le même que pour SharePoint lorsque l’application MVC est hébergée sous SharePoint). Il est possible d’exécuter un bloc de code sous l’identité du compte de service du AppPool en utilisant:

using (HostingEnvironment.Impersonate()) {

// Ce code s’exécute avec l’identité
// assignée au pool d’application (AppPool)

DirectorySearcher searcher …
}

Il faut ajouter une référence àSystem.Web.dll et faire un usingSystem.Web.Hosting.

Cette technique a l’avantage de contrôler les lignes de code devant s’exécuter sous le compte du AppPool. Tout le reste peut continuer de s’exécuter sous l’identité de l’utilisateur du fureteur.

Dans le cas précis de l’accès à Active Directory, cette technique offre un autre avantage. Plutôt que d’avoir à donner accès en lecture à Active Directory à tous vos utilisateurs, vous pouvez accorder ce droit uniquement au compte de domaine assigné au AppPool.

Références

How to use the System.DirectoryServices namespace in ASP.NET

Intégrer une application ASP.Net MVC 3 sous un site Web IIS hébergeant SharePoint Server 2010

SharePoint Foundation / Server 2010 utilisent le .NET Framework 3.5. Même si le pool d’application indique 2.0, SharePoint charge la version 3.5.

image

Les projets de développement Web récents utilisent souvent ASP.Net MVC 3 avec le .NET Framework 4.0. J’avais donné la recette pour intégrer ce type de projet sous WSS 3.0 / SharePoint 2007 mais il y a quelques étapes qui sont différentes avec 2010. En bleu j’ai mis les nouveaux éléments et en orange ceux qui sont un peu différents. Les étapes qui ne sont pas nécesaires ont été enlevées tout simplement.

  1. Vous devez créer un “Application Pool” utilisant le “.NET Framework 4.0” et empruntant la même identité (le même compte de service) que l’ “Application Pool” de SharePoint.Puisque le site IIS a un SPN unique (ex. HTTP/nomgentil.domaine.com), celui-ci est déjà défini sur le compte de service en question. Ainsi, il suffira d’ajouter la déléguation vers SQL Server ou SSAS à ce compte selon ce que fait l’application ASP.Net.
  2. Vouspouvezcopier le répertoire de votre application ASP.Net sous le répertoire contenant SharePoint. Ex. C:\Inetpub\wss\nomgentil.domain.com\ApplicationMVCNote: Vous pouvez le mettre ailleurs mais cela fonctionne très bien à cet endroit.
  3. Les permissions par défaut ne sont pas les même que pour les sites placés directement sous C:\Inetpub alors assurez-vous de donner les permissions Windows à Users ou autre au répertoire de votre application MVC.
  4. Il faut convertir le virtual directory en application dans IIS en prenant bien soin d’utiliser le pool d’application défini précédemment.
  5. Une application ASP.Net utilise un fichier Web.Config afin de configurer différents éléments propres à .Net. Ce qu’il faut savoir c’est qu’il y a un lien d’héritage entre les Web.Config des applications Web. Ainsi si l’application B est placée sous l’application A dans IIS, elle hérite du Web.Config.Le problème c’est qu’en étant sous SharePoint, on hérite de certains éléments incompatibles avec une application utilisant le “.NET Framework 4.0”.

    Il faut donc modifier le web.config de SHAREPOINT pour indiquer qu’on ne souhaite pas hériter de certaines sections dans les sites enfants. Plus spécifiquement, il faut entourer les noeuds <microsoft.sharepoint.client>, <SharePoint>,  <system.web>, <System.Workflow.ComponentModel.WorkflowCompiler>, <ReportingServices>, <system.web.extensions>, <Bpm> et <reportserver> d’un noeud <location path=”.” inheritInChildApplications=”false”>. Par exemple:

    <location inheritinchildapplications= »false » path= ». »>
    <system.web>…</system.web>
    </location>

     

  6. Il faut maintenant déplacer l’élément Xml <sectionGroup> nommé “system.web.extensions” du Web.Config de SharePoint vers le Web.Config qui se trouve à cet endroit: C:\Windows\Microsoft.NET\Framework64\v2.0.50727\CONFIG\Web.Config.

    On doit le mettre sous le noeud <configSections> directement sous <configuration>:

    <configuration>
    <configSections>
    <sectionGroup name= »system.web.extensions » …

    La raison est que le site ASP.Net MVC 3 .NET 4 hérite du Web.Config de SharePoint et ce sectionGroup cause une erreur. On ne peut pas utiliser l’élément <location> à cet endroit. En déplaçant la déclaration directement dans le Web.Config du .NET Framework 2.0, SharePoint en héritera mais pas notre application ASP.Net.

    Vous pouvez obtenir plus d’information ici. Un extrait:

    Move the configSections definition in the Web.config file of the parent application (the application that runs ASP.NET 2.0 or ASP.NET 3.5) into the root Web.config file for the.NET Framework 2.0. The IIS 7 and IIS 7.5 native configuration system scans the configSections element when it merges the hierarchy of configuration files. Moving the configSections definition from the parent Web application’s Web.config file to the root Web.config file effectively hides the element from the configuration merge process that occurs for the child ASP.NET 4 application.

  7. On hérite aussi des Modules du site SharePoint et ceux-ci causent une erreur (en particulier SharePoint14Module). La solution est d’utiliser ce noeud <modules> dans votre application ASP.Net:

    <modules runAllManagedModulesForAllRequests= »true »>
    <remove name= »SPRequestModule » />
    <remove name= »PublishingHttpModule » />
    <remove name= »RSRedirectModule » />
    <remove name= »StateServiceModule » />
    <remove name= »SharePoint14Module » />
    <add name= »Session » type= »System.Web.SessionState.SessionStateModule » />
    </modules>

    Notez qu’en plus d’enlever les modules spécifiques à SharePoint, on réactive la gestion des Session. Si vous ne le faites pas, vous ne pourrez pas utiliser l’objet Session.

    En fait, comme on ne peut pas utiliser la clause <location> pour <system.webServer>, il faut défaire ce qui est fait par SharePoint. Il se peut que votre implantation nécessite d’activer / désactiver certains modules / “Http Handlers”. Voici un extrait de ce que SharePoint active / désactive:

    <modules runAllManagedModulesForAllRequests= »true »>
    <remove name= »AnonymousIdentification » />
    <remove name= »FileAuthorization » />
    <remove name= »Profile » />
    <remove name= »WebDAVModule » />
    <remove name= »Session » />
    <add name= »SPRequestModule » … />
    <add name= »ScriptModule »  … />
    <add name= »SharePoint14Module » … />
    <add name= »StateServiceModule » … />
    <add name= »RSRedirectModule » … />
    <add name= »PublishingHttpModule » … />
    </modules>
    <handlers>
    <remove name= »OPTIONSVerbHandler » />
    <remove name= »WebServiceHandlerFactory-Integrated » />
    <remove name= »svc-Integrated » />
    <remove name= »WebDAV » />
    <add name= »svc-Integrated » … />
    <add name= »OwssvrHandler » … />
    <add name= »ScriptHandlerFactory » … />
    <add name= »ScriptHandlerFactoryAppServices » … />
    <add name= »ScriptResource » …  />
    <add name= »JSONHandlerFactory » … />
    <add name= »ReportViewerWebPart » … />
    <add name= »ReportViewerWebControl » … />
    </handlers>

     

  8. IIS Reset
  9. Si vous avez une erreur qui dit que le fichier de configuration n’est pas accessible, donnez temporairement les droits en lecture au groupe local IIS_IUSRS sur ce fichier (l’erreur indique le chemin d’accès).

    Quand IIS n’arrive pas à déterminer l’authentification utilisée (ex. il y a un nœud dupliqué dans les web.config parent et enfant), il doit avoir accès en mode anonyme. Après l’erreur qui sera affichée sera détaillée (ex. le nœud qui ne peut être redéfini etc.)

  10. Si vous avez une erreur HTTP 500 ou une page blanche, même avec customErrors à OFF, vous pouvez utiliser la fonctionnalité des Failed Request Tracing (FREB). Voici comment l’activer pour un site / application.

    C’est ainsi que j’ai su qu’il me fallait désactiver le module SharePoint14Module:

    Request Diagnostics HTTP 500

Bref, oui c’est possible de mettre une application ASP.Net MVC 3 sous SharePoint 2010 mais il faut quand même effectuer un certain nombre de manipulations …

Bonne chance et à la prochaine …