[Security Solution] Rename Administration > Hosts subtab to Endpoints (#74287)

This commit is contained in:
Dan Panzarella 2020-08-11 13:31:59 -04:00 committed by GitHub
parent 7b5df7ce3b
commit 80a5c4bef7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
39 changed files with 750 additions and 730 deletions

View file

@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { HostAction } from '../../management/pages/endpoint_hosts/store/action';
import { EndpointAction } from '../../management/pages/endpoint_hosts/store/action';
import { PolicyListAction } from '../../management/pages/policy/store/policy_list';
import { PolicyDetailsAction } from '../../management/pages/policy/store/policy_details';
@ -13,4 +13,4 @@ export { dragAndDropActions } from './drag_and_drop';
export { inputsActions } from './inputs';
import { RoutingAction } from './routing';
export type AppAction = HostAction | RoutingAction | PolicyListAction | PolicyDetailsAction;
export type AppAction = EndpointAction | RoutingAction | PolicyListAction | PolicyDetailsAction;

View file

@ -10,7 +10,7 @@ import { SecurityPageName } from '../../app/types';
// --[ ROUTING ]---------------------------------------------------------------------------
export const MANAGEMENT_APP_ID = `${APP_ID}:${SecurityPageName.administration}`;
export const MANAGEMENT_ROUTING_ROOT_PATH = '';
export const MANAGEMENT_ROUTING_HOSTS_PATH = `${MANAGEMENT_ROUTING_ROOT_PATH}/:tabName(${AdministrationSubTab.hosts})`;
export const MANAGEMENT_ROUTING_ENDPOINTS_PATH = `${MANAGEMENT_ROUTING_ROOT_PATH}/:tabName(${AdministrationSubTab.endpoints})`;
export const MANAGEMENT_ROUTING_POLICIES_PATH = `${MANAGEMENT_ROUTING_ROOT_PATH}/:tabName(${AdministrationSubTab.policies})`;
export const MANAGEMENT_ROUTING_POLICY_DETAILS_PATH = `${MANAGEMENT_ROUTING_ROOT_PATH}/:tabName(${AdministrationSubTab.policies})/:policyId`;
@ -21,5 +21,5 @@ export const MANAGEMENT_STORE_GLOBAL_NAMESPACE: ManagementStoreGlobalNamespace =
export const MANAGEMENT_STORE_POLICY_LIST_NAMESPACE = 'policyList';
/** Namespace within the Management state where policy details state is maintained */
export const MANAGEMENT_STORE_POLICY_DETAILS_NAMESPACE = 'policyDetails';
/** Namespace within the Management state where hosts state is maintained */
export const MANAGEMENT_STORE_HOSTS_NAMESPACE = 'hosts';
/** Namespace within the Management state where endpoint-host state is maintained */
export const MANAGEMENT_STORE_ENDPOINTS_NAMESPACE = 'endpoints';

View file

@ -10,13 +10,13 @@ import { generatePath } from 'react-router-dom';
import querystring from 'querystring';
import {
MANAGEMENT_ROUTING_HOSTS_PATH,
MANAGEMENT_ROUTING_ENDPOINTS_PATH,
MANAGEMENT_ROUTING_POLICIES_PATH,
MANAGEMENT_ROUTING_POLICY_DETAILS_PATH,
} from './constants';
import { AdministrationSubTab } from '../types';
import { appendSearch } from '../../common/components/link_to/helpers';
import { HostIndexUIQueryParams } from '../pages/endpoint_hosts/types';
import { EndpointIndexUIQueryParams } from '../pages/endpoint_hosts/types';
// Taken from: https://github.com/microsoft/TypeScript/issues/12936#issuecomment-559034150
type ExactKeys<T1, T2> = Exclude<keyof T1, keyof T2> extends never ? T1 : never;
@ -31,42 +31,44 @@ const querystringStringify: <ExpectedType extends object, ArgType>(
params: Exact<ExpectedType, ArgType>
) => string = querystring.stringify;
/** Make `selected_host` required */
type HostDetailsUrlProps = Omit<HostIndexUIQueryParams, 'selected_host'> &
Required<Pick<HostIndexUIQueryParams, 'selected_host'>>;
/** Make `selected_endpoint` required */
type EndpointDetailsUrlProps = Omit<EndpointIndexUIQueryParams, 'selected_endpoint'> &
Required<Pick<EndpointIndexUIQueryParams, 'selected_endpoint'>>;
export const getHostListPath = (
props: { name: 'default' | 'hostList' } & HostIndexUIQueryParams,
export const getEndpointListPath = (
props: { name: 'default' | 'endpointList' } & EndpointIndexUIQueryParams,
search?: string
) => {
const { name, ...queryParams } = props;
const urlQueryParams = querystringStringify<HostIndexUIQueryParams, typeof queryParams>(
const urlQueryParams = querystringStringify<EndpointIndexUIQueryParams, typeof queryParams>(
queryParams
);
const urlSearch = `${urlQueryParams && !isEmpty(search) ? '&' : ''}${search ?? ''}`;
if (name === 'hostList') {
return `${generatePath(MANAGEMENT_ROUTING_HOSTS_PATH, {
tabName: AdministrationSubTab.hosts,
if (name === 'endpointList') {
return `${generatePath(MANAGEMENT_ROUTING_ENDPOINTS_PATH, {
tabName: AdministrationSubTab.endpoints,
})}${appendSearch(`${urlQueryParams ? `${urlQueryParams}${urlSearch}` : urlSearch}`)}`;
}
return `${appendSearch(`${urlQueryParams ? `${urlQueryParams}${urlSearch}` : urlSearch}`)}`;
};
export const getHostDetailsPath = (
props: { name: 'hostDetails' | 'hostPolicyResponse' } & HostIndexUIQueryParams &
HostDetailsUrlProps,
export const getEndpointDetailsPath = (
props: { name: 'endpointDetails' | 'endpointPolicyResponse' } & EndpointIndexUIQueryParams &
EndpointDetailsUrlProps,
search?: string
) => {
const { name, ...queryParams } = props;
queryParams.show = (props.name === 'hostPolicyResponse'
queryParams.show = (props.name === 'endpointPolicyResponse'
? 'policy_response'
: '') as HostIndexUIQueryParams['show'];
const urlQueryParams = querystringStringify<HostDetailsUrlProps, typeof queryParams>(queryParams);
: '') as EndpointIndexUIQueryParams['show'];
const urlQueryParams = querystringStringify<EndpointDetailsUrlProps, typeof queryParams>(
queryParams
);
const urlSearch = `${urlQueryParams && !isEmpty(search) ? '&' : ''}${search ?? ''}`;
return `${generatePath(MANAGEMENT_ROUTING_HOSTS_PATH, {
tabName: AdministrationSubTab.hosts,
return `${generatePath(MANAGEMENT_ROUTING_ENDPOINTS_PATH, {
tabName: AdministrationSubTab.endpoints,
})}${appendSearch(`${urlQueryParams ? `${urlQueryParams}${urlSearch}` : urlSearch}`)}`;
};

View file

@ -6,8 +6,8 @@
import { i18n } from '@kbn/i18n';
export const HOSTS_TAB = i18n.translate('xpack.securitySolution.hostsTab', {
defaultMessage: 'Hosts',
export const ENDPOINTS_TAB = i18n.translate('xpack.securitySolution.endpointsTab', {
defaultMessage: 'Endpoints',
});
export const POLICIES_TAB = i18n.translate('xpack.securitySolution.policiesTab', {

View file

@ -116,7 +116,7 @@ const PolicyEmptyState = React.memo<{
);
});
const HostsEmptyState = React.memo<{
const EndpointsEmptyState = React.memo<{
loading: boolean;
onActionClick: (event: MouseEvent<HTMLAnchorElement | HTMLButtonElement>) => void;
actionDisabled: boolean;
@ -126,14 +126,14 @@ const HostsEmptyState = React.memo<{
const policySteps = useMemo(
() => [
{
title: i18n.translate('xpack.securitySolution.endpoint.hostList.stepOneTitle', {
title: i18n.translate('xpack.securitySolution.endpoint.list.stepOneTitle', {
defaultMessage: 'Select the integration you want to use',
}),
children: (
<>
<EuiText color="subdued" size="m" grow={false}>
<FormattedMessage
id="xpack.securitySolution.endpoint.hostList.stepOne"
id="xpack.securitySolution.endpoint.list.stepOne"
defaultMessage="Select from existing integrations. This can be changed later."
/>
</EuiText>
@ -151,7 +151,7 @@ const HostsEmptyState = React.memo<{
return loading ? (
<EuiSelectableMessage>
<FormattedMessage
id="xpack.securitySolution.endpoint.hostList.loadingPolicies"
id="xpack.securitySolution.endpoint.list.loadingPolicies"
defaultMessage="Loading integrations"
/>
</EuiSelectableMessage>
@ -159,7 +159,7 @@ const HostsEmptyState = React.memo<{
list
) : (
<FormattedMessage
id="xpack.securitySolution.endpoint.hostList.noPolicies"
id="xpack.securitySolution.endpoint.list.noPolicies"
defaultMessage="There are no integrations."
/>
);
@ -169,7 +169,7 @@ const HostsEmptyState = React.memo<{
),
},
{
title: i18n.translate('xpack.securitySolution.endpoint.hostList.stepTwoTitle', {
title: i18n.translate('xpack.securitySolution.endpoint.list.stepTwoTitle', {
defaultMessage:
'Enroll your agents enabled with Endpoint Security through Ingest Manager',
}),
@ -179,7 +179,7 @@ const HostsEmptyState = React.memo<{
<EuiFlexItem>
<EuiText color="subdued" size="m" grow={false}>
<FormattedMessage
id="xpack.securitySolution.endpoint.hostList.stepTwo"
id="xpack.securitySolution.endpoint.list.stepTwo"
defaultMessage="Youll be provided with the necessary commands to get started."
/>
</EuiText>
@ -211,13 +211,13 @@ const HostsEmptyState = React.memo<{
steps={policySteps}
headerComponent={
<FormattedMessage
id="xpack.securitySolution.endpoint.hostList.noEndpointsPrompt"
id="xpack.securitySolution.endpoint.list.noEndpointsPrompt"
defaultMessage="Next step: Enroll an Agent with Elastic Endpoint Security"
/>
}
bodyComponent={
<FormattedMessage
id="xpack.securitySolution.endpoint.hostList.noEndpointsInstructions"
id="xpack.securitySolution.endpoint.list.noEndpointsInstructions"
defaultMessage="Youve added the Endpoint Security integration. Now enroll your agents using the steps below."
/>
}
@ -265,7 +265,7 @@ const ManagementEmptyState = React.memo<{
});
PolicyEmptyState.displayName = 'PolicyEmptyState';
HostsEmptyState.displayName = 'HostsEmptyState';
EndpointsEmptyState.displayName = 'HostsEmptyState';
ManagementEmptyState.displayName = 'ManagementEmptyState';
export { PolicyEmptyState, HostsEmptyState };
export { PolicyEmptyState, EndpointsEmptyState as HostsEmptyState };

View file

@ -6,20 +6,20 @@
import { Switch, Route } from 'react-router-dom';
import React, { memo } from 'react';
import { HostList } from './view';
import { MANAGEMENT_ROUTING_HOSTS_PATH } from '../../common/constants';
import { EndpointList } from './view';
import { MANAGEMENT_ROUTING_ENDPOINTS_PATH } from '../../common/constants';
import { NotFoundPage } from '../../../app/404';
/**
* Provides the routing container for the hosts related views
*/
export const HostsContainer = memo(() => {
export const EndpointsContainer = memo(() => {
return (
<Switch>
<Route path={MANAGEMENT_ROUTING_HOSTS_PATH} exact component={HostList} />
<Route path={MANAGEMENT_ROUTING_ENDPOINTS_PATH} exact component={EndpointList} />
<Route path="*" component={NotFoundPage} />
</Switch>
);
});
HostsContainer.displayName = 'HostsContainer';
EndpointsContainer.displayName = 'EndpointsContainer';

View file

@ -7,12 +7,12 @@
import React from 'react';
import { Route, Switch } from 'react-router-dom';
import { HostList } from './view';
import { EndpointList } from './view';
export const EndpointHostsRoutes: React.FC = () => (
<Switch>
<Route path="/:pageName(endpoint-hosts)">
<HostList />
<Route path="/:pageName(endpoint-endpoints)">
<EndpointList />
</Route>
</Switch>
);

View file

@ -12,35 +12,35 @@ import {
import { ServerApiError } from '../../../../common/types';
import { GetPolicyListResponse } from '../../policy/types';
import { GetPackagesResponse } from '../../../../../../ingest_manager/common';
import { HostState } from '../types';
import { EndpointState } from '../types';
interface ServerReturnedHostList {
type: 'serverReturnedHostList';
interface ServerReturnedEndpointList {
type: 'serverReturnedEndpointList';
payload: HostResultList;
}
interface ServerFailedToReturnHostList {
type: 'serverFailedToReturnHostList';
interface ServerFailedToReturnEndpointList {
type: 'serverFailedToReturnEndpointList';
payload: ServerApiError;
}
interface ServerReturnedHostDetails {
type: 'serverReturnedHostDetails';
interface ServerReturnedEndpointDetails {
type: 'serverReturnedEndpointDetails';
payload: HostInfo;
}
interface ServerFailedToReturnHostDetails {
type: 'serverFailedToReturnHostDetails';
interface ServerFailedToReturnEndpointDetails {
type: 'serverFailedToReturnEndpointDetails';
payload: ServerApiError;
}
interface ServerReturnedHostPolicyResponse {
type: 'serverReturnedHostPolicyResponse';
interface ServerReturnedEndpointPolicyResponse {
type: 'serverReturnedEndpointPolicyResponse';
payload: GetHostPolicyResponse;
}
interface ServerFailedToReturnHostPolicyResponse {
type: 'serverFailedToReturnHostPolicyResponse';
interface ServerFailedToReturnEndpointPolicyResponse {
type: 'serverFailedToReturnEndpointPolicyResponse';
payload: ServerApiError;
}
@ -63,8 +63,8 @@ interface UserSelectedEndpointPolicy {
};
}
interface ServerCancelledHostListLoading {
type: 'serverCancelledHostListLoading';
interface ServerCancelledEndpointListLoading {
type: 'serverCancelledEndpointListLoading';
}
interface ServerCancelledPolicyItemsLoading {
@ -76,28 +76,28 @@ interface ServerReturnedEndpointPackageInfo {
payload: GetPackagesResponse['response'][0];
}
interface ServerReturnedHostNonExistingPolicies {
type: 'serverReturnedHostNonExistingPolicies';
payload: HostState['nonExistingPolicies'];
interface ServerReturnedEndpointNonExistingPolicies {
type: 'serverReturnedEndpointNonExistingPolicies';
payload: EndpointState['nonExistingPolicies'];
}
interface ServerReturnedHostExistValue {
type: 'serverReturnedHostExistValue';
interface ServerReturnedEndpointExistValue {
type: 'serverReturnedEndpointExistValue';
payload: boolean;
}
export type HostAction =
| ServerReturnedHostList
| ServerFailedToReturnHostList
| ServerReturnedHostDetails
| ServerFailedToReturnHostDetails
| ServerReturnedHostPolicyResponse
| ServerFailedToReturnHostPolicyResponse
export type EndpointAction =
| ServerReturnedEndpointList
| ServerFailedToReturnEndpointList
| ServerReturnedEndpointDetails
| ServerFailedToReturnEndpointDetails
| ServerReturnedEndpointPolicyResponse
| ServerFailedToReturnEndpointPolicyResponse
| ServerReturnedPoliciesForOnboarding
| ServerFailedToReturnPoliciesForOnboarding
| UserSelectedEndpointPolicy
| ServerCancelledHostListLoading
| ServerReturnedHostExistValue
| ServerCancelledEndpointListLoading
| ServerReturnedEndpointExistValue
| ServerCancelledPolicyItemsLoading
| ServerReturnedEndpointPackageInfo
| ServerReturnedHostNonExistingPolicies;
| ServerReturnedEndpointNonExistingPolicies;

View file

@ -13,41 +13,41 @@ import { coreMock } from '../../../../../../../../src/core/public/mocks';
import { HostResultList, AppLocation } from '../../../../../common/endpoint/types';
import { DepsStartMock, depsStartMock } from '../../../../common/mock/endpoint';
import { hostMiddlewareFactory } from './middleware';
import { endpointMiddlewareFactory } from './middleware';
import { hostListReducer } from './reducer';
import { endpointListReducer } from './reducer';
import { uiQueryParams } from './selectors';
import { mockHostResultList } from './mock_host_result_list';
import { HostState, HostIndexUIQueryParams } from '../types';
import { mockEndpointResultList } from './mock_endpoint_result_list';
import { EndpointState, EndpointIndexUIQueryParams } from '../types';
import {
MiddlewareActionSpyHelper,
createSpyMiddleware,
} from '../../../../common/store/test_utils';
import { getHostListPath } from '../../../common/routing';
import { getEndpointListPath } from '../../../common/routing';
describe('host list pagination: ', () => {
describe('endpoint list pagination: ', () => {
let fakeCoreStart: jest.Mocked<CoreStart>;
let depsStart: DepsStartMock;
let fakeHttpServices: jest.Mocked<HttpSetup>;
let history: History<AppLocation['state']>;
let store: Store;
let queryParams: () => HostIndexUIQueryParams;
let queryParams: () => EndpointIndexUIQueryParams;
let waitForAction: MiddlewareActionSpyHelper['waitForAction'];
let actionSpyMiddleware;
const getEndpointListApiResponse = (): HostResultList => {
return mockHostResultList({ request_page_size: 1, request_page_index: 1, total: 10 });
return mockEndpointResultList({ request_page_size: 1, request_page_index: 1, total: 10 });
};
let historyPush: (params: HostIndexUIQueryParams) => void;
let historyPush: (params: EndpointIndexUIQueryParams) => void;
beforeEach(() => {
fakeCoreStart = coreMock.createStart();
depsStart = depsStartMock();
fakeHttpServices = fakeCoreStart.http as jest.Mocked<HttpSetup>;
history = createBrowserHistory();
const middleware = hostMiddlewareFactory(fakeCoreStart, depsStart);
({ actionSpyMiddleware, waitForAction } = createSpyMiddleware<HostState>());
store = createStore(hostListReducer, applyMiddleware(middleware, actionSpyMiddleware));
const middleware = endpointMiddlewareFactory(fakeCoreStart, depsStart);
({ actionSpyMiddleware, waitForAction } = createSpyMiddleware<EndpointState>());
store = createStore(endpointListReducer, applyMiddleware(middleware, actionSpyMiddleware));
history.listen((location) => {
store.dispatch({ type: 'userChangedUrl', payload: location });
@ -55,12 +55,12 @@ describe('host list pagination: ', () => {
queryParams = () => uiQueryParams(store.getState());
historyPush = (nextQueryParams: HostIndexUIQueryParams): void => {
return history.push(getHostListPath({ name: 'hostList', ...nextQueryParams }));
historyPush = (nextQueryParams: EndpointIndexUIQueryParams): void => {
return history.push(getEndpointListPath({ name: 'endpointList', ...nextQueryParams }));
};
});
describe('when the user enteres the host list for the first time', () => {
describe('when the user enteres the endpoint list for the first time', () => {
it('the api is called with page_index and page_size defaulting to 0 and 10 respectively', async () => {
const apiResponse = getEndpointListApiResponse();
fakeHttpServices.post.mockResolvedValue(apiResponse);
@ -70,10 +70,10 @@ describe('host list pagination: ', () => {
type: 'userChangedUrl',
payload: {
...history.location,
pathname: getHostListPath({ name: 'hostList' }),
pathname: getEndpointListPath({ name: 'endpointList' }),
},
});
await waitForAction('serverReturnedHostList');
await waitForAction('serverReturnedEndpointList');
expect(fakeHttpServices.post).toHaveBeenCalledWith('/api/endpoint/metadata', {
body: JSON.stringify({
paging_properties: [{ page_index: '0' }, { page_size: '10' }],

View file

@ -5,24 +5,24 @@
*/
import { createStore, Dispatch, Store } from 'redux';
import { HostState } from '../types';
import { EndpointState } from '../types';
import { listData } from './selectors';
import { mockHostResultList } from './mock_host_result_list';
import { HostAction } from './action';
import { hostListReducer } from './reducer';
import { mockEndpointResultList } from './mock_endpoint_result_list';
import { EndpointAction } from './action';
import { endpointListReducer } from './reducer';
describe('HostList store concerns', () => {
let store: Store<HostState>;
let dispatch: Dispatch<HostAction>;
describe('EndpointList store concerns', () => {
let store: Store<EndpointState>;
let dispatch: Dispatch<EndpointAction>;
const createTestStore = () => {
store = createStore(hostListReducer);
store = createStore(endpointListReducer);
dispatch = store.dispatch;
};
const loadDataToStore = () => {
dispatch({
type: 'serverReturnedHostList',
payload: mockHostResultList({ request_page_size: 1, request_page_index: 1, total: 10 }),
type: 'serverReturnedEndpointList',
payload: mockEndpointResultList({ request_page_size: 1, request_page_index: 1, total: 10 }),
});
};
@ -51,18 +51,18 @@ describe('HostList store concerns', () => {
policyItemsLoading: false,
endpointPackageInfo: undefined,
nonExistingPolicies: {},
hostsExist: true,
endpointsExist: true,
});
});
test('it handles `serverReturnedHostList', () => {
const payload = mockHostResultList({
test('it handles `serverReturnedEndpointList', () => {
const payload = mockEndpointResultList({
request_page_size: 1,
request_page_index: 1,
total: 10,
});
dispatch({
type: 'serverReturnedHostList',
type: 'serverReturnedEndpointList',
payload,
});
@ -80,7 +80,7 @@ describe('HostList store concerns', () => {
loadDataToStore();
});
test('it selects `hostListData`', () => {
test('it selects `endpointListData`', () => {
const currentState = store.getState();
expect(listData(currentState)).toEqual(currentState.hosts);
});

View file

@ -16,36 +16,36 @@ import {
} from '../../../../common/store/test_utils';
import { Immutable, HostResultList } from '../../../../../common/endpoint/types';
import { AppAction } from '../../../../common/store/actions';
import { mockHostResultList } from './mock_host_result_list';
import { mockEndpointResultList } from './mock_endpoint_result_list';
import { listData } from './selectors';
import { HostState } from '../types';
import { hostListReducer } from './reducer';
import { hostMiddlewareFactory } from './middleware';
import { getHostListPath } from '../../../common/routing';
import { EndpointState } from '../types';
import { endpointListReducer } from './reducer';
import { endpointMiddlewareFactory } from './middleware';
import { getEndpointListPath } from '../../../common/routing';
describe('host list middleware', () => {
describe('endpoint list middleware', () => {
let fakeCoreStart: jest.Mocked<CoreStart>;
let depsStart: DepsStartMock;
let fakeHttpServices: jest.Mocked<HttpSetup>;
type HostListStore = Store<Immutable<HostState>, Immutable<AppAction>>;
let store: HostListStore;
let getState: HostListStore['getState'];
let dispatch: HostListStore['dispatch'];
type EndpointListStore = Store<Immutable<EndpointState>, Immutable<AppAction>>;
let store: EndpointListStore;
let getState: EndpointListStore['getState'];
let dispatch: EndpointListStore['dispatch'];
let waitForAction: MiddlewareActionSpyHelper['waitForAction'];
let actionSpyMiddleware;
let history: History<never>;
const getEndpointListApiResponse = (): HostResultList => {
return mockHostResultList({ request_page_size: 1, request_page_index: 1, total: 10 });
return mockEndpointResultList({ request_page_size: 1, request_page_index: 1, total: 10 });
};
beforeEach(() => {
fakeCoreStart = coreMock.createStart({ basePath: '/mock' });
depsStart = depsStartMock();
fakeHttpServices = fakeCoreStart.http as jest.Mocked<HttpSetup>;
({ actionSpyMiddleware, waitForAction } = createSpyMiddleware<HostState>());
({ actionSpyMiddleware, waitForAction } = createSpyMiddleware<EndpointState>());
store = createStore(
hostListReducer,
applyMiddleware(hostMiddlewareFactory(fakeCoreStart, depsStart), actionSpyMiddleware)
endpointListReducer,
applyMiddleware(endpointMiddlewareFactory(fakeCoreStart, depsStart), actionSpyMiddleware)
);
getState = store.getState;
dispatch = store.dispatch;
@ -60,10 +60,10 @@ describe('host list middleware', () => {
type: 'userChangedUrl',
payload: {
...history.location,
pathname: getHostListPath({ name: 'hostList' }),
pathname: getEndpointListPath({ name: 'endpointList' }),
},
});
await waitForAction('serverReturnedHostList');
await waitForAction('serverReturnedEndpointList');
expect(fakeHttpServices.post).toHaveBeenCalledWith('/api/endpoint/metadata', {
body: JSON.stringify({
paging_properties: [{ page_index: '0' }, { page_size: '10' }],

View file

@ -9,14 +9,14 @@ import { HostInfo, HostResultList } from '../../../../../common/endpoint/types';
import { GetPolicyListResponse } from '../../policy/types';
import { ImmutableMiddlewareFactory } from '../../../../common/store';
import {
isOnHostPage,
hasSelectedHost,
isOnEndpointPage,
hasSelectedEndpoint,
uiQueryParams,
listData,
endpointPackageInfo,
nonExistingPolicies,
} from './selectors';
import { HostState } from '../types';
import { EndpointState } from '../types';
import {
sendGetEndpointSpecificPackageConfigs,
sendGetEndpointSecurityPackage,
@ -24,16 +24,16 @@ import {
} from '../../policy/store/policy_list/services/ingest';
import { AGENT_CONFIG_SAVED_OBJECT_TYPE } from '../../../../../../ingest_manager/common';
export const hostMiddlewareFactory: ImmutableMiddlewareFactory<HostState> = (coreStart) => {
export const endpointMiddlewareFactory: ImmutableMiddlewareFactory<EndpointState> = (coreStart) => {
return ({ getState, dispatch }) => (next) => async (action) => {
next(action);
const state = getState();
// Host list
// Endpoint list
if (
action.type === 'userChangedUrl' &&
isOnHostPage(state) &&
hasSelectedHost(state) !== true
isOnEndpointPage(state) &&
hasSelectedEndpoint(state) !== true
) {
if (!endpointPackageInfo(state)) {
sendGetEndpointSecurityPackage(coreStart.http)
@ -50,30 +50,30 @@ export const hostMiddlewareFactory: ImmutableMiddlewareFactory<HostState> = (cor
}
const { page_index: pageIndex, page_size: pageSize } = uiQueryParams(state);
let hostResponse;
let endpointResponse;
try {
hostResponse = await coreStart.http.post<HostResultList>('/api/endpoint/metadata', {
endpointResponse = await coreStart.http.post<HostResultList>('/api/endpoint/metadata', {
body: JSON.stringify({
paging_properties: [{ page_index: pageIndex }, { page_size: pageSize }],
}),
});
hostResponse.request_page_index = Number(pageIndex);
endpointResponse.request_page_index = Number(pageIndex);
dispatch({
type: 'serverReturnedHostList',
payload: hostResponse,
type: 'serverReturnedEndpointList',
payload: endpointResponse,
});
getNonExistingPoliciesForHostsList(
getNonExistingPoliciesForEndpointsList(
coreStart.http,
hostResponse.hosts,
endpointResponse.hosts,
nonExistingPolicies(state)
)
.then((missingPolicies) => {
if (missingPolicies !== undefined) {
dispatch({
type: 'serverReturnedHostNonExistingPolicies',
type: 'serverReturnedEndpointNonExistingPolicies',
payload: missingPolicies,
});
}
@ -83,24 +83,24 @@ export const hostMiddlewareFactory: ImmutableMiddlewareFactory<HostState> = (cor
.catch((error) => console.error(error));
} catch (error) {
dispatch({
type: 'serverFailedToReturnHostList',
type: 'serverFailedToReturnEndpointList',
payload: error,
});
}
// No hosts, so we should check to see if there are policies for onboarding
if (hostResponse && hostResponse.hosts.length === 0) {
// No endpoints, so we should check to see if there are policies for onboarding
if (endpointResponse && endpointResponse.hosts.length === 0) {
const http = coreStart.http;
// The original query to the list could have had an invalid param (ex. invalid page_size),
// so we check first if hosts actually do exist before pulling in data for the onboarding
// so we check first if endpoints actually do exist before pulling in data for the onboarding
// messages.
if (await doHostsExist(http)) {
if (await doEndpointsExist(http)) {
return;
}
dispatch({
type: 'serverReturnedHostExistValue',
type: 'serverReturnedEndpointExistValue',
payload: false,
});
@ -135,13 +135,13 @@ export const hostMiddlewareFactory: ImmutableMiddlewareFactory<HostState> = (cor
}
}
// Host Details
if (action.type === 'userChangedUrl' && hasSelectedHost(state) === true) {
// Endpoint Details
if (action.type === 'userChangedUrl' && hasSelectedEndpoint(state) === true) {
dispatch({
type: 'serverCancelledPolicyItemsLoading',
});
// If user navigated directly to a host details page, load the host list
// If user navigated directly to a endpoint details page, load the endpoint list
if (listData(state).length === 0) {
const { page_index: pageIndex, page_size: pageSize } = uiQueryParams(state);
try {
@ -152,11 +152,11 @@ export const hostMiddlewareFactory: ImmutableMiddlewareFactory<HostState> = (cor
});
response.request_page_index = Number(pageIndex);
dispatch({
type: 'serverReturnedHostList',
type: 'serverReturnedEndpointList',
payload: response,
});
getNonExistingPoliciesForHostsList(
getNonExistingPoliciesForEndpointsList(
coreStart.http,
response.hosts,
nonExistingPolicies(state)
@ -164,7 +164,7 @@ export const hostMiddlewareFactory: ImmutableMiddlewareFactory<HostState> = (cor
.then((missingPolicies) => {
if (missingPolicies !== undefined) {
dispatch({
type: 'serverReturnedHostNonExistingPolicies',
type: 'serverReturnedEndpointNonExistingPolicies',
payload: missingPolicies,
});
}
@ -174,31 +174,35 @@ export const hostMiddlewareFactory: ImmutableMiddlewareFactory<HostState> = (cor
.catch((error) => console.error(error));
} catch (error) {
dispatch({
type: 'serverFailedToReturnHostList',
type: 'serverFailedToReturnEndpointList',
payload: error,
});
}
} else {
dispatch({
type: 'serverCancelledHostListLoading',
type: 'serverCancelledEndpointListLoading',
});
}
// call the host details api
const { selected_host: selectedHost } = uiQueryParams(state);
// call the endpoint details api
const { selected_endpoint: selectedEndpoint } = uiQueryParams(state);
try {
const response = await coreStart.http.get<HostInfo>(
`/api/endpoint/metadata/${selectedHost}`
`/api/endpoint/metadata/${selectedEndpoint}`
);
dispatch({
type: 'serverReturnedHostDetails',
type: 'serverReturnedEndpointDetails',
payload: response,
});
getNonExistingPoliciesForHostsList(coreStart.http, [response], nonExistingPolicies(state))
getNonExistingPoliciesForEndpointsList(
coreStart.http,
[response],
nonExistingPolicies(state)
)
.then((missingPolicies) => {
if (missingPolicies !== undefined) {
dispatch({
type: 'serverReturnedHostNonExistingPolicies',
type: 'serverReturnedEndpointNonExistingPolicies',
payload: missingPolicies,
});
}
@ -208,7 +212,7 @@ export const hostMiddlewareFactory: ImmutableMiddlewareFactory<HostState> = (cor
.catch((error) => console.error(error));
} catch (error) {
dispatch({
type: 'serverFailedToReturnHostDetails',
type: 'serverFailedToReturnEndpointDetails',
payload: error,
});
}
@ -216,15 +220,15 @@ export const hostMiddlewareFactory: ImmutableMiddlewareFactory<HostState> = (cor
// call the policy response api
try {
const policyResponse = await coreStart.http.get(`/api/endpoint/policy_response`, {
query: { hostId: selectedHost },
query: { hostId: selectedEndpoint },
});
dispatch({
type: 'serverReturnedHostPolicyResponse',
type: 'serverReturnedEndpointPolicyResponse',
payload: policyResponse,
});
} catch (error) {
dispatch({
type: 'serverFailedToReturnHostPolicyResponse',
type: 'serverFailedToReturnEndpointPolicyResponse',
payload: error,
});
}
@ -232,11 +236,11 @@ export const hostMiddlewareFactory: ImmutableMiddlewareFactory<HostState> = (cor
};
};
const getNonExistingPoliciesForHostsList = async (
const getNonExistingPoliciesForEndpointsList = async (
http: HttpStart,
hosts: HostResultList['hosts'],
currentNonExistingPolicies: HostState['nonExistingPolicies']
): Promise<HostState['nonExistingPolicies'] | undefined> => {
currentNonExistingPolicies: EndpointState['nonExistingPolicies']
): Promise<EndpointState['nonExistingPolicies'] | undefined> => {
if (hosts.length === 0) {
return;
}
@ -266,14 +270,14 @@ const getNonExistingPoliciesForHostsList = async (
)})`,
},
})
).items.reduce<HostState['nonExistingPolicies']>((list, agentConfig) => {
).items.reduce<EndpointState['nonExistingPolicies']>((list, agentConfig) => {
(agentConfig.package_configs as string[]).forEach((packageConfig) => {
list[packageConfig as string] = true;
});
return list;
}, {});
const nonExisting = policyIdsToCheck.reduce<HostState['nonExistingPolicies']>(
const nonExisting = policyIdsToCheck.reduce<EndpointState['nonExistingPolicies']>(
(list, policyId) => {
if (policiesFound[policyId]) {
return list;
@ -291,7 +295,7 @@ const getNonExistingPoliciesForHostsList = async (
return nonExisting;
};
const doHostsExist = async (http: HttpStart): Promise<boolean> => {
const doEndpointsExist = async (http: HttpStart): Promise<boolean> => {
try {
return (
(
@ -304,7 +308,7 @@ const doHostsExist = async (http: HttpStart): Promise<boolean> => {
);
} catch (error) {
// eslint-disable-next-line no-console
console.error(`error while trying to check if hosts exist`);
console.error(`error while trying to check if endpoints exist`);
// eslint-disable-next-line no-console
console.error(error);
}

View file

@ -26,7 +26,7 @@ import { GetPolicyListResponse } from '../../policy/types';
const generator = new EndpointDocGenerator('seed');
export const mockHostResultList: (options?: {
export const mockEndpointResultList: (options?: {
total?: number;
request_page_size?: number;
request_page_index?: number;
@ -62,7 +62,7 @@ export const mockHostResultList: (options?: {
/**
* returns a mocked API response for retrieving a single host metadata
*/
export const mockHostDetailsApiResult = (): HostInfo => {
export const mockEndpointDetailsApiResult = (): HostInfo => {
return {
metadata: generator.generateHostMetadata(),
host_status: HostStatus.ERROR,
@ -73,14 +73,14 @@ export const mockHostDetailsApiResult = (): HostInfo => {
* Mock API handlers used by the Endpoint Host list. It also sets up a list of
* API handlers for Host details based on a list of Host results.
*/
const hostListApiPathHandlerMocks = ({
hostsResults = mockHostResultList({ total: 3 }).hosts,
const endpointListApiPathHandlerMocks = ({
endpointsResults = mockEndpointResultList({ total: 3 }).hosts,
epmPackages = [generator.generateEpmPackage()],
endpointPackageConfigs = [],
policyResponse = generator.generatePolicyResponse(),
}: {
/** route handlers will be setup for each individual host in this array */
hostsResults?: HostResultList['hosts'];
endpointsResults?: HostResultList['hosts'];
epmPackages?: GetPackagesResponse['response'];
endpointPackageConfigs?: GetPolicyListResponse['items'];
policyResponse?: HostPolicyResponse;
@ -94,17 +94,17 @@ const hostListApiPathHandlerMocks = ({
};
},
// host list
// endpoint list
'/api/endpoint/metadata': (): HostResultList => {
return {
hosts: hostsResults,
hosts: endpointsResults,
request_page_size: 10,
request_page_index: 0,
total: hostsResults?.length || 0,
total: endpointsResults?.length || 0,
};
},
// Do policies referenced in host list exist
// Do policies referenced in endpoint list exist
// just returns 1 single agent config that includes all of the packageConfig IDs provided
[INGEST_API_AGENT_CONFIGS]: (): GetAgentConfigsResponse => {
const agentConfig = generator.generateAgentConfig();
@ -137,9 +137,9 @@ const hostListApiPathHandlerMocks = ({
},
};
// Build a GET route handler for each host details based on the list of Hosts passed on input
if (hostsResults) {
hostsResults.forEach((host) => {
// Build a GET route handler for each endpoint details based on the list of Endpoints passed on input
if (endpointsResults) {
endpointsResults.forEach((host) => {
// @ts-expect-error
apiHandlers[`/api/endpoint/metadata/${host.metadata.host.id}`] = () => host;
});
@ -149,33 +149,36 @@ const hostListApiPathHandlerMocks = ({
};
/**
* Sets up mock impelementations in support of the Hosts list view
* Sets up mock impelementations in support of the Endpoints list view
*
* @param mockedHttpService
* @param hostsResults
* @param endpointsResults
* @param pathHandlersOptions
*/
export const setHostListApiMockImplementation: (
export const setEndpointListApiMockImplementation: (
mockedHttpService: jest.Mocked<HttpStart>,
apiResponses?: Parameters<typeof hostListApiPathHandlerMocks>[0]
apiResponses?: Parameters<typeof endpointListApiPathHandlerMocks>[0]
) => void = (
mockedHttpService,
{ hostsResults = mockHostResultList({ total: 3 }).hosts, ...pathHandlersOptions } = {}
{ endpointsResults = mockEndpointResultList({ total: 3 }).hosts, ...pathHandlersOptions } = {}
) => {
const apiHandlers = hostListApiPathHandlerMocks({ ...pathHandlersOptions, hostsResults });
const apiHandlers = endpointListApiPathHandlerMocks({
...pathHandlersOptions,
endpointsResults,
});
mockedHttpService.post
.mockImplementation(async (...args) => {
throw new Error(`un-expected call to http.post: ${args}`);
})
// First time called, return list of hosts
// First time called, return list of endpoints
.mockImplementationOnce(async () => {
return apiHandlers['/api/endpoint/metadata']();
});
// If the hosts list results is zero, then mock the second call to `/metadata` to return
// empty list - indicating there are no hosts currently present on the system
if (!hostsResults.length) {
// If the endpoints list results is zero, then mock the second call to `/metadata` to return
// empty list - indicating there are no endpoints currently present on the system
if (!endpointsResults.length) {
mockedHttpService.post.mockImplementationOnce(async () => {
return apiHandlers['/api/endpoint/metadata']();
});

View file

@ -4,13 +4,13 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { isOnHostPage, hasSelectedHost } from './selectors';
import { HostState } from '../types';
import { isOnEndpointPage, hasSelectedEndpoint } from './selectors';
import { EndpointState } from '../types';
import { AppAction } from '../../../../common/store/actions';
import { ImmutableReducer } from '../../../../common/store';
import { Immutable } from '../../../../../common/endpoint/types';
export const initialHostListState: Immutable<HostState> = {
export const initialEndpointListState: Immutable<EndpointState> = {
hosts: [],
pageSize: 10,
pageIndex: 0,
@ -29,15 +29,15 @@ export const initialHostListState: Immutable<HostState> = {
policyItemsLoading: false,
endpointPackageInfo: undefined,
nonExistingPolicies: {},
hostsExist: true,
endpointsExist: true,
};
/* eslint-disable-next-line complexity */
export const hostListReducer: ImmutableReducer<HostState, AppAction> = (
state = initialHostListState,
export const endpointListReducer: ImmutableReducer<EndpointState, AppAction> = (
state = initialEndpointListState,
action
) => {
if (action.type === 'serverReturnedHostList') {
if (action.type === 'serverReturnedEndpointList') {
const {
hosts,
total,
@ -53,13 +53,13 @@ export const hostListReducer: ImmutableReducer<HostState, AppAction> = (
loading: false,
error: undefined,
};
} else if (action.type === 'serverFailedToReturnHostList') {
} else if (action.type === 'serverFailedToReturnEndpointList') {
return {
...state,
error: action.payload,
loading: false,
};
} else if (action.type === 'serverReturnedHostNonExistingPolicies') {
} else if (action.type === 'serverReturnedEndpointNonExistingPolicies') {
return {
...state,
nonExistingPolicies: {
@ -67,14 +67,14 @@ export const hostListReducer: ImmutableReducer<HostState, AppAction> = (
...action.payload,
},
};
} else if (action.type === 'serverReturnedHostDetails') {
} else if (action.type === 'serverReturnedEndpointDetails') {
return {
...state,
details: action.payload.metadata,
detailsLoading: false,
detailsError: undefined,
};
} else if (action.type === 'serverFailedToReturnHostDetails') {
} else if (action.type === 'serverFailedToReturnEndpointDetails') {
return {
...state,
detailsError: action.payload,
@ -92,14 +92,14 @@ export const hostListReducer: ImmutableReducer<HostState, AppAction> = (
error: action.payload,
policyItemsLoading: false,
};
} else if (action.type === 'serverReturnedHostPolicyResponse') {
} else if (action.type === 'serverReturnedEndpointPolicyResponse') {
return {
...state,
policyResponse: action.payload.policy_response,
policyResponseLoading: false,
policyResponseError: undefined,
};
} else if (action.type === 'serverFailedToReturnHostPolicyResponse') {
} else if (action.type === 'serverFailedToReturnEndpointPolicyResponse') {
return {
...state,
policyResponseError: action.payload,
@ -111,7 +111,7 @@ export const hostListReducer: ImmutableReducer<HostState, AppAction> = (
selectedPolicyId: action.payload.selectedPolicyId,
policyResponseLoading: false,
};
} else if (action.type === 'serverCancelledHostListLoading') {
} else if (action.type === 'serverCancelledEndpointListLoading') {
return {
...state,
loading: false,
@ -126,22 +126,22 @@ export const hostListReducer: ImmutableReducer<HostState, AppAction> = (
...state,
endpointPackageInfo: action.payload,
};
} else if (action.type === 'serverReturnedHostExistValue') {
} else if (action.type === 'serverReturnedEndpointExistValue') {
return {
...state,
hostsExist: action.payload,
endpointsExist: action.payload,
};
} else if (action.type === 'userChangedUrl') {
const newState: Immutable<HostState> = {
const newState: Immutable<EndpointState> = {
...state,
location: action.payload,
};
const isCurrentlyOnListPage = isOnHostPage(newState) && !hasSelectedHost(newState);
const wasPreviouslyOnListPage = isOnHostPage(state) && !hasSelectedHost(state);
const isCurrentlyOnDetailsPage = isOnHostPage(newState) && hasSelectedHost(newState);
const wasPreviouslyOnDetailsPage = isOnHostPage(state) && hasSelectedHost(state);
const isCurrentlyOnListPage = isOnEndpointPage(newState) && !hasSelectedEndpoint(newState);
const wasPreviouslyOnListPage = isOnEndpointPage(state) && !hasSelectedEndpoint(state);
const isCurrentlyOnDetailsPage = isOnEndpointPage(newState) && hasSelectedEndpoint(newState);
const wasPreviouslyOnDetailsPage = isOnEndpointPage(state) && hasSelectedEndpoint(state);
// if on the host list page for the first time, return new location and load list
// if on the endpoint list page for the first time, return new location and load list
if (isCurrentlyOnListPage) {
if (!wasPreviouslyOnListPage) {
return {
@ -154,7 +154,7 @@ export const hostListReducer: ImmutableReducer<HostState, AppAction> = (
};
}
} else if (isCurrentlyOnDetailsPage) {
// if previous page was the list or another host details page, load host details only
// if previous page was the list or another endpoint details page, load endpoint details only
if (wasPreviouslyOnDetailsPage || wasPreviouslyOnListPage) {
return {
...state,
@ -166,7 +166,7 @@ export const hostListReducer: ImmutableReducer<HostState, AppAction> = (
policyResponseError: undefined,
};
} else {
// if previous page was not host list or host details, load both list and details
// if previous page was not endpoint list or endpoint details, load both list and details
return {
...state,
location: action.payload,
@ -180,14 +180,14 @@ export const hostListReducer: ImmutableReducer<HostState, AppAction> = (
};
}
}
// otherwise we are not on a host list or details page
// otherwise we are not on a endpoint list or details page
return {
...state,
location: action.payload,
error: undefined,
detailsError: undefined,
policyResponseError: undefined,
hostsExist: true,
endpointsExist: true,
};
}
return state;

View file

@ -14,36 +14,36 @@ import {
HostPolicyResponseConfiguration,
HostPolicyResponseActionStatus,
} from '../../../../../common/endpoint/types';
import { HostState, HostIndexUIQueryParams } from '../types';
import { MANAGEMENT_ROUTING_HOSTS_PATH } from '../../../common/constants';
import { EndpointState, EndpointIndexUIQueryParams } from '../types';
import { MANAGEMENT_ROUTING_ENDPOINTS_PATH } from '../../../common/constants';
const PAGE_SIZES = Object.freeze([10, 20, 50]);
export const listData = (state: Immutable<HostState>) => state.hosts;
export const listData = (state: Immutable<EndpointState>) => state.hosts;
export const pageIndex = (state: Immutable<HostState>): number => state.pageIndex;
export const pageIndex = (state: Immutable<EndpointState>): number => state.pageIndex;
export const pageSize = (state: Immutable<HostState>): number => state.pageSize;
export const pageSize = (state: Immutable<EndpointState>): number => state.pageSize;
export const totalHits = (state: Immutable<HostState>): number => state.total;
export const totalHits = (state: Immutable<EndpointState>): number => state.total;
export const listLoading = (state: Immutable<HostState>): boolean => state.loading;
export const listLoading = (state: Immutable<EndpointState>): boolean => state.loading;
export const listError = (state: Immutable<HostState>) => state.error;
export const listError = (state: Immutable<EndpointState>) => state.error;
export const detailsData = (state: Immutable<HostState>) => state.details;
export const detailsData = (state: Immutable<EndpointState>) => state.details;
export const detailsLoading = (state: Immutable<HostState>): boolean => state.detailsLoading;
export const detailsLoading = (state: Immutable<EndpointState>): boolean => state.detailsLoading;
export const detailsError = (state: Immutable<HostState>) => state.detailsError;
export const detailsError = (state: Immutable<EndpointState>) => state.detailsError;
export const policyItems = (state: Immutable<HostState>) => state.policyItems;
export const policyItems = (state: Immutable<EndpointState>) => state.policyItems;
export const policyItemsLoading = (state: Immutable<HostState>) => state.policyItemsLoading;
export const policyItemsLoading = (state: Immutable<EndpointState>) => state.policyItemsLoading;
export const selectedPolicyId = (state: Immutable<HostState>) => state.selectedPolicyId;
export const selectedPolicyId = (state: Immutable<EndpointState>) => state.selectedPolicyId;
export const endpointPackageInfo = (state: Immutable<HostState>) => state.endpointPackageInfo;
export const endpointPackageInfo = (state: Immutable<EndpointState>) => state.endpointPackageInfo;
export const endpointPackageVersion = createSelector(
endpointPackageInfo,
@ -53,14 +53,14 @@ export const endpointPackageVersion = createSelector(
/**
* Returns the full policy response from the endpoint after a user modifies a policy.
*/
const detailsPolicyAppliedResponse = (state: Immutable<HostState>) =>
const detailsPolicyAppliedResponse = (state: Immutable<EndpointState>) =>
state.policyResponse && state.policyResponse.Endpoint.policy.applied;
/**
* Returns the response configurations from the endpoint after a user modifies a policy.
*/
export const policyResponseConfigurations: (
state: Immutable<HostState>
state: Immutable<EndpointState>
) => undefined | Immutable<HostPolicyResponseConfiguration> = createSelector(
detailsPolicyAppliedResponse,
(applied) => {
@ -72,7 +72,7 @@ export const policyResponseConfigurations: (
* Returns a map of the number of failed and warning policy response actions per configuration.
*/
export const policyResponseFailedOrWarningActionCount: (
state: Immutable<HostState>
state: Immutable<EndpointState>
) => Map<string, number> = createSelector(detailsPolicyAppliedResponse, (applied) => {
const failureOrWarningByConfigType = new Map<string, number>();
if (applied?.response?.configurations !== undefined && applied?.actions !== undefined) {
@ -98,7 +98,7 @@ export const policyResponseFailedOrWarningActionCount: (
* Returns the actions taken by the endpoint for each response configuration after a user modifies a policy.
*/
export const policyResponseActions: (
state: Immutable<HostState>
state: Immutable<EndpointState>
) => undefined | Immutable<HostPolicyResponseAppliedAction[]> = createSelector(
detailsPolicyAppliedResponse,
(applied) => {
@ -106,32 +106,32 @@ export const policyResponseActions: (
}
);
export const policyResponseLoading = (state: Immutable<HostState>): boolean =>
export const policyResponseLoading = (state: Immutable<EndpointState>): boolean =>
state.policyResponseLoading;
export const policyResponseError = (state: Immutable<HostState>) => state.policyResponseError;
export const policyResponseError = (state: Immutable<EndpointState>) => state.policyResponseError;
export const isOnHostPage = (state: Immutable<HostState>) => {
export const isOnEndpointPage = (state: Immutable<EndpointState>) => {
return (
matchPath(state.location?.pathname ?? '', {
path: MANAGEMENT_ROUTING_HOSTS_PATH,
path: MANAGEMENT_ROUTING_ENDPOINTS_PATH,
exact: true,
}) !== null
);
};
export const uiQueryParams: (
state: Immutable<HostState>
) => Immutable<HostIndexUIQueryParams> = createSelector(
(state: Immutable<HostState>) => state.location,
(location: Immutable<HostState>['location']) => {
const data: HostIndexUIQueryParams = { page_index: '0', page_size: '10' };
state: Immutable<EndpointState>
) => Immutable<EndpointIndexUIQueryParams> = createSelector(
(state: Immutable<EndpointState>) => state.location,
(location: Immutable<EndpointState>['location']) => {
const data: EndpointIndexUIQueryParams = { page_index: '0', page_size: '10' };
if (location) {
// Removes the `?` from the beginning of query string if it exists
const query = querystring.parse(location.search.slice(1));
const keys: Array<keyof HostIndexUIQueryParams> = [
'selected_host',
const keys: Array<keyof EndpointIndexUIQueryParams> = [
'selected_endpoint',
'page_size',
'page_index',
'show',
@ -171,15 +171,15 @@ export const uiQueryParams: (
}
);
export const hasSelectedHost: (state: Immutable<HostState>) => boolean = createSelector(
export const hasSelectedEndpoint: (state: Immutable<EndpointState>) => boolean = createSelector(
uiQueryParams,
({ selected_host: selectedHost }) => {
return selectedHost !== undefined;
({ selected_endpoint: selectedEndpoint }) => {
return selectedEndpoint !== undefined;
}
);
/** What policy details panel view to show */
export const showView: (state: HostState) => 'policy_response' | 'details' = createSelector(
export const showView: (state: EndpointState) => 'policy_response' | 'details' = createSelector(
uiQueryParams,
(searchParams) => {
return searchParams.show === 'policy_response' ? 'policy_response' : 'details';
@ -189,7 +189,7 @@ export const showView: (state: HostState) => 'policy_response' | 'details' = cre
/**
* Returns the Policy Response overall status
*/
export const policyResponseStatus: (state: Immutable<HostState>) => string = createSelector(
export const policyResponseStatus: (state: Immutable<EndpointState>) => string = createSelector(
(state) => state.policyResponse,
(policyResponse) => {
return (policyResponse && policyResponse?.Endpoint?.policy?.applied?.status) || '';
@ -197,15 +197,16 @@ export const policyResponseStatus: (state: Immutable<HostState>) => string = cre
);
/**
* returns the list of known non-existing polices that may have been in the Host API response.
* returns the list of known non-existing polices that may have been in the Endpoint API response.
* @param state
*/
export const nonExistingPolicies: (
state: Immutable<HostState>
) => Immutable<HostState['nonExistingPolicies']> = (state) => state.nonExistingPolicies;
state: Immutable<EndpointState>
) => Immutable<EndpointState['nonExistingPolicies']> = (state) => state.nonExistingPolicies;
/**
* Return boolean that indicates whether hosts exist
* Return boolean that indicates whether endpoints exist
* @param state
*/
export const hostsExist: (state: Immutable<HostState>) => boolean = (state) => state.hostsExist;
export const endpointsExist: (state: Immutable<EndpointState>) => boolean = (state) =>
state.endpointsExist;

View file

@ -15,7 +15,7 @@ import {
import { ServerApiError } from '../../../common/types';
import { GetPackagesResponse } from '../../../../../ingest_manager/common';
export interface HostState {
export interface EndpointState {
/** list of host **/
hosts: HostInfo[];
/** number of items per page */
@ -53,15 +53,15 @@ export interface HostState {
/** tracks the list of policies IDs used in Host metadata that may no longer exist */
nonExistingPolicies: Record<string, boolean>;
/** Tracks whether hosts exist and helps control if onboarding should be visible */
hostsExist: boolean;
endpointsExist: boolean;
}
/**
* Query params on the host page parsed from the URL
*/
export interface HostIndexUIQueryParams {
/** Selected host id shows host details flyout */
selected_host?: string;
export interface EndpointIndexUIQueryParams {
/** Selected endpoint id shows host details flyout */
selected_endpoint?: string;
/** How many items to show in list */
page_size?: string;
/** Which page to show */

View file

@ -6,7 +6,7 @@
import React, { memo, useMemo } from 'react';
import { EuiLink, EuiLinkAnchorProps } from '@elastic/eui';
import { useHostSelector } from '../hooks';
import { useEndpointSelector } from '../hooks';
import { nonExistingPolicies } from '../../store/selectors';
import { getPolicyDetailPath } from '../../../../common/routing';
import { useFormatUrl } from '../../../../../common/components/link_to';
@ -18,12 +18,12 @@ import { useNavigateByRouterEventHandler } from '../../../../../common/hooks/end
* the `nonExistingPolicies` value in the store. If it does not exist, then regular
* text is returned.
*/
export const HostPolicyLink = memo<
export const EndpointPolicyLink = memo<
Omit<EuiLinkAnchorProps, 'href'> & {
policyId: string;
}
>(({ policyId, children, onClick, ...otherProps }) => {
const missingPolicies = useHostSelector(nonExistingPolicies);
const missingPolicies = useEndpointSelector(nonExistingPolicies);
const { formatUrl } = useFormatUrl(SecurityPageName.administration);
const { toRoutePath, toRouteUrl } = useMemo(() => {
const toPath = getPolicyDetailPath(policyId);
@ -50,4 +50,4 @@ export const HostPolicyLink = memo<
);
});
HostPolicyLink.displayName = 'HostPolicyLink';
EndpointPolicyLink.displayName = 'EndpointPolicyLink';

View file

@ -19,18 +19,18 @@ import React, { memo, useMemo } from 'react';
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
import { HostMetadata } from '../../../../../../common/endpoint/types';
import { useHostSelector, useAgentDetailsIngestUrl } from '../hooks';
import { useEndpointSelector, useAgentDetailsIngestUrl } from '../hooks';
import { useNavigateToAppEventHandler } from '../../../../../common/hooks/endpoint/use_navigate_to_app_event_handler';
import { policyResponseStatus, uiQueryParams } from '../../store/selectors';
import { POLICY_STATUS_TO_HEALTH_COLOR } from '../host_constants';
import { FormattedDateAndTime } from '../../../../../common/components/endpoint/formatted_date_time';
import { useNavigateByRouterEventHandler } from '../../../../../common/hooks/endpoint/use_navigate_by_router_event_handler';
import { LinkToApp } from '../../../../../common/components/endpoint/link_to_app';
import { getHostDetailsPath } from '../../../../common/routing';
import { getEndpointDetailsPath } from '../../../../common/routing';
import { SecurityPageName } from '../../../../../app/types';
import { useFormatUrl } from '../../../../../common/components/link_to';
import { AgentDetailsReassignConfigAction } from '../../../../../../../ingest_manager/public';
import { HostPolicyLink } from '../components/host_policy_link';
import { EndpointPolicyLink } from '../components/endpoint_policy_link';
const HostIds = styled(EuiListGroupItem)`
margin-top: 0;
@ -51,15 +51,15 @@ const LinkToExternalApp = styled.div`
const openReassignFlyoutSearch = '?openReassignFlyout=true';
export const HostDetails = memo(({ details }: { details: HostMetadata }) => {
export const EndpointDetails = memo(({ details }: { details: HostMetadata }) => {
const agentId = details.elastic.agent.id;
const {
url: agentDetailsUrl,
appId: ingestAppId,
appPath: agentDetailsAppPath,
} = useAgentDetailsIngestUrl(agentId);
const queryParams = useHostSelector(uiQueryParams);
const policyStatus = useHostSelector(
const queryParams = useEndpointSelector(uiQueryParams);
const policyStatus = useEndpointSelector(
policyResponseStatus
) as keyof typeof POLICY_STATUS_TO_HEALTH_COLOR;
const { formatUrl } = useFormatUrl(SecurityPageName.administration);
@ -67,13 +67,13 @@ export const HostDetails = memo(({ details }: { details: HostMetadata }) => {
const detailsResultsUpper = useMemo(() => {
return [
{
title: i18n.translate('xpack.securitySolution.endpoint.host.details.os', {
title: i18n.translate('xpack.securitySolution.endpoint.details.os', {
defaultMessage: 'OS',
}),
description: details.host.os.full,
},
{
title: i18n.translate('xpack.securitySolution.endpoint.host.details.lastSeen', {
title: i18n.translate('xpack.securitySolution.endpoint.details.lastSeen', {
defaultMessage: 'Last Seen',
}),
description: <FormattedDateAndTime date={new Date(details['@timestamp'])} />,
@ -83,19 +83,19 @@ export const HostDetails = memo(({ details }: { details: HostMetadata }) => {
const [policyResponseUri, policyResponseRoutePath] = useMemo(() => {
// eslint-disable-next-line @typescript-eslint/naming-convention
const { selected_host, show, ...currentUrlParams } = queryParams;
const { selected_endpoint, show, ...currentUrlParams } = queryParams;
return [
formatUrl(
getHostDetailsPath({
name: 'hostPolicyResponse',
getEndpointDetailsPath({
name: 'endpointPolicyResponse',
...currentUrlParams,
selected_host: details.host.id,
selected_endpoint: details.host.id,
})
),
getHostDetailsPath({
name: 'hostPolicyResponse',
getEndpointDetailsPath({
name: 'endpointPolicyResponse',
...currentUrlParams,
selected_host: details.host.id,
selected_endpoint: details.host.id,
}),
];
}, [details.host.id, formatUrl, queryParams]);
@ -110,7 +110,10 @@ export const HostDetails = memo(({ details }: { details: HostMetadata }) => {
onDoneNavigateTo: [
'securitySolution:administration',
{
path: getHostDetailsPath({ name: 'hostDetails', selected_host: details.host.id }),
path: getEndpointDetailsPath({
name: 'endpointDetails',
selected_endpoint: details.host.id,
}),
},
],
},
@ -121,22 +124,22 @@ export const HostDetails = memo(({ details }: { details: HostMetadata }) => {
const detailsResultsPolicy = useMemo(() => {
return [
{
title: i18n.translate('xpack.securitySolution.endpoint.host.details.policy', {
title: i18n.translate('xpack.securitySolution.endpoint.details.policy', {
defaultMessage: 'Integration',
}),
description: (
<>
<HostPolicyLink
<EndpointPolicyLink
policyId={details.Endpoint.policy.applied.id}
data-test-subj="policyDetailsValue"
>
{details.Endpoint.policy.applied.name}
</HostPolicyLink>
</EndpointPolicyLink>
</>
),
},
{
title: i18n.translate('xpack.securitySolution.endpoint.host.details.policyStatus', {
title: i18n.translate('xpack.securitySolution.endpoint.details.policyStatus', {
defaultMessage: 'Configuration response',
}),
description: (
@ -152,7 +155,7 @@ export const HostDetails = memo(({ details }: { details: HostMetadata }) => {
>
<EuiText size="m">
<FormattedMessage
id="xpack.securitySolution.endpoint.host.details.policyStatusValue"
id="xpack.securitySolution.endpoint.details.policyStatusValue"
defaultMessage="{policyStatus, select, success {Success} warning {Warning} failure {Failed} other {Unknown}}"
values={{ policyStatus }}
/>
@ -166,7 +169,7 @@ export const HostDetails = memo(({ details }: { details: HostMetadata }) => {
const detailsResultsLower = useMemo(() => {
return [
{
title: i18n.translate('xpack.securitySolution.endpoint.host.details.ipAddress', {
title: i18n.translate('xpack.securitySolution.endpoint.details.ipAddress', {
defaultMessage: 'IP Address',
}),
description: (
@ -178,13 +181,13 @@ export const HostDetails = memo(({ details }: { details: HostMetadata }) => {
),
},
{
title: i18n.translate('xpack.securitySolution.endpoint.host.details.hostname', {
title: i18n.translate('xpack.securitySolution.endpoint.details.hostname', {
defaultMessage: 'Hostname',
}),
description: details.host.hostname,
},
{
title: i18n.translate('xpack.securitySolution.endpoint.host.details.endpointVersion', {
title: i18n.translate('xpack.securitySolution.endpoint.details.endpointVersion', {
defaultMessage: 'Endpoint Version',
}),
description: details.agent.version,
@ -197,13 +200,13 @@ export const HostDetails = memo(({ details }: { details: HostMetadata }) => {
<EuiDescriptionList
type="column"
listItems={detailsResultsUpper}
data-test-subj="hostDetailsUpperList"
data-test-subj="endpointDetailsUpperList"
/>
<EuiHorizontalRule margin="m" />
<EuiDescriptionList
type="column"
listItems={detailsResultsPolicy}
data-test-subj="hostDetailsPolicyList"
data-test-subj="endpointDetailsPolicyList"
/>
<LinkToExternalApp>
<LinkToApp
@ -211,11 +214,11 @@ export const HostDetails = memo(({ details }: { details: HostMetadata }) => {
appPath={agentDetailsWithFlyoutPath}
href={agentDetailsWithFlyoutUrl}
onClick={handleReassignEndpointsClick}
data-test-subj="hostDetailsLinkToIngest"
data-test-subj="endpointDetailsLinkToIngest"
>
<EuiIcon type="savedObjectsApp" className="linkToAppIcon" />
<FormattedMessage
id="xpack.securitySolution.endpoint.host.details.linkToIngestTitle"
id="xpack.securitySolution.endpoint.details.linkToIngestTitle"
defaultMessage="Reassign Configuration"
/>
<EuiIcon type="popout" className="linkToAppPopoutIcon" />
@ -225,10 +228,10 @@ export const HostDetails = memo(({ details }: { details: HostMetadata }) => {
<EuiDescriptionList
type="column"
listItems={detailsResultsLower}
data-test-subj="hostDetailsLowerList"
data-test-subj="endpointDetailsLowerList"
/>
</>
);
});
HostDetails.displayName = 'HostDetails';
EndpointDetails.displayName = 'EndpointDetails';

View file

@ -19,7 +19,7 @@ import { useHistory } from 'react-router-dom';
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
import { useToasts } from '../../../../../common/lib/kibana';
import { useHostSelector } from '../hooks';
import { useEndpointSelector } from '../hooks';
import { urlFromQueryParams } from '../url_from_query_params';
import {
uiQueryParams,
@ -33,36 +33,39 @@ import {
policyResponseError,
policyResponseLoading,
} from '../../store/selectors';
import { HostDetails } from './host_details';
import { EndpointDetails } from './endpoint_details';
import { PolicyResponse } from './policy_response';
import { HostMetadata } from '../../../../../../common/endpoint/types';
import { FlyoutSubHeader, FlyoutSubHeaderProps } from './components/flyout_sub_header';
import { useNavigateByRouterEventHandler } from '../../../../../common/hooks/endpoint/use_navigate_by_router_event_handler';
import { getHostListPath } from '../../../../common/routing';
import { getEndpointListPath } from '../../../../common/routing';
import { SecurityPageName } from '../../../../../app/types';
import { useFormatUrl } from '../../../../../common/components/link_to';
export const HostDetailsFlyout = memo(() => {
export const EndpointDetailsFlyout = memo(() => {
const history = useHistory();
const toasts = useToasts();
const queryParams = useHostSelector(uiQueryParams);
const { selected_host: selectedHost, ...queryParamsWithoutSelectedHost } = queryParams;
const details = useHostSelector(detailsData);
const loading = useHostSelector(detailsLoading);
const error = useHostSelector(detailsError);
const show = useHostSelector(showView);
const queryParams = useEndpointSelector(uiQueryParams);
const {
selected_endpoint: selectedEndpoint,
...queryParamsWithoutSelectedEndpoint
} = queryParams;
const details = useEndpointSelector(detailsData);
const loading = useEndpointSelector(detailsLoading);
const error = useEndpointSelector(detailsError);
const show = useEndpointSelector(showView);
const handleFlyoutClose = useCallback(() => {
history.push(urlFromQueryParams(queryParamsWithoutSelectedHost));
}, [history, queryParamsWithoutSelectedHost]);
history.push(urlFromQueryParams(queryParamsWithoutSelectedEndpoint));
}, [history, queryParamsWithoutSelectedEndpoint]);
useEffect(() => {
if (error !== undefined) {
toasts.addDanger({
title: i18n.translate('xpack.securitySolution.endpoint.host.details.errorTitle', {
title: i18n.translate('xpack.securitySolution.endpoint.details.errorTitle', {
defaultMessage: 'Could not find host',
}),
text: i18n.translate('xpack.securitySolution.endpoint.host.details.errorBody', {
text: i18n.translate('xpack.securitySolution.endpoint.details.errorBody', {
defaultMessage: 'Please exit the flyout and select an available host.',
}),
});
@ -73,12 +76,12 @@ export const HostDetailsFlyout = memo(() => {
<EuiFlyout
onClose={handleFlyoutClose}
style={{ zIndex: 4001 }}
data-test-subj="hostDetailsFlyout"
data-test-subj="endpointDetailsFlyout"
size="s"
>
<EuiFlyoutHeader hasBorder>
<EuiTitle size="s">
<h2 data-test-subj="hostDetailsFlyoutTitle">
<h2 data-test-subj="endpointDetailsFlyoutTitle">
{loading ? <EuiLoadingContent lines={1} /> : details?.host?.hostname}
</h2>
</EuiTitle>
@ -93,8 +96,8 @@ export const HostDetailsFlyout = memo(() => {
<>
{show === 'details' && (
<>
<EuiFlyoutBody data-test-subj="hostDetailsFlyoutBody">
<HostDetails details={details} />
<EuiFlyoutBody data-test-subj="endpointDetailsFlyoutBody">
<EndpointDetails details={details} />
</EuiFlyoutBody>
</>
)}
@ -105,31 +108,31 @@ export const HostDetailsFlyout = memo(() => {
);
});
HostDetailsFlyout.displayName = 'HostDetailsFlyout';
EndpointDetailsFlyout.displayName = 'EndpointDetailsFlyout';
const PolicyResponseFlyoutPanel = memo<{
hostMeta: HostMetadata;
}>(({ hostMeta }) => {
const { show, ...queryParams } = useHostSelector(uiQueryParams);
const responseConfig = useHostSelector(policyResponseConfigurations);
const responseActions = useHostSelector(policyResponseActions);
const responseAttentionCount = useHostSelector(policyResponseFailedOrWarningActionCount);
const loading = useHostSelector(policyResponseLoading);
const error = useHostSelector(policyResponseError);
const { show, ...queryParams } = useEndpointSelector(uiQueryParams);
const responseConfig = useEndpointSelector(policyResponseConfigurations);
const responseActions = useEndpointSelector(policyResponseActions);
const responseAttentionCount = useEndpointSelector(policyResponseFailedOrWarningActionCount);
const loading = useEndpointSelector(policyResponseLoading);
const error = useEndpointSelector(policyResponseError);
const { formatUrl } = useFormatUrl(SecurityPageName.administration);
const [detailsUri, detailsRoutePath] = useMemo(
() => [
formatUrl(
getHostListPath({
name: 'hostList',
getEndpointListPath({
name: 'endpointList',
...queryParams,
selected_host: hostMeta.host.id,
selected_endpoint: hostMeta.host.id,
})
),
getHostListPath({
name: 'hostList',
getEndpointListPath({
name: 'endpointList',
...queryParams,
selected_host: hostMeta.host.id,
selected_endpoint: hostMeta.host.id,
}),
],
[hostMeta.host.id, formatUrl, queryParams]
@ -137,7 +140,7 @@ const PolicyResponseFlyoutPanel = memo<{
const backToDetailsClickHandler = useNavigateByRouterEventHandler(detailsRoutePath);
const backButtonProp = useMemo((): FlyoutSubHeaderProps['backButton'] => {
return {
title: i18n.translate('xpack.securitySolution.endpoint.host.policyResponse.backLinkTitle', {
title: i18n.translate('xpack.securitySolution.endpoint.policyResponse.backLinkTitle', {
defaultMessage: 'Endpoint Details',
}),
href: detailsUri,
@ -149,13 +152,13 @@ const PolicyResponseFlyoutPanel = memo<{
<>
<FlyoutSubHeader
backButton={backButtonProp}
data-test-subj="hostDetailsPolicyResponseFlyoutHeader"
data-test-subj="endpointDetailsPolicyResponseFlyoutHeader"
/>
<EuiFlyoutBody data-test-subj="hostDetailsPolicyResponseFlyoutBody">
<EuiText data-test-subj="hostDetailsPolicyResponseFlyoutTitle">
<EuiFlyoutBody data-test-subj="endpointDetailsPolicyResponseFlyoutBody">
<EuiText data-test-subj="endpointDetailsPolicyResponseFlyoutTitle">
<h4>
<FormattedMessage
id="xpack.securitySolution.endpoint.host.policyResponse.title"
id="xpack.securitySolution.endpoint.policyResponse.title"
defaultMessage="Configuration Response"
/>
</h4>
@ -164,7 +167,7 @@ const PolicyResponseFlyoutPanel = memo<{
<EuiEmptyPrompt
title={
<FormattedMessage
id="xpack.securitySolution.endpoint.hostDetails.noPolicyResponse"
id="xpack.securitySolution.endpoint.details.noPolicyResponse"
defaultMessage="No configuration response available"
/>
}

View file

@ -90,7 +90,7 @@ const ResponseActions = memo(
<EuiAccordion
id={action + index}
key={action + index}
data-test-subj="hostDetailsPolicyResponseActionsAccordion"
data-test-subj="endpointDetailsPolicyResponseActionsAccordion"
className="policyResponseActionsAccordion"
buttonContent={
<EuiText
@ -150,7 +150,7 @@ export const PolicyResponse = memo(
<PolicyResponseConfigAccordion
id={generateId(`id_${key}`)}
key={generateId(`key_${key}`)}
data-test-subj="hostDetailsPolicyResponseConfigAccordion"
data-test-subj="endpointDetailsPolicyResponseConfigAccordion"
buttonContent={
<EuiText size="s">
<p>{formatResponse(key)}</p>
@ -162,7 +162,7 @@ export const PolicyResponse = memo(
attentionCount > 0 && (
<EuiNotificationBadge
className="policyResponseAttentionBadge"
data-test-subj="hostDetailsPolicyResponseAttentionBadge"
data-test-subj="endpointDetailsPolicyResponseAttentionBadge"
>
{attentionCount}
</EuiNotificationBadge>

View file

@ -9,198 +9,189 @@ import { i18n } from '@kbn/i18n';
const policyResponses: Array<[string, string]> = [
[
'configure_dns_events',
i18n.translate(
'xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_dns_events',
{ defaultMessage: 'Configure DNS Events' }
),
i18n.translate('xpack.securitySolution.endpoint.details.policyResponse.configure_dns_events', {
defaultMessage: 'Configure DNS Events',
}),
],
[
'configure_elasticsearch_connection',
i18n.translate(
'xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_elasticsearch_connection',
'xpack.securitySolution.endpoint.details.policyResponse.configure_elasticsearch_connection',
{ defaultMessage: 'Configure Elastic Search Connection' }
),
],
[
'configure_file_events',
i18n.translate(
'xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_file_events',
{ defaultMessage: 'Configure File Events' }
),
i18n.translate('xpack.securitySolution.endpoint.details.policyResponse.configure_file_events', {
defaultMessage: 'Configure File Events',
}),
],
[
'configure_imageload_events',
i18n.translate(
'xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_imageload_events',
'xpack.securitySolution.endpoint.details.policyResponse.configure_imageload_events',
{ defaultMessage: 'Configure Image Load Events' }
),
],
[
'configure_kernel',
i18n.translate('xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_kernel', {
i18n.translate('xpack.securitySolution.endpoint.details.policyResponse.configure_kernel', {
defaultMessage: 'Configure Kernel',
}),
],
[
'configure_logging',
i18n.translate('xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_logging', {
i18n.translate('xpack.securitySolution.endpoint.details.policyResponse.configure_logging', {
defaultMessage: 'Configure Logging',
}),
],
[
'configure_malware',
i18n.translate('xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_malware', {
i18n.translate('xpack.securitySolution.endpoint.details.policyResponse.configure_malware', {
defaultMessage: 'Configure Malware',
}),
],
[
'configure_network_events',
i18n.translate(
'xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_network_events',
'xpack.securitySolution.endpoint.details.policyResponse.configure_network_events',
{ defaultMessage: 'Configure Network Events' }
),
],
[
'configure_process_events',
i18n.translate(
'xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_process_events',
'xpack.securitySolution.endpoint.details.policyResponse.configure_process_events',
{ defaultMessage: 'Configure Process Events' }
),
],
[
'configure_registry_events',
i18n.translate(
'xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_registry_events',
'xpack.securitySolution.endpoint.details.policyResponse.configure_registry_events',
{ defaultMessage: 'Configure Registry Events' }
),
],
[
'configure_security_events',
i18n.translate(
'xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_security_events',
'xpack.securitySolution.endpoint.details.policyResponse.configure_security_events',
{ defaultMessage: 'Configure Security Events' }
),
],
[
'connect_kernel',
i18n.translate('xpack.securitySolution.endpoint.hostDetails.policyResponse.connect_kernel', {
i18n.translate('xpack.securitySolution.endpoint.details.policyResponse.connect_kernel', {
defaultMessage: 'Connect Kernel',
}),
],
[
'detect_async_image_load_events',
i18n.translate(
'xpack.securitySolution.endpoint.hostDetails.policyResponse.detect_async_image_load_events',
'xpack.securitySolution.endpoint.details.policyResponse.detect_async_image_load_events',
{ defaultMessage: 'Detect Async Image Load Events' }
),
],
[
'detect_file_open_events',
i18n.translate(
'xpack.securitySolution.endpoint.hostDetails.policyResponse.detect_file_open_events',
'xpack.securitySolution.endpoint.details.policyResponse.detect_file_open_events',
{ defaultMessage: 'Detect File Open Events' }
),
],
[
'detect_file_write_events',
i18n.translate(
'xpack.securitySolution.endpoint.hostDetails.policyResponse.detect_file_write_events',
'xpack.securitySolution.endpoint.details.policyResponse.detect_file_write_events',
{ defaultMessage: 'Detect File Write Events' }
),
],
[
'detect_network_events',
i18n.translate(
'xpack.securitySolution.endpoint.hostDetails.policyResponse.detect_network_events',
{ defaultMessage: 'Detect Network Events' }
),
i18n.translate('xpack.securitySolution.endpoint.details.policyResponse.detect_network_events', {
defaultMessage: 'Detect Network Events',
}),
],
[
'detect_process_events',
i18n.translate(
'xpack.securitySolution.endpoint.hostDetails.policyResponse.detect_process_events',
{ defaultMessage: 'Detect Process Events' }
),
i18n.translate('xpack.securitySolution.endpoint.details.policyResponse.detect_process_events', {
defaultMessage: 'Detect Process Events',
}),
],
[
'detect_registry_events',
i18n.translate(
'xpack.securitySolution.endpoint.hostDetails.policyResponse.detect_registry_events',
'xpack.securitySolution.endpoint.details.policyResponse.detect_registry_events',
{ defaultMessage: 'Detect Registry Events' }
),
],
[
'detect_sync_image_load_events',
i18n.translate(
'xpack.securitySolution.endpoint.hostDetails.policyResponse.detect_sync_image_load_events',
'xpack.securitySolution.endpoint.details.policyResponse.detect_sync_image_load_events',
{ defaultMessage: 'Detect Sync Image Load Events' }
),
],
[
'download_global_artifacts',
i18n.translate(
'xpack.securitySolution.endpoint.hostDetails.policyResponse.download_global_artifacts',
'xpack.securitySolution.endpoint.details.policyResponse.download_global_artifacts',
{ defaultMessage: 'Download Global Artifacts' }
),
],
[
'download_user_artifacts',
i18n.translate(
'xpack.securitySolution.endpoint.hostDetails.policyResponse.download_user_artifacts',
'xpack.securitySolution.endpoint.details.policyResponse.download_user_artifacts',
{ defaultMessage: 'Download User Artifacts' }
),
],
[
'load_config',
i18n.translate('xpack.securitySolution.endpoint.hostDetails.policyResponse.load_config', {
i18n.translate('xpack.securitySolution.endpoint.details.policyResponse.load_config', {
defaultMessage: 'Load Config',
}),
],
[
'load_malware_model',
i18n.translate(
'xpack.securitySolution.endpoint.hostDetails.policyResponse.load_malware_model',
{ defaultMessage: 'Load Malware Model' }
),
i18n.translate('xpack.securitySolution.endpoint.details.policyResponse.load_malware_model', {
defaultMessage: 'Load Malware Model',
}),
],
[
'read_elasticsearch_config',
i18n.translate(
'xpack.securitySolution.endpoint.hostDetails.policyResponse.read_elasticsearch_config',
'xpack.securitySolution.endpoint.details.policyResponse.read_elasticsearch_config',
{ defaultMessage: 'Read ElasticSearch Config' }
),
],
[
'read_events_config',
i18n.translate(
'xpack.securitySolution.endpoint.hostDetails.policyResponse.read_events_config',
{ defaultMessage: 'Read Events Config' }
),
i18n.translate('xpack.securitySolution.endpoint.details.policyResponse.read_events_config', {
defaultMessage: 'Read Events Config',
}),
],
[
'read_kernel_config',
i18n.translate(
'xpack.securitySolution.endpoint.hostDetails.policyResponse.read_kernel_config',
{ defaultMessage: 'Read Kernel Config' }
),
i18n.translate('xpack.securitySolution.endpoint.details.policyResponse.read_kernel_config', {
defaultMessage: 'Read Kernel Config',
}),
],
[
'read_logging_config',
i18n.translate(
'xpack.securitySolution.endpoint.hostDetails.policyResponse.read_logging_config',
{ defaultMessage: 'Read Logging Config' }
),
i18n.translate('xpack.securitySolution.endpoint.details.policyResponse.read_logging_config', {
defaultMessage: 'Read Logging Config',
}),
],
[
'read_malware_config',
i18n.translate(
'xpack.securitySolution.endpoint.hostDetails.policyResponse.read_malware_config',
{ defaultMessage: 'Read Malware Config' }
),
i18n.translate('xpack.securitySolution.endpoint.details.policyResponse.read_malware_config', {
defaultMessage: 'Read Malware Config',
}),
],
[
'workflow',
i18n.translate('xpack.securitySolution.endpoint.hostDetails.policyResponse.workflow', {
i18n.translate('xpack.securitySolution.endpoint.details.policyResponse.workflow', {
defaultMessage: 'Workflow',
}),
],
@ -211,43 +202,43 @@ const responseMap = new Map<string, string>(policyResponses);
// Additional values used in the Policy Response UI
responseMap.set(
'success',
i18n.translate('xpack.securitySolution.endpoint.hostDetails.policyResponse.success', {
i18n.translate('xpack.securitySolution.endpoint.details.policyResponse.success', {
defaultMessage: 'Success',
})
);
responseMap.set(
'warning',
i18n.translate('xpack.securitySolution.endpoint.hostDetails.policyResponse.warning', {
i18n.translate('xpack.securitySolution.endpoint.details.policyResponse.warning', {
defaultMessage: 'Warning',
})
);
responseMap.set(
'failure',
i18n.translate('xpack.securitySolution.endpoint.hostDetails.policyResponse.failed', {
i18n.translate('xpack.securitySolution.endpoint.details.policyResponse.failed', {
defaultMessage: 'Failed',
})
);
responseMap.set(
'logging',
i18n.translate('xpack.securitySolution.endpoint.hostDetails.policyResponse.logging', {
i18n.translate('xpack.securitySolution.endpoint.details.policyResponse.logging', {
defaultMessage: 'Logging',
})
);
responseMap.set(
'streaming',
i18n.translate('xpack.securitySolution.endpoint.hostDetails.policyResponse.streaming', {
i18n.translate('xpack.securitySolution.endpoint.details.policyResponse.streaming', {
defaultMessage: 'Streaming',
})
);
responseMap.set(
'malware',
i18n.translate('xpack.securitySolution.endpoint.hostDetails.policyResponse.malware', {
i18n.translate('xpack.securitySolution.endpoint.details.policyResponse.malware', {
defaultMessage: 'Malware',
})
);
responseMap.set(
'events',
i18n.translate('xpack.securitySolution.endpoint.hostDetails.policyResponse.events', {
i18n.translate('xpack.securitySolution.endpoint.details.policyResponse.events', {
defaultMessage: 'Events',
})
);

View file

@ -7,16 +7,18 @@
import { useSelector } from 'react-redux';
import { useMemo } from 'react';
import { useKibana } from '../../../../common/lib/kibana';
import { HostState } from '../types';
import { EndpointState } from '../types';
import {
MANAGEMENT_STORE_HOSTS_NAMESPACE,
MANAGEMENT_STORE_ENDPOINTS_NAMESPACE,
MANAGEMENT_STORE_GLOBAL_NAMESPACE,
} from '../../../common/constants';
import { State } from '../../../../common/store';
export function useHostSelector<TSelected>(selector: (state: HostState) => TSelected) {
export function useEndpointSelector<TSelected>(selector: (state: EndpointState) => TSelected) {
return useSelector(function (state: State) {
return selector(
state[MANAGEMENT_STORE_GLOBAL_NAMESPACE][MANAGEMENT_STORE_HOSTS_NAMESPACE] as HostState
state[MANAGEMENT_STORE_GLOBAL_NAMESPACE][
MANAGEMENT_STORE_ENDPOINTS_NAMESPACE
] as EndpointState
);
});
}

View file

@ -7,12 +7,12 @@
import React from 'react';
import * as reactTestingLibrary from '@testing-library/react';
import { HostList } from './index';
import { EndpointList } from './index';
import {
mockHostDetailsApiResult,
mockHostResultList,
setHostListApiMockImplementation,
} from '../store/mock_host_result_list';
mockEndpointDetailsApiResult,
mockEndpointResultList,
setEndpointListApiMockImplementation,
} from '../store/mock_endpoint_result_list';
import { AppContextTestRender, createAppRootMockRenderer } from '../../../../common/mock/endpoint';
import {
HostInfo,
@ -27,7 +27,7 @@ import { mockPolicyResultList } from '../../policy/store/policy_list/test_mock_u
jest.mock('../../../../common/components/link_to');
describe('when on the hosts page', () => {
describe('when on the list page', () => {
const docGenerator = new EndpointDocGenerator();
let render: () => ReturnType<AppContextTestRender['render']>;
let history: AppContextTestRender['history'];
@ -38,9 +38,9 @@ describe('when on the hosts page', () => {
beforeEach(() => {
const mockedContext = createAppRootMockRenderer();
({ history, store, coreStart, middlewareSpy } = mockedContext);
render = () => mockedContext.render(<HostList />);
render = () => mockedContext.render(<EndpointList />);
reactTestingLibrary.act(() => {
history.push('/hosts');
history.push('/endpoints');
});
});
@ -50,10 +50,10 @@ describe('when on the hosts page', () => {
expect(timelineFlyout).toBeNull();
});
describe('when there are no hosts or polices', () => {
describe('when there are no endpoints or polices', () => {
beforeEach(() => {
setHostListApiMockImplementation(coreStart.http, {
hostsResults: [],
setEndpointListApiMockImplementation(coreStart.http, {
endpointsResults: [],
});
});
@ -70,8 +70,8 @@ describe('when on the hosts page', () => {
describe('when there are policies, but no hosts', () => {
beforeEach(async () => {
setHostListApiMockImplementation(coreStart.http, {
hostsResults: [],
setEndpointListApiMockImplementation(coreStart.http, {
endpointsResults: [],
endpointPackageConfigs: mockPolicyResultList({ total: 3 }).items,
});
});
@ -111,7 +111,7 @@ describe('when on the hosts page', () => {
it('should not show the flyout', () => {
const renderResult = render();
expect.assertions(1);
return renderResult.findByTestId('hostDetailsFlyout').catch((e) => {
return renderResult.findByTestId('endpointDetailsFlyout').catch((e) => {
expect(e).not.toBeNull();
});
});
@ -122,7 +122,7 @@ describe('when on the hosts page', () => {
let firstPolicyID: string;
beforeEach(() => {
reactTestingLibrary.act(() => {
const hostListData = mockHostResultList({ total: 4 }).hosts;
const hostListData = mockEndpointResultList({ total: 4 }).hosts;
firstPolicyID = hostListData[0].metadata.Endpoint.policy.applied.id;
@ -142,8 +142,8 @@ describe('when on the hosts page', () => {
const ingestPackageConfigs = mockPolicyResultList({ total: 1 }).items;
ingestPackageConfigs[0].id = firstPolicyID;
setHostListApiMockImplementation(coreStart.http, {
hostsResults: hostListData,
setEndpointListApiMockImplementation(coreStart.http, {
endpointsResults: hostListData,
endpointPackageConfigs: ingestPackageConfigs,
});
});
@ -152,7 +152,7 @@ describe('when on the hosts page', () => {
it('should display rows in the table', async () => {
const renderResult = render();
await reactTestingLibrary.act(async () => {
await middlewareSpy.waitForAction('serverReturnedHostList');
await middlewareSpy.waitForAction('serverReturnedEndpointList');
});
const rows = await renderResult.findAllByRole('row');
expect(rows).toHaveLength(5);
@ -160,15 +160,15 @@ describe('when on the hosts page', () => {
it('should show total', async () => {
const renderResult = render();
await reactTestingLibrary.act(async () => {
await middlewareSpy.waitForAction('serverReturnedHostList');
await middlewareSpy.waitForAction('serverReturnedEndpointList');
});
const total = await renderResult.findByTestId('hostListTableTotal');
const total = await renderResult.findByTestId('endpointListTableTotal');
expect(total.textContent).toEqual('4 Hosts');
});
it('should display correct status', async () => {
const renderResult = render();
await reactTestingLibrary.act(async () => {
await middlewareSpy.waitForAction('serverReturnedHostList');
await middlewareSpy.waitForAction('serverReturnedEndpointList');
});
const hostStatuses = await renderResult.findAllByTestId('rowHostStatus');
@ -194,7 +194,7 @@ describe('when on the hosts page', () => {
it('should display correct policy status', async () => {
const renderResult = render();
await reactTestingLibrary.act(async () => {
await middlewareSpy.waitForAction('serverReturnedHostList');
await middlewareSpy.waitForAction('serverReturnedEndpointList');
});
const policyStatuses = await renderResult.findAllByTestId('rowPolicyStatus');
@ -213,7 +213,7 @@ describe('when on the hosts page', () => {
it('should display policy name as a link', async () => {
const renderResult = render();
await reactTestingLibrary.act(async () => {
await middlewareSpy.waitForAction('serverReturnedHostList');
await middlewareSpy.waitForAction('serverReturnedEndpointList');
});
const firstPolicyName = (await renderResult.findAllByTestId('policyNameCellLink'))[0];
expect(firstPolicyName).not.toBeNull();
@ -225,7 +225,7 @@ describe('when on the hosts page', () => {
beforeEach(async () => {
renderResult = render();
await reactTestingLibrary.act(async () => {
await middlewareSpy.waitForAction('serverReturnedHostList');
await middlewareSpy.waitForAction('serverReturnedEndpointList');
});
const hostNameLinks = await renderResult.findAllByTestId('hostnameCellLink');
if (hostNameLinks.length) {
@ -234,7 +234,7 @@ describe('when on the hosts page', () => {
});
it('should show the flyout', () => {
return renderResult.findByTestId('hostDetailsFlyout').then((flyout) => {
return renderResult.findByTestId('endpointDetailsFlyout').then((flyout) => {
expect(flyout).not.toBeNull();
});
});
@ -298,12 +298,12 @@ describe('when on the hosts page', () => {
return policyResponse;
};
const dispatchServerReturnedHostPolicyResponse = (
const dispatchServerReturnedEndpointPolicyResponse = (
overallStatus: HostPolicyResponseActionStatus = HostPolicyResponseActionStatus.success
) => {
reactTestingLibrary.act(() => {
store.dispatch({
type: 'serverReturnedHostPolicyResponse',
type: 'serverReturnedEndpointPolicyResponse',
payload: {
policy_response: createPolicyResponse(overallStatus),
},
@ -316,7 +316,7 @@ describe('when on the hosts page', () => {
// eslint-disable-next-line @typescript-eslint/naming-convention
host_status,
metadata: { host, ...details },
} = mockHostDetailsApiResult();
} = mockEndpointDetailsApiResult();
hostDetails = {
host_status,
@ -334,18 +334,18 @@ describe('when on the hosts page', () => {
const policy = docGenerator.generatePolicyPackageConfig();
policy.id = hostDetails.metadata.Endpoint.policy.applied.id;
setHostListApiMockImplementation(coreStart.http, {
hostsResults: [hostDetails],
setEndpointListApiMockImplementation(coreStart.http, {
endpointsResults: [hostDetails],
endpointPackageConfigs: [policy],
});
reactTestingLibrary.act(() => {
history.push('/hosts?selected_host=1');
history.push('/endpoints?selected_endpoint=1');
});
renderAndWaitForData = async () => {
const renderResult = render();
await middlewareSpy.waitForAction('serverReturnedHostDetails');
await middlewareSpy.waitForAction('serverReturnedEndpointDetails');
return renderResult;
};
});
@ -355,7 +355,7 @@ describe('when on the hosts page', () => {
it('should show the flyout', async () => {
const renderResult = await renderAndWaitForData();
return renderResult.findByTestId('hostDetailsFlyout').then((flyout) => {
return renderResult.findByTestId('endpointDetailsFlyout').then((flyout) => {
expect(flyout).not.toBeNull();
});
});
@ -387,7 +387,7 @@ describe('when on the hosts page', () => {
const policyStatusLink = await renderResult.findByTestId('policyStatusValue');
expect(policyStatusLink).not.toBeNull();
expect(policyStatusLink.getAttribute('href')).toEqual(
'/hosts?page_index=0&page_size=10&selected_host=1&show=policy_response'
'/endpoints?page_index=0&page_size=10&selected_endpoint=1&show=policy_response'
);
});
@ -400,14 +400,14 @@ describe('when on the hosts page', () => {
});
const changedUrlAction = await userChangedUrlChecker;
expect(changedUrlAction.payload.search).toEqual(
'?page_index=0&page_size=10&selected_host=1&show=policy_response'
'?page_index=0&page_size=10&selected_endpoint=1&show=policy_response'
);
});
it('should display Success overall policy status', async () => {
const renderResult = await renderAndWaitForData();
reactTestingLibrary.act(() => {
dispatchServerReturnedHostPolicyResponse(HostPolicyResponseActionStatus.success);
dispatchServerReturnedEndpointPolicyResponse(HostPolicyResponseActionStatus.success);
});
const policyStatusLink = await renderResult.findByTestId('policyStatusValue');
expect(policyStatusLink.textContent).toEqual('Success');
@ -421,7 +421,7 @@ describe('when on the hosts page', () => {
it('should display Warning overall policy status', async () => {
const renderResult = await renderAndWaitForData();
reactTestingLibrary.act(() => {
dispatchServerReturnedHostPolicyResponse(HostPolicyResponseActionStatus.warning);
dispatchServerReturnedEndpointPolicyResponse(HostPolicyResponseActionStatus.warning);
});
const policyStatusLink = await renderResult.findByTestId('policyStatusValue');
expect(policyStatusLink.textContent).toEqual('Warning');
@ -435,7 +435,7 @@ describe('when on the hosts page', () => {
it('should display Failed overall policy status', async () => {
const renderResult = await renderAndWaitForData();
reactTestingLibrary.act(() => {
dispatchServerReturnedHostPolicyResponse(HostPolicyResponseActionStatus.failure);
dispatchServerReturnedEndpointPolicyResponse(HostPolicyResponseActionStatus.failure);
});
const policyStatusLink = await renderResult.findByTestId('policyStatusValue');
expect(policyStatusLink.textContent).toEqual('Failed');
@ -449,7 +449,7 @@ describe('when on the hosts page', () => {
it('should display Unknown overall policy status', async () => {
const renderResult = await renderAndWaitForData();
reactTestingLibrary.act(() => {
dispatchServerReturnedHostPolicyResponse('' as HostPolicyResponseActionStatus);
dispatchServerReturnedEndpointPolicyResponse('' as HostPolicyResponseActionStatus);
});
const policyStatusLink = await renderResult.findByTestId('policyStatusValue');
expect(policyStatusLink.textContent).toEqual('Unknown');
@ -463,7 +463,7 @@ describe('when on the hosts page', () => {
it('should include the link to reassignment in Ingest', async () => {
coreStart.application.getUrlForApp.mockReturnValue('/app/ingestManager');
const renderResult = await renderAndWaitForData();
const linkToReassign = await renderResult.findByTestId('hostDetailsLinkToIngest');
const linkToReassign = await renderResult.findByTestId('endpointDetailsLinkToIngest');
expect(linkToReassign).not.toBeNull();
expect(linkToReassign.textContent).toEqual('Reassign Configuration');
expect(linkToReassign.getAttribute('href')).toEqual(
@ -475,7 +475,7 @@ describe('when on the hosts page', () => {
beforeEach(async () => {
coreStart.application.getUrlForApp.mockReturnValue('/app/ingestManager');
const renderResult = await renderAndWaitForData();
const linkToReassign = await renderResult.findByTestId('hostDetailsLinkToIngest');
const linkToReassign = await renderResult.findByTestId('endpointDetailsLinkToIngest');
reactTestingLibrary.act(() => {
reactTestingLibrary.fireEvent.click(linkToReassign);
});
@ -491,7 +491,7 @@ describe('when on the hosts page', () => {
beforeEach(async () => {
coreStart.http.post.mockImplementation(async (requestOptions) => {
if (requestOptions.path === '/api/endpoint/metadata') {
return mockHostResultList({ total: 0 });
return mockEndpointResultList({ total: 0 });
}
throw new Error(`POST to '${requestOptions.path}' does not have a mock response!`);
});
@ -502,44 +502,44 @@ describe('when on the hosts page', () => {
reactTestingLibrary.fireEvent.click(policyStatusLink);
});
await userChangedUrlChecker;
await middlewareSpy.waitForAction('serverReturnedHostPolicyResponse');
await middlewareSpy.waitForAction('serverReturnedEndpointPolicyResponse');
reactTestingLibrary.act(() => {
dispatchServerReturnedHostPolicyResponse();
dispatchServerReturnedEndpointPolicyResponse();
});
});
afterEach(reactTestingLibrary.cleanup);
it('should hide the host details panel', async () => {
const hostDetailsFlyout = await renderResult.queryByTestId('hostDetailsFlyoutBody');
expect(hostDetailsFlyout).toBeNull();
const endpointDetailsFlyout = await renderResult.queryByTestId('endpointDetailsFlyoutBody');
expect(endpointDetailsFlyout).toBeNull();
});
it('should display policy response sub-panel', async () => {
expect(
await renderResult.findByTestId('hostDetailsPolicyResponseFlyoutHeader')
await renderResult.findByTestId('endpointDetailsPolicyResponseFlyoutHeader')
).not.toBeNull();
expect(
await renderResult.findByTestId('hostDetailsPolicyResponseFlyoutBody')
await renderResult.findByTestId('endpointDetailsPolicyResponseFlyoutBody')
).not.toBeNull();
});
it('should include the sub-panel title', async () => {
expect(
(await renderResult.findByTestId('hostDetailsPolicyResponseFlyoutTitle')).textContent
(await renderResult.findByTestId('endpointDetailsPolicyResponseFlyoutTitle')).textContent
).toBe('Configuration Response');
});
it('should show a configuration section for each protection', async () => {
const configAccordions = await renderResult.findAllByTestId(
'hostDetailsPolicyResponseConfigAccordion'
'endpointDetailsPolicyResponseConfigAccordion'
);
expect(configAccordions).not.toBeNull();
});
it('should show an actions section for each configuration', async () => {
const actionAccordions = await renderResult.findAllByTestId(
'hostDetailsPolicyResponseActionsAccordion'
'endpointDetailsPolicyResponseActionsAccordion'
);
const action = await renderResult.findAllByTestId('policyResponseAction');
const statusHealth = await renderResult.findAllByTestId('policyResponseStatusHealth');
@ -557,14 +557,14 @@ describe('when on the hosts page', () => {
);
reactTestingLibrary.act(() => {
store.dispatch({
type: 'serverReturnedHostPolicyResponse',
type: 'serverReturnedEndpointPolicyResponse',
payload: {
policy_response: policyResponse,
},
});
});
return renderResult
.findAllByTestId('hostDetailsPolicyResponseAttentionBadge')
.findAllByTestId('endpointDetailsPolicyResponseAttentionBadge')
.catch((e) => {
expect(e).not.toBeNull();
});
@ -572,28 +572,28 @@ describe('when on the hosts page', () => {
it('should show a numbered badge if at least one action failed', async () => {
const policyResponseActionDispatched = middlewareSpy.waitForAction(
'serverReturnedHostPolicyResponse'
'serverReturnedEndpointPolicyResponse'
);
reactTestingLibrary.act(() => {
dispatchServerReturnedHostPolicyResponse(HostPolicyResponseActionStatus.failure);
dispatchServerReturnedEndpointPolicyResponse(HostPolicyResponseActionStatus.failure);
});
await policyResponseActionDispatched;
const attentionBadge = await renderResult.findAllByTestId(
'hostDetailsPolicyResponseAttentionBadge'
'endpointDetailsPolicyResponseAttentionBadge'
);
expect(attentionBadge).not.toBeNull();
});
it('should show a numbered badge if at least one action has a warning', async () => {
const policyResponseActionDispatched = middlewareSpy.waitForAction(
'serverReturnedHostPolicyResponse'
'serverReturnedEndpointPolicyResponse'
);
reactTestingLibrary.act(() => {
dispatchServerReturnedHostPolicyResponse(HostPolicyResponseActionStatus.warning);
dispatchServerReturnedEndpointPolicyResponse(HostPolicyResponseActionStatus.warning);
});
await policyResponseActionDispatched;
const attentionBadge = await renderResult.findAllByTestId(
'hostDetailsPolicyResponseAttentionBadge'
'endpointDetailsPolicyResponseAttentionBadge'
);
expect(attentionBadge).not.toBeNull();
});
@ -602,7 +602,7 @@ describe('when on the hosts page', () => {
const subHeaderBackLink = await renderResult.findByTestId('flyoutSubHeaderBackButton');
expect(subHeaderBackLink.textContent).toBe('Endpoint Details');
expect(subHeaderBackLink.getAttribute('href')).toBe(
'/hosts?page_index=0&page_size=10&selected_host=1'
'/endpoints?page_index=0&page_size=10&selected_endpoint=1'
);
});
@ -614,7 +614,7 @@ describe('when on the hosts page', () => {
});
const changedUrlAction = await userChangedUrlChecker;
expect(changedUrlAction.payload.search).toEqual(
'?page_index=0&page_size=10&selected_host=1'
'?page_index=0&page_size=10&selected_endpoint=1'
);
});

View file

@ -25,9 +25,9 @@ import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { createStructuredSelector } from 'reselect';
import { useDispatch } from 'react-redux';
import { HostDetailsFlyout } from './details';
import { EndpointDetailsFlyout } from './details';
import * as selectors from '../store/selectors';
import { useHostSelector } from './hooks';
import { useEndpointSelector } from './hooks';
import {
HOST_STATUS_TO_HEALTH_COLOR,
POLICY_STATUS_TO_HEALTH_COLOR,
@ -46,12 +46,12 @@ import {
AgentConfigDetailsDeployAgentAction,
} from '../../../../../../ingest_manager/public';
import { SecurityPageName } from '../../../../app/types';
import { getHostListPath, getHostDetailsPath } from '../../../common/routing';
import { getEndpointListPath, getEndpointDetailsPath } from '../../../common/routing';
import { useFormatUrl } from '../../../../common/components/link_to';
import { HostAction } from '../store/action';
import { HostPolicyLink } from './components/host_policy_link';
import { EndpointAction } from '../store/action';
import { EndpointPolicyLink } from './components/endpoint_policy_link';
const HostListNavLink = memo<{
const EndpointListNavLink = memo<{
name: string;
href: string;
route: string;
@ -71,10 +71,10 @@ const HostListNavLink = memo<{
</EuiLink>
);
});
HostListNavLink.displayName = 'HostListNavLink';
EndpointListNavLink.displayName = 'EndpointListNavLink';
const selector = (createStructuredSelector as CreateStructuredSelector)(selectors);
export const HostList = () => {
export const EndpointList = () => {
const history = useHistory();
const {
listData,
@ -84,16 +84,16 @@ export const HostList = () => {
listLoading: loading,
listError,
uiQueryParams: queryParams,
hasSelectedHost,
hasSelectedEndpoint,
policyItems,
selectedPolicyId,
policyItemsLoading,
endpointPackageVersion,
hostsExist,
} = useHostSelector(selector);
endpointsExist,
} = useEndpointSelector(selector);
const { formatUrl, search } = useFormatUrl(SecurityPageName.administration);
const dispatch = useDispatch<(a: HostAction) => void>();
const dispatch = useDispatch<(a: EndpointAction) => void>();
const paginationSetup = useMemo(() => {
return {
@ -108,10 +108,10 @@ export const HostList = () => {
const onTableChange = useCallback(
({ page }: { page: { index: number; size: number } }) => {
const { index, size } = page;
// FIXME: PT: if host details is open, table is not displaying correct number of rows
// FIXME: PT: if endpoint details is open, table is not displaying correct number of rows
history.push(
getHostListPath({
name: 'hostList',
getEndpointListPath({
name: 'endpointList',
...queryParams,
page_index: JSON.stringify(index),
page_size: JSON.stringify(size),
@ -130,12 +130,12 @@ export const HostList = () => {
state: {
onCancelNavigateTo: [
'securitySolution:administration',
{ path: getHostListPath({ name: 'hostList' }) },
{ path: getEndpointListPath({ name: 'endpointList' }) },
],
onCancelUrl: formatUrl(getHostListPath({ name: 'hostList' })),
onCancelUrl: formatUrl(getEndpointListPath({ name: 'endpointList' })),
onSaveNavigateTo: [
'securitySolution:administration',
{ path: getHostListPath({ name: 'hostList' }) },
{ path: getEndpointListPath({ name: 'endpointList' }) },
],
},
}
@ -148,7 +148,7 @@ export const HostList = () => {
state: {
onDoneNavigateTo: [
'securitySolution:administration',
{ path: getHostListPath({ name: 'hostList' }) },
{ path: getEndpointListPath({ name: 'endpointList' }) },
],
},
});
@ -183,28 +183,28 @@ export const HostList = () => {
);
const columns: Array<EuiBasicTableColumn<Immutable<HostInfo>>> = useMemo(() => {
const lastActiveColumnName = i18n.translate('xpack.securitySolution.endpointList.lastActive', {
const lastActiveColumnName = i18n.translate('xpack.securitySolution.endpoint.list.lastActive', {
defaultMessage: 'Last Active',
});
return [
{
field: 'metadata.host',
name: i18n.translate('xpack.securitySolution.endpointList.hostname', {
name: i18n.translate('xpack.securitySolution.endpoint.list.hostname', {
defaultMessage: 'Hostname',
}),
render: ({ hostname, id }: HostInfo['metadata']['host']) => {
const toRoutePath = getHostDetailsPath(
const toRoutePath = getEndpointDetailsPath(
{
...queryParams,
name: 'hostDetails',
selected_host: id,
name: 'endpointDetails',
selected_endpoint: id,
},
search
);
const toRouteUrl = formatUrl(toRoutePath);
return (
<HostListNavLink
<EndpointListNavLink
name={hostname}
href={toRouteUrl}
route={toRoutePath}
@ -215,8 +215,8 @@ export const HostList = () => {
},
{
field: 'host_status',
name: i18n.translate('xpack.securitySolution.endpointList.hostStatus', {
defaultMessage: 'Host Status',
name: i18n.translate('xpack.securitySolution.endpoint.list.hostStatus', {
defaultMessage: 'Agent Status',
}),
// eslint-disable-next-line react/display-name
render: (hostStatus: HostInfo['host_status']) => {
@ -227,7 +227,7 @@ export const HostList = () => {
className="eui-textTruncate"
>
<FormattedMessage
id="xpack.securitySolution.endpointList.hostStatusValue"
id="xpack.securitySolution.endpoint.list.hostStatusValue"
defaultMessage="{hostStatus, select, online {Online} error {Error} unenrolling {Unenrolling} other {Offline}}"
values={{ hostStatus }}
/>
@ -237,33 +237,33 @@ export const HostList = () => {
},
{
field: 'metadata.Endpoint.policy.applied',
name: i18n.translate('xpack.securitySolution.endpointList.policy', {
name: i18n.translate('xpack.securitySolution.endpoint.list.policy', {
defaultMessage: 'Integration',
}),
truncateText: true,
// eslint-disable-next-line react/display-name
render: (policy: HostInfo['metadata']['Endpoint']['policy']['applied']) => {
return (
<HostPolicyLink
<EndpointPolicyLink
policyId={policy.id}
className="eui-textTruncate"
data-test-subj="policyNameCellLink"
>
{policy.name}
</HostPolicyLink>
</EndpointPolicyLink>
);
},
},
{
field: 'metadata.Endpoint.policy.applied',
name: i18n.translate('xpack.securitySolution.endpointList.policyStatus', {
name: i18n.translate('xpack.securitySolution.endpoint.list.policyStatus', {
defaultMessage: 'Configuration Status',
}),
render: (policy: HostInfo['metadata']['Endpoint']['policy']['applied'], item: HostInfo) => {
const toRoutePath = getHostDetailsPath({
name: 'hostPolicyResponse',
const toRoutePath = getEndpointDetailsPath({
name: 'endpointPolicyResponse',
...queryParams,
selected_host: item.metadata.host.id,
selected_endpoint: item.metadata.host.id,
});
const toRouteUrl = formatUrl(toRoutePath);
return (
@ -272,7 +272,7 @@ export const HostList = () => {
className="eui-textTruncate"
data-test-subj="rowPolicyStatus"
>
<HostListNavLink
<EndpointListNavLink
name={POLICY_STATUS_TO_TEXT[policy.status]}
href={toRouteUrl}
route={toRoutePath}
@ -284,14 +284,14 @@ export const HostList = () => {
},
{
field: 'metadata.host.os.name',
name: i18n.translate('xpack.securitySolution.endpointList.os', {
name: i18n.translate('xpack.securitySolution.endpoint.list.os', {
defaultMessage: 'Operating System',
}),
truncateText: true,
},
{
field: 'metadata.host.ip',
name: i18n.translate('xpack.securitySolution.endpointList.ip', {
name: i18n.translate('xpack.securitySolution.endpoint.list.ip', {
defaultMessage: 'IP Address',
}),
// eslint-disable-next-line react/display-name
@ -309,7 +309,7 @@ export const HostList = () => {
},
{
field: 'metadata.agent.version',
name: i18n.translate('xpack.securitySolution.endpointList.endpointVersion', {
name: i18n.translate('xpack.securitySolution.endpoint.list.endpointVersion', {
defaultMessage: 'Version',
}),
},
@ -330,10 +330,10 @@ export const HostList = () => {
}, [formatUrl, queryParams, search]);
const renderTableOrEmptyState = useMemo(() => {
if (hostsExist) {
if (endpointsExist) {
return (
<EuiBasicTable
data-test-subj="hostListTable"
data-test-subj="endpointListTable"
items={[...listData]}
columns={columns}
error={listError?.message}
@ -359,7 +359,7 @@ export const HostList = () => {
}
}, [
loading,
hostsExist,
endpointsExist,
policyItemsLoading,
policyItems,
listData,
@ -377,7 +377,7 @@ export const HostList = () => {
return (
<ManagementPageView
viewType="list"
data-test-subj="hostPage"
data-test-subj="endpointPage"
headerLeft={
<>
<EuiFlexGroup alignItems="center" responsive={false}>
@ -385,15 +385,15 @@ export const HostList = () => {
<EuiTitle size="l">
<h1 data-test-subj="pageViewHeaderLeftTitle">
<FormattedMessage
id="xpack.securitySolution.hostList.pageTitle"
defaultMessage="Hosts"
id="xpack.securitySolution.endpoint.list.pageTitle"
defaultMessage="Endpoints"
/>
</h1>
</EuiTitle>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiBetaBadge
label={i18n.translate('xpack.securitySolution.endpoint.hostList.beta', {
label={i18n.translate('xpack.securitySolution.endpoint.list.beta', {
defaultMessage: 'Beta',
})}
/>
@ -403,7 +403,7 @@ export const HostList = () => {
<EuiText size="s" color="subdued">
<p>
<FormattedMessage
id="xpack.securitySolution.hostList.pageSubTitle"
id="xpack.securitySolution.endpoint.list.pageSubTitle"
defaultMessage="Hosts running Elastic Endpoint Security"
/>
</p>
@ -411,12 +411,12 @@ export const HostList = () => {
</>
}
>
{hasSelectedHost && <HostDetailsFlyout />}
{hasSelectedEndpoint && <EndpointDetailsFlyout />}
{listData && listData.length > 0 && (
<>
<EuiText color="subdued" size="xs" data-test-subj="hostListTableTotal">
<EuiText color="subdued" size="xs" data-test-subj="endpointListTableTotal">
<FormattedMessage
id="xpack.securitySolution.endpointList.totalCount"
id="xpack.securitySolution.endpoint.list.totalCount"
defaultMessage="{totalItemCount, plural, one {# Host} other {# Hosts}}"
values={{ totalItemCount }}
/>

View file

@ -7,10 +7,10 @@
// eslint-disable-next-line import/no-nodejs-modules
import querystring from 'querystring';
import { HostIndexUIQueryParams } from '../types';
import { EndpointIndexUIQueryParams } from '../types';
import { AppLocation } from '../../../../../common/endpoint/types';
export function urlFromQueryParams(queryParams: HostIndexUIQueryParams): Partial<AppLocation> {
export function urlFromQueryParams(queryParams: EndpointIndexUIQueryParams): Partial<AppLocation> {
const search = querystring.stringify(queryParams);
return {
search,

View file

@ -30,7 +30,7 @@ describe('when in the Admistration tab', () => {
it('should display the Management view when Ingest is ON', async () => {
(useIngestEnabledCheck as jest.Mock).mockReturnValue({ allEnabled: true });
const renderResult = render();
const hostPage = await renderResult.findByTestId('hostPage');
expect(hostPage).not.toBeNull();
const endpointPage = await renderResult.findByTestId('endpointPage');
expect(endpointPage).not.toBeNull();
});
});

View file

@ -13,24 +13,24 @@ import { EuiText, EuiEmptyPrompt } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { PolicyContainer } from './policy';
import {
MANAGEMENT_ROUTING_HOSTS_PATH,
MANAGEMENT_ROUTING_ENDPOINTS_PATH,
MANAGEMENT_ROUTING_POLICIES_PATH,
MANAGEMENT_ROUTING_ROOT_PATH,
} from '../common/constants';
import { NotFoundPage } from '../../app/404';
import { HostsContainer } from './endpoint_hosts';
import { getHostListPath } from '../common/routing';
import { EndpointsContainer } from './endpoint_hosts';
import { getEndpointListPath } from '../common/routing';
import { APP_ID, SecurityPageName } from '../../../common/constants';
import { GetUrlForApp } from '../../common/components/navigation/types';
import { AdministrationRouteSpyState } from '../../common/utils/route/types';
import { ADMINISTRATION } from '../../app/home/translations';
import { AdministrationSubTab } from '../types';
import { HOSTS_TAB, POLICIES_TAB } from '../common/translations';
import { ENDPOINTS_TAB, POLICIES_TAB } from '../common/translations';
import { SpyRoute } from '../../common/utils/route/spy_routes';
import { useIngestEnabledCheck } from '../../common/hooks/endpoint/ingest_enabled';
const TabNameMappedToI18nKey: Record<string, string> = {
[AdministrationSubTab.hosts]: HOSTS_TAB,
[AdministrationSubTab.endpoints]: ENDPOINTS_TAB,
[AdministrationSubTab.policies]: POLICIES_TAB,
};
@ -102,13 +102,13 @@ export const ManagementContainer = memo(() => {
return (
<Switch>
<Route path={MANAGEMENT_ROUTING_HOSTS_PATH} component={HostsContainer} />
<Route path={MANAGEMENT_ROUTING_ENDPOINTS_PATH} component={EndpointsContainer} />
<Route path={MANAGEMENT_ROUTING_POLICIES_PATH} component={PolicyContainer} />
<Route
path={MANAGEMENT_ROUTING_ROOT_PATH}
exact
render={() => {
history.replace(getHostListPath({ name: 'hostList' }));
history.replace(getEndpointListPath({ name: 'endpointList' }));
return null;
}}
/>

View file

@ -34,7 +34,7 @@ export const AgentsSummary = memo<AgentsSummaryProps>((props) => {
title: i18n.translate(
'xpack.securitySolution.endpoint.policyDetails.agentsSummary.totalTitle',
{
defaultMessage: 'Hosts',
defaultMessage: 'Endpoints',
}
),
health: '',

View file

@ -10,7 +10,7 @@ import { mount } from 'enzyme';
import { PolicyDetails } from './policy_details';
import { EndpointDocGenerator } from '../../../../../common/endpoint/generate_data';
import { AppContextTestRender, createAppRootMockRenderer } from '../../../../common/mock/endpoint';
import { getPolicyDetailPath, getHostListPath } from '../../../common/routing';
import { getPolicyDetailPath, getEndpointListPath } from '../../../common/routing';
import { policyListApiPathHandlers } from '../store/policy_list/test_mock_utils';
jest.mock('../../../../common/components/link_to');
@ -19,7 +19,7 @@ describe('Policy Details', () => {
type FindReactWrapperResponse = ReturnType<ReturnType<typeof render>['find']>;
const policyDetailsPathUrl = getPolicyDetailPath('1');
const hostListPath = getHostListPath({ name: 'hostList' });
const endpointListPath = getEndpointListPath({ name: 'endpointList' });
const sleep = (ms = 100) => new Promise((wakeup) => setTimeout(wakeup, ms));
const generator = new EndpointDocGenerator();
let history: AppContextTestRender['history'];
@ -129,7 +129,7 @@ describe('Policy Details', () => {
const backToListButton = pageHeaderLeft.find('EuiButtonEmpty');
expect(backToListButton.prop('iconType')).toBe('arrowLeft');
expect(backToListButton.prop('href')).toBe(hostListPath);
expect(backToListButton.prop('href')).toBe(endpointListPath);
expect(backToListButton.text()).toBe('Back to endpoint hosts');
const pageTitle = pageHeaderLeft.find('[data-test-subj="pageViewHeaderLeftTitle"]');
@ -143,7 +143,7 @@ describe('Policy Details', () => {
);
expect(history.location.pathname).toEqual(policyDetailsPathUrl);
backToListButton.simulate('click', { button: 0 });
expect(history.location.pathname).toEqual(hostListPath);
expect(history.location.pathname).toEqual(endpointListPath);
});
it('should display agent stats', async () => {
await asyncActions;
@ -153,7 +153,7 @@ describe('Policy Details', () => {
);
const agentsSummary = headerRight.find('EuiFlexGroup[data-test-subj="policyAgentsSummary"]');
expect(agentsSummary).toHaveLength(1);
expect(agentsSummary.text()).toBe('Hosts5Online3Offline1Error1');
expect(agentsSummary.text()).toBe('Endpoints5Online3Offline1Error1');
});
it('should display cancel button', async () => {
await asyncActions;
@ -175,7 +175,7 @@ describe('Policy Details', () => {
const navigateToAppMockedCalls = coreStart.application.navigateToApp.mock.calls;
expect(navigateToAppMockedCalls[navigateToAppMockedCalls.length - 1]).toEqual([
'securitySolution:administration',
{ path: hostListPath },
{ path: endpointListPath },
]);
});
it('should display save button', async () => {

View file

@ -43,7 +43,7 @@ import { PageViewHeaderTitle } from '../../../../common/components/endpoint/page
import { ManagementPageView } from '../../../components/management_page_view';
import { SpyRoute } from '../../../../common/utils/route/spy_routes';
import { SecurityPageName } from '../../../../app/types';
import { getHostListPath } from '../../../common/routing';
import { getEndpointListPath } from '../../../common/routing';
import { useFormatUrl } from '../../../../common/components/link_to';
import { useNavigateToAppEventHandler } from '../../../../common/hooks/endpoint/use_navigate_to_app_event_handler';
import { MANAGEMENT_APP_ID } from '../../../common/constants';
@ -71,7 +71,7 @@ export const PolicyDetails = React.memo(() => {
const [showConfirm, setShowConfirm] = useState<boolean>(false);
const [routeState, setRouteState] = useState<PolicyDetailsRouteState>();
const policyName = policyItem?.name ?? '';
const hostListRouterPath = getHostListPath({ name: 'hostList' });
const hostListRouterPath = getEndpointListPath({ name: 'endpointList' });
// Handle showing update statuses
useEffect(() => {

View file

@ -12,19 +12,19 @@ import {
import { policyListMiddlewareFactory } from '../pages/policy/store/policy_list';
import { policyDetailsMiddlewareFactory } from '../pages/policy/store/policy_details';
import {
MANAGEMENT_STORE_HOSTS_NAMESPACE,
MANAGEMENT_STORE_ENDPOINTS_NAMESPACE,
MANAGEMENT_STORE_GLOBAL_NAMESPACE,
MANAGEMENT_STORE_POLICY_DETAILS_NAMESPACE,
MANAGEMENT_STORE_POLICY_LIST_NAMESPACE,
} from '../common/constants';
import { hostMiddlewareFactory } from '../pages/endpoint_hosts/store/middleware';
import { endpointMiddlewareFactory } from '../pages/endpoint_hosts/store/middleware';
const policyListSelector = (state: State) =>
state[MANAGEMENT_STORE_GLOBAL_NAMESPACE][MANAGEMENT_STORE_POLICY_LIST_NAMESPACE];
const policyDetailsSelector = (state: State) =>
state[MANAGEMENT_STORE_GLOBAL_NAMESPACE][MANAGEMENT_STORE_POLICY_DETAILS_NAMESPACE];
const endpointsSelector = (state: State) =>
state[MANAGEMENT_STORE_GLOBAL_NAMESPACE][MANAGEMENT_STORE_HOSTS_NAMESPACE];
state[MANAGEMENT_STORE_GLOBAL_NAMESPACE][MANAGEMENT_STORE_ENDPOINTS_NAMESPACE];
export const managementMiddlewareFactory: SecuritySubPluginMiddlewareFactory = (
coreStart,
@ -39,6 +39,6 @@ export const managementMiddlewareFactory: SecuritySubPluginMiddlewareFactory = (
policyDetailsSelector,
policyDetailsMiddlewareFactory(coreStart, depsStart)
),
substateMiddlewareFactory(endpointsSelector, hostMiddlewareFactory(coreStart, depsStart)),
substateMiddlewareFactory(endpointsSelector, endpointMiddlewareFactory(coreStart, depsStart)),
];
};

View file

@ -14,14 +14,17 @@ import {
initialPolicyListState,
} from '../pages/policy/store/policy_list/reducer';
import {
MANAGEMENT_STORE_HOSTS_NAMESPACE,
MANAGEMENT_STORE_ENDPOINTS_NAMESPACE,
MANAGEMENT_STORE_POLICY_DETAILS_NAMESPACE,
MANAGEMENT_STORE_POLICY_LIST_NAMESPACE,
} from '../common/constants';
import { ImmutableCombineReducers } from '../../common/store';
import { Immutable } from '../../../common/endpoint/types';
import { ManagementState } from '../types';
import { hostListReducer, initialHostListState } from '../pages/endpoint_hosts/store/reducer';
import {
endpointListReducer,
initialEndpointListState,
} from '../pages/endpoint_hosts/store/reducer';
const immutableCombineReducers: ImmutableCombineReducers = combineReducers;
@ -31,7 +34,7 @@ const immutableCombineReducers: ImmutableCombineReducers = combineReducers;
export const mockManagementState: Immutable<ManagementState> = {
[MANAGEMENT_STORE_POLICY_LIST_NAMESPACE]: initialPolicyListState(),
[MANAGEMENT_STORE_POLICY_DETAILS_NAMESPACE]: initialPolicyDetailsState(),
[MANAGEMENT_STORE_HOSTS_NAMESPACE]: initialHostListState,
[MANAGEMENT_STORE_ENDPOINTS_NAMESPACE]: initialEndpointListState,
};
/**
@ -40,5 +43,5 @@ export const mockManagementState: Immutable<ManagementState> = {
export const managementReducer = immutableCombineReducers({
[MANAGEMENT_STORE_POLICY_LIST_NAMESPACE]: policyListReducer,
[MANAGEMENT_STORE_POLICY_DETAILS_NAMESPACE]: policyDetailsReducer,
[MANAGEMENT_STORE_HOSTS_NAMESPACE]: hostListReducer,
[MANAGEMENT_STORE_ENDPOINTS_NAMESPACE]: endpointListReducer,
});

View file

@ -7,7 +7,7 @@
import { CombinedState } from 'redux';
import { SecurityPageName } from '../app/types';
import { PolicyListState, PolicyDetailsState } from './pages/policy/types';
import { HostState } from './pages/endpoint_hosts/types';
import { EndpointState } from './pages/endpoint_hosts/types';
/**
* The type for the management store global namespace. Used mostly internally to reference
@ -18,14 +18,14 @@ export type ManagementStoreGlobalNamespace = 'management';
export type ManagementState = CombinedState<{
policyList: PolicyListState;
policyDetails: PolicyDetailsState;
hosts: HostState;
endpoints: EndpointState;
}>;
/**
* The management list of sub-tabs. Changes to these will impact the Router routes.
*/
export enum AdministrationSubTab {
hosts = 'hosts',
endpoints = 'endpoints',
policies = 'policy',
}

View file

@ -7,13 +7,13 @@
import React, { memo } from 'react';
import { EuiCallOut, EuiButton, EuiButtonEmpty } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { getHostListPath } from '../../../management/common/routing';
import { getEndpointListPath } from '../../../management/common/routing';
import { useNavigateToAppEventHandler } from '../../../common/hooks/endpoint/use_navigate_to_app_event_handler';
import { useManagementFormatUrl } from '../../../management/components/hooks/use_management_format_url';
import { MANAGEMENT_APP_ID } from '../../../management/common/constants';
export const EndpointNotice = memo<{ onDismiss: () => void }>(({ onDismiss }) => {
const endpointsPath = getHostListPath({ name: 'hostList' });
const endpointsPath = getEndpointListPath({ name: 'endpointList' });
const endpointsLink = useManagementFormatUrl(endpointsPath);
const handleGetStartedClick = useNavigateToAppEventHandler(MANAGEMENT_APP_ID, {
path: endpointsPath,

View file

@ -16233,65 +16233,65 @@
"xpack.securitySolution.editDataProvider.valuePlaceholder": "値",
"xpack.securitySolution.emptyMessage": "Elastic セキュリティは無料かつオープンのElastic SIEMに、Elastic Endpointを搭載。脅威の防御と検知、脅威への対応を支援します。開始するには、セキュリティソリューション関連データをElastic Stackに追加する必要があります。詳細については、ご覧ください ",
"xpack.securitySolution.emptyString.emptyStringDescription": "空の文字列",
"xpack.securitySolution.endpoint.host.details.endpointVersion": "エンドポイントバージョン",
"xpack.securitySolution.endpoint.host.details.errorBody": "フライアウトを終了して、利用可能なホストを選択してください。",
"xpack.securitySolution.endpoint.host.details.errorTitle": "ホストが見つかりませんでした",
"xpack.securitySolution.endpoint.host.details.hostname": "ホスト名",
"xpack.securitySolution.endpoint.host.details.ipAddress": "IP アドレス",
"xpack.securitySolution.endpoint.host.details.lastSeen": "前回の認識",
"xpack.securitySolution.endpoint.host.details.linkToIngestTitle": "ポリシーの再割り当て",
"xpack.securitySolution.endpoint.host.details.os": "OS",
"xpack.securitySolution.endpoint.host.details.policy": "ポリシー",
"xpack.securitySolution.endpoint.host.details.policyStatus": "ポリシーステータス",
"xpack.securitySolution.endpoint.host.details.policyStatusValue": "{policyStatus, select, success {成功} warning {警告} failure {失敗} other {不明}}",
"xpack.securitySolution.endpoint.host.policyResponse.backLinkTitle": "エンドポイント詳細",
"xpack.securitySolution.endpoint.host.policyResponse.title": "ポリシー応答",
"xpack.securitySolution.endpoint.hostDetails.noPolicyResponse": "ポリシー応答がありません",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_dns_events": "DNSイベントの構成",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_elasticsearch_connection": "Elastic Search接続の構成",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_file_events": "ファイルイベントの構成",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_imageload_events": "画像読み込みイベントの構成",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_kernel": "カーネルの構成",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_logging": "ロギングの構成",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_malware": "マルウェアの構成",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_network_events": "ネットワークイベントの構成",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_process_events": "プロセスイベントの構成",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_registry_events": "レジストリイベントの構成",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_security_events": "セキュリティイベントの構成",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.connect_kernel": "カーネルを接続",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.detect_async_image_load_events": "非同期画像読み込みイベントを検出",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.detect_file_open_events": "ファイルオープンイベントを検出",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.detect_file_write_events": "ファイル書き込みイベントを検出",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.detect_network_events": "ネットワークイベントを検出",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.detect_process_events": "プロセスイベントを検出",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.detect_registry_events": "レジストリイベントを検出",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.detect_sync_image_load_events": "同期画像読み込みイベントを検出",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.download_global_artifacts": "グローバルアーチファクトをダウンロード",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.download_user_artifacts": "ユーザーアーチファクトをダウンロード",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.events": "イベント",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.failed": "失敗",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.load_config": "構成の読み込み",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.load_malware_model": "マルウェアモデルの読み込み",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.logging": "ログ",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.malware": "マルウェア",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.read_elasticsearch_config": "Elasticsearch構成を読み取る",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.read_events_config": "イベント構成を読み取る",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.read_kernel_config": "カーネル構成を読み取る",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.read_logging_config": "ロギング構成を読み取る",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.read_malware_config": "マルウェア構成を読み取る",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.streaming": "ストリーム中…",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.success": "成功",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.warning": "警告",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.workflow": "ワークフロー",
"xpack.securitySolution.endpoint.hostList.beta": "ベータ",
"xpack.securitySolution.endpoint.hostList.loadingPolicies": "ポリシー構成を読み込んでいます…",
"xpack.securitySolution.endpoint.hostList.noEndpointsInstructions": "セキュリティポリシーを作成しました。以下のステップに従い、エージェントでElastic Endpoint Security機能を有効にする必要があります。",
"xpack.securitySolution.endpoint.hostList.noEndpointsPrompt": "エージェントでElastic Endpoint Securityを有効にする",
"xpack.securitySolution.endpoint.hostList.noPolicies": "ポリシーがありません。",
"xpack.securitySolution.endpoint.hostList.stepOne": "既存のポリシーは以下のリストのとおりです。これは後から変更できます。",
"xpack.securitySolution.endpoint.hostList.stepOneTitle": "ホストの保護で使用するポリシーを選択",
"xpack.securitySolution.endpoint.hostList.stepTwo": "開始するために必要なコマンドが提供されます。",
"xpack.securitySolution.endpoint.hostList.stepTwoTitle": "Ingest Manager経由でEndpoint Securityによって有効にされたエージェントを登録",
"xpack.securitySolution.endpoint.details.endpointVersion": "エンドポイントバージョン",
"xpack.securitySolution.endpoint.details.errorBody": "フライアウトを終了して、利用可能なホストを選択してください。",
"xpack.securitySolution.endpoint.details.errorTitle": "ホストが見つかりませんでした",
"xpack.securitySolution.endpoint.details.hostname": "ホスト名",
"xpack.securitySolution.endpoint.details.ipAddress": "IP アドレス",
"xpack.securitySolution.endpoint.details.lastSeen": "前回の認識",
"xpack.securitySolution.endpoint.details.linkToIngestTitle": "ポリシーの再割り当て",
"xpack.securitySolution.endpoint.details.os": "OS",
"xpack.securitySolution.endpoint.details.policy": "ポリシー",
"xpack.securitySolution.endpoint.details.policyStatus": "ポリシーステータス",
"xpack.securitySolution.endpoint.details.policyStatusValue": "{policyStatus, select, success {成功} warning {警告} failure {失敗} other {不明}}",
"xpack.securitySolution.endpoint.policyResponse.backLinkTitle": "エンドポイント詳細",
"xpack.securitySolution.endpoint.policyResponse.title": "ポリシー応答",
"xpack.securitySolution.endpoint.details.noPolicyResponse": "ポリシー応答がありません",
"xpack.securitySolution.endpoint.details.policyResponse.configure_dns_events": "DNSイベントの構成",
"xpack.securitySolution.endpoint.details.policyResponse.configure_elasticsearch_connection": "Elastic Search接続の構成",
"xpack.securitySolution.endpoint.details.policyResponse.configure_file_events": "ファイルイベントの構成",
"xpack.securitySolution.endpoint.details.policyResponse.configure_imageload_events": "画像読み込みイベントの構成",
"xpack.securitySolution.endpoint.details.policyResponse.configure_kernel": "カーネルの構成",
"xpack.securitySolution.endpoint.details.policyResponse.configure_logging": "ロギングの構成",
"xpack.securitySolution.endpoint.details.policyResponse.configure_malware": "マルウェアの構成",
"xpack.securitySolution.endpoint.details.policyResponse.configure_network_events": "ネットワークイベントの構成",
"xpack.securitySolution.endpoint.details.policyResponse.configure_process_events": "プロセスイベントの構成",
"xpack.securitySolution.endpoint.details.policyResponse.configure_registry_events": "レジストリイベントの構成",
"xpack.securitySolution.endpoint.details.policyResponse.configure_security_events": "セキュリティイベントの構成",
"xpack.securitySolution.endpoint.details.policyResponse.connect_kernel": "カーネルを接続",
"xpack.securitySolution.endpoint.details.policyResponse.detect_async_image_load_events": "非同期画像読み込みイベントを検出",
"xpack.securitySolution.endpoint.details.policyResponse.detect_file_open_events": "ファイルオープンイベントを検出",
"xpack.securitySolution.endpoint.details.policyResponse.detect_file_write_events": "ファイル書き込みイベントを検出",
"xpack.securitySolution.endpoint.details.policyResponse.detect_network_events": "ネットワークイベントを検出",
"xpack.securitySolution.endpoint.details.policyResponse.detect_process_events": "プロセスイベントを検出",
"xpack.securitySolution.endpoint.details.policyResponse.detect_registry_events": "レジストリイベントを検出",
"xpack.securitySolution.endpoint.details.policyResponse.detect_sync_image_load_events": "同期画像読み込みイベントを検出",
"xpack.securitySolution.endpoint.details.policyResponse.download_global_artifacts": "グローバルアーチファクトをダウンロード",
"xpack.securitySolution.endpoint.details.policyResponse.download_user_artifacts": "ユーザーアーチファクトをダウンロード",
"xpack.securitySolution.endpoint.details.policyResponse.events": "イベント",
"xpack.securitySolution.endpoint.details.policyResponse.failed": "失敗",
"xpack.securitySolution.endpoint.details.policyResponse.load_config": "構成の読み込み",
"xpack.securitySolution.endpoint.details.policyResponse.load_malware_model": "マルウェアモデルの読み込み",
"xpack.securitySolution.endpoint.details.policyResponse.logging": "ログ",
"xpack.securitySolution.endpoint.details.policyResponse.malware": "マルウェア",
"xpack.securitySolution.endpoint.details.policyResponse.read_elasticsearch_config": "Elasticsearch構成を読み取る",
"xpack.securitySolution.endpoint.details.policyResponse.read_events_config": "イベント構成を読み取る",
"xpack.securitySolution.endpoint.details.policyResponse.read_kernel_config": "カーネル構成を読み取る",
"xpack.securitySolution.endpoint.details.policyResponse.read_logging_config": "ロギング構成を読み取る",
"xpack.securitySolution.endpoint.details.policyResponse.read_malware_config": "マルウェア構成を読み取る",
"xpack.securitySolution.endpoint.details.policyResponse.streaming": "ストリーム中…",
"xpack.securitySolution.endpoint.details.policyResponse.success": "成功",
"xpack.securitySolution.endpoint.details.policyResponse.warning": "警告",
"xpack.securitySolution.endpoint.details.policyResponse.workflow": "ワークフロー",
"xpack.securitySolution.endpoint.list.beta": "ベータ",
"xpack.securitySolution.endpoint.list.loadingPolicies": "ポリシー構成を読み込んでいます…",
"xpack.securitySolution.endpoint.list.noEndpointsInstructions": "セキュリティポリシーを作成しました。以下のステップに従い、エージェントでElastic Endpoint Security機能を有効にする必要があります。",
"xpack.securitySolution.endpoint.list.noEndpointsPrompt": "エージェントでElastic Endpoint Securityを有効にする",
"xpack.securitySolution.endpoint.list.noPolicies": "ポリシーがありません。",
"xpack.securitySolution.endpoint.list.stepOne": "既存のポリシーは以下のリストのとおりです。これは後から変更できます。",
"xpack.securitySolution.endpoint.list.stepOneTitle": "ホストの保護で使用するポリシーを選択",
"xpack.securitySolution.endpoint.list.stepTwo": "開始するために必要なコマンドが提供されます。",
"xpack.securitySolution.endpoint.list.stepTwoTitle": "Ingest Manager経由でEndpoint Securityによって有効にされたエージェントを登録",
"xpack.securitySolution.endpoint.ingestManager.createPackageConfig.endpointConfiguration": "このエージェント構成を使用するすべてのエージェントは基本ポリシーを使用します。セキュリティアプリでこのポリシーを変更できます。Fleetはこれらの変更をエージェントにデプロイします。",
"xpack.securitySolution.endpoint.ingestToastMessage": "Ingest Managerが設定中に失敗しました。",
"xpack.securitySolution.endpoint.ingestToastTitle": "アプリを初期化できませんでした",
@ -16412,16 +16412,16 @@
"xpack.securitySolution.endpoint.resolver.runningTrigger": "トリガーの実行中",
"xpack.securitySolution.endpoint.resolver.terminatedProcess": "プロセスを中断しました",
"xpack.securitySolution.endpoint.resolver.terminatedTrigger": "トリガーを中断しました",
"xpack.securitySolution.endpointList.endpointVersion": "バージョン",
"xpack.securitySolution.endpointList.hostname": "ホスト名",
"xpack.securitySolution.endpointList.hostStatus": "ホストステータス",
"xpack.securitySolution.endpointList.hostStatusValue": "{hostStatus, select, online {オンライン} error {エラー} other {オフライン}}",
"xpack.securitySolution.endpointList.ip": "IP アドレス",
"xpack.securitySolution.endpointList.lastActive": "前回のアーカイブ",
"xpack.securitySolution.endpointList.os": "オペレーティングシステム",
"xpack.securitySolution.endpointList.policy": "ポリシー",
"xpack.securitySolution.endpointList.policyStatus": "ポリシーステータス",
"xpack.securitySolution.endpointList.totalCount": "{totalItemCount, plural, one {# ホスト} other {# ホスト}}",
"xpack.securitySolution.endpoint.list.endpointVersion": "バージョン",
"xpack.securitySolution.endpoint.list.hostname": "ホスト名",
"xpack.securitySolution.endpoint.list.hostStatus": "ホストステータス",
"xpack.securitySolution.endpoint.list.hostStatusValue": "{hostStatus, select, online {オンライン} error {エラー} other {オフライン}}",
"xpack.securitySolution.endpoint.list.ip": "IP アドレス",
"xpack.securitySolution.endpoint.list.lastActive": "前回のアーカイブ",
"xpack.securitySolution.endpoint.list.os": "オペレーティングシステム",
"xpack.securitySolution.endpoint.list.policy": "ポリシー",
"xpack.securitySolution.endpoint.list.policyStatus": "ポリシーステータス",
"xpack.securitySolution.endpoint.list.totalCount": "{totalItemCount, plural, one {# ホスト} other {# ホスト}}",
"xpack.securitySolution.endpointManagement.noPermissionsSubText": "Ingest Managerが無効である可能性があります。この機能を使用するには、Ingest Managerを有効にする必要があります。Ingest Managerを有効にする権限がない場合は、Kibana管理者に連絡してください。",
"xpack.securitySolution.endpointManagemnet.noPermissionsText": "Elastic Security Administrationを使用するために必要なKibana権限がありません。",
"xpack.securitySolution.enpdoint.resolver.panelutils.betaBadgeLabel": "BETA",
@ -16610,8 +16610,8 @@
"xpack.securitySolution.host.details.overview.platformTitle": "プラットフォーム",
"xpack.securitySolution.host.details.overview.regionTitle": "地域",
"xpack.securitySolution.host.details.versionLabel": "バージョン",
"xpack.securitySolution.hostList.pageSubTitle": "Elastic Endpoint Securityを実行しているホスト",
"xpack.securitySolution.hostList.pageTitle": "ホスト",
"xpack.securitySolution.endpoint.list.pageSubTitle": "Elastic Endpoint Securityを実行しているホスト",
"xpack.securitySolution.endpoint.list.pageTitle": "ホスト",
"xpack.securitySolution.hosts.kqlPlaceholder": "例host.name: \"foo\"",
"xpack.securitySolution.hosts.navigation.alertsTitle": "外部アラート",
"xpack.securitySolution.hosts.navigation.allHostsTitle": "すべてのホスト",
@ -16623,7 +16623,7 @@
"xpack.securitySolution.hosts.navigaton.matrixHistogram.errorFetchingAuthenticationsData": "認証データをクエリできませんでした",
"xpack.securitySolution.hosts.navigaton.matrixHistogram.errorFetchingEventsData": "イベントデータをクエリできませんでした",
"xpack.securitySolution.hosts.pageTitle": "ホスト",
"xpack.securitySolution.hostsTab": "ホスト",
"xpack.securitySolution.endpointsTab": "ホスト",
"xpack.securitySolution.hostsTable.firstLastSeenToolTip": "選択された日付範囲との相関付けです",
"xpack.securitySolution.hostsTable.hostsTitle": "すべてのホスト",
"xpack.securitySolution.hostsTable.lastSeenTitle": "前回の認識",

View file

@ -16238,65 +16238,65 @@
"xpack.securitySolution.editDataProvider.valuePlaceholder": "值",
"xpack.securitySolution.emptyMessage": "Elastic Security 将免费且开放的 Elastic SIEM 和 Elastic Endpoint Security 整合在一起,从而防御、检测并响应威胁。首先,您需要将安全解决方案相关数据添加到 Elastic Stack。有关更多信息请查看我们的 ",
"xpack.securitySolution.emptyString.emptyStringDescription": "空字符串",
"xpack.securitySolution.endpoint.host.details.endpointVersion": "Endpoint 版本",
"xpack.securitySolution.endpoint.host.details.errorBody": "请退出浮出控件并选择可用主机。",
"xpack.securitySolution.endpoint.host.details.errorTitle": "找不到主机",
"xpack.securitySolution.endpoint.host.details.hostname": "主机名",
"xpack.securitySolution.endpoint.host.details.ipAddress": "IP 地址",
"xpack.securitySolution.endpoint.host.details.lastSeen": "最后看到时间",
"xpack.securitySolution.endpoint.host.details.linkToIngestTitle": "重新分配策略",
"xpack.securitySolution.endpoint.host.details.os": "OS",
"xpack.securitySolution.endpoint.host.details.policy": "政策",
"xpack.securitySolution.endpoint.host.details.policyStatus": "策略状态",
"xpack.securitySolution.endpoint.host.details.policyStatusValue": "{policyStatus, select, success {成功} warning {警告} failure {失败} other {未知}}",
"xpack.securitySolution.endpoint.host.policyResponse.backLinkTitle": "终端详情",
"xpack.securitySolution.endpoint.host.policyResponse.title": "策略响应",
"xpack.securitySolution.endpoint.hostDetails.noPolicyResponse": "没有可用的策略响应",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_dns_events": "配置 DNS 事件",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_elasticsearch_connection": "配置 Elastic 搜索连接",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_file_events": "配置文件事件",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_imageload_events": "配置映像加载事件",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_kernel": "配置内核",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_logging": "配置日志记录",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_malware": "配置恶意软件",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_network_events": "配置网络事件",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_process_events": "配置进程事件",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_registry_events": "配置注册表事件",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.configure_security_events": "配置安全事件",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.connect_kernel": "连接内核",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.detect_async_image_load_events": "检测异步映像加载事件",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.detect_file_open_events": "检测文件打开事件",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.detect_file_write_events": "检测文件写入事件",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.detect_network_events": "检测网络事件",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.detect_process_events": "检测进程事件",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.detect_registry_events": "检测注册表事件",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.detect_sync_image_load_events": "检测同步映像加载事件",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.download_global_artifacts": "下载全局项目",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.download_user_artifacts": "下面用户项目",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.events": "事件",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.failed": "失败",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.load_config": "加载配置",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.load_malware_model": "加载恶意软件模型",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.logging": "日志",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.malware": "恶意软件",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.read_elasticsearch_config": "读取 ElasticSearch 配置",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.read_events_config": "读取时间配置",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.read_kernel_config": "读取内核配置",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.read_logging_config": "读取日志配置",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.read_malware_config": "读取恶意软件配置",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.streaming": "流式传输",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.success": "成功",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.warning": "警告",
"xpack.securitySolution.endpoint.hostDetails.policyResponse.workflow": "工作流",
"xpack.securitySolution.endpoint.hostList.beta": "公测版",
"xpack.securitySolution.endpoint.hostList.loadingPolicies": "正在加载政策配置",
"xpack.securitySolution.endpoint.hostList.noEndpointsInstructions": "您已创建安全策略。现在您需要按照下面的步骤在代理上启用 Elastic Endpoint Security 功能。",
"xpack.securitySolution.endpoint.hostList.noEndpointsPrompt": "在您的代理上启用 Elastic Endpoint Security",
"xpack.securitySolution.endpoint.hostList.noPolicies": "没有策略。",
"xpack.securitySolution.endpoint.hostList.stepOne": "现有策略在下面列出。之后可以对其进行更改。",
"xpack.securitySolution.endpoint.hostList.stepOneTitle": "选择要用于保护主机的策略",
"xpack.securitySolution.endpoint.hostList.stepTwo": "为了让您入门,将会为您提供必要的命令。",
"xpack.securitySolution.endpoint.hostList.stepTwoTitle": "通过采集管理器注册启用 Endpoint Security 的代理",
"xpack.securitySolution.endpoint.details.endpointVersion": "Endpoint 版本",
"xpack.securitySolution.endpoint.details.errorBody": "请退出浮出控件并选择可用主机。",
"xpack.securitySolution.endpoint.details.errorTitle": "找不到主机",
"xpack.securitySolution.endpoint.details.hostname": "主机名",
"xpack.securitySolution.endpoint.details.ipAddress": "IP 地址",
"xpack.securitySolution.endpoint.details.lastSeen": "最后看到时间",
"xpack.securitySolution.endpoint.details.linkToIngestTitle": "重新分配策略",
"xpack.securitySolution.endpoint.details.os": "OS",
"xpack.securitySolution.endpoint.details.policy": "政策",
"xpack.securitySolution.endpoint.details.policyStatus": "策略状态",
"xpack.securitySolution.endpoint.details.policyStatusValue": "{policyStatus, select, success {成功} warning {警告} failure {失败} other {未知}}",
"xpack.securitySolution.endpoint.policyResponse.backLinkTitle": "终端详情",
"xpack.securitySolution.endpoint.policyResponse.title": "策略响应",
"xpack.securitySolution.endpoint.details.noPolicyResponse": "没有可用的策略响应",
"xpack.securitySolution.endpoint.details.policyResponse.configure_dns_events": "配置 DNS 事件",
"xpack.securitySolution.endpoint.details.policyResponse.configure_elasticsearch_connection": "配置 Elastic 搜索连接",
"xpack.securitySolution.endpoint.details.policyResponse.configure_file_events": "配置文件事件",
"xpack.securitySolution.endpoint.details.policyResponse.configure_imageload_events": "配置映像加载事件",
"xpack.securitySolution.endpoint.details.policyResponse.configure_kernel": "配置内核",
"xpack.securitySolution.endpoint.details.policyResponse.configure_logging": "配置日志记录",
"xpack.securitySolution.endpoint.details.policyResponse.configure_malware": "配置恶意软件",
"xpack.securitySolution.endpoint.details.policyResponse.configure_network_events": "配置网络事件",
"xpack.securitySolution.endpoint.details.policyResponse.configure_process_events": "配置进程事件",
"xpack.securitySolution.endpoint.details.policyResponse.configure_registry_events": "配置注册表事件",
"xpack.securitySolution.endpoint.details.policyResponse.configure_security_events": "配置安全事件",
"xpack.securitySolution.endpoint.details.policyResponse.connect_kernel": "连接内核",
"xpack.securitySolution.endpoint.details.policyResponse.detect_async_image_load_events": "检测异步映像加载事件",
"xpack.securitySolution.endpoint.details.policyResponse.detect_file_open_events": "检测文件打开事件",
"xpack.securitySolution.endpoint.details.policyResponse.detect_file_write_events": "检测文件写入事件",
"xpack.securitySolution.endpoint.details.policyResponse.detect_network_events": "检测网络事件",
"xpack.securitySolution.endpoint.details.policyResponse.detect_process_events": "检测进程事件",
"xpack.securitySolution.endpoint.details.policyResponse.detect_registry_events": "检测注册表事件",
"xpack.securitySolution.endpoint.details.policyResponse.detect_sync_image_load_events": "检测同步映像加载事件",
"xpack.securitySolution.endpoint.details.policyResponse.download_global_artifacts": "下载全局项目",
"xpack.securitySolution.endpoint.details.policyResponse.download_user_artifacts": "下面用户项目",
"xpack.securitySolution.endpoint.details.policyResponse.events": "事件",
"xpack.securitySolution.endpoint.details.policyResponse.failed": "失败",
"xpack.securitySolution.endpoint.details.policyResponse.load_config": "加载配置",
"xpack.securitySolution.endpoint.details.policyResponse.load_malware_model": "加载恶意软件模型",
"xpack.securitySolution.endpoint.details.policyResponse.logging": "日志",
"xpack.securitySolution.endpoint.details.policyResponse.malware": "恶意软件",
"xpack.securitySolution.endpoint.details.policyResponse.read_elasticsearch_config": "读取 ElasticSearch 配置",
"xpack.securitySolution.endpoint.details.policyResponse.read_events_config": "读取时间配置",
"xpack.securitySolution.endpoint.details.policyResponse.read_kernel_config": "读取内核配置",
"xpack.securitySolution.endpoint.details.policyResponse.read_logging_config": "读取日志配置",
"xpack.securitySolution.endpoint.details.policyResponse.read_malware_config": "读取恶意软件配置",
"xpack.securitySolution.endpoint.details.policyResponse.streaming": "流式传输",
"xpack.securitySolution.endpoint.details.policyResponse.success": "成功",
"xpack.securitySolution.endpoint.details.policyResponse.warning": "警告",
"xpack.securitySolution.endpoint.details.policyResponse.workflow": "工作流",
"xpack.securitySolution.endpoint.list.beta": "公测版",
"xpack.securitySolution.endpoint.list.loadingPolicies": "正在加载政策配置",
"xpack.securitySolution.endpoint.list.noEndpointsInstructions": "您已创建安全策略。现在您需要按照下面的步骤在代理上启用 Elastic Endpoint Security 功能。",
"xpack.securitySolution.endpoint.list.noEndpointsPrompt": "在您的代理上启用 Elastic Endpoint Security",
"xpack.securitySolution.endpoint.list.noPolicies": "没有策略。",
"xpack.securitySolution.endpoint.list.stepOne": "现有策略在下面列出。之后可以对其进行更改。",
"xpack.securitySolution.endpoint.list.stepOneTitle": "选择要用于保护主机的策略",
"xpack.securitySolution.endpoint.list.stepTwo": "为了让您入门,将会为您提供必要的命令。",
"xpack.securitySolution.endpoint.list.stepTwoTitle": "通过采集管理器注册启用 Endpoint Security 的代理",
"xpack.securitySolution.endpoint.ingestManager.createPackageConfig.endpointConfiguration": "使用此代理配置的任何代理都会使用基本策略。可以在 Security 应用中对此策略进行更改Fleet 会将这些更改部署到代理。",
"xpack.securitySolution.endpoint.ingestToastMessage": "采集管理器在其设置期间失败。",
"xpack.securitySolution.endpoint.ingestToastTitle": "应用无法初始化",
@ -16418,16 +16418,16 @@
"xpack.securitySolution.endpoint.resolver.runningTrigger": "正在运行的触发器",
"xpack.securitySolution.endpoint.resolver.terminatedProcess": "已终止进程",
"xpack.securitySolution.endpoint.resolver.terminatedTrigger": "已终止触发器",
"xpack.securitySolution.endpointList.endpointVersion": "版本",
"xpack.securitySolution.endpointList.hostname": "主机名",
"xpack.securitySolution.endpointList.hostStatus": "主机状态",
"xpack.securitySolution.endpointList.hostStatusValue": "{hostStatus, select, online {联机} error {错误} other {脱机}}",
"xpack.securitySolution.endpointList.ip": "IP 地址",
"xpack.securitySolution.endpointList.lastActive": "上次活动时间",
"xpack.securitySolution.endpointList.os": "操作系统",
"xpack.securitySolution.endpointList.policy": "政策",
"xpack.securitySolution.endpointList.policyStatus": "策略状态",
"xpack.securitySolution.endpointList.totalCount": "{totalItemCount, plural, one {# 个主机} other {# 个主机}}",
"xpack.securitySolution.endpoint.list.endpointVersion": "版本",
"xpack.securitySolution.endpoint.list.hostname": "主机名",
"xpack.securitySolution.endpoint.list.hostStatus": "主机状态",
"xpack.securitySolution.endpoint.list.hostStatusValue": "{hostStatus, select, online {联机} error {错误} other {脱机}}",
"xpack.securitySolution.endpoint.list.ip": "IP 地址",
"xpack.securitySolution.endpoint.list.lastActive": "上次活动时间",
"xpack.securitySolution.endpoint.list.os": "操作系统",
"xpack.securitySolution.endpoint.list.policy": "政策",
"xpack.securitySolution.endpoint.list.policyStatus": "策略状态",
"xpack.securitySolution.endpoint.list.totalCount": "{totalItemCount, plural, one {# 个主机} other {# 个主机}}",
"xpack.securitySolution.endpointManagement.noPermissionsSubText": "似乎采集管理器已禁用。必须启用采集管理器,才能使用此功能。如果您无权启用采集管理器,请联系您的 Kibana 管理员。",
"xpack.securitySolution.endpointManagemnet.noPermissionsText": "您没有所需的 Kibana 权限,无法使用 Elastic Security 管理",
"xpack.securitySolution.enpdoint.resolver.panelutils.betaBadgeLabel": "公测版",
@ -16616,8 +16616,8 @@
"xpack.securitySolution.host.details.overview.platformTitle": "平台",
"xpack.securitySolution.host.details.overview.regionTitle": "地区",
"xpack.securitySolution.host.details.versionLabel": "版本",
"xpack.securitySolution.hostList.pageSubTitle": "运行 Elastic Endpoint Security 的主机",
"xpack.securitySolution.hostList.pageTitle": "主机",
"xpack.securitySolution.endpoint.list.pageSubTitle": "运行 Elastic Endpoint Security 的主机",
"xpack.securitySolution.endpoint.list.pageTitle": "主机",
"xpack.securitySolution.hosts.kqlPlaceholder": "例如 host.name“foo”",
"xpack.securitySolution.hosts.navigation.alertsTitle": "外部告警",
"xpack.securitySolution.hosts.navigation.allHostsTitle": "所有主机",
@ -16629,7 +16629,7 @@
"xpack.securitySolution.hosts.navigaton.matrixHistogram.errorFetchingAuthenticationsData": "无法查询身份验证数据",
"xpack.securitySolution.hosts.navigaton.matrixHistogram.errorFetchingEventsData": "无法查询事件数据",
"xpack.securitySolution.hosts.pageTitle": "主机",
"xpack.securitySolution.hostsTab": "主机",
"xpack.securitySolution.endpointsTab": "主机",
"xpack.securitySolution.hostsTable.firstLastSeenToolTip": "相对于选定日期范围",
"xpack.securitySolution.hostsTable.hostsTitle": "所有主机",
"xpack.securitySolution.hostsTable.lastSeenTitle": "最后看到时间",

View file

@ -13,14 +13,14 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
const esArchiver = getService('esArchiver');
const testSubjects = getService('testSubjects');
describe('host list', function () {
describe('endpoint list', function () {
this.tags('ciGroup7');
const sleep = (ms = 100) => new Promise((resolve) => setTimeout(resolve, ms));
describe('when there is data,', () => {
before(async () => {
await esArchiver.load('endpoint/metadata/api_feature', { useCreate: true });
await pageObjects.endpoint.navigateToHostList();
await pageObjects.endpoint.navigateToEndpointList();
});
after(async () => {
await deleteMetadataStream(getService);
@ -28,14 +28,14 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
it('finds page title', async () => {
const title = await testSubjects.getVisibleText('pageViewHeaderLeftTitle');
expect(title).to.equal('Hosts');
expect(title).to.equal('Endpoints');
});
it('displays table data', async () => {
const expectedData = [
[
'Hostname',
'Host Status',
'Agent Status',
'Integration',
'Configuration Status',
'Operating System',
@ -74,70 +74,76 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
'Jan 24, 2020 @ 16:06:09.541',
],
];
const tableData = await pageObjects.endpointPageUtils.tableData('hostListTable');
const tableData = await pageObjects.endpointPageUtils.tableData('endpointListTable');
expect(tableData).to.eql(expectedData);
});
it('does not show the details flyout initially', async () => {
await testSubjects.missingOrFail('hostDetailsFlyout');
await testSubjects.missingOrFail('endpointDetailsFlyout');
});
describe('when the hostname is clicked on,', () => {
it('display the details flyout', async () => {
await (await testSubjects.find('hostnameCellLink')).click();
await testSubjects.existOrFail('hostDetailsUpperList');
await testSubjects.existOrFail('hostDetailsLowerList');
await testSubjects.existOrFail('endpointDetailsUpperList');
await testSubjects.existOrFail('endpointDetailsLowerList');
});
it('updates the details flyout when a new hostname is selected from the list', async () => {
// display flyout for the first host in the list
// display flyout for the first endpoint in the list
await (await testSubjects.findAll('hostnameCellLink'))[0].click();
await testSubjects.existOrFail('hostDetailsFlyoutTitle');
const hostDetailTitle0 = await testSubjects.getVisibleText('hostDetailsFlyoutTitle');
// select the 2nd host in the host list
await testSubjects.existOrFail('endpointDetailsFlyoutTitle');
const endpointDetailTitle0 = await testSubjects.getVisibleText(
'endpointDetailsFlyoutTitle'
);
// select the 2nd endpoint in the endpoint list
await (await testSubjects.findAll('hostnameCellLink'))[1].click();
await pageObjects.endpoint.waitForVisibleTextToChange(
'hostDetailsFlyoutTitle',
hostDetailTitle0
'endpointDetailsFlyoutTitle',
endpointDetailTitle0
);
const hostDetailTitle1 = await testSubjects.getVisibleText('hostDetailsFlyoutTitle');
expect(hostDetailTitle1).to.not.eql(hostDetailTitle0);
const endpointDetailTitle1 = await testSubjects.getVisibleText(
'endpointDetailsFlyoutTitle'
);
expect(endpointDetailTitle1).to.not.eql(endpointDetailTitle0);
});
it('has the same flyout info when the same hostname is selected', async () => {
// display flyout for the first host in the list
// display flyout for the first endpoint in the list
await (await testSubjects.findAll('hostnameCellLink'))[1].click();
await testSubjects.existOrFail('hostDetailsFlyoutTitle');
const hostDetailTitleInitial = await testSubjects.getVisibleText(
'hostDetailsFlyoutTitle'
await testSubjects.existOrFail('endpointDetailsFlyoutTitle');
const endpointDetailTitleInitial = await testSubjects.getVisibleText(
'endpointDetailsFlyoutTitle'
);
// select the same host in the host list
// select the same endpoint in the endpoint list
await (await testSubjects.findAll('hostnameCellLink'))[1].click();
await sleep(500); // give page time to refresh and verify it did not change
const hostDetailTitleNew = await testSubjects.getVisibleText('hostDetailsFlyoutTitle');
expect(hostDetailTitleNew).to.equal(hostDetailTitleInitial);
const endpointDetailTitleNew = await testSubjects.getVisibleText(
'endpointDetailsFlyoutTitle'
);
expect(endpointDetailTitleNew).to.equal(endpointDetailTitleInitial);
});
// The integration does not work properly yet. Skipping this test for now.
it.skip('navigates to ingest fleet when the Reassign Configuration link is clicked', async () => {
await (await testSubjects.find('hostnameCellLink')).click();
await (await testSubjects.find('hostDetailsLinkToIngest')).click();
await (await testSubjects.find('endpointDetailsLinkToIngest')).click();
await testSubjects.existOrFail('fleetAgentListTable');
});
});
// This set of tests fails the flyout does not open in the before() and will be fixed in soon
describe.skip('has a url with a host id', () => {
describe.skip("has a url with an endpoint host's id", () => {
before(async () => {
await pageObjects.endpoint.navigateToHostList(
await pageObjects.endpoint.navigateToEndpointList(
'selected_host=fc0ff548-feba-41b6-8367-65e8790d0eaf'
);
});
it('shows a flyout', async () => {
await testSubjects.existOrFail('hostDetailsFlyoutBody');
await testSubjects.existOrFail('hostDetailsUpperList');
await testSubjects.existOrFail('hostDetailsLowerList');
await testSubjects.existOrFail('endpointDetailsFlyoutBody');
await testSubjects.existOrFail('endpointDetailsUpperList');
await testSubjects.existOrFail('endpointDetailsLowerList');
});
it('displays details row headers', async () => {
@ -151,13 +157,15 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
'Hostname',
'Sensor Version',
];
const keys = await pageObjects.endpoint.hostFlyoutDescriptionKeys('hostDetailsFlyout');
const keys = await pageObjects.endpoint.endpointFlyoutDescriptionKeys(
'endpointDetailsFlyout'
);
expect(keys).to.eql(expectedData);
});
it('displays details row descriptions', async () => {
const values = await pageObjects.endpoint.hostFlyoutDescriptionValues(
'hostDetailsFlyout'
const values = await pageObjects.endpoint.endpointFlyoutDescriptionValues(
'endpointDetailsFlyout'
);
expect(values).to.eql([
@ -178,7 +186,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
before(async () => {
// clear out the data and reload the page
await deleteMetadataStream(getService);
await pageObjects.endpoint.navigateToHostList();
await pageObjects.endpoint.navigateToEndpointList();
});
it('displays empty Policy Table page.', async () => {
await testSubjects.existOrFail('emptyPolicyTable');

View file

@ -81,7 +81,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
await pageObjects.policy.confirmAndSave();
await testSubjects.existOrFail('policyDetailsSuccessMessage');
await pageObjects.endpoint.navigateToHostList();
await pageObjects.endpoint.navigateToEndpointList();
await pageObjects.policy.navigateToPolicyDetails(policyInfo.packageConfig.id);
expect(await (await testSubjects.find('policyWindowsEvent_process')).isSelected()).to.equal(

View file

@ -14,12 +14,12 @@ export function EndpointPageProvider({ getService, getPageObjects }: FtrProvider
return {
/**
* Navigate to the Hosts list page
* Navigate to the Endpoints list page
*/
async navigateToHostList(searchParams?: string) {
async navigateToEndpointList(searchParams?: string) {
await pageObjects.common.navigateToUrlWithBrowserHistory(
'securitySolutionManagement',
`/hosts${searchParams ? `?${searchParams}` : ''}`
`/endpoints${searchParams ? `?${searchParams}` : ''}`
);
await pageObjects.header.waitUntilLoadingHasFinished();
},
@ -51,7 +51,7 @@ export function EndpointPageProvider({ getService, getPageObjects }: FtrProvider
});
},
async hostFlyoutDescriptionKeys(dataTestSubj: string) {
async endpointFlyoutDescriptionKeys(dataTestSubj: string) {
await testSubjects.exists(dataTestSubj);
const detailsData: WebElementWrapper = await testSubjects.find(dataTestSubj);
const $ = await detailsData.parseDomContent();
@ -65,7 +65,7 @@ export function EndpointPageProvider({ getService, getPageObjects }: FtrProvider
);
},
async hostFlyoutDescriptionValues(dataTestSubj: string) {
async endpointFlyoutDescriptionValues(dataTestSubj: string) {
await testSubjects.exists(dataTestSubj);
const detailsData: WebElementWrapper = await testSubjects.find(dataTestSubj);
const $ = await detailsData.parseDomContent();