Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
94ad784
api changes for suggestions and search strat
parkiino Jun 5, 2025
56d16db
Merge remote-tracking branch 'upstream/main' into task/api-TA-endpoin…
parkiino Jun 5, 2025
202cdfc
Merge remote-tracking branch 'upstream/main' into task/api-TA-endpoin…
parkiino Jun 8, 2025
44875dc
experimental flag and advanced mode button
parkiino Jun 13, 2025
1f81deb
Merge remote-tracking branch 'upstream/main' into task/api-TA-endpoin…
parkiino Jun 13, 2025
bc2f0d8
working advanced mode toggle that updates tag
parkiino Jun 13, 2025
8b01dee
update ta api client and add search strat and suggestions
parkiino Jun 16, 2025
81c87ff
save advanced and basic entries in state and update when toggle changes
parkiino Jun 17, 2025
58ce2d0
wip add exception builder component
parkiino Jun 23, 2025
6c0a3c2
apply konrads patch + fix suggestions request type
parkiino Jun 25, 2025
18ec7c4
Merge remote-tracking branch 'upstream/main' into task/api-TA-endpoin…
parkiino Jun 25, 2025
a4b20d1
Merge remote-tracking branch 'upstream/main' into task/api-TA-endpoin…
parkiino Jun 25, 2025
b6ac16e
adjust spacing, remove unused logger prop, move warning placement
parkiino Jun 26, 2025
9639053
do not do write/read transform for advanced mode entries
parkiino Jul 3, 2025
5ef039d
fix mode change and add advanced mode warning
parkiino Jul 3, 2025
81ea030
Merge remote-tracking branch 'upstream/main' into task/api-TA-endpoin…
parkiino Jul 7, 2025
e3cccdd
[CI] Auto-commit changed files from 'node scripts/styled_components_m…
kibanamachine Jul 7, 2025
9da7d6d
[CI] Auto-commit changed files from 'node scripts/eslint_all_files --…
kibanamachine Jul 7, 2025
8b74e7d
fix logic to show warning text and advanced mode form
parkiino Jul 8, 2025
17386fd
Merge branch 'task/api-TA-endpointSearchStrat-suggestions' of github.…
parkiino Jul 8, 2025
1ec6df5
linting
parkiino Jul 8, 2025
bf09d1f
move common utils, adjust button group to be right aligned
parkiino Jul 8, 2025
e086f88
[CI] Auto-commit changed files from 'node scripts/eslint_all_files --…
kibanamachine Jul 8, 2025
9e34298
fix broken test
parkiino Jul 9, 2025
736c62f
Mt push:wq::
parkiino Jul 9, 2025
8d13553
[CI] Auto-commit changed files from 'node scripts/eslint_all_files --…
kibanamachine Jul 9, 2025
cd86aca
trusted apps operators not modified, renamed event filters operators …
parkiino Jul 11, 2025
0597e5b
Merge branch 'task/api-TA-endpointSearchStrat-suggestions' of github.…
parkiino Jul 11, 2025
fedcf7b
Merge branch 'main' into task/api-TA-endpointSearchStrat-suggestions
tomsonpl Jul 14, 2025
a65b0eb
[CI] Auto-commit changed files from 'node scripts/eslint_all_files --…
kibanamachine Jul 14, 2025
5c05b73
fix broken tests
parkiino Jul 18, 2025
bf1d056
Merge branch 'task/api-TA-endpointSearchStrat-suggestions' of github.…
parkiino Jul 18, 2025
b5100ca
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Jul 18, 2025
ed1232f
[CI] Auto-commit changed files from 'node scripts/eslint_all_files --…
kibanamachine Jul 18, 2025
53b8c96
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Jul 18, 2025
813554f
text chagnes
parkiino Jul 22, 2025
89912d2
Merge remote-tracking branch 'upstream/main' into task/api-TA-endpoin…
parkiino Jul 22, 2025
3b73cca
Merge remote-tracking branch 'upstream/main' into task/api-TA-endpoin…
parkiino Jul 22, 2025
99ab3f4
wip form tests
parkiino Jul 24, 2025
822ad25
Merge branch 'task/api-TA-endpointSearchStrat-suggestions' of github.…
parkiino Jul 24, 2025
212af77
[CI] Auto-commit changed files from 'node scripts/eslint_all_files --…
kibanamachine Jul 24, 2025
b47c8e6
tests for now
parkiino Jul 25, 2025
558feea
Merge branch 'task/api-TA-endpointSearchStrat-suggestions' of github.…
parkiino Jul 25, 2025
8b8da62
Merge remote-tracking branch 'upstream/main' into task/api-TA-endpoin…
parkiino Jul 25, 2025
fb0d0cd
Merge remote-tracking branch 'upstream/main' into task/api-TA-endpoin…
parkiino Jul 28, 2025
d149a09
fix tests add feature flag mock
parkiino Jul 28, 2025
1c5b629
[CI] Auto-commit changed files from 'node scripts/eslint_all_files --…
kibanamachine Jul 28, 2025
0c64b93
Merge remote-tracking branch 'upstream/main' into task/api-TA-endpoin…
parkiino Jul 29, 2025
178ee56
Merge branch 'task/api-TA-endpointSearchStrat-suggestions' of github.…
parkiino Jul 29, 2025
4477186
rename var
parkiino Jul 31, 2025
d7da4a5
Merge remote-tracking branch 'upstream/main' into task/api-TA-endpoin…
parkiino Jul 31, 2025
cc87354
[CI] Auto-commit changed files from 'node scripts/eslint_all_files --…
kibanamachine Jul 31, 2025
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
1 change: 0 additions & 1 deletion packages/kbn-babel-preset/styled_components_files.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import {
doesNotExistOperator,
EVENT_FILTERS_OPERATORS,
ENDPOINT_ARTIFACT_OPERATORS,
ALL_OPERATORS,
existsOperator,
isNotOperator,
Expand Down Expand Up @@ -46,7 +46,7 @@ describe('#getOperators', () => {
type: 'simple',
});

expect(operator).toEqual(EVENT_FILTERS_OPERATORS);
expect(operator).toEqual(ENDPOINT_ARTIFACT_OPERATORS);
});

test('it returns all operator types when field type is not null, boolean, or nested', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { DataViewFieldBase } from '@kbn/es-query';

import {
ALL_OPERATORS,
EVENT_FILTERS_OPERATORS,
ENDPOINT_ARTIFACT_OPERATORS,
OperatorOption,
doesNotExistOperator,
existsOperator,
Expand All @@ -31,7 +31,7 @@ export const getOperators = (field: DataViewFieldBase | undefined): OperatorOpti
} else if (field.type === 'nested') {
return [isOperator];
} else if (field.name === 'file.path.text') {
return EVENT_FILTERS_OPERATORS;
return ENDPOINT_ARTIFACT_OPERATORS;
} else {
return ALL_OPERATORS;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,10 @@ export const doesNotMatchOperator: OperatorOption = {
value: 'does_not_match',
};

export const EVENT_FILTERS_OPERATORS: OperatorOption[] = [
/**
* Operators valid for event filters, trusted apps and endpoint exceptions
*/
export const ENDPOINT_ARTIFACT_OPERATORS: OperatorOption[] = [
isOperator,
isNotOperator,
isOneOfOperator,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
import styled from 'styled-components';
import {
ExceptionListType,
ExceptionListTypeEnum,
ListSchema,
ListOperatorTypeEnum as OperatorTypeEnum,
OsTypeArray,
Expand Down Expand Up @@ -322,12 +323,13 @@ export const BuilderEntryItem: React.FC<EntryItemProps> = ({
);

const renderOperatorInput = (isFirst: boolean): JSX.Element => {
// for event filters forms
// show extra operators for wildcards when field supports matches
// Extra operators for wildcards will be removed if the field does not support matches
const doesFieldSupportMatches = entry.field !== undefined && fieldSupportsMatches(entry.field);
const isEventFilterList = listType === 'endpoint_events';
const isEventFilterList = listType === ExceptionListTypeEnum.ENDPOINT_EVENTS;
const isTrustedAppsList = listType === ExceptionListTypeEnum.ENDPOINT_TRUSTED_APPS;

const augmentedOperatorsList =
operatorsList && doesFieldSupportMatches && isEventFilterList
operatorsList && doesFieldSupportMatches && (isEventFilterList || isTrustedAppsList)
? operatorsList
: operatorsList?.filter((operator) => operator.type !== OperatorTypeEnum.WILDCARD);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import React, { ElementType, useCallback, useEffect, useMemo, useReducer, useState } from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import styled from 'styled-components';
import { HttpStart } from '@kbn/core/public';
import { addIdToItem } from '@kbn/securitysolution-utils';
Expand Down Expand Up @@ -53,7 +53,7 @@ const MyAndBadge = styled(AndOrBadge)`
`;

const MyButtonsContainer = styled(EuiFlexItem)`
margin: 16px 0;
margin: 8px 0;
`;

const initialState: State = {
Expand Down Expand Up @@ -475,8 +475,6 @@ export const ExceptionBuilderComponent = ({
</EuiFlexItem>
))}

<EuiSpacer size="m" />

<MyButtonsContainer data-test-subj={`andOrOperatorButtons`}>
<EuiFlexGroup gutterSize="s">
{andLogicIncluded && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ export const EndpointSuggestionsSchema = {
fieldMeta: schema.maybe(schema.any()),
}),
params: schema.object({
suggestion_type: schema.oneOf([schema.literal('eventFilters'), schema.literal('endpoints')]),
suggestion_type: schema.oneOf([
schema.literal('eventFilters'),
schema.literal('endpoints'),
schema.literal('trustedApps'),
]),
}),
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@

import type { EntryMatch } from '@kbn/securitysolution-io-ts-list-types';
import { ENDPOINT_ARTIFACT_LIST_IDS } from '@kbn/securitysolution-list-constants';
import { EVENT_FILTERS_OPERATORS } from '@kbn/securitysolution-list-utils';
import { ENDPOINT_ARTIFACT_OPERATORS } from '@kbn/securitysolution-list-utils';

export const BY_POLICY_ARTIFACT_TAG_PREFIX = 'policy:';

export const GLOBAL_ARTIFACT_TAG = `${BY_POLICY_ARTIFACT_TAG_PREFIX}all`;

export const ADVANCED_MODE_TAG = 'form_mode:advanced';

export const FILTER_PROCESS_DESCENDANTS_TAG = 'filter_process_descendants';

/** The tag prefix that tracks the space(s) that is considered the "owner" of the artifact. */
Expand All @@ -28,7 +30,7 @@ export const PROCESS_DESCENDANT_EVENT_FILTER_EXTRA_ENTRY: EntryMatch = Object.fr
export const PROCESS_DESCENDANT_EVENT_FILTER_EXTRA_ENTRY_TEXT: string = `${
PROCESS_DESCENDANT_EVENT_FILTER_EXTRA_ENTRY.field
} ${
EVENT_FILTERS_OPERATORS.find(
ENDPOINT_ARTIFACT_OPERATORS.find(
({ type }) => type === PROCESS_DESCENDANT_EVENT_FILTER_EXTRA_ENTRY.type
)?.message
} ${PROCESS_DESCENDANT_EVENT_FILTER_EXTRA_ENTRY.value}`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ export {
getArtifactTagsByPolicySelection,
} from './utils';

export { BY_POLICY_ARTIFACT_TAG_PREFIX, GLOBAL_ARTIFACT_TAG } from './constants';
export { BY_POLICY_ARTIFACT_TAG_PREFIX, GLOBAL_ARTIFACT_TAG, ADVANCED_MODE_TAG } from './constants';
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
FILTER_PROCESS_DESCENDANTS_TAG,
GLOBAL_ARTIFACT_TAG,
OWNER_SPACE_ID_TAG_PREFIX,
ADVANCED_MODE_TAG,
} from './constants';

export type TagFilter = (tag: string) => boolean;
Expand Down Expand Up @@ -122,6 +123,12 @@ export const getEffectedPolicySelectionByTags = (
};
};

export const isAdvancedModeEnabled = (
item: Partial<Pick<ExceptionListItemSchema, 'tags'>>
): boolean => (item.tags ?? []).includes(ADVANCED_MODE_TAG);

export const isAdvancedModeTag: TagFilter = (tag) => tag === ADVANCED_MODE_TAG;

export const isFilterProcessDescendantsEnabled = (
item: Partial<Pick<ExceptionListItemSchema, 'tags'>>
): boolean => (item.tags ?? []).includes(FILTER_PROCESS_DESCENDANTS_TAG);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,26 @@ export const parsePoliciesAndFilterToKql = ({
const policiesKQL = parsePoliciesToKQL(policies, excludedPolicies);
return `(${policiesKQL})${kuery ? ` AND (${kuery})` : ''}`;
};

/**
* Counts the number of conditions added for a new Event filter or Trusted app
* @param formFields
* @returns number of fields
*/
export const getAddedFieldsCounts = (formFields: string[]): { [k: string]: number } =>
formFields.reduce<{ [k: string]: number }>((allFields, field) => {
if (field in allFields) {
allFields[field]++;
} else {
allFields[field] = 1;
}
return allFields;
}, {});

/**
* Checks if conditions in Event filters or Trusted Apps forms have duplicate fields
* @param formFields
* @returns boolean
*/
export const computeHasDuplicateFields = (formFieldsMap: Record<string, number>): boolean =>
Object.values(formFieldsMap).some((e) => e > 1);
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ const StyledEuiFlexItemButtonGroup = styled(EuiFlexItem)`
}
`;

const StyledButtonGroup = styled(EuiButtonGroup)`
export const StyledButtonGroup = styled(EuiButtonGroup)`
display: flex;
justify-content: right;
.euiButtonGroupButton {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ export { useSummaryArtifact } from './use_summary_artifact';
export { useBulkUpdateArtifact } from './use_bulk_update_artifact';
export { useBulkDeleteArtifact } from './use_bulk_delete_artifact';
export { useGetUpdatedTags } from './use_get_updated_tags';
export { useCanAssignArtifactPerPolicy } from './use_can_assign_artifact_per_policy';
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-t
import { useCallback } from 'react';
import type { TagFilter } from '../../../../common/endpoint/service/artifacts/utils';
import {
isAdvancedModeTag,
isOwnerSpaceIdTag,
isFilterProcessDescendantsTag,
isPolicySelectionTag,
Expand All @@ -23,6 +24,7 @@ type GetTagsUpdatedBy<TagFilters> = (tagType: keyof TagFilters, newTags: string[
const DEFAULT_FILTERS = Object.freeze({
policySelection: isPolicySelectionTag,
processDescendantsFiltering: isFilterProcessDescendantsTag,
advancedMode: isAdvancedModeTag,
ownerSpaceId: isOwnerSpaceIdTag,
} as const);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { css } from '@emotion/react';

import type { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types';
import {
EVENT_FILTERS_OPERATORS,
ENDPOINT_ARTIFACT_OPERATORS,
hasWrongOperatorWithWildcard,
hasPartialCodeSignatureEntry,
} from '@kbn/securitysolution-list-utils';
Expand Down Expand Up @@ -61,6 +61,7 @@ import { useFetchIndex } from '../../../../../common/containers/source';
import { Loader } from '../../../../../common/components/loader';
import { useKibana } from '../../../../../common/lib/kibana';
import type { ArtifactFormComponentProps } from '../../../../components/artifact_list_page';
import { getAddedFieldsCounts, computeHasDuplicateFields } from '../../../../common/utils';

import {
ABOUT_EVENT_FILTERS,
Expand Down Expand Up @@ -92,19 +93,6 @@ const osOptions: Array<EuiSuperSelectOption<OperatingSystem>> = OPERATING_SYSTEM
inputDisplay: OS_TITLES[os],
}));

const getAddedFieldsCounts = (formFields: string[]): { [k: string]: number } =>
formFields.reduce<{ [k: string]: number }>((allFields, field) => {
if (field in allFields) {
allFields[field]++;
} else {
allFields[field] = 1;
}
return allFields;
}, {});

const computeHasDuplicateFields = (formFieldsList: Record<string, number>): boolean =>
Object.values(formFieldsList).some((e) => e > 1);

const defaultConditionEntry = (): ExceptionListItemSchema['entries'] => [
{
field: '',
Expand Down Expand Up @@ -586,7 +574,7 @@ export const EventFiltersForm: React.FC<ArtifactFormComponentProps & { allowSele
dataTestSubj: 'alert-exception-builder',
idAria: 'alert-exception-builder',
onChange: handleOnBuilderChange,
operatorsList: EVENT_FILTERS_OPERATORS,
operatorsList: ENDPOINT_ARTIFACT_OPERATORS,
osTypes: exception.os_types,
showValueListModal: ShowValueListModal,
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,20 @@
* 2.0.
*/

import type { CreateExceptionListSchema } from '@kbn/securitysolution-io-ts-list-types';
import type {
CreateExceptionListSchema,
ExceptionListType,
} from '@kbn/securitysolution-io-ts-list-types';
import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
import {
ENDPOINT_TRUSTED_APPS_LIST_DESCRIPTION,
ENDPOINT_TRUSTED_APPS_LIST_ID,
ENDPOINT_TRUSTED_APPS_LIST_NAME,
} from '@kbn/securitysolution-list-constants';

export const TRUSTED_APPS_LIST_TYPE: ExceptionListType =
ExceptionListTypeEnum.ENDPOINT_TRUSTED_APPS;

export const SEARCHABLE_FIELDS: Readonly<string[]> = [
`name`,
`description`,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* 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 type { HttpSetup } from '@kbn/core-http-browser';
import { TrustedAppsApiClient } from './api_client';
import { coreMock } from '@kbn/core/public/mocks';
import { SUGGESTIONS_INTERNAL_ROUTE } from '../../../../../common/endpoint/constants';
import { resolvePathVariables } from '../../../../common/utils/resolve_path_variables';

describe('TrustedAppsApiClient', () => {
let fakeHttpServices: jest.Mocked<HttpSetup>;
let trustedAppsApiClient: TrustedAppsApiClient;

beforeAll(() => {
fakeHttpServices = coreMock.createStart().http as jest.Mocked<HttpSetup>;
trustedAppsApiClient = new TrustedAppsApiClient(fakeHttpServices);
});

beforeEach(() => {
jest.clearAllMocks();
});

it('should call the SUGGESTIONS_INTERNAL_ROUTE with correct URL and body', async () => {
await trustedAppsApiClient.getSuggestions({
field: 'host.name',
query: 'test',
});

expect(fakeHttpServices.post).toHaveBeenCalledWith(
resolvePathVariables(SUGGESTIONS_INTERNAL_ROUTE, { suggestion_type: 'trustedApps' }),
{
version: '1',
body: JSON.stringify({
field: 'host.name',
query: 'test',
}),
}
);
});
});
Loading