Commit graph

109 commits

Author SHA1 Message Date
4573869607
Reduce log noise by changing INFO to DEBUG for routine operations
Changed the following from INFO to DEBUG level:
- Channel join messages
- Job execution start/completion messages
- SNMP operation messages (GET/WALK)
- Device health check results
- MikroTik job execution
- Device poller thread lifecycle
- Credential test messages
- OID collection results

These messages were generating excessive noise during normal operation.
Kept INFO level for:
- Initial connection establishment
- Shutdown/restart messages
- Update operations
- Errors (already at ERROR/WARN level)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 16:49:58 -06:00
7b793b315a
speed up tests: reduce SNMP timeout from 1s to 200ms 2026-02-10 16:19:54 -06:00
57ace0297b
fix clippy needless_return warning 2026-02-10 16:15:37 -06:00
55d001d9f8
Add fork()-based process isolation for SNMP operations
Each SNMP GET/WALK now runs in a forked child process. If libnetsnmp
triggers a SIGSEGV or other fatal signal, only the child dies - the
parent agent logs the crash and continues operating for all other devices.

Key changes:
- C helper: snmp_get_isolated() and snmp_walk_isolated() using
  fork+pipe pattern with 60s alarm watchdog and mutex-serialized forks
- Rust: IsolationMode enum (Fork/Direct) controlled by
  TOWEROPS_SNMP_ISOLATION env var, defaults to Fork
- New CrashRecovered error variant with signal info and logging
- Device poller logs crash recovery events at error level
- Startup logs active isolation mode

Set TOWEROPS_SNMP_ISOLATION=direct to disable isolation for debugging.
2026-02-10 16:12:41 -06:00
ab0db979a1
format 2026-02-10 15:48:51 -06:00
7bffbecd21
Fix function_casts_as_integer warnings in crash handler
Cast function pointers through *const () before converting to
sighandler_t, as required by Rust 1.93+.
2026-02-10 15:44:15 -06:00
29b94c09d4
Fix segfault from Alpine version mismatch, add crash handler
The builder (rust:1.93-alpine) uses Alpine 3.23 but the runtime used
Alpine 3.19. The net-snmp-dev headers from 3.23 don't match
net-snmp-libs from 3.19, causing a segfault on the first SNMP call.

Also adds a SIGSEGV/SIGBUS/SIGABRT signal handler that prints a
diagnostic message instead of silently exiting with code 139.
2026-02-10 14:14:07 -06:00
fa46d279a7
Use short SNMP timeouts in tests to avoid 90s waits
Tests against unreachable hosts (192.0.2.1) were waiting 10s * 3 attempts
per request. With cfg(test) overrides (1s timeout, 0 retries), the full
test suite runs in ~3s instead of ~90s.
2026-02-10 14:00:56 -06:00
32a60beadb
Fix rustls CryptoProvider panic by explicitly selecting ring
Both ring and aws-lc-rs were enabled transitively (webpki-roots enables
rustls default features), causing rustls to panic at runtime because it
couldn't auto-detect which crypto provider to use.

- Add rustls as direct dep with ring only, disable default features
- Switch russh from aws-lc-rs (default) to ring crypto backend
- Call ring::default_provider().install_default() at startup
- Add macOS build fix: detect Homebrew OpenSSL path for netsnmp's libcrypto
2026-02-10 13:50:33 -06:00
91c407ed5b
Replace surge-ping library with command-line ping
Switched from surge-ping Rust library to system ping command (iputils)
to avoid requiring CAP_NET_RAW capability for ICMP ping.

Changes:
- Use tokio::process::Command to execute /bin/ping or /bin/ping6
- Parse response time from ping output (time=X.XX ms)
- Removed surge-ping and rand dependencies from Cargo.toml
- Added tokio "process" feature

Benefits:
- No special capabilities required (ping binary has setuid root)
- Works in restricted container environments
- Already available in Docker image (iputils package)
- More portable across different container runtimes

The system ping command is already installed in the Docker image
and has setuid root permissions, allowing it to create raw sockets
without requiring the container to have CAP_NET_RAW.
2026-02-10 13:24:32 -06:00
b0f3b57671
Add restart and self-update handlers, publish standalone binaries
Handle server-initiated restart (exit for Docker restart) and
self-update (download binary, verify SHA256, replace via exec)
commands received over the WebSocket channel. Report architecture
in heartbeat so the server can select the correct binary.

- Add restart and update handlers in websocket_client.rs
- Add self_update() with download, checksum verification, and exec
- Add arch field to AgentHeartbeat protobuf
- Add reqwest and sha2 dependencies
- chown binary in Dockerfile for non-root self-update
- Extract standalone binaries from Docker images in CI
- Create GitHub Releases with binary assets on version tags
2026-02-10 13:06:23 -06:00
f8c8c8bb8e
Remove get_local_ip - server determines IP from WebSocket connection 2026-02-10 09:52:25 -06:00
8824eb1ddb
Remove hostname sending 2026-02-10 09:49:15 -06:00
58d53cab1e
Remove TUI feature and all related code
Drop ratatui, crossterm, hostname dependencies and the tui feature flag.
Delete src/tui/ directory, remove event bus plumbing from websocket client,
and simplify connect/init_logger to single implementations.

-1,979 lines of conditional compilation removed.
2026-02-10 09:31:39 -06:00
dba1c6a79c
Fix arm64 build: use c_char instead of i8 in FFI declarations
On ARM64 Linux, c_char is u8 (unsigned), not i8 (signed).
Using the platform-correct std::ffi::c_char type fixes the
cross-compilation error.
2026-02-10 08:40:15 -06:00
7882e6b726
Fix test compilation: make device_id field public 2026-02-10 08:33:18 -06:00
2850f4f68f
Use iterator instead of index loop in walk result parsing 2026-02-10 08:31:07 -06:00
36f89ddef3
Remove dead code: unused functions, constants, methods, and enum variant 2026-02-10 08:30:11 -06:00
23ccd24210
Fix SNMP client tests for Linux CI environment
- Map "Failed to parse OID" C library errors to InvalidOid variant
- Walk to unreachable host may return empty results instead of error
  on some Linux configurations
2026-02-10 08:26:19 -06:00
1192774e30
Use build timestamp version in TUI display
The TUI agent state was using CARGO_PKG_VERSION (0.1.0) instead of
version::current_version() which returns the RFC 3339 build timestamp.
2026-02-10 07:51:52 -06:00
65fbf3bb31
use datestamp instead of creating a version 2026-02-09 13:49:19 -06:00
792825f682
major overhaul to use more C for snmp, may not be stable 2026-02-09 12:31:41 -06:00
cd45e9ff51
feat: add agent-side ICMP ping health monitoring
Implements health monitoring in the agent using ICMP ping, allowing
devices assigned to local (non-cloud) agents to be monitored.

Changes:
- Add surge-ping library for async ICMP ping operations
- Create ping.rs module with ping_device() function (5s timeout)
- Rename JobType::MONITOR to JobType::PING in protobuf
- Add monitoring_check channels for result communication
- Implement execute_ping_job() to handle PING jobs
- Update TUI to display ping result events

The agent now receives PING jobs from Phoenix, executes ICMP pings,
and sends MonitoringCheck results back for storage in the database.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-08 13:44:09 -06:00
cee0788300
format 2026-02-07 11:43:50 -06:00
f5b7e589f2
fix: implement agent IP detection and remove dead poller code
- Implement get_local_ip() using UDP socket trick to resolve local
  interface address without sending traffic, so heartbeat reports
  actual agent IP instead of "unknown"
- Remove dead poller/scheduler/executor and api_client modules that
  referenced non-existent modules and were never compiled
2026-02-07 09:17:47 -06:00
2111453653
Fix TUI 2026-02-06 13:18:23 -06:00
6275562f35
Resolve issues from TUI implementation 2026-02-06 13:08:06 -06:00
a2cef243ee
Handle discovered ip addresses 2026-02-06 12:20:53 -06:00
8c969401fb
fix live and scheduled polling 2026-02-05 12:45:13 -06:00
d44682ce9c
fix: increase SNMP timeout to 120s for SNMPv3 discovery
Discovery with SNMPv3 was completing in 52 seconds, dangerously close
to the 60s timeout. Increasing to 120s provides comfortable headroom
for complete MikroTik OID tree traversal with encryption overhead.
2026-02-05 09:02:05 -06:00
357d1711be
fix: increase SNMP timeout to 60s for SNMPv3 operations
SNMPv3 has significant encryption and authentication overhead compared to
v2c. MikroTik enterprise tree walks (1.3.6.1.4.1.14988) can take 16+
seconds with SNMPv3, causing timeouts with the previous 30s limit.

Increased timeout from 30s to 60s in both client.rs and device_poller.rs
to accommodate SNMPv3's additional latency.
2026-02-05 08:45:20 -06:00
c62330bf40
handle other encryption methods 2026-02-04 17:46:09 -06:00
55d55a2c86
fix tests 2026-02-04 17:29:19 -06:00
f454a1f7ea
experimental tcp snmp handling 2026-02-04 17:25:39 -06:00
df334e4db8
Security hardening and performance improvements 2026-02-04 16:50:36 -06:00
91913bd6e4
Implement snmp v3 support 2026-02-04 12:02:10 -06:00
1be76b0049
show partially redacted snmp community 2026-02-03 16:50:11 -06:00
0f19518065
snmpv3 first stab 2026-02-03 16:46:19 -06:00
4719bb8249
bump russh 2026-02-02 17:17:53 -06:00
89a53eb07a
fix snmp community redaction 2026-02-02 17:03:46 -06:00
78aee7ce40
add ssh support 2026-02-02 16:39:09 -06:00
8e8ea6426d
mikrotik api improvements 2026-02-02 14:02:27 -06:00
d137925a0f
update deps 2026-02-02 13:26:02 -06:00
575735b0da
Handle generic mikrotik commands 2026-02-02 13:18:31 -06:00
eb330b2f6f
protobufs update for mikrotik things 2026-02-02 12:25:40 -06:00
98d1bbbb21
structured logging 2026-01-31 15:40:42 -06:00
b8aecf0a55
more tests 2026-01-31 15:26:36 -06:00
4cd357777f
Add TRAP_ENABLED env var to conditionally enable trap listener 2026-01-31 14:39:24 -06:00
89adc3a6b3
Add SNMP trap listener for v1 and v2c traps
- Add trap.rs with BER/ASN.1 parser for SNMP trap PDUs
- Support both SNMPv1 and SNMPv2c trap formats
- Listen on configurable UDP port (default 162)
- Log received traps at INFO level
- Add LOG_LEVEL env var for log verbosity control
- Add TRAP_PORT env var and CLI flag
- Update docker-compose with trap port mapping
2026-01-31 14:14:56 -06:00
8ed2208271
poll each device simultaneously 2026-01-31 14:00:00 -06:00