Migrazione di account utente dalle attestazioni di Windows ad attestazioni SAML
Migrazione di account utente dalle attestazioni di Windows ad attestazioni SAML
Durante l'ultimo lavoro di cui mi sono occupato, ho notato che molti utenti hanno l'esigenza di iniziare a utilizzare le attestazioni di Windows, per passare in seguito alle attestazioni SAML. Sebbene sia una richiesta ragionevole, non esiste uno strumento predefinito che consenta di eseguire la migrazione degli account dalle attestazioni di Windows alle attestazioni SAML. Fortunatamente, il gruppo di prodotti per SharePoint aggiunto nell'aggiornamento del mese di agosto 2010 consente di eseguire codice personalizzato nel metodo MigrateUsers. A breve sarà disponibile un intero documento dedicato all'API, che include un esempio di codice tratto dall'eccellente lavoro di Bryan P. e Raju S., su cui è basato l'esempio fornito in questo blog. Poiché la nuova API (di fatto l'interfaccia IMigrateUserCallback) viene documentata in modo più che esauriente in tale articolo, non è necessario illustrarla in dettaglio anche in questo post. Appena sarà disponibile un collegamento alle nuove informazioni pubblicate lo aggiungerò al post.
Pertanto, comincio come di consueto incollando il codice della classe di migrazione personalizzata, quindi esaminerò in dettaglio le parti più interessanti.
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("https://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;
}
}
}
È innanzitutto necessario controllare il valore del parametro SPWebApplication.AuthenticationMethod passato al metodo. Poiché desidero convertire solo gli utenti delle attestazioni (da Windows a SAML), questa è l'unica situazione in cui deve essere eseguito il codice. Se l'utente corrente è un utente di attestazione, recupero innanzitutto un riferimento all'oggetto SPClaimProviderManager locale, in modo da ottenere una rappresentazione dell'utente basata sull'attestazione, per determinare se utilizza un'attestazione Windows, FBA o SAML. In questo caso, desidero convertire solo gli utenti delle attestazioni di Windows.
Dopo avere individuato un utente di questo tipo, devo stabilire se l'attestazione si riferisce a un utente o a un gruppo. Ora si verifica un fatto strano. Anche se l'utente corrente è un gruppo con attestazioni di Windows, il parametro isGroup passato al metodo restituisce false. Ciò significa che è necessario verificare direttamente se l'entità corrente è un utente o un gruppo. A tale scopo, basta verificare il valore dell'attestazione. Se si tratta di un utente, avrà formato dominio\utente, in caso contrario si tratta di un gruppo, con formato SID.
Dopo avere identificato il tipo di entità, è possibile determinare il tipo di attestazione necessario. Per un utente, è necessario creare un'attestazione d'identità. A tale scopo devo conoscere il nome dell'oggetto SPTrustedIdentityTokenIssuer utilizzato nell'applicazione Web. Avrei potuto scrivere il codice necessario per determinare tale valore, ma poiché si tratta semplicemente di un esempio, per brevità ho deciso di imporre all'utente di passare il nome corretto nel costruttore della classe. Quindi recupero il nome di accesso dell'utente (che segue il nome del dominio) e, per questo esempio, l'indirizzo di posta elettronica è sempre nomediaccesso@contoso.com. Se questa tecnica non è applicabile alla vostra organizzazione, dovrete utilizzare altre soluzioni per determinare l'indirizzo di posta elettronica corretto. Nel codice precedente l'indirizzo di posta elettronica viene utilizzato per creare un'attestazione d'identità per l'utente, ovvero il valore da restituire, che in questo caso è quello in cui deve essere convertito l'account vbtoys\darrins.
Per i gruppi, è necessario recuperare il SID fornito e utilizzare la classe NTAccount per ottenere il nome descrittivo del gruppo, che viene quindi utilizzato per creare una nuova attestazione relativa al ruolo. Il valore codificato di tale attestazione sarà quello a cui migrare il gruppo.
È importante ricordare che non è consigliabile eseguire automaticamente la migrazione di tutti gli account, sia per gli utenti che per i gruppi. A seconda delle vostre esigenze specifiche, esistono alcuni account che non è consigliabile migrare, come gli account di servizio e gli account predefiniti. Il vantaggio di questo metodo di migrazione è che può essere eseguito tutte le volte che se ne presenta la necessità. Potete eseguire la migrazione di un sottoinsieme di utenti, in batch, nel tempo o in qualsiasi altro modo desideriate. Se ad esempio disponete di un database che contiene tutti gli utenti da migrare, potete eseguire una query sul database per recuperare l'elenco e, quando un utente viene chiamato nel codice di migrazione, verificare se è incluso nell'elenco recuperato dal database. Questo comunque è solo un esempio.
Anche se non voglio addentrarmi eccessivamente nella documentazione dell'SDK scritta da Bryan e Raju, mi sento in dovere di spiegare almeno come viene chiamata la classe che abbiamo appena creato, per non lasciarvi troppo in sospeso. Ho creato una semplice applicazione Windows Form e ho aggiunto al progetto un riferimento all'assembly descritto in precedenza. Questo semplifica sia la compilazione che il debug. Il codice utilizzato per richiamare la classe ed eseguire la migrazione è simile al seguente.
//get a reference to my web application
SPWebApplication wa = SPWebApplication.Lookup(new Uri("https://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);
È tutto. Per coprire tutti gli scenari saranno necessarie molte altre varianti di questo codice, ma è già un buon punto di partenza. Inoltre, Bryan e Raju aggiungeranno molte altre funzionalità a questo progetto di base.
Questo è un post di blog localizzato. Consultate l'articolo originale: Migrating User Accounts from Windows Claims to SAML Claims