Skip to content

Commit

Permalink
Change: Adjust host details (#1557)
Browse files Browse the repository at this point in the history
Instead of having key-value pairs for host details we now have a defined struct, which also includes source information.
  • Loading branch information
Kraemii authored Jan 24, 2024
1 parent e2a5c9d commit b12152b
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 59 deletions.
94 changes: 68 additions & 26 deletions rust/doc/openapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,8 @@ paths:
description: "Schema of a result"
get result 3:
$ref: "#/components/examples/scan_result"
host detail:
$ref: "#/components/examples/host_detail"
"404":
description: "Result or Scan not found"
"406":
Expand Down Expand Up @@ -732,9 +734,37 @@ components:
message:
description: "Additional information about the result."
type: "string"
details:
description: "An object with key and value pairs. Only set on `host_detail` and should be treated as a `HashMap<String, String>` as there is not formalization possible."
detail:
description: "The detail object is only used for results of type host_detail. It contains information about a scanned hosted such as hardware information, architecture and many more."
type: "object"
properties:
name:
description: "descriptive name of the detail"
type: "string"
value:
description: "value of the host detail"
type: "string"
source:
description: "source of the host detail"
type: "object"
properties:
type:
description: "type of the source, e.g. nvt"
type: "string"
name:
description: "descriptive name of the source, in case of type nvt this is its OID"
type: "string"
description:
description: "Optional information about the detection, could contain how the data actually was collected."
type: "string"
required:
- type
- name
required:
- name
- value
- source

required:
- type

Expand Down Expand Up @@ -1063,9 +1093,31 @@ components:
"ip_address": "127.0.0.1",
"hostname": "localhost",
"oid": "1.3.6.1.4.1.25623.1.0.147696",
"port": 22,
"protocol": "tcp",
"message": "Installed version: 9.53.3\nFixed version: 9.55\nInstallation\npath / port: /usr/bin/gs",
}
host_detail:
description: "Example for a result of type host detail"
value:
{
"id": 3,
"type": "host_detail",
"ip_address": "127.0.0.1",
"hostname": "localhost",
"oid": "1.3.6.1.4.1.25623.1.0.103997",
"detail":
{
"name": "OS",
"value": "Debian GNU/Linux 11.5",
"source":
{
"type": "nvt",
"name": "1.3.6.1.4.1.25623.1.0.50282",
"description": "Determine OS and list of installed packages via SSH login",
},
},
}

scan_status_stored:
description: "Status of a queued Scan"
Expand Down Expand Up @@ -1148,39 +1200,29 @@ components:
"suse_linux_enterprise_module_for_live_patching_15-sp1",
"suse_manager_debian_9.0",
"slackware_10.1",
"slackware_10.2"
"slackware_10.2",
]
notus_simple:
description: "A simple example for notus run."
value:
[
"foo",
"bar",
"foo2",
]
value: ["foo", "bar", "foo2"]
notus_results:
description: "A simple example for notus run response including a vulnerable package list and their fix"
value:
[
{
"oid": "1.2.3",
"vulnerable_packages": [
"vulnerable_packages":
[
{
"package_name": "foo",
"installed_version": "1.2.3",
"fixed_versions": {
"start": "1.2.2",
"end": "1.2.5"
}
"package_name": "foo",
"installed_version": "1.2.3",
"fixed_versions": { "start": "1.2.2", "end": "1.2.5" },
},
{
"package_name": "bar",
"installed_version": "1.2.4",
"fixed_versions": {
"version": "1.2.5",
"specifier": ">="
}
}
]
}
]
"package_name": "bar",
"installed_version": "1.2.4",
"fixed_versions": { "version": "1.2.5", "specifier": ">=" },
},
],
},
]
36 changes: 34 additions & 2 deletions rust/models/src/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,41 @@ pub struct Result {

#[cfg_attr(
feature = "serde_support",
serde(skip_serializing_if = "HashMap::is_empty", default)
serde(skip_serializing_if = "Option::is_none", default)
)]
pub details: HashMap<String, String>,
pub detail: Option<Detail>,
}

/// Host Details information
#[derive(Debug, Clone, PartialEq, Eq, Default)]
#[cfg_attr(
feature = "serde_support",
derive(serde::Serialize, serde::Deserialize)
)]

pub struct Detail {
/// Descriptive name of a Host Detail
pub name: String,
/// Detected detail information
pub value: String,
/// Information about the source of the information
pub source: Source,
}

/// Host details source information
#[derive(Debug, Clone, PartialEq, Eq, Default)]
#[cfg_attr(
feature = "serde_support",
derive(serde::Serialize, serde::Deserialize)
)]
pub struct Source {
#[serde(rename = "type")]
/// type of the source
pub s_type: String,
/// source reference, e.g. an OID in case of a nvt type
pub name: String,
/// description about the source
pub description: String,
}

// is used for enumerate handling
Expand Down
55 changes: 24 additions & 31 deletions rust/osp/src/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,36 +344,25 @@ impl From<&ScanResult> for models::ResultType {
("HOST_START", ResultType::Log) => models::ResultType::HostStart,
("HOST_END", ResultType::Log) => models::ResultType::HostEnd,
("DEADHOST", ResultType::Log) => models::ResultType::DeadHost,
(_, ResultType::Log) =>
// is either set on nasl-script as proto or on openvas when
// a host is dead
// we need to clarify if we transform the host detail from
// xml to json as map[string]string or if we just keep it as is
// and let the user handle it
{
if sr.port == "general/Host_Details" {
models::ResultType::HostDetail
} else {
models::ResultType::Log
}
}
("Host Details", ResultType::Log) => models::ResultType::HostDetail,
(_, ResultType::Log) => models::ResultType::Log,
(_, ResultType::Alarm) => models::ResultType::Alarm,
(_, ResultType::Error) => models::ResultType::Error,
// hostdetails are sent via log messages
// host details are sent via log messages
(_, ResultType::HostDetail) => unreachable!(),
}
}
}

#[derive(Deserialize, Debug)]
struct Detail {
name: String,
value: String,
#[derive(Deserialize, Debug, Default)]
struct HostDetail {
detail: Vec<models::Detail>,
}

#[derive(Deserialize, Debug)]
struct HostDetail {
detail: Vec<Detail>,
impl HostDetail {
pub fn extract(&self) -> Option<models::Detail> {
self.detail.first().cloned()
}
}

impl From<&ScanResult> for models::Result {
Expand All @@ -394,14 +383,10 @@ impl From<&ScanResult> for models::Result {
"" => None,
_ => Some(result.description.clone()),
};
let details = match r_type {
let detail = match r_type {
models::ResultType::HostDetail => match urlencoding::decode(&result.description) {
Ok(decoded) => match quick_xml::de::from_str::<HostDetail>(&decoded) {
Ok(details) => details
.detail
.into_iter()
.map(|d| (d.name, d.value))
.collect(),
Ok(details) => details,
Err(_) => Default::default(),
},
Err(_) => Default::default(),
Expand All @@ -424,7 +409,7 @@ impl From<&ScanResult> for models::Result {
oid: Some(result.test_id.clone()),
r_type,
message,
details,
detail: detail.extract(),
}
}
}
Expand Down Expand Up @@ -745,7 +730,7 @@ mod tests {
<scan id="9750f1f8-07aa-49cc-9c31-2f9e469c8f65" target="192.168.1.252" end_time="1432824234" progress="100" status="finished" start_time="1432824206">
<results>
<result name="HOST_START" type="Log Message" severity="0.0" host="127.0.0.1" hostname="" test_id="" port="" qod="" uri="">Mon May 8 09:24:07 2023</result>
<result name="SSL/TLS: Collect and Report Certificate Details" type="Log Message" severity="0.0" host="127.0.0.1" hostname="localhost" test_id="1.3.6.1.4.1.25623.1.0.103692" port="general/Host_Details" qod="98" uri="">&lt;host&gt;&lt;detail&gt;&lt;name&gt;test&lt;/name&gt;&lt;value&gt;bla&lt;/value&gt;&lt;source&gt;&lt;type&gt;nvt&lt;/type&gt;&lt;name&gt;1.3.6.1.4.1.25623.1.0.103692&lt;/name&gt;&lt;description&gt;SSL/TLS Certificate&lt;/description&gt;&lt;/source&gt;&lt;/detail&gt;&lt;/host&gt;
<result name="Host Details" type="Log Message" severity="0.0" host="127.0.0.1" hostname="localhost" test_id="1.3.6.1.4.1.25623.1.0.103692" port="general/Host_Details" qod="80" uri="">&lt;host&gt;&lt;detail&gt;&lt;name&gt;test&lt;/name&gt;&lt;value&gt;bla&lt;/value&gt;&lt;source&gt;&lt;type&gt;nvt&lt;/type&gt;&lt;name&gt;1.3.6.1.4.1.25623.1.0.103692&lt;/name&gt;&lt;description&gt;SSL/TLS Certificate&lt;/description&gt;&lt;/source&gt;&lt;/detail&gt;&lt;/host&gt;
</result>
<result name="HOST_END" type="Log Message" severity="0.0" host="127.0.0.1" hostname="" test_id="" port="" qod="" uri="">Mon May 8 09:31:41 2023</result>
</results>
Expand All @@ -768,7 +753,7 @@ mod tests {
<get_scans_response status_text="OK" status="200">
<scan id="9750f1f8-07aa-49cc-9c31-2f9e469c8f65" target="192.168.1.252" end_time="1432824234" progress="100" status="finished" start_time="1432824206">
<results>
<result name="SSL/TLS: Collect and Report Certificate Details" type="Log Message" severity="0.0" host="127.0.0.1" hostname="localhost" test_id="1.3.6.1.4.1.25623.1.0.103692" port="general/Host_Details" qod="98" uri="">&lt;host&gt;&lt;detail&gt;&lt;name&gt;test&lt;/name&gt;&lt;value&gt;bla&lt;/value&gt;&lt;source&gt;&lt;type&gt;nvt&lt;/type&gt;&lt;name&gt;1.3.6.1.4.1.25623.1.0.103692&lt;/name&gt;&lt;description&gt;SSL/TLS Certificate&lt;/description&gt;&lt;/source&gt;&lt;/detail&gt;&lt;/host&gt;
<result name="Host Details" type="Log Message" severity="0.0" host="127.0.0.1" hostname="localhost" test_id="1.3.6.1.4.1.25623.1.0.103692" port="general/Host_Details" qod="80" uri="">&lt;host&gt;&lt;detail&gt;&lt;name&gt;test&lt;/name&gt;&lt;value&gt;bla&lt;/value&gt;&lt;source&gt;&lt;type&gt;nvt&lt;/type&gt;&lt;name&gt;1.3.6.1.4.1.25623.1.0.103692&lt;/name&gt;&lt;description&gt;SSL/TLS Certificate&lt;/description&gt;&lt;/source&gt;&lt;/detail&gt;&lt;/host&gt;
</result>
</results>
</scan>
Expand All @@ -778,6 +763,14 @@ mod tests {
let results: Vec<models::Result> = response.try_into().unwrap();
assert_eq!(results.len(), 1);
let result = results.first().unwrap();
assert_eq!(result.details["test"], "bla");
let detail = result.detail.clone().unwrap();
assert_eq!(detail.name, "test".to_string());
assert_eq!(detail.value, "bla".to_string());
assert_eq!(detail.source.s_type, "nvt".to_string());
assert_eq!(
detail.source.name,
"1.3.6.1.4.1.25623.1.0.103692".to_string()
);
assert_eq!(detail.source.description, "SSL/TLS Certificate".to_string());
}
}

0 comments on commit b12152b

Please sign in to comment.