3

Many examples on the web show the way to check current user for Administrative privileges using

[Security.Principal.WindowsPrincipal]    
[Security.Principal.WindowsIdentity]::GetCurrent()

Is there a similar way to check not the 'current' identity, but any (local or domain, for example, retrieved from Get-ACL cmdlet) when running commands on a particular server.

I checked https://learn.microsoft.com/en-us/dotnet/api/system.security.principal.windowsidentity.-ctor?view=netframework-4.7.2#System_Security_Principal_WindowsIdentity__ctor_System_String_, but couldn't find a way to do it (only if you use constructor with UPN parameter, which is not suitable in my case). I would appreciate any hint.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Max
  • 71
  • 3
  • 8
  • Why UPN is not suitable for you? How you're planning to specify a username? – montonero Dec 24 '18 at 11:38
  • 1
    I want it to be suitable also for local users. As 'SERVER\username' or 'DOMAIN\username'. – Max Dec 24 '18 at 12:04
  • 2
    You can use UPN for domain users without problems (like user@domain) but not for local ones. You could try a different approach as described here https://stackoverflow.com/questions/18835134/how-to-create-windowsidentity-windowsprincipal-from-username-in-domain-user-form – montonero Dec 24 '18 at 12:22

1 Answers1

3

You can try the following function, which, for a given user name:

  • tries to find the underlying identity (NT user account) in the same context as the calling user (domain vs. local); the user name may be specified in several formats, among them the NTLM format (<domain>\<username>).
  • then tests that identity for (static) membership in the built-in local Administrators group.
function Test-LocalAdminGroupMembership {
  param([string] $user)

  # Load the required assembly (a no-op if already loaded).
  Add-Type -AssemblyName System.DirectoryServices.AccountManagement

  # Obtain the specified user as a UserPrincipal instance.
  $up = try {
    if (-not $user) { # default to current user
      [System.DirectoryServices.AccountManagement.UserPrincipal]::Current
    } else {
      [System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity(
        [System.DirectoryServices.AccountManagement.UserPrincipal]::Current.Context,
        $user
      )
    }
  } catch {
    Throw
  }

  # See if the well-known SID of the local Administrators group
  # is among the SIDs of the groups that the user is a member of (PSv3+ syntax).
  $up.GetGroups().SID.Value -contains 'S-1-5-32-544'

}
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Checking group mermbership is a bit different approach, and I already wrote a function for this utilizing WMI, recursive one, but the approach with `IsInRole:Administrator` seemed like less overhead, so I hoped to utilize that 'lazy' way... Those classes from `System.DirectoryServices.AccountManagement` namespace can be useful, but I currently don't see the benefit vs WMI + `GetRelated()` method, even more - as far as I understand, I have to create and operate with two contexts (Machine+Domain) if I have to check both local and domain users. Thanks for the hint anyway. – Max Dec 25 '18 at 20:18
  • 1
    @Max: My understanding is that if you want to check for a _different_ user, checking group membership is _all_ that you can do, in the absence of an account token associated with a concrete _process_. _Effective_ administrative rights - as opposed to _potential_ ones, via group membership - can only be checked for an actual process. (As an aside: It would be easy to extend the function to look both in the domain and in the machine context.) – mklement0 Dec 25 '18 at 20:37
  • I see. BTW, can you point out how to implement effective access check for NTFS ACLs for a specific user? It's beyond the scope of my question, but related to what I'm trying to do. – Max Dec 25 '18 at 20:48
  • @Max: See https://stackoverflow.com/a/53780392/45375 and the comments on it - it looks like you may have to call the Windows API via P/Invoke yourself. – mklement0 Dec 26 '18 at 13:30