Migration des comptes d’utilisateur du mode revendications Windows vers le mode revendications SAML

Certains utilisateurs m’ont dit qu’ils souhaitaient démarrer en mode revendications Windows et passer ensuite en mode revendications SAML.  Cette idée n’est pas dénuée d’intérêt. Le problème est qu’il n’existait pas de solution prête à l’emploi pour effectuer cette migration.  La bonne nouvelle est que, dans la mise à jour cumulative d’août 2010, le groupe de produits SharePoint a ajouté des points de raccordement pour vous permettre d’exécuter votre propre code personnalisé dans la méthode MigrateUsers.  Nous disposons actuellement d’un document complet sur l’API qui va sortir prochainement, ainsi que d’un exemple de code issu du travail réalisé conjointement par Bryan P. et Raju S. Mon exemple à moi s’appuie sur ces travaux.  Bryan et Raju ayant documenté la nouvelle API de façon très approfondie (à l’heure actuelle, une interface IMigrateUserCallback), je n’aborderai pas ce sujet en détail dans ce billet de blog.  En revanche, je ne manquerai pas de vous indiquer le lien vers ce document dès qu’il me sera communiqué.

Bon, comme d’habitude, je vais commencer par coller le code de ma classe de migration personnalisée, puis je vais détailler les parties qui me semblent intéressantes.

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Diagnostics;

using System.Security;

using System.Security.Principal;

//add references to Microsoft.SharePoint and Microsoft.IdentityModel for these

using Microsoft.SharePoint;

using Microsoft.SharePoint.Administration;

using Microsoft.SharePoint.Administration.Claims;

using Microsoft.IdentityModel.Claims;

 

 

namespace MigrateUserSample

{

   public class MigrateTest : IMigrateUserCallback

   {

 

       public string SPTrustedIdentityTokenIssuerName { get; set; }

 

 

       public MigrateTest(string TrustedIdentityTokenIssuerName)

       {

          SPTrustedIdentityTokenIssuerName = TrustedIdentityTokenIssuerName;

       }

 

 

       public string ConvertFromOldUser(string oldUser,

              SPWebApplication.AuthenticationMethod authType, bool isGroup)

       {

          string value = string.Empty;

 

          try

          {

              switch (authType)

              {

                 case SPWebApplication.AuthenticationMethod.Windows:

                     //code for converting from classic Windows would be here

                     Debug.WriteLine(oldUser);

                     break;

                 case SPWebApplication.AuthenticationMethod.Claims:

                     //this is the only scenario this sample will cover

                     //migrating from Windows claims to SAML claims

                     Debug.WriteLine(oldUser);

 

                     //get the claim provider manager

                     SPClaimProviderManager cpm = SPClaimProviderManager.Local;

 

                     //create a claim from the identifier so we can see if the

                     //original issuer came from Windows

                     SPClaim idClaim = cpm.ConvertIdentifierToClaim(oldUser,

                           SPIdentifierTypes.EncodedClaim);

 

                     //this is a Windows claims user, and we are going to

                     //convert to a SAML claims user

                     if (idClaim.OriginalIssuer == "Windows")

                     {

                        //windows claims users will be in the format domain\user;

                        //windows claims groups will be in the SID format

                        if (idClaim.Value.Contains("\\"))

                        {

                           //migrating a user

 

                           //you will want to check the identity of the user here

                           //there may be some Windows claims accounts you don't want to

                           //convert yet, and there will also be service accounts that

                           //are passed in that you may not want to convert either; 

                           //ideally you would just read from a data source to determine

                           //which users you should convert, and then check the identity

                           //here to see if it's one of the users that should be

                           //converted

 

                           //in this case, I'm only converting one user - darrins

                           if (idClaim.Value == "contoso\\darrins")

                           {

                               //I’m getting an identity claim here, grabbing the

                               //part after the "domain\", and appending the email

                               //suffix to it, so it becomes darrins@contoso.com

                               SPClaim migratedUserClaim =

                                         SPClaimProviderManager.CreateUserClaim(

                                         idClaim.Value.Split('\\')[1] + "@contoso.com",

                                         SPOriginalIssuerType.TrustedProvider,

                                         SPTrustedIdentityTokenIssuerName);

 

                               //get the encoded value of what the new identity

                               //claim will be

                               value = migratedUserClaim.ToEncodedString();

                           }

                        }

                        else

                        {

                           //migrating a group

 

                           //get the plain name of the group

                           SecurityIdentifier sid =

                               new SecurityIdentifier(idClaim.Value);

                           NTAccount groupAccount =

                               (NTAccount)sid.Translate(typeof(NTAccount));

 

                           string groupName = groupAccount.ToString();

 

                           //only interested in migrating the Portal People group

                           if (groupName.ToLower() == "contoso\\portal people")

                           {

                               //create a new role claim

                               SPClaim migratedGroupClaim =

                                  new SPClaim("http://schemas.microsoft.com/ws/2008/06/identity/claims/role",

                                  groupName.Split('\\')[1],

                                  Microsoft.IdentityModel.Claims.ClaimValueTypes.String,

                                  SPOriginalIssuers.Format(

                                  SPOriginalIssuerType.TrustedProvider,

                                  SPTrustedIdentityTokenIssuerName));

 

                               //get the encoded value of what the new role claim will be

                               value = migratedGroupClaim.ToEncodedString();

                           }

                        }

                     }

 

                     break;

                 case SPWebApplication.AuthenticationMethod.Forms:

                     //code for converting from Forms would be here

                     Debug.WriteLine(oldUser);

                     break;

              }

          }

          catch (Exception ex)

          {

              Debug.WriteLine(ex.Message);

          }

 

          return value;

       }

   }

}

 

 

Je vais commencer par vérifier la valeur du paramètre SPWebApplication.AuthenticationMethod passé.  Comme seule m’intéresse la conversion des utilisateurs de revendications (Windows en SAML), c’est le seul cas où je dois exécuter du code.  Lorsque l’utilisateur actuel est un utilisateur de revendications, je commence par envoyer une référence au SPClaimProviderManager local afin d’obtenir une représentation des revendications de l’utilisateur.  Cela me permet de savoir s’il s’agit d’un utilisateur de revendications Windows, FBA ou SAML.  Dans le cas présent, je ne veux convertir que les utilisateurs de revendications Windows. 

 

Après avoir identifié le type de l’utilisateur de revendications, je dois déterminer si la revendication concerne un utilisateur ou un groupe.  À ce stade, vous risquez d’observer quelques bizarreries.  Même si l’utilisateur actuel est un groupe de revendications Windows, le paramètre isGroup passé dans la méthode renvoie false.  Cela signifie que je dois vérifier moi-même si « l’entité » actuelle est un utilisateur ou un groupe.  Il suffit pour cela d’examiner la valeur de la revendication. S’il s’agit d’un utilisateur, le format est : domain\user ; s’il s’agit d’un groupe, le format est un format SID.

Maintenant que je sais de quel type d’entité il s’agit, je suis en mesure de déterminer le type de revendication nécessaire.  Pour un utilisateur, je dois créer une revendication d’identité.  Pour cela, je dois connaître le nom du SPTrustedIdentityTokenIssuer utilisé sur l’application Web.  J’aurais pu écrire du code pour le savoir mais au lieu de cela, je vais me montrer un peu paresseux (il ne s’agit que d’un exemple après tout) et je vais vous obliger à passer le nom correct de ma classe dans le constructeur.  Je prends donc le nom de connexion de l’utilisateur (après la partie domaine) et, dans le cadre de cet exemple, son adresse électronique sera toujours loginname@contoso.com.  Si votre organisation ne fonctionne pas selon ce schéma, vous devrez utiliser votre propre méthode pour déterminer l’adresse électronique correcte.  Je l’utilise avec le code ci-dessus afin de créer une revendication d’identité pour cet utilisateur et c’est la valeur que je renvoie (dans mon exemple, c’est dans cette valeur que le compte vbtoys\darrins sera converti.  la grammaire n’est pas top, ce n’est pas grave...).

Pour les groupes, je prends le SID qui m’a été indiqué et j’utilise la classe NTAccount pour récupérer le nom convivial du groupe.  J’utilise le SID pour créer une revendication de rôle, puis j’en extraie la valeur codée vers laquelle le groupe sera migré.  (la grammaire, c’est mieux...)

Il y a un autre point à noter ici. Pour les utilisateurs comme pour les groupes, je n’essaie pas de tout migrer automatiquement.  Par exemple, vous ne voudrez peut-être pas migrer des comptes de service, des comptes intégrés, tout dépend de vos besoins.  Ce qu’il y a de bien dans cette méthode de migration, c’est que vous pouvez la mettre en œuvre aussi souvent que vous le souhaitez.  Si vous voulez migrer un sous-ensemble d’utilisateurs seulement, effectuer la migration par lots ou par étapes, c’est possible.  Par exemple, vous pourriez avoir une base de données contenant la liste de tous les utilisateurs que vous êtes supposé migrer.  Vous pourriez l’interroger pour récupérer la liste puis, à mesure que chaque utilisateur est appelé dans votre code de migration, vérifier si celui-ci est répertorié.  Voici un exemple illustrant ce cas de figure.

Bon, je ne veux pas entrer dans les détails de la documentation sur le SDK puisque Bryan et Raju s’y sont déjà employés, mais je tiens quand même à vous montrer comment votre classe est invoquée.  J’ai écrit une application WinForms et j’ai ajouté une référence de projet à l’assembly personnalisé décrit plus haut.  La construction et le débogage n’en seront que plus faciles.  Le code que j’utilise pour invoquer ma classe et effectuer une migration ressemble à ceci :

 

//get a reference to my web application

SPWebApplication wa = SPWebApplication.Lookup(new Uri("http://foo"));

 

//this is the name of my trusted identity token issuer

string SPTrustedIdentityTokenIssuerName = "ADFSProvider";

 

//create an instance of the custom migrate user callback class

MigrateUserSample.MigrateTest mt =

new MigrateUserSample.MigrateTest(SPTrustedIdentityTokenIssuerName);

 

//create an interface reference to it

IMigrateUserCallback muc = mt as IMigrateUserCallback;

 

//migrate the users with it

wa.MigrateUsers(muc);

 

Voilà.  Même si beaucoup d’autres variantes sont nécessaires pour traiter tous les cas de figure, cet exemple est un bon début ! N’oubliez pas de consulter par la suite la documentation rédigée par Bryan et Raju pour des informations détaillées.

Ce billet de blog a été traduit de l’anglais. L’article d’origine est disponible à la page Migrating User Accounts from Windows Claims to SAML Claims