Now, before I start, I will let you in on a secret: this is on a Domain Controller.*
*The above statement is stricken due to irrelevance as the only significant change that occurs to the Local Administrator account and the Local Administrator Group (within the context and scope of this question) is minimal and doesn't alter the outcome enough to require differentiation.
I didn't have this kind of trouble on any of the other servers and I am willing to bet that the reason behind it is because it is on a DC.*
*Same reason as stated above. The accepted answer explains the inconsistency and was an oversight on my part, not the architecture (read features) of Windows Security or Domain Controllers.
I have been playing around with a few ideas on how to check if a script has been called from an account that is either the local Administrator or, at the very least, called by an account that is part of the Local Administrators group.
I have renamed the local Admin account, however, I know that I can see if the script has been called by local Admin account by typing:
(New-Object System.Security.Principal.NTAccount('reserved')).Translate([System.Security.Principal.SecurityIdentifier]).Value
and I can see if the SID ends in -500
.
The problem occurs when I run a condition to see if the calling account is part of the Administrators group (which is a larger scope) by typing:
PS> [bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).Groups -match "S-1-5-32-544")
PS> False
A quick check to see what account it was using:
PS> $env:username
PS> reserved
or the needlessly complicated way (though I prefer it sometimes):
PS> Write-Host ((Get-WmiObject Win32_Account | ?{$_.SID.Substring($_.SID.Length-4,4) -eq '-500'}).Caption).Split("\",2)[1] -fore GREEN
PS> reserved
and I even type:
PS> net user reserved
where it tells me Local Group Memberships *Administrators
.
I pull up ADUC (dsa.msc
) and I look in the Builtin
container and double-click on the Administrators group. I select the Members tag and lo, and behold, reserved
is actually a member!
So, a recap:
By typing net user reserved
, I was able to verify it was part of the Local Administrators group
I looked in ADUC and verified reserved was a member of the builtin Administrators group
I ensured reserved was indeed the Local Administrator account by verifying the SID started with S-1-5...
and ended with ...-500
To take it a step further, I made sure the SID matched the Active Directory Group named "Administrators" by typing Get-ADGroup -Identity "Administrators"
. I then typed Get-ADGroupMember -Identity "Administrators"
and made sure reserved
was listed (it was AND the SID matched!).
When I check to see if the well-known Administrators Group SID is found in the Groups of that account (by getting the current Windows Identity), it says that it isn't.
What gives?
Why do I get every indication that it actually is a member of the Local Administrators group but that SID isn't found in the account's groups?
I happened to stumble across something and I realized the answer to this question. For the sake of those that come here looking for assistance, here is the answer to my question:
Very simply--in regards to Powershell--if the Administrator Group SID (S-1-5-32-544) does not show up in the Groups of the user, that is a first-line indication that the script is not running with Administrative credentials.
For example, when I type out:
([Security.Principal.WindowsIdentity]::GetCurrent()).Groups
and I do not see the Administrator Group SID listed even though I know for a fact that the account I am signed into is a member of the Administrator Group, it means the current Powershell process does not have Administrative credentials.
If you click Run As Administrator
and type the same as above, you will see that it lists the Administrator Group SID in Groups
.
The reason why I was experiencing the inconsistency is simply because I was not running the Powershell process as an Administrator.
So, in short, there are a few ways you can check to verify if your current Powershell session has Administrator credentials. The first one is found in countless websites around the internet and is very common (I did not write this one):
$myWindowsID = [Security.Principal.WindowsIdentity]::GetCurrent()
$myWindowsPrincipal = New-Object Security.Principal.WindowsPrincipal($myWindowsID)
$adminRole = [Security.Principal.WindowsBuiltInRole]::Administrator
if($myWindowsPrincipal.IsInRole($adminRole)) {
\\ TODO: Process is running as Administrator
Clear-Host
} else {
$newProcess = New-Object System.Diagnostics.ProcessStartInfo "Powershell"
$newProcess.Arguments = "& '" + $script:MyInvocation.MyCommand.Path + "'"
$newProcess.Verb = "runas"
[System.Diagnostics.Process]::Start($newProcess)
exit
}
Here is another way (I did write this one):
[Security.Principal.WindowsIdentity]::GetCurrent() | %{
if($_.Groups -contains "S-1-5-32-544") {
\\ TODO: Process is running as Administrator
Clear-Host
} else {
Start Powershell -ArgumentList "& '$MyInvocation.MyCommand.Path'" -Verb runas
exit
}
}
# The Foreach-Object (%) could be replaced with another pipeline filter
I see a lot of people asking this question and because of Powershell appealing to many Systems Administrator (especially ones without a background in programming), I really think this will come in handy for others down the line.