From a0f473de85a70c7e04440539ef62f70638e6907b Mon Sep 17 00:00:00 2001 From: Johanah LEKEU Date: Fri, 15 Nov 2024 14:14:42 +0100 Subject: [PATCH] add conditional rendering details --- .../atomic_testing/AtomicTestingDetail.tsx | 92 +------ .../AtomicTestingPayloadInfo.tsx | 150 ++++++++-- openbas-front/src/utils/api-types.d.ts | 257 ++++++++++++++---- .../io/openbas/database/model/Payload.java | 18 ++ 4 files changed, 346 insertions(+), 171 deletions(-) diff --git a/openbas-front/src/admin/components/atomic_testings/atomic_testing/AtomicTestingDetail.tsx b/openbas-front/src/admin/components/atomic_testings/atomic_testing/AtomicTestingDetail.tsx index e73c360bd7..814915ac54 100644 --- a/openbas-front/src/admin/components/atomic_testings/atomic_testing/AtomicTestingDetail.tsx +++ b/openbas-front/src/admin/components/atomic_testings/atomic_testing/AtomicTestingDetail.tsx @@ -5,6 +5,7 @@ import { FunctionComponent, useContext } from 'react'; import { useFormatter } from '../../../../components/i18n'; import ItemStatus from '../../../../components/ItemStatus'; +import { InjectResultOverviewOutputContext, InjectResultOverviewOutputContextType } from '../InjectResultOverviewOutputContext'; const useStyles = makeStyles(() => ({ paper: { @@ -23,7 +24,7 @@ const useStyles = makeStyles(() => ({ const AtomicTestingDetail: FunctionComponent = () => { const classes = useStyles(); - const { t, tPick } = useFormatter(); + const { t } = useFormatter(); // Fetching data const { injectResultOverviewOutput } = useContext(InjectResultOverviewOutputContext); @@ -31,95 +32,6 @@ const AtomicTestingDetail: FunctionComponent = () => { return ( - {t('Configuration')} - {injectResultOverviewOutput ? ( - - - - - {t('Description')} - - - {injectResultOverviewOutput?.inject_description || '-'} - - - - - {t('Type')} - - - {tPick(injectResultOverviewOutput.inject_injector_contract?.injector_contract_labels)} - - - - - {t('Expectations')} - - { - injectResultOverviewOutput.inject_expectations !== undefined && injectResultOverviewOutput.inject_expectations.length > 0 - ? Array.from(new Set(injectResultOverviewOutput.inject_expectations.map(expectation => expectation.inject_expectation_name))) - .map((name, index) => ( - - {name} - - )) - : ( - - - - - ) - } - - - - ) : ( - - {t('No data available')} - - )} - - {injectResultOverviewOutput?.inject_commands_lines && ( - - {t('Command Lines')} - - - {t('Attack command')} - - {(injectResultOverviewOutput.inject_commands_lines?.content?.length ?? 0) > 0 ? ( -
-                
-                  {injectResultOverviewOutput.inject_commands_lines?.content?.map((content, index) => (
-                    
  • {content}
  • - ))} -
    -
    - ) : '-'} - - {t('Cleanup command')} - - {(injectResultOverviewOutput.inject_commands_lines?.cleanup_command?.length ?? 0) > 0 ? ( -
    -                
    -                  {injectResultOverviewOutput.inject_commands_lines?.cleanup_command?.map((content, index) => (
    -                    
  • {content}
  • - ))} -
    -
    - ) : '-'} - - {t('External ID')} - - {injectResultOverviewOutput.inject_commands_lines?.external_id ? ( -
    -                
    -                  {injectResultOverviewOutput.inject_commands_lines?.external_id}
    -                
    -              
    - ) : '-'} -
    -
    - )} - {t('Execution logs')} {injectResultOverviewOutput ? ( diff --git a/openbas-front/src/admin/components/atomic_testings/atomic_testing/AtomicTestingPayloadInfo.tsx b/openbas-front/src/admin/components/atomic_testings/atomic_testing/AtomicTestingPayloadInfo.tsx index 69ad8a8f70..01435b1826 100644 --- a/openbas-front/src/admin/components/atomic_testings/atomic_testing/AtomicTestingPayloadInfo.tsx +++ b/openbas-front/src/admin/components/atomic_testings/atomic_testing/AtomicTestingPayloadInfo.tsx @@ -3,12 +3,10 @@ import { makeStyles } from '@mui/styles'; import { Props } from 'html-react-parser/lib/attributes-to-props'; import { FunctionComponent, useContext } from 'react'; -import { AttackPatternHelper } from '../../../../actions/attack_patterns/attackpattern-helper'; import { useFormatter } from '../../../../components/i18n'; import ItemCopy from '../../../../components/ItemCopy'; import ItemTags from '../../../../components/ItemTags'; import PlatformIcon from '../../../../components/PlatformIcon'; -import { useHelper } from '../../../../store'; import { AttackPattern, PayloadArgument, PayloadPrerequisite } from '../../../../utils/api-types'; import { emptyFilled } from '../../../../utils/String'; import { InjectResultDtoContext, InjectResultDtoContextType } from '../InjectResultDtoContext'; @@ -132,26 +130,134 @@ const AtomicTestingPayloadInfo: FunctionComponent = () => { {t('Commands')} {injectResultDto ? ( - - {t('Command executor')} - - {/* {injectResultDto?.inject_injector_contract?.injector_contract_payload?.} */} - - {t('Attack commands')} - -
    -              {/*  */}
    -            
    + {injectResultDto?.inject_injector_contract?.injector_contract_payload?.payload_type === 'Command' && ( + <> + + {t('Command executor')} + + {injectResultDto?.inject_injector_contract?.injector_contract_payload?.command_executor} + + {t('Attack commands')} + +
    +                  
    +                
    + + )} + {injectResultDto?.inject_injector_contract?.injector_contract_payload?.payload_type === 'Executable' && ( + <> + + {t('Executable files')} + + { + injectResultDto?.inject_injector_contract?.injector_contract_payload?.executable_file !== undefined + ? ( + + {injectResultDto?.inject_injector_contract?.injector_contract_payload?.executable_file?.document_name ?? '-'} + + ) + : ( + + - + + ) + } + + {t('Architecture')} + + {injectResultDto?.inject_injector_contract?.injector_contract_payload?.executable_arch} + + )} + {injectResultDto?.inject_injector_contract?.injector_contract_payload?.payload_type === 'File' && ( + <> + + {t('File drop file')} + + { + injectResultDto?.inject_injector_contract?.injector_contract_payload?.file_drop_file !== undefined + ? ( + + {injectResultDto?.inject_injector_contract?.injector_contract_payload?.file_drop_file?.document_name ?? '-'} + + ) + : ( + + - + + ) + } + + )} + {injectResultDto?.inject_injector_contract?.injector_contract_payload?.payload_type === 'Dns' && ( + <> + + {t('Dns resolution hostname')} + + {injectResultDto?.inject_injector_contract?.injector_contract_payload?.dns_resolution_hostname} + + )} + {injectResultDto?.inject_injector_contract?.injector_contract_payload?.payload_type === 'Network' && ( + <> + + {t('Network traffic ip destination')} + + {injectResultDto?.inject_injector_contract?.injector_contract_payload?.network_traffic_ip_dst} + + {t('Network traffic port destination')} + + {injectResultDto?.inject_injector_contract?.injector_contract_payload?.network_traffic_port_dst} + + {t('Network traffic ip source')} + + {injectResultDto?.inject_injector_contract?.injector_contract_payload?.network_traffic_ip_src} + + {t('Network traffic port source')} + + {injectResultDto?.inject_injector_contract?.injector_contract_payload?.network_traffic_port_src} + + {t('Network traffic protocol')} + + {injectResultDto?.inject_injector_contract?.injector_contract_payload?.network_traffic_protocol} + + )} = { + payload_type: Key; +} & Type; + export interface Challenge { challenge_category?: string; challenge_content?: string; @@ -432,6 +462,34 @@ export interface ComcheckStatus { listened?: boolean; } +export interface Command { + command_content: string; + command_executor: string; + listened?: boolean; + payload_arguments?: PayloadArgument[]; + payload_attack_patterns?: AttackPattern[]; + payload_cleanup_command?: string; + payload_cleanup_executor?: string; + payload_collector?: Collector; + payload_collector_type?: string; + /** @format date-time */ + payload_created_at: string; + payload_description?: string; + payload_elevation_required?: boolean; + payload_external_id?: string; + payload_id: string; + payload_name: string; + payload_platforms?: ("Linux" | "Windows" | "MacOS" | "Container" | "Service" | "Generic" | "Internal" | "Unknown")[]; + payload_prerequisites?: PayloadPrerequisite[]; + payload_source: "COMMUNITY" | "FILIGRAN" | "MANUAL"; + payload_status: "UNVERIFIED" | "VERIFIED"; + /** @uniqueItems true */ + payload_tags?: Tag[]; + payload_type?: string; + /** @format date-time */ + payload_updated_at: string; +} + export interface Communication { communication_ack?: boolean; communication_animation?: boolean; @@ -478,6 +536,33 @@ export interface DirectInjectInput { inject_users?: string[]; } +export interface DnsResolution { + dns_resolution_hostname: string; + listened?: boolean; + payload_arguments?: PayloadArgument[]; + payload_attack_patterns?: AttackPattern[]; + payload_cleanup_command?: string; + payload_cleanup_executor?: string; + payload_collector?: Collector; + payload_collector_type?: string; + /** @format date-time */ + payload_created_at: string; + payload_description?: string; + payload_elevation_required?: boolean; + payload_external_id?: string; + payload_id: string; + payload_name: string; + payload_platforms?: ("Linux" | "Windows" | "MacOS" | "Container" | "Service" | "Generic" | "Internal" | "Unknown")[]; + payload_prerequisites?: PayloadPrerequisite[]; + payload_source: "COMMUNITY" | "FILIGRAN" | "MANUAL"; + payload_status: "UNVERIFIED" | "VERIFIED"; + /** @uniqueItems true */ + payload_tags?: Tag[]; + payload_type?: string; + /** @format date-time */ + payload_updated_at: string; +} + export interface Document { document_description?: string; /** @uniqueItems true */ @@ -526,19 +611,15 @@ export interface DryInjectStatus { listened?: boolean; status_id?: string; status_name?: + | "SUCCESS" + | "ERROR" + | "MAYBE_PREVENTED" | "DRAFT" - | "INFO" | "QUEUING" | "EXECUTING" | "PENDING" | "PARTIAL" - | "ERROR" - | "WARNING" - | "COMMAND_NOT_FOUND" - | "COMMAND_CANNOT_BE_EXECUTED" - | "MAYBE_PARTIAL_PREVENTED" - | "MAYBE_PREVENTED" - | "SUCCESS"; + | "MAYBE_PARTIAL_PREVENTED"; status_traces?: InjectStatusExecution[]; /** @format date-time */ tracking_ack_date?: string; @@ -666,6 +747,34 @@ export interface EvaluationInput { evaluation_score?: number; } +export interface Executable { + executable_arch: "x86_64" | "arm64" | "Unknown"; + executable_file?: Document; + listened?: boolean; + payload_arguments?: PayloadArgument[]; + payload_attack_patterns?: AttackPattern[]; + payload_cleanup_command?: string; + payload_cleanup_executor?: string; + payload_collector?: Collector; + payload_collector_type?: string; + /** @format date-time */ + payload_created_at: string; + payload_description?: string; + payload_elevation_required?: boolean; + payload_external_id?: string; + payload_id: string; + payload_name: string; + payload_platforms?: ("Linux" | "Windows" | "MacOS" | "Container" | "Service" | "Generic" | "Internal" | "Unknown")[]; + payload_prerequisites?: PayloadPrerequisite[]; + payload_source: "COMMUNITY" | "FILIGRAN" | "MANUAL"; + payload_status: "UNVERIFIED" | "VERIFIED"; + /** @uniqueItems true */ + payload_tags?: Tag[]; + payload_type?: string; + /** @format date-time */ + payload_updated_at: string; +} + export interface Executor { /** @format date-time */ executor_created_at: string; @@ -907,6 +1016,33 @@ export interface ExportMapperInput { ids_to_export: string[]; } +export interface FileDrop { + file_drop_file?: Document; + listened?: boolean; + payload_arguments?: PayloadArgument[]; + payload_attack_patterns?: AttackPattern[]; + payload_cleanup_command?: string; + payload_cleanup_executor?: string; + payload_collector?: Collector; + payload_collector_type?: string; + /** @format date-time */ + payload_created_at: string; + payload_description?: string; + payload_elevation_required?: boolean; + payload_external_id?: string; + payload_id: string; + payload_name: string; + payload_platforms?: ("Linux" | "Windows" | "MacOS" | "Container" | "Service" | "Generic" | "Internal" | "Unknown")[]; + payload_prerequisites?: PayloadPrerequisite[]; + payload_source: "COMMUNITY" | "FILIGRAN" | "MANUAL"; + payload_status: "UNVERIFIED" | "VERIFIED"; + /** @uniqueItems true */ + payload_tags?: Tag[]; + payload_type?: string; + /** @format date-time */ + payload_updated_at: string; +} + export interface Filter { key: string; mode?: "and" | "or"; @@ -1335,19 +1471,15 @@ export interface InjectStatus { status_commands_lines?: InjectStatusCommandLine; status_id?: string; status_name: + | "SUCCESS" + | "ERROR" + | "MAYBE_PREVENTED" | "DRAFT" - | "INFO" | "QUEUING" | "EXECUTING" | "PENDING" | "PARTIAL" - | "ERROR" - | "WARNING" - | "COMMAND_NOT_FOUND" - | "COMMAND_CANNOT_BE_EXECUTED" - | "MAYBE_PARTIAL_PREVENTED" - | "MAYBE_PREVENTED" - | "SUCCESS"; + | "MAYBE_PARTIAL_PREVENTED"; status_traces?: InjectStatusExecution[]; /** @format date-time */ tracking_ack_date?: string; @@ -1378,19 +1510,14 @@ export interface InjectStatusExecution { execution_duration?: number; execution_message?: string; execution_status?: - | "DRAFT" - | "INFO" - | "QUEUING" - | "EXECUTING" - | "PENDING" - | "PARTIAL" + | "SUCCESS" | "ERROR" - | "WARNING" + | "MAYBE_PREVENTED" + | "INFO" | "COMMAND_NOT_FOUND" | "COMMAND_CANNOT_BE_EXECUTED" - | "MAYBE_PARTIAL_PREVENTED" - | "MAYBE_PREVENTED" - | "SUCCESS"; + | "WARNING" + | "ASSET_INACTIVE"; /** @format date-time */ execution_time?: string; } @@ -1448,19 +1575,15 @@ export interface InjectTestStatus { listened?: boolean; status_id?: string; status_name: + | "SUCCESS" + | "ERROR" + | "MAYBE_PREVENTED" | "DRAFT" - | "INFO" | "QUEUING" | "EXECUTING" | "PENDING" | "PARTIAL" - | "ERROR" - | "WARNING" - | "COMMAND_NOT_FOUND" - | "COMMAND_CANNOT_BE_EXECUTED" - | "MAYBE_PARTIAL_PREVENTED" - | "MAYBE_PREVENTED" - | "SUCCESS"; + | "MAYBE_PARTIAL_PREVENTED"; status_traces?: InjectStatusExecution[]; /** @format date-time */ tracking_ack_date?: string; @@ -1933,6 +2056,39 @@ export interface MitigationUpsertInput { mitigations?: MitigationCreateInput[]; } +export interface NetworkTraffic { + listened?: boolean; + network_traffic_ip_dst: string; + network_traffic_ip_src: string; + /** @format int32 */ + network_traffic_port_dst: number; + /** @format int32 */ + network_traffic_port_src: number; + network_traffic_protocol: string; + payload_arguments?: PayloadArgument[]; + payload_attack_patterns?: AttackPattern[]; + payload_cleanup_command?: string; + payload_cleanup_executor?: string; + payload_collector?: Collector; + payload_collector_type?: string; + /** @format date-time */ + payload_created_at: string; + payload_description?: string; + payload_elevation_required?: boolean; + payload_external_id?: string; + payload_id: string; + payload_name: string; + payload_platforms?: ("Linux" | "Windows" | "MacOS" | "Container" | "Service" | "Generic" | "Internal" | "Unknown")[]; + payload_prerequisites?: PayloadPrerequisite[]; + payload_source: "COMMUNITY" | "FILIGRAN" | "MANUAL"; + payload_status: "UNVERIFIED" | "VERIFIED"; + /** @uniqueItems true */ + payload_tags?: Tag[]; + payload_type?: string; + /** @format date-time */ + payload_updated_at: string; +} + export interface OAuthProvider { provider_login?: string; provider_name?: string; @@ -2422,31 +2578,14 @@ export interface Pause { pause_exercise?: Exercise; } -export interface Payload { - listened?: boolean; - payload_arguments?: PayloadArgument[]; - payload_attack_patterns?: AttackPattern[]; - payload_cleanup_command?: string; - payload_cleanup_executor?: string; - payload_collector?: Collector; - payload_collector_type?: string; - /** @format date-time */ - payload_created_at: string; - payload_description?: string; - payload_elevation_required?: boolean; - payload_external_id?: string; - payload_id: string; - payload_name: string; - payload_platforms?: ("Linux" | "Windows" | "MacOS" | "Container" | "Service" | "Generic" | "Internal" | "Unknown")[]; - payload_prerequisites?: PayloadPrerequisite[]; - payload_source: "COMMUNITY" | "FILIGRAN" | "MANUAL"; - payload_status: "UNVERIFIED" | "VERIFIED"; - /** @uniqueItems true */ - payload_tags?: Tag[]; - payload_type?: string; - /** @format date-time */ - payload_updated_at: string; -} +export type Payload = BasePayload & + ( + | BasePayloadPayloadTypeMapping<"Command", Command> + | BasePayloadPayloadTypeMapping<"Executable", Executable> + | BasePayloadPayloadTypeMapping<"File", FileDrop> + | BasePayloadPayloadTypeMapping<"Dns", DnsResolution> + | BasePayloadPayloadTypeMapping<"Network", NetworkTraffic> + ); export interface PayloadArgument { default_value: string; diff --git a/openbas-model/src/main/java/io/openbas/database/model/Payload.java b/openbas-model/src/main/java/io/openbas/database/model/Payload.java index c93b24b69d..834451572b 100644 --- a/openbas-model/src/main/java/io/openbas/database/model/Payload.java +++ b/openbas-model/src/main/java/io/openbas/database/model/Payload.java @@ -14,6 +14,8 @@ import io.openbas.helper.MonoIdDeserializer; import io.openbas.helper.MultiIdListDeserializer; import io.openbas.helper.MultiIdSetDeserializer; +import io.swagger.v3.oas.annotations.media.DiscriminatorMapping; +import io.swagger.v3.oas.annotations.media.Schema; import jakarta.persistence.*; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; @@ -31,6 +33,22 @@ @Inheritance(strategy = InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name = "payload_type", discriminatorType = STRING) @EntityListeners(ModelBaseListener.class) +@Schema( + discriminatorProperty = "payload_type", + oneOf = { + Command.class, + Executable.class, + FileDrop.class, + DnsResolution.class, + NetworkTraffic.class + }, + discriminatorMapping = { + @DiscriminatorMapping(value = "Command", schema = Command.class), + @DiscriminatorMapping(value = "Executable", schema = Executable.class), + @DiscriminatorMapping(value = "File", schema = FileDrop.class), + @DiscriminatorMapping(value = "Dns", schema = DnsResolution.class), + @DiscriminatorMapping(value = "Network", schema = NetworkTraffic.class) + }) public class Payload implements Base { public enum PAYLOAD_SOURCE {