Impersonation not working in Powershell 7
Impersonation working fine in Powershell 5.1.19041.1320
Errors when using Powershell 7.2.1:
Running:
Push-ImpersonationContext -Credential "PcName\UserName"
Output (after typing in the password):
New-Object: PowerShell\Modules\SecurityFever\2.8.1\Helpers\Impersonation\Initialize-ImpersonationContext.ps1:64:40
Line |
64 | … onContext = New-Object -TypeName 'System.Collections.Generic.Stack[Sy …
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| Cannot find type [System.Collections.Generic.Stack[System.Security.Principal.WindowsImpersonationContext]]: verify that the assembly containing this type is loaded.
InvalidOperation: PowerShell\Modules\SecurityFever\2.8.1\Functions\Impersonation\Push-ImpersonationContext.ps1:82:5
Line |
82 | $newImpersonationContext = [System.Security.Principal.WindowsIden …
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| Method invocation failed because [System.Security.Principal.WindowsIdentity] does not contain a method named 'Impersonate'.
InvalidOperation: PowerShell\Modules\SecurityFever\2.8.1\Functions\Impersonation\Push-ImpersonationContext.ps1:83:5
Line |
83 | $Script:ImpersonationContext.Push($newImpersonationContext)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| You cannot call a method on a null-valued expression.
Could you please fix this for PS7?
Thanks and best regards, Skaldhor
Same issue with PS 7.2.2
Here's what I've learned so far:
- Powershell 5.1
- is generically called "Windows Powershell"
- runs only on Windows, hence the name
- hooks into ".Net Framework"
- Powershell 7
- is aptly called "Powershell", but is also known as "Powershell Core"
- hooks into ".Net Core", but not ".Net Framework"
- Powershell 7 code base was originally forked from Windows Powershell but is to support cross platform compatibility
- Powershell 7 should be called something like generic like"Universal Powershell" to retain the naming convention introduced with "Windows Powershell"
- Universal Powershell Is a stand alone version of powershell and will co-exist with previously installed versions of "Windows Powershell"
- Universal Powershell has about 25% of the commandlets available to Windows Powershell
- .Net Core was specifically designed to not support WindowsImpersonationContext due to security concerns around the function
Recommended solution for your user impersonation. It's not ideal : instead of trying to push impersonation you can refactor your command to use Start-Job which will accept a credential.
Example:
In Get-MySqlData I'm calling a private function called Invoke-SQL contained in my automatically loaded module.
The Get-MySqlData function will:
- Accept all the usual particulars like SQL statement, Credential, and Database Info.
- Pass parameters into a
Start-Jobusing the credential and run the script block to callInvoke-SQL - Wait for the job to complete
- Return the results
function Get-MySqlData {
param (
[string]$SqlStatement
, [PsCredential]$Credential = $( Get-Credential )
, [string]$Database = "DatabaseInstanceName"
, [string]$Server = "DatabaseServerName"
) # end param
$ScriptBlock = {
Param( [hashtable]$Options )
write-host "welcome '$($Env:username)'"
write-host "`$Options = $($Options | ConvertTo-Json) # end json"
Invoke-SQL @Options
} # end scriptblock
$Options = @{
SqlStatement = $SqlStatement
Database = $Database
Server = $Server
} # end hash
$Job = Start-Job -ScriptBlock $ScriptBlock -Credential $Credential -ArgumentList $Options
return $Job | Wait-Job | Receive-Job
} # end function Get-MySqlData