github mickem/nscp 0.11.33

pre-release5 hours ago

What's Changed

NSClient++ 0.11.33 Release Notes

Changes since 0.11.32 (commit 06be00cc).

This release is focused on two user-facing areas:

  1. HTTP proxy support for every HTTP-based client (NRDPClient, ElasticClient, Op5Client, the configuration
    loader, ...).
  2. CheckDisk improvements — a new check_single_file command plus five long-standing check_files bug fixes.

HTTP proxy support

NSClient++ can now route HTTP and HTTPS traffic through a corporate proxy. The same configuration surface is used by
every component that builds on the internal http::simple_client (NRDPClient, ElasticClient, Op5Client, the remote
boot.ini loader, ...).

For HTTPS targets the client opens a CONNECT tunnel to the proxy, validates the proxy's response, and only then performs
the TLS handshake — so a single setting covers both http:// and https:// URLs.

Per-target proxy on submit (NRDP, Elastic, Op5)

Two new options are accepted on every HTTP client command and target:

Option Purpose
proxy Proxy URL — scheme://[user:pass@]host[:port]/. Empty value disables the proxy.
no-proxy Comma-separated list of hosts that bypass the proxy. A leading . is a suffix match.

Example — submit an NRDP check through a corporate proxy, but never proxy intranet hosts:

nscp client --module NRDPClient --query submit_nrdp \
    --host nagios.example.com --token mytoken \
    --proxy http://alice:s%40cret@proxy.corp.example:3128/ \
    --no-proxy localhost,127.0.0.1,.internal \
    --command check_disk --result OK --message "All disks healthy"

The same keys are accepted in nsclient.ini target definitions:

[/settings/NRDP/client/targets/nagios]
address = https://nagios.example.com/nrdp/
token = mytoken
proxy = http://proxy.corp.example:3128/
no proxy = localhost,127.0.0.1,.internal

Notes:

  • If the proxy needs authentication, embed credentials in the URL — they are sent as Proxy-Authorization: Basic. Both
    @ and : inside the username/password must be percent-encoded (alice:s%40cret decodes to alice:s@cret).
  • Bypass matching is case-insensitive. .internal matches both foo.internal and internal.
  • On a 407 Proxy Authentication Required the proxy's response body is now captured in the error message, so
    misconfigured credentials produce an actionable error instead of an opaque "connect failed".

Proxy for the configuration loader

If boot.ini itself lives behind a proxy, configure it in boot.ini:

[proxy]
url = http://proxy.corp.example:3128/
no_proxy = localhost,127.0.0.1,.internal

The proxy is applied to the initial configuration download, every refresh, and any attachments declared in the remote
configuration. HTTPS targets are tunnelled via CONNECT, so the same setting covers http:// and https:// settings
URLs.

Failed downloads still fall back to the cached copy of the configuration if one is present, so a transient proxy
outage will not stop NSClient++ from starting — but the very first run on a fresh machine needs the proxy to be
reachable.

What is not included

  • Only the http:// proxy scheme is supported. socks5:// / https:// proxies are not.
  • No automatic detection of system proxy settings (HTTP_PROXY env vars, WinINET / WPAD). The proxy must be configured
    explicitly.

CheckDisk: new command check_single_file

check_single_file is a focused variant of check_files for inspecting a single, known path. Compared to using
check_files for the same job it has:

  • Only one required argument (file=<path>) — no path + pattern, no max-depth, no total.
  • A clear error when the input is empty (No file specified (use file=<path>)).
  • UNKNOWN: File not found: <path> when the file is missing — instead of the empty-set / "No files found" workflow that
    surprised users in #613.
  • A useful default detail-syntax (%(filename) (size=%(size), age=%(age))) so a no-threshold run is informative on
    its own.

All existing filter keywords (size, age, written, version, line_count, type, ...) work, because the
implementation reuses the existing check_files filter machinery.

Examples

Confirm a file exists:

check_single_file file=C:/Windows/System32/notepad.exe
OK: notepad.exe (size=201728, age=12345)

Warn when a file becomes stale:

check_single_file file=C:/windows/WindowsUpdate.log "warn=age > 5m" "crit=age > 1h"
CRITICAL: WindowsUpdate.log (size=276, age=917)

Pin a specific binary version:

check_single_file file="C:/Windows/System32/notepad.exe" \
    "crit=version != '1.2.3.4'" \
    "detail-syntax=%(filename): %(version)"
CRITICAL: notepad.exe: 6.2.26100.8115

CheckDisk: check_files bug fixes

#730max-depth=0 is now "top directory only"

Previously max-depth=0 caused check_files to bail out before scanning anything, returning no files found for users
who simply asked for a non-recursive scan. It is now equivalent to max-depth=1 (scan the top directory, do not
recurse). max-depth=N for N >= 1 is unchanged, so this is not a breaking change for existing configurations.

check_files path=C:/logs pattern=*.log max-depth=0

#598 — Non-ASCII paths now work

Beware that this is still tricky to get right if you are checking from linux via for instance NRPE.

Recursive scanning previously called GetFileAttributes through boost::filesystem's system codepage conversion while
every other Win32 call in the same scan went through UTF-8 conversion. Paths containing accented letters, CJK
characters, etc. were silently mangled and reported as File was NOT found even when they existed. They now work
consistently.

#613 — Missing paths surface as UNKNOWN

If the path passed to check_files could not be opened (typo, deleted directory, permission denied) the failure was
previously hidden behind the configured empty-state — typically OK or a generic No files found. Operators monitoring
file/folder counts therefore got a green status for misconfigured paths.

Top-level paths that cannot be opened now produce an explicit UNKNOWN: Path was not found: <path>, so the failure is
visible in the monitoring system.

#605 — Reparse points are skipped during recursion

NTFS junctions, symlinks and mount points all look like directories, so a tree containing a junction back into itself
was walked twice and files were counted twice. check_files now skips entries whose attributes contain
FILE_ATTRIBUTE_REPARSE_POINT when recursing — the same default as Windows tools like robocopy /XJ. Files matched in
the top-level pass are unaffected.

#717 — Legacy CheckFiles defaults empty-state=ok

The legacy CheckFiles shim translates old-style arguments (path, pattern, MaxWarn, MaxCrit, …) into modern
check_files arguments. Modern check_files defaults empty-state to unknown, which meant a legacy command that
found zero files came back as UNKNOWN even though the original 0.4-era behaviour was to return OK. The shim now sets
empty-state=ok when translating, restoring the legacy semantics.


Other changes

  • Numerous small clean-ups across CheckSystem, CheckSystemUnix, CheckNet, NRDPClient, Op5Client, ElasticClient and the
    WEB server — internal only, no behaviour change.
  • New unit test infrastructure for the settings layer (settings_dummy_test, settings_http_test, settings_ini_test,
    settings_interface_impl_test) and 100+ new tests around the HTTP client / proxy code paths.
  • Linux build is back to green after the proxy work.

Upgrade notes

  • No configuration migration is required. All new keys (proxy, no-proxy, the [proxy] boot.ini section) are opt-in.
  • The check_files fixes change observable behaviour in a few corner cases:
    • max-depth=0 now scans the top directory instead of returning empty (#730).
    • Missing paths now return UNKNOWN instead of OK/empty (#613).
    • Junction loops are no longer double-counted (#605).
    • Legacy CheckFiles calls that previously returned UNKNOWN on empty results will now return OK (#717).
      If any existing alerting was relying on the old behaviour of these specific corner cases, review it before
      upgrading.

Full Changelog: 0.11.32...0.11.33

Don't miss a new nscp release

NewReleases is sending notifications on new releases.