1 use std::{fmt, path::PathBuf};
2 
3 use bytes::Bytes;
4 use rpki::repository::x509::Time;
5 
6 use crate::commons::{
7     api::{Handle, PublisherHandle},
8     error::KrillIoError,
9     util::file,
10 };
11 
12 /// This type helps to log CMS (RFC8181 and RFC6492) protocol messages
13 /// for auditing purposes.
14 pub struct CmsLogger {
15     path: Option<PathBuf>,
16     now: i64,
17 }
18 
19 impl CmsLogger {
new(path: Option<PathBuf>) -> Self20     fn new(path: Option<PathBuf>) -> Self {
21         CmsLogger {
22             path,
23             now: Time::now().timestamp_millis(),
24         }
25     }
26 
for_rfc6492_rcvd(log_dir: Option<&PathBuf>, ca: &Handle, sender: &Handle) -> Self27     pub fn for_rfc6492_rcvd(log_dir: Option<&PathBuf>, ca: &Handle, sender: &Handle) -> Self {
28         let path = log_dir.map(|dir| {
29             let mut path = dir.clone();
30             path.push(ca.as_str());
31             path.push("rcvd");
32             path.push(sender.as_str());
33             path
34         });
35 
36         Self::new(path)
37     }
38 
for_rfc6492_sent(log_dir: Option<&PathBuf>, ca: &Handle, recipient: &Handle) -> Self39     pub fn for_rfc6492_sent(log_dir: Option<&PathBuf>, ca: &Handle, recipient: &Handle) -> Self {
40         let path = log_dir.map(|dir| {
41             let mut path = dir.clone();
42             path.push(ca.as_str());
43             path.push("sent");
44             path.push(recipient.as_str());
45             path
46         });
47 
48         Self::new(path)
49     }
50 
for_rfc8181_sent(log_dir: Option<&PathBuf>, ca: &Handle) -> Self51     pub fn for_rfc8181_sent(log_dir: Option<&PathBuf>, ca: &Handle) -> Self {
52         let path = log_dir.map(|dir| {
53             let mut path = dir.clone();
54             path.push(ca.as_str());
55             path.push("sent");
56             path
57         });
58 
59         Self::new(path)
60     }
61 
for_rfc8181_rcvd(log_dir: Option<&PathBuf>, publisher: &PublisherHandle) -> Self62     pub fn for_rfc8181_rcvd(log_dir: Option<&PathBuf>, publisher: &PublisherHandle) -> Self {
63         let path = log_dir.map(|dir| {
64             let mut path = dir.clone();
65             path.push(publisher.as_str());
66             path.push("rcvd");
67             path
68         });
69 
70         Self::new(path)
71     }
72 
received(&self, msg: &Bytes) -> Result<(), KrillIoError>73     pub fn received(&self, msg: &Bytes) -> Result<(), KrillIoError> {
74         self.save(msg, "rcvd")
75     }
76 
reply(&self, msg: &Bytes) -> Result<(), KrillIoError>77     pub fn reply(&self, msg: &Bytes) -> Result<(), KrillIoError> {
78         self.save(msg, "repl")
79     }
80 
sent(&self, msg: &Bytes) -> Result<(), KrillIoError>81     pub fn sent(&self, msg: &Bytes) -> Result<(), KrillIoError> {
82         self.save(msg, "sent")
83     }
84 
err(&self, msg: impl fmt::Display) -> Result<(), KrillIoError>85     pub fn err(&self, msg: impl fmt::Display) -> Result<(), KrillIoError> {
86         self.save(msg.to_string().as_bytes(), "err")
87     }
88 
save(&self, content: &[u8], ext: &str) -> Result<(), KrillIoError>89     fn save(&self, content: &[u8], ext: &str) -> Result<(), KrillIoError> {
90         if let Some(path) = self.path.as_ref() {
91             let mut path = path.clone();
92             path.push(&format!("{}.{}", self.now, ext));
93 
94             file::save(content, &path)
95         } else {
96             Ok(())
97         }
98     }
99 }
100