Skip to content
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

[7.x] [Security Solution] [Cases] Swimlane Connector for Cases (#100086) #103165

Merged
merged 1 commit into from
Jun 23, 2021
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
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