Recommended Blog Post: The good, the bad and sIDHistory

Based on various experiences with Exchange 2010 behavior after an Exchange and Active Directory Inter Forest Migration, Exchange PRO Ingo Gegenwarth published this interesting Post:

The clueless guy

This post is about my personal journey with a cross-forest migration.

When it comes to account migration there is no way to do so without sIDHistory. It would be really hard to have a smooth migration without.

By using this attribute a end-user most likely won’t experience any impact…..unless you start doing a cleanup of this attribute.

In terms of Exchange users might see something like this

Calendar_Error

or this

Inbox_Error

But what’s behind those issues and how could you mitigate this? I was part of a migration, where those issues popped up and I’m going to describe how you could determine possible impact for end-users before it happens.

View original post 3,675 more words

How to write or migrate sidHistory with Powershell (3)

In our large scale Active Directory Cross Forest migration project, we now have migrated already 40.000 user accounts globally. Our self made scripting routine to migrate/write sidHistory into the target accounts turned out to be a robust, reliable part of the process and I feel safe now to share some experiences. We are running it on multiple migration servers around the globe as scheduled task – which you can easily call a “service” as it is running every 5 minutes.
I will write about the whole mechanism of how we automated our large scale Active Directory migration in another blog post, but will concentrate here to share our way of managing the sidHistory part.
As you know already from part 2 of this blog post, we were buidling our code on the examples that MSFT Jiri Formacek published here.

However, 2 main restrictions prevented us from using this code as is:

  1. We wanted to make sure that we really used the Domain Controller with the PDC Emulator role from source domain. Our source environment has 100+ domain controllers and the PDC role is siwtched from one DC to another DC under certain conditions. Therefore to use a fixed name for the PDC role Domain Controller was not acceptable.
  2. Our Active Directory account migration process was fully automated and it was the user who starts his/her migration not us. Therefore the requirement was given, that we only can run sidHistory migration (together with the account activation in target domain) as a continuous background service. Every session based approach would not have helped like we can find it in ADMT or Dell Migration Manager for Active Directory.
    Prepopulating sidHistory on the previously created disabled accounts in target domain was not an option, since Exchange 2010 was giving errors for disabled users with sidHistory of source active users under certain circumstances.

Solutions:
1) This was not a big thing. A small function could do the trick.

function getPDCE($domain) {
$context = new-object System.DirectoryServices.ActiveDirectory.DirectoryContext("domain",$domain)
$PDC=[System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($context).PdcRoleOwner.Name
return $PDC
} 

2) This was not that easy (for us). Running our account migration script as usual – means as scheduled task with admin credentials – did not work for the sidHistory part in it since the credentials of the logged user account were not handed over to the SIDCloner routine.
All the code we could find on Jiri’s page asked for credential information interactively or would need explicit credentials in the script in another way.
Although we are packaging our Powershell Scripts into an .exe file by using Sapien Powershell Studio and could hide the password from simple file editing, putting user name and password into the script was not an acceptable way for us to go.
After testing back and forth, someone cam up with the idea of using the Windows credential manager to work around our deadlock situation.
The script would access the credential manager interface, get the credential information from there and would then pass them to the DsAddSidHistory function.
We created a function to retrieve credentials from Credential Manager store based on a very good script example to be found on Technet here.
While this seemed to be a clever way of achieving our target of having a scheduled user account activation script with sidHistory functionality, we ran into errors again. Retrieving credentials from Credential Manager by script obviously fails, when the script runs with exactly the credentials that you want to retrieve. This was true in our case, because the user account migration script was scheduled with that “big admin” account.

The solution finally was:
The user account migration script was running as a scheduled task with full admin credentials. When it came to migrate (in our project setup: activate) a user account in the target domain, it did not (could not) write sidHistory, but created an input file with username and target DC (the DC closest to the site where the user was had logged in from – remember that the user triggers his/her migration in our project).
On the same migration server a second script was scheduled with a server-local admin account. This script consists of 3 parts. First part is to check if there are new input files. Second part is to retrieve the full admin credentials from Credential manager and passing them to second part. Third part is to migrate sidHistory which succeeds because you have put all parts together for the SIDCloner routine:
PDC Emulator DC for source you have found by query.
Target DC was in file (but you can take every writable you want if replication delay does not matter).
Explicit credentials you get from Credential Manager.
Nowhere in both scripts password information is saved in clear text.

Additional Information

Active Directory Migration – How to remove sidHistory after migration – Part 2

As mentioned in my previous blog post regarding SID history, SID history can be both, burden and blessing. The recommendation from Microsoft is to clean up sidHistory from your accounts when migration is finished and all your Windows network resources have been re-ACLed (permissions of source domain accounts SIDs have been replaced by permissions of target domain SIDs).

Although it is not possible to remove sidHistory values like many other attribute values in Active Directory by using ADSIEDIT, LDAP or ADUC, there are still several ways to achieve this goal.

Caution: There is a big difference in how the tools handle the cleanup. Since sidHistory is a multi-value attribute and contain several SIDs from prior migrations, you might want to delete only SIDs related to specific domains.

Some of the tools erase the complete sidHistory value, some provide the option to delete selectively if there are multiple SIDs in the sidHistory.

1.Option: Use VB Script from Microsoft Support

DELETING SELECTIVELY: NO

For a very long time, a VB script is available from Microsoft support, which can be used to remove sidHistory. The raw version of this script is not very comfortable. You might need to adjust the coding.

The script can be downloaded here:

http://support.microsoft.com/kb/295758

Usage for ClearSidHistory.vbs is as follows:

cscript.exe ClearSidHistory.vbs -n=<name> [-o=<objectCategory>] [-c=<objectClass>]

-n=<name of the object you are looking for>

-o=<objectCategory of the object you are looking for>

-c=<objectClass of the object you are looking for>

Examples:

cscript.exe ClearSidHistory.vbs -n=My Contact

cscript.exe ClearSidHistory.vbs -n=Computer1 -o=computer

cscript.exe ClearSidHistory.vbs -n=James Smith -o=Person -c=user

Recommendation:

IT-Pro Arne Scherhag provides an extended version of this VB Script here:

http://www.winmigrationsite.de/sites/default/files/clearSidHistory_0.zip

2.Option: Use Microsoft Active Directory Module for Powershell

DELETING SELECTIVELY: NO

If you are used to the Active Directory Powershell commandlets, you can also delete sidHistory values programmatically.

Examples:

Delete sidHistory values in all user objects of the domain:

Get-ADUser –filter ‘sidhistory –like “*”’ –searchbase “dc=name,dc=name” –searchscope subtree –properties sidhistory | foreach {Set-ADUser $_ -remove @{sidhistory=$_.sidhistory.value}}

3.Option: Use Quest Active Roles Management Shell for Active Directory commandlets

DELETING SELECTIVELY: NO

If your scripting is based on Quest Active Directory Powershell extensions, you also can use the get-qaduser and get-qadgroup commands to erase the sidHistory values.

Example:

Get-QADUser “john wayne” | %{Set-QADUser $_ -ObjectAttributes @{sIDHistory=@{delete=$_[‘sIDHistory’]}}}

In Part 3 of this blog post, we will have a look at the tools which can selectively delete sidHistory.

Active Directory Migration – How to remove sidHistory after migration – Part 1

About sidHistory

In almost all Active Directory Inter-Forest migration scenarios the sidHistory functionality of Windows Server plays an important role to maintain resource access from migrated users to their not yet migrated Windows resources (e.g. file shares, Exchange mailbox etc.).

The sidHistory attribute of a migrated user in the target domain contains the SID of the original user from the source domain. When the user logs on with his/her account to the target Active Directory domain, the security token generated by the DC, contains both, the SID of the actively logged on target user account and the SID of the source user account of the source domain. If the user now accesses resources in the source domain, the target account and the source account SID are presented for ticket granting process. This ensures that the user can use his/her resources seamlessly, no matter if the resources are located in the source Forest or are migrated to target Forest already. An alternative to using sidHistory is the re-ACLing of the resources in the source Forest, which can be a large, long running task.

NOTE: SidHistory does not work in the following cases:

  • SID Filtering is enabled on the Forest Trust or Domain external Trust Relationship
  • For all permissions that are set by using well known SIDs (like Domain Users, Account Operators etc.). Those well-known SIDs are filtered out by default when accessing resources over the trust.
     

Disadvantages of sidHistory

Although sidHistory is a very big help in Inter-Forest Active Directory migration, it challenges all security considerations at the same time. A rogue administrator can add the SID of a given user account to his account’s sidHistory and thus gets access to the user’s resources. Another disadvantage is the blow up of the security token of a user account, since when using sidHistory, the token contains the SID of the account and the SIDs of all groups where the account is member of + the source account’s SID  and all SIDs of all the groups from source domain – assuming the groups have been migrated. There is a system limitation on token size which allows a maximum of 1015 groups. Using sidHistory for groups every group membership in a migrated group counts twice. If the source user is member of 550 groups in source domain and all groups have been migrated to target domain with sidHistory, the target account will most likely not be able to log on, because the security token is bloated. As long as the groups contain their sidHistory from before the migration, the group membership of users must be monitored constantly.

For Active Directory limits check here:

(http://technet.microsoft.com/en-us/library/active-directory-maximum-limits-scalability(v=ws.10).aspx#BKMK_Groups)

RECOMMENDATION: Taking into account the security and system related disadvantages of sidHistory, we recommend removing the sidHistory value after migration of accounts and resources.

In Part 2 of this thread we will show some ways to remove sidHistory values which is not possible via ADUC and ADSIEDIT and other LDAP based tools.