Incident

Struct Incident 

Source
pub struct Incident {
Show 17 fields pub id: String, pub title: String, pub description: String, pub status: IncidentStatus, pub severity: ThreatSeverity, pub category: ThreatCategory, pub created_at: DateTime<Utc>, pub updated_at: DateTime<Utc>, pub acknowledged_at: Option<DateTime<Utc>>, pub resolved_at: Option<DateTime<Utc>>, pub assigned_to: Option<String>, pub related_alerts: Vec<String>, pub affected_assets: Vec<String>, pub actions_taken: Vec<ActionResult>, pub notes: Vec<IncidentNote>, pub timeline: Vec<TimelineEntry>, pub metrics: IncidentMetrics,
}
Expand description

Security incident

Fields§

§id: String§title: String§description: String§status: IncidentStatus§severity: ThreatSeverity§category: ThreatCategory§created_at: DateTime<Utc>§updated_at: DateTime<Utc>§acknowledged_at: Option<DateTime<Utc>>§resolved_at: Option<DateTime<Utc>>§assigned_to: Option<String>§related_alerts: Vec<String>§affected_assets: Vec<String>§actions_taken: Vec<ActionResult>§notes: Vec<IncidentNote>§timeline: Vec<TimelineEntry>§metrics: IncidentMetrics

Implementations§

Source§

impl Incident

Source

pub fn from_alert(alert: &ThreatAlert) -> Self

Create new incident from alert

Source

pub fn update_status(&mut self, new_status: IncidentStatus, actor: &str)

Update incident status

Examples found in repository?
examples/incident_response.rs (line 74)
14fn main() {
15    println!("=== Automated Incident Response Demo v2.0 ===\n");
16
17    let mut manager = IncidentResponseManager::new();
18
19    // Example 1: Create incident from alert
20    println!("--- Example 1: Create Incident from Alert ---");
21    let alert = ThreatAlert {
22        alert_id: "ALERT-001".to_string(),
23        timestamp: Utc::now(),
24        severity: ThreatSeverity::High,
25        category: ThreatCategory::BruteForce,
26        description: "Multiple failed login attempts detected from external IP".to_string(),
27        source_log: "auth.log - 500 failed attempts in 10 minutes".to_string(),
28        indicators: vec!["203.0.113.50".to_string(), "admin".to_string()],
29        recommended_action: "Block source IP and review user account".to_string(),
30        threat_score: 85,
31        correlated_alerts: vec![],
32    };
33
34    let incident_id = manager.create_incident(&alert);
35    println!("Created incident: {}", incident_id);
36
37    // Get and display incident details
38    if let Some(incident) = manager.get_incident(&incident_id) {
39        println!("  Title: {}", incident.title);
40        println!("  Status: {:?}", incident.status);
41        println!("  Severity: {:?}", incident.severity);
42        println!("  Category: {:?}", incident.category);
43    }
44
45    // Example 2: Find and execute playbooks
46    println!("\n--- Example 2: Execute Response Playbook ---");
47    let playbook = {
48        manager.find_playbooks(&alert).first().map(|&p| p.clone())
49    };
50
51    if let Some(playbook) = playbook {
52        println!("Found applicable playbook: {}", playbook.name);
53        println!("  Actions to execute: {}", playbook.actions.len());
54
55        let mut context = HashMap::new();
56        context.insert("source_ip".to_string(), "203.0.113.50".to_string());
57        context.insert("username".to_string(), "admin".to_string());
58
59        let results = manager.execute_playbook(&incident_id, &playbook, &context);
60        println!("  Executed {} actions:", results.len());
61        for result in &results {
62            println!("    - {}: {} ({}ms)",
63                result.action.name(),
64                if result.success { "Success" } else { "Failed" },
65                result.execution_time_ms
66            );
67        }
68    }
69
70    // Example 3: Incident lifecycle
71    println!("\n--- Example 3: Incident Lifecycle ---");
72    if let Some(incident) = manager.get_incident_mut(&incident_id) {
73        // Acknowledge the incident
74        incident.update_status(IncidentStatus::Acknowledged, "analyst1");
75        println!("Status updated to: {:?}", incident.status);
76
77        // Add investigation note
78        incident.add_note("analyst1", "Initial triage complete. IP belongs to known malicious range.");
79        println!("Added investigation note");
80
81        // Update to investigating
82        incident.update_status(IncidentStatus::Investigating, "analyst1");
83        println!("Status updated to: {:?}", incident.status);
84
85        // Update to containing
86        incident.update_status(IncidentStatus::Containing, "analyst1");
87        println!("Status updated to: {:?}", incident.status);
88
89        // Show timeline
90        println!("\nIncident Timeline:");
91        for entry in &incident.timeline {
92            println!("  [{}] {} by {}: {}",
93                entry.timestamp.format("%H:%M:%S"),
94                entry.event_type,
95                entry.actor,
96                entry.description
97            );
98        }
99
100        // Show metrics
101        println!("\nIncident Metrics:");
102        println!("  Time to Acknowledge: {:?} seconds", incident.metrics.time_to_acknowledge_seconds);
103        println!("  Time to Contain: {:?} seconds", incident.metrics.time_to_contain_seconds);
104        println!("  Total Actions: {}", incident.metrics.total_actions);
105        println!("  Successful Actions: {}", incident.metrics.successful_actions);
106    }
107
108    // Example 4: Create multiple incidents for statistics
109    println!("\n--- Example 4: Incident Statistics ---");
110
111    // Create a few more incidents
112    for i in 2..=5 {
113        let test_alert = ThreatAlert {
114            alert_id: format!("ALERT-{:03}", i),
115            timestamp: Utc::now(),
116            severity: if i % 2 == 0 { ThreatSeverity::High } else { ThreatSeverity::Medium },
117            category: if i % 3 == 0 { ThreatCategory::MalwareDetection } else { ThreatCategory::BruteForce },
118            description: format!("Test alert {}", i),
119            source_log: "test.log".to_string(),
120            indicators: vec![],
121            recommended_action: "Investigate".to_string(),
122            threat_score: 60 + i * 5,
123            correlated_alerts: vec![],
124        };
125        manager.create_incident(&test_alert);
126    }
127
128    let stats = manager.get_statistics();
129    println!("Incident Statistics:");
130    println!("  Total Incidents: {}", stats.total_incidents);
131    println!("  Active Incidents: {}", stats.active_incidents);
132    println!("  Resolved Incidents: {}", stats.resolved_incidents);
133    println!("  By Severity:");
134    for (severity, count) in &stats.by_severity {
135        println!("    {:?}: {}", severity, count);
136    }
137    println!("  By Category:");
138    for (category, count) in &stats.by_category {
139        println!("    {:?}: {}", category, count);
140    }
141
142    // Example 5: List available playbooks
143    println!("\n--- Example 5: Available Playbooks ---");
144    let playbooks = manager.get_playbooks();
145    println!("Available playbooks: {}", playbooks.len());
146    for pb in playbooks {
147        println!("\n  {} ({})", pb.name, pb.id);
148        println!("    Description: {}", pb.description);
149        println!("    Categories: {:?}", pb.threat_categories);
150        println!("    Min Severity: {:?}", pb.min_severity);
151        println!("    Requires Approval: {}", pb.requires_approval);
152        println!("    Actions: {}", pb.actions.len());
153    }
154
155    // Example 6: Query active and high-severity incidents
156    println!("\n--- Example 6: Query Incidents ---");
157
158    let active = manager.get_active_incidents();
159    println!("Active incidents: {}", active.len());
160
161    let high_severity = manager.get_incidents_by_severity(ThreatSeverity::High);
162    println!("High severity or above: {}", high_severity.len());
163
164    // Example 7: Custom response action
165    println!("\n--- Example 7: Response Action Types ---");
166    let actions = vec![
167        ResponseAction::BlockIP { ip: "1.2.3.4".to_string(), duration_hours: 24 },
168        ResponseAction::DisableAccount { account: "compromised_user".to_string() },
169        ResponseAction::IsolateHost { hostname: "infected-host".to_string() },
170        ResponseAction::NotifyTeam { team: "SOC".to_string(), message: "Critical incident".to_string() },
171        ResponseAction::EscalateToSOC { priority: "P1".to_string() },
172    ];
173
174    println!("Available response actions:");
175    for action in &actions {
176        println!("  - {} (reversible: {})", action.name(), action.is_reversible());
177    }
178
179    println!("\n=== Demo Complete ===");
180}
Source

pub fn add_action_result(&mut self, result: ActionResult)

Add action result

Source

pub fn add_note(&mut self, author: &str, content: &str)

Add note to incident

Examples found in repository?
examples/incident_response.rs (line 78)
14fn main() {
15    println!("=== Automated Incident Response Demo v2.0 ===\n");
16
17    let mut manager = IncidentResponseManager::new();
18
19    // Example 1: Create incident from alert
20    println!("--- Example 1: Create Incident from Alert ---");
21    let alert = ThreatAlert {
22        alert_id: "ALERT-001".to_string(),
23        timestamp: Utc::now(),
24        severity: ThreatSeverity::High,
25        category: ThreatCategory::BruteForce,
26        description: "Multiple failed login attempts detected from external IP".to_string(),
27        source_log: "auth.log - 500 failed attempts in 10 minutes".to_string(),
28        indicators: vec!["203.0.113.50".to_string(), "admin".to_string()],
29        recommended_action: "Block source IP and review user account".to_string(),
30        threat_score: 85,
31        correlated_alerts: vec![],
32    };
33
34    let incident_id = manager.create_incident(&alert);
35    println!("Created incident: {}", incident_id);
36
37    // Get and display incident details
38    if let Some(incident) = manager.get_incident(&incident_id) {
39        println!("  Title: {}", incident.title);
40        println!("  Status: {:?}", incident.status);
41        println!("  Severity: {:?}", incident.severity);
42        println!("  Category: {:?}", incident.category);
43    }
44
45    // Example 2: Find and execute playbooks
46    println!("\n--- Example 2: Execute Response Playbook ---");
47    let playbook = {
48        manager.find_playbooks(&alert).first().map(|&p| p.clone())
49    };
50
51    if let Some(playbook) = playbook {
52        println!("Found applicable playbook: {}", playbook.name);
53        println!("  Actions to execute: {}", playbook.actions.len());
54
55        let mut context = HashMap::new();
56        context.insert("source_ip".to_string(), "203.0.113.50".to_string());
57        context.insert("username".to_string(), "admin".to_string());
58
59        let results = manager.execute_playbook(&incident_id, &playbook, &context);
60        println!("  Executed {} actions:", results.len());
61        for result in &results {
62            println!("    - {}: {} ({}ms)",
63                result.action.name(),
64                if result.success { "Success" } else { "Failed" },
65                result.execution_time_ms
66            );
67        }
68    }
69
70    // Example 3: Incident lifecycle
71    println!("\n--- Example 3: Incident Lifecycle ---");
72    if let Some(incident) = manager.get_incident_mut(&incident_id) {
73        // Acknowledge the incident
74        incident.update_status(IncidentStatus::Acknowledged, "analyst1");
75        println!("Status updated to: {:?}", incident.status);
76
77        // Add investigation note
78        incident.add_note("analyst1", "Initial triage complete. IP belongs to known malicious range.");
79        println!("Added investigation note");
80
81        // Update to investigating
82        incident.update_status(IncidentStatus::Investigating, "analyst1");
83        println!("Status updated to: {:?}", incident.status);
84
85        // Update to containing
86        incident.update_status(IncidentStatus::Containing, "analyst1");
87        println!("Status updated to: {:?}", incident.status);
88
89        // Show timeline
90        println!("\nIncident Timeline:");
91        for entry in &incident.timeline {
92            println!("  [{}] {} by {}: {}",
93                entry.timestamp.format("%H:%M:%S"),
94                entry.event_type,
95                entry.actor,
96                entry.description
97            );
98        }
99
100        // Show metrics
101        println!("\nIncident Metrics:");
102        println!("  Time to Acknowledge: {:?} seconds", incident.metrics.time_to_acknowledge_seconds);
103        println!("  Time to Contain: {:?} seconds", incident.metrics.time_to_contain_seconds);
104        println!("  Total Actions: {}", incident.metrics.total_actions);
105        println!("  Successful Actions: {}", incident.metrics.successful_actions);
106    }
107
108    // Example 4: Create multiple incidents for statistics
109    println!("\n--- Example 4: Incident Statistics ---");
110
111    // Create a few more incidents
112    for i in 2..=5 {
113        let test_alert = ThreatAlert {
114            alert_id: format!("ALERT-{:03}", i),
115            timestamp: Utc::now(),
116            severity: if i % 2 == 0 { ThreatSeverity::High } else { ThreatSeverity::Medium },
117            category: if i % 3 == 0 { ThreatCategory::MalwareDetection } else { ThreatCategory::BruteForce },
118            description: format!("Test alert {}", i),
119            source_log: "test.log".to_string(),
120            indicators: vec![],
121            recommended_action: "Investigate".to_string(),
122            threat_score: 60 + i * 5,
123            correlated_alerts: vec![],
124        };
125        manager.create_incident(&test_alert);
126    }
127
128    let stats = manager.get_statistics();
129    println!("Incident Statistics:");
130    println!("  Total Incidents: {}", stats.total_incidents);
131    println!("  Active Incidents: {}", stats.active_incidents);
132    println!("  Resolved Incidents: {}", stats.resolved_incidents);
133    println!("  By Severity:");
134    for (severity, count) in &stats.by_severity {
135        println!("    {:?}: {}", severity, count);
136    }
137    println!("  By Category:");
138    for (category, count) in &stats.by_category {
139        println!("    {:?}: {}", category, count);
140    }
141
142    // Example 5: List available playbooks
143    println!("\n--- Example 5: Available Playbooks ---");
144    let playbooks = manager.get_playbooks();
145    println!("Available playbooks: {}", playbooks.len());
146    for pb in playbooks {
147        println!("\n  {} ({})", pb.name, pb.id);
148        println!("    Description: {}", pb.description);
149        println!("    Categories: {:?}", pb.threat_categories);
150        println!("    Min Severity: {:?}", pb.min_severity);
151        println!("    Requires Approval: {}", pb.requires_approval);
152        println!("    Actions: {}", pb.actions.len());
153    }
154
155    // Example 6: Query active and high-severity incidents
156    println!("\n--- Example 6: Query Incidents ---");
157
158    let active = manager.get_active_incidents();
159    println!("Active incidents: {}", active.len());
160
161    let high_severity = manager.get_incidents_by_severity(ThreatSeverity::High);
162    println!("High severity or above: {}", high_severity.len());
163
164    // Example 7: Custom response action
165    println!("\n--- Example 7: Response Action Types ---");
166    let actions = vec![
167        ResponseAction::BlockIP { ip: "1.2.3.4".to_string(), duration_hours: 24 },
168        ResponseAction::DisableAccount { account: "compromised_user".to_string() },
169        ResponseAction::IsolateHost { hostname: "infected-host".to_string() },
170        ResponseAction::NotifyTeam { team: "SOC".to_string(), message: "Critical incident".to_string() },
171        ResponseAction::EscalateToSOC { priority: "P1".to_string() },
172    ];
173
174    println!("Available response actions:");
175    for action in &actions {
176        println!("  - {} (reversible: {})", action.name(), action.is_reversible());
177    }
178
179    println!("\n=== Demo Complete ===");
180}
Source

pub fn duration(&self) -> Duration

Calculate incident duration

Source

pub fn is_overdue(&self, sla_hours: i64) -> bool

Check if incident is overdue

Trait Implementations§

Source§

impl Clone for Incident

Source§

fn clone(&self) -> Incident

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Incident

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for Incident

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Serialize for Incident

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,