Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add the "reserved" field for vulnerabilities #966

Merged
merged 1 commit into from
Nov 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions entity/src/advisory_vulnerability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub struct Model {
pub title: Option<String>,
pub summary: Option<String>,
pub description: Option<String>,
pub reserved_date: Option<OffsetDateTime>,
pub discovery_date: Option<OffsetDateTime>,
pub release_date: Option<OffsetDateTime>,
pub cwes: Option<Vec<String>>,
Expand Down
1 change: 1 addition & 0 deletions entity/src/vulnerability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub struct Model {
#[sea_orm(primary_key)]
pub id: String,
pub title: Option<String>,
pub reserved: Option<OffsetDateTime>,
pub published: Option<OffsetDateTime>,
pub modified: Option<OffsetDateTime>,
pub withdrawn: Option<OffsetDateTime>,
Expand Down
2 changes: 2 additions & 0 deletions migration/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ mod m0000660_purl_id_indexes;
mod m0000670_version_cmp;
mod m0000680_fix_update_deprecated_advisory;
mod m0000690_alter_sbom_details;
mod m0000700_advisory_add_reserved;

pub struct Migrator;

Expand Down Expand Up @@ -179,6 +180,7 @@ impl MigratorTrait for Migrator {
Box::new(m0000670_version_cmp::Migration),
Box::new(m0000680_fix_update_deprecated_advisory::Migration),
Box::new(m0000690_alter_sbom_details::Migration),
Box::new(m0000700_advisory_add_reserved::Migration),
]
}
}
Expand Down
71 changes: 71 additions & 0 deletions migration/src/m0000700_advisory_add_reserved.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
use sea_orm_migration::prelude::*;

#[derive(DeriveMigrationName)]
pub struct Migration;

#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(Vulnerability::Table)
.add_column(
ColumnDef::new(Vulnerability::Reserved)
.timestamp_with_time_zone()
.to_owned(),
)
.to_owned(),
)
.await?;

manager
.alter_table(
Table::alter()
.table(AdvisoryVulnerability::Table)
.add_column(
ColumnDef::new(AdvisoryVulnerability::ReservedDate)
.timestamp_with_time_zone()
.to_owned(),
)
.to_owned(),
)
.await?;

Ok(())
}

async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(AdvisoryVulnerability::Table)
.drop_column(AdvisoryVulnerability::ReservedDate)
.to_owned(),
)
.await?;

manager
.alter_table(
Table::alter()
.table(Vulnerability::Table)
.drop_column(Vulnerability::Reserved)
.to_owned(),
)
.await?;

Ok(())
}
}

#[derive(DeriveIden)]
enum Vulnerability {
Table,
Reserved,
}

#[derive(DeriveIden)]
enum AdvisoryVulnerability {
Table,
ReservedDate,
}
1 change: 1 addition & 0 deletions modules/fundamental/src/purl/model/details/purl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ impl PurlAdvisory {
let vulnerability = vuln.unwrap_or(vulnerability::Model {
id: status.vulnerability_id.clone(),
title: None,
reserved: None,
published: None,
modified: None,
withdrawn: None,
Expand Down
2 changes: 2 additions & 0 deletions modules/fundamental/src/vulnerability/endpoints/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ async fn one_vulnerability(ctx: &TrustifyContext) -> Result<(), anyhow::Error> {
VulnerabilityInformation {
title: Some("Something wicked this way comes".to_string()),
published: Some(OffsetDateTime::now_utc()),
reserved: None,
modified: None,
withdrawn: None,
cwes: None,
Expand Down Expand Up @@ -268,6 +269,7 @@ async fn delete_vulnerability(ctx: &TrustifyContext) -> Result<(), anyhow::Error
"CVE-123",
VulnerabilityInformation {
title: Some("Something wicked this way comes".to_string()),
reserved: None,
published: Some(OffsetDateTime::now_utc()),
modified: None,
withdrawn: None,
Expand Down
1 change: 1 addition & 0 deletions modules/fundamental/src/vulnerability/model/details/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ impl VulnerabilityDetails {
identifier: vulnerability.id.clone(),
title: None,
description: None,
reserved: None,
published: None,
modified: None,
withdrawn: None,
Expand Down
7 changes: 7 additions & 0 deletions modules/fundamental/src/vulnerability/model/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ pub struct VulnerabilityHead {
#[schema(required)]
pub description: Option<String>,

/// The date (in RFC3339 format) of when the vulnerability identifier was reserved, if any.
#[schema(required)]
#[serde(with = "time::serde::rfc3339::option")]
pub reserved: Option<OffsetDateTime>,

/// The date (in RFC3339 format) of when the vulnerability was published, if any.
#[schema(required)]
#[serde(with = "time::serde::rfc3339::option")]
Expand Down Expand Up @@ -92,6 +97,7 @@ impl VulnerabilityHead {
identifier: entity.id.clone(),
title: entity.title.clone(),
description,
reserved: entity.reserved,
published: entity.published,
modified: entity.modified,
withdrawn: entity.withdrawn,
Expand All @@ -110,6 +116,7 @@ impl VulnerabilityHead {
identifier: vuln.id.clone(),
title: advisory_vulnerability.title.clone(),
description: advisory_vulnerability.description.clone(),
reserved: advisory_vulnerability.reserved_date,
published: None,
modified: None,
withdrawn: None,
Expand Down
1 change: 1 addition & 0 deletions modules/fundamental/tests/advisory/csaf/delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ async fn delete_check_vulns(ctx: &TrustifyContext) -> anyhow::Result<()> {
identifier: "CVE-2023-33201".to_string(),
title: None,
description: None,
reserved: None,
published: None,
modified: None,
withdrawn: None,
Expand Down
3 changes: 3 additions & 0 deletions modules/fundamental/tests/advisory/csaf/reingest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ async fn change_ps_list_vulns(ctx: &TrustifyContext) -> anyhow::Result<()> {
identifier: "CVE-2023-33201".to_string(),
title: None,
description: None,
reserved: None,
published: None,
modified: None,
withdrawn: None,
Expand Down Expand Up @@ -240,6 +241,7 @@ async fn change_ps_list_vulns_all(ctx: &TrustifyContext) -> anyhow::Result<()> {
identifier: "CVE-2023-33201".to_string(),
title: None,
description: None,
reserved: None,
published: None,
modified: None,
withdrawn: None,
Expand All @@ -261,6 +263,7 @@ async fn change_ps_list_vulns_all(ctx: &TrustifyContext) -> anyhow::Result<()> {
identifier: "CVE-2023-33201".to_string(),
title: None,
description: None,
reserved: None,
published: None,
modified: None,
withdrawn: None,
Expand Down
2 changes: 2 additions & 0 deletions modules/fundamental/tests/advisory/osv/reingest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ async fn withdrawn(ctx: &TrustifyContext) -> anyhow::Result<()> {
identifier: "CVE-2020-5238".to_string(),
title: None,
description: None,
reserved: None,
published: None,
modified: None,
withdrawn: None,
Expand All @@ -142,6 +143,7 @@ async fn withdrawn(ctx: &TrustifyContext) -> anyhow::Result<()> {
identifier: "CVE-2020-5238".to_string(),
title: None,
description: None,
reserved: None,
published: None,
modified: None,
withdrawn: None,
Expand Down
2 changes: 2 additions & 0 deletions modules/graphql/src/vulnerability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ impl VulnerabilityQuery {
Ok(Some(vulnerability)) => Ok(Vulnerability {
id: vulnerability.vulnerability.id,
title: vulnerability.vulnerability.title,
reserved: vulnerability.vulnerability.reserved,
published: vulnerability.vulnerability.published,
modified: vulnerability.vulnerability.modified,
withdrawn: vulnerability.vulnerability.withdrawn,
Expand All @@ -47,6 +48,7 @@ impl VulnerabilityQuery {
Ok(Vulnerability {
id: vulnerability.vulnerability.id,
title: vulnerability.vulnerability.title,
reserved: vulnerability.vulnerability.reserved,
published: vulnerability.vulnerability.published,
modified: vulnerability.vulnerability.modified,
withdrawn: vulnerability.vulnerability.withdrawn,
Expand Down
2 changes: 2 additions & 0 deletions modules/ingestor/src/graph/advisory/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ pub struct AdvisoryVulnerabilityInformation {
pub title: Option<String>,
pub summary: Option<String>,
pub description: Option<String>,
pub reserved_date: Option<OffsetDateTime>,
pub discovery_date: Option<OffsetDateTime>,
pub release_date: Option<OffsetDateTime>,
pub cwes: Option<Vec<String>>,
Expand Down Expand Up @@ -275,6 +276,7 @@ impl<'g> AdvisoryContext<'g> {
description: Set(information
.as_ref()
.and_then(|info| info.description.clone())),
reserved_date: Set(information.as_ref().and_then(|info| info.reserved_date)),
discovery_date: Set(information.as_ref().and_then(|info| info.discovery_date)),
release_date: Set(information.as_ref().and_then(|info| info.release_date)),
cwes: Set(information.as_ref().and_then(|info| info.cwes.clone())),
Expand Down
5 changes: 5 additions & 0 deletions modules/ingestor/src/graph/vulnerability/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use uuid::Uuid;
#[derive(Clone, Default, Debug)]
pub struct VulnerabilityInformation {
pub title: Option<String>,
pub reserved: Option<OffsetDateTime>,
pub published: Option<OffsetDateTime>,
pub modified: Option<OffsetDateTime>,
pub withdrawn: Option<OffsetDateTime>,
Expand All @@ -25,6 +26,7 @@ pub struct VulnerabilityInformation {
impl VulnerabilityInformation {
pub fn has_data(&self) -> bool {
self.title.is_some()
|| self.reserved.is_some()
|| self.published.is_some()
|| self.modified.is_some()
|| self.withdrawn.is_some()
Expand All @@ -36,6 +38,7 @@ impl From<()> for VulnerabilityInformation {
fn from(_: ()) -> Self {
Self {
title: None,
reserved: None,
published: None,
modified: None,
withdrawn: None,
Expand All @@ -59,6 +62,7 @@ impl Graph {
let on_conflict = match information.has_data() {
true => on_conflict.update_columns([
vulnerability::Column::Title,
vulnerability::Column::Reserved,
vulnerability::Column::Published,
vulnerability::Column::Modified,
vulnerability::Column::Withdrawn,
Expand All @@ -75,6 +79,7 @@ impl Graph {
let entity = vulnerability::ActiveModel {
id: Set(identifier.to_string()),
title: Set(information.title),
reserved: Set(information.reserved),
published: Set(information.published),
modified: Set(information.modified),
withdrawn: Set(information.withdrawn),
Expand Down
1 change: 1 addition & 0 deletions modules/ingestor/src/service/advisory/csaf/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ impl<'g> CsafLoader<'g> {
title: vulnerability.title.clone(),
summary: None,
description: None,
reserved_date: None,
discovery_date: vulnerability.discovery_date.and_then(|date| {
OffsetDateTime::from_unix_timestamp(date.timestamp()).ok()
}),
Expand Down
14 changes: 13 additions & 1 deletion modules/ingestor/src/service/advisory/cve/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ impl<'g> CveLoader<'g> {

let cwes = information.cwes.clone();
let release_date = information.published;
let reserved_date = information.reserved;
let title = information.title.clone();
let advisory_info = AdvisoryInformation {
title: information.title.clone(),
Expand Down Expand Up @@ -92,6 +93,7 @@ impl<'g> CveLoader<'g> {
title,
summary: None,
description: english_description.map(ToString::to_string),
reserved_date,
discovery_date: assigned,
release_date,
cwes,
Expand Down Expand Up @@ -199,6 +201,10 @@ impl<'g> CveLoader<'g> {
}

fn extract_vuln_info(cve: &Cve) -> VulnerabilityDetails {
let reserved = cve
.common_metadata()
.date_reserved
.map(Timestamp::assume_utc);
let published = cve
.common_metadata()
.date_published
Expand Down Expand Up @@ -276,6 +282,7 @@ impl<'g> CveLoader<'g> {
affected,
information: VulnerabilityInformation {
title: title.clone(),
reserved,
published,
modified,
withdrawn,
Expand Down Expand Up @@ -325,6 +332,7 @@ mod test {
use std::str::FromStr;
use test_context::test_context;
use test_log::test;
use time::macros::datetime;
use trustify_common::db::Transactional;
use trustify_common::purl::Purl;
use trustify_test_context::{document, TrustifyContext};
Expand All @@ -351,13 +359,17 @@ mod test {

let loaded_vulnerability = graph.get_vulnerability("CVE-2024-28111", ()).await?;
assert!(loaded_vulnerability.is_some());
let loaded_vulnerability = loaded_vulnerability.unwrap();
assert_eq!(
loaded_vulnerability.vulnerability.reserved,
Some(datetime!(2024-03-04 14:19:14.059 UTC))
);

let loaded_advisory = graph
.get_advisory_by_digest(&digests.sha256.encode_hex::<String>(), Transactional::None)
.await?;
assert!(loaded_advisory.is_some());

let loaded_vulnerability = loaded_vulnerability.unwrap();
let descriptions = loaded_vulnerability.descriptions("en", ()).await?;
assert_eq!(1, descriptions.len());
assert!(descriptions[0]
Expand Down
1 change: 1 addition & 0 deletions modules/ingestor/src/service/advisory/osv/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ impl<'g> OsvLoader<'g> {
title: osv.summary.clone(),
summary: osv.summary.clone(),
description: osv.details.clone(),
reserved_date: None,
discovery_date: None,
release_date: None,
cwes: None,
Expand Down
10 changes: 9 additions & 1 deletion modules/ingestor/tests/reingest/cve.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#![allow(clippy::expect_used)]
#![allow(clippy::unwrap_used)]

use anyhow::bail;
use test_context::test_context;
use test_log::test;
use time::macros::datetime;
use trustify_common::id::Id;
use trustify_module_ingestor::model::IngestResult;
use trustify_test_context::TrustifyContext;
Expand All @@ -20,7 +22,13 @@ async fn reingest(ctx: &TrustifyContext) -> Result<(), anyhow::Error> {
.await?
.expect("must be found");

assert_eq!(adv.vulnerabilities(()).await?.len(), 1);
let mut adv_vulns = adv.vulnerabilities(()).await?;
assert_eq!(adv_vulns.len(), 1);
let adv_vuln = adv_vulns.pop().unwrap();
assert_eq!(
adv_vuln.advisory_vulnerability.reserved_date,
Some(datetime!(2021-05-12 0:00:00 UTC))
);

let vulns = ctx.graph.get_vulnerabilities(()).await?;
assert_eq!(vulns.len(), 1);
Expand Down
Loading