Skip to content

Commit

Permalink
[Security Solution] Add a missing domain tag to Endpoint Exceptions A…
Browse files Browse the repository at this point in the history
…PI (#193019)

**Addresses:** #183375

This PR adds a missing domain tag to Endpoint Exceptions API. The rest API endpoints got their tags in #189621.

(cherry picked from commit 09374ad)
  • Loading branch information
maximpn committed Nov 12, 2024
1 parent 8b6cb59 commit c055507
Show file tree
Hide file tree
Showing 95 changed files with 1,934 additions and 872 deletions.
13 changes: 8 additions & 5 deletions oas_docs/output/kibana.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33105,17 +33105,20 @@ components:
type: object
properties:
unit:
enum:
- s
- m
- h
type: string
$ref: >-
#/components/schemas/Security_Detections_API_AlertSuppressionDurationUnit
value:
minimum: 1
type: integer
required:
- value
- unit
Security_Detections_API_AlertSuppressionDurationUnit:
enum:
- s
- m
- h
type: string
Security_Detections_API_AlertSuppressionGroupBy:
items:
type: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -555,10 +555,15 @@ export const RuleExceptionList = z.object({
namespace_type: z.enum(['agnostic', 'single']),
});

export type AlertSuppressionDurationUnit = z.infer<typeof AlertSuppressionDurationUnit>;
export const AlertSuppressionDurationUnit = z.enum(['s', 'm', 'h']);
export type AlertSuppressionDurationUnitEnum = typeof AlertSuppressionDurationUnit.enum;
export const AlertSuppressionDurationUnitEnum = AlertSuppressionDurationUnit.enum;

export type AlertSuppressionDuration = z.infer<typeof AlertSuppressionDuration>;
export const AlertSuppressionDuration = z.object({
value: z.number().int().min(1),
unit: z.enum(['s', 'm', 'h']),
unit: AlertSuppressionDurationUnit,
});

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -581,18 +581,21 @@ components:
- type
- namespace_type

AlertSuppressionDurationUnit:
type: string
enum:
- s
- m
- h

AlertSuppressionDuration:
type: object
properties:
value:
type: integer
minimum: 1
unit:
type: string
enum:
- s
- m
- h
$ref: '#/components/schemas/AlertSuppressionDurationUnit'
required:
- value
- unit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1560,17 +1560,19 @@ components:
type: object
properties:
unit:
enum:
- s
- m
- h
type: string
$ref: '#/components/schemas/AlertSuppressionDurationUnit'
value:
minimum: 1
type: integer
required:
- value
- unit
AlertSuppressionDurationUnit:
enum:
- s
- m
- h
type: string
AlertSuppressionGroupBy:
items:
type: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -850,17 +850,19 @@ components:
type: object
properties:
unit:
enum:
- s
- m
- h
type: string
$ref: '#/components/schemas/AlertSuppressionDurationUnit'
value:
minimum: 1
type: integer
required:
- value
- unit
AlertSuppressionDurationUnit:
enum:
- s
- m
- h
type: string
AlertSuppressionGroupBy:
items:
type: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ export const uiPlugins = ({
insightsUpsellingMessage,
interactionsUpsellingMessage,
}: {
insightsUpsellingMessage: string | null;
interactionsUpsellingMessage: string | null;
insightsUpsellingMessage?: string;
interactionsUpsellingMessage?: string;
}) => {
const currentPlugins = nonStatefulUiPlugins.map((plugin) => plugin.name);
const insightPluginWithLicense = insightMarkdownPlugin.plugin({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ describe('plugin', () => {
});

it('show investigate message when insightsUpsellingMessage is not provided', () => {
const result = plugin({ insightsUpsellingMessage: null });
const result = plugin({ insightsUpsellingMessage: undefined });

expect(result.button.label).toEqual('Investigate');
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -541,11 +541,7 @@ const exampleInsight = `${insightPrefix}{
]
}}`;

export const plugin = ({
insightsUpsellingMessage,
}: {
insightsUpsellingMessage: string | null;
}) => {
export const plugin = ({ insightsUpsellingMessage }: { insightsUpsellingMessage?: string }) => {
return {
name: 'insights',
button: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ const OsqueryEditor = React.memo(OsqueryEditorComponent);
export const plugin = ({
interactionsUpsellingMessage,
}: {
interactionsUpsellingMessage: string | null;
interactionsUpsellingMessage?: string;
}) => {
return {
name: 'osquery',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ const TimelineEditor = memo(TimelineEditorComponent);
export const plugin = ({
interactionsUpsellingMessage,
}: {
interactionsUpsellingMessage: string | null;
interactionsUpsellingMessage?: string;
}): EuiMarkdownEditorUiPlugin => {
return {
name: ID,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ describe('use_upselling', () => {
expect(result.all.length).toBe(1); // assert that it should not cause unnecessary re-renders
});

test('useUpsellingMessage returns null when upsellingMessageId not found', () => {
test('useUpsellingMessage returns undefined when upsellingMessageId not found', () => {
const emptyMessages = {};
mockUpselling.setPages(emptyMessages);

Expand All @@ -81,6 +81,6 @@ describe('use_upselling', () => {
wrapper: RenderWrapper,
}
);
expect(result.current).toBe(null);
expect(result.current).toBeUndefined();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ export const useUpsellingComponent = (id: UpsellingSectionId): React.ComponentTy
return useMemo(() => upsellingSections?.get(id) ?? null, [id, upsellingSections]);
};

export const useUpsellingMessage = (id: UpsellingMessageId): string | null => {
export const useUpsellingMessage = (id: UpsellingMessageId): string | undefined => {
const upselling = useUpsellingService();
const upsellingMessages = useObservable(upselling.messages$, upselling.getMessagesValue());

return useMemo(() => upsellingMessages?.get(id) ?? null, [id, upsellingMessages]);
return useMemo(() => upsellingMessages?.get(id), [id, upsellingMessages]);
};

export const useUpsellingPage = (pageName: SecurityPageName): React.ComponentType | null => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { act, fireEvent, waitFor } from '@testing-library/react';

export function showEuiComboBoxOptions(comboBoxToggleButton: HTMLElement): Promise<void> {
fireEvent.click(comboBoxToggleButton);

return waitFor(() => {
const listWithOptionsElement = document.querySelector('[role="listbox"]');
const emptyListElement = document.querySelector('.euiComboBoxOptionsList__empty');

expect(listWithOptionsElement || emptyListElement).toBeInTheDocument();
});
}

type SelectEuiComboBoxOptionParameters =
| {
comboBoxToggleButton: HTMLElement;
optionIndex: number;
optionText?: undefined;
}
| {
comboBoxToggleButton: HTMLElement;
optionText: string;
optionIndex?: undefined;
};

export function selectEuiComboBoxOption({
comboBoxToggleButton,
optionIndex,
optionText,
}: SelectEuiComboBoxOptionParameters): Promise<void> {
return act(async () => {
await showEuiComboBoxOptions(comboBoxToggleButton);

const options = Array.from(
document.querySelectorAll('[data-test-subj*="comboBoxOptionsList"] [role="option"]')
);

if (typeof optionText === 'string') {
const optionToSelect = options.find((option) => option.textContent === optionText);

if (optionToSelect) {
fireEvent.click(optionToSelect);
} else {
throw new Error(
`Could not find option with text "${optionText}". Available options: ${options
.map((option) => option.textContent)
.join(', ')}`
);
}
} else {
fireEvent.click(options[optionIndex]);
}
});
}

export function selectFirstEuiComboBoxOption({
comboBoxToggleButton,
}: {
comboBoxToggleButton: HTMLElement;
}): Promise<void> {
return selectEuiComboBoxOption({ comboBoxToggleButton, optionIndex: 0 });
}

export function clearEuiComboBoxSelection({
clearButton,
}: {
clearButton: HTMLElement;
}): Promise<void> {
return act(async () => {
fireEvent.click(clearButton);
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import React, { memo } from 'react';
import { EuiPanel, EuiText, EuiToolTip } from '@elastic/eui';
import type { DataViewFieldBase } from '@kbn/es-query';
import { useFormData } from '../../../../../shared_imports';
import { MissingFieldsStrategySelector } from './missing_fields_strategy_selector';
import { SuppressionDurationSelector } from './suppression_duration_selector';
import { SuppressionFieldsSelector } from './suppression_fields_selector';
import { ALERT_SUPPRESSION_FIELDS_FIELD_NAME } from '../constants/fields';

interface AlertSuppressionEditProps {
suppressibleFields: DataViewFieldBase[];
labelAppend?: React.ReactNode;
disabled?: boolean;
disabledText?: string;
warningText?: string;
}

export const AlertSuppressionEdit = memo(function AlertSuppressionEdit({
suppressibleFields,
labelAppend,
disabled,
disabledText,
warningText,
}: AlertSuppressionEditProps): JSX.Element {
const [{ [ALERT_SUPPRESSION_FIELDS_FIELD_NAME]: suppressionFields }] = useFormData<{
[ALERT_SUPPRESSION_FIELDS_FIELD_NAME]: string[];
}>({
watch: ALERT_SUPPRESSION_FIELDS_FIELD_NAME,
});
const hasSelectedFields = suppressionFields?.length > 0;
const content = (
<>
<SuppressionFieldsSelector
suppressibleFields={suppressibleFields}
labelAppend={labelAppend}
disabled={disabled}
/>
{warningText && (
<EuiText size="xs" color="warning" data-test-subj="alertSuppressionWarning">
{warningText}
</EuiText>
)}
<EuiPanel paddingSize="m" hasShadow={false}>
<SuppressionDurationSelector disabled={disabled || !hasSelectedFields} />
<MissingFieldsStrategySelector disabled={disabled || !hasSelectedFields} />
</EuiPanel>
</>
);

return disabled && disabledText ? (
<EuiToolTip position="right" content={disabledText}>
{content}
</EuiToolTip>
) : (
content
);
});
Loading

0 comments on commit c055507

Please sign in to comment.