postfix_log_parser/events/
proxymap.rs

1//! Proxymap代理映射服务模块
2//!
3//! 处理Postfix proxymap守护进程的事件,负责映射表的代理访问和配置管理
4
5use serde::{Deserialize, Serialize};
6use std::fmt;
7
8/// Proxymap代理映射服务事件
9///
10/// 记录Postfix proxymap服务的配置警告和映射操作
11#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
12pub struct ProxymapEvent {
13    /// 事件发生时间戳(原始字符串格式)
14    /// 保持原始时间格式,如"Apr 08 17:54:42"
15    pub timestamp: String,
16
17    /// 进程ID(字符串格式)
18    /// proxymap服务进程的标识符
19    pub process_id: String,
20
21    /// 事件类型(通常为配置覆盖警告)
22    pub event_type: ProxymapEventType,
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
26pub enum ProxymapEventType {
27    /// Configuration override warning
28    ConfigOverrideWarning {
29        file_path: String,
30        line_number: u32,
31        parameter: String,
32        value: String,
33    },
34}
35
36impl fmt::Display for ProxymapEvent {
37    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38        write!(
39            f,
40            "[{}] proxymap[{}]: {}",
41            self.timestamp, self.process_id, self.event_type
42        )
43    }
44}
45
46impl fmt::Display for ProxymapEventType {
47    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48        match self {
49            ProxymapEventType::ConfigOverrideWarning {
50                file_path,
51                line_number,
52                parameter,
53                value,
54            } => {
55                write!(
56                    f,
57                    "Config override warning: {}, line {}: overriding earlier entry: {}={}",
58                    file_path, line_number, parameter, value
59                )
60            }
61        }
62    }
63}
64
65#[cfg(test)]
66mod tests {
67    use super::*;
68
69    #[test]
70    fn test_config_override_warning_event() {
71        let event = ProxymapEvent {
72            timestamp: "Apr 08 17:54:42".to_string(),
73            process_id: "80".to_string(),
74            event_type: ProxymapEventType::ConfigOverrideWarning {
75                file_path: "/etc/postfix/main.cf".to_string(),
76                line_number: 820,
77                parameter: "smtpd_recipient_restrictions".to_string(),
78                value: "check_client_access pcre:/etc/postfix/filter_trusted".to_string(),
79            },
80        };
81
82        assert_eq!(event.process_id, "80");
83
84        let ProxymapEventType::ConfigOverrideWarning {
85            file_path,
86            line_number,
87            parameter,
88            ..
89        } = &event.event_type;
90
91        assert_eq!(file_path, "/etc/postfix/main.cf");
92        assert_eq!(*line_number, 820);
93        assert_eq!(parameter, "smtpd_recipient_restrictions");
94    }
95
96    #[test]
97    fn test_event_serialization() {
98        let event = ProxymapEvent {
99            timestamp: "Apr 10 11:17:43".to_string(),
100            process_id: "80".to_string(),
101            event_type: ProxymapEventType::ConfigOverrideWarning {
102                file_path: "/etc/postfix/main.cf".to_string(),
103                line_number: 806,
104                parameter: "smtpd_client_message_rate_limit".to_string(),
105                value: "0".to_string(),
106            },
107        };
108
109        let serialized = serde_json::to_string(&event).unwrap();
110        let deserialized: ProxymapEvent = serde_json::from_str(&serialized).unwrap();
111        assert_eq!(event, deserialized);
112    }
113
114    #[test]
115    fn test_event_display() {
116        let event = ProxymapEvent {
117            timestamp: "Apr 10 11:17:43".to_string(),
118            process_id: "80".to_string(),
119            event_type: ProxymapEventType::ConfigOverrideWarning {
120                file_path: "/etc/postfix/main.cf".to_string(),
121                line_number: 826,
122                parameter: "smtpd_discard_ehlo_keywords".to_string(),
123                value: "silent-discard,dsn,etrn".to_string(),
124            },
125        };
126
127        let display = format!("{}", event);
128        assert!(display.contains("proxymap[80]"));
129        assert!(display.contains("Config override warning"));
130        assert!(display.contains("main.cf"));
131        assert!(display.contains("line 826"));
132    }
133
134    #[test]
135    fn test_complex_parameter_value() {
136        let event = ProxymapEvent {
137            timestamp: "Apr 08 17:54:42".to_string(),
138            process_id: "80".to_string(),
139            event_type: ProxymapEventType::ConfigOverrideWarning {
140                file_path: "/etc/postfix/main.cf".to_string(),
141                line_number: 820,
142                parameter: "smtpd_recipient_restrictions".to_string(),
143                value: "check_client_access pcre:/etc/postfix/filter_trusted, permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination, pcre:/etc/postfix/filter_default".to_string(),
144            },
145        };
146
147        let ProxymapEventType::ConfigOverrideWarning { value, .. } = &event.event_type;
148        assert!(value.contains("check_client_access"));
149        assert!(value.contains("permit_sasl_authenticated"));
150        assert!(value.contains("reject_unauth_destination"));
151    }
152
153    #[test]
154    fn test_different_parameters() {
155        let events = vec![
156            (
157                "smtpd_recipient_restrictions",
158                "check_client_access pcre:/etc/postfix/filter_trusted",
159            ),
160            ("smtpd_client_message_rate_limit", "0"),
161            ("smtpd_discard_ehlo_keywords", "silent-discard,dsn,etrn"),
162        ];
163
164        for (param, val) in events {
165            let event = ProxymapEvent {
166                timestamp: "Apr 10 11:17:43".to_string(),
167                process_id: "80".to_string(),
168                event_type: ProxymapEventType::ConfigOverrideWarning {
169                    file_path: "/etc/postfix/main.cf".to_string(),
170                    line_number: 806,
171                    parameter: param.to_string(),
172                    value: val.to_string(),
173                },
174            };
175
176            let ProxymapEventType::ConfigOverrideWarning {
177                parameter, value, ..
178            } = &event.event_type;
179
180            assert_eq!(parameter, param);
181            assert_eq!(value, val);
182        }
183    }
184
185    #[test]
186    fn test_event_equality() {
187        let event1 = ProxymapEvent {
188            timestamp: "Apr 08 17:54:42".to_string(),
189            process_id: "80".to_string(),
190            event_type: ProxymapEventType::ConfigOverrideWarning {
191                file_path: "/etc/postfix/main.cf".to_string(),
192                line_number: 820,
193                parameter: "smtpd_recipient_restrictions".to_string(),
194                value: "check_client_access pcre:/etc/postfix/filter_trusted".to_string(),
195            },
196        };
197
198        let event2 = ProxymapEvent {
199            timestamp: "Apr 08 17:54:42".to_string(),
200            process_id: "80".to_string(),
201            event_type: ProxymapEventType::ConfigOverrideWarning {
202                file_path: "/etc/postfix/main.cf".to_string(),
203                line_number: 820,
204                parameter: "smtpd_recipient_restrictions".to_string(),
205                value: "check_client_access pcre:/etc/postfix/filter_trusted".to_string(),
206            },
207        };
208
209        assert_eq!(event1, event2);
210    }
211}