Skip to content

Commit 860c3e1

Browse files
authored
Merge pull request #1405 from mickem/test/checknet-external-connectivity
ci+fix: Validate RedHat/Rocky builds, and fix the CA bundle they exposed
2 parents 913553a + 8697b65 commit 860c3e1

13 files changed

Lines changed: 138 additions & 30 deletions

File tree

.github/workflows/integration-tests-linux.yml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,14 +180,19 @@ jobs:
180180
# dependent scenario (icinga, nrpe, nsca, …) skip itself so this stage
181181
# runs without a docker daemon. Each rest-* test spins its own nscp
182182
# via NscpInstance, so no manual start/kill/log-tail is needed here.
183+
#
184+
# This used to be deb-only, from when the harness still needed a docker
185+
# daemon. NSCP_SKIP_DOCKER removed that, but the condition stayed - which
186+
# left the rpm packages with only acceptance-tests.sh for coverage, so
187+
# anything that behaves differently on RHEL went untested. The RPM base
188+
# dependencies already install Node 20 from nodesource, so both package
189+
# types run the same suite.
183190
- name: Install integration harness deps
184-
if: inputs.package-type == 'deb'
185191
working-directory: tests
186192
shell: bash
187193
run: npm install
188194

189195
- name: Run REST scenarios (no-docker)
190-
if: inputs.package-type == 'deb'
191196
working-directory: tests
192197
shell: bash
193198
env:

CMakeLists.txt

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ endif()
2222

2323
# ##############################################################################
2424
#
25-
# Setup cmake enviornment and include custom config overrides
25+
# Setup cmake environment and include custom config overrides
2626
#
2727
# ##############################################################################
2828
if(NSCP_CMAKE_CONFIG)
@@ -328,7 +328,7 @@ if(NOT HAVE_REQUIRED_DEPENDENCIES)
328328
else(NOT HAVE_REQUIRED_DEPENDENCIES)
329329
message(
330330
STATUS
331-
" - All required dependecies found! (some modules and features migh stil be missing though)"
331+
" - All required dependencies found! (some modules and features might still be missing though)"
332332
)
333333
endif(NOT HAVE_REQUIRED_DEPENDENCIES)
334334

@@ -729,7 +729,7 @@ else(WIN32)
729729
set(MAIN_CONFIGURATION
730730
/etc/nscp/nscp.xml
731731
CACHE PATH
732-
"Path for the client configurtion file"
732+
"Path for the client configuration file"
733733
)
734734
set(DEPLOYROOT /usr/bin CACHE PATH "Path to deploy examples into)")
735735
endif(WIN32)
@@ -863,6 +863,13 @@ if(WIN32)
863863
CACHE STRING
864864
"security (certificates) folder"
865865
)
866+
# The service exports the Windows ROOT store here at boot (windows_ca_store),
867+
# so unlike unix this is a path we own rather than one the platform ships.
868+
set(CONFIG_CA_PATH
869+
"\${certificate-path}/windows-ca.pem"
870+
CACHE STRING
871+
"Trusted CA bundle used when a check does not name its own"
872+
)
866873
set(CONFIG_DEFAULT_CACHE_PATH
867874
"\${shared-path}/cache"
868875
CACHE STRING
@@ -920,8 +927,53 @@ else()
920927
set(CONFIG_CERT_FOLDER
921928
"\${shared-path}/security"
922929
CACHE STRING
923-
"securoty (certificates) folder"
930+
"security (certificates) folder"
924931
)
932+
933+
# The trusted CA bundle belongs to the distribution, so this is an absolute
934+
# path that must NOT track CMAKE_INSTALL_PREFIX: a --prefix=/usr/local build
935+
# still reads the system bundle, not /usr/local/etc/ssl/...
936+
#
937+
# Where that bundle lives differs per family, and picking wrong is silent -
938+
# every TLS check that does not name its own CA then fails with "Failed to
939+
# load CA <path>: No such file or directory", including checks against a
940+
# local self-signed server with verification disabled, since the file is
941+
# loaded before the verify mode is considered. Detecting it here works
942+
# because a package is built in a container of the distribution it targets;
943+
# a packager who knows better can override with -DCONFIG_CA_PATH=...
944+
if(NOT CONFIG_CA_PATH)
945+
foreach(
946+
_ca_candidate
947+
"/etc/ssl/certs/ca-certificates.crt" # Debian, Ubuntu, Gentoo
948+
"/etc/pki/tls/certs/ca-bundle.crt" # RHEL, Rocky, Alma, Fedora
949+
"/etc/ssl/ca-bundle.pem" # SUSE
950+
"/etc/ssl/cert.pem" # Alpine, FreeBSD, macOS
951+
)
952+
if(EXISTS "${_ca_candidate}")
953+
set(_ca_detected "${_ca_candidate}")
954+
break()
955+
endif()
956+
endforeach()
957+
if(NOT _ca_detected)
958+
# Nothing found: keep the historical value so the define is never
959+
# empty, and say so - a build host without a CA bundle is unusual
960+
# enough to be worth a line in the configure output.
961+
set(_ca_detected "/etc/ssl/certs/ca-certificates.crt")
962+
message(
963+
WARNING
964+
"No system CA bundle found; defaulting ca-path to ${_ca_detected}. "
965+
"TLS checks that do not name their own CA will fail unless that file exists at runtime "
966+
"(override with -DCONFIG_CA_PATH=/path/to/bundle)."
967+
)
968+
endif()
969+
set(CONFIG_CA_PATH
970+
"${_ca_detected}"
971+
CACHE STRING
972+
"Trusted CA bundle used when a check does not name its own"
973+
)
974+
endif()
975+
message(STATUS "System CA bundle (ca-path): ${CONFIG_CA_PATH}")
976+
925977
set(CONFIG_DEFAULT_CACHE_PATH
926978
"\${shared-path}/cache"
927979
CACHE STRING
@@ -1188,7 +1240,7 @@ set(NSCP_CLIENT_HPP
11881240

11891241
# ##############################################################################
11901242
#
1191-
# Build everything (not already built lik libraries)!
1243+
# Build everything (not already built like libraries)!
11921244
#
11931245
# ##############################################################################
11941246

check_deps.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ set(CMAKE_FIND_LIBRARY_PREFIXES
1111
set(CMAKE_FIND_LIBRARY_SUFFIXES .lib)
1212
#############################################################################
1313
#
14-
# Setup cmake enviornment and include custom config overrides
14+
# Setup cmake environment and include custom config overrides
1515
#
1616
#############################################################################
1717
if(EXISTS ${TARGET}/build.cmake)

include/config.h.in

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@
4646
#define WEB_FOLDER "@CONFIG_WEB_FOLDER@"
4747
#define SCRIPTS_FOLDER "@CONFIG_SCRIPTS_FOLDER@"
4848
#define CERT_FOLDER "@CONFIG_CERT_FOLDER@"
49+
// Trusted CA bundle used whenever a check does not name its own. On Windows the
50+
// service exports the ROOT store to this file at boot; on unix it is the system
51+
// bundle, detected at configure time because its location differs per
52+
// distribution (see CONFIG_CA_PATH in CMakeLists.txt).
53+
#define CA_PATH "@CONFIG_CA_PATH@"
4954
#define LOG_FOLDER "@CONFIG_LOG_FOLDER@"
5055
#ifndef WIN32
5156
#define UNIX_SHARED_PATH_FOLDER "@UNIX_SHARED_PATH_FOLDER@"

installer_lib/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ set(CONFIG_SCRIPTS_FOLDER "\${exe-path}/scripts" CACHE STRING "script folder")
171171
set(CONFIG_CERT_FOLDER
172172
"\${shared-path}/security"
173173
CACHE STRING
174-
"securoty (certificates) folder"
174+
"security (certificates) folder"
175175
)
176176
set(CONFIG_DEFAULT_CACHE_PATH
177177
"\${shared-path}/cache"

modules/CheckNSCP/CheckNSCP.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,10 @@ bool CheckNSCP::loadModuleEx(std::string alias, NSCAPI::moduleLoadMode) {
3838
NSC_DEBUG_MSG_STD("Crash folder is: " + crashFolder.string());
3939

4040
// Default the CA bundle to the trusted system store (${ca-path} expands to
41-
// certificate-path/windows-ca.pem on Windows, /etc/ssl/certs/ca-certificates.crt
42-
// on Linux). The same setting is used by CheckNet's check_http and lets the
43-
// update check validate api.github.com out of the box.
41+
// certificate-path/windows-ca.pem on Windows, and on unix to the
42+
// distribution's own bundle, detected at configure time - see CONFIG_CA_PATH).
43+
// The same setting is used by CheckNet's check_http and lets the update check
44+
// validate api.github.com out of the box.
4445
const std::string default_ca = get_core()->expand_path("${ca-path}");
4546

4647
// clang-format off

modules/CheckNet/CheckNet.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,9 @@ boost::atomic<unsigned short> identifier(0);
3131
bool CheckNet::loadModuleEx(const std::string &, NSCAPI::moduleLoadMode) {
3232
// Resolve the trusted CA bundle path once, at module load. ${ca-path}
3333
// expands to ${certificate-path}/windows-ca.pem on Windows (the auto-
34-
// generated system ROOT bundle) and to /etc/ssl/certs/ca-certificates.crt
35-
// on Linux. check_http hands this through as the default `ca` so HTTPS
34+
// generated system ROOT bundle) and on unix to the distribution's own bundle,
35+
// detected at configure time because its location differs per family
36+
// (CONFIG_CA_PATH). check_http hands this through as the default `ca` so HTTPS
3637
// checks against public-CA-signed servers validate out of the box.
3738
default_ca_ = get_core()->expand_path("${ca-path}");
3839
return true;

service/NSClient++.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ bool NSClientT::load_configuration_2(const bool override_log) {
266266
LOG_ERROR_CORE_STD("COM exception: " + e.reason());
267267
return false;
268268
} catch (...) {
269-
LOG_ERROR_CORE("Unknown exception iniating COM...");
269+
LOG_ERROR_CORE("Unknown exception initiating COM...");
270270
return false;
271271
}
272272

@@ -486,7 +486,7 @@ bool NSClientT::stop_nsclient() {
486486
} catch (com_helper::com_exception &e) {
487487
LOG_ERROR_CORE_STD("COM exception: " + e.reason());
488488
} catch (...) {
489-
LOG_ERROR_CORE("Unknown exception uniniating COM...");
489+
LOG_ERROR_CORE("Unknown exception uninitiating COM...");
490490
}
491491
#endif
492492
LOG_DEBUG_CORE("Stopping: Settings instance");

service/path_manager.cpp

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -85,25 +85,20 @@ std::string nsclient::core::path_manager::get_path_for_key(const std::string &ke
8585
// Static defaults baked in by CMake via config.h. Most are templated on
8686
// ${shared-path} or ${certificate-path}; expand_path resolves the chain.
8787
// Note on ca-path: on Windows the service exports the system ROOT store to
88-
// this file at boot (see windows_ca_store); on Linux this is the de-facto
89-
// Debian/Ubuntu location, overridable via boot.ini's [paths] section
90-
// (or the --path-override CLI flag) for other distros.
88+
// this file at boot (see windows_ca_store); on unix it is the distribution's
89+
// own bundle, whose location differs per family and is therefore detected at
90+
// configure time (CONFIG_CA_PATH). Either way it stays overridable via
91+
// boot.ini's [paths] section or --path-override ca-path=...
9192
static const std::map<std::string, std::string> defaults = {
9293
{"certificate-path", CERT_FOLDER},
9394
{"module-path", MODULE_FOLDER},
9495
{"web-path", WEB_FOLDER},
9596
{"scripts", SCRIPTS_FOLDER},
9697
{"log-path", LOG_FOLDER},
98+
{"ca-path", CA_PATH},
9799
{CACHE_FOLDER_KEY, DEFAULT_CACHE_PATH},
98100
{CRASH_ARCHIVE_FOLDER_KEY, "${shared-path}/crash-dumps"},
99-
#ifdef WIN32
100-
{"ca-path", "${certificate-path}/windows-ca.pem"},
101-
#else
102-
// ca-path stays a literal absolute path: the system CA bundle belongs to
103-
// the distro, lives at /etc/ssl/... regardless of our install prefix, and
104-
// must NOT track ${etc}/NSCP_SYSCONFDIR (a --prefix=/usr/local build still
105-
// reads /etc/ssl/certs/..., not /usr/local/etc/ssl/...).
106-
{"ca-path", "/etc/ssl/certs/ca-certificates.crt"},
101+
#ifndef WIN32
107102
{"shared-path", UNIX_SHARED_PATH_FOLDER},
108103
{"data-path", UNIX_DATA_PATH_FOLDER},
109104
// ${etc} tracks this build's config root (NSCP_SYSCONFDIR) so user

service/path_manager_test.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#include <config.h>
77
#include <gtest/gtest.h>
88

9+
#include <boost/filesystem.hpp>
10+
911
#include <memory>
1012
#include <nsclient/logger/logger.hpp>
1113

@@ -79,6 +81,16 @@ TEST_F(PathManagerTest, CaPathExpandsToBundleFile) {
7981
EXPECT_NE(expanded.find("windows-ca.pem"), std::string::npos);
8082
#else
8183
EXPECT_EQ(expanded.rfind("/etc/", 0), 0u);
84+
85+
// ...and it must name a bundle that is actually there. This used to be one
86+
// hardcoded path for every non-Windows platform - the Debian one - so on
87+
// RHEL-family it named a file that does not exist, and every TLS check that
88+
// did not carry its own ca= failed with "Failed to load CA <path>: No such
89+
// file or directory". CONFIG_CA_PATH now detects the platform bundle at
90+
// configure time, and this asserts the detection actually found it: the build
91+
// host is the distribution the package targets, so a regression to a
92+
// hardcoded value shows up here rather than in the field.
93+
EXPECT_TRUE(boost::filesystem::exists(expanded)) << "ca-path does not exist: " << expanded;
8294
#endif
8395
}
8496

0 commit comments

Comments
 (0)