Skip to content

Commit

Permalink
[Security Solution] [Cases] Swimlane Connector for Cases (#100086)
Browse files Browse the repository at this point in the history
Co-authored-by: Josh <[email protected]>
Co-authored-by: Xavier Mouligneau <[email protected]>
Co-authored-by: Christos Nasikas <[email protected]>
Co-authored-by: Jonathan Buttner <[email protected]>
Co-authored-by: Kibana Machine <[email protected]>
  • Loading branch information
6 people authored Jun 23, 2021
1 parent 1813d70 commit 2dc1715
Show file tree
Hide file tree
Showing 110 changed files with 5,531 additions and 233 deletions.
4 changes: 4 additions & 0 deletions docs/management/action-types.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ a| <<slack-action-type, Slack>>

| Send a message to a Slack channel or user.

a| <<swimlane-action-type, Swimlane>>

| Create an incident in Swimlane.

a| <<webhook-action-type, Webhook>>

| Send a request to a web service.
Expand Down
105 changes: 105 additions & 0 deletions docs/management/connectors/action-types/swimlane.asciidoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
[role="xpack"]
[[swimlane-action-type]]
=== Swimlane connector and action
++++
<titleabbrev>Swimlane</titleabbrev>
++++

The Swimlane connector uses the https://swimlane.com/knowledge-center/docs/developer-guide/rest-api/[Swimlane REST API] to create Swimlane records.

[float]
[[swimlane-connector-configuration]]
==== Connector configuration

Swimlane connectors have the following configuration properties.

Name:: The name of the connector. The name is used to identify a connector in the **Stack Management** UI connector listing, and in the connector list when configuring an action.
URL:: Swimlane instance URL.
Application ID:: Swimlane application ID.
API token:: Swimlane API authentication token for HTTP Basic authentication.

[float]
[[Preconfigured-swimlane-configuration]]
==== Preconfigured connector type

[source,text]
--
my-swimlane:
name: preconfigured-swimlane-connector-type
actionTypeId: .swimlane
config:
apiUrl: https://elastic.swimlaneurl.us
appId: app-id
mappings:
alertIdConfig:
fieldType: text
id: agp4s
key: alert-id
name: Alert ID
caseIdConfig:
fieldType: text
id: ae1mi
key: case-id
name: Case ID
caseNameConfig:
fieldType: text
id: anxnr
key: case-name
name: Case Name
commentsConfig:
fieldType: comments
id: au18d
key: comments
name: Comments
descriptionConfig:
fieldType: text
id: ae1gd
key: description
name: Description
ruleNameConfig:
fieldType: text
id: avfsl
key: rule-name
name: Rule Name
severityConfig:
fieldType: text
id: a71ik
key: severity
name: severity
secrets:
apiToken: tokenkeystorevalue
--

Config defines information for the connector type.

`apiUrl`:: An address that corresponds to *URL*.
`appId`:: A key that corresponds to *Application ID*.

Secrets defines sensitive information for the connector type.

`apiToken`:: A string that corresponds to *API Token*. Should be stored in the <<creating-keystore, {kib} keystore>>.

[float]
[[define-swimlane-ui]]
==== Define connector in Stack Management

Define Swimlane connector properties.

[role="screenshot"]
image::management/connectors/images/swimlane-connector.png[Swimlane connector]

Test Swimlane action parameters.

[role="screenshot"]
image::management/connectors/images/swimlane-params-test.png[Swimlane params test]

[float]
[[swimlane-action-configuration]]
==== Action configuration

Swimlane actions have the following configuration properties.

Comments:: Additional information for the client, such as how to troubleshoot the issue.
Severity:: The severity of the incident.

NOTE: Alert ID and Rule Name are filled automatically. Specifically, Alert ID is set to `{{alert.id}}` and Rule Name to `{{rule.name}}`.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/management/connectors/index.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ include::action-types/teams.asciidoc[]
include::action-types/pagerduty.asciidoc[]
include::action-types/server-log.asciidoc[]
include::action-types/servicenow.asciidoc[]
include::action-types/swimlane.asciidoc[]
include::action-types/slack.asciidoc[]
include::action-types/webhook.asciidoc[]
include::pre-configured-connectors.asciidoc[]
145 changes: 89 additions & 56 deletions x-pack/plugins/actions/README.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const ACTION_TYPE_IDS = [
'.pagerduty',
'.server-log',
'.slack',
'.swimlane',
'.teams',
'.webhook',
];
Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/actions/server/builtin_action_types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { Logger } from '../../../../../src/core/server';
import { getActionType as getEmailActionType } from './email';
import { getActionType as getIndexActionType } from './es_index';
import { getActionType as getPagerDutyActionType } from './pagerduty';
import { getActionType as getSwimlaneActionType } from './swimlane';
import { getActionType as getServerLogActionType } from './server_log';
import { getActionType as getSlackActionType } from './slack';
import { getActionType as getWebhookActionType } from './webhook';
Expand Down Expand Up @@ -65,6 +66,7 @@ export function registerBuiltInActionTypes({
);
actionTypeRegistry.register(getIndexActionType({ logger }));
actionTypeRegistry.register(getPagerDutyActionType({ logger, configurationUtilities }));
actionTypeRegistry.register(getSwimlaneActionType({ logger, configurationUtilities }));
actionTypeRegistry.register(getServerLogActionType({ logger }));
actionTypeRegistry.register(getSlackActionType({ logger, configurationUtilities }));
actionTypeRegistry.register(getWebhookActionType({ logger, configurationUtilities }));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
JiraSecretConfigurationType,
JiraExecutorResultData,
ExecutorSubActionGetFieldsByIssueTypeParams,
ExecutorSubActionGetIssueTypesParams,
ExecutorSubActionCommonFieldsParams,
ExecutorSubActionGetIssuesParams,
ExecutorSubActionGetIssueParams,
ExecutorSubActionGetIncidentParams,
Expand Down Expand Up @@ -137,7 +137,7 @@ async function executor(
}

if (subAction === 'issueTypes') {
const getIssueTypesParams = subActionParams as ExecutorSubActionGetIssueTypesParams;
const getIssueTypesParams = subActionParams as ExecutorSubActionCommonFieldsParams;
data = await api.issueTypes({
externalService,
params: getIssueTypesParams,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,6 @@ export const ExternalIncidentServiceSecretConfigurationSchema = schema.object(
ExternalIncidentServiceSecretConfiguration
);

export const ExecutorSubActionSchema = schema.oneOf([
schema.literal('getIncident'),
schema.literal('pushToService'),
schema.literal('handshake'),
schema.literal('issueTypes'),
schema.literal('fieldsByIssueType'),
]);

export const ExecutorSubActionPushParamsSchema = schema.object({
incident: schema.object({
summary: schema.string(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,25 +155,25 @@ describe('Jira service', () => {
).toThrow();
});

test('throws without username', () => {
test('throws without email/username', () => {
expect(() =>
createExternalService(
{
config: { apiUrl: 'test.com' },
secrets: { apiToken: '', email: '[email protected]' },
config: { apiUrl: 'test.com', projectKey: 'CK' },
secrets: { apiToken: 'token' },
},
logger,
configurationUtilities
)
).toThrow();
});

test('throws without password', () => {
test('throws without apiToken/password', () => {
expect(() =>
createExternalService(
{
config: { apiUrl: 'test.com' },
secrets: { apiToken: '', email: undefined },
config: { apiUrl: 'test.com', projectKey: 'CK' },
secrets: { email: '[email protected]' },
},
logger,
configurationUtilities
Expand Down
10 changes: 5 additions & 5 deletions x-pack/plugins/actions/server/builtin_action_types/jira/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ import {
ExecutorSubActionGetIncidentParamsSchema,
ExecutorSubActionHandshakeParamsSchema,
ExecutorSubActionGetCapabilitiesParamsSchema,
ExecutorSubActionGetIssueTypesParamsSchema,
ExecutorSubActionGetFieldsByIssueTypeParamsSchema,
ExecutorSubActionGetIssuesParamsSchema,
ExecutorSubActionGetIssueParamsSchema,
ExecutorSubActionCommonFieldsParamsSchema,
} from './schema';
import { ActionsConfigurationUtilities } from '../../actions_config';
import { Logger } from '../../../../../../src/core/server';
Expand Down Expand Up @@ -124,8 +124,8 @@ export type ExecutorSubActionGetCapabilitiesParams = TypeOf<
typeof ExecutorSubActionGetCapabilitiesParamsSchema
>;

export type ExecutorSubActionGetIssueTypesParams = TypeOf<
typeof ExecutorSubActionGetIssueTypesParamsSchema
export type ExecutorSubActionCommonFieldsParams = TypeOf<
typeof ExecutorSubActionCommonFieldsParamsSchema
>;

export type ExecutorSubActionGetFieldsByIssueTypeParams = TypeOf<
Expand Down Expand Up @@ -157,12 +157,12 @@ export interface HandshakeApiHandlerArgs extends ExternalServiceApiHandlerArgs {

export interface GetIssueTypesHandlerArgs {
externalService: ExternalService;
params: ExecutorSubActionGetIssueTypesParams;
params: ExecutorSubActionCommonFieldsParams;
}

export interface GetCommonFieldsHandlerArgs {
externalService: ExternalService;
params: ExecutorSubActionGetIssueTypesParams;
params: ExecutorSubActionCommonFieldsParams;
}

export interface GetFieldsByIssueTypeHandlerArgs {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,6 @@ export const ExternalIncidentServiceSecretConfigurationSchema = schema.object(
ExternalIncidentServiceSecretConfiguration
);

export const ExecutorSubActionSchema = schema.oneOf([
schema.literal('getIncident'),
schema.literal('pushToService'),
schema.literal('handshake'),
schema.literal('incidentTypes'),
schema.literal('severity'),
]);

export const ExecutorSubActionPushParamsSchema = schema.object({
incident: schema.object({
name: schema.string(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,6 @@ export const ExternalIncidentServiceSecretConfigurationSchema = schema.object(
ExternalIncidentServiceSecretConfiguration
);

export const ExecutorSubActionSchema = schema.oneOf([
schema.literal('getFields'),
schema.literal('getIncident'),
schema.literal('pushToService'),
schema.literal('handshake'),
schema.literal('getChoices'),
]);

const CommentsSchema = schema.nullable(
schema.arrayOf(
schema.object({
Expand Down
Loading

0 comments on commit 2dc1715

Please sign in to comment.