PoshSensu is a PowerShell module to handle running PowerShell scripts as Sensu checks. The results are submitted to a Sensu client via the client socket input feature that the Sensu client provides.
The Sensu client already handles executing PowerShell checks, so you may be wondering why I wrote a module for this. This is why:
When a PowerShell process first loads, there is a fairly large CPU impact - usually spiking to around 20-30% for a second or two. When you are running 20-30 PowerShell checks every minute on your servers, this adds up to a lot of wasted CPU cycles.
This module aims to resolve this problem.
- Sends check results to Sensu Cleint via TCP to the the client socket input feature
- Easily to use JSON configuration file
- Allows setting different check groups that may have different max execution times, ttl's or execution intervals
- Automatic configuration file reloads allowing adding additional checks without having to restart any services
- Detailed logging (can be turned off)
- Runs checks using PowerShell Background Jobs
- Checks can be loaded from multiple JSON files, making configuration management and templating of checks easy.
- Rotates its own log file
- Runs as a service
- Download the repository and place into a PowerShell Modules directory called PoshSensu. The module directories can be found by running
$env:PSModulePath
in PowerShell. For example,C:\Program Files\WindowsPowerShell\Modules\PoshSensu
- Make sure the files are un-blocked by right clicking on them and going to properties
- Make a new folder to store the configuration file, for example,
C:\PoshSensu
- Copy the
poshsensu_config.json.example
toC:\PoshSensu\poshsensu_config.json
- Modify the
poshsensu_config.json
configuration file. Instructions in the Modifying the Configuration File section. - Open PowerShell and ensure you set your Execution Policy to allow scripts be run. For example
Set-ExecutionPolicy RemoteSigned
.
You can verify PoshSensu is working correctly by running it in TestMode
. This will show all output to the screen but not actually send check results to the Sensu server.
Open a PowerShell window and do the following:
# Import the module
Import-Module -Name PoshSensu
# Start PoshSensu in TestMode
Start-SensuChecks -ConfigPath 'C:\PoshSensu\poshsensu_config.json' -TestMode
You should see some JSON output of the script starting and the checks returning, which should look similar to this:
You can also run the script without the TestMode
switch in the PowerShell console and checks should be sent to the local Sensu Client.
After you are happy everything is working correctly, you can install PoshSensu as a service.
The easiest way to achieve this is using NSSM - the Non-Sucking Service Manager.
- Download nssm from nssm.cc
- Extract the zip file to your machine, for example to
C:\nssm-2.24
Now you can use NSSM and PowerShell to install the service:
# Change to the nssm path
cd C:\nssm-2.24\win64
# Install Service
Start-Process -FilePath .\nssm.exe -ArgumentList 'install PoshSensu "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "-command "& { Import-Module -Name PoshSensu ; Start-SensuChecks -ConfigPath "C:\PoshSensu\poshsensu_config.json" }"" ' -NoNewWindow -Wait
# Set the service description
Start-Process -FilePath .\nssm.exe -ArgumentList 'set PoshSensu Description "PoshSensu - The PowerShell check runner for Sensu."' -NoNewWindow -Wait
# Start the service
Start-Service -Name PoshSensu
# Make sure the service is running
Get-Service -Name PoshSensu
It is a good idea to check the PoshSensu log file for any errors.
You can remove the service by running the following:
Stop-Service -Name PoshSensu -Force
cd C:\nssm-2.24\win64
Start-Process -FilePath .\nssm.exe -ArgumentList 'remove PoshSensu confirm'
The following section details each setting in the configuration file.
NOTE: When using JSON configuration files, backslashes need to be escaped, for example \
would be \\
.
Key | Default Value | Description |
---|---|---|
sensu_socket_ip | localhost |
IP address or host name of the Sensu client where check results will be sent via TCP |
sensu_socket_port | 3030 |
TCP Port of the Sensu client socket input |
logging_enabled | true |
Enable or disable logging to a file |
logging_level | debug |
Level of logging to perform. Valid options are debug , info , warn , error |
logging_directory | C:\\PoshSensu |
Directory to store the log file. The directory will be created if it doesn't exist |
logging_filename | poshsensu.log |
Name for the log file |
logging_max_file_size_mb | 10 |
The size of the log file before it is rotated |
checks_directory | C:\\Program Files\\WindowsPowerShell\\Modules\\PoshSensu\\Checks |
The directory that contains the PowerShell checks. |
check_groups | N/A |
Array of check groups |
check_group_path | null |
Optional path to directory containing JSON files of additional check groups that will be merged into the configuration file. |
A Check Group is a grouping of checks. Each check group is run in its own PowerShell instance using Background Jobs.
The reason there is multiple check groups it to allow you to bundle checks together that have the same check interval.
You can additionally add any other JSON key/value for the check group and it will get sent to the Sensu client. All key/values in the check group configuration section (including the defaults) are sent to the Sensu server.
There are 2 methods for adding check groups to the configuration file:
- Add them in the main configuration file as a JSON array (shown in
poshsensu_config.json.example
) - Configure the
check_group_path
option in the configuration file to point to a directory containing multiple JSON files, each containing its own check group (show inposhsensu_config.json.example2
).
The below values can be configured for a check group:
Key | Example Value | Description |
---|---|---|
group_name | quickchecks |
Name of the check group. Useful to find the group in the log file |
max_execution_time | 30 |
Used to determine the check group run order. Does not currently have any other function. |
ttl | 120 |
Sent to Sensu so it knows how often the check should be received. If no message is received in this time period, Sensu will throw a warning. |
interval | 60 |
How often each check in this group needs to be run |
checks | N/A |
Array of checks |
Here is an example of a check group configuration that is in its own JSON file (located in .\CheckGroups\checkgroup_services.json
):
{
"group_name": "check_services",
"max_execution_time": 15,
"ttl": 125,
"interval": 60,
"checks": [
{
"name": "service_dhcp",
"type": "metric",
"command": "check_service.ps1",
"arguments": "-Name Dhcp"
},
{
"name": "service_ip_helper",
"type": "metric",
"command": "check_service.ps1",
"arguments": "-Name iphlpsvc"
}
]
}
A check is the PowerShell script that will be run, with the results being sent to the Sensu client.
PoshSensu allows two methods to execute a check, depending on how the check script is written in PowerShell.
This is the most common method of writing advanced PowerShell functions. You wrap PowerShell code in a function Get-Beer { #logic }
block. To use these functions in PowerShell you would usually dot source and then execute the function with paramaters. For example:
# Dot Source the function
. .\Get-Beer.ps1
# Execute the function with optional paramaters
Get-Beer -Location 'The Fridge'
To use a PowerShell function with a check, the check configration option arguments
uses a special syntax - it has a ~
in front of the function name and paramaters. Here is a configuration example of what a check running a function would look like:
{
"name": "disk_c",
"type": "metric",
"command": "Get-VolumePercentUsed.ps1",
"arguments": "~ Get-VolumePercentUsed -Identifier DeviceID -Value 'E:'"
}
Take note of the ~
in front of the function call. This tells PoshSensu it is a function and to dot source it first.
This is a less commonly used method to write PowerShell functions that require input. They usually have a paramater block, but are not wrapped in the function
tags. These are executed diferently in PowerShell, for example:
# Run the function and pass paramaters on the same line
.\check_service.ps1 -Name 'Netlogon'
To execute a check like this with PoshSensu, the check configuration would look like this:
{
"name": "service_spooler",
"type": "metric",
"command": "check_service.ps1",
"arguments": "-Name Spooler"
}
Key | Example Value | Description |
---|---|---|
name | service_bits |
Name of the check that will be sent to Sensu |
type | metric |
The check type, either standard or metric . Setting type to metric will cause OK (exit 0) check results to create events. I recommend keeping this on metric |
command | check_service.ps1 |
The file name of the check to execute in PowerShell. These checks are located in the checks_directory configuration value configured previously. |
arguments | -Name BITS |
Any arguments that are required to run the PowerShell check. Useful when using parameters in your checks. If the check is an advanced PowerShell function, use a ~ in front of the function call. If your arguments contain a variable, for example $true , make sure you escape it with a back tick (``$true`) |
Writing checks for use with the Sensu PowerShell module is reasonably simple. The only requirement is that they return a PSObject or Hash with the mandatory fields output
and status
Mandatory Field | Example Value | Description |
---|---|---|
output | Serivce Check OK: The lanmanworkstation service is running. |
This is where the result or an explanation of the check status is returned |
status | 1 |
A number which relates to Sensu status code. 0 for OK , 1 for WARNING , 2 for CRITICAL and 3 or greater to indicate UNKNOWN |
It is also a good idea to parameterize your checks so they are more useful across multiple servers.
You can use Advanced Functions that have paramaters or just simple PowerShell scripts that return a result without requiring any parameters.
The check can also return key/value which will get sent to the Sensu client. This is handy for providing some more details on the check, for example in the check_service.ps1
check, I am also retrieving DisplayName
, DependentServices
, RequiredServices
and Status
properties from the service object in PowerShell and returning them. These details show up when the check has a problem:
Take a look at some example checks to give yourself an idea how checks work.