-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
[EDR Workflows] Add RunScript CS Command - UI #202012
Changes from 45 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,66 @@ 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', | ||||||
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. Q: Should be file name I think? Unless script name and file name are the same?
Suggested change
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. 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 |
||||||
} | ||||||
), | ||||||
}, | ||||||
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', | ||||||
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
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', | ||||||
}), | ||||||
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(() => { | ||
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 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,87 @@ 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=""`, | ||
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. 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.
|
||
helpUsage: ` | ||
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 needs to be |
||
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" | ||
|
||
`, | ||
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', | ||
}, | ||
CloudFile: { | ||
required: false, | ||
allowMultiples: false, | ||
about: CROWDSTRIKE_CONSOLE_COMMANDS.runscript.args.cloudFile.about, | ||
mustHaveValue: 'non-empty-string', | ||
}, | ||
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', | ||
}, | ||
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 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 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: 'non-empty-string', | ||
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. |
||
}, | ||
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'm a bit confused on this setup for the arguments... Should at least one of these be required? if so, then all arguments configuration should have 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. Good point, I wasn't aware 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. Reading through the options again - can you detail in the issue what the input is to these arguments and how they should be used? Example:
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. Sure, I understand this may be a bit unclear 👍
I'll put some info about it in the issue itself too as you suggested 👍 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. Also: I played with CS Console and it's possible to pass multiple arguments eg. What do you think? |
||
...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': | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -299,6 +299,13 @@ const CODES = Object.freeze({ | |
'xpack.securitySolution.endpointActionResponseCodes.scan.success', | ||
{ defaultMessage: 'Scan complete' } | ||
), | ||
|
||
// Dev: | ||
// runscript success/competed | ||
ra_runscript_success_done: i18n.translate( | ||
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. You should not be using these code for Crowdstrike. This are Elastic Defend specific and IMO should remain as such. 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 did it to reflect the behavior in tests, but I am ok with removing it 👍 |
||
'xpack.securitySolution.endpointActionResponseCodes.runscript.success', | ||
{ defaultMessage: 'Runscript complete' } | ||
), | ||
}); | ||
|
||
/** | ||
|
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.
Do you also have a list of error codes? Then you should add those below in a function as well.
randomRunscriptFailureCode()
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.
I don't have a list unfortunately, I noted a few codes though so when I conitnue working on CrowdStrike connector and results - I'll adjust the CS errors list 👍