fix(security): Implement Phase 1 critical security fixes

CORS:
- Restrict CORS to DASHBOARD_URL environment variable
- Default to production dashboard domain

Authentication:
- Add AuthUser requirement to all agent management endpoints
- Add AuthUser requirement to all command endpoints
- Add AuthUser requirement to all metrics endpoints
- Add audit logging for command execution (user_id tracked)

Agent Security:
- Replace Unicode characters with ASCII markers [OK]/[ERROR]/[WARNING]
- Add certificate pinning for update downloads (allowlist domains)
- Fix insecure temp file creation (use /var/run/gururmm with 0700 perms)
- Fix rollback script backgrounding (use setsid instead of literal &)

Dashboard Security:
- Move token storage from localStorage to sessionStorage
- Add proper TypeScript types (remove 'any' from error handlers)
- Centralize token management functions

Legacy Agent:
- Add -AllowInsecureTLS parameter (opt-in required)
- Add Windows Event Log audit trail when insecure mode used
- Update documentation with security warnings

Closes: Phase 1 items in issue #1

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-20 21:16:24 -07:00
parent 6d3271c144
commit 65086f4407
15 changed files with 1708 additions and 99 deletions

View File

@@ -457,14 +457,14 @@ WantedBy=multi-user.target
anyhow::bail!("systemctl enable failed");
}
println!("\n GuruRMM Agent installed successfully!");
println!("\n[OK] GuruRMM Agent installed successfully!");
println!("\nInstalled files:");
println!(" Binary: {}", binary_dest);
println!(" Config: {}", config_dest);
println!(" Service: {}", unit_file);
if config_needs_manual_edit {
println!("\n⚠️ IMPORTANT: Edit {} with your server URL and API key!", config_dest);
println!("\n[WARNING] IMPORTANT: Edit {} with your server URL and API key!", config_dest);
println!("\nNext steps:");
println!(" 1. Edit {} with your server URL and API key", config_dest);
println!(" 2. Start the service: sudo systemctl start {}", SERVICE_NAME);
@@ -475,9 +475,9 @@ WantedBy=multi-user.target
.status();
if status.is_ok() && status.unwrap().success() {
println!(" Service started successfully!");
println!("[OK] Service started successfully!");
} else {
println!("⚠️ Failed to start service. Check logs: sudo journalctl -u {} -f", SERVICE_NAME);
println!("[WARNING] Failed to start service. Check logs: sudo journalctl -u {} -f", SERVICE_NAME);
}
}
@@ -556,7 +556,7 @@ async fn uninstall_systemd_service() -> Result<()> {
.args(["daemon-reload"])
.status();
println!("\n GuruRMM Agent uninstalled successfully!");
println!("\n[OK] GuruRMM Agent uninstalled successfully!");
println!("\nNote: Config directory {} was preserved.", CONFIG_DIR);
println!("Remove it manually if no longer needed: sudo rm -rf {}", CONFIG_DIR);
@@ -582,7 +582,7 @@ async fn start_service() -> Result<()> {
.context("Failed to start service")?;
if status.success() {
println!("** Service started successfully");
println!("[OK] Service started successfully");
println!("Check status: sudo systemctl status gururmm-agent");
} else {
anyhow::bail!("Failed to start service. Check: sudo journalctl -u gururmm-agent -n 50");
@@ -616,7 +616,7 @@ async fn stop_service() -> Result<()> {
.context("Failed to stop service")?;
if status.success() {
println!("** Service stopped successfully");
println!("[OK] Service stopped successfully");
} else {
anyhow::bail!("Failed to stop service");
}