I've been looking into Group Managed Service Accounts (gmsa) accounts and I've been using them to run scheduled tasks on Server 2012R2 and PowerShell 5.0.10586.117.
After I've been using them a while I've encountered some very weird behavior.
The problem seem to be some kind of timing issue/race condition somewhere when a task is run as a gmsa account. Some core commands might not exists/be loaded while running the script.
Example:
Script called in the task C:\temp\broken-task\test.cmd
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy "ByPass" -File "C:\temp\broken-task\test.ps1" > "C:\temp\broken-task\test.cmd.txt"
The actual script with weird behavior C:\temp\broken-task\test.ps1
<#
.SYNOPSIS
Broken task.
.DESCRIPTION
Broken task.
#>
[CmdletBinding()] Param ()
Process {
$ErrorActionPreference
Set-Variable -Name "ErrorActionPreference" -Scope "Script" -Value "Stop"
Set-Variable -Name "ErrorActionPreference" -Scope "Script" -Value "Stop"
$ErrorActionPreference
}
I then create and run a task in C:\temp\broken-task\task.ps1
$Action = New-ScheduledTaskAction -Execute "C:\Windows\System32\cmd.exe" -Argument "/C C:\temp\broken-task\test.cmd"
$Principal = New-ScheduledTaskPrincipal -UserID "my-gmsa-user$" -LogonType "Password"
New-ScheduledTask -Action $Action -Principal $Principal | Register-ScheduledTask -TaskPath "\test\" -TaskName "test123" | Out-Null
Start-ScheduledTask -TaskPath "\test\" -TaskName "test123"
After task completion the content of C:\temp\broken-task\test.cmd.txt
is the following:
Continue
Set-Variable : The term 'Set-Variable' is not recognized as the name of a cmdle
t, function, script file, or operable program. Check the spelling of the name,
or if a path was included, verify that the path is correct and try again.
At C:\temp\broken-task\test.ps1:15 char:5
+ Set-Variable -Name "ErrorActionPreference" -Scope "Script" -Value ...
+ ~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Set-Variable:String) [], Comman
dNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Stop
What is happening above is that Set-Variable
doesn't exist on line 2 of the process block in test.ps1
, but exist on line 3 (we can see that $ErrorActionPreference
has changed).
If I run either the cmd script or the ps1 as myself (a normal user) I will get the expected output with no errors:
Continue
Stop
So what's going on here? The Set-Variable
command is in the Microsoft.PowerShell.Utility
module. Is the module somehow loaded in between the first and second call? This also happen with other commands like Get-Item "C:\"
.
What might be even worse is that this does not always happen. I've seen a task work properly in one run and fail in the other.
Also note that I find it hard to create good examples and this does not always yield the same weird results (but the above example has currently failed without exception in my tests).
Is the combination of powershell, gmsa and task scheduler broken somehow?
I can't really trust the system to do as I which when it has this inconsistent behavior.
A workaround might be explicit loading of the Microsoft.PowerShell.Utility
module before calling Set-Variable
, but I'm not sure if this is due to timing or something else..