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

[Security Solution][Endpoint] Port trusted apps to ArtifactlsListPage component #129208

Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
e37c34c
move validations to artifacts
ashokaditya Apr 1, 2022
5599cc2
use ArtifactsListPage
ashokaditya Apr 1, 2022
b91215b
Remove redundant files
ashokaditya Apr 5, 2022
c90fba3
Update trusted app list ftr test
ashokaditya Apr 5, 2022
b296f41
fix test mock
ashokaditya Apr 5, 2022
a5636f2
add trusted app form tests
ashokaditya Apr 6, 2022
e922e14
Merge branch 'main' into task/olm-3092-port-trusted-apps-to-ArtifactL…
ashokaditya Apr 19, 2022
d246bb8
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine Apr 19, 2022
ea38543
Merge branch 'main' into task/olm-3092-port-trusted-apps-to-ArtifactL…
ashokaditya Apr 19, 2022
82e6df8
Merge branch 'main' into task/olm-3092-port-trusted-apps-to-ArtifactL…
ashokaditya Apr 19, 2022
f52f60b
default page index to 1 when set to 0
ashokaditya Apr 20, 2022
e82f9ac
add tests for new routing methods
ashokaditya Apr 20, 2022
fbaa8c7
review changes
ashokaditya Apr 20, 2022
534efeb
update fleet integration test
ashokaditya Apr 20, 2022
6a792fc
Merge branch 'main' into task/olm-3092-port-trusted-apps-to-ArtifactL…
ashokaditya Apr 20, 2022
2b2509d
update translation again after merge
ashokaditya Apr 20, 2022
0567f36
Merge branch 'main' into task/olm-3092-port-trusted-apps-to-ArtifactL…
ashokaditya Apr 20, 2022
8527db8
Merge branch 'main' into task/olm-3092-port-trusted-apps-to-ArtifactL…
ashokaditya Apr 21, 2022
3d2cdbc
add a test for search field KQL
ashokaditya Apr 21, 2022
87a649e
remove redundant flyout size
ashokaditya Apr 21, 2022
06f0330
Merge branch 'main' into task/olm-3092-port-trusted-apps-to-ArtifactL…
ashokaditya Apr 21, 2022
83c4e1c
Update trusted_apps_list.test.tsx
ashokaditya Apr 21, 2022
4d287a6
Merge branch 'main' into task/olm-3092-port-trusted-apps-to-ArtifactL…
kibanamachine Apr 21, 2022
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
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import { schema } from '@kbn/config-schema';
import { ConditionEntryField, OperatingSystem } from '@kbn/securitysolution-utils';
import { TrustedAppConditionEntry } from '../types';
import { getDuplicateFields, isValidHash } from '../service/trusted_apps/validations';
import { getDuplicateFields, isValidHash } from '../service/artifacts/validations';

export const DeleteTrustedAppsRequestSchema = {
params: schema.object({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

import { EndpointAction } from '../../management/pages/endpoint_hosts/store/action';
import { PolicyDetailsAction } from '../../management/pages/policy/store/policy_details';
import { TrustedAppsPageAction } from '../../management/pages/trusted_apps/store/action';
import { EventFiltersPageAction } from '../../management/pages/event_filters/store/action';

export { appActions } from './app';
Expand All @@ -20,5 +19,4 @@ export type AppAction =
| EndpointAction
| RoutingAction
| PolicyDetailsAction
| TrustedAppsPageAction
| EventFiltersPageAction;
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
* 2.0.
*/

import { extractTrustedAppsListPageLocation, getTrustedAppsListPath } from './routing';
import type { ArtifactListPageLocation } from '../types';
import { getTrustedAppsListPath, extractTrustedAppsListPageLocation } from './routing';
import { MANAGEMENT_DEFAULT_PAGE, MANAGEMENT_DEFAULT_PAGE_SIZE } from './constants';
import { TrustedAppsListPageLocation } from '../pages/trusted_apps/state';

describe('routing', () => {
describe('extractListPaginationParams()', () => {
Expand Down Expand Up @@ -76,24 +76,6 @@ describe('routing', () => {
it('extracts default "show" when single invalid value provided', () => {
expect(extractTrustedAppsListPageLocation({ show: 'invalid' }).show).toBeUndefined();
});

it('extracts proper view type when single valid value provided', () => {
expect(extractTrustedAppsListPageLocation({ view_type: 'list' }).view_type).toBe('list');
});

it('extracts only last view type when multiple values provided', () => {
expect(extractTrustedAppsListPageLocation({ view_type: ['grid', 'list'] }).view_type).toBe(
'list'
);
});

it('extracts default view type when no value provided', () => {
expect(extractTrustedAppsListPageLocation({}).view_type).toBe('grid');
});

it('extracts default view type when single invalid value provided', () => {
expect(extractTrustedAppsListPageLocation({ view_type: 'invalid' }).view_type).toBe('grid');
});
});

describe('getTrustedAppsListPath()', () => {
Expand Down Expand Up @@ -124,82 +106,70 @@ describe('routing', () => {
expect(getTrustedAppsListPath({ show })).toEqual(`/administration/trusted_apps?show=${show}`);
});

it('builds proper path when only view type provided', () => {
const viewType = 'list';
expect(getTrustedAppsListPath({ view_type: viewType })).toEqual(
`/administration/trusted_apps?view_type=${viewType}`
);
});

it('builds proper path when all params provided', () => {
const location: TrustedAppsListPageLocation = {
const location: ArtifactListPageLocation = {
page_index: 2,
page_size: 20,
show: 'create',
view_type: 'list',
filter: 'test',
included_policies: 'globally',
};

expect(getTrustedAppsListPath(location)).toEqual(
`/administration/trusted_apps?page_index=${location.page_index}&page_size=${location.page_size}&view_type=${location.view_type}&show=${location.show}&filter=${location.filter}&included_policies=${location.included_policies}`
`/administration/trusted_apps?page_index=${location.page_index}&page_size=${location.page_size}&show=${location.show}&filter=${location.filter}&included_policies=${location.included_policies}`
);
});

it('builds proper path when page index is equal to default', () => {
const location: TrustedAppsListPageLocation = {
const location: ArtifactListPageLocation = {
page_index: MANAGEMENT_DEFAULT_PAGE,
page_size: 20,
show: 'create',
view_type: 'list',
filter: '',
included_policies: '',
};
const path = getTrustedAppsListPath(location);

expect(path).toEqual(
`/administration/trusted_apps?page_size=${location.page_size}&view_type=${location.view_type}&show=${location.show}`
`/administration/trusted_apps?page_size=${location.page_size}&show=${location.show}`
);
});

it('builds proper path when page size is equal to default', () => {
const location: TrustedAppsListPageLocation = {
const location: ArtifactListPageLocation = {
page_index: 2,
page_size: MANAGEMENT_DEFAULT_PAGE_SIZE,
show: 'create',
view_type: 'list',
filter: '',
included_policies: '',
};
const path = getTrustedAppsListPath(location);

expect(path).toEqual(
`/administration/trusted_apps?page_index=${location.page_index}&view_type=${location.view_type}&show=${location.show}`
`/administration/trusted_apps?page_index=${location.page_index}&show=${location.show}`
);
});

it('builds proper path when "show" is equal to default', () => {
const location: TrustedAppsListPageLocation = {
const location: ArtifactListPageLocation = {
page_index: 2,
page_size: 20,
show: undefined,
view_type: 'list',
filter: '',
included_policies: '',
};
const path = getTrustedAppsListPath(location);

expect(path).toEqual(
`/administration/trusted_apps?page_index=${location.page_index}&page_size=${location.page_size}&view_type=${location.view_type}`
`/administration/trusted_apps?page_index=${location.page_index}&page_size=${location.page_size}`
);
});

it('builds proper path when view type is equal to default', () => {
const location: TrustedAppsListPageLocation = {
const location: ArtifactListPageLocation = {
page_index: 2,
page_size: 20,
show: 'create',
view_type: 'grid',
filter: '',
included_policies: '',
};
Expand All @@ -215,7 +185,6 @@ describe('routing', () => {
page_index: MANAGEMENT_DEFAULT_PAGE,
page_size: MANAGEMENT_DEFAULT_PAGE_SIZE,
show: undefined,
view_type: 'grid',
});

expect(path).toEqual('/administration/trusted_apps');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ import { EndpointIndexUIQueryParams } from '../pages/endpoint_hosts/types';
import { EventFiltersPageLocation } from '../pages/event_filters/types';
import { HostIsolationExceptionsPageLocation } from '../pages/host_isolation_exceptions/types';
import { PolicyDetailsArtifactsPageLocation } from '../pages/policy/types';
import { TrustedAppsListPageLocation } from '../pages/trusted_apps/state';
import { AdministrationSubTab } from '../types';
import { ArtifactListPageLocation, AdministrationSubTab } from '../types';
import {
MANAGEMENT_DEFAULT_PAGE,
MANAGEMENT_DEFAULT_PAGE_SIZE,
Expand Down Expand Up @@ -153,9 +152,10 @@ const isDefaultOrMissing = <T>(value: T | undefined, defaultValue: T) => {
return value === undefined || value === defaultValue;
};

const normalizeTrustedAppsPageLocation = (
location?: Partial<TrustedAppsListPageLocation>
): Partial<TrustedAppsListPageLocation> => {
// TODO: use this instead of named artifact methods below
const normalizeArtifactsPageLocation = (
location?: Partial<ArtifactListPageLocation>
): Partial<ArtifactListPageLocation> => {
if (location) {
return {
...(!isDefaultOrMissing(location.page_index, MANAGEMENT_DEFAULT_PAGE)
Expand All @@ -164,7 +164,6 @@ const normalizeTrustedAppsPageLocation = (
...(!isDefaultOrMissing(location.page_size, MANAGEMENT_DEFAULT_PAGE_SIZE)
? { page_size: location.page_size }
: {}),
...(!isDefaultOrMissing(location.view_type, 'grid') ? { view_type: location.view_type } : {}),
...(!isDefaultOrMissing(location.show, undefined) ? { show: location.show } : {}),
...(!isDefaultOrMissing(location.id, undefined) ? { id: location.id } : {}),
...(!isDefaultOrMissing(location.filter, '') ? { filter: location.filter } : ''),
Expand Down Expand Up @@ -317,29 +316,23 @@ export const extractArtifactsListPaginationParams = (query: querystring.ParsedUr

export const extractTrustedAppsListPageLocation = (
query: querystring.ParsedUrlQuery
): TrustedAppsListPageLocation => {
const showParamValue = extractFirstParamValue(
query,
'show'
) as TrustedAppsListPageLocation['show'];
): ArtifactListPageLocation => {
const showParamValue = extractFirstParamValue(query, 'show') as ArtifactListPageLocation['show'];

return {
...extractTrustedAppsListPaginationParams(query),
view_type: extractFirstParamValue(query, 'view_type') === 'list' ? 'list' : 'grid',
show:
showParamValue && ['edit', 'create'].includes(showParamValue) ? showParamValue : undefined,
id: extractFirstParamValue(query, 'id'),
};
};

export const getTrustedAppsListPath = (location?: Partial<TrustedAppsListPageLocation>): string => {
export const getTrustedAppsListPath = (location?: Partial<ArtifactListPageLocation>): string => {
const path = generatePath(MANAGEMENT_ROUTING_TRUSTED_APPS_PATH, {
tabName: AdministrationSubTab.trustedApps,
});

return `${path}${appendSearch(
querystring.stringify(normalizeTrustedAppsPageLocation(location))
)}`;
return `${path}${appendSearch(querystring.stringify(normalizeArtifactsPageLocation(location)))}`;
};

export const extractPolicyDetailsArtifactsListPageLocation = (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import React, { memo, useCallback, useEffect, useMemo, useState } from 'react';
import { i18n } from '@kbn/i18n';
import { DocLinks } from '@kbn/doc-links';
import { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types';
import {
EuiButton,
Expand All @@ -33,7 +34,7 @@ import {
} from '../types';
import { ManagementPageLoader } from '../../management_page_loader';
import { ExceptionsListApiClient } from '../../../services/exceptions_list/exceptions_list_api_client';
import { useToasts } from '../../../../common/lib/kibana';
import { useKibana, useToasts } from '../../../../common/lib/kibana';
import { createExceptionListItemForCreate } from '../../../../../common/endpoint/service/artifacts/utils';
import { useWithArtifactSubmitData } from '../hooks/use_with_artifact_submit_data';
import { useIsArtifactAllowedPerPolicyUsage } from '../hooks/use_is_artifact_allowed_per_policy_usage';
Expand Down Expand Up @@ -96,7 +97,7 @@ export const ARTIFACT_FLYOUT_LABELS = Object.freeze({
* );
* }
*/
flyoutDowngradedLicenseDocsInfo: (): React.ReactNode =>
flyoutDowngradedLicenseDocsInfo: (_: DocLinks['securitySolution']): React.ReactNode =>
i18n.translate('xpack.securitySolution.artifactListPage.flyoutDowngradedLicenseDocsInfo', {
defaultMessage: 'For more information, see our documentation.',
}),
Expand Down Expand Up @@ -188,6 +189,11 @@ export const ArtifactFlyout = memo<ArtifactFlyoutProps>(
'data-test-subj': dataTestSubj,
size = 'm',
}) => {
const {
docLinks: {
links: { securitySolution },
},
} = useKibana().services;
const getTestId = useTestIdGenerator(dataTestSubj);
const toasts = useToasts();
const isFlyoutOpened = useIsFlyoutOpened();
Expand Down Expand Up @@ -364,7 +370,8 @@ export const ArtifactFlyout = memo<ArtifactFlyoutProps>(
iconType="help"
data-test-subj={getTestId('expiredLicenseCallout')}
>
{`${labels.flyoutDowngradedLicenseInfo} ${labels.flyoutDowngradedLicenseDocsInfo()}`}
{`${labels.flyoutDowngradedLicenseInfo}`}{' '}
{labels.flyoutDowngradedLicenseDocsInfo(securitySolution)}
</EuiCallOut>
)}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { ArtifactFormComponentProps } from './types';
import { ArtifactListPage, ArtifactListPageProps } from './artifact_list_page';
import { AppContextTestRender, createAppRootMockRenderer } from '../../../common/mock/endpoint';
import { trustedAppsAllHttpMocks } from '../../pages/mocks';
import { TrustedAppsApiClient } from '../../pages/trusted_apps/service/trusted_apps_api_client';
import { TrustedAppsApiClient } from '../../pages/trusted_apps/service/api_client';
import { artifactListPageLabels } from './translations';

export const getFormComponentMock = (): {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ import {
BY_POLICY_ARTIFACT_TAG_PREFIX,
} from '../../../../../../common/endpoint/service/artifacts/constants';
import { useLicense } from '../../../../../common/hooks/use_license';
import { isValidHash } from '../../../../../../common/endpoint/service/trusted_apps/validations';
import { isValidHash } from '../../../../../../common/endpoint/service/artifacts/validations';
import { isArtifactGlobal } from '../../../../../../common/endpoint/service/artifacts';
import type { PolicyData } from '../../../../../../common/endpoint/types';
import { isGlobalPolicyEffected } from '../../../../components/effected_policy_select/utils';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import {
BY_POLICY_ARTIFACT_TAG_PREFIX,
GLOBAL_ARTIFACT_TAG,
} from '../../../../common/endpoint/service/artifacts/constants';
import { entriesToConditionEntries } from '../../../common/utils/exception_list_items/mappers';

interface FindExceptionListItemSchemaQueryParams
extends Omit<FindExceptionListItemSchema, 'page' | 'per_page'> {
Expand Down Expand Up @@ -148,6 +149,11 @@ export const trustedAppsGetOneHttpMocks =
exceptionItem.namespace_type =
apiQueryParams.namespace_type ?? exceptionItem.namespace_type;

// map process.hash entries to have * as suffix
exceptionItem.entries = entriesToConditionEntries(
exceptionItem.entries
) as ExceptionListItemSchema['entries'];

return exceptionItem;
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,61 @@
* 2.0.
*/

import { GetTrustedAppsListResponse } from '../../../../../common/endpoint/types';
import { createSampleTrustedApps } from '../../trusted_apps/test_utils';
import { OperatingSystem } from '@kbn/securitysolution-utils';
import { GetTrustedAppsListResponse, TrustedApp } from '../../../../../common/endpoint/types';
import {
MANAGEMENT_DEFAULT_PAGE,
MANAGEMENT_DEFAULT_PAGE_SIZE,
MANAGEMENT_PAGE_SIZE_OPTIONS,
} from '../../../common/constants';

interface Pagination {
pageIndex: number;
pageSize: number;
totalItemCount: number;
pageSizeOptions: number[];
}

const OPERATING_SYSTEMS: OperatingSystem[] = [
OperatingSystem.WINDOWS,
OperatingSystem.MAC,
OperatingSystem.LINUX,
];

const generate = <T>(count: number, generator: (i: number) => T) =>
[...new Array(count).keys()].map(generator);

const createSampleTrustedApp = (i: number, longTexts?: boolean): TrustedApp => {
return {
id: String(i),
version: 'abc123',
name: generate(longTexts ? 10 : 1, () => `trusted app ${i}`).join(' '),
description: generate(longTexts ? 10 : 1, () => `Trusted App ${i}`).join(' '),
created_at: '1 minute ago',
created_by: 'someone',
updated_at: '1 minute ago',
updated_by: 'someone',
os: OPERATING_SYSTEMS[i % 3],
entries: [],
effectScope: { type: 'global' },
};
};

const createDefaultPagination = (): Pagination => ({
pageIndex: MANAGEMENT_DEFAULT_PAGE,
pageSize: MANAGEMENT_DEFAULT_PAGE_SIZE,
totalItemCount: 200,
pageSizeOptions: [...MANAGEMENT_PAGE_SIZE_OPTIONS],
});

const createSampleTrustedApps = (
pagination: Partial<Pagination>,
longTexts?: boolean
): TrustedApp[] => {
const fullPagination = { ...createDefaultPagination(), ...pagination };

return generate(fullPagination.pageSize, (i: number) => createSampleTrustedApp(i, longTexts));
};

export const getMockListResponse: () => GetTrustedAppsListResponse = () => ({
data: createSampleTrustedApps({}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { useGetLinkTo } from './use_policy_artifacts_empty_hooks';
import { useUserPrivileges } from '../../../../../../common/components/user_privileges';
import { POLICY_ARTIFACT_EMPTY_UNASSIGNED_LABELS } from './translations';
import { EventFiltersPageLocation } from '../../../../event_filters/types';
import { TrustedAppsListPageLocation } from '../../../../trusted_apps/state';
import type { ArtifactListPageLocation } from '../../../../../types';
import { HostIsolationExceptionsPageLocation } from '../../../../host_isolation_exceptions/types';
interface CommonProps {
policyId: string;
Expand All @@ -23,7 +23,7 @@ interface CommonProps {
getArtifactPath: (
location?:
| Partial<EventFiltersPageLocation>
| Partial<TrustedAppsListPageLocation>
| Partial<ArtifactListPageLocation>
| Partial<HostIsolationExceptionsPageLocation>
) => string;
}
Expand Down
Loading