-
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
TheHive Case Connector #180138
TheHive Case Connector #180138
Conversation
Pinging @elastic/response-ops-cases (Feature:Cases) |
Pinging @elastic/response-ops (Team:ResponseOps) |
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 did a lightweight review and left some comments. I will leave the full review and testing to the Security solution team.
PUSH_TO_SERVICE = 'pushToService', | ||
CREATE_ALERT = 'createAlert', | ||
} | ||
export enum TheHiveSeverity { |
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 remember discussing it but just to be sure, are we sure that the severity and the TLP values are fixed and cannot be changed by users in TheHive?
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.
Correct, users can't change or add new enum for severity and TLP in TheHive.
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 confirm, the TLP, PAP and Severity are static values in TheHive
summary: schema.nullable(schema.string()), | ||
impactStatus: schema.nullable(schema.string()), | ||
assignee: schema.nullable(schema.string()), | ||
customFields: schema.nullable(schema.arrayOf(schema.object({}, { unknowns: 'allow' }))), |
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.
Instead of schema.object({}, { unknowns: 'allow' })
you can use schema.recordOf(schema.stirng(), schema.any())
]); | ||
|
||
|
||
export const TheHiveIncidentResponseSchema = schema.object( |
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.
Are we sure that we need all the fields to be listed in the schema? Do we use them all?
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.
No, we don't use all of them. However, I've included them all as a precaution for future needs.
LMK your thoughts.
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 am not sure what is best tbh. Assuming TheHIve will not introduce any breaking changes in the fields I do not see any harm in keeping them. If they do then our validation will start failing. The more field we have the more the chance for this to happen. If they are documented here https://docs.strangebee.com/thehive/api-docs/#operation/Create%20case then I think it is fine to keep them.
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.
Yes, They are documented.
{ unknowns: 'ignore' } | ||
); | ||
|
||
export const TheHiveUpdateIncidentResponseSchema = schema.any(); |
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.
What does TheHive
return when you update a case?
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.
It is a PATCH
request and it returns 204 No Content
.
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.
Interesting. Do you know if schema.never()
works? Not of this PR, but maybe the framework should skip the validation if the response is 204 No Content
.
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.
Will check and update.
type: schema.number(), | ||
message: schema.string(), | ||
}, | ||
{ unknowns: 'allow' } |
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.
Should we ignore
?
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.
Will remove it.
this.url = this.config.url; | ||
this.organisation = this.config.organisation; | ||
this.api_key = this.secrets.api_key; | ||
this.urlWithoutTrailingSlash = this.url.endsWith('/') ? this.url.slice(0, -1) : this.url; |
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.
The framework will take care of that for you. You can do this.url
directly in the requests.
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.
Right. But it is needed while we returning ExternalServiceIncidentResponse
.
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 missed that. All good!
method: 'patch', | ||
url: `${this.url}/api/${API_VERSION}/case/${incidentId}`, | ||
data: incident, | ||
headers: { Authorization: `Bearer ${this.api_key}`, 'X-Organisation': this.organisation }, |
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.
It seems that the same headers are being used in all requests. What about creating a util function getHeaders
where it can be used in all functions?
|
||
}, [actionParams]); | ||
|
||
useEffect(() => { |
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.
Why do we need this useEffect
?
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.
When the eventAction
changes, it sets subAction
props and defaults the severity
and TLP
values.
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.
Why do we need to put the defaults when the eventAction
changes? Theoretically eventAction
should never change.
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.
When user change the toggle(for selecting a case or an alert), we are updating eventAction
state accordingly and clear out all the fields and set defaults values in severity
and TLP
.
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.
If that's the case then you can clear the fields inside setEventActionType
when the user changes the toggle.
onChange={(e) => setEventActionType(e.target.value as SUB_ACTION)} | ||
/> | ||
</EuiFormRow> | ||
{eventAction === SUB_ACTION.PUSH_TO_SERVICE ? |
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 think is better if you create two components one for each subAction
and not having all logic in this component. Each component can manage its own state and the parent can reset the global state when the subAction
changes.
errors, | ||
messageVariables | ||
}) => { | ||
const [eventAction, setEventAction] = useState(actionParams.subAction ?? SUB_ACTION.PUSH_TO_SERVICE); |
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 was not part of the conversation so sorry if it was already discussed. Do we want the users to select if they want to create a case or an alert or we should only create alerts?
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.
Yes, we've previously discussed providing support for both creating a case or an alert. However, I'll double-check with the team to confirm once more.
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.
Perfect! Thanks!
@@ -69,6 +70,7 @@ export function registerConnectorTypes({ | |||
connectorTypeRegistry.register(getTorqConnectorType()); | |||
connectorTypeRegistry.register(getTinesConnectorType()); | |||
connectorTypeRegistry.register(getD3SecurityConnectorType()); | |||
connectorTypeRegistry.register(getTheHiveConnectorType()); |
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.
Hey @cnasikas, does the new convention to put new connectors under a feature flag apply to this PR?
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.
Hey! Yes, we need to follow the new intermediate release process for all new connectors.
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.
@brijesh-elastic The code looks great, we have good test coverage, and everything works well when tested locally, both sending to theHive alerts and cases.
What I have noticed is that we don't send any information about the alerts generated when the rule is triggered.
When the alerts are received in TheHive we only have the static information defined in the connector configuration, we know the rule, but nothing else.
Is this behavior intended?
I say that because most of the connectors have a body template parameter to parse the alerts and send information about them, such as the host, IP, user... So we have some details to add to the alert description in theHive.
<EuiComboBox | ||
data-test-subj="tagsInput" | ||
fullWidth | ||
placeholder="Tags" |
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.
We need to apply translation here
<EuiComboBox | ||
data-test-subj="tagsInput" | ||
fullWidth | ||
placeholder="Tags" |
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.
We need to apply translation here as well
We've decided not to set default message variables for the description parameter, allowing users instead to add their own message variables during connector configuration. This approach doesn't limit users, enabling them to include any desired information in the alert descriptions. Additionally, following discussions with the Hive Team, we've agreed to leave this as blank. Let me know your thoughts on this. |
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.
Approving on behalf of Security Solution.
I desk-tested the PR with a local instance of TheHive, everything works well on the Security Solution side. I haven't been able to spot any issues.
The connector sends one alert to theHive (case or alert) per rule execution when alerts are detected, with the static title and description defined on the connector parameters when it is attached to the rule.
The code LGTM. Only a couple of minor test fixes are needed.
Thanks @brijesh-elastic
⏳ Build in-progress, with failures
Failed CI StepsTest Failures
History
|
Hey @jamiehynds! The team is aware and we will review the PR soon! |
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.
ResponseOps changes look good, follows the guidelines of sub actions framework and case connector. 👍
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.
The PR is great and already approved.
However, could you please hold on merging it till we confirm whether it needs to follow an intermediate release process for serverless or not.
Putting this comment as request change to stop getting it merged accidentally.
@elasticmachine merge upstream |
I tested the code for the intermediate release process and is working as expected. @semd @brijesh-elastic I found a bug when I tried to use the connector with fake credentials. React is stuck in an infinite loop. I think we should fix it because this can be a valid scenario (the user puts wrong credentials or TheHive returns a 403 error). |
@elasticmachine merge upstream |
@semd @brijesh-elastic I tested the connector on the Stack management and I found a bug. Even though I set the Severity, the TLP, and the tags the UI does not show my values. The values are correctly persisted on the backend. Screen.Recording.2024-07-29.at.12.07.52.PM.movAlso for the tags (both for cases and alerts):
|
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 tested @js-jankisalvi changes and the bug fixes from @brijesh-elastic. Everything is working as expected!
💛 Build succeeded, but was flaky
Failed CI StepsTest Failures
Metrics [docs]Module Count
Async chunks
Page load bundle
Unknown metric groupsasync chunk count
ESLint disabled line counts
Total ESLint disabled count
History
To update your PR or re-run it, just comment with: |
## Summary This PR implements the case support for TheHive connector. Depends on : #180138 ## Screenshots **List of connectors** ![image](https://github.com/elastic/kibana/assets/123942796/7236eaed-d1d5-4506-80b1-c4e43c6ce36a) **Configure thehive connector from cases** ![image](https://github.com/elastic/kibana/assets/123942796/bb4843d5-9f29-47c2-baa3-77db81a35319) ### Checklist Delete any items that are not applicable to this PR. - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [x] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed - [x] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [x] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - [x] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker) - [x] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [x] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --------- Co-authored-by: Elastic Machine <[email protected]> Co-authored-by: kibanamachine <[email protected]> Co-authored-by: Christos Nasikas <[email protected]>
Summary
TheHive is a new case connector, enabling users to seamlessly transfer elastic cases to TheHive Security Incident Response Platform. This connector facilitates sub-actions such as creating cases, updating cases, and adding comments and creating alerts.
create connector
test connector
Checklist
Delete any items that are not applicable to this PR.
For maintainers