remove hive-level infra-container restart from web ui and agents
This commit is contained in:
parent
ccf9951e5d
commit
7516a4e10e
17 changed files with 112 additions and 272 deletions
|
|
@ -1,23 +1,20 @@
|
|||
//! Sqlite-backed audit trail of agent-initiated privileged actions.
|
||||
//! Sqlite-backed audit trail of privileged actions worth a durable,
|
||||
//! operator-visible who/what/when record beyond hive-priv's low-level
|
||||
//! journal trace — currently the dashboard's operator-driven infra
|
||||
//! container start/stop (`dashboard::infra_containers::post_infra_container`).
|
||||
//!
|
||||
//! Surfaces, durably and operator-visibly, the privileged operations
|
||||
//! hive-c0re performs *on behalf of an agent* — the ones that cross the
|
||||
//! agent/operator trust boundary and so warrant a who/what/when record
|
||||
//! beyond hive-priv's low-level journal trace. First entry: infra
|
||||
//! container restarts via the `infra_admin`-gated `restart` tool (the
|
||||
//! follow-up audit trail for that capability).
|
||||
//!
|
||||
//! Deliberately scoped to *agent-initiated* privileged actions. The bulk
|
||||
//! of `PrivRequest` traffic (token writes, nspawn-flag edits) fires
|
||||
//! constantly during normal lifecycle and is hive-c0re's own bookkeeping,
|
||||
//! not an agent crossing the boundary — logging all of it would drown the
|
||||
//! signal the operator actually wants.
|
||||
//! Deliberately narrow: the bulk of `PrivRequest` traffic (token writes,
|
||||
//! nspawn-flag edits) fires constantly during normal lifecycle and is
|
||||
//! hive-c0re's own bookkeeping, not a privileged action worth a standalone
|
||||
//! record — logging all of it would drown the signal the operator
|
||||
//! actually wants. Nothing agent-initiated lands here today; the module
|
||||
//! stays generic for whatever privileged action needs this record next.
|
||||
//!
|
||||
//! Same process-singleton handle pattern as `build_logs`: installed once
|
||||
//! at `Coordinator::open`, and fetched by recording sites (e.g.
|
||||
//! `socket_server::handle_restart_infra`) so they don't have to thread an
|
||||
//! `Arc<AuditLog>` through every call path. Recording is best-effort: a
|
||||
//! sqlite blip must never fail the underlying privileged action.
|
||||
//! at `Coordinator::open`, and fetched by recording sites so they don't
|
||||
//! have to thread an `Arc<AuditLog>` through every call path. Recording is
|
||||
//! best-effort: a sqlite blip must never fail the underlying privileged
|
||||
//! action.
|
||||
|
||||
use std::path::Path;
|
||||
use std::sync::{Arc, Mutex, OnceLock};
|
||||
|
|
@ -85,9 +82,10 @@ impl AuditOutcome {
|
|||
pub struct AuditEntry {
|
||||
pub id: i64,
|
||||
pub ts_unix: DateTime<Utc>,
|
||||
/// Agent on whose behalf the action was taken.
|
||||
/// Actor who took the action (e.g. `"operator"`, or an agent name for
|
||||
/// a future agent-initiated entry).
|
||||
pub agent: String,
|
||||
/// What was done (e.g. `restart_infra`).
|
||||
/// What was done (e.g. `stop_infra`).
|
||||
pub action: String,
|
||||
/// What it acted on (e.g. `hive-ci`).
|
||||
pub target: String,
|
||||
|
|
@ -267,15 +265,15 @@ mod tests {
|
|||
let (_d, db) = tmpdb();
|
||||
// record() returns the canonical inserted row (id + ts assigned).
|
||||
let entry = db
|
||||
.record("atlas", "restart_infra", "hive-ci", AuditOutcome::Ok, None)
|
||||
.record("operator", "stop_infra", "hive-ci", AuditOutcome::Ok, None)
|
||||
.expect("record returns the inserted entry");
|
||||
assert!(entry.id > 0);
|
||||
assert_eq!(entry.target, "hive-ci");
|
||||
assert_eq!(entry.outcome, "ok");
|
||||
assert!(entry.detail.is_none());
|
||||
let _ = db.record(
|
||||
"atlas",
|
||||
"restart_infra",
|
||||
"operator",
|
||||
"stop_infra",
|
||||
"hive-gateway",
|
||||
AuditOutcome::Err,
|
||||
Some("systemctl failed"),
|
||||
|
|
@ -289,8 +287,8 @@ mod tests {
|
|||
assert_eq!(rows[1].target, "hive-ci");
|
||||
assert_eq!(rows[1].outcome, "ok");
|
||||
assert!(rows[1].detail.is_none());
|
||||
assert_eq!(rows[0].agent, "atlas");
|
||||
assert_eq!(rows[0].action, "restart_infra");
|
||||
assert_eq!(rows[0].agent, "operator");
|
||||
assert_eq!(rows[0].action, "stop_infra");
|
||||
assert_eq!(db.count_total().expect("count"), 2);
|
||||
}
|
||||
|
||||
|
|
@ -305,7 +303,7 @@ mod tests {
|
|||
#[test]
|
||||
fn vacuum_drops_only_old_rows() {
|
||||
let (_d, db) = tmpdb();
|
||||
let _ = db.record("a", "restart_infra", "hive-ci", AuditOutcome::Ok, None);
|
||||
let _ = db.record("operator", "stop_infra", "hive-ci", AuditOutcome::Ok, None);
|
||||
// Backdate it past the retention window.
|
||||
{
|
||||
let conn = db.conn.lock().unwrap();
|
||||
|
|
@ -315,7 +313,13 @@ mod tests {
|
|||
)
|
||||
.unwrap();
|
||||
}
|
||||
let _ = db.record("a", "restart_infra", "hive-forge", AuditOutcome::Ok, None);
|
||||
let _ = db.record(
|
||||
"operator",
|
||||
"stop_infra",
|
||||
"hive-forge",
|
||||
AuditOutcome::Ok,
|
||||
None,
|
||||
);
|
||||
let removed = db.vacuum().expect("vacuum");
|
||||
assert_eq!(removed, 1, "only the backdated row should be reaped");
|
||||
let rows = db.list_recent(10).expect("list");
|
||||
|
|
|
|||
Loading…
Reference in a new issue