mofa_foundation/secretary/monitoring/
plugins.rs1use super::event::{Event, EventType};
7use super::plugin::{BaseEventResponsePlugin, EventResponseConfig, EventResponsePlugin};
8use async_trait::async_trait;
9use mofa_kernel::plugin::{PluginPriority, PluginResult};
10use std::collections::HashMap;
11use std::sync::RwLock;
12
13pub struct ServerFaultResponsePlugin {
23 base: BaseEventResponsePlugin,
24 config: RwLock<EventResponseConfig>,
25}
26
27impl ServerFaultResponsePlugin {
28 pub fn new() -> Self {
30 let handled_event_types = vec![EventType::ServerFault];
31 let workflow_steps = vec![
32 "attempt_auto_restart".to_string(),
33 "notify_administrator".to_string(),
34 ];
35
36 let base = BaseEventResponsePlugin::new(
37 "server-fault-responder",
38 "Server Fault Responder",
39 handled_event_types.clone(), workflow_steps,
41 )
42 .with_priority(PluginPriority::High) .with_max_impact_scope("instance");
44
45 let config = RwLock::new(EventResponseConfig {
46 handled_event_types,
47 priority: PluginPriority::High,
48 ..Default::default()
49 });
50
51 Self { base, config }
52 }
53
54 async fn attempt_auto_restart(&self, server: &str) -> Result<bool, String> {
56 println!("Attempting to restart server: {}", server);
58 Ok(true)
62 }
63
64 async fn notify_administrator(&self, event: &Event) -> Result<(), String> {
66 println!("Notifying administrator about server fault:");
68 println!(" Event ID: {}", event.id);
69 println!(" Source: {}", event.source);
70 println!(" Description: {}", event.description);
71
72 Ok(())
73 }
74}
75
76#[async_trait]
77impl EventResponsePlugin for ServerFaultResponsePlugin {
78 fn config(&self) -> &EventResponseConfig {
79 panic!("config() should not be called directly on this plugin");
80 }
81
82 async fn update_config(&mut self, config: EventResponseConfig) -> PluginResult<()> {
83 {
85 let mut current_config = self.config.write().unwrap();
86 *current_config = config.clone();
87 }
88 self.base.update_config(config).await
90 }
91
92 fn can_handle(&self, event: &Event) -> bool {
93 self.base.can_handle(event)
94 }
95
96 async fn handle_event(&mut self, event: Event) -> PluginResult<Event> {
97 self.base.handle_event(event).await
98 }
99
100 async fn execute_workflow(&self, event: &Event) -> PluginResult<HashMap<String, String>> {
101 let mut result = HashMap::new();
102
103 let server_name = event
105 .data
106 .get("server")
107 .and_then(|s| s.as_str())
108 .unwrap_or("unknown");
109
110 let restart_result = self.attempt_auto_restart(server_name).await;
111
112 match restart_result {
113 Ok(success) => {
114 result.insert(
115 "auto_restart".to_string(),
116 if success {
117 "success".to_string()
118 } else {
119 "failed".to_string()
120 },
121 );
122 }
123 Err(err) => {
124 result.insert("auto_restart".to_string(), format!("error: {}", err));
125 }
126 }
127
128 match self.notify_administrator(event).await {
130 Ok(_) => {
131 result.insert("notify_admin".to_string(), "success".to_string());
132 }
133 Err(err) => {
134 result.insert("notify_admin".to_string(), format!("error: {}", err));
135 }
136 }
137
138 result.insert(
140 "workflow_status".to_string(),
141 "server_fault_workflow_completed".to_string(),
142 );
143
144 Ok(result)
145 }
146}
147
148#[async_trait]
149impl mofa_kernel::plugin::AgentPlugin for ServerFaultResponsePlugin {
150 fn metadata(&self) -> &mofa_kernel::plugin::PluginMetadata {
151 self.base.metadata()
152 }
153
154 fn state(&self) -> mofa_kernel::plugin::PluginState {
155 self.base.state()
156 }
157
158 async fn load(
159 &mut self,
160 ctx: &mofa_kernel::plugin::PluginContext,
161 ) -> mofa_kernel::plugin::PluginResult<()> {
162 self.base.load(ctx).await
163 }
164
165 async fn init_plugin(&mut self) -> mofa_kernel::plugin::PluginResult<()> {
166 self.base.init_plugin().await
167 }
168
169 async fn start(&mut self) -> mofa_kernel::plugin::PluginResult<()> {
170 self.base.start().await
171 }
172
173 async fn stop(&mut self) -> mofa_kernel::plugin::PluginResult<()> {
174 self.base.stop().await
175 }
176
177 async fn unload(&mut self) -> mofa_kernel::plugin::PluginResult<()> {
178 self.base.unload().await
179 }
180
181 async fn execute(&mut self, input: String) -> mofa_kernel::plugin::PluginResult<String> {
182 self.base.execute(input).await
183 }
184
185 fn as_any(&self) -> &dyn std::any::Any {
186 self
187 }
188
189 fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
190 self
191 }
192
193 fn into_any(self: Box<Self>) -> Box<dyn std::any::Any> {
194 self
195 }
196}
197
198impl From<ServerFaultResponsePlugin> for Box<dyn EventResponsePlugin> {
199 fn from(plugin: ServerFaultResponsePlugin) -> Self {
200 Box::new(plugin)
201 }
202}
203
204impl From<ServerFaultResponsePlugin> for Box<dyn mofa_kernel::plugin::AgentPlugin> {
205 fn from(plugin: ServerFaultResponsePlugin) -> Self {
206 Box::new(plugin)
207 }
208}
209
210pub struct NetworkAttackResponsePlugin {
221 base: BaseEventResponsePlugin,
222 config: RwLock<EventResponseConfig>,
223}
224
225impl NetworkAttackResponsePlugin {
226 pub fn new() -> Self {
228 let handled_event_types = vec![EventType::NetworkAttack];
229 let workflow_steps = vec![
230 "block_attacking_ip".to_string(),
231 "analyze_attack_pattern".to_string(),
232 "notify_security_team".to_string(),
233 ];
234
235 let base = BaseEventResponsePlugin::new(
236 "network-attack-responder",
237 "Network Attack Responder",
238 handled_event_types.clone(), workflow_steps,
240 )
241 .with_priority(PluginPriority::Critical) .with_max_impact_scope("system");
243
244 let config = RwLock::new(EventResponseConfig {
245 handled_event_types,
246 priority: PluginPriority::Critical,
247 ..Default::default()
248 });
249
250 Self { base, config }
251 }
252
253 async fn block_attacking_ip(&self, ip: &str) -> Result<bool, String> {
255 println!("Blocking attacking IP: {}", ip);
257 Ok(true)
260 }
261
262 async fn analyze_attack_pattern(&self, event: &Event) -> Result<String, String> {
264 println!("Analyzing attack pattern for event: {}", event.id);
266
267 Ok("ddos_attack".to_string()) }
269
270 async fn notify_security_team(&self, event: &Event, attack_type: &str) -> Result<(), String> {
272 println!("Notifying security team about {} attack:", attack_type);
274 println!(" Event ID: {}", event.id);
275 println!(" Source IP: {:?}", event.data.get("source_ip"));
276
277 Ok(())
278 }
279}
280
281#[async_trait]
282impl EventResponsePlugin for NetworkAttackResponsePlugin {
283 fn config(&self) -> &EventResponseConfig {
284 panic!("config() should not be called directly on this plugin");
285 }
286
287 async fn update_config(&mut self, config: EventResponseConfig) -> PluginResult<()> {
288 {
290 let mut current_config = self.config.write().unwrap();
291 *current_config = config.clone();
292 }
293 self.base.update_config(config).await
295 }
296
297 fn can_handle(&self, event: &Event) -> bool {
298 self.base.can_handle(event)
299 }
300
301 async fn handle_event(&mut self, event: Event) -> PluginResult<Event> {
302 self.base.handle_event(event).await
303 }
304
305 async fn execute_workflow(&self, event: &Event) -> PluginResult<HashMap<String, String>> {
306 let mut result = HashMap::new();
307
308 let source_ip = event
310 .data
311 .get("source_ip")
312 .and_then(|ip| ip.as_str())
313 .unwrap_or("unknown");
314
315 let block_result = self.block_attacking_ip(source_ip).await;
316 match block_result {
317 Ok(success) => {
318 result.insert(
319 "block_ip".to_string(),
320 if success {
321 "success".to_string()
322 } else {
323 "failed".to_string()
324 },
325 );
326 }
327 Err(err) => {
328 result.insert("block_ip".to_string(), format!("error: {}", err));
329 }
330 }
331
332 let analysis_result = self.analyze_attack_pattern(event).await;
334 let attack_type = match analysis_result {
335 Ok(attack) => {
336 result.insert("attack_analysis".to_string(), attack.clone());
337 attack
338 }
339 Err(err) => {
340 result.insert("attack_analysis".to_string(), format!("error: {}", err));
341 "unknown".to_string()
342 }
343 };
344
345 if let Err(err) = self.notify_security_team(event, &attack_type).await {
347 result.insert("notify_security".to_string(), format!("error: {}", err));
348 } else {
349 result.insert("notify_security".to_string(), "success".to_string());
350 }
351
352 result.insert(
354 "workflow_status".to_string(),
355 "network_attack_workflow_completed".to_string(),
356 );
357
358 Ok(result)
359 }
360}
361
362#[async_trait]
363impl mofa_kernel::plugin::AgentPlugin for NetworkAttackResponsePlugin {
364 fn metadata(&self) -> &mofa_kernel::plugin::PluginMetadata {
365 self.base.metadata()
366 }
367
368 fn state(&self) -> mofa_kernel::plugin::PluginState {
369 self.base.state()
370 }
371
372 async fn load(
373 &mut self,
374 ctx: &mofa_kernel::plugin::PluginContext,
375 ) -> mofa_kernel::plugin::PluginResult<()> {
376 self.base.load(ctx).await
377 }
378
379 async fn init_plugin(&mut self) -> mofa_kernel::plugin::PluginResult<()> {
380 self.base.init_plugin().await
381 }
382
383 async fn start(&mut self) -> mofa_kernel::plugin::PluginResult<()> {
384 self.base.start().await
385 }
386
387 async fn stop(&mut self) -> mofa_kernel::plugin::PluginResult<()> {
388 self.base.stop().await
389 }
390
391 async fn unload(&mut self) -> mofa_kernel::plugin::PluginResult<()> {
392 self.base.unload().await
393 }
394
395 async fn execute(&mut self, input: String) -> mofa_kernel::plugin::PluginResult<String> {
396 self.base.execute(input).await
397 }
398
399 fn as_any(&self) -> &dyn std::any::Any {
400 self
401 }
402
403 fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
404 self
405 }
406
407 fn into_any(self: Box<Self>) -> Box<dyn std::any::Any> {
408 self
409 }
410}
411
412impl From<NetworkAttackResponsePlugin> for Box<dyn EventResponsePlugin> {
413 fn from(plugin: NetworkAttackResponsePlugin) -> Self {
414 Box::new(plugin)
415 }
416}
417
418impl From<NetworkAttackResponsePlugin> for Box<dyn mofa_kernel::plugin::AgentPlugin> {
419 fn from(plugin: NetworkAttackResponsePlugin) -> Self {
420 Box::new(plugin)
421 }
422}