Skip to content

Commit

Permalink
Improve README
Browse files Browse the repository at this point in the history
  • Loading branch information
lazyfrosch committed Sep 7, 2020
1 parent 8fb5696 commit e905961
Showing 1 changed file with 124 additions and 63 deletions.
187 changes: 124 additions & 63 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,67 +1,21 @@
# check_by_winrm

check_by_winrm is a check plugin for Icinga 2 written in GO. It's build on the go-library [winrm](https://github.com/masterzen/winrm), which can execute remote commands on Windows machines through
the use of WinRM/WinRS.
Icinga check plugin to run checks and other commands directly on any Windows system using WinRM (Windows Remote Management).

## Preparing the remote Windows machine for Basic authentication
This project supports only basic authentication for local accounts (domain users are not supported). The remote windows system must be prepared for winrm:
Main use case would be to call one of the [plugins](https://github.com/Icinga/icinga-powershell-plugins)
from the [Icinga Powershell Framework](https://github.com/Icinga/icinga-powershell-framework). This will avoid the
requirement of installing an Icinga 2 agent on every Windows system.

### HTTP
winrm quickconfig
winrm set winrm/config/service/Auth '@{Basic="true"}'
winrm set winrm/config/service '@{AllowUnencrypted="true"}'
winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="1024"}'
The plugin will require WinRM to be preconfigured for access with a HTTPs or HTTP connection.

### HTTPS
By default WinRM uses Kerberos for authentication so Windows never sends the password to the system requesting validation.
WinRM HTTPS requires a local computer "Server Authentication" certificate with a CN matching the hostname, that is not expired, revoked, or self-signed to be installed.
On the remote host, a PowerShell prompt, using the __Run as Administrator__ :
Supported authentication methods:

$CertThumbprint = 'cert_thumbprint';
* Basic with local users
* NTLM with local or AD accounts
* TLS client certificate
* (SSH connection)

$certificate = Get-ChildItem -Path cert:\ -Recurse | Where-Object Thumbprint -eq $CertThumbprint;

if ($null -eq $certificate) {
throw 'The provided thumbprint was not found in any certificate stores';
}

# Allow PS-Remote configuration
Enable-PSRemoting -SkipNetworkProfileCheck -Force;

# Disable HTTP transport for PS-Remoting to ensure encryption
Get-ChildItem WSMan:\Localhost\listener | Where-Object Keys -eq "Transport=HTTP" | Remove-Item -Recurse;

# Set the HTTPS Transport with our provided Thumbprint for the SSL certificate
New-Item -Path WSMan:\LocalHost\Listener -Transport HTTPS -Address * -CertificateThumbPrint $CertThumbprint -Force;

# Set Firewall Rule for allowing communication
New-NetFirewallRule -DisplayName "Windows Remote Management (HTTPS-In)" -Name "Windows Remote Management (HTTPS-In)" -Profile Any -LocalPort 5986 -Protocol TCP;

# Enable the HTTPS lisener
Set-Item WSMan:\localhost\Service\EnableCompatibilityHttpsListener -Value true;

# Disable possible old HTTP firewall rules
Disable-NetFirewallRule -DisplayName "Windows Remote Management (HTTP-In)";
Disable-NetFirewallRule -DisplayName "Windows-Remoteverwaltung (HTTP eingehend)";

winrm set winrm/config/service/auth '@{Basic="true"}';
winrm set winrm/config/client '@{TrustedHosts="*"}';

Restart-Service winrm;

If it's necessary to use a self-signed-certificate, you can follow this [guide](https://www.visualstudiogeeks.com/devops/how-to-configure-winrm-for-https-manually)

## GO build example
To compile for a specific platform, you have to set the GOOS and GOARCH environment variables. For more [information](https://golang.org/pkg/go/build/)

| **Platform** | **GOOS** | **GOARCH** |
| ------------- |:-------------:| -----:|
| Mac | darwin | amd64 |
| Linux | linux | amd64 |
| Windows | windows | amd64 |

### Example - Linux
GOOS=linux GOARCH=amd64 go build -o check_by_winrm main.go
Not supported at the moment is Kerberos.

## Usage

Expand All @@ -88,16 +42,123 @@ Arguments:
-V, --version Print version and exit
```

### Execute a script over http
./check_by_winrm -H 192.168.172.217 -p 5985 --cmd "cscript.exe /T:30 /NoLogo C:\Windows\system32\check_time.vbs 1.de.pool.ntp.org 20 240" --user "windowsuser" --password 'secret!pw'
Also, see the Icinga 2 examples in the [icinga2/ directory](icinga2/).

OK - NTP OK: Offset +0.0556797 secs|'offset'=+0.0556797s;20;240;
## Examples

It is necessary that the PowerShell script exits with an exitcode like *exit 2*, otherwise the plugin could exit with an unexpected exitcode.
Calling a PowerShell plugin from the framework is easy:

### Execute a Icinga PowerShell Framework Commandlet over https
./check_by_winrm -H "example.local.de" --icingacmd "Invoke-IcingaCheckCPU" --user "windowsuser" --password '!secret!pw' --tls --unsecure -t 30
./check_by_winrm -H example.local.de --user 'ad\user' --password '!secret!pw' \
--icingacmd 'Invoke-IcingaCheckCPU -Warning 80 -Critical 90'

[OK] Check package "CPU Load"
| 'core_23_10'=2.31%;;;0;100 'core_23_3'=2.54%;;;0;100 'core_23_15'=2.12%;;;0;100 'core_23_5'=2.39%;;;0;100
'core_23_1'=2.04%;;;0;100 'core_23'=1.93%;;;0;100 'core_2_15'=2.78%;;;0;100 'core_2_10'=2.89%;;;0;100 [...]
Notes:
* You can use `--insecure` to skip CA trust and certificate checks - be careful!
* You can use `--no-tls` to use a HTTP connection

Executing any other Windows program or script, could be another Icinga plugin:

./check_by_winrm -H 192.168.172.217 \
--user 'windowsuser' --password 'secret!pw' \
--cmd "cscript.exe /T:30 /NoLogo C:\Windows\system32\check_time.vbs 1.de.pool.ntp.org 20 240"

OK - NTP OK: Offset +0.0556797 secs|'offset'=+0.0556797s;20;240;

If you run a program or script like this, you need to make sure to exit the script with a proper exit code, to reflect
the correct status for Icinga.

## Preparing the Windows machine

By default, WinRM is not enabled, and if enabled, will only allow Kerberos authentication. WinRM can be configured in
many ways, to allow connections by HTTP or HTTPs.

Best practice would be to configure WinRM with a TLS certificate, signed by the PKI of the Active Directory domain,
and using NTLM auth to access the systems.

Anything you configure via cmd or powershell needs to be run from an administrative shell.

We start with the minimal setup of enabling WinRM and raising the memory limit:

```
winrm quickconfig
winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="1024"}'
```

### Setting up a HTTPS / TLS listener

Make sure to install the certificate in the local machine cert store. This example is using PowerShell.

WinRM HTTPS requires a local computer "Server Authentication" certificate with a CN matching the hostname, that is not
expired, revoked, or self-signed to be installed.

```powershell
# Find the cert
Get-ChildItem -Path cert:\LocalMachine\My -Recurse;
# Put the thumbprint here or script it otherwise
$CertThumbprint = 'cert_thumbprint';
# Allow PS-Remote configuration
Enable-PSRemoting -SkipNetworkProfileCheck -Force;
# (optional) Disable HTTP transport for PS-Remoting to ensure encryption
Get-ChildItem WSMan:\Localhost\listener | Where-Object Keys -eq "Transport=HTTP" | Remove-Item -Recurse;
# Set the HTTPS Transport with our provided Thumbprint for the SSL certificate
New-Item -Path WSMan:\LocalHost\Listener -Transport HTTPS -Address * -CertificateThumbPrint $CertThumbprint -Force;
# Set Firewall Rule for allowing communication
New-NetFirewallRule -DisplayName "Windows Remote Management (HTTPS-In)" `
-Name "Windows Remote Management (HTTPS-In)" -Profile Any -LocalPort 5986 -Protocol TCP;
# Enable the HTTPS lisener
Set-Item WSMan:\localhost\Service\EnableCompatibilityHttpsListener -Value true;
# Disable possible old HTTP firewall rules (names language specific)
Disable-NetFirewallRule -DisplayName "Windows Remote Management (HTTP-In)";
Disable-NetFirewallRule -DisplayName "Windows-Remoteverwaltung (HTTP eingehend)";
# (optional) You can configure hosts that are allowed to connect to WinRM
winrm set winrm/config/client '@{TrustedHosts="*"}';
Restart-Service winrm;
```

If it's necessary to use a self-signed-certificate, you can follow the
[guide on visualstudiogeeks.com](https://www.visualstudiogeeks.com/devops/how-to-configure-winrm-for-https-manually).

### Enabling Basic Auth

Basic auth can be used as fallback for NTLM, but will require a local account on each machine.

```
winrm set winrm/config/service/Auth '@{Basic="true"}'
```

### Enabling unencrypted HTTP or basic auth

**Warning:** This is insecure, and should only be done during testing!

This will allow credentials and data transmitted over an **unencrypted** connection like HTTP.

```
winrm set winrm/config/service '@{AllowUnencrypted="true"}'
```

## Manually building the program

The plugin is written in Golang and can easily be compiled from source, see the [documentation](https://golang.org/doc/)
for further details.

```
GOOS=linux GOARCH=amd64 go build -o check_by_winrm .
GOOS=windows GOARCH=amd64 go build -o check_by_winrm.exe .
```

## Acknowledgements

To Brice Figureau [@masterzen](https://github.com/masterzen), who built a
[WinRM client for golang](https://github.com/masterzen/winrm).

0 comments on commit e905961

Please sign in to comment.