sensu-plugins-windows 2.2.1 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,603 @@
1
+ #
2
+ # check-muilti-template.ps1
3
+ #
4
+ # DESCRIPTION:
5
+ # This is a teplate which should be imported and adapted with the use of a
6
+ # $CheckOptions object.
7
+ #
8
+ # By default, it will check the state of Windows services, just to provide
9
+ # an example. Please also see the example 'check-adapters.ps1' for more
10
+ # info on how to build on this template.
11
+ #
12
+ # Please see the '-Help' parameter, under the 'Sensu check token
13
+ # substitution' header for more info on some extra parsing features.
14
+ #
15
+ # OUTPUT:
16
+ # plain text
17
+ #
18
+ # PLATFORMS:
19
+ # Windows
20
+ #
21
+ # DEPENDENCIES:
22
+ #
23
+ # USAGE:
24
+ # Please run this check with the '-help' parameter for more info.
25
+ #
26
+ # NOTES:
27
+ #
28
+ # LICENSE:
29
+ # Copyright 2016 James Booth <james@absolutejam.co.uk>
30
+ # Released under the same terms as Sensu (the MIT license); see LICENSE for details.
31
+ #
32
+
33
+
34
+ #REGION Configurables
35
+
36
+ [CmdletBinding()]
37
+ Param(
38
+ # Items to check. If any of these items are in a 'failed' state, the check
39
+ # will return a CRITICAL (2) status.
40
+ # Please supply -Help for more information.
41
+ [Parameter(
42
+ Mandatory = $False
43
+ )]
44
+ [array]$CriticalItems,
45
+
46
+ # Items to check. If any of these items are in a 'failed' state, the check
47
+ # will return a WARNING (1) status.
48
+ # Please supply -Help for more information.
49
+ [Parameter(
50
+ Mandatory = $False
51
+ )]
52
+ [array]$ImportantItems,
53
+
54
+ # Display help about this check.
55
+ [switch]$Help = $Help
56
+ # This is so wrapper scripts can pass through '-help'
57
+
58
+ )
59
+
60
+ # Default options. Overridee after importing if required.
61
+ $CheckOptions = @{
62
+ # Example output using below values:
63
+ # CheckName CRITICAL: The following items are in a failed state:
64
+ # - ItemOne
65
+ # - ItemTwo
66
+
67
+ # The name of the check
68
+ 'CheckName' = 'CheckItem'
69
+ # The message to display in event of an OK state
70
+ 'MessageOK' = 'All items are in an OK state.'
71
+ # The message to display in event of a WARNING state
72
+ 'MessageImportant' = 'The following important items are in a failed state:'
73
+ # The message to display in event of a CRITICAL state
74
+ 'MessageCritical' = 'The following critical items are in a failed state:'
75
+ # The message to display in event of missing items
76
+ 'MessageMissing' = 'The following items are missing:'
77
+ # The message to display if no items are specified
78
+ 'MessageNoneSpecified' = 'No items specified.'
79
+ # Change this to $True if you want to check for items that are missing
80
+ # from FailedItems
81
+ 'Inverse' = $False
82
+ # Check if any items are missing
83
+ 'CheckMissing' = $True
84
+ # State of check in the event of missing items
85
+ # (1 OK 2 WARNING 3 CRITICAL)
86
+ 'MissingState' = 2
87
+
88
+ # NOTE: The following scriptblocks must return comparable data
89
+ # eg. an array of strings
90
+ # ScriptBlock to get ALL items
91
+ 'ScriptBlockBaseItems' = {
92
+ Get-Service |
93
+ Select-Object -ExpandProperty Name
94
+ }
95
+ # ScriptBlock to get FAILED items
96
+ 'ScriptBlockMatchItems' = {
97
+ Get-Service |
98
+ Where-Object { $_.Status -ne 'Running' } |
99
+ Select-Object -ExpandProperty Name
100
+ }
101
+ # Help message for this check
102
+ 'CheckHelp' = @'
103
+ Checks whether any specified items are in a failed state.
104
+
105
+ Arguments:
106
+ -CriticalItems A string of comma-separated items
107
+ -ImportantItems A string of comma-separated items
108
+ -Help Show help
109
+
110
+ Example usage:
111
+ powershell.exe -file check-multi-template.ps1 -criticalitems "item1,item2" -warningitems "item3,item4"
112
+
113
+ '@
114
+ }
115
+
116
+ #ENDREGION Configurables
117
+
118
+
119
+ #REGION Functions
120
+
121
+ Function Format-ParamArray {
122
+ <#
123
+ .SYNOPSIS
124
+ Convert an array of strings that contain comma-separated values into
125
+ a single array of all the values. Also removes instances of 'None'.
126
+ .EXAMPLE
127
+ Add-OutputEntry -Status 2 -Items 'alpha','bravo'
128
+ #>
129
+ [CmdletBinding()]
130
+ Param(
131
+ # Array of arrays or strings to be flattened
132
+ [Parameter(
133
+ Mandatory = $False
134
+ )]
135
+ [string[]]$Param = @()
136
+ )
137
+
138
+ # Convert a single string into an array with a single value
139
+ if ($Param -is [string]) {
140
+ $Return = @($Param)
141
+ return ,$Return
142
+ }
143
+
144
+ # Flatten the (potential) array into a string
145
+ $Param = $Param -Join ','
146
+ # Strip any instances of 'None'
147
+ $Param = $Param -Replace 'None[,]?',''
148
+ # Replace multiple consecutive commas with a single comma
149
+ $Param = $Param -Replace '[,]{2,}',','
150
+ # If the last character is a comma, remove it
151
+ if ($Param[-1] -eq ',') {
152
+ $Param = $Param.substring(0, $Param.Length-1)
153
+ }
154
+ # Split into an array
155
+ [array]$Param = $Param -split ','
156
+
157
+ return ,$Param
158
+ }
159
+
160
+ Function Write-ExitState {
161
+ <#
162
+ .SYNOPSIS
163
+ Exit script with supplied exit code
164
+ .PARAMETER ExitState
165
+ The exit code/state of the check (0 OK, 1 WARNING, 2 CRITICAL)
166
+ #>
167
+ [CmdletBinding()]
168
+ Param(
169
+ [Parameter(
170
+ Mandatory = $False
171
+ )]
172
+ [ValidateSet(0, 1, 2)]
173
+ [int]$ExitState = 0
174
+ )
175
+
176
+ Exit $ExitState
177
+ }
178
+
179
+ Function Add-OutputEntry {
180
+ <#
181
+ .SYNOPSIS
182
+ Append check output to 'Output' array.
183
+ .DESCRIPTION
184
+ Allows multiple levels of check results to be included in a check's
185
+ output by adding them all to a single 'Output' array and joining them
186
+ upon submitting check result.
187
+ .PARAMETER State
188
+ The state of the check (0 OK, 1 WARNING, 2 CRITICAL)
189
+ .PARAMETER Items
190
+ Items to format into a bullet list that will be included in the check
191
+ output, eg. a list of failed services that need attention.
192
+ .PARAMETER Message
193
+ Override the default message if required.
194
+ .EXAMPLE
195
+ Add-OutputEntry -Status 2 -Items 'alpha','bravo'
196
+ #>
197
+ [CmdletBinding()]
198
+ Param(
199
+ # The check state (0, 1, 2)
200
+ [Parameter(
201
+ Mandatory = $False
202
+ )]
203
+ [ValidateSet(0, 1, 2)]
204
+ [int]$State = 0,
205
+
206
+ # Items to be enumerated in the check output.
207
+ [Parameter(
208
+ Mandatory = $False
209
+ )]
210
+ [array]$Items,
211
+
212
+ # Supply a custom message.
213
+ [Parameter(
214
+ Mandatory = $False
215
+ )]
216
+ [string]$Message
217
+ )
218
+
219
+ $OutputEntry = New-Object PSObject -Property @{
220
+ 'State' = $State
221
+ 'Items' = $Items
222
+ 'Message' = $Message
223
+ }
224
+ $Output.Add($OutputEntry) | Out-Null
225
+
226
+ }
227
+
228
+ Function Test-NullParameters {
229
+ <#
230
+ .SYNOPSIS
231
+ Exit with OK state if no parameters are passed to script.
232
+
233
+ .PARAMETER Parameters
234
+ Check that each item in the array isn#t an empty string.
235
+ #>
236
+ [CmdletBinding()]
237
+ Param(
238
+ [array]$Parameters
239
+ )
240
+
241
+ # Check if any of the parameters (eg. CriticalItems) is empty
242
+ $ParamCount = 0
243
+ ForEach ($Parameter in $Parameters) {
244
+ $ParamCount += $Parameter |
245
+ Where-Object { $_ -ne '' } |
246
+ Measure-Object |
247
+ Select-Object -ExpandProperty Count
248
+ }
249
+
250
+ if ($ParamCount -eq 0) {
251
+ Add-OutputEntry -State 0 -Message $CheckOptions.MessageNoneSpecified
252
+ Write-CheckResult
253
+ }
254
+
255
+ }
256
+
257
+ Function Compare-CheckItems {
258
+ <#
259
+ .SYNOPSIS
260
+ Compares an 'BaseItems' array against an array of items that
261
+ we want to check the status of.
262
+
263
+ .DESCRIPTION
264
+ Compares a 'CompareItems' array against a 'BaseItems' array,
265
+ returning either those items that are missing from BaseItems
266
+ (-Missing flag), items that are present in both arrays.
267
+
268
+ This lets us compare a list of critical services we want
269
+ to ensure are running against an array of failed services,
270
+ or compare a list of users we want to ensure are absent from
271
+ the system against all users on the system.
272
+
273
+ .PARAMETER BaseItems
274
+ An arrayo of all items in a specific state, such as all services
275
+ available or all network adapters that are disconnected.
276
+
277
+ .PARAMETER CompareItems
278
+ An array of items that we want to explicitly check against the
279
+ BaseItems array.
280
+
281
+ .PARAMETER Missing
282
+ Supply this parameter if you only want to return items that have
283
+ been supplied but are missing from the BaseItems array (Essentially
284
+ reverses the effect of the function).
285
+
286
+ .EXAMPLE
287
+ $CriticalServices = 'dhcp','dnscache'
288
+ $AllServices = Get-Services | Select-Object -ExpandProperty Name
289
+ Compare-CheckItems -BaseItems $AllServices -CompareItems $CriticalServices
290
+
291
+ #>
292
+ [CmdletBinding()]
293
+ Param(
294
+ [array]$BaseItems,
295
+ [array]$CompareItems,
296
+ [switch]$Missing
297
+ )
298
+
299
+ # If an array of arrays was passed, extract all values. Otherwise just
300
+ # use values from array.
301
+ $MergedCompareItems = New-Object -TypeName System.Collections.ArrayList
302
+ ForEach ($Item in $CompareItems |
303
+ Where-Object { $_ -ne '' }) {
304
+ if ($Item -is [array]) {
305
+ ForEach ($ArrayItem in $Item |
306
+ Where-Object { $_ -ne '' }) {
307
+ $MergedCompareItems.Add($ArrayItem) | Out-Null
308
+ }
309
+ } else {
310
+ $MergedCompareItems.Add($Item) | Out-Null
311
+ }
312
+ }
313
+
314
+ if ($Missing) {
315
+ $ReturnItems = Compare-Object -ReferenceObject $MergedCompareItems `
316
+ -DifferenceObject $BaseItems |
317
+ Where-Object { $_.SideIndicator -eq '<=' } |
318
+ Select-Object -ExpandProperty InputObject
319
+
320
+
321
+ } else {
322
+ $ReturnItems = Compare-Object -ReferenceObject $MergedCompareItems `
323
+ -DifferenceObject $BaseItems `
324
+ -ExcludeDifferent `
325
+ -IncludeEqual |
326
+ Where-Object { $_.SideIndicator -eq '==' } |
327
+ Select-Object -ExpandProperty InputObject
328
+ }
329
+
330
+ # This hackery forces Powershell to return an array and stops it mangling
331
+ # it into $Null or a string
332
+ if ($ReturnItems -eq $Null) {
333
+ $ReturnItems = ,@()
334
+ Return $ReturnItems
335
+ } else {
336
+ return ,$ReturnItems
337
+ }
338
+ }
339
+
340
+ Function Get-CheckStatus {
341
+ <#
342
+ .SYNOPSIS
343
+ Returns a string containing the check status based on numerical state/
344
+ #>
345
+ [CmdletBinding()]
346
+ Param(
347
+ [array]$State
348
+ )
349
+
350
+ switch ($State) {
351
+ 0 {
352
+ return New-Object PSObject -Property @{
353
+ 'Status' = 'OK:'
354
+ 'MessageBody' = $CheckOptions.MessageOK
355
+ }
356
+ }
357
+
358
+ 1 {
359
+ return New-Object PSObject -Property @{
360
+ 'Status' = 'WARN:'
361
+ 'MessageBody' = $CheckOptions.MessageImportant
362
+ }
363
+ }
364
+
365
+ 2 {
366
+ return New-Object PSObject -Property @{
367
+ 'Status' = 'CRITICAL:'
368
+ 'MessageBody' = $CheckOptions.MessageCritical
369
+ }
370
+ }
371
+ }
372
+ }
373
+
374
+ Function Write-CheckResult() {
375
+ <#
376
+ .SYNOPSIS
377
+ Return the frmatted check result based on $Output
378
+ #>
379
+
380
+ # Get the highest 'state' value and use that as the total check state
381
+ $FinalState = $Output | Sort-Object -Property state -Descending |
382
+ Select-Object -First 1 |
383
+ Select-Object -ExpandProperty 'State'
384
+
385
+ $FinalStatus = Get-CheckStatus -State $FinalState |
386
+ Select-Object -ExpandProperty 'Status'
387
+
388
+ # Compile the final output
389
+ $CheckMessage = New-Object -TypeName System.Collections.ArrayList
390
+ $CheckMessage.Add(
391
+ ('{0} {1}' -f $CheckOptions.CheckName,$FinalStatus)
392
+ ) | Out-Null
393
+
394
+ ForEach ($State in $Output |
395
+ Group-Object -Property State |
396
+ Sort-Object -Property State -Descending) {
397
+
398
+ ForEach ($Entry in $State.Group) {
399
+ $CheckState = Get-CheckStatus -State $Entry.State
400
+
401
+ if ($Entry.Message) {
402
+ $MessageBody = $Entry.Message
403
+ } else {
404
+ $MessageBody = $CheckState.MessageBody
405
+ }
406
+
407
+ if ($Entry.Items) {
408
+ $Bullet = "`r`n -"
409
+ $ItemsInformation = "$Bullet {1}" -f $Bullet,($Entry.Items -join "$Bullet ")
410
+ } else {
411
+ $ItemsInformation = ''
412
+ }
413
+
414
+ #$Entry | gm
415
+
416
+ # Format message to add
417
+ $Message = " {0}{1}" -f $MessageBody,$ItemsInformation
418
+
419
+ $CheckMessage.Add($Message) | Out-Null
420
+ }
421
+ }
422
+
423
+ Write-Output ($CheckMessage -join "`r`n")
424
+ Write-ExitState -ExitState $FinalState
425
+ }
426
+
427
+ Function Write-Help() {
428
+ <#
429
+ .SYNOPSIS
430
+ Exit, showing help text.
431
+ #>
432
+ Write-Output ("{0}`r`n{1}" -f $CheckOptions.CheckHelp, $CheckMultiHelp)
433
+ Write-ExitState -ExitState 0
434
+ }
435
+
436
+ # This is standard across all checks using this template.
437
+ $CheckMultiHelp = @'
438
+ Sensu check token substitution:
439
+ Because this check is designed to make full use of Sensu's check token
440
+ substitution (https://sensuapp.org/docs/latest/reference/checks.html#check-token-substitution)
441
+ feature, some special considerations have been taken for how the arguments are parsed.
442
+
443
+ The main parameters support a list of of comma-separated strings.
444
+ eg. -CriticalItems 'value1','value2'
445
+ They also accepts accept a single string with comma-separated values.
446
+ eg. -param1 'value1,value2'
447
+ ...or you can mix & match the two and all of the values will be merged.
448
+ eg. -param1 'value1','value2,value3'
449
+ Additionally, any use of the word 'None' will be ignored.
450
+ eg. -param1 'value1','None,value2','None'
451
+
452
+ This is because Sensu's client attribute substitution tokens only work with
453
+ flat strings, but by supporting both of the above methods, it allows the use
454
+ of multiple values within a single check/client attribute AND multiple
455
+ different client/check attributes to be used. Additionally, because 'None'
456
+ is ignored, it allows the user to provide a default value in the check
457
+ token substitution, as not to throw an error if the value is missing.
458
+
459
+ Token substitution example:
460
+ Check attribute 'check_attr' = "alpha,bravo"
461
+ Client attribute 'client_attr' = "charlie,delta"
462
+
463
+ powershell.exe -File check.ps1 -param1 ":::check_attr|None:::",":::missing_attr|None:::",":::client_attr|None:::"
464
+
465
+ Which evaluates to:
466
+
467
+ powershell.exe -File check.ps1 -param "alpha,bravo","None","charlie,delta"
468
+
469
+ The script then strips any instances of 'None' and processes the
470
+ comma-separated string as single flat array.
471
+ '@
472
+
473
+ #
474
+ # MAIN FUNCTION
475
+ #
476
+ Function Invoke-Main {
477
+ <#
478
+ .SYNOPSIS
479
+ The main process. Run automatically when running the script, or when
480
+ called if script is imported.
481
+
482
+ .PARAMETER CriticalItems
483
+ Variable to pass through to CriticalItems
484
+
485
+ .PARAMETER ImportantItems
486
+ Variable to pass through to ImportantItems
487
+ #>
488
+ [CmdletBinding()]
489
+ Param(
490
+ [Parameter(
491
+ Mandatory = $False
492
+ )]
493
+ [array]$CriticalItems = @(),
494
+
495
+ [Parameter(
496
+ Mandatory = $False
497
+ )]
498
+ [array]$ImportantItems = @()
499
+ )
500
+ # If -Help is passed, show help and exit
501
+ if ($Help) {
502
+ Write-Help
503
+ }
504
+
505
+ # Setup
506
+ $Output = New-Object -TypeName System.Collections.ArrayList
507
+
508
+ # Merge the cli parameters into a single string
509
+ $CriticalItemList = Format-ParamArray -Param $CriticalItems
510
+ $ImportantItemList = Format-ParamArray -Param $ImportantItems
511
+
512
+ # Exit if no/null parameters specified
513
+ Test-NullParameters -Parameters $CriticalItemList,$ImportantItemList
514
+
515
+ # Evaluate the scriptblocks so we can compare items passed into the script
516
+ # vs. running state.
517
+ if ($CheckOptions.CheckMissing -ne $False -and
518
+ $CheckOptions.Inverse -ne $True) {
519
+ $BaseItems = & $CheckOptions.ScriptblockBaseItems
520
+ }
521
+ $MatchItems = & $CheckOptions.ScriptBlockMatchItems
522
+ if ($MatchItems.Count -eq 0) { $MatchItems = ,@() }
523
+
524
+ # Check that all of the items specified are present before checking their
525
+ # status
526
+ if ($CheckOptions.CheckMissing -ne $False -and
527
+ $CheckOptions.Inverse -ne $True) {
528
+ $MissingItems = Compare-CheckItems -BaseItems $BaseItems `
529
+ -CompareItems $CriticalItemList,
530
+ $ImportantItemList `
531
+ -Missing
532
+
533
+ if ($MissingItems.Count -gt 0) {
534
+ Add-OutputEntry -State $CheckOptions.MissingState `
535
+ -Message $CheckOptions.MessageMissing `
536
+ -Items $MissingItems
537
+ }
538
+ }
539
+
540
+
541
+ # ImportantItems
542
+ if ($CheckOptions.Inverse) {
543
+ # Only return items that are MISSING from $MatchItems
544
+ $MatchedImportantItems = Compare-CheckItems `
545
+ -BaseItems $MatchItems `
546
+ -CompareItems $ImportantItemList `
547
+ -Missing
548
+
549
+ } else {
550
+ # Return items that match those in $MatchItems
551
+ $MatchedImportantItems = Compare-CheckItems `
552
+ -BaseItems $MatchItems `
553
+ -CompareItems $ImportantItemList
554
+
555
+ }
556
+
557
+ if ($MatchedImportantItems.Count -gt 0) {
558
+ Add-OutputEntry -State 1 -Items $MatchedImportantItems
559
+ }
560
+
561
+
562
+
563
+ # CriticalItems
564
+ if ($CheckOptions.Inverse) {
565
+ # Only return items that are MISSING from $MatchItems
566
+ $MatchedCriticalItems = Compare-CheckItems `
567
+ -BaseItems $MatchItems `
568
+ -CompareItems $CriticalItemList `
569
+ -Missing
570
+ } else {
571
+ # Return items that match those in $MatchItems
572
+ $MatchedCriticalItems = Compare-CheckItems `
573
+ -BaseItems $MatchItems `
574
+ -CompareItems $CriticalItemList
575
+ }
576
+
577
+ if ($MatchedCriticalItems.Count -gt 0) {
578
+ Add-OutputEntry -State 2 -Items $MatchedCriticalItems
579
+ }
580
+
581
+
582
+
583
+ # No issues so far!
584
+ if ($Output.Count -eq 0) {
585
+ Add-OutputEntry -State 0
586
+ }
587
+
588
+ Write-CheckResult
589
+
590
+ }
591
+
592
+ #ENDREGION Functions
593
+
594
+
595
+ #REGION Main
596
+
597
+ # Run 'Invoke-Main' if run directly, but don't if imported.
598
+ # (Python way is best way)
599
+ $Imported = $MyInvocation.InvocationName -eq '.'
600
+ if (!$Imported) {
601
+ Invoke-Main -CriticalItems $CriticalItems `
602
+ -ImportantItems $ImportantItems
603
+ }