Commit graph

47 commits

Author SHA1 Message Date
rcourtman
1b221cca71 feat: Add configurable allowlist for webhook private IP targets (addresses #673)
Allow homelab users to send webhooks to internal services while maintaining security defaults.

Changes:
- Add webhookAllowedPrivateCIDRs field to SystemSettings (persistent config)
- Implement CIDR parsing and validation in NotificationManager
- Convert ValidateWebhookURL to instance method to access allowlist
- Add UI controls in System Settings for configuring trusted CIDR ranges
- Maintain strict security by default (block all private IPs)
- Keep localhost, link-local, and cloud metadata services blocked regardless of allowlist
- Re-validate on both config save and webhook delivery (DNS rebinding protection)
- Add comprehensive tests for CIDR parsing and IP matching

Backend:
- UpdateAllowedPrivateCIDRs() parses comma-separated CIDRs with validation
- Support for bare IPs (auto-converts to /32 or /128)
- Thread-safe allowlist updates with RWMutex
- Logging when allowlist is updated or used
- Validation errors prevent invalid CIDRs from being saved

Frontend:
- New "Webhook Security" section in System Settings
- Input field with examples and helpful placeholder text
- Real-time unsaved changes tracking
- Loads and saves allowlist via system settings API

Security:
- Default behavior unchanged (all private IPs blocked)
- Explicit opt-in required via configuration
- Localhost (127/8) always blocked
- Link-local (169.254/16) always blocked
- Cloud metadata services always blocked
- DNS resolution checked at both save and send time

Testing:
- Tests for CIDR parsing (valid/invalid inputs)
- Tests for IP allowlist matching
- Tests for bare IP address handling
- Tests for security boundaries (localhost, link-local remain blocked)

Related to #673

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-09 08:31:12 +00:00
rcourtman
8dad0872ae Fix CSRF token parsing in config export/import (related to #646)
The config backup export and import functions were incorrectly parsing
the CSRF token from cookies, causing "Export requires authentication"
errors even when users were properly logged in.

Two issues were fixed:

1. Cookie parsing used `.split('=')[1]` which truncated tokens containing
   `=` padding characters (common in base64 tokens). Fixed by using
   `.split('=').slice(1).join('=')` to preserve the full value.

2. Missing URL decoding of the cookie value. Browsers percent-encode
   cookie values, so `=` becomes `%3D`. The backend then failed to match
   the encoded token hash. Fixed by adding `decodeURIComponent()`.

Both fixes mirror the pattern already used in apiClient.ts.
2025-11-08 11:17:18 +00:00
rcourtman
d70fa88d26 Fix config restore for CLI exports (related to #646)
The v4.26.4 fix inadvertently broke CLI export compatibility. The frontend
attempted JSON.parse on all backup files and returned early with "Invalid
JSON file format" when parsing failed. This prevented the format detection
code from ever executing, breaking CLI-generated exports which are raw
base64 strings without a JSON wrapper.

Root cause:
- CLI exports (`pulse config export`) output raw base64 via
  internal/config/export.go:128
- The fix at Settings.tsx:2030-2034 called showError() and returned
  immediately on parse failure
- Format detection logic at lines 2040-2049 never executed for CLI exports

This changes the parsing flow to:
1. Try JSON.parse first (handles UI exports with {status, data} format)
2. On parse success, extract data field as before
3. On parse failure, treat entire file contents as raw base64 (CLI format)

This preserves the v4.26.4 improvements (12-char validation, better error
messages) while restoring CLI export compatibility.

Related to #646 where user confirmed v4.26.4 still failed to restore backups.
2025-11-07 17:57:22 +00:00
rcourtman
7ed9203e4b Fix config backup/restore failures (related to #646)
Addresses two issues preventing configuration backup/restore:

1. Export passphrase validation mismatch: UI only validated 12+ char
   requirement when using custom passphrase, but backend always enforced
   it. Users with shorter login passwords saw unexplained failures.
   - Frontend now validates all passphrases meet 12-char minimum
   - Clear error message suggests custom passphrase if login password too short

2. Import data parsing failed silently: Frontend sent `exportData.data`
   which was undefined for legacy/CLI backups (raw base64 strings).
   Backend rejected these with no logs.
   - Frontend now handles both formats: {status, data} and raw strings
   - Backend logs validation failures for easier troubleshooting

Related to #646 where user reported "error after entering password" with
no container logs. These changes ensure proper validation feedback and
make the backup system resilient to different export formats.
2025-11-06 17:53:54 +00:00
rcourtman
fd4182563e Fix custom backup polling interval selection not persisting
Addresses issue #567 where selecting "Custom interval..." from the
backup polling dropdown would revert to a preset option if the current
custom minutes value happened to match a predefined interval.

The bug occurred because:
1. User selects "Custom interval..." from dropdown
2. Code sets interval based on current customMinutes value
3. If that value matches a preset (e.g., 60 min = 1 hour), the
   computed select value returns the preset instead of 'custom'
4. Dropdown reverts, hiding the custom input field

Fix introduces a dedicated state variable (backupPollingUseCustom)
to explicitly track whether custom mode is active, independent of
whether the current interval value matches a preset option.

Changes:
- Add backupPollingUseCustom signal to track custom mode state
- Update backupIntervalSelectValue() to check custom flag first
- Set/clear custom flag in dropdown onChange handler
- Initialize custom flag when loading settings from API

Related to #567
2025-11-05 20:15:48 +00:00
rcourtman
449d77504f Improve PMG connection testing to validate metrics endpoints
Related to #551

Enhanced the PMG connection test to actually validate the metrics
endpoints that Pulse uses for monitoring, rather than only checking
the version endpoint. This provides users with immediate feedback if
their PMG credentials lack the necessary permissions to collect metrics.

Backend changes:
- Test mail statistics, cluster status, and quarantine endpoints during
  connection test (internal/api/config_handlers.go:1695-1714)
- Return warnings array in test response when endpoints are unavailable
- Increased timeout from 10s to 15s to accommodate multiple endpoint checks
- Added warning logs for failed endpoint checks

Frontend changes:
- Added showWarning() toast function for warning messages
- Enhanced NodeModal to display warning status with amber styling
- Added warnings list display in test results UI
- Updated Settings.tsx to show warnings from connection tests

This change helps users identify permission issues immediately rather
than discovering later that metrics aren't being collected despite a
"successful" connection.
2025-11-05 18:40:39 +00:00
rcourtman
27f2038dab Add per-node temperature monitoring and fix critical config update bug
This commit implements per-node temperature monitoring control and fixes a critical
bug where partial node updates were destroying existing configuration.

Backend changes:
- Add TemperatureMonitoringEnabled field (*bool) to PVEInstance, PBSInstance, and PMGInstance
- Update monitor.go to check per-node temperature setting with global fallback
- Convert all NodeConfigRequest boolean fields to *bool pointers
- Add nil checks in HandleUpdateNode to prevent overwriting unmodified fields
- Fix critical bug where partial updates zeroed out MonitorVMs, MonitorContainers, etc.
- Update NodeResponse, NodeFrontend, and StateSnapshot to include temperature setting
- Fix HandleAddNode and test connection handlers to use pointer-based boolean fields

Frontend changes:
- Add temperatureMonitoringEnabled to Node interface and config types
- Create per-node temperature monitoring toggle handler with optimistic updates
- Update NodeModal to wire up per-node temperature toggle
- Add isTemperatureMonitoringEnabled helper to check effective monitoring state
- Update ConfiguredNodeTables to show/hide temperature badge based on monitoring state
- Update NodeSummaryTable to conditionally show temperature column
- Pass globalTemperatureMonitoringEnabled prop through component tree

The critical bug fix ensures that when updating a single field (like temperature
monitoring), the backend only modifies that specific field instead of zeroing out
all other boolean configuration fields.
2025-11-05 14:11:53 +00:00
rcourtman
d52ac6d8b5 Fix CSRF token validation and improve token management
- Add Access-Control-Expose-Headers to allow frontend to read X-CSRF-Token response header
- Implement proactive CSRF token issuance on GET requests when session exists but CSRF cookie is missing
- Ensures frontend always has valid CSRF token before making POST requests
- Fixes 403 Forbidden errors when toggling system settings

This resolves CSRF validation failures that occurred when CSRF tokens expired or were missing while valid sessions existed.
2025-11-05 09:23:44 +00:00
rcourtman
6eb1a10d9b Refactor: Code cleanup and localStorage consolidation
This commit includes comprehensive codebase cleanup and refactoring:

## Code Cleanup
- Remove dead TypeScript code (types/monitoring.ts - 194 lines duplicate)
- Remove unused Go functions (GetClusterNodes, MigratePassword, GetClusterHealthInfo)
- Clean up commented-out code blocks across multiple files
- Remove unused TypeScript exports (helpTextClass, private tag color helpers)
- Delete obsolete test files and components

## localStorage Consolidation
- Centralize all storage keys into STORAGE_KEYS constant
- Update 5 files to use centralized keys:
  * utils/apiClient.ts (AUTH, LEGACY_TOKEN)
  * components/Dashboard/Dashboard.tsx (GUEST_METADATA)
  * components/Docker/DockerHosts.tsx (DOCKER_METADATA)
  * App.tsx (PLATFORMS_SEEN)
  * stores/updates.ts (UPDATES)
- Benefits: Single source of truth, prevents typos, better maintainability

## Previous Work Committed
- Docker monitoring improvements and disk metrics
- Security enhancements and setup fixes
- API refactoring and cleanup
- Documentation updates
- Build system improvements

## Testing
- All frontend tests pass (29 tests)
- All Go tests pass (15 packages)
- Production build successful
- Zero breaking changes

Total: 186 files changed, 5825 insertions(+), 11602 deletions(-)
2025-11-04 21:50:46 +00:00
rcourtman
5c4be1921c chore: snapshot current changes 2025-11-02 22:47:55 +00:00
rcourtman
b3285c05c8 Consolidate pending changes
- Add Docker metadata test comment
- Update alerts configuration and thresholds
- Enhance config file watcher
- Update documentation
- Refine settings UI
2025-10-28 23:20:44 +00:00
rcourtman
e07336dd9f refactor: remove legacy DISABLE_AUTH flag and enhance authentication UX
Major authentication system improvements:

- Remove deprecated DISABLE_AUTH environment variable support
- Update all documentation to remove DISABLE_AUTH references
- Add auth recovery instructions to docs (create .auth_recovery file)
- Improve first-run setup and Quick Security wizard flows
- Enhance login page with better error messaging and validation
- Refactor Docker hosts view with new unified table and tree components
- Add useDebouncedValue hook for better search performance
- Improve Settings page with better security configuration UX
- Update mock mode and development scripts for consistency
- Add ScrollableTable persistence and improved responsive design

Backend changes:
- Remove DISABLE_AUTH flag detection and handling
- Improve auth configuration validation and error messages
- Enhance security status endpoint responses
- Update router integration tests

Frontend changes:
- New Docker components: DockerUnifiedTable, DockerTree, DockerSummaryStats
- Better connection status indicator positioning
- Improved authentication state management
- Enhanced CSRF and session handling
- Better loading states and error recovery

This completes the migration away from the insecure DISABLE_AUTH pattern
toward proper authentication with recovery mechanisms.
2025-10-27 19:46:51 +00:00
rcourtman
7075cef326 Harden API auth and token handling 2025-10-25 14:54:03 +00:00
rcourtman
a6bf2c852b feat: add token revocation tracking and install script improvements
This commit adds comprehensive token revocation tracking across the UI and enhances the agent installation script for better platform support.

Key changes:
- Added token revocation warnings in Docker hosts and host agents UI with amber-colored indicators
- Implemented automatic token revocation detection when tokens are deleted
- Enhanced install scripts with Unraid detection and manual start instructions for non-systemd platforms
- Improved service management with restart instead of start for systemd
- Added visual indicators for revoked tokens with contextual warnings
- Updated table column widths in hosts overview for better layout
2025-10-24 22:30:10 +00:00
rcourtman
655fec2225 refactor: streamline host and Docker agent setup UI
Simplifies the onboarding flow by removing verbose instructions and toggles, consolidating navigation elements, and cleaning up the settings interface. Improves the macOS host agent installer with better Keychain access control and launchd service management.
2025-10-24 14:59:50 +00:00
rcourtman
8f553a93e9 refactor: remove pill-shaped badges from settings UI
Replace rounded pill badges with cleaner text and chip styles:
- Remove pill backgrounds from token/user authentication badges in node tables
- Simplify cluster node count from pill to plain text
- Change mobile navigation from pill bubbles to underlined tabs
- Convert subnet selection from rounded-full pills to squared chips

Reduces visual clutter and provides a more modern, minimal interface.
2025-10-24 11:52:38 +00:00
rcourtman
ffca20bc38 refactor: unify navigation icons across settings UI
Ensure consistent icon usage between top navigation tabs and settings sidebar:
- Proxmox: Use ProxmoxIcon in both locations
- Docker: Use DockerIcon (Simple Icons whale logo) in both locations
- Hosts: Simplify HostsIcon to use lucide Monitor icon everywhere

This improves visual consistency and reduces confusion between navigation contexts.
2025-10-24 11:48:22 +00:00
rcourtman
6a230b7677 fix: change Docker icon in left sidebar to Container icon
PROPERLY fix the Docker icon in the main left sidebar navigation by updating the DockerIcon component to use lucide's Container icon instead of Simple Icons Docker logo.

Also revert incorrect changes that added Docker to the Proxmox sub-navigation tabs - Docker should not be in the Proxmox settings sub-menu.
2025-10-24 11:40:27 +00:00
rcourtman
106be7540f fix: show settings navigation on Docker tab
The SettingsSectionNav was only visible on the Proxmox tab. Now it also shows on the Docker settings page (/settings/docker), displaying all four tabs: Virtual Environment, Backup Server, Mail Gateway, and Docker.

When on the Docker tab, the navigation correctly highlights Docker as active.
2025-10-24 11:37:36 +00:00
rcourtman
05771e982a refactor: simplify Docker agent token generation flow
Remove bloated multi-step wizard pattern and localStorage token storage in favor of a clean inline flow:
- Remove token generation modal and multi-step confirmation UI
- Remove localStorage persistence (useScopedTokenManager hook)
- Remove showTokenReveal popup - token goes directly into command
- Remove summary stat cards and redundant info cards
- Add simple inline input for optional token naming
- Token generation now instantly inserts into install command

The new flow: enter optional name → generate → copy command. No modals, no stored tokens, no extra steps.
2025-10-24 10:34:03 +00:00
rcourtman
a1bc0a94d5 refactor: condense settings UI with tab navigation
Replace large card-style buttons with compact tab navigation matching the Proxmox pages pattern. Remove redundant section headers that duplicated tab labels, significantly reducing visual bloat.
2025-10-24 10:16:22 +00:00
rcourtman
f20eccee86 refactor: remove step-based UI pattern from Proxmox settings
Replace the misleading "Step 1/Step 2" wizard pattern with a cleaner
dashboard-style layout. This better reflects the actual user flow of
selecting and configuring integrations.

Changes:
- Remove AgentStepSection wrapper and numbered badges
- Replace with standard SectionHeader for consistent typography
- Wrap PVE/PBS/PMG tables in Card components for better visual hierarchy
- Group action buttons (Discovery, Refresh, Add Node) in card headers
- Enhance empty states with icons and better messaging
- Fix spacing between integration selector and configuration sections
- Remove unused AgentStepSection import

All agent types (PVE, PBS, PMG, Docker, Host) now have consistent
presentation and improved visual clarity.
2025-10-24 09:10:52 +00:00
rcourtman
b311bdd069 Rename legacy settings tabs to Proxmox and Hosts 2025-10-24 08:50:18 +00:00
rcourtman
9d372ba9a8 refactor: improve frontend performance with lazy loading and component extraction
Add lazy loading for major route components (Dashboard, Settings, Docker, etc.) to reduce initial bundle size and improve load times. Extract node configuration tables (PVE, PBS, PMG) into dedicated reusable components with consistent table-based layouts. Implement Suspense fallbacks for smoother transitions between routes.
2025-10-24 08:20:12 +00:00
rcourtman
6333a445e9 feat: add native Windows service support and expandable host details
Windows Host Agent Enhancements:
- Implement native Windows service support using golang.org/x/sys/windows/svc
- Add Windows Event Log integration for troubleshooting
- Create professional PowerShell installation/uninstallation scripts
- Add process termination and retry logic to handle Windows file locking
- Register uninstall endpoint at /uninstall-host-agent.ps1

Host Agent UI Improvements:
- Add expandable drawer to Hosts page (click row to view details)
- Display system info, network interfaces, disks, and temperatures in cards
- Replace status badges with subtle colored indicators
- Remove redundant master-detail sidebar layout
- Add search filtering for hosts

Technical Details:
- service_windows.go: Windows service lifecycle management with graceful shutdown
- service_stub.go: Cross-platform compatibility for non-Windows builds
- install-host-agent.ps1: Full Windows installation with validation
- uninstall-host-agent.ps1: Clean removal with process termination and retries
- HostsOverview.tsx: Expandable row pattern matching Docker/Proxmox pages

Files Added:
- cmd/pulse-host-agent/service_windows.go
- cmd/pulse-host-agent/service_stub.go
- scripts/install-host-agent.ps1
- scripts/uninstall-host-agent.ps1
- frontend-modern/src/components/Hosts/HostsOverview.tsx
- frontend-modern/src/components/Hosts/HostsFilter.tsx

The Windows service now starts reliably with automatic restart on failure,
and the uninstall script handles file locking gracefully without requiring reboots.
2025-10-23 22:11:56 +00:00
rcourtman
f800d7d59d refactor: unify agent hub layout and copy 2025-10-23 18:09:09 +00:00
rcourtman
e565b292bf feat: unify agent deployments and scoped token flows 2025-10-23 17:14:34 +00:00
rcourtman
76263be05d Add gradient banners to settings pages for visual consistency
Adds polished gradient banner headers to all configuration pages:
- System > General, Network, Updates, Backups
- Security > Authentication (updated from gray to blue/indigo gradient)
- API Access

Resource management pages (PVE, PBS, Docker, etc.) intentionally left
without banners to keep focus on node tables and operational content.
2025-10-23 12:57:39 +00:00
rcourtman
5c54685f04 Add API token scopes and standalone host agent
Introduces granular permission scopes for API tokens (docker:report, docker:manage, host-agent:report, monitoring:read/write, settings:read/write) allowing tokens to be restricted to minimum required access. Legacy tokens default to full access until scopes are explicitly configured.

Adds standalone host agent for monitoring Linux, macOS, and Windows servers outside Proxmox/Docker estates. New Servers workspace in UI displays uptime, OS metadata, and capacity metrics from enrolled agents.

Includes comprehensive token management UI overhaul with scope presets, inline editing, and visual scope indicators.
2025-10-23 11:40:31 +00:00
rcourtman
971d55f334 Use lucide loader icon for discovery spinners 2025-10-22 12:30:04 +00:00
rcourtman
bc479643e4 release: prepare v4.25.0 2025-10-22 10:46:18 +00:00
rcourtman
ff4dc49ae4 Update Pulse install flow and related components 2025-10-21 19:58:53 +00:00
rcourtman
66b97333f7 fix: skip update check for source builds and show appropriate UI message
Source builds use commit hashes (main-c147fa1) not semantic versions
(v4.23.0), so update checks would always fail or show misleading
"Update Available" banners.

Changes:
- Add IsSourceBuild flag to VersionInfo struct
- Detect source builds via BUILD_FROM_SOURCE marker file
- Skip update check for source builds (like Docker)
- Update frontend to show "Built from source" message
- Disable manual update check button for source builds
- Return "source" deployment type for source builds

Backend:
- internal/updates/version.go: Add isSourceBuildEnvironment() detection
- internal/updates/manager.go: Skip check with appropriate message
- internal/api/types.go: Add isSourceBuild to API response
- internal/api/router.go: Include isSourceBuild in version endpoint

Frontend:
- src/api/updates.ts: Add isSourceBuild to VersionInfo type
- src/stores/updates.ts: Don't poll for updates on source builds
- src/components/Settings/Settings.tsx: Show "Built from source" message

Fixes the confusing "Update Available" banner for users who explicitly
chose --source to get latest main branch code.

Co-authored-by: Codex AI
2025-10-21 10:08:00 +00:00
rcourtman
524f42cc28 security: complete Phase 1 sensor proxy hardening
Implements comprehensive security hardening for pulse-sensor-proxy:
- Privilege drop from root to unprivileged user (UID 995)
- Hash-chained tamper-evident audit logging with remote forwarding
- Per-UID rate limiting (0.2 QPS, burst 2) with concurrency caps
- Enhanced command validation with 10+ attack pattern tests
- Fuzz testing (7M+ executions, 0 crashes)
- SSH hardening, AppArmor/seccomp profiles, operational runbooks

All 27 Phase 1 tasks complete. Ready for production deployment.
2025-10-20 15:13:37 +00:00
rcourtman
b640347a78 fix: improve discovery performance and reliability
Discovery Fixes:
- Always update cache even when scan finds no servers (prevents stale data)
- Remove automatic re-add of deleted nodes to discovery (was causing confusion)
- Optimize Docker subnet scanning from 762 IPs to 254 IPs (3x faster)
- Add getHostSubnetFromGateway() to detect host network from container

Frontend Type Fixes:
- Fix ThresholdsTable editScope type errors
- Fix SnapshotAlertConfig index signature
- Remove unused variable in Settings.tsx

These changes make discovery faster, more reliable, and fix the issue where
deleted nodes would persist in the discovery cache or immediately reappear.
2025-10-18 22:59:40 +00:00
Pulse Automation Bot
cfdfe896be Adjust backup and snapshot alert handling 2025-10-18 20:11:01 +00:00
Pulse Automation Bot
0b4e4f9c59 Add configurable backup polling interval 2025-10-18 13:06:41 +00:00
Richard Courtman
669d7dc05c feat: add turnkey temperature monitoring for standalone nodes
Implements automatic temperature monitoring setup for standalone
Proxmox/Pimox nodes without manual SSH key configuration.

Changes:
- Add /api/system/proxy-public-key endpoint to expose proxy's SSH public key
- Setup script now detects standalone nodes (non-cluster)
- Auto-fetches and installs proxy SSH key with forced commands
- Add Raspberry Pi temperature support via cpu_thermal and /sys/class/thermal
- Enhance setup script with better error handling for lm-sensors installation
- Add RPi detection to skip lm-sensors and use native thermal interface

Security:
- Public key endpoint is safe (public keys are meant to be public)
- All installed keys use forced command="sensors -j" with full restrictions
- No shell access, port forwarding, or other SSH features enabled
2025-10-17 22:15:50 +00:00
rcourtman
123e0f04ca feat: add comprehensive node cleanup system
Implements automated cleanup workflow when nodes are deleted from Pulse, removing all monitoring footprint from the host. Changes include a new RPC handler in the sensor proxy for cleanup requests, enhanced node deletion modal with detailed cleanup explanations, and improved SSH key management with proper tagging for atomic updates.
2025-10-17 18:53:45 +00:00
rcourtman
f141f7db33 feat: enhance sensor proxy with improved cluster discovery and SSH management
Improvements to pulse-sensor-proxy:
- Fix cluster discovery to use pvecm status for IP addresses instead of node names
- Add standalone node support for non-clustered Proxmox hosts
- Enhanced SSH key push with detailed logging, success/failure tracking, and error reporting
- Add --pulse-server flag to installer for custom Pulse URLs
- Configure www-data group membership for Proxmox IPC access

UI and API cleanup:
- Remove unused "Ensure cluster keys" button from Settings
- Remove /api/diagnostics/temperature-proxy/ensure-cluster-keys endpoint
- Remove EnsureClusterKeys method from tempproxy client

The setup script already handles SSH key distribution during initial configuration,
making the manual refresh button redundant.
2025-10-17 11:43:26 +00:00
rcourtman
3a4fc044ea Add guest agent caching and update doc hints (refs #560) 2025-10-16 08:15:49 +00:00
rcourtman
e2a0fbe816 Fix API token generation UX 2025-10-15 22:38:50 +00:00
rcourtman
5ce47a72ec Improve discovery classification heuristics
Refs #551
2025-10-15 14:08:05 +00:00
rcourtman
261bd7ac74 Adopt multi-token auth across docs, UI, and tooling 2025-10-14 15:47:49 +00:00
rcourtman
5c79d2516d feat: streamline docker agent onboarding 2025-10-14 09:45:32 +00:00
rcourtman
a74baed121 feat: capture Proxmox memory snapshots in diagnostics 2025-10-12 10:25:43 +00:00
rcourtman
f46ff1792b Fix settings security tab navigation 2025-10-11 23:29:47 +00:00