sentinel_agent_protocol/
lib.rs1#![allow(dead_code)]
51
52mod client;
53mod errors;
54mod protocol;
55mod server;
56
57pub use errors::AgentProtocolError;
59
60pub use protocol::{
62 AgentRequest, AgentResponse, AuditMetadata, Decision, EventType, HeaderOp,
63 RequestBodyChunkEvent, RequestCompleteEvent, RequestHeadersEvent, RequestMetadata,
64 ResponseBodyChunkEvent, ResponseHeadersEvent, MAX_MESSAGE_SIZE, PROTOCOL_VERSION,
65};
66
67pub use client::AgentClient;
69
70pub use server::{AgentHandler, AgentServer, DenylistAgent, EchoAgent};
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76 use std::collections::HashMap;
77 use std::time::Duration;
78 use tempfile::tempdir;
79
80 #[tokio::test]
81 async fn test_agent_protocol_echo() {
82 let dir = tempdir().unwrap();
83 let socket_path = dir.path().join("test.sock");
84
85 let server = AgentServer::new("test-echo", socket_path.clone(), Box::new(EchoAgent));
87
88 let server_handle = tokio::spawn(async move {
89 server.run().await.unwrap();
90 });
91
92 tokio::time::sleep(Duration::from_millis(100)).await;
94
95 let mut client =
97 AgentClient::unix_socket("test-client", &socket_path, Duration::from_secs(5))
98 .await
99 .unwrap();
100
101 let event = RequestHeadersEvent {
103 metadata: RequestMetadata {
104 correlation_id: "test-123".to_string(),
105 request_id: "req-456".to_string(),
106 client_ip: "127.0.0.1".to_string(),
107 client_port: 12345,
108 server_name: Some("example.com".to_string()),
109 protocol: "HTTP/1.1".to_string(),
110 tls_version: None,
111 tls_cipher: None,
112 route_id: Some("default".to_string()),
113 upstream_id: Some("backend".to_string()),
114 timestamp: chrono::Utc::now().to_rfc3339(),
115 },
116 method: "GET".to_string(),
117 uri: "/test".to_string(),
118 headers: HashMap::new(),
119 };
120
121 let response = client
122 .send_event(EventType::RequestHeaders, &event)
123 .await
124 .unwrap();
125
126 assert_eq!(response.decision, Decision::Allow);
128 assert_eq!(response.request_headers.len(), 1);
129
130 client.close().await.unwrap();
132 server_handle.abort();
133 }
134
135 #[tokio::test]
136 async fn test_agent_protocol_denylist() {
137 let dir = tempdir().unwrap();
138 let socket_path = dir.path().join("denylist.sock");
139
140 let agent = DenylistAgent::new(vec!["/admin".to_string()], vec!["10.0.0.1".to_string()]);
142 let server = AgentServer::new("test-denylist", socket_path.clone(), Box::new(agent));
143
144 let server_handle = tokio::spawn(async move {
145 server.run().await.unwrap();
146 });
147
148 tokio::time::sleep(Duration::from_millis(100)).await;
150
151 let mut client =
153 AgentClient::unix_socket("test-client", &socket_path, Duration::from_secs(5))
154 .await
155 .unwrap();
156
157 let event = RequestHeadersEvent {
159 metadata: RequestMetadata {
160 correlation_id: "test-123".to_string(),
161 request_id: "req-456".to_string(),
162 client_ip: "127.0.0.1".to_string(),
163 client_port: 12345,
164 server_name: Some("example.com".to_string()),
165 protocol: "HTTP/1.1".to_string(),
166 tls_version: None,
167 tls_cipher: None,
168 route_id: Some("default".to_string()),
169 upstream_id: Some("backend".to_string()),
170 timestamp: chrono::Utc::now().to_rfc3339(),
171 },
172 method: "GET".to_string(),
173 uri: "/admin/secret".to_string(),
174 headers: HashMap::new(),
175 };
176
177 let response = client
178 .send_event(EventType::RequestHeaders, &event)
179 .await
180 .unwrap();
181
182 match response.decision {
184 Decision::Block { status, .. } => assert_eq!(status, 403),
185 _ => panic!("Expected block decision"),
186 }
187
188 client.close().await.unwrap();
190 server_handle.abort();
191 }
192}