Skip to content

Commit

Permalink
Allow calculation of CVSS3 score using SQL functions, like a madman.
Browse files Browse the repository at this point in the history
Provide enough escape-hatches around filterin/sorting to do my evil deeds.
Do some evil deeds in SQL to allow sorting/filtering by synthetic `average_score` on advisories.
Do even more evil, by writing entirely too many SQL functions.
Lay in appropriate DOWN migration for cvss3 scoring functions.
  • Loading branch information
Bob McWhirter committed Jun 11, 2024
1 parent 968fb08 commit 26a977b
Show file tree
Hide file tree
Showing 10 changed files with 515 additions and 34 deletions.
8 changes: 8 additions & 0 deletions common/src/db/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,11 @@ impl Iden for ToJson {
s.write_str("to_json").unwrap();
}
}

pub struct Cvss3Score;

impl Iden for Cvss3Score {
fn unquoted(&self, s: &mut dyn Write) {
write!(s, "cvss3_score").unwrap()
}
}
37 changes: 37 additions & 0 deletions common/src/db/limiter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,43 @@ where
}
}

pub trait LimiterAsModelTrait<'db, C>
where
C: ConnectionTrait,
{
fn limiting_as<M: FromQueryResult + Sync + Send>(
self,
db: &'db C,
offset: u64,
limit: u64,
) -> Limiter<'db, C, SelectModel<M>, SelectModel<M>>;
}

impl<'db, C, E> LimiterAsModelTrait<'db, C> for Select<E>
where
C: ConnectionTrait,
E: EntityTrait,
{
fn limiting_as<M: FromQueryResult + Sync + Send>(
self,
db: &'db C,
offset: u64,
limit: u64,
) -> Limiter<'db, C, SelectModel<M>, SelectModel<M>> {
let selector = self
.clone()
.limit(NonZeroU64::new(limit).map(|limit| limit.get()))
.offset(NonZeroU64::new(offset).map(|offset| offset.get()))
.into_model::<M>();

Limiter {
db,
paginator: self.clone().into_model::<M>().paginate(db, 1),
selector,
}
}
}

pub fn limit_selector<'db, C, E, EM, M>(
db: &'db C,
select: Select<E>,
Expand Down
1 change: 1 addition & 0 deletions common/src/db/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,7 @@ fn envalue(s: &str, ct: &ColumnType) -> Result<Value, Error> {
}
Ok(match ct {
ColumnType::Integer => s.parse::<i32>().map_err(err)?.into(),
ColumnType::Decimal(_) => s.parse::<f64>().map_err(err)?.into(),
ColumnType::TimestampWithTimeZone => {
if let Ok(odt) = OffsetDateTime::parse(s, &Rfc3339) {
odt.into()
Expand Down
3 changes: 1 addition & 2 deletions entity/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub mod fixed_package_version;
pub mod importer;
pub mod importer_report;
pub mod not_affected_package_version;
pub mod organization;
pub mod package;
pub mod package_relates_to_package;
pub mod package_version;
Expand All @@ -23,5 +24,3 @@ pub mod sbom_package_cpe_ref;
pub mod sbom_package_purl_ref;
pub mod vulnerability;
pub mod vulnerability_description;

pub mod organization;
2 changes: 2 additions & 0 deletions migration/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ mod m0000280_add_advisory_vulnerability_meta;
mod m0000290_create_product;
mod m0000300_create_product_version;
mod m0000310_alter_advisory_primary_key;
mod m0000315_create_cvss3_scoring_function;

pub struct Migrator;

Expand Down Expand Up @@ -66,6 +67,7 @@ impl MigratorTrait for Migrator {
Box::new(m0000290_create_product::Migration),
Box::new(m0000300_create_product_version::Migration),
Box::new(m0000310_alter_advisory_primary_key::Migration),
Box::new(m0000315_create_cvss3_scoring_function::Migration),
]
}
}
Expand Down
74 changes: 74 additions & 0 deletions migration/src/m0000315_create_cvss3_scoring_function.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
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
.get_connection()
.execute_unprepared(include_str!("m0000315_create_cvss3_scoring_function.sql"))
.await
.map(|_| ())
}

async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.get_connection()
.execute_unprepared(r#"drop function cvss3_score"#)
.await?;

manager
.get_connection()
.execute_unprepared(r#"drop function cvss3_exploitability"#)
.await?;

manager
.get_connection()
.execute_unprepared(r#"drop function cvss3_impact"#)
.await?;

manager
.get_connection()
.execute_unprepared(r#"drop function cvss3_av_score"#)
.await?;

manager
.get_connection()
.execute_unprepared(r#"drop function cvss3_ac_score"#)
.await?;

manager
.get_connection()
.execute_unprepared(r#"drop function cvss3_pr_scoped_score"#)
.await?;

manager
.get_connection()
.execute_unprepared(r#"drop function cvss3_ui_score"#)
.await?;

manager
.get_connection()
.execute_unprepared(r#"drop function cvss3_scope_changed"#)
.await?;

manager
.get_connection()
.execute_unprepared(r#"drop function cvss3_c_score"#)
.await?;

manager
.get_connection()
.execute_unprepared(r#"drop function cvss3_i_score"#)
.await?;

manager
.get_connection()
.execute_unprepared(r#"drop function cvss3_a_score"#)
.await?;

Ok(())
}
}
Loading

0 comments on commit 26a977b

Please sign in to comment.