Windows 클레임에서 SAML 클레임으로 사용자 계정 마이그레이션

최근 진행했던 작업에서 알게 된 사용자 중에는 일단 Windows 클레임 사용자로 시작했다가 나중에 SAML 클레임을 사용하도록 전환하는 사용자들이 많았습니다. 이 경우 Windows 클레임에서 SAML 클레임으로 계정을 손쉽게 마이그레이션할 수 있는 방법이 없다는 것이 문제입니다. 2010년 8월의 CU에 추가된 SharePoint 제품 그룹을 사용하면 MigrateUsers 메서드에서 자체 사용자 지정 코드를 실행할 수 있습니다. Bryan P. 및 Raju S.가 작성한 훌륭한 코드 샘플이 포함된 API 관련 전체 문서가 곧 제공될 예정입니다. 저의 샘플도 이 코드 샘플을 기반으로 하고 있습니다. Bryan과 Raju가 새로운 API(실제로는 IMigrateUserCallback 인터페이스)를 적절하게 문서로 작성했기 때문에 여기서는 해당 내용을 자세히 설명하지 않겠습니다. 새롭게 게시되는 정보에 대한 링크가 제공되면 해당 링크를 포함하여 이 게시물을 업데이트하겠습니다.

따라서 여기서는 평소대로 제가 작성한 사용자 지정 마이그레이션 클래스의 코드에 붙여 넣은 다음, 확인할 필요가 있는 부분에 대해 설명하겠습니다.

 

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;

       }

   }

}

 

 

먼저 전달된 SPWebApplication.AuthenticationMethod 매개 변수의 값을 확인합니다. 클레임 사용자만 변환(Windows에서 SAML로)할 것이므로 해당 작업에서만 코드를 실행하면 됩니다. 현재 사용자가 클레임 사용자이면 해당 사용자의 클레임 표현을 가져올 수 있도록 먼저 로컬 SPClaimProviderManager에 대한 참조를 가져옵니다. 이렇게 하면 사용자가 Windows 클레임 사용자인지, FBA 클레임 사용자인지 아니면 SAML 클레임 사용자인지를 확인할 수 있습니다. 여기서는 Windows 클레임 사용자만 변환할 것입니다. 

 

클레임을 확인한 후에는 해당 클레임이 사용자용인지 그룹용인지를 확인합니다. 여기서 다소 혼란이 발생할 수 있는데요, 현재 사용자가 Windows 클레임 그룹인 경우에도 메서드로 전달되는 isGroup 매개 변수는 false로 반환됩니다. 즉, 현재 "엔터티"가 사용자인지 그룹인지를 직접 확인해야 합니다. 따라서 클레임 값을 확인해야 합니다. 엔터티가 사용자인 경우에는 도메인\사용자 형식이고, 이 형식이 아니라 SID 형식인 경우에는 엔터티가 그룹입니다.

엔터티 유형이 확인되었으면 필요한 클레임 유형을 결정할 수 있습니다. 사용자의 경우에는 ID 클레임을 만들어야 합니다. 이렇게 하려면 웹 응용 프로그램에서 사용되고 있는 SPTrustedIdentityTokenIssuer의 이름을 알아야 합니다. 이름 확인을 위한 코드를 작성할 수도 있지만, 이 코드는 샘플이므로 간단하게 유지하기 위해 클래스 생성자에 정확한 이름을 전달할 것을 지시합니다. 따라서 사용자의 로그인 이름(도메인 부분 뒤에 있음)을 가져옵니다. 이 코드의 용도상, 사용자의 전자 메일 주소는 항상 loginname@contoso.com이 됩니다. 조직에서 이러한 전자 메일 주소를 사용하지 않는 경우에는 고유한 방법으로 올바른 전자 메일 주소를 확인해야 합니다. 위의 코드에서는 이 전자 메일 주소를 사용하여 해당 사용자의 ID 클레임을 만들었습니다. 그리고 코드에서는 이 값이 반환됩니다. 즉, vbtoys\darrins 계정이 이 전자 메일 주소로 변환됩니다.

그룹의 경우에는 제공된 SID를 가져온 다음 NTAccount 클래스를 사용하여 그룹 이름을 가져옵니다. 이 이름을 사용하여 새 역할 클레임을 만든 후에, 그룹을 마이그레이션할 값으로 해당 클레임에서 인코딩된 값을 가져옵니다.

여기서는 사용자 및 그룹 둘 다에 대해 모든 항목을 자동으로 마이그레이션하지 않습니다. 서비스 계정, 기본 제공 계정 등 마이그레이션하지 않으려는 항목도 있기 때문입니다. 이러한 항목을 마이그레이션할지 여부는 요구 사항에 따라 달라집니다. 이와 같은 마이그레이션 수행 방법의 이점은 작업을 원하는 횟수만큼 수행할 수 있다는 것입니다. 사용자 하위 집합만 마이그레이션하거나 사용자를 일괄로 마이그레이션하는 등 원하는 어떤 작업이든 수행할 수 있습니다. 예를 들어 모든 사용자를 마이그레이션할 데이터베이스가 있는 경우 해당 데이터베이스를 쿼리하여 목록을 가져온 다음 마이그레이션 코드에서 각 사용자가 호출되면 사용자가 데이터베이스에서 가져온 사용자 목록에 들어 있는지를 확인하면 됩니다. 위의 코드가 이러한 마이그레이션의 한 예입니다.

앞서 언급한 것처럼, 여기서는 Bryan과 Raju가 공들여 작성한 SDK 설명서의 내용을 다루지는 않겠습니다. 그러나 여러분이 어러움을 느끼지 않도록 최소한 클래스가 호출되는 방식은 설명해야 할 것 같습니다. 이를 위해 winforms 응용 프로그램을 작성한 다음 위에서 설명한 사용자 지정 어셈블리에 대한 프로젝트 참조를 추가합니다. 이렇게 하면 매우 쉽게 빌드와 디버그를 함께 수행할 수 있습니다. 그런 후에 클래스를 호출하고 마이그레이션을 수행하는 데 사용하는 코드는 다음과 같습니다.

 

//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);

 

어때요, 간단하죠? 모든 시나리오를 다루려면 이 코드를 다양하게 변형해야 할 것입니다. 그러나 이 코드를 기반으로도 간단한 작업은 수행할 수 있으며, Bryan과 Raju가 작성한 관련 설명서에서는 이 게시물의 내용보다 훨씬 많은 코드를 추가로 설명합니다.

이 문서는 현지화된 블로그 게시물입니다. 원본 문서는 Migrating User Accounts from Windows Claims to SAML Claims를 참조하십시오.