Skip to content

Commit

Permalink
Add: handle scan status for openvas (no ospd) (#1606)
Browse files Browse the repository at this point in the history
* Add: handle scan status for openvas (no ospd)

* fix preference name and message type

* fix scan start/end time

* fix tests and typos
  • Loading branch information
jjnicola committed Mar 25, 2024
1 parent 9044e17 commit 6addc38
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 18 deletions.
4 changes: 4 additions & 0 deletions rust/models/src/scanner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ pub trait ScanResultFetcher {
async fn fetch_results<I>(&self, id: I) -> Result<ScanResults, Error>
where
I: AsRef<str> + Send + 'static;

fn do_addition(&self) -> bool {
false
}
}

/// Is a scanner implementation primarily for testing purposes.
Expand Down
28 changes: 26 additions & 2 deletions rust/openvas/src/openvas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use std::{
process::Child,
str::FromStr,
sync::{Arc, Mutex},
time::SystemTime,
};

use crate::{
Expand Down Expand Up @@ -310,9 +311,28 @@ impl ScanResultFetcher for Scanner {
))
})?
.into();
let start_time = match status {
Phase::Running => Some(
SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.expect("Valid timestamp for start scan")
.as_secs() as u32,
),
_ => None,
};
let end_time = match status {
Phase::Failed | Phase::Stopped | Phase::Succeeded => Some(
SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.expect("Valid timestamp for start scan")
.as_secs() as u32,
),
_ => None,
};

let st = Status {
start_time: None,
end_time: None,
start_time,
end_time,
status: status.clone(),
host_info: Some(hosts_info),
};
Expand Down Expand Up @@ -347,4 +367,8 @@ impl ScanResultFetcher for Scanner {
Err(_) => return Err(OpenvasError::ScanNotFound(scan_id.to_string()).into()),
};
}

fn do_addition(&self) -> bool {
true
}
}
4 changes: 2 additions & 2 deletions rust/openvas/src/pref_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ where

self.redis_connector.push_kb_item(
format!("internal/{}/scanprefs", self.scan_config.scan_id.clone()).as_str(),
format!("excluded_hosts|||{}", excluded_hosts),
format!("exclude_hosts|||{}", excluded_hosts),
)
}

Expand Down Expand Up @@ -580,7 +580,7 @@ mod tests {
assert!(prefh.prepare_host_options_for_openvas().await.is_ok());
assert!(prefh
.redis_connector
.item_exists("internal/123-456/scanprefs", "excluded_hosts|||127.0.0.1"));
.item_exists("internal/123-456/scanprefs", "exclude_hosts|||127.0.0.1"));

assert!(prefh.prepare_credentials_for_openvas().await.is_ok());
assert!(prefh.redis_connector.item_exists(
Expand Down
12 changes: 6 additions & 6 deletions rust/openvas/src/result_collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ where
let host_is_dead = value.contains("Host dead") || result_type == "DEADHOST";
let host_deny = value.contains("Host access denied");
let start_end_msg = result_type == "HOST_START" || result_type == "HOST_END";
let host_count = result_type == "HOST_COUNT";
let host_count = result_type == "HOSTS_COUNT";
let error_msg = result_type == "ERRMSG";
let excluded_hosts = result_type == "HOSTS_EXCLUDED";

Expand Down Expand Up @@ -198,13 +198,10 @@ where

if host_progress == -1 {
new_dead += 1;
all_hosts.remove(current_host);
} else if host_progress < 100 {
all_hosts.insert(current_host.to_string(), host_progress);
} else if host_progress == 100 {
new_alive += 1;
all_hosts.remove(current_host);
}
all_hosts.insert(current_host.to_string(), host_progress);

tracing::debug!("Host {} has progress: {}", current_host, host_progress);
}
Expand Down Expand Up @@ -249,7 +246,7 @@ mod tests {
"ERRMSG|||127.0.0.1||| localhost ||||||1.2.3.4.5.6||| NVT timeout".to_string(),
"ALARM|||127.0.0.1||| example.com |||22/tcp|||12.11.10.9.8.7||| Something wrong|||/var/lib/lib1.jar".to_string(),
"DEADHOST||| ||| ||| ||| |||3".to_string(),
"HOST_COUNT||| ||| ||| ||| |||12".to_string(),
"HOSTS_COUNT||| ||| ||| ||| |||12".to_string(),
"DEADHOST||| ||| ||| ||| |||1".to_string(),
"HOSTS_EXCLUDED||| ||| ||| ||| |||4".to_string(),

Expand Down Expand Up @@ -362,6 +359,9 @@ mod tests {
let mut r = HashMap::new();
r.insert("127.0.0.1".to_string(), 12);
r.insert("127.0.0.3".to_string(), 75);
r.insert("127.0.0.4".to_string(), 100);
r.insert("127.0.0.2".to_string(), -1);
r.insert("127.0.0.5".to_string(), -1);

assert_eq!(resh.results.as_ref().lock().unwrap().host_status, r);
assert_eq!(resh.results.as_ref().lock().unwrap().count_alive, 1);
Expand Down
79 changes: 71 additions & 8 deletions rust/openvasd/src/scheduling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later

use std::fmt::Display;
use std::time::SystemTime;

use crate::storage::{Error as StorageError, FeedHash};
use async_trait::async_trait;
Expand Down Expand Up @@ -210,7 +211,7 @@ where
match self.scanner.start_scan(scan).await {
Ok(_) => {
tracing::debug!(%scan_id, "started");
running.push(scan_id);
running.push(scan_id.clone());
}
Err(ScanError::Connection(e)) => {
tracing::warn!(%scan_id, %e, "requeuing because of a connection error");
Expand Down Expand Up @@ -245,14 +246,69 @@ where
match self.fetch_results(scan_id.clone()).await {
// using self.append_fetch_result instead of db to keep track of the status
// and may remove them from running.
Ok(results) => match self.append_fetched_result(vec![results]).await {
Ok(()) => {
tracing::trace!(%scan_id, "fetched and append results");
Ok(mut results) => {
if self.scanner.do_addition() {
let scan_status = self.db.get_status(&scan_id).await?;
let current_hosts_status = scan_status.host_info.unwrap_or_default();
let mut new_status = results.status.host_info.unwrap_or_default();
// total hosts value is sent once and only once must be updated
if current_hosts_status.all != 0 {
new_status.all = current_hosts_status.all;
}
// excluded hosts value is sent once and only once must be updated
if new_status.excluded == 0 {
new_status.excluded = current_hosts_status.excluded;
}
// new dead/alive/finished hosts are found during the scan.
// the new count must be added to the previous one
new_status.dead += current_hosts_status.dead;
new_status.alive += current_hosts_status.alive;
new_status.finished += current_hosts_status.finished;

//Update each single host status. Remove it if finished.
let mut hs = current_hosts_status.scanning.unwrap_or_default().clone();
for (host, progress) in
new_status.scanning.clone().unwrap_or_default().iter()
{
if *progress == 100 || *progress == -1 {
hs.remove(host);
} else {
hs.insert(host.to_string(), *progress);
}
}
new_status.scanning = Some(hs);

// update the hosts stauts into the result before storing
results.status.host_info = Some(new_status);

// Update start and end time if set from openvas
if scan_status.start_time.is_some() {
results.status.start_time = scan_status.start_time;
}

if scan_status.end_time.is_some() {
results.status.end_time = scan_status.end_time;
}

match self.append_fetched_result(vec![results]).await {
Ok(()) => {
tracing::trace!(%scan_id, "fetched and append results");
}
Err(e) => {
tracing::warn!(%scan_id, %e, "unable to append results");
}
};
} else {
match self.append_fetched_result(vec![results]).await {
Ok(()) => {
tracing::trace!(%scan_id, "fetched and append results");
}
Err(e) => {
tracing::warn!(%scan_id, %e, "unable to append results");
}
}
}
Err(e) => {
tracing::warn!(%scan_id, %e, "unable to append results");
}
},
}
Err(e) => {
tracing::warn!(%scan_id, %e, "unable to fetch results");
}
Expand Down Expand Up @@ -316,6 +372,13 @@ where
}
let mut current_status = self.db.get_status(&cid).await?;
current_status.status = Phase::Stopped;
current_status.end_time = Some(
SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.expect("Valid timestamp for end scan")
.as_secs() as u32,
);

self.db.update_status(&cid, current_status).await?;
Ok(())
}
Expand Down

0 comments on commit 6addc38

Please sign in to comment.