Repository navigation
Match IPv6 addresses when mapping Cacti devices to Nagios hosts - #55
Open
somethingwithproof wants to merge 2 commits into
Open
somethingwithproof wants to merge 2 commits into
somethingwithproof wants to merge 2 commits into
Conversation
…include Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Description
The Nagios host import decides whether a Nagios host already exists in Cacti by comparing addresses. It built its map of Cacti devices with
gethostbyname(), which only returns IPv4, and compared the imported address as plain text. A device that only has an IPv6 address never matched, so the import tried to add it a second time. A device with both kinds was only known by its first IPv4 address, and the same IPv6 address written two ways (2001:DB8::1and2001:db8:0:0:0:0:0:1) did not match itself.This change keeps the same cache file and the same lookup flow and makes the address handling correct for IPv6:
dns_get_record(). If the resolver returns no records, the system lookup that earlier versions used (gethostbyname()) is tried, so names that resolved before still resolve.inet_pton()theninet_ntop()):2001:DB8::1,2001:db8:0:0:0:0:0:1and[2001:db8::1]are the same address, and an IPv4-mapped IPv6 address (::ffff:192.0.2.10) is the IPv4 address.$cacheKeyand$hosts). It gains$cacheVersion = 2. A file written by an earlier version has no version and is rebuilt once, because it only holds the first IPv4 address of each device. An earlier version reading a new file ignores the extra variable.checkHostExists()also calledNpcCactiController::getHostnames()statically, which is an Error on PHP 8 (the plugin's floor is 8.2), so the method could not run at all. It now calls the method on an instance.Related Issue
No open issue.
Motivation and Context
Dual-stack and IPv6-only monitoring is common. With the old map the import duplicated every Cacti device that was not reachable through an IPv4 name, and it could not recognise an IPv6 address that Nagios and Cacti wrote differently.
Other places that handle addresses were checked and need no change:
npc_hosts.addressisvarchar(128)and holds a full IPv6 address (at most 45 characters); the controllers only select and return the column;js/npc.jsshows it as text; there is no IPv4 pattern anywhere in the plugin;cli.phpandperfdata.phpprint it with a fixed column width of 30, which is cosmetic for the longest IPv6 text and was left alone because those files cannot be covered by the unit tests. The import passes the address tocli/add_device.php --ip=, which accepts IPv6 in Cacti.Scope and risk
controllers/sync.php(address handling,checkHostExists()), the unit bootstrap,phpunit.xml(measurecontrollers/sync.php), tests, CHANGELOG.normalizeAddress(),resolveAddresses()) and two overridable lookups (dnsRecords(),legacyLookup()) are added./tmp/npc_address_cache.phpand is still read withinclude. That is a separate problem and is not changed here; the hardening PR (Harden the NPC controllers and fix review findings #54) replaces it. Both PRs changecheckHostExists(), so the second one merged needs a rebase of that method.Rollback
Revert the merge commit. A cache file written by this version has a different set of keys; delete
/tmp/npc_address_cache.phpafter a revert, or let the next import rebuild it.How Has This Been Tested?
tests/Unit/SyncAddressMapTest.php(56 cases). DNS is replaced by closures, so no test sends a query and every result is deterministic.Executed locally (PHP 8.4, Pest through a Docker image with Xdebug, MariaDB 11.8.9 in a throwaway container) in the order of the CI workflow on two Cacti trees, a 1.2.x tree (1.2.32) and a develop tree (1.3.0):
php -lplugin_manage --install --enablecleanThe skipped test is a root-user permission check. All 56 new tests fail against the unchanged
controllers/sync.php. The Pest and PHPUnit versions come from the develop tree's lock file; a freshcomposer installfor 1.2.x and PHP 8.2 and 8.3 were not run locally. The tests use noeval, nohttp://literal, no SQL and no network, and write only to temporary files that they remove.Performance
Building the map now asks for A and AAAA records of each Cacti device with one
dns_get_record()call instead of onegethostbyname()call, which is one extra query per device name when the resolver answers. The map is built once per cache key, not per import request. I did not measure it: the local setup has no resolver whose latency would mean anything. Reading the cache is unchanged apart from normalising the imported address, which is a few string operations.Types of changes
Checklist: