Skip to content

feat(inventory): Add ESET Antivirus inventory support across macOS, Linux, and Windows - #1212

Merged
g-bougard merged 29 commits into
glpi-project:developfrom
eduardomozart:feat-antivirus-eset
Jul 31, 2026
Merged

feat(inventory): Add ESET Antivirus inventory support across macOS, Linux, and Windows#1212
g-bougard merged 29 commits into
glpi-project:developfrom
eduardomozart:feat-antivirus-eset

Conversation

@eduardomozart

Copy link
Copy Markdown
Contributor

📋 Overview

This pull request introduces comprehensive inventory and license detection support for ESET Endpoint Security and ESET Endpoint Antivirus across macOS, Linux, and Windows. It also harmonizes product naming across all three operating systems to ensure consistent inventory reporting entries on GLPI Server.


🚀 Key Changes

🍎 macOS Support (New & Enhanced)

  • AntiVirus Module (MacOS::AntiVirus::ESET):
    • Added detection for ESET Endpoint Security and ESET Endpoint Antivirus application bundles in /Applications/.
    • Status Verification (ENABLED): Verifies active protection by combining two reliable checks:
      1. Daemon Verification: Uses built-in GLPI::Agent::XML to read /Library/LaunchDaemons/com.eset.protection.plist, extract the daemon execution binary (startd), and verify it is running in process lists via getProcesses. If the plist cannot be read, it safely falls back to checking $basepath/startd.
      2. Real-time Protection Status: Parses /Library/Application Support/ESET/Security/var/confd/settings.json using Cpanel::JSON::XS to verify that real-time file system protection (RTFSEnabled) is active (ce_val == 1).
    • Update Heuristics: Collects license expiration dates from lic --status and calculates an up-to-date heuristic by evaluating detection engine modules from upd --list-modules.
    • Shell-Safe Execution: Uses array reference command invocations (e.g., [ "$basepath/upd", "--list-modules" ]) to prevent shell word splitting on bundle paths containing spaces.
    • Dynamic Fallback Resolution: Automatically resolves product names from the application bundle directory path if Product name: is omitted from command outputs.
  • License Inventory (MacOS::License):
    • Extracts ESET Public ID from lic --status and populates the LICENSEINFOS inventory section.

🐧 Linux & 🪟 Windows Support

  • Product Name Harmonization (MacOS::License, Linux::AntiVirus::EEA): Automatically strips OS-specific product suffixes (e.g., " for macOS", " for Linux", " for Windows") when creating LICENSEINFOS entries. This ensures the license name exactly matches the SOFTWARES inventory and its Windows counterpart.
  • Windows Registry Enhancements (Win32::License): Updated registry traversal to prioritize native 64-bit registry paths (HKLM\SOFTWARE\...) before falling back to Wow6432Node when querying ESET license GUIDs and Publisher data.

🧪 Testing & Verification

All unit test suites and mock resources have been updated and verified across isolated environments without warnings:

  • t/tasks/inventory/macos/antivirus/eset.t — Verifies ESET macOS inventory parsing, plist XML handling, JSON settings evaluation, and dynamic bundle fallbacks.
  • t/tasks/inventory/macos/license-eset.t — Verifies macOS ESET license extraction and suffix stripping.
  • t/tasks/inventory/linux/antivirus/eea.t — Verifies Linux EEA inventory and license suffix stripping.
  • t/tasks/inventory/windows/license.t — Verifies Windows 64-bit/32-bit registry license lookup.

- Implement MacOS::AntiVirus::ESET submodule to detect ESET Endpoint Security and ESET Endpoint Antivirus bundles in /Applications
- Add launchctl (com.eset.protection), daemon binary (startd), and settings.json (RTFSEnabled) validation for accurate ENABLED status reporting on macOS
- Update MacOS::License and Linux::AntiVirus::EEA to extract ESET Public ID into LICENSEINFOS and harmonize product names by removing OS suffixes ('for macOS/Linux/Windows') to match SOFTWARES inventory
- Add dynamic product name fallback resolution from bundle path when Product name is omitted from lic status output
- Enhance Win32::License to query 64-bit registry hive first before falling back to Wow6432Node
- Add comprehensive unit tests and mock resources for ESET inventory across all supported platforms
- Implement MacOS::AntiVirus::ESET submodule to detect ESET Endpoint Security and ESET Endpoint Antivirus bundles in /Applications
- Add launchctl (com.eset.protection), daemon binary (startd), and settings.json (RTFSEnabled) validation for accurate ENABLED status reporting on macOS
- Update MacOS::License and Linux::AntiVirus::EEA to extract ESET Public ID into LICENSEINFOS and harmonize product names by removing OS suffixes ('for macOS/Linux/Windows') to match SOFTWARES inventory
- Add dynamic product name fallback resolution from bundle path when Product name is omitted from lic status output
- Enhance Win32::License to query 64-bit registry hive first before falling back to Wow6432Node
- Add comprehensive unit tests and mock resources for ESET inventory across all supported platforms

@g-bougard g-bougard left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @eduardomozart

thank you for your PR.

Anyway, I saw a lot of problems.

Comment thread lib/GLPI/Agent/Task/Inventory/Linux/AntiVirus/EEA.pm Outdated
Comment thread lib/GLPI/Agent/Task/Inventory/Linux/AntiVirus/EEA.pm Outdated
Comment thread lib/GLPI/Agent/Task/Inventory/Win32/License.pm Outdated
Comment thread lib/GLPI/Agent/Task/Inventory/Win32/License.pm Outdated
Comment thread lib/GLPI/Agent/Task/Inventory/Win32/License.pm Outdated
Comment thread lib/GLPI/Agent/Task/Inventory/MacOS/AntiVirus/ESET.pm Outdated
Comment thread lib/GLPI/Agent/Task/Inventory/MacOS/AntiVirus/ESET.pm
Comment thread lib/GLPI/Agent/Task/Inventory/MacOS/AntiVirus/ESET.pm Outdated
Comment thread lib/GLPI/Agent/Task/Inventory/MacOS/AntiVirus/ESET.pm
Comment thread lib/GLPI/Agent/Task/Inventory/MacOS/AntiVirus/ESET.pm Outdated
eduardomozart and others added 14 commits July 30, 2026 11:40
Co-authored-by: Guillaume Bougard <gbougard@teclib.com>
Co-authored-by: Guillaume Bougard <gbougard@teclib.com>
Co-authored-by: Guillaume Bougard <gbougard@teclib.com>
Co-authored-by: Guillaume Bougard <gbougard@teclib.com>
Co-authored-by: Guillaume Bougard <gbougard@teclib.com>
Co-authored-by: Guillaume Bougard <gbougard@teclib.com>
Co-authored-by: Guillaume Bougard <gbougard@teclib.com>
Co-authored-by: Guillaume Bougard <gbougard@teclib.com>
Co-authored-by: Guillaume Bougard <gbougard@teclib.com>
Co-authored-by: Guillaume Bougard <gbougard@teclib.com>
Co-authored-by: Guillaume Bougard <gbougard@teclib.com>
Co-authored-by: Guillaume Bougard <gbougard@teclib.com>
Co-authored-by: Guillaume Bougard <gbougard@teclib.com>

@eduardomozart eduardomozart left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've just pushed a new commit to address your points:

Linux License Segregation & %params

  • Reverted the %params injection in Linux::AntiVirus::EEA::_getEEAInfo to keep it clean, relying just on logger.
  • Completely separated the ESET License logic from the AntiVirus inventory. I've created a dedicated Linux::License module and a Linux::License::EEA submodule, mirroring the architecture you suggested.

Windows Refactoring

  • Added InstallDir to the mocked registry .reg file (with proper UTF-16LE encoding) so ermm.exe correctly dynamically resolves its install path during the inventory sweep.
  • Removed the manual SOFTWARE/ESET/... nested hash traversal in Win32::License that was polluting the core code. It now relies cleanly on the leaf node passed directly from loadRegistryDump during test mocks.

macOS Polish & Fixes

  • Implemented your suggested parsing loop using empty($line) from GLPI::Agent::Tools across both the Linux and macOS license parser loops.
  • Fixed a bug where lic -status was accidentally passed instead of lic --status, restoring the proper extraction of the "Expiration Date".
  • Fixed a bug where getAllLines was mutating the %params arguments incorrectly, ensuring ENABLED parses active protection properly again.

General Cleanup

  • Addressed all trailing whitespaces, duplicate variable declarations, and syntax issues. The full test suite (t/03var.t, t/07whitespaces.t, and all unit tests) is passing completely green locally.

Comment thread lib/GLPI/Agent/Task/Inventory/MacOS/License.pm
@eduardomozart
eduardomozart requested a review from g-bougard July 30, 2026 15:35

@g-bougard g-bougard left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @eduardomozart

here we are also next to a merge.

I still see few required optimization and syntax quirks to fix.

Can check my comments ?

Thank you

Comment thread lib/GLPI/Agent/Task/Inventory/MacOS/AntiVirus/ESET.pm Outdated
Comment thread lib/GLPI/Agent/Task/Inventory/MacOS/AntiVirus/ESET.pm Outdated
Comment thread lib/GLPI/Agent/Task/Inventory/MacOS/AntiVirus/ESET.pm Outdated
Comment thread lib/GLPI/Agent/Task/Inventory/MacOS/AntiVirus/ESET.pm Outdated
Comment thread lib/GLPI/Agent/Task/Inventory/MacOS/AntiVirus/ESET.pm Outdated
Comment thread lib/GLPI/Agent/Task/Inventory/MacOS/AntiVirus/ESET.pm Outdated
Comment thread lib/GLPI/Agent/Task/Inventory/MacOS/License.pm Outdated
Comment thread lib/GLPI/Agent/Task/Inventory/Win32/License.pm Outdated
Comment thread lib/GLPI/Agent/Task/Inventory/Win32/License.pm Outdated
eduardomozart and others added 9 commits July 31, 2026 11:52
Co-authored-by: Guillaume Bougard <gbougard@teclib.com>
Co-authored-by: Guillaume Bougard <gbougard@teclib.com>
Co-authored-by: Guillaume Bougard <gbougard@teclib.com>
Co-authored-by: Guillaume Bougard <gbougard@teclib.com>
Co-authored-by: Guillaume Bougard <gbougard@teclib.com>
Co-authored-by: Guillaume Bougard <gbougard@teclib.com>
Co-authored-by: Guillaume Bougard <gbougard@teclib.com>
Co-authored-by: Guillaume Bougard <gbougard@teclib.com>
Co-authored-by: Guillaume Bougard <gbougard@teclib.com>
@eduardomozart
eduardomozart requested a review from g-bougard July 31, 2026 14:57

@eduardomozart eduardomozart left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

@g-bougard g-bougard left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test is failing on windows. It seems you made a mistake on _test_date in macos eset av test.

Check my comments below.

Comment thread t/tasks/inventory/macos/antivirus/eset.t Outdated
Comment thread lib/GLPI/Agent/Task/Inventory/MacOS/AntiVirus/ESET.pm Outdated
eduardomozart and others added 3 commits July 31, 2026 13:16
Co-authored-by: Guillaume Bougard <gbougard@teclib.com>
Co-authored-by: Guillaume Bougard <gbougard@teclib.com>
… InstallDir

When the ESET InstallDir registry key is not available, the code now
falls back to %ProgramFiles% and %ProgramFiles(x86)% environment
variables before using the hardcoded C:\Program Files path. This
handles cases where ESET is installed on a non-default drive.
@g-bougard
g-bougard merged commit d5d166e into glpi-project:develop Jul 31, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants