Skip to content

Commit

Permalink
Merge branch '7.x' into backport/7.x/pr-91991
Browse files Browse the repository at this point in the history
  • Loading branch information
kibanamachine authored Mar 1, 2021
2 parents 663b07d + 1e1540a commit 3ab0457
Show file tree
Hide file tree
Showing 80 changed files with 810 additions and 384 deletions.
22 changes: 22 additions & 0 deletions x-pack/plugins/alerts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Table of Contents
- [Usage](#usage)
- [Alerts API keys](#alerts-api-keys)
- [Limitations](#limitations)
- [Plugin status](#plugin-status)
- [Alert types](#alert-types)
- [Methods](#methods)
- [Executor](#executor)
Expand Down Expand Up @@ -79,6 +80,27 @@ Note that the `manage_own_api_key` cluster privilege is not enough - it can be u
is unauthorized for user [user-name-here]
```

## Plugin status

The plugin status of an alert is customized by including information about checking failures for the framework decryption:
```
core.status.set(
combineLatest([
core.status.derivedStatus$,
getHealthStatusStream(startPlugins.taskManager),
]).pipe(
map(([derivedStatus, healthStatus]) => {
if (healthStatus.level > derivedStatus.level) {
return healthStatus as ServiceStatus;
} else {
return derivedStatus;
}
})
)
);
```
To check for framework decryption failures, we use the task `alerting_health_check`, which runs every 60 minutes by default. To change the default schedule, use the kibana.yml configuration option `xpack.alerts.healthCheck.interval`.

## Alert types

### Methods
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ interface Tab {
key: string;
href: string;
text: ReactNode;
hidden?: boolean;
render: () => ReactNode;
}

Expand Down Expand Up @@ -126,6 +127,7 @@ export function ServiceDetailTabs({ serviceName, tab }: Props) {
const profilingTab = {
key: 'profiling',
href: useServiceProfilingHref({ serviceName }),
hidden: !config.profilingEnabled,
text: (
<EuiFlexGroup direction="row" gutterSize="s">
<EuiFlexItem>
Expand Down Expand Up @@ -167,22 +169,20 @@ export function ServiceDetailTabs({ serviceName, tab }: Props) {
tabs.push(metricsTab);
}

tabs.push(serviceMapTab);

if (config.profilingEnabled) {
tabs.push(profilingTab);
}
tabs.push(serviceMapTab, profilingTab);

const selectedTab = tabs.find((serviceTab) => serviceTab.key === tab);

return (
<>
<MainTabs>
{tabs.map(({ href, key, text }) => (
<EuiTab href={href} isSelected={key === tab} key={key}>
{text}
</EuiTab>
))}
{tabs
.filter((t) => !t.hidden)
.map(({ href, key, text }) => (
<EuiTab href={href} isSelected={key === tab} key={key}>
{text}
</EuiTab>
))}
<div style={{ marginLeft: 'auto' }}>
<Correlations />
</div>
Expand Down
35 changes: 0 additions & 35 deletions x-pack/plugins/case/common/api/cases/commentable_case.ts

This file was deleted.

1 change: 0 additions & 1 deletion x-pack/plugins/case/common/api/cases/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,3 @@ export * from './comment';
export * from './status';
export * from './user_actions';
export * from './sub_case';
export * from './commentable_case';
8 changes: 4 additions & 4 deletions x-pack/plugins/case/common/api/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ export const getSubCasesUrl = (caseID: string): string => {
return SUB_CASES_URL.replace('{case_id}', caseID);
};

export const getSubCaseDetailsUrl = (caseID: string, subCaseID: string): string => {
return SUB_CASE_DETAILS_URL.replace('{case_id}', caseID).replace('{sub_case_id}', subCaseID);
export const getSubCaseDetailsUrl = (caseID: string, subCaseId: string): string => {
return SUB_CASE_DETAILS_URL.replace('{case_id}', caseID).replace('{sub_case_id}', subCaseId);
};

export const getCaseCommentsUrl = (id: string): string => {
Expand All @@ -40,8 +40,8 @@ export const getCaseUserActionUrl = (id: string): string => {
return CASE_USER_ACTIONS_URL.replace('{case_id}', id);
};

export const getSubCaseUserActionUrl = (caseID: string, subCaseID: string): string => {
return SUB_CASE_USER_ACTIONS_URL.replace('{case_id}', caseID).replace('{sub_case_id}', subCaseID);
export const getSubCaseUserActionUrl = (caseID: string, subCaseId: string): string => {
return SUB_CASE_USER_ACTIONS_URL.replace('{case_id}', caseID).replace('{sub_case_id}', subCaseId);
};

export const getCasePushUrl = (caseId: string, connectorId: string): string => {
Expand Down
27 changes: 25 additions & 2 deletions x-pack/plugins/case/common/api/runtime_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,37 @@ import { either, fold } from 'fp-ts/lib/Either';
import { identity } from 'fp-ts/lib/function';
import { pipe } from 'fp-ts/lib/pipeable';
import * as rt from 'io-ts';
import { failure } from 'io-ts/lib/PathReporter';
import { isObject } from 'lodash/fp';

type ErrorFactory = (message: string) => Error;

export const formatErrors = (errors: rt.Errors): string[] => {
const err = errors.map((error) => {
if (error.message != null) {
return error.message;
} else {
const keyContext = error.context
.filter(
(entry) => entry.key != null && !Number.isInteger(+entry.key) && entry.key.trim() !== ''
)
.map((entry) => entry.key)
.join(',');

const nameContext = error.context.find((entry) => entry.type?.name?.length > 0);
const suppliedValue =
keyContext !== '' ? keyContext : nameContext != null ? nameContext.type.name : '';
const value = isObject(error.value) ? JSON.stringify(error.value) : error.value;
return `Invalid value "${value}" supplied to "${suppliedValue}"`;
}
});

return [...new Set(err)];
};

export const createPlainError = (message: string) => new Error(message);

export const throwErrors = (createError: ErrorFactory) => (errors: rt.Errors) => {
throw createError(failure(errors).join('\n'));
throw createError(formatErrors(errors).join());
};

export const decodeOrThrow = <A, O, I>(
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/case/server/client/cases/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export interface TransformFieldsArgs<P, S> {

export interface ExternalServiceComment {
comment: string;
commentId?: string;
commentId: string;
}

export interface MapIncident {
Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/case/server/client/cases/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,7 @@ describe('utils', () => {
},
{
comment: 'Elastic Security Alerts attached to the case: 3',
commentId: 'mock-id-1-total-alerts',
},
]);
});
Expand Down Expand Up @@ -569,6 +570,7 @@ describe('utils', () => {
},
{
comment: 'Elastic Security Alerts attached to the case: 4',
commentId: 'mock-id-1-total-alerts',
},
]);
});
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/case/server/client/cases/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ export const createIncident = async ({
if (totalAlerts > 0) {
comments.push({
comment: `Elastic Security Alerts attached to the case: ${totalAlerts}`,
commentId: `${theCase.id}-total-alerts`,
});
}

Expand Down
6 changes: 3 additions & 3 deletions x-pack/plugins/case/server/client/comments/add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
CaseType,
SubCaseAttributes,
CommentRequest,
CollectionWithSubCaseResponse,
CaseResponse,
User,
CommentRequestAlertType,
AlertCommentRequestRt,
Expand Down Expand Up @@ -113,7 +113,7 @@ const addGeneratedAlerts = async ({
caseClient,
caseId,
comment,
}: AddCommentFromRuleArgs): Promise<CollectionWithSubCaseResponse> => {
}: AddCommentFromRuleArgs): Promise<CaseResponse> => {
const query = pipe(
AlertCommentRequestRt.decode(comment),
fold(throwErrors(Boom.badRequest), identity)
Expand Down Expand Up @@ -260,7 +260,7 @@ export const addComment = async ({
caseId,
comment,
user,
}: AddCommentArgs): Promise<CollectionWithSubCaseResponse> => {
}: AddCommentArgs): Promise<CaseResponse> => {
const query = pipe(
CommentRequestRt.decode(comment),
fold(throwErrors(Boom.badRequest), identity)
Expand Down
3 changes: 1 addition & 2 deletions x-pack/plugins/case/server/client/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
CasesPatchRequest,
CasesResponse,
CaseStatuses,
CollectionWithSubCaseResponse,
CommentRequest,
ConnectorMappingsAttributes,
GetFieldsResponse,
Expand Down Expand Up @@ -89,7 +88,7 @@ export interface ConfigureFields {
* This represents the interface that other plugins can access.
*/
export interface CaseClient {
addComment(args: CaseClientAddComment): Promise<CollectionWithSubCaseResponse>;
addComment(args: CaseClientAddComment): Promise<CaseResponse>;
create(theCase: CasePostRequest): Promise<CaseResponse>;
get(args: CaseClientGet): Promise<CaseResponse>;
getAlerts(args: CaseClientGetAlerts): Promise<CaseClientGetAlertsResponse>;
Expand Down
63 changes: 41 additions & 22 deletions x-pack/plugins/case/server/common/models/commentable_case.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ import {
CaseSettings,
CaseStatuses,
CaseType,
CollectionWithSubCaseResponse,
CollectWithSubCaseResponseRt,
CaseResponse,
CaseResponseRt,
CommentAttributes,
CommentPatchRequest,
CommentRequest,
Expand Down Expand Up @@ -254,7 +254,7 @@ export class CommentableCase {
};
}

public async encode(): Promise<CollectionWithSubCaseResponse> {
public async encode(): Promise<CaseResponse> {
const collectionCommentStats = await this.service.getAllCaseComments({
client: this.soClient,
id: this.collection.id,
Expand All @@ -265,22 +265,6 @@ export class CommentableCase {
},
});

if (this.subCase) {
const subCaseComments = await this.service.getAllSubCaseComments({
client: this.soClient,
id: this.subCase.id,
});

return CollectWithSubCaseResponseRt.encode({
subCase: flattenSubCaseSavedObject({
savedObject: this.subCase,
comments: subCaseComments.saved_objects,
totalAlerts: countAlertsForID({ comments: subCaseComments, id: this.subCase.id }),
}),
...this.formatCollectionForEncoding(collectionCommentStats.total),
});
}

const collectionComments = await this.service.getAllCaseComments({
client: this.soClient,
id: this.collection.id,
Expand All @@ -291,10 +275,45 @@ export class CommentableCase {
},
});

return CollectWithSubCaseResponseRt.encode({
const collectionTotalAlerts =
countAlertsForID({ comments: collectionComments, id: this.collection.id }) ?? 0;

const caseResponse = {
comments: flattenCommentSavedObjects(collectionComments.saved_objects),
totalAlerts: countAlertsForID({ comments: collectionComments, id: this.collection.id }),
totalAlerts: collectionTotalAlerts,
...this.formatCollectionForEncoding(collectionCommentStats.total),
});
};

if (this.subCase) {
const subCaseComments = await this.service.getAllSubCaseComments({
client: this.soClient,
id: this.subCase.id,
});
const totalAlerts = countAlertsForID({ comments: subCaseComments, id: this.subCase.id }) ?? 0;

return CaseResponseRt.encode({
...caseResponse,
/**
* For now we need the sub case comments and totals to be exposed on the top level of the response so that the UI
* functionality can stay the same. Ideally in the future we can refactor this so that the UI will look for the
* comments either in the top level for a case or a collection or in the subCases field if it is a sub case.
*
* If we ever need to return both the collection's comments and the sub case comments we'll need to refactor it then
* as well.
*/
comments: flattenCommentSavedObjects(subCaseComments.saved_objects),
totalComment: subCaseComments.saved_objects.length,
totalAlerts,
subCases: [
flattenSubCaseSavedObject({
savedObject: this.subCase,
totalComment: subCaseComments.saved_objects.length,
totalAlerts,
}),
],
});
}

return CaseResponseRt.encode(caseResponse);
}
}
4 changes: 2 additions & 2 deletions x-pack/plugins/case/server/connectors/case/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import {
AssociationType,
CaseResponse,
CasesResponse,
CollectionWithSubCaseResponse,
} from '../../../common/api';
import {
connectorMappingsServiceMock,
Expand Down Expand Up @@ -1018,9 +1017,10 @@ describe('case connector', () => {

describe('addComment', () => {
it('executes correctly', async () => {
const commentReturn: CollectionWithSubCaseResponse = {
const commentReturn: CaseResponse = {
id: 'mock-it',
totalComment: 0,
totalAlerts: 0,
version: 'WzksMV0=',

closed_at: null,
Expand Down
4 changes: 2 additions & 2 deletions x-pack/plugins/case/server/connectors/case/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
ConnectorSchema,
CommentSchema,
} from './schema';
import { CaseResponse, CasesResponse, CollectionWithSubCaseResponse } from '../../../common/api';
import { CaseResponse, CasesResponse } from '../../../common/api';

export type CaseConfiguration = TypeOf<typeof CaseConfigurationSchema>;
export type Connector = TypeOf<typeof ConnectorSchema>;
Expand All @@ -29,7 +29,7 @@ export type ExecutorSubActionAddCommentParams = TypeOf<
>;

export type CaseExecutorParams = TypeOf<typeof CaseExecutorParamsSchema>;
export type CaseExecutorResponse = CaseResponse | CasesResponse | CollectionWithSubCaseResponse;
export type CaseExecutorResponse = CaseResponse | CasesResponse;

export type CaseActionType = ActionType<
CaseConfiguration,
Expand Down
Loading

0 comments on commit 3ab0457

Please sign in to comment.