#![cfg_attr(not(target_os = "linux"), allow(dead_code))]
mod control_plane;
mod error;
mod receipt;
pub use control_plane::ControlPlane;
pub use error::{Error, Result};
pub use receipt::{Action, ActionType, SecurityDecision, SecurityMechanism, Subject};
#[cfg(test)]
use chrono::Utc;
use std::sync::atomic::{AtomicBool, Ordering};
#[derive(Debug)]
pub struct AgentGuard {
initialized: AtomicBool,
}
impl AgentGuard {
#[deprecated(note = "agent-guard is a scaffold — no OS enforcement is implemented")]
#[cfg(target_os = "linux")]
pub fn new() -> Self {
Self {
initialized: AtomicBool::new(false),
}
}
#[deprecated(note = "agent-guard is a scaffold — no OS enforcement is implemented")]
#[cfg(not(target_os = "linux"))]
pub fn new() -> Self {
Self {
initialized: AtomicBool::new(false),
}
}
#[deprecated(note = "agent-guard is a scaffold — no OS enforcement is implemented")]
pub fn initialize(&mut self) -> Result<()> {
#[cfg(target_os = "linux")]
{
self.initialized.store(true, Ordering::SeqCst);
Ok(())
}
#[cfg(not(target_os = "linux"))]
{
Err(Error::InvalidConfig(
"AgentGuard is only available on Linux".to_string(),
))
}
}
pub fn is_initialized(&self) -> bool {
self.initialized.load(Ordering::SeqCst)
}
#[cfg(test)]
fn make_decision(&self, subject: &Subject, action: &Action) -> SecurityDecision {
let decision_id = format!("guard-{}-{}", subject.name, Utc::now().timestamp());
SecurityDecision {
decision_id,
subject: subject.clone(),
action: action.clone(),
allowed: true,
reason: "Allowed by AgentGuard control plane".to_string(),
timestamp: Utc::now(),
mechanisms: vec![],
}
}
}
impl Default for AgentGuard {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[allow(deprecated)]
fn test_agent_guard_new() {
let guard = AgentGuard::new();
assert!(!guard.is_initialized());
}
#[test]
#[allow(deprecated)]
#[cfg(target_os = "linux")]
fn test_agent_guard_initialize() {
let mut guard = AgentGuard::new();
assert!(guard.initialize().is_ok());
assert!(guard.is_initialized());
}
#[test]
#[allow(deprecated)]
fn test_make_decision() {
let guard = AgentGuard::new();
let subject = Subject {
pid: Some(1234),
name: "test-agent".to_string(),
cgroup_path: None,
};
let action = Action {
action_type: ActionType::FileRead,
resource: "/etc/passwd".to_string(),
metadata: None,
};
let decision = guard.make_decision(&subject, &action);
assert!(decision.allowed);
assert_eq!(decision.subject.name, "test-agent");
}
#[test]
#[allow(deprecated)]
#[cfg(not(target_os = "linux"))]
fn test_agent_guard_not_available() {
let mut guard = AgentGuard::new();
let result = guard.initialize();
assert!(result.is_err());
}
}