diff --git a/rust/Cargo.lock b/rust/Cargo.lock
index a04ccec6a..5e87aff49 100644
--- a/rust/Cargo.lock
+++ b/rust/Cargo.lock
@@ -1718,6 +1718,7 @@ checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65"
name = "notus"
version = "0.1.0"
dependencies = [
+ "clap",
"models",
"regex",
"serde",
diff --git a/rust/notus/Cargo.toml b/rust/notus/Cargo.toml
index 030566817..58eaabc87 100644
--- a/rust/notus/Cargo.toml
+++ b/rust/notus/Cargo.toml
@@ -8,5 +8,7 @@ edition = "2021"
[dependencies]
regex = "1.10.2"
serde_json = "1.0.96"
-serde = { version = "1.0.163", features = ["derive"] }
+serde = { version = "1.0.163" }
+clap = { version = "~4" }
+
models = { path = "../models" }
diff --git a/rust/notus/src/loader/json.rs b/rust/notus/src/loader/json.rs
index c072d1ae2..735ae5151 100644
--- a/rust/notus/src/loader/json.rs
+++ b/rust/notus/src/loader/json.rs
@@ -15,14 +15,14 @@ use crate::error::Error;
use super::AdvisoriesLoader;
#[derive(Debug)]
-pub struct JSONAdvisoriesLoader
+pub struct JSONAdvisoryLoader
where
P: AsRef,
{
path: P,
}
-impl JSONAdvisoriesLoader
+impl
JSONAdvisoryLoader
where
P: AsRef,
{
@@ -43,7 +43,7 @@ where
}
}
-impl AdvisoriesLoader for JSONAdvisoriesLoader
+impl
AdvisoriesLoader for JSONAdvisoryLoader
where
P: AsRef,
{
@@ -75,13 +75,13 @@ mod tests {
use crate::{error::Error, loader::AdvisoriesLoader};
- use super::JSONAdvisoriesLoader;
+ use super::JSONAdvisoryLoader;
#[test]
fn test_load_advisories() {
let mut path = env!("CARGO_MANIFEST_DIR").to_string();
path.push_str("/data");
- let loader = JSONAdvisoriesLoader::new(path).unwrap();
+ let loader = JSONAdvisoryLoader::new(path).unwrap();
let _ = loader.load_package_advisories("debian_10").unwrap();
}
@@ -90,7 +90,7 @@ mod tests {
let mut path = env!("CARGO_MANIFEST_DIR").to_string();
path.push_str("/data_foo");
assert!(
- matches!(JSONAdvisoriesLoader::new(path.clone()).expect_err("Should fail"), Error::MissingAdvisoryDir(p) if p == path)
+ matches!(JSONAdvisoryLoader::new(path.clone()).expect_err("Should fail"), Error::MissingAdvisoryDir(p) if p == path)
);
}
@@ -99,7 +99,7 @@ mod tests {
let mut path = env!("CARGO_MANIFEST_DIR").to_string();
path.push_str("/data/debian_10.notus");
assert!(
- matches!(JSONAdvisoriesLoader::new(path.clone()).expect_err("Should fail"), Error::AdvisoryDirIsFile(p) if p == path)
+ matches!(JSONAdvisoryLoader::new(path.clone()).expect_err("Should fail"), Error::AdvisoryDirIsFile(p) if p == path)
);
}
@@ -107,7 +107,7 @@ mod tests {
fn test_err_unknown_os() {
let mut path = env!("CARGO_MANIFEST_DIR").to_string();
path.push_str("/data");
- let loader = JSONAdvisoriesLoader::new(path).unwrap();
+ let loader = JSONAdvisoryLoader::new(path).unwrap();
let os = "foo";
assert!(
@@ -119,7 +119,7 @@ mod tests {
fn test_err_json_parse() {
let mut path = env!("CARGO_MANIFEST_DIR").to_string();
path.push_str("/data");
- let loader = JSONAdvisoriesLoader::new(path.clone()).unwrap();
+ let loader = JSONAdvisoryLoader::new(path.clone()).unwrap();
let os = "debian_10_json_parse_err";
assert!(
diff --git a/rust/notus/src/main.rs b/rust/notus/src/main.rs
new file mode 100644
index 000000000..dc2d12f4f
--- /dev/null
+++ b/rust/notus/src/main.rs
@@ -0,0 +1,70 @@
+// SPDX-FileCopyrightText: 2023 Greenbone AG
+//
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+use std::{fs::File, io::Read, path::PathBuf};
+
+use clap::{arg, value_parser, ArgAction, Command};
+use notus::{loader::json::JSONAdvisoryLoader, notus::Notus};
+
+fn main() {
+ let matches = Command::new("nasl-cli")
+ .version("1.0")
+ .about("Is a CLI tool around Notus.")
+ .arg(
+ arg!(-p --path "Path to the notus advisories.")
+ .required(true)
+ .value_parser(value_parser!(PathBuf)),
+ )
+ .arg(arg!(-s --os "To the packages corresponding operating system").required(true))
+ .arg(
+ arg!(-f --"pkg-file" "Path to the notus packages to check for vulnerabilities, the file should contain a comma separated list of packages")
+ .required_unless_present("pkg-list")
+ .conflicts_with("pkg-list")
+ .value_parser(value_parser!(PathBuf)),
+ )
+ .arg(
+ arg!(-l --"pkg-list" "A comma separated list of packages to check for vulnerabilities")
+ .required_unless_present("pkg-file"),
+ )
+ .arg(
+ arg!(-n --pretty "Enables pretty printing for the result").action(ArgAction::SetTrue)
+ )
+ .get_matches();
+
+ let advisory_path = matches.get_one::("path").unwrap();
+ let loader = match JSONAdvisoryLoader::new(advisory_path) {
+ Ok(loader) => loader,
+ Err(err) => {
+ eprintln!("{err}");
+ return;
+ }
+ };
+
+ let packages = match matches.get_one::("pkg-file") {
+ Some(path) => {
+ let mut buf = String::new();
+ File::open(path).unwrap().read_to_string(&mut buf).unwrap();
+ buf.split(",").map(str::to_string).collect::>()
+ }
+ None => {
+ let list = matches.get_one::("pkg-list").unwrap();
+ list.split(",").map(str::to_string).collect::>()
+ }
+ };
+
+ let os = matches.get_one::("os").unwrap();
+
+ let mut notus = Notus::new(loader);
+ match notus.scan(os, &packages) {
+ Ok(results) => {
+ let json = match matches.contains_id("pretty") {
+ true => serde_json::to_string_pretty(&results).unwrap(),
+ false => serde_json::to_string(&results).unwrap(),
+ };
+
+ println!("{json}");
+ }
+ Err(err) => eprintln!("{err}"),
+ }
+}
diff --git a/rust/notus/tests/notus.rs b/rust/notus/tests/notus.rs
index 5830bbe6a..e6bd44275 100644
--- a/rust/notus/tests/notus.rs
+++ b/rust/notus/tests/notus.rs
@@ -6,13 +6,13 @@
mod tests {
use models::{FixedPackage, FixedVersion, Specifier};
- use notus::{error::Error, loader::json::JSONAdvisoriesLoader, notus::Notus};
+ use notus::{error::Error, loader::json::JSONAdvisoryLoader, notus::Notus};
#[test]
fn test_notus() {
let mut path = env!("CARGO_MANIFEST_DIR").to_string();
path.push_str("/data");
- let loader = JSONAdvisoriesLoader::new(path.clone()).unwrap();
+ let loader = JSONAdvisoryLoader::new(path.clone()).unwrap();
let mut notus = Notus::new(loader);
let packages = vec![
@@ -65,7 +65,7 @@ mod tests {
fn test_err_package_parse_error() {
let mut path = env!("CARGO_MANIFEST_DIR").to_string();
path.push_str("/data");
- let loader = JSONAdvisoriesLoader::new(path.clone()).unwrap();
+ let loader = JSONAdvisoryLoader::new(path.clone()).unwrap();
let mut notus = Notus::new(loader);
let pkg_name = "wepofkewf~.124.sdefpo3-_~s#";
@@ -82,7 +82,7 @@ mod tests {
fn test_err_advisory_parse_error() {
let mut path = env!("CARGO_MANIFEST_DIR").to_string();
path.push_str("/data");
- let loader = JSONAdvisoriesLoader::new(path.clone()).unwrap();
+ let loader = JSONAdvisoryLoader::new(path.clone()).unwrap();
let mut notus = Notus::new(loader);
let packages = vec![];