User & Group information DirectoryServices.AccountManagement

When you are tasked with administering windows machines/servers more often than not you need to have Remote Server access tools for the version of Operating system you are supporting.  What do you do when you can’t get those tools installed for administrative or other reasons.  The best thing to do is to look for a means to do this in PowerShell.  This article describes how to find user and group information via the Dll’s that are available on windows.

All users/groups and objects in active directory have unique Security Identifier’s. To be able to locate and translate SID’s the class System.DirectoryServices.AccountManagement. The current logged in user’s sid can be retrieved using:

Add-Type -AssemblyName System.DirectoryServices.AccountManagement
[System.Security.Principal.WindowsIdentity]::getcurrent()

AuthenticationType : CloudAP
ImpersonationLevel : None
IsAuthenticated    : True
IsGuest            : False
IsSystem           : False
IsAnonymous        : False
Name               : somemachine\xxxxx
Owner              : S-1-5-24-2812812812-3456789123-4444444444-1001
User               : S-1-5-24-2812812812-3456789123-4444444444-1001
Groups             : {S-1-1-0, S-1-5-21-2242821411-3846915716-4272663257-1009, S-1-5-21-2242821411-3846915716-4272663257-1003, S-1-5-99-812...}
AccessToken        : Microsoft.Win32.SafeHandles.SafeAccessTokenHandle
Token              : 3688
UserClaims         : {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: somemachine\xxxxx, http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid: S-1-5-24-2812812812-3456789123-4444444444-1001, http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid: S-1-1-0, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/denyonlysid: S-1-5-189...}
DeviceClaims       : {}
Claims             : {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: somemachine\xxxxx, http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid: S-1-5-24-2812812812-3456789123-4444444444-1001, http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid: S-1-1-0, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/denyonlysid: S-1-5-189...}
Actor              :
BootstrapContext   :
Label              :
NameClaimType      : http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
RoleClaimType      : http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid

While the sid information has been redacted it is intact in terms of what would be displayed when calling the function.  it’s groups we are looking for turns out this function has a Groups method.


[System.Security.Principal.WindowsIdentity]::getcurrent().groups

BinaryLength AccountDomainSid Value
------------ ---------------- -----
12 S-1-1-0
28 redactedAcountSid RedactedValue

The return value I received was much larger for this on a Corporate network especially if the (current) user is in a number of Groups.

Now that we have the Group SID’s now on to the process of Converting the SID’s into a human readable form.  For the accounts discovered previously if we choose the first item [0] we can then see there is a .Translate on this item


([System.Security.Principal.WindowsIdentity]::getcurrent().groups[0]).translate

OverloadDefinitions
-------------------
System.Security.Principal.IdentityReference Translate(type targetType)

In order to do the translation we’ll need to specify the type that the dotnet class expects.  It expects a type of system.security.principal.ntaccount . This is the only class from the documentation that has the type expected.


([System.Security.Principal.WindowsIdentity]::getcurrent().groups[0]).translate([system.security.principal.ntaccount])

Value
-----
Everyone

The groups are known now to put this all together in a Foreach Loop to find out all the groups that the currently logged in user is a member of:


([System.Security.Principal.WindowsIdentity]::getcurrent().groups) | Foreach{( `

[System.Security.Principal.SecurityIdentifier]$_.value).Translate([system.security.principal.ntaccount])}

Value
-----
Everyone
.....(more groups Redacted)

With a few more updates this script can be modified to find per user when in a domain scenario. Or for local users:


Add-Type -AssemblyName System.DirectoryServices.AccountManagement
$userprincipal = ([System.DirectoryServices.AccountManagement.UserPrincipal]) -as [type]
$up = $userprincipal::FindByIdentity([System.DirectoryServices.AccountManagement.ContextType]::Machine,[System.DirectoryServices.AccountManagement.IdentityType]::SamAccountName,"somemachine\defaultAccount")

$up

GivenName :
MiddleName :
Surname :
EmailAddress :
VoiceTelephoneNumber :
EmployeeId :
AdvancedSearchFilter : System.DirectoryServices.AccountManagement.AdvancedFilters
Enabled : False
AccountLockoutTime :
.......
.......

ContextType : Machine
Description : A user account managed by the system.
DisplayName :
SamAccountName : DefaultAccount
UserPrincipalName :
Sid : S-1-5-xx-xxxxxxxx-xxxxxxxxxxx-xxxxxxxxxxxxxxxx-503
Guid :
....

Name : DefaultAccount

$up.GetGroups()

IsSecurityGroup : True
GroupScope : Local
Members : {DefaultAccount}
Context : System.DirectoryServices.AccountManagement.PrincipalContext
ContextType : Machine
Description : Members of this group are managed by the system.
DisplayName :
SamAccountName : System Managed Accounts Group
UserPrincipalName :
Sid : S-1-5-xx-xxx
Guid :
DistinguishedName :
StructuralObjectClass :
Name : System Managed Accounts Group

$up.getGroups().samacccountname

System Managed Accounts Group

Now if you need who’s in a group either Locally with: [System.DirectoryServices.AccountManagement.ContextType]::Machine

Domain with

ApplicationDirectory with

[ system.DirectoryServices.Accountmanagement.contextType ]::ApplicationDirectory

I hope this helps someone out.

 

Until then

 

Keep Scripting

 

Thom

Advertisements