Monthly Archives: June 2017

The lowdown on SIDHistory

Sup’ PSHomies,

SIDHistory is one of those Active Directory attributes you love to hate. When migrating from one domain to another, it let’s you retain access to resources in the Source Domain. This is a great way to transition, but in my experience it also makes for quick-shift migrations.

The first thing I do whenever we start a migration is have a look at SIDHistory. This will let me know quickly what we’re dealing with:

  • Has there been a previous migration? (I’ve seen objects in excess of 5 entries)
  • Did they clean up? (Obviously they didn’t or I wouldn’t see any entries)
  • Do I need to worry about Token-bloat?

Remember the blog I did about SDDL? Well SDDL deals with access based on SIDs. When a user logs on to the system, not only the new SID, but also the old SID is retrieved from the SIDHistory attribute and is added to the user’s access token and used to determine the user’s group memberships. The SIDs of the groups of which the user is a member through either the new SID or the old SID are then also added to the access token, together with any SIDHistory those groups might have.

This is also the reason tokenbloat can be an issue if it isn’t cleaned up after a migration.

So how do you find out about SIDHistory?

Get-ADObject -LDAPFilter "(sIDHistory=*)" -Property objectClass, distinguishedname, samAccountName, objectSID, sIDHistory |
Select-Object objectClass, DistinguishedName, SamAccountName, objectSID -ExpandProperty SIDHistory |
ForEach-Object {
[PSCustomObject]@{
ObjectClass = $_.objectClass
DistinguishedName = $_.DistinguishedName
SamAccountName = $_.SamAccountName
SID = $_.ObjectSID
DomainSID = $_.AccountDomainSID
SIDHistory = $_.Value
}
} |
Out-GridView -Title "AD Objects with SIDHistory"

On the subject of removing SIDHistory

This is tricky. Having and keeping SIDHistory intact will keep many a pesky helpdesk calls at bay… But is it wise to keep it?

From a Data (Read NTFS) perspective, you’ll need to Re-Acl your data structure. If you’ve kept you NTFS ACLs (Access Control List) nice and tidy (Wait, gimme a second to catch my breath from laughing) then you’re golden! This has never been the case in all my migrations  so far. My advice when it comes to Re-Acl, is to recreate the data structure (empty) and assign the correct ACEs (Access Control Entry) to the ACLs. Maybe I need to explain what Re-acl a bit more…

Re-ACL is the process of translating SIDs on Resources. I first came across the term using Quest Migration tools. This gave me the option to:

  • add the target SID to a resource
  • replace source SID on said resource
  • remove source SID from resource if everything is working

Here are the things you need to consider for each option

Adding the targetSID to a Resource

This gives the AD Object  access without having to rely on SIDHistory. This means that once the target SID has been added you can safely clean up SIDHistory. A target SID can only be added if a valid source SID has been found. I’ve seen too many ACLs with unknown ACEs in migrations I did over the years. This does nothing to clean up those unknown ACEs. Adding a target SID will expand you ACLs, which can have an impact on processing time

Replacing the sourceSID on a Resource

This makes for a cleaner ACL. Again, this does nothing for unknown ACEs. Replacing adds the targetSID and removes the sourceSID in the same process. A bold move, reverting SIDHistory isn’t as easy a writing to other AD object attributes and for good reason.

Remove sourceSID from Resource once everything has been verified to be working

Most are quite content that everything is working and don’t bother with this. Again, if your structure is up to date, this shouldn’t be an issue. What I’ll usually hear is: “We’ll create a new structure later on and get that cleaned up…” This rarely happens…

To wrap up

SIDHistory is a great way to retain access to source Resources, just make cleanup a part of the migration (If possible).This will vastly improve tokensize and improve your security

Re-Acl only makes sense if you’re content with your current NTFS data structure. If not, then I’d suggest redefining your Data structure. It’s a chore but well worth it.

Hope it’s worth something to you…

Ttyl,

Urv

Venturing into the world of PowerShell & DataTables

‘Sup PSHomies,

Been rethinking my Active Directory snapshot approach…

There are many ways to Rome, so which one to you choose? I’ve always been a fan of CSV and the Export-Csv cmdlet. Then I found out that Export-CliXML makes for a better experience when it comes to saving PS Objects (just don’t try figuring the tags out). Use the Import-CliXML cmdlet and you’ve got your PS Objects with Types back and in tact! Kevin Marguette has a great blog about this. While you’re at it, Jeff Hicks also has a great series on this topic, sharing is caring… 🙂

Gathering all you Active Directory data in one PS Object might not be the best approach when it comes to performance on a sizable AD. In my test lab, that wasn’t an issue. When I ran my script against a sizable AD, let’s just say I ran into some memory issues… 😉

My objective is to:

  • Gather AD data for offline reporting  purposes.
  • Keep data fragmentation to a minimum.

Let’s gather ADUser data for this exercise…

I want to collect the following data on AD users:

  • Disabled
  • Expired
  • NoExperationDate
  • Inactive
  • MustChangePassword
  • CannotChangepassword
  • All User & Properties

Approach #1

Pretty straightforward. Use the pipeline to keep resource usage to a minimum. When processing large collections you should always think pipeline!

Get-ADUser -Filter * -Properties * |
Export-Clixml .\export\dsa\dsADUsers-CliXML.xml -Encoding UTF8

Exporting directly using Export-CliXML will get the job done. I could do this for each AD User query:

  • Search-ADAccount -AccountDisabled
  • Search-ADAccount -AccountExpired
  • Get-ADUser -LDAPFilter ‘(|(accountExpires=0)(accountExpires=9223372036854775807))’
  • Search-ADAccount -AccountInactive
  • Get-ADUser -Filter {pwdLastSet -eq 0}
  • Get-ADUser -Filter * -Properties CannotChangePassword |Where-Object {$_.CannotChangePassword}
  • Get-ADUser -Filter * -Properties *

Nothing wrong with that, other than having a bunch of CliXML files. Collecting everything first isn’t an option performance wise.

Approach #2

Use a data Set/Table.

Full disclosure: This is my first attempt using data set/tables. I’m pretty sure that there’s a better approach and I’d love to here all about it!!!

I (re)found Chrissy LeMaire blog on basic .NET Datasets. Now why doesn’t that surprise me? 😛 Hehe…

$dsADUsers = New-Object System.Data.DataSet
$dtADUsers = New-Object System.Data.Datatable 'ADUsers'
$columnsADUsers = Get-ADUser -Identity guest -Properties * |
Get-Member -MemberType Property |
Select-Object -ExpandProperty Name
$columnsADUsers |
Foreach-Object{
[void]$dtADUsers.Columns.Add("$($_)")
}
Get-ADUser -Filter * -Properties * |
Foreach-Object{
$Row = $dtADUsers.NewRow()
foreach ($column in $columnsADUsers){
$Row["$($column)"] = if($_.$column -ne $null){($_ | Select-Object -ExpandProperty $column) -join "`n"}else{$null}
}
$dtADUsers.Rows.Add($Row)
}
$dsADUsers.Tables.Add($dtADUsers)
$dtADUsers.WriteXml('c:\scripts\export\dsa\dtADUsers.xml')

 

Quick breakdown: First I created a Dataset (prefix ds just in case you were wondering…) and the data table. I wanted all available properties. I realize this might be more than you need so feel free to change that to your needs. To get the necessary column Names I’m using the Get-Member cmdlet with parameter MemberType Property. A quick select and expand and I have column names, beats hard coding column names…

Ok here’s where it gets a bit tricky, So I’m processing each object as it goes through the pipeline, but I do have a datatable object… Like I said first attempt…

Once the data table is ready just add it to the dataset! A dataset can hold multiple datatables which helps in solving my data gathering fragmentation.

Fun fact

Did you know that you can write/export your datatable to XML? Unlike CliXML output this one is legible…

dataTable ADuser

To write the dataTable to XML:

$dtADUsers.WriteXml('c:\scripts\export\dsa\dtADUsers.xml')

Same command applies for the dataSet 🙂 Added bonus is the file size, much smaller than CliXML, but then again not as rich…

dataTable ADuser size

Take away

I love the fact that there’s more than one way to work with data. I guess it comes down to preference. I was pleasantly surprised by the datatable XML formatting, nice and clean! If  export file size is an issue, then datasets can help, the trade off being you’ll loose rich data of the PS objects. The *CliXML cmdlets are sufficient for my needs, if I’m honest with myself, still glad I looked into data sets/tables…

Now If you have a full fledged SQL environment you can take advantage of, then, Go for it!!! Just ask Rob Sewell aka sqldbawithbeard  or Chrissy LeMaire, our PowerShell SQL experts to point you in the right direction!

The more you know! 😉

Hope it’s worth something to you…

Ttyl,

Urv