windows_task: Fix handling of multiple triggers

When using `schtasks` a list is returned if the task has multiple
triggers. This merges that list with the last item taking precedence.
This is how `Get-ScheduledTask` behaves.

Initially, I was going to rewrite this resource to use
`Get-ScheduledTask` but the original author purposely did not do this
so that PowerShell v3 would be supported. We only support PowerShell
v5, but I don't want to break any current users and this change didn't
seem to controversial to me.

If it gives us trouble, I recommend rewriting it to use
`Get-ScheduledTask`.

Signed-off-by: Jerry Aldrich <jerryaldrichiii@gmail.com>
This commit is contained in:
Jerry Aldrich 2019-06-28 00:14:24 -07:00
parent 8bcbaf6967
commit 668b8d82bf
5 changed files with 24 additions and 4 deletions

View file

@ -84,6 +84,11 @@ module Inspec::Resources
return nil
end
# If multiple triggers are defined, `schtasks` returns a list.
# This merges that list with the latest item taking precedence.
# This is the same behavior as `Get-ScheduledTask`.
params = params.reduce(:merge) if params.is_a?(Array)
@cache = {
uri: params["URI"],
state: params["State"],

View file

@ -371,8 +371,10 @@ class MockLoader
"get-hotfix -id KB9999999" => empty.call(),
# windows_task doesnt exist
"schtasks /query /v /fo csv /tn 'does-not-exist' | ConvertFrom-Csv | Select @{N='URI';E={$_.TaskName}},@{N='State';E={$_.Status.ToString()}},'Logon Mode','Last Result','Task To Run','Run As User','Scheduled Task State' | ConvertTo-Json -Compress" => cmd.call("schtasks-error"),
# windows_task exist
"schtasks /query /v /fo csv /tn 'WeLovePizza' | ConvertFrom-Csv | Select @{N='URI';E={$_.TaskName}},@{N='State';E={$_.Status.ToString()}},'Logon Mode','Last Result','Task To Run','Run As User','Scheduled Task State' | ConvertTo-Json -Compress" => cmd.call("schtasks-success"),
# windows_task exists and has 1 trigger
"schtasks /query /v /fo csv /tn 'WeLovePizza' | ConvertFrom-Csv | Select @{N='URI';E={$_.TaskName}},@{N='State';E={$_.Status.ToString()}},'Logon Mode','Last Result','Task To Run','Run As User','Scheduled Task State' | ConvertTo-Json -Compress" => cmd.call("schtasks-success-single-trigger"),
# windows_task exists and has multiple triggers
"schtasks /query /v /fo csv /tn 'WeLoveMultiplePizzas' | ConvertFrom-Csv | Select @{N='URI';E={$_.TaskName}},@{N='State';E={$_.Status.ToString()}},'Logon Mode','Last Result','Task To Run','Run As User','Scheduled Task State' | ConvertTo-Json -Compress" => cmd.call("schtasks-success-multiple-triggers"),
"modinfo -F version dhcp" => cmd.call("modinfo-f-version-dhcp"),
# crontab display for root / current user
"crontab -l" => cmd.call("crontab-root"),

View file

@ -0,0 +1 @@
[{"URI":"\\Microsoft\\Windows\\Time Synchronization\\SynchronizeTime","State":"Ready","Logon Mode":"Interactive/Background","Last Result":"999","Task To Run":"%windir%\\system32\\sc.exe start w32time task_started","Run As User":"LOCAL SERVICE","Scheduled Task State":"Enabled"},{"URI":"\\Microsoft\\Windows\\Time Synchronization\\SynchronizeTime","State":"Ready","Logon Mode":"Interactive/Background","Last Result":"1056","Task To Run":"%windir%\\system32\\sc.exe start w32time task_started","Run As User":"LOCAL SERVICE","Scheduled Task State":"Enabled"}]

View file

@ -0,0 +1 @@
{"URI":"\\Microsoft\\Windows\\Time Synchronization\\SynchronizeTime","State":"Ready","Logon Mode":"Interactive/Background","Last Result":"1056","Task To Run":"%windir%\\system32\\sc.exe start w32time task_started","Run As User":"LOCAL SERVICE","Scheduled Task State":"Enabled"}

View file

@ -3,11 +3,11 @@ require "inspec/resource"
require "inspec/resources/windows_task"
describe "Inspec::Resources::WindowsTasks" do
it "verify parsing a windows task that does not exist" do
it "can handle a Windows task that does not exist" do
resource_fail = MockLoader.new(:windows).load_resource("windows_task", "does-not-exist")
_(resource_fail.exists?).must_equal false
end
it "verify parsing a windows task which is valid" do
it "parses a windows task with one trigger correctly" do
resource = MockLoader.new(:windows).load_resource("windows_task", "WeLovePizza")
_(resource.enabled?).must_equal true
_(resource.disabled?).must_equal false
@ -18,4 +18,15 @@ describe "Inspec::Resources::WindowsTasks" do
_(resource.type).must_equal "windows-task"
_(resource.to_s).must_equal "Windows Task 'WeLovePizza'"
end
it "parses a windows task with more than one trigger correctly" do
resource = MockLoader.new(:windows).load_resource("windows_task", "WeLoveMultiplePizzas")
_(resource.enabled?).must_equal true
_(resource.disabled?).must_equal false
_(resource.logon_mode).must_equal "Interactive/Background"
_(resource.last_result).must_equal "1056"
_(resource.task_to_run).must_equal '%windir%\\system32\\sc.exe start w32time task_started'
_(resource.run_as_user).must_equal "LOCAL SERVICE"
_(resource.type).must_equal "windows-task"
_(resource.to_s).must_equal "Windows Task 'WeLoveMultiplePizzas'"
end
end