use capsec::prelude::*;
fn load_config(path: &str, cap: &impl CapProvider<FsRead>) -> Result<String, CapSecError> {
capsec::fs::read_to_string(path, cap)
}
fn send_metrics(
addr: &str,
data: &str,
cap: &impl CapProvider<NetConnect>,
) -> Result<(), CapSecError> {
let mut stream = capsec::net::tcp_connect(addr, cap)?;
std::io::Write::write_all(&mut stream, data.as_bytes())?;
Ok(())
}
fn save_cache(path: &str, data: &str) {
std::fs::write(path, data).expect("cache write failed");
}
fn get_log_level() -> String {
std::env::var("LOG_LEVEL").unwrap_or_else(|_| "info".into())
}
fn format_report(config: &str, level: &str) -> String {
format!("[{level}] config loaded: {}", config.len())
}
#[capsec::main]
fn main(root: CapRoot) -> Result<(), Box<dyn std::error::Error>> {
let fs_read = root.fs_read();
let net_cap = root.net_connect();
let config = load_config("/etc/app/config.toml", &fs_read)?;
let level = get_log_level();
save_cache("/tmp/app.cache", &config);
let report = format_report(&config, &level);
send_metrics("metrics.example.com:9090", &report, &net_cap)?;
println!("{report}");
Ok(())
}