mirror of
https://github.com/Cacti/cacti.git
synced 2026-10-28 23:57:30 +09:00
fix/graph-wrapper-date-range-develop
15
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
7b551eea72 |
chore: normalize CRLF line endings to LF across Cacti-owned files (#8156)
Excludes vendored packages, third-party JS, patches, and the Win32 probe fixture. Pure EOL change; guards pass and php -l is clean. |
||
|
|
0415606710 |
fix: skip replication-ignored files in cache_in_path() to stop poll-cycle log spam (#8127)
* fix: skip replication-ignored files in cache_in_path() to stop poll-cycle log spam cache_in_path() emitted a 'Detecting Resource Change' log and called update_db_from_path() for tooling artifacts (.gitignore, .mdlrc, tests/, ...) that update_db_from_path() then declines to cache. Because their md5 is never stored, every poll cycle re-detected them as changed, spamming the Cacti log once per minute. Guard cache_in_path() with should_ignore_from_replication() up front so these paths are skipped entirely. * test: assert cache_in_path() consults the ignore predicate before logging/updating Regression guard for the per-poll-cycle log spam fix. cache_in_path() runs change detection before update_db_from_path(), so it must short-circuit on should_ignore_from_replication() up front. Without that early return an ignored dotfile (.gitignore, .mdlrc, ...) is logged and re-processed every cycle because its md5 is never stored and it is forever re-detected as "changed". The new test pins the guard ahead of the first change-detection log line in cache_in_path(). * fix: restore literal <?php opening tag in replication exclusion test The previous commit stored the opening tag as an HTML entity, which would make the test file fail to parse. |
||
|
|
ac2445fab5 |
Exclude 'tests' directories from resource replication (#8118)
* poller: exclude 'tests' directories from resource replication should_ignore_from_replication() now skips any path with a 'tests' segment, covering Cacti's own tests/ and every plugin's tests/ for both the cache-in (md5sum_path/update_db_from_path) and cache-out (resource_cache_out) directions. update_resource_cache()'s plugin scan also adds 'tests' to its directory exclusions so a plugin's tests/ tree is never cached in the first place. Adds a Pest unit test covering both directions and the plugin-scan exclusion. * poller: purge stale excluded rows, guard collector dirs, strip install root Address review feedback on #8118: - should_ignore_from_replication() now strips CACTI_PATH_BASE from absolute file paths before segment matching, so an installation living under a 'tests' ancestor (e.g. /srv/tests/cacti) no longer rejects ordinary files. - update_resource_cache() purges rows that are now excluded even when their source file still exists, dropping tests/* rows cached before the exclusion. - The remote collector skips excluded plugin rows before building directories, so it no longer recreates plugins/foo/tests/ from stale cache rows. Adds regression tests for the absolute-path handling and both source-level guards. |
||
|
|
af8449e487 |
Fix RECACHE ASSERT loop caused by SNMP uptime selection diverging from spine (develop) (#8058)
* fix: match spine's unconditional engine-time preference for SNMP uptime recache (develop) PR #7982 changed cacti_snmp_select_uptime() to prefer whichever of sysUpTime and snmpEngineTime is numerically larger. Spine's own reindex-assert re-check (poller.c) has no such magnitude comparison - it always prefers a numeric engine time, only falling back to sysUpTime when the engine OID isn't present. For any device where snmpEngineTime is legitimately smaller than sysUpTime (e.g. the SNMP agent/engine restarted more recently than the OS, a common, unremarkable scenario), lib/poller.php's update_reindex_cache() now picks sysUpTime as the recache baseline while spine always re-derives its live comparison value from the smaller engine time. Every poll then reports "RECACHE ASSERT FAILED" and queues a reindex; Cacti recomputes the baseline the same way, so it never converges - an infinite RECACHE ASSERT loop that looks like a spine bug even though spine is unchanged. Fix: add an opt-in $prefer_engine_time parameter to cacti_snmp_select_uptime() that keeps the existing wall-clock rejection (issue#7342) but skips the "prefer whichever is larger" comparison, matching spine's rule exactly. Use it for the two call sites that must stay consistent with spine's own live re-check: lib/poller.php's recache baseline, and both uptime reads in cmd.php (update_system_mibs()'s host.snmp_sysUpTimeInstance update, and ping_and_reindex_check()'s own PHP-poller equivalent of spine's reindex re-check). The display-only call sites (lib/api_device.php, lib/api_automation.php) keep the existing wrap-aware "prefer larger" logic, since they aren't compared against a persisted, spine-shared baseline. Ported from the 1.2.x fix (#8057). Added tests covering the new parameter and asserting both call sites opt into it. * test(snmp): cover prefer_engine_time in the coverage-gated suite phpunit-snmp.xml's "SNMP coverage" testsuite only runs SnmpCoverageTest.php, not SnmpUptimeSelectionTest.php where the new $prefer_engine_time assertions were added. The engine-time-preference branch in cacti_snmp_select_uptime() was never executed under the 100% line coverage gate, so the "lib/snmp.php 100% coverage" check failed at 99.8%. Mirror the same prefer_engine_time assertions into SnmpCoverageTest.php so the coverage-gated suite exercises the new branch. * fix: match spine's lack of wall-clock awareness for prefer_engine_time paths The wall-clock rejection guard ran before the prefer_engine_time branch, so an OpenBSD-style agent (engine time == Unix clock) still fell back to sysUpTime on the spine-facing paths even with prefer_engine_time=true. Spine's own re-check has no wall-clock awareness at all - it unconditionally prefers any numeric engine time - so that class of device kept the RECACHE ASSERT loop. Move the prefer_engine_time short-circuit before the wall-clock check so those paths replicate spine exactly; the wall-clock rejection still protects the display-only call sites. * test(snmp): fix stale wall-clock assumption in prefer_engine_time coverage test |
||
|
|
1e5329dd89 |
security: consolidate verified GHSA-rjvj win32 cmd.exe hardening for develop (#8056)
* fix(win32): harden the cmd.exe shell sinks on develop (GHSA-rjvj-r52f-8v5q) Forward-port of the 1.2.x win32 command-injection remediation. On Windows the SNMP/ping/data-query/trap commands run through cmd.exe, which ignores the \" escape and toggles quoting on every ", so cacti_escapeshellarg cannot stop & | ^ < > ( ). - add cacti_escapeshellarg_cmd(), stripping those operators on win32 before quoting (a Unix pass-through) - snmp_escape_string(): strip the operators in the win32 branch - route the SNMP binary hostname, the data-query device values (get_script_query_path), the data-input arg builders, the Windows ping hostname, and the SNMP trap notification arguments through the strip get_script_query_path is device-reachable (a rogue monitored device supplies an SNMP index/system field that executes on the Windows poller); the rest are post-auth. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * fix(win32): strip %VAR% from the hostname on Windows (GHSA-rjvj-r52f-8v5q) cmd.exe expands %VAR% even inside quotes, so a device hostname of %USERNAME% would expand into the SNMP/ping command line. Add an opt-in $strip_env flag to cacti_escapeshellarg_cmd() and set it for the SNMP binary and ping hostnames, which never legitimately contain a percent. Community and credential values are left untouched because they can legitimately contain %. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * docs(changelog): note win32 cmd.exe hardening for develop * security: require Package Management permission to trust new package signers package_accept_key() (reachable via the repository-based package import flow) inserted new keys into package_public_keys, the global trust store consulted by import_validate_signature() for every future import by every user, without checking for the Package Management (realm 29) permission that gates package_keys.php/package.php/package_repos.php for the same table. An Import Templates (realm 17) user could therefore add themselves as a trusted signer for the whole install. Also add the 'accept' action to the CSRF-protected bad_actions list so the acceptance step requires POST plus a valid token like every other state-changing action. GHSA-gxgm-8rhv-r7jv * docs(changelog): note package-signer trust authorization fix * security: close tab-based open redirect bypass in CSRF timeout handler sanitize_uri()'s guard ( |
||
|
|
344ed3dcef |
fix(snmpagent): clarify missing SNMP notification receiver message on develop (#8040)
* fix(snmpagent): clarify missing SNMP notification receiver message * fix(snmpagent): point notice at the real SNMP Managers menu and isolate test config * fix(js): regenerate DOMPurify 3.4.15 asset and skip node_modules cleanup in CI * chore: add PR number to CHANGELOG entry |
||
|
|
3f377531b7 |
fix(poller): stop the registry pid probe narrowing a wide pid to -1 (#7956)
* fix(poller): stop the registry pid probe narrowing a wide pid to -1 processes.pid is int(10) unsigned, so a corrupted row can hold 4294967295. Through PHP 8.4 posix_kill() narrows that to a 32 bit pid_t of -1 and kill(2) reads it as every process the caller may signal, so cacti_process_pid_exists() calls a dead registry row live and the two kill sites that ask it first SIGTERM the caller's whole session. From PHP 8.5 the same value raises a ValueError and ends the poller instead. Refusing it ahead of the call covers both. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * hardening: bound every process table PID before signalling it Twelve call sites read a pid out of a process table and handed it straight to posix_kill(). processes.pid is int(10) unsigned, so a corrupted row can carry 4294967295, which narrows to a 32 bit pid_t of -1 and signals every process the caller owns, or from PHP 8.5 raises a ValueError that ends the collector. They now go through cacti_process_kill(), which refuses init, anything that cannot name a process, and anything wider than pid_t. poller_recovery read its pid with a bare posix_kill($pid, 0) and treats false as "stale, clear the row and run". cacti_process_signalable() keeps exactly that meaning, including EPERM as stale, and adds the bound. Neither cacti_process_pid_exists() nor cacti_process_still_running() fits there: both report a pid live when signalling it is merely forbidden, so a recycled recovery_pid would have wedged recovery until an operator cleared the row. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * test: place process guards in poller domain Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * fix(poller): honor platform PID ranges Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * test(poller): cover platform signal semantics Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> --------- Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> |
||
|
|
4744d0d9db |
Forward-port data query source guard (#7985)
* issue#7809: stop reading a missing source key on output-only data query fields
query_snmp_host() tested $field_array['source'] as the left-most term of the
method-fix guard, so PHP raised "Undefined array key source" for every
output-only field before the direction test could short-circuit. Testing
direction first reads source only for input fields, which always define it.
The boolean result is unchanged.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
(cherry picked from commit
|
||
|
|
95060c49ba | Close test-suite discovery and coverage gaps (#7970) | ||
|
|
130f58243b | Fix SNMP uptime selection across polling paths (#7984) | ||
|
|
ed5ab24474 |
fix: detect a failed SNMP walk by exit code, not by device data (#7929)
* fix: detect a failed SNMP walk by exit code, not by device data cacti_snmp_walk() discarded the entire walk when its output contained the word Timeout. That output is the walk itself, one line per OID, so a device with an ifAlias of 'Timeout Monitor' or a matching sysDescr emptied the result and data_query.php then dropped every index for the device. The check could not detect a real timeout either. net-snmp writes that to stderr and neither walk command redirects it, so the matched string was always device data. cacti_snmp_get() already reads the exit code for exactly this reason; exec_into_array() exposes it by reference. Also refuse a walk with empty credentials, matching cacti_snmp_get, get_raw and getnext. An unknown v3 protocol previously built a credential-less snmpwalk and failed with no log line. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * test: cover the credential guard and refresh the security baselines Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * test: give the exec_into_array stub the real signature The stub dropped the by-reference exit code that lib/functions.php exposes, so any code reading it saw 0 regardless of what the command returned. That is why the walk's failure detection could regress to matching stdout without a test noticing. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * test: expect the exit-code wording for a failed walk Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> --------- Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> |
||
|
|
22d19cfcc6 |
issue#7355: add ENTITY-SENSOR, JUNIPER and F5-BIGIP script data queries (#7839)
* issue#7355: add a vendor-neutral ENTITY-SENSOR-MIB script data query ENTITY-SENSOR-MIB (RFC 3433) exposes physical sensors (temperature, fan, PSU, voltage, current) on most modern gear, so one data query covers F5, Juniper, Arista, Cisco NX-OS and others. ss_entity_sensor collects the sensor table and scales each reading through entPhySensorScale and entPhySensorPrecision; the SNMP I/O sits behind an injectable walker so every logic branch is unit tested. A dedicated coverage job enforces 100% line coverage on the collector. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * issue#7355: add a JUNIPER-MIB jnxOperatingTable script data query Junos routers and switches expose per-subject health (Routing Engine, FPC, PSU, fan) through JUNIPER-MIB jnxOperatingTable, which is the signature Juniper data beyond the IF-MIB and HOST-RESOURCES standards. ss_juniper_operating collects CPU, temperature, buffer and state; the multi-index table is keyed on the full OID suffix. SNMP I/O sits behind an injectable walker so every branch is unit tested, and a dedicated job enforces 100% line coverage. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * issue#7355: add an F5-BIGIP-SYSTEM-MIB per-CPU utilization script data query BIG-IP reports per-CPU utilization as sliding 5s/1m/5m averages in sysMultiHostCpuTable, the signature F5 metric beyond the IF-MIB and HOST-RESOURCES standards. ss_f5_cpu collects that multi-indexed table, keyed on the full OID suffix. Every OID was resolved from the published F5-BIGIP-SYSTEM-MIB with snmptranslate. SNMP I/O sits behind an injectable walker so every branch is unit tested, and a dedicated job enforces 100% line coverage. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * style: apply php-cs-fixer to ss_entity_sensor.php Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> --------- Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> |
||
|
|
abb50e636a |
feat: build SNMP sessions from a device row with cacti_snmp_session_from_host() (#7835)
cacti_snmp_session() takes fifteen positional arguments. The poller, data queries, and automation each spelled out the same $host-row mapping, which is where SNMPv3 credential handling drifted between callers. This adds one wrapper that assembles the arguments, and converts the two data_query.php call sites as the first adopters. Missing keys fall back to cacti_snmp_session()'s own defaults, so behavior is unchanged. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> |
||
|
|
49f5212181 |
fix(tests): restore paths and isolate test doubles (#7764)
* fix(tests): correct path depths after the domain reorganisation The category move left nine files resolving paths relative to their old depth, so the bootstrap could not read tests/Helpers/UnitStubs.php and no test ran at all. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * fix tests without replacing production functions * remove unrelated failing integration tests * remove unrelated broken test workflows --------- Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> |
||
|
|
96033267cb |
refactor(tests): reorganize unit tests into domain category folders (#7733)
* refactor(tests): reorganize unit tests into domain category folders - Consolidate per-advisory GHSA regression tests into Security/ subfolders by vuln class - Group all 186 test files into domain folders: DataCollection/, Ui/, Core/, Database/, Installer/, Scripts/, Security/, Plugin/ - Strip GitHub issue/GHSA numbers from filenames; keep IDs in test descriptions - Fix all __DIR__ relative paths to match new folder nesting depth - Update CI workflow path triggers and phpunit XML configs for new file locations - Update .github/copilot-instructions.md with unit test organization guidelines - Add tests/vendor/ to .gitignore * add gaurds * fix up guard for unit tests * fix redeclaration of cacti_log in tests * fix updates to unit tests * fix test patjhs * fix: update test __DIR__ paths for reorganized test structure * fix: conditionally define read_user_setting to prevent redeclaration in tests * fix: conditionally define functions to prevent redeclaration in tests - Wrap clean_up_lines, raise_message, cacti_debug_backtrace, and get_debug_prefix with function_exists() checks to prevent conflicts when test stubs are loaded before lib/functions.php in the same PHP process * fix: add unit test bootstrap to prevent function redeclaration errors - Create tests/bootstrap-unit.php to load core libraries before tests - Ensures lib/functions.php loads before test stubs define stub functions - Test stubs use function_exists() checks, so they detect pre-loaded functions - Update phpunit.xml to use bootstrap-unit.php for Unit testsuite - Fixes 'Cannot redeclare read_user_setting()' errors when tests run in same process * fix: load test stubs before global.php in unit test bootstrap - Reorder bootstrap to load CactiStubs.php and UnitStubs.php first - Ensures stub functions like __() are available when global.php loads - global.php calls get_cacti_version_text() which needs __() for translations - Fixes 'Call to undefined function __()' error during bootstrap * fix: remove function conflicts from test stubs - Remove stub definitions for functions already in lib/functions.php: cacti_sizeof, cacti_log, cacti_strtolower, read_config_option, read_user_setting, cacti_count - Keep translation function stubs (__(), __esc()) needed by global.php - Update bootstrap to load lib/functions.php after stubs - This prevents function redeclaration errors while maintaining test isolation * fix: prevent constant and variable redeclaration in bootstrap - Remove explicit PHP_TESTING and CACTI_TEST_BOOTSTRAP defines from bootstrap (CactiStubs.php now handles this with guards) - Add guards to CactiStubs.php to prevent redefinition of PHP_TESTING - Only set CACTI_TEST_BOOTSTRAP env vars if not already set - Fixes PHP warnings about 'Constant X already defined' * fix: remove redundant lib/functions.php load from bootstrap include/global.php already loads lib/functions.php at lines 287-288. The bootstrap was trying to load it again after global.php, but global.php needs format_cacti_version() to be available on lines 293-294 to define CACTI_VERSION and CACTI_VERSION_FULL constants. Solution: Let global.php handle loading lib/functions.php itself, and don't load it separately in the bootstrap. * fix: remove more conflicting function stubs from test helpers - Remove stubs for functions also defined in lib/functions.php: raise_message, clean_up_lines, cacti_debug_backtrace, get_debug_prefix - Remove POLLER_ID constant stub (defined unconditionally by global.php) - Keep only translation functions and test-specific helpers - This prevents function/constant redeclaration errors * fix: minimize test stubs to only translation functions Remove ALL helper functions and constants from UnitStubs.php that are: - Defined in lib/functions.php (raise_message, clean_up_lines, etc.) - Defined in lib/html_utility.php (srv, set_request_var) - Defined in global_constants.php (POLLER_VERBOSITY_*, MESSAGE_LEVEL_*) - Defined in global.php (POLLER_ID) Keep ONLY translation functions (__(), __esc()) that are: - Called by global.php during initialization - Not defined elsewhere - Required for proper bootstrap sequence This eliminates all constant and function redeclaration errors. * fix: remove __esc stub - already defined in global_languages.php Keep only __() translation function stub, which is needed by global.php and not defined elsewhere in Cacti core. * fix: handle no-arg case in __() translation stub The __() function may be called with just a string and no format arguments. Previously, vsprintf() would fail with 'arguments array must contain 2 items'. Now, if no args are provided, return the text as-is. |