From 734fc175a347b018e30895f95835acc01a41f2a1 Mon Sep 17 00:00:00 2001 From: Andrew Macri Date: Wed, 5 Feb 2025 11:35:18 -0500 Subject: [PATCH] [Security Solution] [Attack discovery] Display additional Attack Chain tactics (#209434) ### [Security Solution] [Attack discovery] Display additional Attack Chain tactics This PR updates the Attack discovery _Attack Chain_ allow list to visualize additional tactics (e.g. `Defense Evasion`), as illustarted by the screenshot below: ![attack_chain](https://github.com/user-attachments/assets/afc57cef-bc01-4a67-8028-8528c96e8ced) _Above: The Attack Chain includes `Defense Evasion`, a newly allow listed tactic_ #### Details This PR updates the Attack Chain allow list to include the following additional tactics: - `Resource Development` - `Defense Evasion` - `Credential Access` - `Collection` - `Impact` #### Desk testing 1. Navigate to Security > Attack discovery 2. Click `Generate` to generate Attack discoveries **Expected result** - The Attack Chain visualization includes the additional allow listed tactics noted in the details of this PR 3. Locate an Attack discovery where one of the newly allow listed tactics is red, (which indicates the tactic was part of the attack), and click the `View in AI Assistant` button **Expected result** - A `>` accordion button in the assistant appears next to the selected Attack discovery, indicating it will be included as context 4. Click the `>` button to expand the discovery in the assistant **Expected result** - The expanded `Attack Chain` markdown includes an entry for the newly allow listed tactic, and all other tactics that were colored red in the discovery --- .../index.test.ts | 2 +- .../helpers/get_output_parser/index.test.ts | 2 +- .../server/lib/prompt/prompts.ts | 10 ++++ .../public/attack_discovery/helpers.test.tsx | 8 +++- .../public/attack_discovery/helpers.ts | 20 ++++++++ .../get_attack_discovery_markdown.test.tsx | 46 ++++++++++++++++++- .../attack/attack_chain/index.tsx | 6 +-- .../attack/attack_chain/tactic/index.tsx | 31 ++++--------- .../public/attack_discovery/translations.ts | 34 ++++++++++++++ 9 files changed, 127 insertions(+), 32 deletions(-) diff --git a/x-pack/solutions/security/plugins/elastic_assistant/server/lib/attack_discovery/graphs/default_attack_discovery_graph/nodes/helpers/get_chain_with_format_instructions/index.test.ts b/x-pack/solutions/security/plugins/elastic_assistant/server/lib/attack_discovery/graphs/default_attack_discovery_graph/nodes/helpers/get_chain_with_format_instructions/index.test.ts index 36ed8dc85f09e..ce00651992d2d 100644 --- a/x-pack/solutions/security/plugins/elastic_assistant/server/lib/attack_discovery/graphs/default_attack_discovery_graph/nodes/helpers/get_chain_with_format_instructions/index.test.ts +++ b/x-pack/solutions/security/plugins/elastic_assistant/server/lib/attack_discovery/graphs/default_attack_discovery_graph/nodes/helpers/get_chain_with_format_instructions/index.test.ts @@ -45,7 +45,7 @@ Your output will be parsed and type-checked according to the provided schema ins Here is the JSON Schema instance your output must adhere to. Include the enclosing markdown codeblock: \`\`\`json -{"type":"object","properties":{"insights":{"type":"array","items":{"type":"object","properties":{"alertIds":{"type":"array","items":{"type":"string"},"description":"The alert IDs that the insight is based on."},"detailsMarkdown":{"type":"string","description":"A detailed insight with markdown, where each markdown bullet contains a description of what happened that reads like a story of the attack as it played out and always uses special {{ field.name fieldValue1 fieldValue2 fieldValueN }} syntax for field names and values from the source data. Examples of CORRECT syntax (includes field names and values): {{ host.name hostNameValue }} {{ user.name userNameValue }} {{ source.ip sourceIpValue }} Examples of INCORRECT syntax (bad, because the field names are not included): {{ hostNameValue }} {{ userNameValue }} {{ sourceIpValue }}"},"entitySummaryMarkdown":{"type":"string","description":"A short (no more than a sentence) summary of the insight featuring only the host.name and user.name fields (when they are applicable), using the same {{ field.name fieldValue1 fieldValue2 fieldValueN }} syntax"},"mitreAttackTactics":{"type":"array","items":{"type":"string"},"description":"An array of MITRE ATT&CK tactic for the insight, using one of the following values: Reconnaissance,Initial Access,Execution,Persistence,Privilege Escalation,Discovery,Lateral Movement,Command and Control,Exfiltration"},"summaryMarkdown":{"type":"string","description":"A markdown summary of insight, using the same {{ field.name fieldValue1 fieldValue2 fieldValueN }} syntax"},"title":{"type":"string","description":"A short, no more than 7 words, title for the insight, NOT formatted with special syntax or markdown. This must be as brief as possible."}},"required":["alertIds","detailsMarkdown","summaryMarkdown","title"],"additionalProperties":false},"description":"Insights with markdown that always uses special {{ field.name fieldValue1 fieldValue2 fieldValueN }} syntax for field names and values from the source data. Examples of CORRECT syntax (includes field names and values): {{ host.name hostNameValue }} {{ user.name userNameValue }} {{ source.ip sourceIpValue }} Examples of INCORRECT syntax (bad, because the field names are not included): {{ hostNameValue }} {{ userNameValue }} {{ sourceIpValue }}"}},"required":["insights"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"} +{"type":"object","properties":{"insights":{"type":"array","items":{"type":"object","properties":{"alertIds":{"type":"array","items":{"type":"string"},"description":"The alert IDs that the insight is based on."},"detailsMarkdown":{"type":"string","description":"A detailed insight with markdown, where each markdown bullet contains a description of what happened that reads like a story of the attack as it played out and always uses special {{ field.name fieldValue1 fieldValue2 fieldValueN }} syntax for field names and values from the source data. Examples of CORRECT syntax (includes field names and values): {{ host.name hostNameValue }} {{ user.name userNameValue }} {{ source.ip sourceIpValue }} Examples of INCORRECT syntax (bad, because the field names are not included): {{ hostNameValue }} {{ userNameValue }} {{ sourceIpValue }}"},"entitySummaryMarkdown":{"type":"string","description":"A short (no more than a sentence) summary of the insight featuring only the host.name and user.name fields (when they are applicable), using the same {{ field.name fieldValue1 fieldValue2 fieldValueN }} syntax"},"mitreAttackTactics":{"type":"array","items":{"type":"string"},"description":"An array of MITRE ATT&CK tactic for the insight, using one of the following values: Reconnaissance,Resource Development,Initial Access,Execution,Persistence,Privilege Escalation,Defense Evasion,Credential Access,Discovery,Lateral Movement,Collection,Command and Control,Exfiltration,Impact"},"summaryMarkdown":{"type":"string","description":"A markdown summary of insight, using the same {{ field.name fieldValue1 fieldValue2 fieldValueN }} syntax"},"title":{"type":"string","description":"A short, no more than 7 words, title for the insight, NOT formatted with special syntax or markdown. This must be as brief as possible."}},"required":["alertIds","detailsMarkdown","summaryMarkdown","title"],"additionalProperties":false},"description":"Insights with markdown that always uses special {{ field.name fieldValue1 fieldValue2 fieldValueN }} syntax for field names and values from the source data. Examples of CORRECT syntax (includes field names and values): {{ host.name hostNameValue }} {{ user.name userNameValue }} {{ source.ip sourceIpValue }} Examples of INCORRECT syntax (bad, because the field names are not included): {{ hostNameValue }} {{ userNameValue }} {{ sourceIpValue }}"}},"required":["insights"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"} \`\`\` `; diff --git a/x-pack/solutions/security/plugins/elastic_assistant/server/lib/attack_discovery/graphs/default_attack_discovery_graph/nodes/helpers/get_output_parser/index.test.ts b/x-pack/solutions/security/plugins/elastic_assistant/server/lib/attack_discovery/graphs/default_attack_discovery_graph/nodes/helpers/get_output_parser/index.test.ts index 2fcff45fd3d1c..5d6179aa23009 100644 --- a/x-pack/solutions/security/plugins/elastic_assistant/server/lib/attack_discovery/graphs/default_attack_discovery_graph/nodes/helpers/get_output_parser/index.test.ts +++ b/x-pack/solutions/security/plugins/elastic_assistant/server/lib/attack_discovery/graphs/default_attack_discovery_graph/nodes/helpers/get_output_parser/index.test.ts @@ -39,7 +39,7 @@ Your output will be parsed and type-checked according to the provided schema ins Here is the JSON Schema instance your output must adhere to. Include the enclosing markdown codeblock: \`\`\`json -{"type":"object","properties":{"insights":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"alertIds\":{\"type\":\"array\",\"items\":{\"type\":\"string\"},\"description\":\"The alert IDs that the insight is based on.\"},\"detailsMarkdown\":{\"type\":\"string\",\"description\":\"A detailed insight with markdown, where each markdown bullet contains a description of what happened that reads like a story of the attack as it played out and always uses special {{ field.name fieldValue1 fieldValue2 fieldValueN }} syntax for field names and values from the source data. Examples of CORRECT syntax (includes field names and values): {{ host.name hostNameValue }} {{ user.name userNameValue }} {{ source.ip sourceIpValue }} Examples of INCORRECT syntax (bad, because the field names are not included): {{ hostNameValue }} {{ userNameValue }} {{ sourceIpValue }}\"},\"entitySummaryMarkdown\":{\"type\":\"string\",\"description\":\"A short (no more than a sentence) summary of the insight featuring only the host.name and user.name fields (when they are applicable), using the same {{ field.name fieldValue1 fieldValue2 fieldValueN }} syntax\"},\"mitreAttackTactics\":{\"type\":\"array\",\"items\":{\"type\":\"string\"},\"description\":\"An array of MITRE ATT&CK tactic for the insight, using one of the following values: Reconnaissance,Initial Access,Execution,Persistence,Privilege Escalation,Discovery,Lateral Movement,Command and Control,Exfiltration\"},\"summaryMarkdown\":{\"type\":\"string\",\"description\":\"A markdown summary of insight, using the same {{ field.name fieldValue1 fieldValue2 fieldValueN }} syntax\"},\"title\":{\"type\":\"string\",\"description\":\"A short, no more than 7 words, title for the insight, NOT formatted with special syntax or markdown. This must be as brief as possible.\"}},\"required\":[\"alertIds\",\"detailsMarkdown\",\"summaryMarkdown\",\"title\"],\"additionalProperties\":false},\"description\":\"Insights with markdown that always uses special {{ field.name fieldValue1 fieldValue2 fieldValueN }} syntax for field names and values from the source data. Examples of CORRECT syntax (includes field names and values): {{ host.name hostNameValue }} {{ user.name userNameValue }} {{ source.ip sourceIpValue }} Examples of INCORRECT syntax (bad, because the field names are not included): {{ hostNameValue }} {{ userNameValue }} {{ sourceIpValue }}\"}},\"required\":[\"insights\"],\"additionalProperties":false,\"$schema\":\"http://json-schema.org/draft-07/schema#\"} +{"type":"object","properties":{"insights":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"alertIds\":{\"type\":\"array\",\"items\":{\"type\":\"string\"},\"description\":\"The alert IDs that the insight is based on.\"},\"detailsMarkdown\":{\"type\":\"string\",\"description\":\"A detailed insight with markdown, where each markdown bullet contains a description of what happened that reads like a story of the attack as it played out and always uses special {{ field.name fieldValue1 fieldValue2 fieldValueN }} syntax for field names and values from the source data. Examples of CORRECT syntax (includes field names and values): {{ host.name hostNameValue }} {{ user.name userNameValue }} {{ source.ip sourceIpValue }} Examples of INCORRECT syntax (bad, because the field names are not included): {{ hostNameValue }} {{ userNameValue }} {{ sourceIpValue }}\"},\"entitySummaryMarkdown\":{\"type\":\"string\",\"description\":\"A short (no more than a sentence) summary of the insight featuring only the host.name and user.name fields (when they are applicable), using the same {{ field.name fieldValue1 fieldValue2 fieldValueN }} syntax\"},\"mitreAttackTactics\":{\"type\":\"array\",\"items\":{\"type\":\"string\"},\"description\":\"An array of MITRE ATT&CK tactic for the insight, using one of the following values: Reconnaissance,Resource Development,Initial Access,Execution,Persistence,Privilege Escalation,Defense Evasion,Credential Access,Discovery,Lateral Movement,Collection,Command and Control,Exfiltration,Impact"},\"summaryMarkdown\":{\"type\":\"string\",\"description\":\"A markdown summary of insight, using the same {{ field.name fieldValue1 fieldValue2 fieldValueN }} syntax\"},\"title\":{\"type\":\"string\",\"description\":\"A short, no more than 7 words, title for the insight, NOT formatted with special syntax or markdown. This must be as brief as possible.\"}},\"required\":[\"alertIds\",\"detailsMarkdown\",\"summaryMarkdown\",\"title\"],\"additionalProperties\":false},\"description\":\"Insights with markdown that always uses special {{ field.name fieldValue1 fieldValue2 fieldValueN }} syntax for field names and values from the source data. Examples of CORRECT syntax (includes field names and values): {{ host.name hostNameValue }} {{ user.name userNameValue }} {{ source.ip sourceIpValue }} Examples of INCORRECT syntax (bad, because the field names are not included): {{ hostNameValue }} {{ userNameValue }} {{ sourceIpValue }}\"}},\"required\":[\"insights\"],\"additionalProperties":false,\"$schema\":\"http://json-schema.org/draft-07/schema#\"} \`\`\` `; diff --git a/x-pack/solutions/security/plugins/elastic_assistant/server/lib/prompt/prompts.ts b/x-pack/solutions/security/plugins/elastic_assistant/server/lib/prompt/prompts.ts index 3d931ab83eab1..706288b96659f 100644 --- a/x-pack/solutions/security/plugins/elastic_assistant/server/lib/prompt/prompts.ts +++ b/x-pack/solutions/security/plugins/elastic_assistant/server/lib/prompt/prompts.ts @@ -102,25 +102,35 @@ const BAD_SYNTAX_EXAMPLES = 'Examples of INCORRECT syntax (bad, because the field names are not included): {{ hostNameValue }} {{ userNameValue }} {{ sourceIpValue }}'; const RECONNAISSANCE = 'Reconnaissance'; +const RESOURCE_DEVELOPMENT = 'Resource Development'; const INITIAL_ACCESS = 'Initial Access'; const EXECUTION = 'Execution'; const PERSISTENCE = 'Persistence'; const PRIVILEGE_ESCALATION = 'Privilege Escalation'; +const DEFENSE_EVASION = 'Defense Evasion'; +const CREDENTIAL_ACCESS = 'Credential Access'; const DISCOVERY = 'Discovery'; const LATERAL_MOVEMENT = 'Lateral Movement'; +const COLLECTION = 'Collection'; const COMMAND_AND_CONTROL = 'Command and Control'; const EXFILTRATION = 'Exfiltration'; +const IMPACT = 'Impact'; const MITRE_ATTACK_TACTICS = [ RECONNAISSANCE, + RESOURCE_DEVELOPMENT, INITIAL_ACCESS, EXECUTION, PERSISTENCE, PRIVILEGE_ESCALATION, + DEFENSE_EVASION, + CREDENTIAL_ACCESS, DISCOVERY, LATERAL_MOVEMENT, + COLLECTION, COMMAND_AND_CONTROL, EXFILTRATION, + IMPACT, ] as const; export const ATTACK_DISCOVERY_GENERATION_DETAILS_MARKDOWN = `A detailed insight with markdown, where each markdown bullet contains a description of what happened that reads like a story of the attack as it played out and always uses special ${SYNTAX} syntax for field names and values from the source data. ${GOOD_SYNTAX_EXAMPLES} ${BAD_SYNTAX_EXAMPLES}`; export const ATTACK_DISCOVERY_GENERATION_ENTITY_SUMMARY_MARKDOWN = `A short (no more than a sentence) summary of the insight featuring only the host.name and user.name fields (when they are applicable), using the same ${SYNTAX} syntax`; diff --git a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/helpers.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/helpers.test.tsx index 05970dcec0233..14fd85b5b2142 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/helpers.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/helpers.test.tsx @@ -47,7 +47,13 @@ describe('helpers', () => { }); describe('getTacticMetadata', () => { - const expectedDetected = ['Initial Access', 'Execution', 'Persistence', 'Privilege Escalation']; + const expectedDetected = [ + 'Initial Access', + 'Execution', + 'Persistence', + 'Privilege Escalation', + 'Credential Access', + ]; expectedDetected.forEach((tactic) => { it(`sets the detected property to true for the '${tactic}' tactic`, () => { diff --git a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/helpers.ts b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/helpers.ts index aa56835d5a1ed..07f976d7a21eb 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/helpers.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/helpers.ts @@ -9,32 +9,44 @@ import type { AttackDiscovery } from '@kbn/elastic-assistant-common'; import * as i18n from './translations'; export const RECONNAISSANCE = 'Reconnaissance'; +export const RESOURCE_DEVELOPMENT = 'Resource Development'; export const INITIAL_ACCESS = 'Initial Access'; export const EXECUTION = 'Execution'; export const PERSISTENCE = 'Persistence'; export const PRIVILEGE_ESCALATION = 'Privilege Escalation'; +export const DEFENSE_EVASION = 'Defense Evasion'; +export const CREDENTIAL_ACCESS = 'Credential Access'; export const DISCOVERY = 'Discovery'; export const LATERAL_MOVEMENT = 'Lateral Movement'; +export const COLLECTION = 'Collection'; export const COMMAND_AND_CONTROL = 'Command and Control'; export const EXFILTRATION = 'Exfiltration'; +export const IMPACT = 'Impact'; /** A subset of the Mitre Attack Tactics */ export const MITRE_ATTACK_TACTICS_SUBSET = [ RECONNAISSANCE, + RESOURCE_DEVELOPMENT, INITIAL_ACCESS, EXECUTION, PERSISTENCE, PRIVILEGE_ESCALATION, + DEFENSE_EVASION, + CREDENTIAL_ACCESS, DISCOVERY, LATERAL_MOVEMENT, + COLLECTION, COMMAND_AND_CONTROL, EXFILTRATION, + IMPACT, ] as const; export const getTacticLabel = (tactic: string): string => { switch (tactic) { case RECONNAISSANCE: return i18n.RECONNAISSANCE; + case RESOURCE_DEVELOPMENT: + return i18n.RESOURCE_DEVELOPMENT; case INITIAL_ACCESS: return i18n.INITIAL_ACCESS; case EXECUTION: @@ -43,14 +55,22 @@ export const getTacticLabel = (tactic: string): string => { return i18n.PERSISTENCE; case PRIVILEGE_ESCALATION: return i18n.PRIVILEGE_ESCALATION; + case DEFENSE_EVASION: + return i18n.DEFENSE_EVASION; + case CREDENTIAL_ACCESS: + return i18n.CREDENTIAL_ACCESS; case DISCOVERY: return i18n.DISCOVERY; case LATERAL_MOVEMENT: return i18n.LATERAL_MOVEMENT; + case COLLECTION: + return i18n.COLLECTION; case COMMAND_AND_CONTROL: return i18n.COMMAND_AND_CONTROL; case EXFILTRATION: return i18n.EXFILTRATION; + case IMPACT: + return i18n.IMPACT; default: return tactic; } diff --git a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/attack_discovery_panel/get_attack_discovery_markdown/get_attack_discovery_markdown.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/attack_discovery_panel/get_attack_discovery_markdown/get_attack_discovery_markdown.test.tsx index cf354039dcdd1..8514363654f1b 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/attack_discovery_panel/get_attack_discovery_markdown/get_attack_discovery_markdown.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/attack_discovery_panel/get_attack_discovery_markdown/get_attack_discovery_markdown.test.tsx @@ -65,7 +65,7 @@ describe('getAttackDiscoveryMarkdown', () => { expect(result).toBe(''); }); - it('returns the expected attack chain markdown when tactics are detected', () => { + it('returns the expected attack chain markdown when a subset of tactics are detected', () => { const result = getAttackChainMarkdown(mockAttackDiscovery); expect(result).toBe(`### Attack Chain @@ -73,6 +73,48 @@ describe('getAttackDiscoveryMarkdown', () => { - Execution - Persistence - Privilege Escalation +- Credential Access +`); + }); + + it('returns the expected attack chain markdown when the full set of tactics are detected', () => { + const allTactics = { + ...mockAttackDiscovery, + mitreAttackTactics: [ + 'Reconnaissance', + 'Resource Development', + 'Initial Access', + 'Execution', + 'Persistence', + 'Privilege Escalation', + 'Defense Evasion', + 'Credential Access', + 'Discovery', + 'Lateral Movement', + 'Collection', + 'Command and Control', + 'Exfiltration', + 'Impact', + ], + }; + + const result = getAttackChainMarkdown(allTactics); + + expect(result).toBe(`### Attack Chain +- Reconnaissance +- Resource Development +- Initial Access +- Execution +- Persistence +- Privilege Escalation +- Defense Evasion +- Credential Access +- Discovery +- Lateral Movement +- Collection +- Command & Control +- Exfiltration +- Impact `); }); }); @@ -138,6 +180,7 @@ This appears to be a multi-stage attack involving malware delivery, privilege es - Execution - Persistence - Privilege Escalation +- Credential Access `; @@ -174,6 +217,7 @@ This appears to be a multi-stage attack involving malware delivery, privilege es - Execution - Persistence - Privilege Escalation +- Credential Access `; diff --git a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/attack_discovery_panel/tabs/attack_discovery_tab/attack/attack_chain/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/attack_discovery_panel/tabs/attack_discovery_tab/attack/attack_chain/index.tsx index 498030798d38c..2e722d0d938b7 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/attack_discovery_panel/tabs/attack_discovery_tab/attack/attack_chain/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/attack_discovery_panel/tabs/attack_discovery_tab/attack/attack_chain/index.tsx @@ -36,11 +36,7 @@ const AttackChainComponent: React.FC = ({ attackDiscovery }) => { {tacticMetadata.map((tactic, i) => ( - + ))} diff --git a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/attack_discovery_panel/tabs/attack_discovery_tab/attack/attack_chain/tactic/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/attack_discovery_panel/tabs/attack_discovery_tab/attack/attack_chain/tactic/index.tsx index 798c0f82fd030..7399357d71049 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/attack_discovery_panel/tabs/attack_discovery_tab/attack/attack_chain/tactic/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/results/attack_discovery_panel/tabs/attack_discovery_tab/attack/attack_chain/tactic/index.tsx @@ -12,22 +12,18 @@ import React, { useMemo } from 'react'; import { AxisTick } from '../axis_tick'; const INNER_CIRCLE_LEFT_JUSTIFY_X_OFFSET = 0; // px -const INNER_CIRCLE_RIGHT_JUSTIFY_X_OFFSET = 232; // px - const OUTER_CIRCLE_LEFT_JUSTIFY_X_OFFSET = -4; // px -const OUTER_CIRCLE_RIGHT_JUSTIFY_X_OFFSET = 228; // px interface Props { detected: boolean; - rightJustify?: boolean; tactic: string; } -const TacticComponent: React.FC = ({ detected, rightJustify = false, tactic }) => { +const TacticComponent: React.FC = ({ detected, tactic }) => { const { euiTheme } = useEuiTheme(); - const WIDTH = 120; // px - const TICK_COUNT = 10; + const WIDTH = 144; // px + const TICK_COUNT = 12; const ticks = useMemo( () => ( @@ -49,13 +45,6 @@ const TacticComponent: React.FC = ({ detected, rightJustify = false, tact ); const color = detected ? euiTheme.colors.danger : euiTheme.colors.subduedText; - const innerCircleXOffset = rightJustify - ? INNER_CIRCLE_RIGHT_JUSTIFY_X_OFFSET - : INNER_CIRCLE_LEFT_JUSTIFY_X_OFFSET; - - const outerCircleXOffset = rightJustify - ? OUTER_CIRCLE_RIGHT_JUSTIFY_X_OFFSET - : OUTER_CIRCLE_LEFT_JUSTIFY_X_OFFSET; return (
= ({ detected, rightJustify = false, tact width: ${WIDTH}px; `} > - + = ({ detected, rightJustify = false, tact grow={false} >
= ({ detected, rightJustify = false, tact height: 16px; opacity: ${detected ? 25 : 0}%; position: absolute; - transform: translate(${outerCircleXOffset}px, -6px); + transform: translate(${OUTER_CIRCLE_LEFT_JUSTIFY_X_OFFSET}px, -6px); width: 16px; `} data-test-subj="outerCircle" diff --git a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/translations.ts b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/translations.ts index 50bab7ae536eb..70fa46d8a3bf5 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/translations.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/translations.ts @@ -7,6 +7,13 @@ import { i18n } from '@kbn/i18n'; +export const COLLECTION = i18n.translate( + 'xpack.securitySolution.attackDiscovery.mitre.attack.tactics.collectionLabel', + { + defaultMessage: 'Collection', + } +); + export const COMMAND_AND_CONTROL = i18n.translate( 'xpack.securitySolution.attackDiscovery.mitre.attack.tactics.commandAndControlLabel', { @@ -14,6 +21,20 @@ export const COMMAND_AND_CONTROL = i18n.translate( } ); +export const CREDENTIAL_ACCESS = i18n.translate( + 'xpack.securitySolution.attackDiscovery.mitre.attack.tactics.credentialAccessLabel', + { + defaultMessage: 'Credential Access', + } +); + +export const DEFENSE_EVASION = i18n.translate( + 'xpack.securitySolution.attackDiscovery.mitre.attack.tactics.defenseEvasionLabel', + { + defaultMessage: 'Defense Evasion', + } +); + export const DISCOVERY = i18n.translate( 'xpack.securitySolution.attackDiscovery.mitre.attack.tactics.discoveryLabel', { @@ -42,6 +63,12 @@ export const LATERAL_MOVEMENT = i18n.translate( } ); +export const IMPACT = i18n.translate( + 'xpack.securitySolution.attackDiscovery.mitre.attack.tactics.impactLabel', + { + defaultMessage: 'Impact', + } +); export const INITIAL_ACCESS = i18n.translate( 'xpack.securitySolution.attackDiscovery.mitre.attack.tactics.initialAccessLabel', { @@ -69,3 +96,10 @@ export const RECONNAISSANCE = i18n.translate( defaultMessage: 'Reconnaissance', } ); + +export const RESOURCE_DEVELOPMENT = i18n.translate( + 'xpack.securitySolution.attackDiscovery.mitre.attack.tactics.resourceDevelopmentLabel', + { + defaultMessage: 'Resource Development', + } +);