Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ScheduledTask: Added BuiltInUser (Issue #130) & Fixed IdleWaitTimeout… #192

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,31 @@
## Unreleased

- ScheduledTask:
- IdleWaitTimeout returned from Get-TargetResource always null - See [Issue #186](https://github.com/PowerShell/ComputerManagementDsc/issues/186).
- Added Property BuiltInAccount - See [Issue #130](https://github.com/PowerShell/ComputerManagementDsc/issues/130).
Used for running the Scheduled Task as one of the built in
service accounts.
Valid Values: 'SYSTEM', 'LOCAL SERVICE', 'NETWORK SERVICE'.
If set ExecuteAsCredential will be ignored and LogonType will
be overwritten to 'SericeAccount'.
Added Example [16-CreateScheduledTasksAsBuiltinServiceAccount.ps1](Modules/ComputerManagementDsc/Examples/Resources/ScheduledTask/16-CreateScheduledTasksAsBuiltinServiceAccount.ps1).
The name BuiltInAccount and it's pattern of use is based on
the property of the same name in the [Service DSCR](https://github.com/PowerShell/PSDscResources#service).
The reason for defining a new property and not using the
alternative eg:

`ExecuteAsCredential = ([pscredential]::new(
'NT AUTHORITY\NETWORK SERVICE',
(ConvertTo-SecureString -String 'TEST' -AsPlainText -Force)))`

was the above requires either; the configuration to be compiled
with PSDscAllowPlainTextPassword = $true (not secure) or the
resultant MOF file to be encrytpted (additional complexity that
may not otherwise be required for a specific environment)
- Added support for Group Managed Service Accounts, implemented using the ExecuteAsGMSA
parameter. Fixes [Issue #111](https://github.com/PowerShell/ComputerManagementDsc/issues/111)
- Added support to set the Synchronize Across Time Zone option. Fixes [Issue #109](https://github.com/PowerShell/ComputerManagementDsc/issues/109)
- Added .VSCode settings for applying DSC PSSA rules - fixes [Issue #189](https://github.com/PowerShell/ComputerManagementDsc/issues/189).
- Added .VSCode settings for applying DSC PSSA rules - fixes [Issue #189](https://github.com/PowerShell/ComputerManagementDsc/issues/189).

## 5.2.0.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ $script:localizedData = Get-LocalizedData `
True if the task should be enabled, false if it should be disabled.
Not used in Get-TargetResource.

.PARAMETER BuiltInAccount
Run the task as one of the built in service accounts ('SYSTEM', 'LOCAL SERVICE', 'NETWORK SERVICE').
When set -ExecuteAsCredential will be ignored and -LogonType will be set to 'SericeAccount'

.PARAMETER ExecuteAsCredential
The credential this task should execute as. If not specified defaults to running
as the local system account. Cannot be used in combination with ExecuteAsGMSA.
Expand Down Expand Up @@ -277,6 +281,10 @@ function Get-TargetResource
[System.Boolean]
$Enable = $true,

[ValidateSet('SYSTEM', 'LOCAL SERVICE', 'NETWORK SERVICE')]
[String]
$BuiltInAccount,

[Parameter()]
[System.Management.Automation.PSCredential]
$ExecuteAsCredential,
Expand Down Expand Up @@ -511,7 +519,7 @@ function Get-TargetResource
$returnSynchronizeAcrossTimeZone = $false
}

return @{
$result = @{
TaskName = $task.TaskName
TaskPath = $task.TaskPath
StartTime = $startAt
Expand All @@ -538,7 +546,9 @@ function Get-TargetResource
AllowStartIfOnBatteries = -not $settings.DisallowStartIfOnBatteries
Hidden = $settings.Hidden
RunOnlyIfIdle = $settings.RunOnlyIfIdle
IdleWaitTimeout = ConvertTo-TimeSpanStringFromScheduledTaskString -TimeSpan $settings.IdleSettings.IdleWaitTimeout
#$settings.IdleSettings.IdleWaitTimeout is always null, changed to WaitTimeout property to avoid Test-TargetResource returning a spurious value
#IdleWaitTimeout = ConvertTo-TimeSpanStringFromScheduledTaskString -TimeSpan $settings.IdleSettings.IdleWaitTimeout
IdleWaitTimeout = ConvertTo-TimeSpanStringFromScheduledTaskString -TimeSpan $settings.IdleSettings.WaitTimeout
NetworkName = $settings.NetworkSettings.Name
DisallowStartOnRemoteAppSession = $settings.DisallowStartOnRemoteAppSession
StartWhenAvailable = $settings.StartWhenAvailable
Expand All @@ -558,6 +568,13 @@ function Get-TargetResource
EventSubscription = $trigger.Subscription
Delay = ConvertTo-TimeSpanStringFromScheduledTaskString -TimeSpan $trigger.Delay
}

if (($result.ContainsKey('LogonType')) -and ($result['LogonType'] -ieq 'ServiceAccount'))
{
$result.Add('BuiltInAccount', $task.Principal.UserId)
}

return $result
}
}

Expand Down Expand Up @@ -604,6 +621,10 @@ function Get-TargetResource
.PARAMETER Enable
True if the task should be enabled, false if it should be disabled.

.PARAMETER BuiltInAccount
Run the task as one of the built in service accounts ('SYSTEM', 'LOCAL SERVICE', 'NETWORK SERVICE').
When set -ExecuteAsCredential will be ignored and -LogonType will be set to 'SericeAccount'

.PARAMETER ExecuteAsCredential
The credential this task should execute as. If not specified defaults to running
as the local system account. Cannot be used in combination with ExecuteAsGMSA.
Expand Down Expand Up @@ -786,6 +807,10 @@ function Set-TargetResource
[System.Boolean]
$Enable = $true,

[ValidateSet('SYSTEM', 'LOCAL SERVICE', 'NETWORK SERVICE')]
[String]
$BuiltInAccount,

[Parameter()]
[System.Management.Automation.PSCredential]
$ExecuteAsCredential,
Expand Down Expand Up @@ -945,9 +970,9 @@ function Set-TargetResource
and the action executable isn't specified then disable the task
#>
if ($currentValues.Ensure -eq 'Present' `
-and $currentValues.Enable `
-and -not $Enable `
-and -not $PSBoundParameters.ContainsKey('ActionExecutable'))
-and $currentValues.Enable `
-and -not $Enable `
-and -not $PSBoundParameters.ContainsKey('ActionExecutable'))
{
Write-Verbose -Message ($script:localizedData.DisablingExistingScheduledTask -f $TaskName, $TaskPath)
Disable-ScheduledTask -TaskName $TaskName -TaskPath $TaskPath
Expand Down Expand Up @@ -990,7 +1015,7 @@ function Set-TargetResource
-ArgumentName EventSubscription
}

if ($ExecuteAsCredential -and $ExecuteAsGMSA)
if ($ExecuteAsGMSA -and ($ExecuteAsCredential -or $BuiltInAccount))
{
New-InvalidArgumentException `
-Message ($script:localizedData.gMSAandCredentialError) `
Expand Down Expand Up @@ -1245,7 +1270,15 @@ function Set-TargetResource
# Prepare the register arguments
$registerArguments = @{}

if ($PSBoundParameters.ContainsKey('ExecuteAsGMSA'))
$username = $null
if ($PSBoundParameters.ContainsKey('BuiltInAccount'))
{
#the validateset on BuiltInAccount has already checked the non null value to be 'LOCAL SERVICE', 'NETWORK SERVICE' or 'SYSTEM'
$username = 'NT AUTHORITY\' + $BuiltInAccount
$registerArguments.Add('User', $username)
$LogonType = 'ServiceAccount'
}
elseif ($PSBoundParameters.ContainsKey('ExecuteAsGMSA'))
{
$username = $ExecuteAsGMSA
$LogonType = 'Password'
Expand All @@ -1269,6 +1302,7 @@ function Set-TargetResource
}
else
{
#'NT AUTHORITY\SYSTEM' basically gives the schedule task admin privileges, should we default to 'NT AUTHORITY\LOCAL SERVICE' instead?
$username = 'NT AUTHORITY\SYSTEM'
$registerArguments.Add('User', $username)
$LogonType = 'ServiceAccount'
Expand Down Expand Up @@ -1367,8 +1401,8 @@ function Set-TargetResource

# Register the scheduled task

$registerArguments.Add('TaskName',$TaskName)
$registerArguments.Add('TaskPath',$TaskPath)
$registerArguments.Add('TaskName', $TaskName)
$registerArguments.Add('TaskPath', $TaskPath)
$registerArguments.Add('InputObject', $scheduledTask)

$null = Register-ScheduledTask @registerArguments
Expand Down Expand Up @@ -1426,6 +1460,10 @@ function Set-TargetResource
.PARAMETER Enable
True if the task should be enabled, false if it should be disabled.

.PARAMETER BuiltInAccount
Run the task as one of the built in service accounts ('SYSTEM', 'LOCAL SERVICE', 'NETWORK SERVICE').
When set -ExecuteAsCredential will be ignored and -LogonType will be set to 'SericeAccount'

.PARAMETER ExecuteAsCredential
The credential this task should execute as. If not specified defaults to running
as the local system account. Cannot be used in combination with ExecuteAsGMSA.
Expand Down Expand Up @@ -1609,6 +1647,10 @@ function Test-TargetResource
[System.Boolean]
$Enable = $true,

[ValidateSet('SYSTEM', 'LOCAL SERVICE', 'NETWORK SERVICE')]
[String]
$BuiltInAccount,

[Parameter()]
[System.Management.Automation.PSCredential]
$ExecuteAsCredential,
Expand Down Expand Up @@ -1824,12 +1866,34 @@ function Test-TargetResource
return $false
}

if ($PSBoundParameters.ContainsKey('ExecuteAsCredential'))
if ($PSBoundParameters.ContainsKey('BuiltInAccount'))
{

$PSBoundParameters.User = $BuiltInAccount
$currentValues.User = $BuiltInAccount

$PSBoundParameters['LogonType'] = 'ServiceAccount'
$currentValues['LogonType'] = 'ServiceAccount'
}
elseif ($PSBoundParameters.ContainsKey('ExecuteAsCredential'))
{
# The password of the execution credential can not be compared
$username = $ExecuteAsCredential.UserName
$PSBoundParameters['ExecuteAsCredential'] = $username
}
else
{
# must be running as System, login type is ServiceAccount
$PSBoundParameters['LogonType'] = 'ServiceAccount'
$currentValues['LogonType'] = 'ServiceAccount'
}

if ($PSBoundParameters.ContainsKey('WeeksInterval') -and ((-not $currentValues.ContainsKey('WeeksInterval')) -or ($null -eq $currentValues['WeeksInterval'])))
{
#The WeeksInterval parameter is defaulted to 1, even when the property is unset/undefined for the current task returned from Get-TargetResouce
#initialise a missing or null WeeksInterval to spurious calls to Set-TargetResouce
$currentValues.WeeksInterval = $PSBoundParameters['WeeksInterval']
}

if ($PSBoundParameters.ContainsKey('ExecuteAsGMSA'))
{
Expand All @@ -1848,6 +1912,11 @@ function Test-TargetResource

$desiredValues = $PSBoundParameters
$desiredValues.TaskPath = $TaskPath
if ($desiredValues.ContainsKey('Verbose'))
{
#initialise a missing or null Verbose to spurious calls to Set-TargetResouce
$currentValues.Add('Verbose', $desiredValues['Verbose'])
}

Write-Verbose -Message ($script:localizedData.TestingDscParameterStateMessage)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ class MSFT_ScheduledTask : OMI_BaseResource
[Write, Description("Enable the scheduled task option to synchronize across time zones. This is enabled by including the timezone offset in the scheduled task trigger. Defaults to false which does not include the timezone offset.")] boolean SynchronizeAcrossTimeZone;
[Write, Description("Present if the task should exist, Absent if it should be removed"), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] string Ensure;
[Write, Description("True if the task should be enabled, false if it should be disabled")] boolean Enable;
[Write, Description("Run the task as one of the built in service accounts ('SYSTEM', 'LOCAL SERVICE', 'NETWORK SERVICE'). When set -ExecuteAsCredential will be ignored and -LogonType will be set to 'SericeAccount'"), ValueMap{"SYSTEM", "LOCAL SERVICE", "NETWORK SERVICE"}, Values{"SYSTEM", "LOCAL SERVICE", "NETWORK SERVICE"}] string BuiltInAccount;
[Write, Description("The credential this task should execute as. If not specified defaults to running as the local system account"), EmbeddedInstance("MSFT_Credential")] string ExecuteAsCredential;
[Write, Description("The gMSA (Group Managed Service Account) this task should execute as. Cannot be used in combination with ExecuteAsCredential.")] string ExecuteAsGMSA;
[Write, Description("The gMSA (Group Managed Service Account) this task should execute as. Cannot be used in combination with ExecuteAsCredential or BuiltInAccount.")] string ExecuteAsGMSA;
[Write, Description("Specifies the interval between the days in the schedule. An interval of 1 produces a daily schedule. An interval of 2 produces an every-other day schedule.")] Uint32 DaysInterval;
[Write, Description("Specifies a random amount of time to delay the start time of the trigger. The delay time is a random time between the time the task triggers and the time that you specify in this setting.")] String RandomDelay;
[Write, Description("Specifies how long the repetition pattern repeats after the task starts. May be set to `Indefinitely` to specify an indefinite duration.")] String RepetitionDuration;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ ConvertFrom-StringData @'
WeeksIntervalError = WeeksInterval must be greater than zero (0) for Weekly schedules. WeeksInterval specified is '{0}'.
WeekDayMissingError = At least one weekday must be selected for Weekly schedule.
OnEventSubscriptionError = No (valid) XML Event Subscription was provided. This is required when the scheduletype is OnEvent.
gMSAandCredentialError = Both ExecuteAsGMSA and ExecuteAsCredential parameters have been specified. A task can either run as a gMSA (Group Managed Service Account) or as a custom credential, not both. Please modify your configuration to include just one of the two.
gMSAandCredentialError = Both ExecuteAsGMSA and (ExecuteAsCredential or BuiltInAccount) parameters have been specified. A task can run as a gMSA (Group Managed Service Account), a builtin service account or as a custom credential. Please modify your configuration to include just one of the three options.
SynchronizeAcrossTimeZoneInvalidScheduleType = Setting SynchronizeAcrossTimeZone to true when the ScheduleType is not Once, Daily or Weekly is not a valid configuration. Please keep the default value of false when using other schedule types.
TriggerCreationError = Error creating new scheduled task trigger.
ConfigureTriggerRepetitionMessage = Configuring trigger repetition.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<#
.EXAMPLE
This example creates a scheduled task called 'TriggerOnServiceFailures' in the folder
root folder. The task is delayed by exactly 30 seconds each time. The task will run when
an error event 7001 of source Service Control Manager is generated in the system log.
When a service crashes, it waits for 30 seconds and then starts a new PowerShell instance,
in which the file c:\temp\seeme.txt get's created with the value 'Worked!'
#>
Configuration Example
{
param
(
[Parameter()]
[System.String[]]
$NodeName = 'localhost'
)

Import-DscResource -ModuleName ComputerManagementDsc

Node $NodeName
{
ScheduledTask ServiceEventManager
{
TaskName = 'TaskRunAsNetworkService'
Ensure = 'Present'
ActionExecutable = 'C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe'
ActionArguments = '-Command Set-Content -Path c:\temp\seeme.txt -Value ''Worked!'''
ScheduleType = 'Once'
RepeatInterval = '00:15:00'
RepetitionDuration = '4.00:00:00'
BuiltInAccount = 'NETWORK SERVICE'
}
}
}
Loading