-
Notifications
You must be signed in to change notification settings - Fork 8.5k
[EDR Workflows] Add RunScript CS Command - UI #202012
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
01e79af
ac4fdec
61743fc
bf9766d
0acea0f
067fb0c
61623bd
ecf0773
d833f7f
9c31946
d3a5ce4
992699b
500697d
de6feec
7da7d70
9a8537d
18402f6
d2ddf72
80f7be2
48acdd7
cb9275c
a5f9605
2647466
6a0648d
cdbc6d9
221bc77
c743d45
adeb2f4
5519a47
f1293fb
8302bc9
da1a2f8
3822bf5
0075942
65cbd2c
e0c9c44
e2c15b8
c2c4456
aed126a
924ab36
f3e1220
c785860
aa60ebc
5ab705f
7f87374
d3c067e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -215,6 +215,88 @@ export const CONSOLE_COMMANDS = { | |||||
| }, | ||||||
| }; | ||||||
|
|
||||||
| export const CROWDSTRIKE_CONSOLE_COMMANDS = { | ||||||
| runscript: { | ||||||
| args: { | ||||||
| raw: { | ||||||
| about: i18n.translate( | ||||||
| 'xpack.securitySolution.crowdStrikeConsoleCommands.runscript.args.raw.about', | ||||||
| { | ||||||
| defaultMessage: 'Raw script content', | ||||||
| } | ||||||
| ), | ||||||
| }, | ||||||
| cloudFile: { | ||||||
| about: i18n.translate( | ||||||
| 'xpack.securitySolution.crowdStrikeConsoleCommands.runscript.args.cloudFile.about', | ||||||
| { | ||||||
| defaultMessage: 'Script name in cloud storage', | ||||||
| } | ||||||
| ), | ||||||
| }, | ||||||
| commandLine: { | ||||||
| about: i18n.translate( | ||||||
| 'xpack.securitySolution.crowdStrikeConsoleCommands.runscript.args.commandLine.about', | ||||||
| { | ||||||
| defaultMessage: 'Command line arguments', | ||||||
| } | ||||||
| ), | ||||||
| }, | ||||||
| hostPath: { | ||||||
| about: i18n.translate( | ||||||
| 'xpack.securitySolution.crowdStrikeConsoleCommands.runscript.args.hostPath.about', | ||||||
| { | ||||||
| defaultMessage: 'Absolute or relative path of script on host machine', | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was taken 1:1 from CrowdStrike console - although I am ok with adjusting if you prefer |
||||||
| } | ||||||
| ), | ||||||
| }, | ||||||
| timeout: { | ||||||
| about: i18n.translate( | ||||||
| 'xpack.securitySolution.crowdStrikeConsoleCommands.runscript.args.timeout.about', | ||||||
| { | ||||||
| defaultMessage: 'Timeout in seconds', | ||||||
| } | ||||||
| ), | ||||||
| }, | ||||||
| }, | ||||||
| title: i18n.translate('xpack.securitySolution.crowdStrikeConsoleCommands.runscript.title', { | ||||||
| defaultMessage: 'Isolate', | ||||||
| }), | ||||||
| about: i18n.translate('xpack.securitySolution.crowdStrikeConsoleCommands.runscript.about', { | ||||||
| defaultMessage: 'Run a script on the host', | ||||||
| }), | ||||||
| helpUsage: i18n.translate('xpack.securitySolution.crowdStrikeConsoleCommands.runscript.about', { | ||||||
| defaultMessage: ` | ||||||
| Command Examples for Running Scripts: | ||||||
|
|
||||||
| 1. Executes a script saved in the CrowdStrike cloud with the specified command-line arguments. | ||||||
|
|
||||||
| runscript --CloudFile="CloudScript1.ps1" --CommandLine="-Verbose true" | ||||||
|
|
||||||
| 2. Executes a script saved in the CrowdStrike cloud with the specified command-line arguments and a 180-second timeout. | ||||||
|
|
||||||
| runscript --CloudFile="CloudScript1.ps1" --CommandLine="-Verbose true" -Timeout=180 | ||||||
|
|
||||||
| 3. Executes a raw script provided entirely within the "--Raw" flag. | ||||||
|
|
||||||
| runscript --Raw="Get-ChildItem." | ||||||
|
|
||||||
| 4. Executes a script located on the remote host at the specified path with the provided command-line arguments. | ||||||
|
|
||||||
| runscript --HostPath="C:\\temp\\LocalScript.ps1" --CommandLine="-Verbose true" | ||||||
|
|
||||||
| `, | ||||||
| }), | ||||||
| privileges: i18n.translate( | ||||||
| 'xpack.securitySolution.crowdStrikeConsoleCommands.runscript.privileges', | ||||||
| { | ||||||
| defaultMessage: | ||||||
| 'Insufficient privileges to run script. Contact your Kibana administrator if you think you should have this permission.', | ||||||
| } | ||||||
| ), | ||||||
| }, | ||||||
| }; | ||||||
|
|
||||||
| export const CONFIRM_WARNING_MODAL_LABELS = (entryType: string) => { | ||||||
| return { | ||||||
| title: i18n.translate('xpack.securitySolution.artifacts.confirmWarningModal.title', { | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,6 +33,13 @@ export const CommandInputUsage = memo<Pick<CommandUsageProps, 'commandDef'>>(({ | |
| }); | ||
| }, [commandDef]); | ||
|
|
||
| const helpExample = useMemo(() => { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why did we need to add a
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, that was the reason 👍 |
||
| if (commandDef.helpUsage) { | ||
| return commandDef.helpUsage; | ||
| } | ||
| return commandDef.exampleUsage; | ||
| }, [commandDef]); | ||
|
|
||
| return ( | ||
| <> | ||
| <EuiDescriptionList | ||
|
|
@@ -55,7 +62,7 @@ export const CommandInputUsage = memo<Pick<CommandUsageProps, 'commandDef'>>(({ | |
| titleProps={additionalProps} | ||
| /> | ||
| <EuiSpacer size="s" /> | ||
| {commandDef.exampleUsage && ( | ||
| {helpExample && ( | ||
| <EuiDescriptionList | ||
| compressed | ||
| type="column" | ||
|
|
@@ -69,7 +76,7 @@ export const CommandInputUsage = memo<Pick<CommandUsageProps, 'commandDef'>>(({ | |
| })} | ||
| </ConsoleCodeBlock> | ||
| ), | ||
| description: <ConsoleCodeBlock>{commandDef.exampleUsage}</ConsoleCodeBlock>, | ||
| description: <ConsoleCodeBlock>{helpExample}</ConsoleCodeBlock>, | ||
| }, | ||
| ]} | ||
| descriptionProps={additionalProps} | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -42,7 +42,7 @@ import { | |
| import { getCommandAboutInfo } from './get_command_about_info'; | ||
|
|
||
| import { validateUnitOfTime } from './utils'; | ||
| import { CONSOLE_COMMANDS } from '../../../common/translations'; | ||
| import { CONSOLE_COMMANDS, CROWDSTRIKE_CONSOLE_COMMANDS } from '../../../common/translations'; | ||
| import { ScanActionResult } from '../command_render_components/scan_action'; | ||
|
|
||
| const emptyArgumentValidator = (argData: ParsedArgData): true | string => { | ||
|
|
@@ -167,6 +167,7 @@ export const getEndpointConsoleCommands = ({ | |
| const featureFlags = ExperimentalFeaturesService.get(); | ||
|
|
||
| const isUploadEnabled = featureFlags.responseActionUploadEnabled; | ||
| const crowdstrikeRunScriptEnabled = featureFlags.crowdstrikeRunScriptEnabled; | ||
|
|
||
| const doesEndpointSupportCommand = (commandName: ConsoleResponseActionCommands) => { | ||
| // Agent capabilities is only validated for Endpoint agent types | ||
|
|
@@ -523,6 +524,71 @@ export const getEndpointConsoleCommands = ({ | |
| privileges: endpointPrivileges, | ||
| }), | ||
| }); | ||
| if (crowdstrikeRunScriptEnabled) { | ||
| consoleCommands.push({ | ||
| name: 'runscript', | ||
| about: getCommandAboutInfo({ | ||
| aboutInfo: CROWDSTRIKE_CONSOLE_COMMANDS.runscript.about, | ||
| isSupported: doesEndpointSupportCommand('runscript'), | ||
| }), | ||
| RenderComponent: () => null, | ||
| meta: { | ||
| agentType, | ||
| endpointId: endpointAgentId, | ||
| capabilities: endpointCapabilities, | ||
| privileges: endpointPrivileges, | ||
| }, | ||
| exampleUsage: `runscript --Raw=\`\`\`Get-ChildItem .\`\`\` -CommandLine=""`, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FYI - I still see the use of ` here for the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, we want --, I mistakenly omitted the -CommandLine - will adjust
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure you understood my comment (although, I did not notice the single Look at the value of
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right... well, apparently an example I copied over from CS. But indeed it makes no sense, will remove! thx |
||
| helpUsage: CROWDSTRIKE_CONSOLE_COMMANDS.runscript.helpUsage, | ||
| exampleInstruction: CROWDSTRIKE_CONSOLE_COMMANDS.runscript.about, | ||
| validate: capabilitiesAndPrivilegesValidator(agentType), | ||
| mustHaveArgs: true, | ||
| args: { | ||
| Raw: { | ||
| required: false, | ||
| allowMultiples: false, | ||
| about: CROWDSTRIKE_CONSOLE_COMMANDS.runscript.args.raw.about, | ||
| mustHaveValue: 'non-empty-string', | ||
| exclusiveOr: true, | ||
| }, | ||
| CloudFile: { | ||
| required: false, | ||
| allowMultiples: false, | ||
| about: CROWDSTRIKE_CONSOLE_COMMANDS.runscript.args.cloudFile.about, | ||
| mustHaveValue: 'non-empty-string', | ||
| exclusiveOr: true, | ||
| }, | ||
| CommandLine: { | ||
| required: false, | ||
| allowMultiples: false, | ||
| about: CROWDSTRIKE_CONSOLE_COMMANDS.runscript.args.commandLine.about, | ||
| mustHaveValue: 'non-empty-string', | ||
| }, | ||
| HostPath: { | ||
| required: false, | ||
| allowMultiples: false, | ||
| about: CROWDSTRIKE_CONSOLE_COMMANDS.runscript.args.hostPath.about, | ||
| mustHaveValue: 'non-empty-string', | ||
| exclusiveOr: true, | ||
| }, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought you said that 1 of these tree needed to be used... so should have the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a bit tricky, since CrowdStrike lets you add multiple of these arguments, and then the strange behavior I explained during the meeting happened. But I agree with you that our approach would be to use
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok. Sorry about this - I do now remember that we discussed that they can use multiples, but at least one of them must be present. In that case, you are correct in that we can't use The main issue I saw when testing this is that there was no validations in place. Realizing now that all three could be used, and that at least 1 must be defined, I think the perhaps the command should be setup as:
Removing the |
||
| Timeout: { | ||
| required: false, | ||
| allowMultiples: false, | ||
| about: CROWDSTRIKE_CONSOLE_COMMANDS.runscript.args.timeout.about, | ||
| mustHaveValue: 'number-greater-than-zero', | ||
| }, | ||
| ...commandCommentArgument(), | ||
| }, | ||
| helpGroupLabel: HELP_GROUPS.responseActions.label, | ||
| helpGroupPosition: HELP_GROUPS.responseActions.position, | ||
| helpCommandPosition: 9, | ||
| helpDisabled: !doesEndpointSupportCommand('runscript'), | ||
| helpHidden: !getRbacControl({ | ||
| commandName: 'runscript', | ||
| privileges: endpointPrivileges, | ||
| }), | ||
| }); | ||
| } | ||
|
|
||
| switch (agentType) { | ||
| case 'sentinel_one': | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Q: Should be file name I think? Unless script name and file name are the same?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question. So scripts are on the Cloud, files are on a host. Again I copied this over from CrowdStrike console. But I am happy to adjust if you prefer