1#![cfg_attr(not(target_os = "linux"), allow(dead_code))]
27
28mod control_plane;
29mod error;
30mod receipt;
31
32pub use control_plane::ControlPlane;
33pub use error::{Error, Result};
34pub use receipt::{Action, ActionType, SecurityDecision, SecurityMechanism, Subject};
35
36#[cfg(test)]
37use chrono::Utc;
38use std::sync::atomic::{AtomicBool, Ordering};
39
40#[derive(Debug)]
50pub struct AgentGuard {
51 initialized: AtomicBool,
52}
53
54impl AgentGuard {
55 #[deprecated(note = "agent-guard is a scaffold — no OS enforcement is implemented")]
63 #[cfg(target_os = "linux")]
64 pub fn new() -> Self {
65 Self {
66 initialized: AtomicBool::new(false),
67 }
68 }
69
70 #[deprecated(note = "agent-guard is a scaffold — no OS enforcement is implemented")]
72 #[cfg(not(target_os = "linux"))]
73 pub fn new() -> Self {
74 Self {
75 initialized: AtomicBool::new(false),
76 }
77 }
78
79 #[deprecated(note = "agent-guard is a scaffold — no OS enforcement is implemented")]
90 pub fn initialize(&mut self) -> Result<()> {
91 #[cfg(target_os = "linux")]
92 {
93 self.initialized.store(true, Ordering::SeqCst);
96 Ok(())
97 }
98
99 #[cfg(not(target_os = "linux"))]
100 {
101 Err(Error::InvalidConfig(
102 "AgentGuard is only available on Linux".to_string(),
103 ))
104 }
105 }
106
107 pub fn is_initialized(&self) -> bool {
109 self.initialized.load(Ordering::SeqCst)
110 }
111
112 #[cfg(test)]
114 fn make_decision(&self, subject: &Subject, action: &Action) -> SecurityDecision {
115 let decision_id = format!("guard-{}-{}", subject.name, Utc::now().timestamp());
116 SecurityDecision {
117 decision_id,
118 subject: subject.clone(),
119 action: action.clone(),
120 allowed: true,
121 reason: "Allowed by AgentGuard control plane".to_string(),
122 timestamp: Utc::now(),
123 mechanisms: vec![],
124 }
125 }
126}
127
128impl Default for AgentGuard {
129 fn default() -> Self {
130 Self::new()
131 }
132}
133
134#[cfg(test)]
135mod tests {
136 use super::*;
137
138 #[test]
139 #[allow(deprecated)]
140 fn test_agent_guard_new() {
141 let guard = AgentGuard::new();
142 assert!(!guard.is_initialized());
143 }
144
145 #[test]
146 #[allow(deprecated)]
147 #[cfg(target_os = "linux")]
148 fn test_agent_guard_initialize() {
149 let mut guard = AgentGuard::new();
150 assert!(guard.initialize().is_ok());
151 assert!(guard.is_initialized());
152 }
153
154 #[test]
155 #[allow(deprecated)]
156 fn test_make_decision() {
157 let guard = AgentGuard::new();
158 let subject = Subject {
159 pid: Some(1234),
160 name: "test-agent".to_string(),
161 cgroup_path: None,
162 };
163 let action = Action {
164 action_type: ActionType::FileRead,
165 resource: "/etc/passwd".to_string(),
166 metadata: None,
167 };
168 let decision = guard.make_decision(&subject, &action);
169 assert!(decision.allowed);
170 assert_eq!(decision.subject.name, "test-agent");
171 }
172
173 #[test]
174 #[allow(deprecated)]
175 #[cfg(not(target_os = "linux"))]
176 fn test_agent_guard_not_available() {
177 let mut guard = AgentGuard::new();
178 let result = guard.initialize();
179 assert!(result.is_err());
180 }
181}