sdl_parser/
training_learning_objective.rs1use std::collections::HashMap;
2
3use anyhow::{anyhow, Result};
4use serde::{Deserialize, Serialize};
5
6use crate::{evaluation::Evaluation, helpers::Connection};
7
8#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone)]
9pub struct TrainingLearningObjective {
10 #[serde(alias = "Name", alias = "NAME")]
11 pub name: Option<String>,
12 #[serde(alias = "Description", alias = "DESCRIPTION")]
13 pub description: Option<String>,
14 #[serde(alias = "Evaluation", alias = "EVALUATION")]
15 pub evaluation: String,
16}
17
18pub type TrainingLearningObjectives = HashMap<String, TrainingLearningObjective>;
19
20impl Connection<Evaluation> for (&String, &TrainingLearningObjective) {
21 fn validate_connections(&self, potential_evaluation_names: &Option<Vec<String>>) -> Result<()> {
22 if let Some(existing_evaluation_names) = potential_evaluation_names {
23 if !existing_evaluation_names.contains(&self.1.evaluation) {
24 return Err(anyhow!(
25 "TLO \"{tlo_name}\" Evaluation \"{evaluation_name}\" not found under Scenario Evaluations",
26 tlo_name = self.0,
27 evaluation_name =self.1.evaluation
28 ));
29 }
30 } else {
31 return Err(anyhow!(
32 "TLO \"{tlo_name}\" requires an Evaluation but none found under Scenario",
33 tlo_name = self.0
34 ));
35 }
36
37 Ok(())
38 }
39}
40
41#[cfg(test)]
42mod tests {
43 use super::*;
44 use crate::parse_sdl;
45
46 #[test]
47 fn parses_sdl_with_tlos() {
48 let sdl = r#"
49 name: test-scenario
50 description: some description
51 conditions:
52 condition-1:
53 command: executable/path.sh
54 interval: 30
55 metrics:
56 metric-1:
57 type: MANUAL
58 artifact: true
59 max-score: 10
60 metric-2:
61 type: CONDITIONAL
62 max-score: 10
63 condition: condition-1
64 vulnerabilities:
65 vulnerability-1:
66 name: Some other vulnerability
67 description: some-description
68 technical: false
69 class: CWE-1343
70 vulnerability-2:
71 name: Some vulnerability
72 description: some-description
73 technical: false
74 class: CWE-1341
75 evaluations:
76 evaluation-1:
77 description: some description
78 metrics:
79 - metric-1
80 - metric-2
81 min-score: 50
82 tlos:
83 tlo-1:
84 description: some description
85 evaluation: evaluation-1
86 "#;
87 let tlos = parse_sdl(sdl).unwrap().tlos;
88 insta::with_settings!({sort_maps => true}, {
89 insta::assert_yaml_snapshot!(tlos);
90 });
91 }
92
93 #[test]
94 fn parses_training_learning_objective() {
95 let tlo_string = r#"
96 name: test-training-learning-objective
97 description: some description
98 evaluation: evaluation-2
99 "#;
100 serde_yaml::from_str::<TrainingLearningObjective>(tlo_string).unwrap();
101 }
102}