Skip to content

Commit

Permalink
expose affected tags in API
Browse files Browse the repository at this point in the history
  • Loading branch information
WebFreak001 committed Mar 21, 2024
1 parent 4e00844 commit fb8e554
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 46 deletions.
184 changes: 144 additions & 40 deletions kraken/src/api/handler/finding_affected/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use rorm::update;
use crate::api::extractors::SessionUser;
use crate::api::handler::common::error::ApiError;
use crate::api::handler::common::error::ApiResult;
use crate::api::handler::common::schema::SimpleTag;
use crate::api::handler::domains::schema::SimpleDomain;
use crate::api::handler::finding_affected::schema::CreateFindingAffectedRequest;
use crate::api::handler::finding_affected::schema::FindingAffectedObject;
Expand All @@ -30,13 +31,23 @@ use crate::api::handler::services::schema::SimpleService;
use crate::chan::global::GLOBAL;
use crate::chan::ws_manager::schema::WsMessage;
use crate::models::Domain;
use crate::models::DomainGlobalTag;
use crate::models::DomainWorkspaceTag;
use crate::models::Finding;
use crate::models::FindingAffected;
use crate::models::FindingDetails;
use crate::models::GlobalTag;
use crate::models::Host;
use crate::models::HostGlobalTag;
use crate::models::HostWorkspaceTag;
use crate::models::Port;
use crate::models::PortGlobalTag;
use crate::models::PortWorkspaceTag;
use crate::models::Service;
use crate::models::ServiceGlobalTag;
use crate::models::ServiceWorkspaceTag;
use crate::models::Workspace;
use crate::models::WorkspaceTag;
use crate::modules::cache::EditorCached;

/// Add a new affected object to a finding
Expand Down Expand Up @@ -194,69 +205,161 @@ pub async fn get_finding_affected(
.try_collect()
.await?;

let affected = match (domain, host, port, service) {
let (affected, affected_tags) = match (domain, host, port, service) {
(Some(fm), None, None, None) => {
let domain = query!(&mut tx, Domain)
.condition(Domain::F.uuid.equals(*fm.key()))
.one()
.await?;
FindingAffectedObject::Domain(SimpleDomain {
uuid: domain.uuid,
domain: domain.domain,
comment: domain.comment,
workspace: *domain.workspace.key(),
created_at: domain.created_at,
certainty: domain.certainty,
})

let mut tags: Vec<_> = query!(&mut tx, (DomainGlobalTag::F.global_tag as GlobalTag,))
.condition(DomainGlobalTag::F.domain.equals(domain.uuid))
.stream()
.map_ok(|(tag,)| SimpleTag::from(tag))
.try_collect()
.await?;

let global_tags: Vec<_> = query!(
&mut tx,
(DomainWorkspaceTag::F.workspace_tag as WorkspaceTag,)
)
.condition(DomainWorkspaceTag::F.domain.equals(domain.uuid))
.stream()
.map_ok(|(tag,)| SimpleTag::from(tag))
.try_collect()
.await?;

tags.extend(global_tags);

(
FindingAffectedObject::Domain(SimpleDomain {
uuid: domain.uuid,
domain: domain.domain,
comment: domain.comment,
workspace: *domain.workspace.key(),
created_at: domain.created_at,
certainty: domain.certainty,
}),
tags,
)
}
(None, Some(fm), None, None) => {
let host = query!(&mut tx, Host)
.condition(Host::F.uuid.equals(*fm.key()))
.one()
.await?;
FindingAffectedObject::Host(SimpleHost {
uuid: host.uuid,
ip_addr: host.ip_addr.ip(),
os_type: host.os_type,
response_time: host.response_time,
comment: host.comment,
workspace: *host.workspace.key(),
created_at: host.created_at,
certainty: host.certainty,
})

let mut tags: Vec<_> = query!(&mut tx, (HostGlobalTag::F.global_tag as GlobalTag,))
.condition(HostGlobalTag::F.host.equals(host.uuid))
.stream()
.map_ok(|(tag,)| SimpleTag::from(tag))
.try_collect()
.await?;

let global_tags: Vec<_> = query!(
&mut tx,
(HostWorkspaceTag::F.workspace_tag as WorkspaceTag,)
)
.condition(HostWorkspaceTag::F.host.equals(host.uuid))
.stream()
.map_ok(|(tag,)| SimpleTag::from(tag))
.try_collect()
.await?;

tags.extend(global_tags);

(
FindingAffectedObject::Host(SimpleHost {
uuid: host.uuid,
ip_addr: host.ip_addr.ip(),
os_type: host.os_type,
response_time: host.response_time,
comment: host.comment,
workspace: *host.workspace.key(),
created_at: host.created_at,
certainty: host.certainty,
}),
tags,
)
}
(None, None, Some(fm), None) => {
let port = query!(&mut tx, Port)
.condition(Port::F.uuid.equals(*fm.key()))
.one()
.await?;
FindingAffectedObject::Port(SimplePort {
uuid: port.uuid,
port: port.port as u16,
protocol: port.protocol,
certainty: port.certainty,
host: *port.host.key(),
comment: port.comment,
workspace: *port.workspace.key(),
created_at: port.created_at,
})

let mut tags: Vec<_> = query!(&mut tx, (PortGlobalTag::F.global_tag as GlobalTag,))
.condition(PortGlobalTag::F.port.equals(port.uuid))
.stream()
.map_ok(|(tag,)| SimpleTag::from(tag))
.try_collect()
.await?;

let global_tags: Vec<_> = query!(
&mut tx,
(PortWorkspaceTag::F.workspace_tag as WorkspaceTag,)
)
.condition(PortWorkspaceTag::F.port.equals(port.uuid))
.stream()
.map_ok(|(tag,)| SimpleTag::from(tag))
.try_collect()
.await?;

tags.extend(global_tags);

(
FindingAffectedObject::Port(SimplePort {
uuid: port.uuid,
port: port.port as u16,
protocol: port.protocol,
certainty: port.certainty,
host: *port.host.key(),
comment: port.comment,
workspace: *port.workspace.key(),
created_at: port.created_at,
}),
tags,
)
}
(None, None, None, Some(fm)) => {
let service = query!(&mut tx, Service)
.condition(Service::F.uuid.equals(*fm.key()))
.one()
.await?;
FindingAffectedObject::Service(SimpleService {
uuid: service.uuid,
name: service.name,
version: service.version,
certainty: service.certainty,
host: *service.host.key(),
port: service.port.map(|fm| *fm.key()),
comment: service.comment,
workspace: *service.workspace.key(),
created_at: service.created_at,
})

let mut tags: Vec<_> = query!(&mut tx, (ServiceGlobalTag::F.global_tag as GlobalTag,))
.condition(ServiceGlobalTag::F.service.equals(service.uuid))
.stream()
.map_ok(|(tag,)| SimpleTag::from(tag))
.try_collect()
.await?;

let global_tags: Vec<_> = query!(
&mut tx,
(ServiceWorkspaceTag::F.workspace_tag as WorkspaceTag,)
)
.condition(ServiceWorkspaceTag::F.service.equals(service.uuid))
.stream()
.map_ok(|(tag,)| SimpleTag::from(tag))
.try_collect()
.await?;

tags.extend(global_tags);

(
FindingAffectedObject::Service(SimpleService {
uuid: service.uuid,
name: service.name,
version: service.version,
certainty: service.certainty,
host: *service.host.key(),
port: service.port.map(|fm| *fm.key()),
comment: service.comment,
workspace: *service.workspace.key(),
created_at: service.created_at,
}),
tags,
)
}
_ => return Err(ApiError::InternalServerError),
};
Expand All @@ -282,6 +385,7 @@ pub async fn get_finding_affected(
created_at: finding.created_at,
},
affected,
affected_tags,
#[rustfmt::skip]
user_details: GLOBAL.editor_cache.finding_affected_details.get(finding_affected_uuid).await?.unwrap_or_default().0,
tool_details: details.as_mut().and_then(|d| d.tool_details.take()),
Expand Down
4 changes: 4 additions & 0 deletions kraken/src/api/handler/finding_affected/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use utoipa::ToSchema;
use uuid::Uuid;

use crate::api::handler::common::de_optional;
use crate::api::handler::common::schema::SimpleTag;
use crate::api::handler::domains::schema::SimpleDomain;
use crate::api::handler::findings::schema::FullFinding;
use crate::api::handler::hosts::schema::SimpleHost;
Expand Down Expand Up @@ -66,6 +67,9 @@ pub struct FullFindingAffected {
/// The affected object
pub affected: FindingAffectedObject,

/// List of tags for the affected object
pub affected_tags: Vec<SimpleTag>,

/// Notes about the finding provided by the user
///
/// May be used for documenting command invocation or other information
Expand Down
13 changes: 7 additions & 6 deletions kraken_frontend/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -9706,13 +9706,14 @@
"FullFindingAffected": {
"type": "object",
"description": "An affected object's details and the finding it is affected by",
"required": ["finding", "affected", "user_details", "created_at"],
"required": ["finding", "affected", "affected_tags", "user_details", "created_at"],
"properties": {
"finding": {
"$ref": "#/components/schemas/FullFinding"
},
"affected": {
"$ref": "#/components/schemas/FindingAffectedObject"
"finding": { "$ref": "#/components/schemas/FullFinding" },
"affected": { "$ref": "#/components/schemas/FindingAffectedObject" },
"affected_tags": {
"type": "array",
"items": { "$ref": "#/components/schemas/SimpleTag" },
"description": "List of tags for the affected object"
},
"user_details": {
"type": "string",
Expand Down
15 changes: 15 additions & 0 deletions kraken_frontend/src/api/generated/models/FullFindingAffected.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ import {
FullFindingFromJSONTyped,
FullFindingToJSON,
} from './FullFinding';
import type { SimpleTag } from './SimpleTag';
import {
SimpleTagFromJSON,
SimpleTagFromJSONTyped,
SimpleTagToJSON,
} from './SimpleTag';

/**
* An affected object's details and the finding it is affected by
Expand All @@ -44,6 +50,12 @@ export interface FullFindingAffected {
* @memberof FullFindingAffected
*/
affected: FindingAffectedObject;
/**
* List of tags for the affected object
* @type {Array<SimpleTag>}
* @memberof FullFindingAffected
*/
affectedTags: Array<SimpleTag>;
/**
* Notes about the finding provided by the user
*
Expand Down Expand Up @@ -88,6 +100,7 @@ export function instanceOfFullFindingAffected(value: object): boolean {
let isInstance = true;
isInstance = isInstance && "finding" in value;
isInstance = isInstance && "affected" in value;
isInstance = isInstance && "affectedTags" in value;
isInstance = isInstance && "userDetails" in value;
isInstance = isInstance && "createdAt" in value;

Expand All @@ -106,6 +119,7 @@ export function FullFindingAffectedFromJSONTyped(json: any, ignoreDiscriminator:

'finding': FullFindingFromJSON(json['finding']),
'affected': FindingAffectedObjectFromJSON(json['affected']),
'affectedTags': ((json['affected_tags'] as Array<any>).map(SimpleTagFromJSON)),
'userDetails': json['user_details'],
'toolDetails': !exists(json, 'tool_details') ? undefined : json['tool_details'],
'screenshot': !exists(json, 'screenshot') ? undefined : json['screenshot'],
Expand All @@ -125,6 +139,7 @@ export function FullFindingAffectedToJSON(value?: FullFindingAffected | null): a

'finding': FullFindingToJSON(value.finding),
'affected': FindingAffectedObjectToJSON(value.affected),
'affected_tags': ((value.affectedTags as Array<any>).map(SimpleTagToJSON)),
'user_details': value.userDetails,
'tool_details': value.toolDetails,
'screenshot': value.screenshot,
Expand Down

0 comments on commit fb8e554

Please sign in to comment.