manta_server/server/audit/
auth.rs1use axum::http::StatusCode;
9
10use super::{
11 AuditLog,
12 event::{Actor, Client, EventKind, Outcome, Request, Verdict},
13};
14
15pub fn send_auth_audit(
17 audit: &AuditLog,
18 success: bool,
19 username: &str,
20 source_ip: &str,
21 site: &str,
22) {
23 let mut event = audit.event(EventKind::AuthAttempt, "auth.token".into());
24 event.actor = Actor {
25 username: Some(username.to_string()),
26 ..Actor::default()
27 };
28 event.client = Client {
29 ip: Some(source_ip.to_string()),
30 forwarded_for: None,
31 };
32 event.site = Some(site.to_string());
33 event.request = Request {
34 method: "POST".into(),
35 route: "/v2/auth/token".into(),
36 path: "/v2/auth/token".into(),
37 query: None,
38 };
39 let status = if success {
40 StatusCode::OK
41 } else {
42 StatusCode::UNAUTHORIZED
43 };
44 event.outcome = Outcome {
45 result: Verdict::from_status(status),
46 status: status.as_u16(),
47 duration_ms: 0,
48 };
49 audit.emit(event);
50}
51
52#[cfg(test)]
53mod tests {
54 use std::sync::Arc;
55
56 use super::*;
57 use crate::server::audit::CaptureSink;
58
59 #[test]
60 fn records_username_site_and_outcome() {
61 let sink = Arc::new(CaptureSink::default());
62 let log = AuditLog::with_sinks(vec![sink.clone()]);
63 send_auth_audit(&log, false, "alice", "10.0.0.1", "alps");
64 let events = sink.0.lock().unwrap();
65 let e = &events[0];
66 assert_eq!(e.kind, EventKind::AuthAttempt);
67 assert_eq!(e.actor.username.as_deref(), Some("alice"));
68 assert_eq!(e.client.ip.as_deref(), Some("10.0.0.1"));
69 assert_eq!(e.site.as_deref(), Some("alps"));
70 assert_eq!(e.outcome.result, Verdict::Denied);
71 }
72}