399 Commits

Author SHA1 Message Date
rcourtman 1760419c63 test: add additional tests for internal/agentupdate
Add 6 tests covering:
- Config struct zero value defaults
- NewUpdater with InsecureSkipVerify option
- NewUpdater with Disabled option
- determineArch format validation
- verifyBinaryMagic on directories
- Package constants validation
2025-11-26 14:37:01 +00:00
rcourtman 394ab3ad4d test: add unit tests for internal/models converters
Add 22 tests covering:
- zeroIfNegative helper function
- copyStringFloatMap deep copy helper
- Node.ToFrontend with display name fallback
- VM.ToFrontend including tags, backup time, negative values
- Container.ToFrontend
- DockerContainer.ToFrontend with ports, networks, mounts, block IO
- DockerService.ToFrontend with endpoint ports
- DockerSwarmInfo.ToFrontend
- Storage.ToFrontend
- hostSensorSummaryToFrontend nil handling
- RemovedDockerHost.ToFrontend
- DockerServicePort.ToFrontend
- DockerTask.ToFrontend with timestamps
2025-11-26 14:33:57 +00:00
rcourtman 63043adf3b test: add unit tests for internal/metrics
Add 14 tests covering:
- RecordAlertFired, RecordAlertResolved, RecordAlertAcknowledged
- RecordNotificationSent with success/failure
- RecordNotificationRetry, RecordNotificationDLQ
- RecordGroupedNotification with various counts
- RecordAlertEscalation with various levels
- RecordAlertSuppressed with various reasons
- UpdateQueueDepth, UpdateHistorySize
- RecordHistorySaveError
- Metric vector initialization verification
2025-11-26 14:27:54 +00:00
rcourtman b6f771f43d test: add unit tests for internal/tempproxy
Add 24 tests covering:
- ErrorType enum constants
- ProxyError Error() and Unwrap() methods
- calculateBackoff exponential backoff with jitter
- contains case-insensitive substring matching
- classifyError error classification for node, auth, SSH, sensor, rate limit, timeout, transport
- RPCRequest and RPCResponse struct fields
- Client struct fields
2025-11-26 14:26:59 +00:00
rcourtman c1ae651b0d test: add unit tests for internal/agentbinaries 2025-11-26 14:17:58 +00:00
rcourtman 7a091fd3fd test: add unit tests for system package 2025-11-26 14:11:25 +00:00
rcourtman 6f9eecec65 test: add unit tests for types package 2025-11-26 14:10:21 +00:00
rcourtman e4f4688fe4 test: add unit tests for hostagent package 2025-11-26 14:09:55 +00:00
rcourtman d109b53eb6 test: add unit tests for errors package 2025-11-26 14:09:14 +00:00
rcourtman d046971fdb test: add unit tests for sensors parser 2025-11-26 14:06:56 +00:00
rcourtman 2eb9e61f0e test: add unit tests for utils package
- Test ID generation (uniqueness, format)
- Test JSON response writing (various types, headers)
- Test boolean parsing (truthy/falsy values)
- Test environment variable trimming
- Test data directory resolution
- Test large payload handling
2025-11-26 13:56:30 +00:00
rcourtman ed81143119 test: add unit tests for crypto package
- Test encrypt/decrypt round-trip (various data types)
- Test string encryption (base64 output)
- Test key persistence across manager instances
- Test key file permissions (0600)
- Test decryption of invalid/corrupted data
- Test encryption uniqueness (random nonce)
- Test orphaned data protection
- Test large data encryption (1MB)
2025-11-26 13:52:05 +00:00
rcourtman 3c1cd4ee98 test: add unit tests for auth package
- Test API token generation (uniqueness, format)
- Test API token hashing (SHA3-256, deterministic)
- Test constant-time token comparison
- Test token hash detection
- Test password hashing (bcrypt, salted)
- Test password verification
- Test password complexity validation
- Verify bcrypt cost and minimum password length constants
2025-11-26 13:51:13 +00:00
rcourtman f111c3ff6a test: add unit tests for agentupdate security features
- Test binary magic verification (ELF, PE, Mach-O)
- Test architecture detection
- Test Unraid persistent path generation
- Test updater configuration defaults
- Test edge cases: empty files, too short, non-existent
2025-11-26 13:50:19 +00:00
rcourtman dc4669f9f6 security: harden agent installers and auto-update mechanism
Install script (scripts/install.sh):
- Add multi-platform support: Unraid, OpenRC/Alpine, Synology DSM 6/7
- Add input validation for URL, token format, and interval
- Add binary magic verification (ELF/Mach-O/PE)
- Add cleanup trap for temp files
- Wrap script in main() for partial download protection
- Fix shellcheck compliance issues
- Add curl timeouts

Agent auto-update (agentupdate, dockeragent):
- Enforce TLS 1.2 minimum version
- Make SHA256 checksum verification mandatory
- Add 100MB binary size limit
- Add binary magic verification before replacement
- Add Unraid persistent binary update after self-update
- Add 5-minute download timeout

Frontend:
- Update Linux install description to note auto-detection of init systems
2025-11-26 13:14:58 +00:00
rcourtman 9daf1d5398 fix: cache daemon ID at init to prevent Podman token binding conflicts
Podman can return unstable or empty daemon IDs across API calls. When
the agent fetched info.ID on every report cycle, this could cause the
agent identity to change mid-session, triggering "token already in use"
errors on the server.

Cache the daemon ID at initialization and use it consistently for all
reports.

Related to #740
2025-11-26 10:23:22 +00:00
rcourtman 7d7368f18f fix: use correct script paths in unified agent handlers
The unified agent handlers were using r.config.AppRoot which pointed
to /app, but scripts are in /opt/pulse/scripts. Updated to match the
pattern used by other script handlers - check /opt/pulse/scripts first,
then fall back to project root for dev environment.

Also added no-cache headers to prevent stale scripts being served.
2025-11-26 10:05:43 +00:00
rcourtman f3e85a7455 fix: remove references to deleted install-host-agent.sh script
The unified agent system replaced install-host-agent.sh with install.sh.
This commit updates all references:
- Dockerfile: removed COPY for deleted script
- router.go: serve install.sh at /install-host-agent.sh endpoint (backwards compatible)
- build-release.sh: removed copy of deleted script
- validate-release.sh: removed validation of deleted script
- install.sh: updated script list for bare-metal installs
2025-11-26 09:57:06 +00:00
rcourtman 6853a0ffd1 feat: serve install scripts from GitHub releases instead of main branch
Scripts like install.sh and install-sensor-proxy.sh are now attached
as release assets and downloaded from releases/latest/download/ URLs.
This ensures users always get scripts compatible with their installed
version, even while development continues on main.

Changes:
- build-release.sh: copy install scripts to release directory
- create-release.yml: upload scripts as release assets
- Updated all documentation and code references to use release URLs
- Scripts reference each other via release URLs for consistency
2025-11-26 08:59:59 +00:00
rcourtman ae3b78d661 fix: propagate unified agent version and improve legacy cleanup
Issues found during scenario testing:

1. Version propagation: The hostagent and dockeragent packages were
   reporting their own Version (0.1.0-dev) instead of the unified
   agent's version. Added AgentVersion config field to pass the
   parent's version down.

2. macOS legacy cleanup: The install.sh script was missing cleanup
   for pulse-docker-agent on macOS.

3. Windows legacy cleanup: The install.ps1 script was missing cleanup
   for legacy PulseHostAgent and PulseDockerAgent services.

These fixes ensure:
- Unified agent reports consistent version across host/docker metrics
- Legacy agents are properly removed on all platforms during upgrade
- Users migrating from legacy agents get a clean transition
2025-11-25 23:39:10 +00:00
rcourtman ea335546fc feat: improve legacy agent detection and migration UX
Add seamless migration path from legacy agents to unified agent:

- Add AgentType field to report payloads (unified vs legacy detection)
- Update server to detect legacy agents by type instead of version
- Add UI banner showing upgrade command when legacy agents are detected
- Add deprecation notice to install-host-agent.ps1
- Create install-docker-agent.sh stub that redirects to unified installer

Legacy agents (pulse-host-agent, pulse-docker-agent) now show a "Legacy"
badge in the UI with a one-click copy command to upgrade to the unified
agent.
2025-11-25 23:26:22 +00:00
rcourtman 0436101ee5 feat: add auto-update support for unified agent
Implement self-update capability for the unified pulse-agent binary:

- Add internal/agentupdate package with cross-platform update logic
- Hourly version checks against /api/agent/version endpoint
- SHA256 checksum verification for downloaded binaries
- Atomic binary replacement with backup/rollback on failure
- Support for Linux, macOS, and Windows (10 platform/arch combinations)

Build and release changes:
- Dockerfile builds unified agent for all platforms
- build-release.sh includes unified agent in release artifacts
- validate-release.sh validates unified agent binaries
- Install scripts (install.sh, install.ps1) use correct URL format

Related to #727, #737
2025-11-25 23:15:03 +00:00
courtmanr@gmail.com 1716774e71 feat: adaptive node table layout, guest row fixes, and legacy agent detection
- Implemented adaptive layout for NodeSummaryTable with responsive columns and sticky name column.
- Fixed GuestRow background display issues.
- Added IsLegacy field to Host and DockerHost models to flag legacy agents (version < 1.0.0).
- Updated monitor to populate IsLegacy based on agent version.
2025-11-25 17:19:36 +00:00
courtmanr@gmail.com 930c086556 WIP: Save all pending changes including frontend updates and unified agent scaffolding 2025-11-25 11:27:07 +00:00
courtmanr@gmail.com 9466db4868 Register unified installer routes
Exposes /api/install/install.sh and /api/install/install.ps1 for the unified agent installer.
2025-11-25 11:25:10 +00:00
courtmanr@gmail.com 3ec7b401a3 Improve installer UX with pauses and popups on failure
Fixes #755. Adds interactive pauses and graphical popups (where available) to installer scripts when critical errors occur, ensuring troubleshooting guides are readable. Also clarifies 'build from source' instructions.
2025-11-25 11:17:37 +00:00
courtmanr@gmail.com 71fea10aa5 Further reduce setup script verbosity: silence token checks and consolidate permission logs 2025-11-25 10:20:17 +00:00
courtmanr@gmail.com 32c1c3fac5 Suppress 'User already exists' message in setup script 2025-11-25 10:16:08 +00:00
courtmanr@gmail.com bddb90229b Improve setup script clarity: reduce verbosity and fix confusing messages 2025-11-25 10:13:20 +00:00
courtmanr@gmail.com 0c6fd01ff2 Improve setup script output by hiding irrelevant Docker/proxy info 2025-11-25 10:01:41 +00:00
courtmanr@gmail.com 584ad94ee5 Refactor: Parallelize PVE node polling 2025-11-25 08:38:03 +00:00
courtmanr@gmail.com f4c2bd7c35 Implement UI toggle for Hide Local Login (related to issue #750) 2025-11-25 08:14:19 +00:00
courtmanr@gmail.com a68f2de3e6 Relax container SSH check for temperature monitoring (ref #727) 2025-11-25 08:00:08 +00:00
courtmanr@gmail.com e9665cb1cd Fix: Prevent unnecessary config reloads by checking file content hash 2025-11-24 22:42:24 +00:00
courtmanr@gmail.com cfc4ccf14e Fix: Allow double slashes in install script URLs 2025-11-24 17:58:00 +00:00
courtmanr@gmail.com f347dedcdd Add PULSE_AUTH_HIDE_LOCAL_LOGIN option to hide password form
Implements #750 - allows hiding the username/password login form when
using OIDC SSO to avoid user confusion, while maintaining security.

- Added HideLocalLogin config option (env: PULSE_AUTH_HIDE_LOCAL_LOGIN)
- Exposed hideLocalLogin in /api/security/status endpoint
- Updated Login.tsx to conditionally hide local login form
- Added escape hatch via ?show_local=true URL parameter

This approach avoids the security and upgrade issues that led to
DISABLE_AUTH being removed (see #707, #678), while solving the UX
problem of users being confused by multiple login options.
2025-11-24 17:40:43 +00:00
courtmanr@gmail.com 65852e8b4a Fix #735: Allow HEAD requests for download endpoints and fix routing
- Allow HEAD requests in addition to GET for all download handlers
  (install scripts, binaries, checksums) to prevent 405 errors
- Add /uninstall-host-agent.sh to special routes in ServeHTTP
- Add test coverage for HEAD request handling
- Resolves 'method not allowed' errors during agent installation
2025-11-24 15:16:14 +00:00
courtmanr@gmail.com 4168eb41f8 Fix host agent registration verification issues (#746)
- Change default server listen addresses to empty string (listen on all interfaces including IPv6)
- Add short hostname matching fallback in host lookup API to handle FQDN vs short name mismatches
- Implement retry loop (30s) in both Windows and Linux/macOS installers for registration verification
- Fix lint errors: remove unnecessary fmt.Sprintf and nil checks before len()

This resolves the 'Installer could not yet confirm host registration with Pulse' warning
by addressing timing issues, hostname matching, and network connectivity.
2025-11-24 14:28:09 +00:00
courtmanr@gmail.com a991f7d47d Add host agent checksum route and bump version to 4.32.6
- Add /download/pulse-host-agent.sha256 route to serve checksums
- Fixes 'Checksum not available' warning during host agent installation
- Bump version to 4.32.6

Related to #746
2025-11-24 07:57:17 +00:00
courtmanr@gmail.com 0d4406b91f Add mutex protection for config watcher reloads (re #748)
Introduced sync.RWMutex to protect concurrent access to configuration
fields (AuthUser, AuthPass, APITokens) that are modified by the
ConfigWatcher at runtime.

- Added global config.Mu RWMutex in internal/config/config.go
- Protected config updates in ConfigWatcher.reloadConfig() and reloadAPITokens()
- Protected config reads in CheckAuth and all API token handlers
- Protected Router.SetConfig() during full config reloads

This prevents race conditions when .env file changes trigger config
reloads while authentication handlers are reading the same fields.
2025-11-24 07:45:21 +00:00
courtmanr@gmail.com d23ab9a7f7 Feat: Add support for Raspberry Pi RP1 ADC temperature sensor (Fixes #745)
- Added 'rp1_adc' to the list of recognized CPU temperature chips
2025-11-23 22:33:16 +00:00
courtmanr@gmail.com d6addee8b4 Fix: Correct context cancellation in loop (Fixes #727)
- Replaced defer in loop with explicit cancellation to avoid resource leak
- Properly tagged issue #727
2025-11-23 22:28:28 +00:00
courtmanr@gmail.com 78308cbc10 Fix: Prevent single node auth failure from disabling global SSH temperature collection
- Removed global legacySSHDisabled flag that was triggered by any single node auth failure
- Changed disableLegacySSHOnAuthFailure to only log warnings
- Fixed potential context leak in monitor.go
- Updated tests to reflect removal of global disable logic
2025-11-23 22:24:15 +00:00
courtmanr@gmail.com 4640633430 Improve agent update logging and installer warnings (related to #737) 2025-11-23 22:07:37 +00:00
courtmanr@gmail.com 76b4abd9e5 fix: Add dev environment fallback paths for Docker agent downloads
- Add fallback to project root scripts/ directory for install-docker-agent.sh
- Add fallback to project root bin/ directory for pulse-docker-agent binary
- Fixes 404 errors when downloading agent installer and binary in dev mode
- Production paths remain unchanged (/opt/pulse/...)
2025-11-23 16:01:40 +00:00
courtmanr@gmail.com 64a509e3da Fix install-host-agent.sh function order, remove duplicate, and improve dev serving 2025-11-23 12:27:11 +00:00
courtmanr@gmail.com 5f3fd17025 Fix temperature collection regression for cluster nodes. Related to #727 2025-11-23 12:13:57 +00:00
courtmanr@gmail.com 85461618fd Fix ZFS storage reporting on TrueNAS SCALE (#718)
- Refactor collector to support mocking
- Fix ZFS detection to support 'fuse.zfs' and case-insensitivity
- Add regression tests for ZFS dataset deduplication
2025-11-22 23:53:39 +00:00
courtmanr@gmail.com 83e07969f0 fix: ensure proxmox nodes are displayed even if cluster endpoints are missing
Fixes #727. Previously, if temperature monitoring was enabled and a node wasn't found in ClusterEndpoints, the entire node processing was skipped. This change ensures we only skip temperature collection.
2025-11-22 23:31:30 +00:00
rcourtman a0c27e84ae Persist PVE fallback host after portless retry 2025-11-22 17:06:15 +00:00