Skip to content

Commit 6691525

Browse files
author
paolo9921
committed
fix comments
1 parent e35467b commit 6691525

File tree

3 files changed

+51
-19
lines changed

3 files changed

+51
-19
lines changed

domain-db/src/cve_sources/nist/cve/node.rs

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub struct Node {
2525
pub struct CpeMatch {
2626
pub vulnerable: bool,
2727
#[serde(
28-
rename = "criteria",
28+
rename = "cpe23Uri",
2929
deserialize_with = "cpe23_string_deserialize",
3030
serialize_with = "cpe23_string_serialize"
3131
)]
@@ -90,10 +90,14 @@ impl CpeMatch {
9090
}
9191

9292
pub fn is_match(&self, product: &str, version: &str) -> bool {
93+
// only evaluate leaves marked as vulnerable by NVD
9394
if !self.vulnerable {
9495
return false;
9596
}
97+
98+
// product must match
9699
if cpe23_product_match(&self.cpe23, product) {
100+
// match contains a version range
97101
if self.has_version_range() {
98102
return self.version_range_matches(version);
99103
}
@@ -170,14 +174,16 @@ impl Node {
170174
let op = self.operator.as_ref().unwrap_or(&Operator::Or);
171175

172176
let res = if !self.cpe_match.is_empty() {
177+
// leaf node
173178
match op {
174-
Operator::Or => self.cpe_match.iter().any(|m| m.is_match(product, version)),
175-
Operator::And => self.cpe_match.iter().all(|m| m.is_match(product, version)),
179+
Operator::Or => self.cpe_match.iter().any(|m| m.is_match(product, version)), // any of them
180+
Operator::And => self.cpe_match.iter().all(|m| m.is_match(product, version)), // all of them
176181
}
177182
} else {
183+
// evaluate children
178184
match op {
179-
Operator::Or => self.children.iter().any(|c| c.is_match(product, version)),
180-
Operator::And => self.children.iter().all(|c| c.is_match(product, version)),
185+
Operator::Or => self.children.iter().any(|c| c.is_match(product, version)), // any of them
186+
Operator::And => self.children.iter().all(|c| c.is_match(product, version)), // all of them
181187
}
182188
};
183189

@@ -197,8 +203,8 @@ where
197203
struct StringVisitor;
198204
impl<'de> Visitor<'de> for StringVisitor {
199205
type Value = cpe::CPE23;
200-
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
201-
f.write_str("CPE 2.3 string")
206+
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
207+
formatter.write_str("CPE 2.3 string")
202208
}
203209
fn visit_str<E>(self, value: &str) -> Result<cpe::CPE23, E>
204210
where
@@ -231,14 +237,17 @@ mod tests {
231237
"cpe:2.3:o:vendor:product:-:*:*:*:*:*:*:*",
232238
ProductMatch("stratocaster", false),
233239
);
240+
234241
table.insert(
235242
"cpe:2.3:o:gibson:lespaul:-:*:*:*:*:*:*:*",
236243
ProductMatch("lespaul", true),
237244
);
245+
238246
table.insert(
239247
"cpe:2.3:o:vendor:tar:-:*:*:*:*:node.js:*:*",
240248
ProductMatch("tar", false),
241249
);
250+
242251
table.insert(
243252
"cpe:2.3:o:vendor:tar:-:*:*:*:*:node.js:*:*",
244253
ProductMatch("node-tar", true),
@@ -260,38 +269,47 @@ mod tests {
260269
"cpe:2.3:o:vendor:product:-:*:*:*:*:*:*:*",
261270
VersionMatch("1.0.0", false),
262271
);
272+
263273
table.insert(
264274
"cpe:2.3:o:vendor:product:*:*:*:*:*:*:*:*",
265275
VersionMatch("1.0.0", true),
266276
);
277+
267278
table.insert(
268279
"cpe:2.3:o:vendor:product:*:*:*:*:*:*:*:*",
269280
VersionMatch("0.0.0", true),
270281
);
282+
271283
table.insert(
272284
"cpe:2.3:o:vendor:product:1:*:*:*:*:*:*:*",
273285
VersionMatch("1.0.0", true),
274286
);
287+
275288
table.insert(
276289
"cpe:2.3:o:vendor:product:1.0:*:*:*:*:*:*:*",
277290
VersionMatch("1.0.0", true),
278291
);
292+
279293
table.insert(
280294
"cpe:2.3:o:vendor:product:1.0.0:*:*:*:*:*:*:*",
281295
VersionMatch("1.0.0", true),
282296
);
297+
283298
table.insert(
284299
"cpe:2.3:o:vendor:product:1.0.1:*:*:*:*:*:*:*",
285300
VersionMatch("1.0.0", false),
286301
);
302+
287303
table.insert(
288304
"cpe:2.3:o:vendor:product:1.0.1:*:*:*:*:*:*:*",
289305
VersionMatch("1.0.1", true),
290306
);
307+
291308
table.insert(
292309
"cpe:2.3:o:vendor:product:1.0.1:rc0:*:*:*:*:*:*",
293310
VersionMatch("1.0.1", false),
294311
);
312+
295313
table.insert(
296314
"cpe:2.3:o:vendor:product:1.0.1:rc0:*:*:*:*:*:*",
297315
VersionMatch("1.0.1 RC0", true),

domain-db/src/cve_sources/nist/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ fn read_cves_from_path<P: AsRef<Path>>(path: P) -> Result<Vec<cve::CVE>> {
8686
let resp: NvdResponse = serde_json::from_reader(reader)
8787
.with_context(|| format!("failed to parse cve file from {}", path.as_ref().display()))?;
8888

89+
// Filter out incomplete CVE entries; NVD may publish before processing completes.
8990
let cves = resp
9091
.vulnerabilities
9192
.into_iter()

domain-db/src/db/mod.rs

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ impl PostgresRepository {
4848
let manager = ConnectionManager::<PgConnection>::new(database_url);
4949
let pool = r2d2::Pool::new(manager)?;
5050
let migrations = FileBasedMigrations::from_path(migrations_directory)?;
51+
5152
Ok(Self { pool, migrations })
5253
}
5354
}
@@ -60,20 +61,27 @@ impl PostgresRepository {
6061

6162
pub fn any_pending_migrations(&self) -> Result<bool> {
6263
let mut conn = self.pool.get()?;
64+
6365
conn.has_pending_migration(self.migrations.clone())
6466
.map_err(|e| anyhow!(e))
6567
.context("failed checking pending migrations")
6668
}
6769

6870
pub fn run_pending_migrations(&self) -> Result<()> {
6971
let mut conn = self.pool.get()?;
72+
7073
conn.run_pending_migrations(self.migrations.clone())
7174
.map_err(|e| anyhow!(e))
7275
.context("failed running pending migrations")?;
76+
7377
Ok(())
7478
}
7579

76-
/// Insert objects (dedup by `cve` via ON CONFLICT DO NOTHING) in batches.
80+
/// Insert a list of objects into the database if they don't already exist.
81+
///
82+
/// Insertion is done in batches of size `KEPLER__BATCH_SIZE` to avoid exceeding the maximum number of parameters = *(65535)* for PostgreSQL
83+
///
84+
/// Returns a [`HashMap<String, i32>`] of CVE IDs to their assigned object IDs.
7785
pub fn insert_objects(
7886
&self,
7987
objects_to_insert: Vec<models::NewObject>,
@@ -86,12 +94,14 @@ impl PostgresRepository {
8694
for chunk in objects_to_insert.chunks(*KEPLER_BATCH_SIZE) {
8795
let inserted_ids: HashMap<String, i32> =
8896
self.batch_insert_objects(chunk)?.into_iter().collect();
97+
8998
inserted_object_ids.extend(inserted_ids);
9099
}
100+
91101
Ok(inserted_object_ids)
92102
}
93103

94-
/// Inserts [`schema::objects`] in batches of size `KEPLER__BATCH_SIZE`.
104+
/// Inserts [`schema::objects`] into database in batches of size `KEPLER__BATCH_SIZE`.
95105
pub fn batch_insert_objects(
96106
&self,
97107
values_list: &[models::NewObject],
@@ -114,7 +124,7 @@ impl PostgresRepository {
114124
log::warn!("Zero object records are inserted!");
115125
}
116126

117-
// Query back to get IDs (idempotent whether inserted-or-existing).
127+
// Query back the inserted records to get their assigned IDs.
118128
let inserted_objects = objects
119129
.filter(cve.eq_any(&object_cves))
120130
.select((cve, id))
@@ -125,9 +135,12 @@ impl PostgresRepository {
125135
})
126136
}
127137

128-
/// Batch insert CVEs (dedup by `(cve,vendor,product)`).
138+
/// Batch insert CVEs if they don't already exist in the database.
139+
///
140+
/// Returns the number of inserted records.
129141
pub fn batch_insert_cves(&self, values_list: Vec<models::NewCVE>) -> Result<usize> {
130142
use schema::cves::dsl::*;
143+
131144
let mut conn = self.pool.get()?;
132145
conn.transaction(|conn| {
133146
let inserted_count = insert_into(cves)
@@ -136,12 +149,14 @@ impl PostgresRepository {
136149
.do_nothing()
137150
.execute(conn)
138151
.context("error creating cves in batch")?;
152+
139153
Ok(inserted_count)
140154
})
141155
}
142156

143157
pub fn delete_cve(&self, the_vendor: &str, the_product: &str, the_cve: &str) -> Result<usize> {
144158
use schema::cves::dsl::*;
159+
145160
let mut conn = self.pool.get()?;
146161
diesel::delete(
147162
cves.filter(
@@ -157,6 +172,7 @@ impl PostgresRepository {
157172

158173
pub fn get_products(&self) -> Result<Vec<models::Product>> {
159174
use schema::cves::dsl::*;
175+
160176
let mut conn = self.pool.get()?;
161177

162178
let prods: Vec<(String, String)> = cves
@@ -208,21 +224,16 @@ impl PostgresRepository {
208224

209225
let mut conn = self.pool.get()?;
210226

211-
// Fetch candidate rows
227+
// fetch potential candidates for this query
212228
let start = Instant::now();
213-
log::debug!(
214-
"query candidates by vendor={:?}, product='{}'",
215-
query.vendor,
216-
query.product
217-
);
218229
let candidates = fetch_candidates(&mut conn, query.vendor.as_ref(), &query.product)?;
219230
log::info!(
220231
"found {} candidates in {} ms",
221232
candidates.len(),
222233
start.elapsed().as_millis()
223234
);
224235

225-
// Deserialize stored JSON payloads into source-specific structs
236+
// deserialize all objects belonging to the potential CVEs
226237
let start = Instant::now();
227238
let sources = candidates
228239
.into_iter()
@@ -249,9 +260,11 @@ impl PostgresRepository {
249260
vendor: cve_row.vendor,
250261
product: cve_row.product,
251262
};
263+
252264
let matched_cve: MatchedCVE = match source {
253265
Source::Nist(nist_cve) => (product, nist_cve).into(),
254266
};
267+
255268
Some(matched_cve)
256269
} else {
257270
None
@@ -269,7 +282,7 @@ impl PostgresRepository {
269282
}
270283
}
271284

272-
/// Build unique objects from CVEs; value is the serialized full NVD 2.0 CVE for later re-hydration.
285+
/// Create unique objects from the CVE list
273286
pub fn create_unique_objects(
274287
cve_list: &[nist::cve::CVE],
275288
) -> Result<HashMap<String, models::NewObject>> {

0 commit comments

Comments
 (0)