Release / Plan (reuse the published image?) (push) Successful in 3s
CI / Docker image (build and smoke test) (push) Skipped
CI / Format and clippy (push) Successful in 4m32s
CI / Dependency audit (push) Successful in 11s
CI / Tests (Linux) (push) Successful in 9m15s
Release / ci (push) Successful in 9m18s
Release / Build image (arm64) (push) Failing after 7m7s
Release / Build image (amd64) (push) Failing after 13m53s
Release / Publish tags (push) Skipped
Release / Gitea release (push) Skipped
Acaua is a collective SOC daemon consuming only Zeek log files, not a single-user tool needing local hardware like its siblings. Drop the Tauri desktop shell, installers and self-update entirely; the server and its web dashboard ship as a container, updated by pulling a new image tag. Link against the official prebuilt libduckdb instead of compiling it from source via the bundled feature, cutting image build time from 15+ minutes to about 3. Fix a real bug found along the way: as PID 1 in a container, the daemon ignored SIGTERM and was always killed after the stop timeout; it now shuts down gracefully. Also corrects the Pillar 1 beaconing score: the period estimate had a harmonic alias (a perfectly periodic 4h series resolved to 600s), and the old score formula flagged pure random traffic as suspicious (p95 = 0.839 on Poisson noise). The new formula was validated against 300 samples per scenario. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VAyr8d7HuAdUGB6aA5xmDD
69 lines
2.0 KiB
Rust
69 lines
2.0 KiB
Rust
use crate::error::{AcauaError, Result};
|
|
use serde::{Deserialize, Serialize};
|
|
use std::process::Command;
|
|
|
|
const LATEST_RELEASE_URL: &str =
|
|
"https://git.lucasrguerra.dev.br/api/v1/repos/ciberfauna/acaua/releases/latest";
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
struct Release {
|
|
tag_name: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize)]
|
|
pub struct UpdateStatus {
|
|
pub current_version: String,
|
|
pub latest_version: Option<String>,
|
|
pub update_available: bool,
|
|
}
|
|
|
|
fn curl_text(url: &str) -> Result<String> {
|
|
let output = Command::new("curl")
|
|
.args(["-fsSL", "-H", "User-Agent: acaua-updater", url])
|
|
.output()
|
|
.map_err(|error| AcauaError::CommandFailed {
|
|
cmd: format!("curl {url}"),
|
|
detail: error.to_string(),
|
|
})?;
|
|
if !output.status.success() {
|
|
return Err(AcauaError::CommandFailed {
|
|
cmd: format!("curl {url}"),
|
|
detail: String::from_utf8_lossy(&output.stderr).into_owned(),
|
|
});
|
|
}
|
|
Ok(String::from_utf8_lossy(&output.stdout).into_owned())
|
|
}
|
|
|
|
pub fn check(current_version: &str) -> Result<UpdateStatus> {
|
|
let body = match curl_text(LATEST_RELEASE_URL) {
|
|
Ok(body) => body,
|
|
Err(_) => {
|
|
return Ok(UpdateStatus {
|
|
current_version: current_version.to_string(),
|
|
latest_version: None,
|
|
update_available: false,
|
|
});
|
|
}
|
|
};
|
|
let release: Release = serde_json::from_str(&body)?;
|
|
let latest = release.tag_name.trim_start_matches('v').to_string();
|
|
let update_available = latest != current_version;
|
|
Ok(UpdateStatus {
|
|
current_version: current_version.to_string(),
|
|
latest_version: Some(latest),
|
|
update_available,
|
|
})
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn parses_latest_release_tag() {
|
|
let json = r#"{"tag_name": "v0.2.0"}"#;
|
|
let release: Release = serde_json::from_str(json).unwrap();
|
|
assert_eq!(release.tag_name, "v0.2.0");
|
|
}
|
|
}
|