Windows PowerShell Tip of the Week

Here’s a quick tip on working with Windows PowerShell. These are published every week for as long as we can come up with new tips. If you have a tip you’d like us to share or a question about how to do something, let us know.

Find more tips in the Windows PowerShell Tip of the Week archive.

Working with SIDs

You know, every week the Scripting Guys get barraged by a bunch of questions involved SIDs (Security Identifiers):

  • How can I determine the SID for a local user account?

  • How can I determine the SID for an Active Directory user account?

  • I have a SID here. How can I determine which account that SID belongs to?

So many questions, and such little time in which to answer them! Which means we better get started, eh?

Determining the SID for a Local User Account

As it turns out, determining the SID for a local user account is remarkably easy; that’s due, in large part, to the fact that Windows PowerShell makes it easy for us to tap into the power of the .NET Framework. Here’s a simple little script that returns the SID for a local user named kenmyer:

$objUser = New-Object System.Security.Principal.NTAccount("kenmyer")
$strSID = $objUser.Translate([System.Security.Principal.SecurityIdentifier])
$strSID.Value

As you can see, in line 1 we use the New-Object cmdlet to create an instance of the System.Security.Principal.NTAccount class; this class is used to represent a user or group account. (Which means that you can’t determine computer SIDs using this script. That’s another tip for another week.) Notice that, when we create this new instance of the NTAccount class, we need to pass it a single parameter: the user name of the account of interest (kenmyer).

Once we have an object ($objUser) representing the kenmyer account we can then use the Translate method to convert this user name identity into another type of identity; in particular, we can convert the user name into an instance of the System.Security.Principal.SecurityIdentifier class, the .NET class that represents user and group SIDs. That’s what this line of code is for:

$strSID = $objUser.Translate([System.Security.Principal.SecurityIdentifier])

At that point all we have to do is echo back the SID’s Value property:

S-1-5-21-1220945662-1202665555-839525555-5555

Believe it or not, that’s all there is to it.

Determining the SID for an Active Directory User Account

Of course, no one out there in PowerShell Land is naïve. You know how technical writers operate: they show you a really simple example first, just to whet your appetite and make you keep reading. It’s only after you’ve been sucked in that they show you how hard it is to do everything else.

Of course, no one out there in PowerShell Land believes that the Scripting Guys are technical writers, either. It was pretty darn easy to determine the SID for a local user account; is it going to be equally easy to determine a SID for an Active Directory user account? Let’s see for ourselves:

$objUser = New-Object System.Security.Principal.NTAccount("fabrikam", "kenmyer")
$strSID = $objUser.Translate([System.Security.Principal.SecurityIdentifier])
$strSID.Value

See? The Scripting Guys would never try to trick you by luring you in with an easy example and then hitting you over the head with something difficult and complex. (Mainly because we don’t like difficult and complex, either.) As it turns out, you use the exact same approach to determining an Active Directory SID as you do a local user SID; the only difference is that you need to include both the domain (fabrikam) and the user name (kenmyer) when creating an instance of the NTAccount class:

$objUser = New-Object System.Security.Principal.NTAccount("fabrikam", "kenmyer")

That’s the only difference between the two scripts. When we run this script we should get Ken Myer’s domain SID:

S-1-5-21-1454471165-1004335555-1606985555-5555

Very cool.

Determining Which Account a SID Belongs to

Now for the pièce de résistance.

Note. Interestingly enough, pièce de résistance really does translate as “piece of resistance.” Supposedly that’s because the pièce de résistance is the piece of something (like an article about using Windows PowerShell to work with SIDs) that “resists” the drab and the mundane and makes the piece stand out amongst the crowd.

Well, that’s what we were told, anyway.

At any rate, suppose you have a SID, and you’d like to know which account that SID belongs to. Is that going to be a problem? Maybe. But not if you have Windows PowerShell:

$objSID = New-Object System.Security.Principal.SecurityIdentifier `
    ("S-1-5-21-1454471165-1004335555-1606985555-5555")
$objUser = $objSID.Translate( [System.Security.Principal.NTAccount])
$objUser.Value

Again, this is as about as simple a script as you could ever hope to find. In line 1, we’re creating a new instance of the SecurityIdentifier class, specifying the SID in question (S-1-5-21-1454471165-1004335555-1606985555-5555) along the way. In line 2, we use the Translate method to convert this SID to an instance of the NTAccount class, and then in line 3 we echo back the Value of this new instance of NTAccount.

If you’re thinking, “This is the exact opposite of the process used to convert a name to a SID,” well, give yourself a gold star: you’re absolutely right.

What the heck: give yourself two gold stars. You’ve earned them.

After we run this script we should see information similar to the following onscreen:

FABRIKAM\kenmyer

Perfect.

That’s all we have time for this week; after all, the 2008 Winter Scripting Games are now just two weeks away. But we’ll come back to the Security.Principal classes again one of these days; as you might expect, there are all sorts of cool things you can do with these classes. Until then, however, well, we’ll see everyone next week.