Skip to content

Commit 80d6772

Browse files
authored
Tests 6.1.4 through 6.1.7 (#42)
* Update CSAF schema 2.1, add support for handling notes Introduced `NoteTrait` and `WithGroupIds` traits, extending functionality to handle notes and group IDs across CSAF structures. Updated relevant getter implementations for compatibility with these enhancements. * Add validation for undefined product_group_id in CSAF documents This adds a new validation function, `test_6_1_04_missing_definition_of_product_group_id`, to ensure all product group IDs used in notes, vulnerabilities, remediations, threats, and flags are defined in the product tree. * Add validation for duplicate product group IDs (test_6_1_05) Introduce a new validation to detect multiple definitions of the same product group ID in CSAF documents. This ensures data integrity by identifying conflicts within the `product_tree` structure. Includes corresponding unit tests for CSAF 2.0 and 2.1 versions. * Add validation for conflicting remediation, minor cleanup Extended the test to include a case where a product listed as fixed has a conflicting remediation category of "no_fix_planned". Ensures better coverage and accuracy in remediation validation logic. * Update RFC3339 regex to disallow leap seconds Revised the date-time validation regex to exclude leap seconds, ensuring stricter compliance with RFC3339. Updated test cases and error messages to reflect the change and improve clarity for non-compliant date-time issues. * Add validation for conflicting product status groups. This commit introduces `test_6_1_06_contradicting_product_status` to verify that no product has contradictory status groups (e.g., affected vs. not affected). Includes error handling, tests, and updates to the module index. * Add support for accessing CVSS, EPSS, and content paths in traits Expanded `ContentTrait` and related implementations to include methods for accessing CVSS v2/v3/v4, EPSS, and JSON content paths. Updated CSAF 2.0 and 2.1 schema integrations with new fields and improved consistency in metrics handling. * Add validation for duplicate vulnerability metrics check Introduced a new validation test (test_6_1_07) to ensure no product is assigned the same type of vulnerability metric multiple times. This includes support for various metrics like CVSS and EPSS, with detailed error handling and unit tests for CSAF 2.1 compliance. * Add support for CSAF 2.0 tests in test_6_1_07 validation. This update introduces `run_csaf20_tests` to validate CSAF 2.0 cases alongside CSAF 2.1. Common path prefixes are refactored for clarity and reuse, ensuring consistent test implementation across versions. * Update CSAF schema enforcing stricter validation rules Replaced JSON schema reference and file name for CSAF v2.1. Introduced `additionalProperties: false` across the schema to ensure no extraneous fields are allowed. Added new fields such as `first_known_exploitation_dates`, `license_expression`, and others. Updated deserialization logic with `deny_unknown_fields` to improve validation rigor. * Add `get_source` method to traits and fixed validation 6.1.7 Introduced the `get_source` method in relevant traits and implementations to access the source of vulnerability metrics. Enhanced the duplicate metric validation logic to account for sources, updating error messages to reflect source details.
1 parent d00216e commit 80d6772

File tree

16 files changed

+2326
-249
lines changed

16 files changed

+2326
-249
lines changed

csaf

Submodule csaf updated 812 files

csaf-lib/build.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ fn main() -> Result<(), BuildError> {
2929
false,
3030
)?;
3131
build(
32-
"./src/csaf/csaf2_1/csaf_json_schema.json",
32+
"./src/csaf/csaf2_1/csaf.json",
3333
"csaf/csaf2_1/schema.rs",
3434
true,
3535
)?;

csaf-lib/src/csaf/csaf2_0/getter_implementations.rs

Lines changed: 94 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
1-
use crate::csaf::csaf2_0::schema::{Branch, CategoryOfTheRemediation, CommonSecurityAdvisoryFramework, DocumentGenerator, DocumentLevelMetaData, DocumentStatus, Flag, FullProductNameT, HelperToIdentifyTheProduct, Id, Involvement, LabelOfTlp, ProductGroup, ProductStatus, ProductTree, Relationship, Remediation, Revision, RulesForSharingDocument, Threat, Tracking, TrafficLightProtocolTlp, Vulnerability};
2-
use crate::csaf::csaf2_1::schema::{CategoryOfTheRemediation as Remediation21, DocumentStatus as Status21, LabelOfTlp as Tlp21};
3-
use crate::csaf::getter_traits::{BranchTrait, CsafTrait, DistributionTrait, DocumentTrait, FlagTrait, ProductTrait, GeneratorTrait, InvolvementTrait, MetricTrait, ProductGroupTrait, ProductIdentificationHelperTrait, ProductStatusTrait, ProductTreeTrait, RelationshipTrait, RemediationTrait, RevisionTrait, SharingGroupTrait, ThreatTrait, TlpTrait, TrackingTrait, VulnerabilityTrait, ContentTrait, VulnerabilityIdTrait};
1+
use crate::csaf::csaf2_0::schema::{Branch, CategoryOfTheRemediation, CommonSecurityAdvisoryFramework, DocumentGenerator, DocumentLevelMetaData, DocumentStatus, Flag, FullProductNameT, HelperToIdentifyTheProduct, Id, Involvement, LabelOfTlp, Note, ProductGroup, ProductStatus, ProductTree, Relationship, Remediation, Revision, RulesForSharingDocument, Score, Threat, Tracking, TrafficLightProtocolTlp, Vulnerability};
2+
use crate::csaf::csaf2_1::schema::{CategoryOfTheRemediation as Remediation21, DocumentStatus as Status21, Epss, LabelOfTlp as Tlp21};
3+
use crate::csaf::getter_traits::{BranchTrait, CsafTrait, DistributionTrait, DocumentTrait, FlagTrait, ProductTrait, GeneratorTrait, InvolvementTrait, MetricTrait, ProductGroupTrait, ProductIdentificationHelperTrait, ProductStatusTrait, ProductTreeTrait, RelationshipTrait, RemediationTrait, RevisionTrait, SharingGroupTrait, ThreatTrait, TlpTrait, TrackingTrait, VulnerabilityTrait, ContentTrait, VulnerabilityIdTrait, NoteTrait, WithGroupIds};
44
use std::ops::Deref;
55
use serde::de::Error;
6+
use serde_json::{Map, Value};
67
use crate::csaf::csaf2_1::ssvc_schema::SsvcV1;
78
use crate::csaf::validation::ValidationError;
89

10+
impl WithGroupIds for Remediation {
11+
fn get_group_ids(&self) -> Option<impl Iterator<Item=&String> + '_> {
12+
self.group_ids.as_ref().map(|g| (*g).iter().map(|x| x.deref()))
13+
}
14+
}
15+
916
impl RemediationTrait for Remediation {
1017
/// Normalizes the remediation categories from CSAF 2.0 to those of CSAF 2.1.
1118
///
@@ -31,10 +38,6 @@ impl RemediationTrait for Remediation {
3138
self.product_ids.as_ref().map(|p| (*p).iter().map(|x| x.deref()))
3239
}
3340

34-
fn get_group_ids(&self) -> Option<impl Iterator<Item = &String> + '_> {
35-
self.group_ids.as_ref().map(|g| (*g).iter().map(|x| x.deref()))
36-
}
37-
3841
fn get_date(&self) -> &Option<String> {
3942
&self.date
4043
}
@@ -72,29 +75,73 @@ impl ProductStatusTrait for ProductStatus {
7275
fn get_under_investigation(&self) -> Option<impl Iterator<Item = &String> + '_> {
7376
self.under_investigation.as_ref().map(|p| (*p).iter().map(|x| x.deref()))
7477
}
78+
79+
/// Not specified for CSAF 2.0, so `None`
80+
fn get_unknown(&self) -> Option<impl Iterator<Item=&String> + '_> {
81+
None::<std::iter::Empty<&String>>
82+
}
7583
}
7684

77-
impl MetricTrait for () {
78-
type ContentType = ();
85+
impl MetricTrait for Score {
86+
type ContentType = Score;
7987

80-
//noinspection RsConstantConditionIf
8188
fn get_products(&self) -> impl Iterator<Item = &String> + '_ {
82-
// This construction is required to satisfy compiler checks
83-
// and still panic if this is ever called (as this would be a clear error!).
84-
if true {
85-
panic!("Metrics are not implemented in CSAF 2.0");
86-
}
87-
std::iter::empty()
89+
self.products.iter().map(|x| x.deref())
8890
}
8991

9092
fn get_content(&self) -> &Self::ContentType {
91-
panic!("Metrics are not implemented in CSAF 2.0");
93+
self
94+
}
95+
96+
fn get_source(&self) -> &Option<String> {
97+
&None
9298
}
9399
}
94100

95-
impl ContentTrait for () {
101+
impl ContentTrait for Score {
102+
fn has_ssvc_v1(&self) -> bool {
103+
false
104+
}
105+
96106
fn get_ssvc_v1(&self) -> Result<SsvcV1, serde_json::Error> {
97-
Err(serde_json::Error::custom("Metrics are not implemented in CSAF 2.0"))
107+
Err(serde_json::Error::custom("SSVC metrics are not implemented in CSAF 2.0"))
108+
}
109+
110+
fn get_cvss_v2(&self) -> Option<&Map<String, Value>> {
111+
if self.cvss_v2.is_empty() {
112+
None
113+
} else {
114+
Some(&self.cvss_v2)
115+
}
116+
}
117+
118+
fn get_cvss_v3(&self) -> Option<&Map<String, Value>> {
119+
if self.cvss_v3.is_empty() {
120+
None
121+
} else {
122+
Some(&self.cvss_v3)
123+
}
124+
}
125+
126+
fn get_cvss_v4(&self) -> Option<&Map<String, Value>> {
127+
None
128+
}
129+
130+
fn get_epss(&self) -> &Option<Epss> {
131+
&None::<Epss>
132+
}
133+
134+
fn get_content_json_path(&self, vulnerability_idx: usize, metric_idx: usize) -> String {
135+
format!(
136+
"/vulnerabilities/{}/scores/{}",
137+
vulnerability_idx, metric_idx
138+
)
139+
}
140+
}
141+
142+
impl WithGroupIds for Threat {
143+
fn get_group_ids(&self) -> Option<impl Iterator<Item = &String> + '_> {
144+
self.group_ids.as_ref().map(|g| (*g).iter().map(|x| x.deref()))
98145
}
99146
}
100147

@@ -112,11 +159,12 @@ impl VulnerabilityTrait for Vulnerability {
112159
type RemediationType = Remediation;
113160
type ProductStatusType = ProductStatus;
114161
// Metrics are not implemented in CSAF 2.0
115-
type MetricType = ();
162+
type MetricType = Score;
116163
type ThreatType = Threat;
117164
type FlagType = Flag;
118165
type InvolvementType = Involvement;
119166
type VulnerabilityIdType = Id;
167+
type NoteType = Note;
120168

121169
fn get_remediations(&self) -> &Vec<Self::RemediationType> {
122170
&self.remediations
@@ -126,9 +174,8 @@ impl VulnerabilityTrait for Vulnerability {
126174
&self.product_status
127175
}
128176

129-
fn get_metrics(&self) -> &Option<Vec<Self::MetricType>> {
130-
// Metrics are not implemented in CSAF 2.0
131-
&None
177+
fn get_metrics(&self) -> Option<&Vec<Self::MetricType>> {
178+
Some(&self.scores)
132179
}
133180

134181
fn get_threats(&self) -> &Vec<Self::ThreatType> {
@@ -154,9 +201,14 @@ impl VulnerabilityTrait for Vulnerability {
154201
fn get_cve(&self) -> Option<&String> {
155202
self.cve.as_ref().map(|x| x.deref())
156203
}
204+
157205
fn get_ids(&self) -> &Option<Vec<Self::VulnerabilityIdType>> {
158206
&self.ids
159207
}
208+
209+
fn get_notes(&self) -> Option<&Vec<Self::NoteType>> {
210+
self.notes.as_ref().map(|x| x.deref())
211+
}
160212
}
161213

162214
impl VulnerabilityIdTrait for Id {
@@ -169,6 +221,12 @@ impl VulnerabilityIdTrait for Id {
169221
}
170222
}
171223

224+
impl WithGroupIds for Flag {
225+
fn get_group_ids(&self) -> Option<impl Iterator<Item=&String> + '_> {
226+
self.group_ids.as_ref().map(|g| (*g).iter().map(|x| x.deref()))
227+
}
228+
}
229+
172230
impl FlagTrait for Flag {
173231
fn get_date(&self) -> &Option<String> {
174232
&self.date
@@ -202,6 +260,7 @@ impl CsafTrait for CommonSecurityAdvisoryFramework {
202260
impl DocumentTrait for DocumentLevelMetaData {
203261
type TrackingType = Tracking;
204262
type DistributionType = RulesForSharingDocument;
263+
type NoteType = Note;
205264

206265
fn get_tracking(&self) -> &Self::TrackingType {
207266
&self.tracking
@@ -222,6 +281,10 @@ impl DocumentTrait for DocumentLevelMetaData {
222281
Some(distribution) => Ok(distribution)
223282
}
224283
}
284+
285+
fn get_notes(&self) -> Option<&Vec<Self::NoteType>> {
286+
self.notes.as_ref().map(|x| x.deref())
287+
}
225288
}
226289

227290
impl DistributionTrait for RulesForSharingDocument {
@@ -249,6 +312,14 @@ impl DistributionTrait for RulesForSharingDocument {
249312
}
250313
}
251314

315+
impl WithGroupIds for Note {
316+
fn get_group_ids(&self) -> Option<impl Iterator<Item=&String> + '_> {
317+
None::<std::iter::Empty<&String>>
318+
}
319+
}
320+
321+
impl NoteTrait for Note {}
322+
252323
impl SharingGroupTrait for () {
253324
fn get_id(&self) -> &String {
254325
panic!("Sharing groups are not implemented in CSAF 2.0");

0 commit comments

Comments
 (0)