Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/reference/connectors-kibana/thehive-action-type.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ Source reference
: A source reference for the alert.

Body
: A Json payload specifying additional parameter, such as observables and procedures. It can be populated using a predefined template or customized using the `Custom Template` option. For example:
: A Json payload specifying additional parameter, such as observables and procedures. For example:

```json
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
*/

import React from 'react';
import { render } from '@testing-library/react';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { ActionConnector } from '@kbn/triggers-actions-ui-plugin/public/types';
import { TheHiveParamsAlertFields } from './params_alert';
import { SUB_ACTION } from '../../../common/thehive/constants';
import { ExecutorParams, ExecutorSubActionCreateAlertParams } from '../../../common/thehive/types';
import userEvent from '@testing-library/user-event';

describe('TheHiveParamsFields renders', () => {
const subActionParams: ExecutorSubActionCreateAlertParams = {
Expand Down Expand Up @@ -61,12 +62,46 @@ describe('TheHiveParamsFields renders', () => {
expect(getByTestId('descriptionTextArea')).toBeInTheDocument();
expect(getByTestId('tagsInput')).toBeInTheDocument();
expect(getByTestId('severitySelectInput')).toBeInTheDocument();
expect(getByTestId('rule-severity-toggle')).toBeInTheDocument();
expect(getByTestId('tlpSelectInput')).toBeInTheDocument();
expect(getByTestId('typeInput')).toBeInTheDocument();
expect(getByTestId('sourceInput')).toBeInTheDocument();
expect(getByTestId('sourceRefInput')).toBeInTheDocument();
expect(getByTestId('bodyJsonEditor')).toBeInTheDocument();

expect(getByTestId('severitySelectInput')).toHaveValue('2');
expect(getByTestId('tlpSelectInput')).toHaveValue('2');
expect(getByTestId('rule-severity-toggle')).not.toBeChecked();
});

it('hides the severity select input when rule severity toggle is enabled', () => {
const { getByTestId } = render(<TheHiveParamsAlertFields {...defaultProps} />);
const ruleSeverityToggleEl = getByTestId('rule-severity-toggle');

fireEvent.click(ruleSeverityToggleEl);
expect(getByTestId('rule-severity-toggle')).toBeEnabled();
expect(editAction).toHaveBeenCalledWith(
'subActionParams',
{ ...subActionParams, severity: 2, isRuleSeverity: true },
0
);

expect(screen.queryByTestId('severitySelectInput')).not.toBeInTheDocument();
});

it('should updates body content', async () => {
const bodyValue = JSON.stringify({ bar: 'test' });
render(<TheHiveParamsAlertFields {...defaultProps} />);

await userEvent.click(await screen.findByTestId('bodyJsonEditor'));
await userEvent.paste(bodyValue);

await waitFor(() => {
expect(editAction).toHaveBeenCalledWith(
'subActionParams',
{ ...subActionParams, body: bodyValue },
0
);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ export const TheHiveParamsAlertFields: React.FC<ActionParamsProps<ExecutorParams
}}
errors={errors['createAlertParam.sourceRef'] as string[]}
/>
{!isTest && Boolean(isRuleSeverity) && (
{!isTest && (
<EuiFormRow fullWidth>
<EuiSwitch
label={translations.IS_RULE_SEVERITY_LABEL}
Expand Down Expand Up @@ -216,26 +216,24 @@ export const TheHiveParamsAlertFields: React.FC<ActionParamsProps<ExecutorParams
noSuggestions
/>
</EuiFormRow>
{alert.body != null && (
<JsonEditorWithMessageVariables
messageVariables={messageVariables}
paramsProperty={'body'}
inputTargetValue={alert.body}
label={translations.BODY_LABEL}
ariaLabel={translations.BODY_DESCRIPTION}
errors={errors.body as string[]}
onDocumentsChange={(json: string) =>
editAction('subActionParams', { ...alert, body: json }, index)
<JsonEditorWithMessageVariables
messageVariables={messageVariables}
paramsProperty={'body'}
inputTargetValue={alert.body}
label={translations.BODY_LABEL}
ariaLabel={translations.BODY_DESCRIPTION}
errors={errors.body as string[]}
onDocumentsChange={(json: string) =>
editAction('subActionParams', { ...alert, body: json }, index)
}
dataTestSubj="thehive-body"
onBlur={() => {
if (!alert.body) {
editAction('subActionParams', { ...alert, body: null }, index);
}
dataTestSubj="thehive-body"
onBlur={() => {
if (!alert.body) {
editAction('subActionParams', { ...alert, body: null }, index);
}
}}
isOptionalField
/>
)}
}}
isOptionalField
/>
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,6 @@ export const SOURCE_REF_LABEL = i18n.translate(
}
);

export const TEMPLATE_LABEL = i18n.translate(
'xpack.stackConnectors.components.thehive.templateFieldLabel',
{
defaultMessage: 'Template',
}
);

export const BODY_LABEL = i18n.translate(
'xpack.stackConnectors.components.thehive.bodyFieldLabel',
{
Expand All @@ -130,13 +123,6 @@ export const BODY_DESCRIPTION = i18n.translate(
}
);

export const SELECT_BODY_TEMPLATE_POPOVER_BUTTON = i18n.translate(
'xpack.stackConnectors.components.thehive.selectBodyTemplatePopoverButton',
{
defaultMessage: 'Select body template',
}
);

export const TITLE_REQUIRED = i18n.translate(
'xpack.stackConnectors.components.thehive.requiredTitleText',
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,17 @@ export class TheHiveSimulator extends Simulator {
if (this.returnError) {
return TheHiveSimulator.sendErrorResponse(response);
}

return TheHiveSimulator.sendResponse(response);
const pathName = request.url!;
return TheHiveSimulator.sendResponse(
response,
pathName.includes('case') ? theHiveCaseSuccessResponse : theHiveAlertSuccessResponse
);
}

private static sendResponse(response: http.ServerResponse) {
private static sendResponse(response: http.ServerResponse, data: any) {
response.statusCode = 201;
response.setHeader('Content-Type', 'application/json');
response.end(JSON.stringify(theHiveSuccessResponse, null, 4));
response.end(JSON.stringify(data, null, 4));
}

private static sendErrorResponse(response: http.ServerResponse) {
Expand All @@ -44,7 +47,7 @@ export class TheHiveSimulator extends Simulator {
}
}

export const theHiveSuccessResponse = {
export const theHiveCaseSuccessResponse = {
_id: '~172064',
_type: 'Case',
_createdBy: 'user1@thehive.local',
Expand Down Expand Up @@ -96,6 +99,34 @@ export const theHiveSuccessResponse = {
timeToDetect: 0,
};

export const theHiveAlertSuccessResponse = {
_id: '~245821592',
_type: 'Alert',
_createdBy: 'user1@thehive.local',
_createdAt: 1750411773815,
type: 'type',
source: 'source',
sourceRef: 'sourceRef',
title: 'title',
description: 'description',
severity: 1,
severityLabel: 'LOW',
date: 1750411773798,
tags: ['tags1', 'tags2'],
tlp: 2,
tlpLabel: 'AMBER',
pap: 2,
papLabel: 'AMBER',
follow: true,
customFields: [],
observableCount: 3,
status: 'New',
stage: 'New',
extraData: {},
newDate: 1750411773800,
timeToDetect: 0,
};

export const theHiveFailedResponse = {
type: 'BadRequest',
message: 'Invalid json',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ export default function theHiveTest({ getService }: FtrProviderContext) {
simulator.close();
});

it('should send a formatted JSON object', async () => {
it('should create a case', async () => {
const { body } = await supertest
.post(`/api/actions/connector/${theHiveActionId}/_execute`)
.set('kbn-xsrf', 'foo')
Expand Down Expand Up @@ -284,6 +284,67 @@ export default function theHiveTest({ getService }: FtrProviderContext) {
},
});
});

it('should create an alert', async () => {
const { body } = await supertest
.post(`/api/actions/connector/${theHiveActionId}/_execute`)
.set('kbn-xsrf', 'foo')
.send({
params: {
subAction: 'createAlert',
subActionParams: {
title: 'title',
description: 'description',
tlp: 2,
source: 'source',
type: 'type',
sourceRef: 'sourceRef',
isRuleSeverity: false,
severity: 1,
tags: ['tags1', 'tags2'],
body: '{"observables":[{"dataType":"url","data":"http://example.com"},{"dataType":"mail","data":"foo@example.org"},{"dataType":"ip","data":"127.0.0.1"}],"procedures":[{"patternId":"T1132","occurDate":1640000000000}]}',
},
},
})
.expect(200);

expect(simulator.requestData).to.eql({
title: 'title',
description: 'description',
type: 'type',
source: 'source',
sourceRef: 'sourceRef',
severity: 1,
tags: ['tags1', 'tags2'],
tlp: 2,
observables: [
{
dataType: 'url',
data: 'http://example.com',
},
{
dataType: 'mail',
data: 'foo@example.org',
},
{
dataType: 'ip',
data: '127.0.0.1',
},
],
procedures: [
{
patternId: 'T1132',
occurDate: 1640000000000,
},
],
});

expect(body).to.eql({
status: 'ok',
connector_id: theHiveActionId,
data: {},
});
});
});

describe('error response simulator', () => {
Expand Down