Skip to content

Commit

Permalink
feat: add average_severity to PurlStatus
Browse files Browse the repository at this point in the history
Fixes: 1099

Signed-off-by: Jim Crossley <[email protected]>
  • Loading branch information
jcrossley3 committed Jan 9, 2025
1 parent 44ade24 commit 4a7ae84
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 35 deletions.
4 changes: 4 additions & 0 deletions modules/fundamental/src/purl/endpoints/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,10 @@ async fn package_with_status(ctx: &TrustifyContext) -> Result<(), anyhow::Error>
let response: Value = app.call_and_read_body_json(request).await;

assert_eq!(uuid, Uuid::parse_str(response["uuid"].as_str().unwrap())?);
assert_eq!(
"critical",
response["advisories"][0]["status"][0]["average_severity"]
);

Ok(())
}
74 changes: 39 additions & 35 deletions modules/fundamental/src/purl/model/details/purl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use crate::{
vulnerability::model::VulnerabilityHead,
Error,
};
use ::cpe::uri::OwnedUri;
use sea_orm::{
ColumnTrait, ConnectionTrait, DbErr, EntityTrait, FromQueryResult, LoaderTrait, ModelTrait,
QueryFilter, QueryOrder, QueryResult, QuerySelect, QueryTrait, RelationTrait, Select,
Expand All @@ -20,10 +19,12 @@ use trustify_common::{
memo::Memo,
purl::Purl,
};
use trustify_cvss::cvss3::{score::Score, severity::Severity, Cvss3Base};
use trustify_entity::{
advisory, base_purl, cpe, license, organization, product, product_status, product_version,
product_version_range, purl_license_assertion, purl_status, qualified_purl, sbom, sbom_package,
sbom_package_purl_ref, status, version_range, versioned_purl, vulnerability,
advisory, base_purl, cpe, cvss3, license, organization, product, product_status,
product_version, product_version_range, purl_license_assertion, purl_status, qualified_purl,
sbom, sbom_package, sbom_package_purl_ref, status, version_range, versioned_purl,
vulnerability,
};
use trustify_module_ingestor::common::{Deprecation, DeprecationForExt};
use utoipa::ToSchema;
Expand Down Expand Up @@ -247,21 +248,13 @@ impl PurlAdvisory {
withdrawn: None,
cwes: None,
};

let advisory_cpe: Option<OwnedUri> = (&product_status.cpe).try_into().ok();

let purl_status = PurlStatus {
vulnerability: VulnerabilityHead::from_vulnerability_entity(
&vuln,
Memo::NotProvided,
tx,
)
.await?,
status: product_status.status.slug,
context: advisory_cpe
.as_ref()
.map(|e| StatusContext::Cpe(e.to_string())),
};
let purl_status = PurlStatus::new(
&vuln,
product_status.status.slug,
Some(product_status.cpe.to_string()),
tx,
)
.await?;

if let Some(entry) = results
.iter_mut()
Expand Down Expand Up @@ -294,6 +287,7 @@ impl PurlAdvisory {
#[derive(Serialize, Deserialize, Debug, ToSchema, PartialEq, Eq)]
pub struct PurlStatus {
pub vulnerability: VulnerabilityHead,
pub average_severity: Severity,
pub status: String,
#[schema(required)]
pub context: Option<StatusContext>,
Expand All @@ -307,36 +301,46 @@ pub enum StatusContext {
}

impl PurlStatus {
pub async fn from_entity<C: ConnectionTrait>(
pub async fn new<C: ConnectionTrait>(
vuln: &vulnerability::Model,
package_status: &purl_status::Model,
status: String,
cpe: Option<String>,
tx: &C,
) -> Result<Self, Error> {
let status = status::Entity::find_by_id(package_status.status_id)
.one(tx)
.await?;

let status = status.map(|e| e.slug).unwrap_or("unknown".to_string());

let cpe = if let Some(context_cpe) = package_status.context_cpe_id {
let cpe = cpe::Entity::find_by_id(context_cpe).one(tx).await?;

cpe.map(|cpe| cpe.to_string())
} else {
None
};

let cvss3 = vuln.find_related(cvss3::Entity).all(tx).await?;
let average_severity = Score::from_iter(cvss3.iter().map(Cvss3Base::from)).severity();
Ok(Self {
vulnerability: VulnerabilityHead::from_vulnerability_entity(
vuln,
Memo::NotProvided,
tx,
)
.await?,
average_severity,
status,
context: cpe.map(StatusContext::Cpe),
})
}

pub async fn from_entity<C: ConnectionTrait>(
vuln: &vulnerability::Model,
package_status: &purl_status::Model,
tx: &C,
) -> Result<Self, Error> {
let status = status::Entity::find_by_id(package_status.status_id)
.one(tx)
.await?
.map(|e| e.slug)
.unwrap_or("unknown".into());
let cpe = match package_status.context_cpe_id {
Some(context_cpe) => {
let cpe = cpe::Entity::find_by_id(context_cpe).one(tx).await?;
cpe.map(|v| v.to_string())
}
_ => None,
};
PurlStatus::new(vuln, status, cpe, tx).await
}
}

#[derive(Serialize, Clone, Deserialize, Debug, ToSchema)]
Expand Down
2 changes: 2 additions & 0 deletions modules/fundamental/tests/advisory/csaf/delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use super::prepare_ps_state_change;
use test_context::test_context;
use test_log::test;
use trustify_common::purl::Purl;
use trustify_cvss::cvss3::severity::Severity;
use trustify_module_fundamental::{
advisory::service::AdvisoryService,
purl::{
Expand Down Expand Up @@ -131,6 +132,7 @@ async fn delete_check_vulns(ctx: &TrustifyContext) -> anyhow::Result<()> {
identifier: "CVE-2023-33201".to_string(),
..Default::default()
},
average_severity: Severity::High,
status: "affected".to_string(),
context: Some(StatusContext::Cpe(
"cpe:/a:redhat:jboss_enterprise_application_platform:7.4:*:el9:*".to_string()
Expand Down
4 changes: 4 additions & 0 deletions modules/fundamental/tests/advisory/csaf/reingest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use super::{prepare_ps_state_change, twice};
use test_context::test_context;
use test_log::test;
use trustify_common::purl::Purl;
use trustify_cvss::cvss3::severity::Severity;
use trustify_module_fundamental::{
purl::{
model::details::purl::{PurlStatus, StatusContext},
Expand Down Expand Up @@ -143,6 +144,7 @@ async fn change_ps_list_vulns(ctx: &TrustifyContext) -> anyhow::Result<()> {
identifier: "CVE-2023-33201".to_string(),
..Default::default()
},
average_severity: Severity::High,
status: "fixed".to_string(),
context: Some(StatusContext::Cpe(
"cpe:/a:redhat:jboss_enterprise_application_platform:7.4:*:el9:*".to_string()
Expand Down Expand Up @@ -233,6 +235,7 @@ async fn change_ps_list_vulns_all(ctx: &TrustifyContext) -> anyhow::Result<()> {
identifier: "CVE-2023-33201".to_string(),
..Default::default()
},
average_severity: Severity::High,
status: "affected".to_string(),
context: Some(StatusContext::Cpe(
"cpe:/a:redhat:jboss_enterprise_application_platform:7.4:*:el9:*".to_string()
Expand All @@ -247,6 +250,7 @@ async fn change_ps_list_vulns_all(ctx: &TrustifyContext) -> anyhow::Result<()> {
identifier: "CVE-2023-33201".to_string(),
..Default::default()
},
average_severity: Severity::High,
status: "fixed".to_string(),
context: Some(StatusContext::Cpe(
"cpe:/a:redhat:jboss_enterprise_application_platform:7.4:*:el9:*".to_string()
Expand Down
3 changes: 3 additions & 0 deletions modules/fundamental/tests/advisory/osv/reingest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use super::{twice, update_mark_fixed_again, update_unmark_fixed};
use test_context::test_context;
use test_log::test;
use trustify_common::purl::Purl;
use trustify_cvss::cvss3::severity::Severity;
use trustify_module_fundamental::{
purl::{model::details::purl::PurlStatus, service::PurlService},
vulnerability::{model::VulnerabilityHead, service::VulnerabilityService},
Expand Down Expand Up @@ -123,6 +124,7 @@ async fn withdrawn(ctx: &TrustifyContext) -> anyhow::Result<()> {
identifier: "CVE-2020-5238".to_string(),
..Default::default()
},
average_severity: Severity::None,
status: "affected".to_string(),
context: None,
}]
Expand All @@ -135,6 +137,7 @@ async fn withdrawn(ctx: &TrustifyContext) -> anyhow::Result<()> {
identifier: "CVE-2020-5238".to_string(),
..Default::default()
},
average_severity: Severity::None,
status: "affected".to_string(),
context: None,
}]
Expand Down
3 changes: 3 additions & 0 deletions openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3308,9 +3308,12 @@ components:
type: object
required:
- vulnerability
- average_severity
- status
- context
properties:
average_severity:
$ref: '#/components/schemas/Severity'
context:
oneOf:
- type: 'null'
Expand Down

0 comments on commit 4a7ae84

Please sign in to comment.