botserver/src/settings/mod.rs
Rodrigo Rodriguez (Pragmatismo) faeae250bc Add security protection module with sudo-based privilege escalation
- Create installer.rs for 'botserver install protection' command
- Requires root to install packages and create sudoers config
- Sudoers uses exact commands (no wildcards) for security
- Update all tool files (lynis, rkhunter, chkrootkit, suricata, lmd) to use sudo
- Update manager.rs service management to use sudo
- Add 'sudo' and 'visudo' to command_guard.rs whitelist
- Update CLI with install/remove/status protection commands

Security model:
- Installation requires root (sudo botserver install protection)
- Runtime uses sudoers NOPASSWD for specific commands only
- No wildcards in sudoers - exact command specifications
- Tools run on host system, not in containers
2026-01-10 09:41:12 -03:00

158 lines
4.9 KiB
Rust

pub mod audit_log;
pub mod menu_config;
pub mod permission_inheritance;
pub mod rbac;
pub mod rbac_ui;
pub mod security_admin;
use axum::{
extract::State,
response::Html,
routing::{get, post},
Router,
};
use std::sync::Arc;
use crate::shared::state::AppState;
pub fn configure_settings_routes() -> Router<Arc<AppState>> {
Router::new()
.route("/api/user/storage", get(get_storage_info))
.route("/api/user/storage/connections", get(get_storage_connections))
.route("/api/user/security/2fa/status", get(get_2fa_status))
.route("/api/user/security/2fa/enable", post(enable_2fa))
.route("/api/user/security/2fa/disable", post(disable_2fa))
.route("/api/user/security/sessions", get(get_active_sessions))
.route(
"/api/user/security/sessions/revoke-all",
post(revoke_all_sessions),
)
.route("/api/user/security/devices", get(get_trusted_devices))
.merge(rbac::configure_rbac_routes())
.merge(security_admin::configure_security_admin_routes())
}
async fn get_storage_info(State(_state): State<Arc<AppState>>) -> Html<String> {
Html(
r##"<div class="storage-info">
<div class="storage-bar">
<div class="storage-used" style="width: 25%"></div>
</div>
<div class="storage-details">
<span class="storage-used-text">2.5 GB used</span>
<span class="storage-total-text">of 10 GB</span>
</div>
<div class="storage-breakdown">
<div class="storage-item">
<span class="storage-icon">📄</span>
<span class="storage-label">Documents</span>
<span class="storage-size">1.2 GB</span>
</div>
<div class="storage-item">
<span class="storage-icon">🖼️</span>
<span class="storage-label">Images</span>
<span class="storage-size">800 MB</span>
</div>
<div class="storage-item">
<span class="storage-icon">📧</span>
<span class="storage-label">Emails</span>
<span class="storage-size">500 MB</span>
</div>
</div>
</div>"##
.to_string(),
)
}
async fn get_storage_connections(State(_state): State<Arc<AppState>>) -> Html<String> {
Html(
r##"<div class="connections-empty">
<p class="text-muted">No external storage connections configured</p>
<button class="btn-secondary" onclick="showAddConnectionModal()">
+ Add Connection
</button>
</div>"##
.to_string(),
)
}
async fn get_2fa_status(State(_state): State<Arc<AppState>>) -> Html<String> {
Html(
r##"<div class="status-indicator">
<span class="status-dot inactive"></span>
<span class="status-text">Two-factor authentication is not enabled</span>
</div>"##
.to_string(),
)
}
async fn enable_2fa(State(_state): State<Arc<AppState>>) -> Html<String> {
Html(
r##"<div class="status-indicator">
<span class="status-dot active"></span>
<span class="status-text">Two-factor authentication enabled</span>
</div>"##
.to_string(),
)
}
async fn disable_2fa(State(_state): State<Arc<AppState>>) -> Html<String> {
Html(
r##"<div class="status-indicator">
<span class="status-dot inactive"></span>
<span class="status-text">Two-factor authentication disabled</span>
</div>"##
.to_string(),
)
}
async fn get_active_sessions(State(_state): State<Arc<AppState>>) -> Html<String> {
Html(
r##"<div class="session-item current">
<div class="session-info">
<div class="session-device">
<span class="device-icon">💻</span>
<span class="device-name">Current Session</span>
<span class="session-badge current">This device</span>
</div>
<div class="session-details">
<span class="session-location">Current browser session</span>
<span class="session-time">Active now</span>
</div>
</div>
</div>
<div class="sessions-empty">
<p class="text-muted">No other active sessions</p>
</div>"##
.to_string(),
)
}
async fn revoke_all_sessions(State(_state): State<Arc<AppState>>) -> Html<String> {
Html(
r##"<div class="success-message">
<span class="success-icon">✓</span>
<span>All other sessions have been revoked</span>
</div>"##
.to_string(),
)
}
async fn get_trusted_devices(State(_state): State<Arc<AppState>>) -> Html<String> {
Html(
r##"<div class="device-item current">
<div class="device-info">
<span class="device-icon">💻</span>
<div class="device-details">
<span class="device-name">Current Device</span>
<span class="device-last-seen">Last active: Just now</span>
</div>
</div>
<span class="device-badge trusted">Trusted</span>
</div>
<div class="devices-empty">
<p class="text-muted">No other trusted devices</p>
</div>"##
.to_string(),
)
}